diff --git a/go.mod b/go.mod index 069f5f6..c9fe070 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,32 @@ module github.com/nats-io/nats-account-server require ( - github.com/julienschmidt/httprouter v1.2.0 + github.com/julienschmidt/httprouter v1.3.0 github.com/mitchellh/go-homedir v1.1.0 github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7 - github.com/nats-io/jwt/v2 v2.0.0-20201015190852-e11ce317263c - github.com/nats-io/nats-server/v2 v2.1.8-0.20201209001253-25a5fa62ebc8 - github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0 - github.com/nats-io/nkeys v0.2.0 - github.com/rs/cors v1.6.0 - github.com/stretchr/testify v1.6.1 - golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd + github.com/nats-io/jwt/v2 v2.8.0 + github.com/nats-io/nats-server/v2 v2.11.12 + github.com/nats-io/nats.go v1.48.0 + github.com/nats-io/nkeys v0.4.12 + github.com/rs/cors v1.8.0 + github.com/stretchr/testify v1.7.1 + golang.org/x/sys v0.40.0 ) -go 1.13 +require ( + github.com/antithesishq/antithesis-sdk-go v0.5.0-default-no-op // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/go-tpm v0.9.8 // indirect + github.com/klauspost/compress v1.18.3 // indirect + github.com/kr/pretty v0.2.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/time v0.14.0 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +go 1.24.0 diff --git a/go.sum b/go.sum index 42a908b..ad6c19a 100644 --- a/go.sum +++ b/go.sum @@ -1,78 +1,80 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/antithesishq/antithesis-sdk-go v0.5.0-default-no-op h1:Ucf+QxEKMbPogRO5guBNe5cgd9uZgfoJLOYs8WWhtjM= +github.com/antithesishq/antithesis-sdk-go v0.5.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA= -github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= +github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= +github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= +github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= +github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7 h1:RnGotxlghqR5D2KDAu4TyuLqyjuylOsJiAFhXvMvQIc= github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= -github.com/nats-io/jwt/v2 v2.0.0-20200916203241-1f8ce17dff02/go.mod h1:vs+ZEjP+XKy8szkBmQwCB7RjYdIlMaPsFPs4VdS4bTQ= -github.com/nats-io/jwt/v2 v2.0.0-20201015190852-e11ce317263c h1:Hc1D9ChlsCMVwCxJ6QT5xqfk2zJ4XNea+LtdfaYhd20= -github.com/nats-io/jwt/v2 v2.0.0-20201015190852-e11ce317263c/go.mod h1:vs+ZEjP+XKy8szkBmQwCB7RjYdIlMaPsFPs4VdS4bTQ= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200524125952-51ebd92a9093/go.mod h1:rQnBf2Rv4P9adtAs/Ti6LfFmVtFG6HLhl/H7cVshcJU= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200601203034-f8d6dd992b71/go.mod h1:Nan/1L5Sa1JRW+Thm4HNYcIDcVRFc5zK9OpSZeI2kk4= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200929001935-7f44d075f7ad/go.mod h1:TkHpUIDETmTI7mrHN40D1pzxfzHZuGmtMbtb83TGVQw= -github.com/nats-io/nats-server/v2 v2.1.8-0.20201209001253-25a5fa62ebc8 h1:er4LVQlmaTxq+AlmwVuPg/5kWmIHD2zSulEobxWWUnM= -github.com/nats-io/nats-server/v2 v2.1.8-0.20201209001253-25a5fa62ebc8/go.mod h1:XD0zHR/jTXdZvWaQfS5mQgsXj6x12kMjKLyAk/cOGgY= -github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= -github.com/nats-io/nats.go v1.10.1-0.20200531124210-96f2130e4d55/go.mod h1:ARiFsjW9DVxk48WJbO3OSZ2DG8fjkMi7ecLmXoY/n9I= -github.com/nats-io/nats.go v1.10.1-0.20200606002146-fc6fed82929a h1:gzSKZOBlu/DpbuPbt34paXCOvA6+E+lVfU2BmomQ9HA= -github.com/nats-io/nats.go v1.10.1-0.20200606002146-fc6fed82929a/go.mod h1:8eAIv96Mo9QW6Or40jUHejS7e4VwZ3VRYD6Sf0BTDp4= -github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0 h1:s//xxvMgNRVJNTRXTRNvLlES0zvJoDLXfcmbK0YgN0E= -github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0/go.mod h1:VU2zERjp8xmF+Lw2NH4u2t5qWZxwc7jB3+7HVMWQXPI= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g= +github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA= +github.com/nats-io/nats-server/v2 v2.11.12 h1:jGDXTkcjqQ5fCRstwIxvv1K0RHfftFUoSCT/iIZcqOc= +github.com/nats-io/nats-server/v2 v2.11.12/go.mod h1:5MCp/pqm5SEfsvVZ31ll1088ZTwEUdvRX1Hmh/mTTDg= +github.com/nats-io/nats.go v1.48.0 h1:pSFyXApG+yWU/TgbKCjmm5K4wrHu86231/w84qRVR+U= +github.com/nats-io/nats.go v1.48.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g= github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nkeys v0.4.12 h1:nssm7JKOG9/x4J8II47VWCL1Ds29avyiQDRn0ckMvDc= +github.com/nats-io/nkeys v0.4.12/go.mod h1:MT59A1HYcjIcyQDJStTfaOY6vhy9XTUjOFo+SVsvpBg= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= -github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so= +github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/LICENSE b/vendor/github.com/antithesishq/antithesis-sdk-go/LICENSE new file mode 100644 index 0000000..90f1712 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Antithesis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert.go new file mode 100644 index 0000000..3ede010 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert.go @@ -0,0 +1,214 @@ +//go:build enable_antithesis_sdk + +// Package assert enables defining [test properties] about your program or [workload]. It is part of the [Antithesis Go SDK], which enables Go applications to integrate with the [Antithesis platform]. +// +// Code that uses this package should be instrumented with the [antithesis-go-generator] utility. This step is required for the Always, Sometime, and Reachable methods. It is not required for the Unreachable and AlwaysOrUnreachable methods, but it will improve the experience of using them. +// +// These functions are no-ops with minimal performance overhead when called outside of the Antithesis environment. However, if the environment variable ANTITHESIS_SDK_LOCAL_OUTPUT is set, these functions will log to the file pointed to by that variable using a structured JSON format defined [here]. This allows you to make use of the Antithesis assertions package in your regular testing, or even in production. In particular, very few assertions frameworks offer a convenient way to define [Sometimes assertions], but they can be quite useful even outside Antithesis. +// +// Each function in this package takes a parameter called message, which is a human readable identifier used to aggregate assertions. Antithesis generates one test property per unique message and this test property will be named "" in the [triage report]. +// +// This test property either passes or fails, which depends upon the evaluation of every assertion that shares its message. Different assertions in different parts of the code should have different message, but the same assertion should always have the same message even if it is moved to a different file. +// +// Each function also takes a parameter called details, which is a key-value map of optional additional information provided by the user to add context for assertion failures. The information that is logged will appear in the [triage report], under the details section of the corresponding property. Normally the values passed to details are evaluated at runtime. +// +// [Antithesis Go SDK]: https://antithesis.com/docs/using_antithesis/sdk/go/ +// [Antithesis platform]: https://antithesis.com +// [test properties]: https://antithesis.com/docs/using_antithesis/properties/ +// [workload]: https://antithesis.com/docs/getting_started/first_test/ +// [antithesis-go-generator]: https://antithesis.com/docs/using_antithesis/sdk/go/instrumentor/ +// [triage report]: https://antithesis.com/docs/reports/ +// [here]: https://antithesis.com/docs/using_antithesis/sdk/fallback/ +// [Sometimes assertions]: https://antithesis.com/docs/best_practices/sometimes_assertions/ +// +// [details]: https://antithesis.com/docs/reports/ +package assert + +import ( + "encoding/json" + "fmt" +) + +type assertInfo struct { + Location *locationInfo `json:"location"` + Details map[string]any `json:"details"` + AssertType string `json:"assert_type"` + DisplayType string `json:"display_type"` + Message string `json:"message"` + Id string `json:"id"` + Hit bool `json:"hit"` + MustHit bool `json:"must_hit"` + Condition bool `json:"condition"` +} + +// Create a custom json marshaler for assertInfo so that we can force Errors to be marshaled with their error details. +// Without this, custom errors are marshaled as an empty object because the default json marshaler doesn't include the error +// (because it's a method - not an exported struct field). +func (f assertInfo) MarshalJSON() ([]byte, error) { + type alias assertInfo // prevent infinite recursion + a := alias(f) + if a.Details != nil { + a.Details = normalizeMap(a.Details) + } + return json.Marshal(a) +} + +type jsonError struct { + innerError error +} + +func (e jsonError) MarshalJSON() ([]byte, error) { + // Marshal this as the debug output string instead of e.Error(). These should be equivalent, but Sprintf correctly + // handles nil values for us (which otherwise are annoying to defend against due to this - https://go.dev/doc/faq#nil_error) + return json.Marshal(fmt.Sprintf("%+v", e.innerError)) +} + +// Recursively replace any `error` with jsonError while doing a deep copy. +// Most of the logic is in the normalize method below. This method exists to localize the type assertions +// and provide a function that takes in/out a map instead of any. +func normalizeMap(v map[string]any) map[string]any { + return normalize(v).(map[string]any) +} + +func normalize(input any) any { + // This switch will miss some cases (pointers, structs, non-any types), but should catch a very large proportion of real error interfaces + // in real details objects. We can augment this if we find other cases common enough to support. + switch inputTyped := input.(type) { + case error: + // Check if the underlying error implements json.Marshaler, so that if the error + // already knows who to marshal itself, we don't override that. + if _, ok := inputTyped.(json.Marshaler); ok { + return inputTyped + } else { + return jsonError{inputTyped} + } + case map[string]any: + out := make(map[string]any, len(inputTyped)) + for k, v := range inputTyped { + out[k] = normalize(v) + } + return out + case []any: + out := make([]any, len(inputTyped)) + for i := range inputTyped { + out[i] = normalize(inputTyped[i]) + } + return out + default: + return input + } +} + +type wrappedAssertInfo struct { + A *assertInfo `json:"antithesis_assert"` +} + +// -------------------------------------------------------------------------------- +// Assertions +// -------------------------------------------------------------------------------- +const ( + wasHit = true + mustBeHit = true + optionallyHit = false + expectingTrue = true +) + +const ( + universalTest = "always" + existentialTest = "sometimes" + reachabilityTest = "reachability" +) + +const ( + alwaysDisplay = "Always" + alwaysOrUnreachableDisplay = "AlwaysOrUnreachable" + sometimesDisplay = "Sometimes" + reachableDisplay = "Reachable" + unreachableDisplay = "Unreachable" +) + +// Always asserts that condition is true every time this function is called, and that it is called at least once. The corresponding test property will be viewable in the Antithesis SDK: Always group of your triage report. +func Always(condition bool, message string, details map[string]any) { + locationInfo := newLocationInfo(offsetAPICaller) + id := makeKey(message, locationInfo) + assertImpl(condition, message, details, locationInfo, wasHit, mustBeHit, universalTest, alwaysDisplay, id) +} + +// AlwaysOrUnreachable asserts that condition is true every time this function is called. The corresponding test property will pass if the assertion is never encountered (unlike Always assertion types). This test property will be viewable in the “Antithesis SDK: Always” group of your triage report. +func AlwaysOrUnreachable(condition bool, message string, details map[string]any) { + locationInfo := newLocationInfo(offsetAPICaller) + id := makeKey(message, locationInfo) + assertImpl(condition, message, details, locationInfo, wasHit, optionallyHit, universalTest, alwaysOrUnreachableDisplay, id) +} + +// Sometimes asserts that condition is true at least one time that this function was called. (If the assertion is never encountered, the test property will therefore fail.) This test property will be viewable in the “Antithesis SDK: Sometimes” group. +func Sometimes(condition bool, message string, details map[string]any) { + locationInfo := newLocationInfo(offsetAPICaller) + id := makeKey(message, locationInfo) + assertImpl(condition, message, details, locationInfo, wasHit, mustBeHit, existentialTest, sometimesDisplay, id) +} + +// Unreachable asserts that a line of code is never reached. The corresponding test property will fail if this function is ever called. (If it is never called the test property will therefore pass.) This test property will be viewable in the “Antithesis SDK: Reachablity assertions” group. +func Unreachable(message string, details map[string]any) { + locationInfo := newLocationInfo(offsetAPICaller) + id := makeKey(message, locationInfo) + assertImpl(false, message, details, locationInfo, wasHit, optionallyHit, reachabilityTest, unreachableDisplay, id) +} + +// Reachable asserts that a line of code is reached at least once. The corresponding test property will pass if this function is ever called. (If it is never called the test property will therefore fail.) This test property will be viewable in the “Antithesis SDK: Reachablity assertions” group. +func Reachable(message string, details map[string]any) { + locationInfo := newLocationInfo(offsetAPICaller) + id := makeKey(message, locationInfo) + assertImpl(true, message, details, locationInfo, wasHit, mustBeHit, reachabilityTest, reachableDisplay, id) +} + +// AssertRaw is a low-level method designed to be used by third-party frameworks. Regular users of the assert package should not call it. +func AssertRaw(cond bool, message string, details map[string]any, + classname, funcname, filename string, line int, + hit bool, mustHit bool, + assertType string, displayType string, + id string, +) { + assertImpl(cond, message, details, + &locationInfo{classname, funcname, filename, line, columnUnknown}, + hit, mustHit, + assertType, displayType, + id) +} + +func assertImpl(cond bool, message string, details map[string]any, + loc *locationInfo, + hit bool, mustHit bool, + assertType string, displayType string, + id string, +) { + trackerEntry := assertTracker.getTrackerEntry(id, loc.Filename, loc.Classname) + + // Always grab the Filename and Classname captured when the trackerEntry was established + // This provides the consistency needed between instrumentation-time and runtime + if loc.Filename != trackerEntry.Filename { + loc.Filename = trackerEntry.Filename + } + + if loc.Classname != trackerEntry.Classname { + loc.Classname = trackerEntry.Classname + } + + aI := &assertInfo{ + Hit: hit, + MustHit: mustHit, + AssertType: assertType, + DisplayType: displayType, + Message: message, + Condition: cond, + Id: id, + Location: loc, + Details: details, + } + + trackerEntry.emit(aI) +} + +func makeKey(message string, _ *locationInfo) string { + return message +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert_noop.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert_noop.go new file mode 100644 index 0000000..640f18e --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert_noop.go @@ -0,0 +1,16 @@ +//go:build !enable_antithesis_sdk + +package assert + +func Always(condition bool, message string, details map[string]any) {} +func AlwaysOrUnreachable(condition bool, message string, details map[string]any) {} +func Sometimes(condition bool, message string, details map[string]any) {} +func Unreachable(message string, details map[string]any) {} +func Reachable(message string, details map[string]any) {} +func AssertRaw(cond bool, message string, details map[string]any, + classname, funcname, filename string, line int, + hit bool, mustHit bool, + assertType string, displayType string, + id string, +) { +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert_types.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert_types.go new file mode 100644 index 0000000..d520381 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/assert_types.go @@ -0,0 +1,30 @@ +package assert + +// Allowable numeric types of comparison parameters +type Number interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint8 | ~uint16 | ~uint32 | ~float32 | ~float64 | ~uint64 | ~uint | ~uintptr +} + +// Internally, numeric guidanceFn Operands only use these +type operandConstraint interface { + int32 | int64 | uint64 | float64 +} + +type numConstraint interface { + uint64 | float64 +} + +// Used for boolean assertions +type NamedBool struct { + First string `json:"first"` + Second bool `json:"second"` +} + +// Convenience function to construct a NamedBool used for boolean assertions +func NewNamedBool(first string, second bool) *NamedBool { + p := NamedBool{ + First: first, + Second: second, + } + return &p +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/boolean_guidance.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/boolean_guidance.go new file mode 100644 index 0000000..7a2af84 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/boolean_guidance.go @@ -0,0 +1,66 @@ +//go:build enable_antithesis_sdk + +package assert + +import ( + "sync" + + "github.com/antithesishq/antithesis-sdk-go/internal" +) + +// TODO: Tracker is intended to prevent sending the same guidance +// more than once. In this case, we always send, so the tracker +// is not presently used. +type booleanGuidance struct { + n int +} + +type booleanGuidanceTracker map[string]*booleanGuidance + +var ( + boolean_guidance_tracker booleanGuidanceTracker = make(booleanGuidanceTracker) + boolean_guidance_tracker_mutex sync.Mutex + boolean_guidance_info_mutex sync.Mutex +) + +func (tracker booleanGuidanceTracker) getTrackerEntry(messageKey string) *booleanGuidance { + var trackerEntry *booleanGuidance + var ok bool + + if tracker == nil { + return nil + } + + boolean_guidance_tracker_mutex.Lock() + defer boolean_guidance_tracker_mutex.Unlock() + if trackerEntry, ok = boolean_guidance_tracker[messageKey]; !ok { + trackerEntry = newBooleanGuidance() + tracker[messageKey] = trackerEntry + } + + return trackerEntry +} + +// Create a boolean guidance tracker +func newBooleanGuidance() *booleanGuidance { + trackerInfo := booleanGuidance{} + return &trackerInfo +} + +func (tI *booleanGuidance) send_value(bgI *booleanGuidanceInfo) { + if tI == nil { + return + } + + boolean_guidance_info_mutex.Lock() + defer boolean_guidance_info_mutex.Unlock() + + // The tracker entry should be consulted to determine + // if this Guidance info has already been sent, or not. + + emitBooleanGuidance(bgI) +} + +func emitBooleanGuidance(bgI *booleanGuidanceInfo) error { + return internal.Json_data(map[string]any{"antithesis_guidance": bgI}) +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/location.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/location.go new file mode 100644 index 0000000..463340a --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/location.go @@ -0,0 +1,58 @@ +//go:build enable_antithesis_sdk + +package assert + +import ( + "path" + "runtime" + "strings" +) + +// stackFrameOffset indicates how many frames to go up in the +// call stack to find the filename/location/line info. As +// this work is always done in NewLocationInfo(), the offset is +// specified from the perspective of NewLocationInfo +type stackFrameOffset int + +// Order is important here since iota is being used +const ( + offsetNewLocationInfo stackFrameOffset = iota + offsetHere + offsetAPICaller + offsetAPICallersCaller +) + +// locationInfo represents the attributes known at instrumentation time +// for each Antithesis assertion discovered +type locationInfo struct { + Classname string `json:"class"` + Funcname string `json:"function"` + Filename string `json:"file"` + Line int `json:"begin_line"` + Column int `json:"begin_column"` +} + +// columnUnknown is used when the column associated with +// a locationInfo is not available +const columnUnknown = 0 + +// NewLocationInfo creates a locationInfo directly from +// the current execution context +func newLocationInfo(nframes stackFrameOffset) *locationInfo { + // Get location info and add to details + funcname := "*function*" + classname := "*class*" + pc, filename, line, ok := runtime.Caller(int(nframes)) + if !ok { + filename = "*file*" + line = 0 + } else { + if this_func := runtime.FuncForPC(pc); this_func != nil { + fullname := this_func.Name() + funcname = path.Ext(fullname) + classname, _ = strings.CutSuffix(fullname, funcname) + funcname = funcname[1:] + } + } + return &locationInfo{classname, funcname, filename, line, columnUnknown} +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/numeric_guidance.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/numeric_guidance.go new file mode 100644 index 0000000..1bba49e --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/numeric_guidance.go @@ -0,0 +1,323 @@ +//go:build enable_antithesis_sdk + +package assert + +import ( + "math" + "sync" + + "github.com/antithesishq/antithesis-sdk-go/internal" +) + +// -------------------------------------------------------------------------------- +// IntegerGap is used for: +// - int, int8, int16, int32, int64: +// - uint, uint8, uint16, uint32, uint64, uintptr: +// +// FloatGap is used for: +// - float32, float64 +// -------------------------------------------------------------------------------- +type numericGapType int + +const ( + integerGapType numericGapType = iota + floatGapType +) + +func gapTypeForOperand[T Number](num T) numericGapType { + gapType := integerGapType + + switch any(num).(type) { + case float32, float64: + gapType = floatGapType + } + return gapType +} + +// -------------------------------------------------------------------------------- +// numericGuidanceTracker - Tracking Info for Numeric Guidance +// +// For GuidanceFnMaximize: +// - gap is the largest value sent so far +// +// For GuidanceFnMinimize: +// - gap is the most negative value sent so far +// +// -------------------------------------------------------------------------------- +type numericGuidanceInfo struct { + gap any + descriminator numericGapType + maximize bool +} + +type numericGuidanceTracker map[string]*numericGuidanceInfo + +var ( + numeric_guidance_tracker numericGuidanceTracker = make(numericGuidanceTracker) + numeric_guidance_tracker_mutex sync.Mutex + numeric_guidance_info_mutex sync.Mutex +) + +func (tracker numericGuidanceTracker) getTrackerEntry(messageKey string, trackerType numericGapType, maximize bool) *numericGuidanceInfo { + var trackerEntry *numericGuidanceInfo + var ok bool + + if tracker == nil { + return nil + } + + numeric_guidance_tracker_mutex.Lock() + defer numeric_guidance_tracker_mutex.Unlock() + if trackerEntry, ok = numeric_guidance_tracker[messageKey]; !ok { + trackerEntry = newNumericGuidanceInfo(trackerType, maximize) + tracker[messageKey] = trackerEntry + } + + return trackerEntry +} + +// Create an numeric guidance entry +func newNumericGuidanceInfo(trackerType numericGapType, maximize bool) *numericGuidanceInfo { + + var gap any + if trackerType == integerGapType { + gap = newGapValue(uint64(math.MaxUint64), maximize) + } else { + gap = newGapValue(float64(math.MaxFloat64), maximize) + } + trackerInfo := numericGuidanceInfo{ + maximize: maximize, + descriminator: trackerType, + gap: gap, + } + return &trackerInfo +} + +func (tI *numericGuidanceInfo) should_maximize() bool { + return tI.maximize +} + +func (tI *numericGuidanceInfo) is_integer_gap() bool { + return tI.descriminator == integerGapType +} + +// -------------------------------------------------------------------------------- +// Represents integral and floating point extremes +// -------------------------------------------------------------------------------- +type gapValue[T numConstraint] struct { + gap_size T + gap_is_negative bool +} + +func newGapValue[T numConstraint](sz T, is_neg bool) any { + switch any(sz).(type) { + case uint64: + return gapValue[uint64]{gap_size: uint64(sz), gap_is_negative: is_neg} + + case float64: + return gapValue[float64]{gap_size: float64(sz), gap_is_negative: is_neg} + } + return nil +} + +func is_same_sign(left_val int64, right_val int64) bool { + same_sign := false + if left_val < 0 { + // left is negative + if right_val < 0 { + same_sign = true + } + } else { + // left is non-negative + if right_val >= 0 { + same_sign = true + } + } + return same_sign +} + +func abs_int64(val int64) uint64 { + if val >= 0 { + return uint64(val) + } + return uint64(0 - val) +} + +func is_greater_than[T numConstraint](left gapValue[T], right gapValue[T]) bool { + if !left.gap_is_negative && !right.gap_is_negative { + return left.gap_size > right.gap_size + } + if !left.gap_is_negative && right.gap_is_negative { + return true // any positive is greater than a negative + } + if left.gap_is_negative && right.gap_is_negative { + return right.gap_size > left.gap_size + } + if left.gap_is_negative && !right.gap_is_negative { + return false // any negative is less than a positive + } + return false +} + +func is_less_than[T numConstraint](left gapValue[T], right gapValue[T]) bool { + if !left.gap_is_negative && !right.gap_is_negative { + return left.gap_size < right.gap_size + } + if !left.gap_is_negative && right.gap_is_negative { + return false // any positive is greater than a negative + } + if left.gap_is_negative && right.gap_is_negative { + return right.gap_size < left.gap_size + } + if left.gap_is_negative && !right.gap_is_negative { + return true // any negative is less than a positive + } + return true +} + +func send_value_if_needed(tI *numericGuidanceInfo, gI *guidanceInfo) { + if tI == nil { + return + } + + numeric_guidance_info_mutex.Lock() + defer numeric_guidance_info_mutex.Unlock() + + // if this is a catalog entry (gI.hit is false) + // do not update the reference gap in the tracker (tI *numericGuidanceInfo) + if !gI.Hit { + emitGuidance(gI) + return + } + + should_send := false + maximize := tI.should_maximize() + + var gap gapValue[uint64] + var float_gap gapValue[float64] + + // Needs to have individual case statements to assist + // the compiler to infer the actual type of the var named 'operands' + switch operands := (gI.Data).(type) { + case numericOperands[int32]: + gap = makeGap(operands) + case numericOperands[int64]: + gap = makeGap(operands) + case numericOperands[uint64]: + gap = makeGap(operands) + case numericOperands[float64]: + float_gap = makeFloatGap(operands) + } + + var prev_gap gapValue[uint64] + var prev_float_gap gapValue[float64] + has_prev_gap := false + has_prev_float_gap := false + + prev_gap, has_prev_gap = tI.gap.(gapValue[uint64]) + if !has_prev_gap { + prev_float_gap, has_prev_float_gap = tI.gap.(gapValue[float64]) + } + + if has_prev_gap { + if maximize { + should_send = is_greater_than(gap, prev_gap) + } else { + should_send = is_less_than(gap, prev_gap) + } + } + + if has_prev_float_gap { + if maximize { + should_send = is_greater_than(float_gap, prev_float_gap) + } else { + should_send = is_less_than(float_gap, prev_float_gap) + } + } + + if should_send { + if tI.is_integer_gap() { + tI.gap = gap + } else { + tI.gap = float_gap + } + emitGuidance(gI) + } +} + +func emitGuidance(gI *guidanceInfo) error { + return internal.Json_data(map[string]any{"antithesis_guidance": gI}) +} + +// When left and right are the same sign (both negative, or both non-negative) +// Calculate: = (left - right). The gap_size is abs() and +// gap_is_negative is (right > left) +func makeGap[Op operandConstraint](operand numericOperands[Op]) gapValue[uint64] { + + var gap_size uint64 + var gap_is_negative bool + + switch this_op := any(operand).(type) { + case numericOperands[int32]: + result := int64(this_op.Left) - int64(this_op.Right) + gap_size = abs_int64(result) + gap_is_negative = result < 0 + + case numericOperands[int64]: + if is_same_sign(this_op.Left, this_op.Right) { + result := int64(this_op.Left) - int64(this_op.Right) + gap_size = abs_int64(result) + gap_is_negative = result < 0 + break + } + + // Otherwise left and right are opposite signs + // gap = abs(left) + abs(right) + // gap_is_negative = left < right + left_gap_size := abs_int64(this_op.Left) + right_gap_size := abs_int64(this_op.Right) + gap_size = left_gap_size + right_gap_size + gap_is_negative = this_op.Left < this_op.Right + + case numericOperands[uint64]: + left_val := this_op.Left + right_val := this_op.Right + gap_is_negative = false + if left_val < right_val { + gap_is_negative = true + gap_size = right_val - left_val + } else { + gap_size = left_val - right_val + } + + default: + zero_gap, _ := newGapValue(uint64(0), false).(gapValue[uint64]) + return zero_gap + } + + this_gap, _ := newGapValue(gap_size, gap_is_negative).(gapValue[uint64]) + return this_gap +} // MakeGap + +func makeFloatGap[Op operandConstraint](operand numericOperands[Op]) gapValue[float64] { + switch this_op := any(operand).(type) { + case numericOperands[float64]: + left_val := this_op.Left + right_val := this_op.Right + gap_is_negative := false + var gap_size float64 + if left_val < right_val { + gap_is_negative = true + gap_size = right_val - left_val + } else { + gap_size = left_val - right_val + } + + this_gap, _ := newGapValue(gap_size, gap_is_negative).(gapValue[float64]) + return this_gap + + default: + zero_gap, _ := newGapValue(float64(0.0), false).(gapValue[float64]) + return zero_gap + } +} // MakeFloatGap diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/rich_assert.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/rich_assert.go new file mode 100644 index 0000000..0edc736 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/rich_assert.go @@ -0,0 +1,330 @@ +//go:build enable_antithesis_sdk + +package assert + +// A type for writing raw assertions. +// guidanceFnType allows the assertion to provide guidance to +// the Antithesis platform when testing in Antithesis. +// Regular users of the assert package should not use it. +type guidanceFnType int + +const ( + guidanceFnMaximize guidanceFnType = iota // Maximize (left - right) values + guidanceFnMinimize // Minimize (left - right) values + guidanceFnWantAll // Encourages fuzzing explorations where boolean values are true + guidanceFnWantNone // Encourages fuzzing explorations where boolean values are false + guidanceFnExplore +) + +// guidanceFnExplore + +func get_guidance_type_string(gt guidanceFnType) string { + switch gt { + case guidanceFnMaximize, guidanceFnMinimize: + return "numeric" + case guidanceFnWantAll, guidanceFnWantNone: + return "boolean" + case guidanceFnExplore: + return "json" + } + return "" +} + +type numericOperands[T operandConstraint] struct { + Left T `json:"left"` + Right T `json:"right"` +} + +type guidanceInfo struct { + Data any `json:"guidance_data,omitempty"` + Location *locationInfo `json:"location"` + GuidanceType string `json:"guidance_type"` + Message string `json:"message"` + Id string `json:"id"` + Maximize bool `json:"maximize"` + Hit bool `json:"hit"` +} + +type booleanGuidanceInfo struct { + Data any `json:"guidance_data,omitempty"` + Location *locationInfo `json:"location"` + GuidanceType string `json:"guidance_type"` + Message string `json:"message"` + Id string `json:"id"` + Maximize bool `json:"maximize"` + Hit bool `json:"hit"` +} + +func uses_maximize(gt guidanceFnType) bool { + return gt == guidanceFnMaximize || gt == guidanceFnWantAll +} + +func newOperands[T Number](left, right T) any { + switch any(left).(type) { + case int8, int16, int32: + return numericOperands[int32]{int32(left), int32(right)} + case int, int64: + return numericOperands[int64]{int64(left), int64(right)} + case uint8, uint16, uint32, uint, uint64, uintptr: + return numericOperands[uint64]{uint64(left), uint64(right)} + case float32, float64: + return numericOperands[float64]{float64(left), float64(right)} + } + return nil +} + +func build_numeric_guidance[T Number](gt guidanceFnType, message string, left, right T, loc *locationInfo, id string, hit bool) *guidanceInfo { + + operands := newOperands(left, right) + if !hit { + operands = nil + } + + gI := guidanceInfo{ + GuidanceType: get_guidance_type_string(gt), + Message: message, + Id: id, + Location: loc, + Maximize: uses_maximize(gt), + Data: operands, + Hit: hit, + } + + return &gI +} + +type namedBoolDictionary map[string]bool + +func build_boolean_guidance(gt guidanceFnType, message string, named_bools []NamedBool, + loc *locationInfo, + id string, hit bool) *booleanGuidanceInfo { + + var guidance_data any + + // To ensure the sequence and naming for the named_bool values + if hit { + named_bool_dictionary := namedBoolDictionary{} + for _, named_bool := range named_bools { + named_bool_dictionary[named_bool.First] = named_bool.Second + } + guidance_data = named_bool_dictionary + } + + bgI := booleanGuidanceInfo{ + GuidanceType: get_guidance_type_string(gt), + Message: message, + Id: id, + Location: loc, + Maximize: uses_maximize(gt), + Data: guidance_data, + Hit: hit, + } + + return &bgI +} + +func behavior_to_guidance(behavior string) guidanceFnType { + guidance := guidanceFnExplore + switch behavior { + case "maximize": + guidance = guidanceFnMaximize + case "minimize": + guidance = guidanceFnMinimize + case "all": + guidance = guidanceFnWantAll + case "none": + guidance = guidanceFnWantNone + } + return guidance +} + +func numericGuidanceImpl[T Number](left, right T, message, id string, loc *locationInfo, guidanceFn guidanceFnType, hit bool) { + tI := numeric_guidance_tracker.getTrackerEntry(id, gapTypeForOperand(left), uses_maximize(guidanceFn)) + gI := build_numeric_guidance(guidanceFn, message, left, right, loc, id, hit) + send_value_if_needed(tI, gI) +} + +func booleanGuidanceImpl(named_bools []NamedBool, message, id string, loc *locationInfo, guidanceFn guidanceFnType, hit bool) { + tI := boolean_guidance_tracker.getTrackerEntry(id) + bgI := build_boolean_guidance(guidanceFn, message, named_bools, loc, id, hit) + tI.send_value(bgI) +} + +// NumericGuidanceRaw is a low-level method designed to be used by third-party frameworks. Regular users of the assert package should not call it. +func NumericGuidanceRaw[T Number]( + left, right T, + message, id string, + classname, funcname, filename string, + line int, + behavior string, + hit bool, +) { + loc := &locationInfo{classname, funcname, filename, line, columnUnknown} + guidanceFn := behavior_to_guidance(behavior) + numericGuidanceImpl(left, right, message, id, loc, guidanceFn, hit) +} + +// BooleanGuidanceRaw is a low-level method designed to be used by third-party frameworks. Regular users of the assert package should not call it. +func BooleanGuidanceRaw( + named_bools []NamedBool, + message, id string, + classname, funcname, filename string, + line int, + behavior string, + hit bool, +) { + loc := &locationInfo{classname, funcname, filename, line, columnUnknown} + guidanceFn := behavior_to_guidance(behavior) + booleanGuidanceImpl(named_bools, message, id, loc, guidanceFn, hit) +} + +func add_numeric_details[T Number](details map[string]any, left, right T) map[string]any { + // ---------------------------------------------------- + // Can not use maps.Clone() until go 1.21.0 or above + // enhancedDetails := maps.Clone(details) + // ---------------------------------------------------- + enhancedDetails := map[string]any{} + for k, v := range details { + enhancedDetails[k] = v + } + enhancedDetails["left"] = left + enhancedDetails["right"] = right + return enhancedDetails +} + +func add_boolean_details(details map[string]any, named_bools []NamedBool) map[string]any { + // ---------------------------------------------------- + // Can not use maps.Clone() until go 1.21.0 or above + // enhancedDetails := maps.Clone(details) + // ---------------------------------------------------- + enhancedDetails := map[string]any{} + for k, v := range details { + enhancedDetails[k] = v + } + for _, named_bool := range named_bools { + enhancedDetails[named_bool.First] = named_bool.Second + } + return enhancedDetails +} + +// Equivalent to asserting Always(left > right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func AlwaysGreaterThan[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left > right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, universalTest, alwaysDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMinimize, wasHit) +} + +// Equivalent to asserting Always(left >= right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func AlwaysGreaterThanOrEqualTo[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left >= right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, universalTest, alwaysDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMinimize, wasHit) +} + +// Equivalent to asserting Sometimes(T left > T right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func SometimesGreaterThan[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left > right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, existentialTest, sometimesDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMaximize, wasHit) +} + +// Equivalent to asserting Sometimes(T left >= T right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func SometimesGreaterThanOrEqualTo[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left >= right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, existentialTest, sometimesDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMaximize, wasHit) +} + +// Equivalent to asserting Always(left < right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func AlwaysLessThan[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left < right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, universalTest, alwaysDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMaximize, wasHit) +} + +// Equivalent to asserting Always(left <= right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func AlwaysLessThanOrEqualTo[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left <= right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, universalTest, alwaysDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMaximize, wasHit) +} + +// Equivalent to asserting Sometimes(T left < T right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func SometimesLessThan[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left < right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, existentialTest, sometimesDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMinimize, wasHit) +} + +// Equivalent to asserting Sometimes(T left <= T right, message, details). Information about left and right will automatically be added to the details parameter, with keys left and right. If you use this function for assertions that compare numeric quantities, you may help Antithesis find more bugs. +func SometimesLessThanOrEqualTo[T Number](left, right T, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + condition := left <= right + all_details := add_numeric_details(details, left, right) + assertImpl(condition, message, all_details, loc, wasHit, mustBeHit, existentialTest, sometimesDisplay, id) + + numericGuidanceImpl(left, right, message, id, loc, guidanceFnMinimize, wasHit) +} + +// Asserts that every time this is called, at least one bool in named_bools is true. Equivalent to Always(named_bools[0].second || named_bools[1].second || ..., message, details). If you use this for assertions about the behavior of booleans, you may help Antithesis find more bugs. Information about named_bools will automatically be added to the details parameter, and the keys will be the names of the bools. +func AlwaysSome(named_bools []NamedBool, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + disjunction := false + for _, named_bool := range named_bools { + if named_bool.Second { + disjunction = true + break + } + } + all_details := add_boolean_details(details, named_bools) + assertImpl(disjunction, message, all_details, loc, wasHit, mustBeHit, universalTest, alwaysDisplay, id) + + booleanGuidanceImpl(named_bools, message, id, loc, guidanceFnWantNone, wasHit) +} + +// Asserts that at least one time this is called, every bool in named_bools is true. Equivalent to Sometimes(named_bools[0].second && named_bools[1].second && ..., message, details). If you use this for assertions about the behavior of booleans, you may help Antithesis find more bugs. Information about named_bools will automatically be added to the details parameter, and the keys will be the names of the bools. +func SometimesAll(named_bools []NamedBool, message string, details map[string]any) { + loc := newLocationInfo(offsetAPICaller) + id := makeKey(message, loc) + conjunction := true + for _, named_bool := range named_bools { + if !named_bool.Second { + conjunction = false + break + } + } + all_details := add_boolean_details(details, named_bools) + assertImpl(conjunction, message, all_details, loc, wasHit, mustBeHit, existentialTest, sometimesDisplay, id) + + booleanGuidanceImpl(named_bools, message, id, loc, guidanceFnWantAll, wasHit) +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/rich_assert_nop.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/rich_assert_nop.go new file mode 100644 index 0000000..79ca12c --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/rich_assert_nop.go @@ -0,0 +1,34 @@ +//go:build !enable_antithesis_sdk + +package assert + +func AlwaysGreaterThan[T Number](left, right T, message string, details map[string]any) {} +func AlwaysGreaterThanOrEqualTo[T Number](left, right T, message string, details map[string]any) {} +func SometimesGreaterThan[T Number](left, right T, message string, details map[string]any) {} +func SometimesGreaterThanOrEqualTo[T Number](left, right T, message string, details map[string]any) {} +func AlwaysLessThan[T Number](left, right T, message string, details map[string]any) {} +func AlwaysLessThanOrEqualTo[T Number](left, right T, message string, details map[string]any) {} +func SometimesLessThan[T Number](left, right T, message string, details map[string]any) {} +func SometimesLessThanOrEqualTo[T Number](left, right T, message string, details map[string]any) {} + +func AlwaysSome(named_bool []NamedBool, message string, details map[string]any) {} +func SometimesAll(named_bool []NamedBool, message string, details map[string]any) {} + +func NumericGuidanceRaw[T Number](left, right T, + message, id string, + classname, funcname, filename string, + line int, + behavior string, + hit bool, +) { +} + +func BooleanGuidanceRaw( + named_bools []NamedBool, + message, id string, + classname, funcname, filename string, + line int, + behavior string, + hit bool, +) { +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/assert/tracker.go b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/tracker.go new file mode 100644 index 0000000..c88497d --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/assert/tracker.go @@ -0,0 +1,111 @@ +//go:build enable_antithesis_sdk + +package assert + +import ( + "runtime" + "sync" + "sync/atomic" + + "github.com/antithesishq/antithesis-sdk-go/internal" +) + +type trackerInfo struct { + Filename string + Classname string + PassCount int + FailCount int +} + +type emitTracker map[string]*trackerInfo + +// assert_tracker (global) keeps track of the unique asserts evaluated +var ( + assertTracker emitTracker = make(emitTracker) + trackerMutex sync.Mutex + trackerInfoMutex sync.Mutex +) + +func (tracker emitTracker) getTrackerEntry(messageKey string, filename, classname string) *trackerInfo { + var trackerEntry *trackerInfo + var ok bool + + if tracker == nil { + return nil + } + + trackerMutex.Lock() + defer trackerMutex.Unlock() + if trackerEntry, ok = tracker[messageKey]; !ok { + trackerEntry = newTrackerInfo(filename, classname) + tracker[messageKey] = trackerEntry + } + return trackerEntry +} + +func newTrackerInfo(filename, classname string) *trackerInfo { + trackerInfo := trackerInfo{ + PassCount: 0, + FailCount: 0, + Filename: filename, + Classname: classname, + } + return &trackerInfo +} + +func (ti *trackerInfo) emit(ai *assertInfo) { + if ti == nil || ai == nil { + return + } + + // Registrations are just sent to voidstar + hit := ai.Hit + if !hit { + emitAssert(ai) + return + } + + var err error + cond := ai.Condition + + trackerInfoMutex.Lock() + defer trackerInfoMutex.Unlock() + if cond { + if ti.PassCount == 0 { + err = emitAssert(ai) + } + if err == nil { + ti.PassCount++ + } + return + } + if ti.FailCount == 0 { + err = emitAssert(ai) + } + if err == nil { + ti.FailCount++ + } +} + +func versionMessage() { + languageBlock := map[string]any{ + "name": "Go", + "version": runtime.Version(), + } + versionBlock := map[string]any{ + "language": languageBlock, + "sdk_version": internal.SDK_Version, + "protocol_version": internal.Protocol_Version, + } + internal.Json_data(map[string]any{"antithesis_sdk": versionBlock}) +} + +// package-level flag +var hasEmitted atomic.Bool // initialzed to false + +func emitAssert(ai *assertInfo) error { + if hasEmitted.CompareAndSwap(false, true) { + versionMessage() + } + return internal.Json_data(wrappedAssertInfo{ai}) +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/internal/emit.go b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/emit.go new file mode 100644 index 0000000..a932f5c --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/emit.go @@ -0,0 +1,100 @@ +//go:build enable_antithesis_sdk + +package internal + +import ( + "encoding/json" + "log" + "math/rand" + "os" +) + +func Json_data(v any) error { + if data, err := json.Marshal(v); err != nil { + return err + } else { + handler.output(string(data)) + return nil + } +} + +func Get_random() uint64 { + return handler.random() +} + +func Notify(edge uint64) bool { + return handler.notify(edge) +} + +func InitCoverage(num_edges uint64, symbols string) uint64 { + return handler.init_coverage(num_edges, symbols) +} + +type libHandler interface { + output(message string) + random() uint64 + notify(edge uint64) bool + init_coverage(num_edges uint64, symbols string) uint64 +} + +const ( + errorLogLinePrefix = "[* antithesis-sdk-go *]" +) + +var handler libHandler + +type localHandler struct { + outputFile *os.File // can be nil +} + +func (h *localHandler) output(message string) { + msg_len := len(message) + if msg_len == 0 { + return + } + if h.outputFile != nil { + h.outputFile.WriteString(message + "\n") + } +} + +func (h *localHandler) random() uint64 { + return rand.Uint64() +} + +func (h *localHandler) notify(edge uint64) bool { + return false +} + +func (h *localHandler) init_coverage(num_edges uint64, symbols string) uint64 { + return 0 +} + +func init() { + handler = init_in_antithesis() + if handler == nil { + // Otherwise fallback to the local handler. + handler = openLocalHandler() + } +} + +// If `localOutputEnvVar` is set to a non-empty path, attempt to open that path and truncate the file +// to serve as the log file of the local handler. +// Otherwise, we don't have a log file, and logging is a no-op in the local handler. +func openLocalHandler() *localHandler { + path, is_set := os.LookupEnv(localOutputEnvVar) + if !is_set || len(path) == 0 { + return &localHandler{nil} + } + + // Open the file R/W (create if needed and possible) + file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + log.Printf("%s Failed to open path %s: %v", errorLogLinePrefix, path, err) + file = nil + } else if err = file.Truncate(0); err != nil { + log.Printf("%s Failed to truncate file at %s: %v", errorLogLinePrefix, path, err) + file = nil + } + + return &localHandler{file} +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/internal/sdk_const.go b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/sdk_const.go new file mode 100644 index 0000000..a4db4e7 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/sdk_const.go @@ -0,0 +1,12 @@ +package internal + +// -------------------------------------------------------------------------------- +// Versions +// -------------------------------------------------------------------------------- +const SDK_Version = "0.5.0" +const Protocol_Version = "1.1.0" + +// -------------------------------------------------------------------------------- +// Environment Vars +// -------------------------------------------------------------------------------- +const localOutputEnvVar = "ANTITHESIS_SDK_LOCAL_OUTPUT" diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/internal/voidstar_handler.go b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/voidstar_handler.go new file mode 100644 index 0000000..eb410fd --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/voidstar_handler.go @@ -0,0 +1,160 @@ +//go:build enable_antithesis_sdk && linux && amd64 && cgo + +package internal + +import ( + "fmt" + "unsafe" + "os" +) + +// -------------------------------------------------------------------------------- +// To build and run an executable with this package +// +// CC=clang CGO_ENABLED=1 go run ./main.go +// -------------------------------------------------------------------------------- + +// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// The commented lines below, and the `import "C"` line which must directly follow +// the commented lines are used by CGO. They are load-bearing, and should not be +// changed without first understanding how CGO uses them. +// +// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +// #cgo LDFLAGS: -ldl +// +// #include +// #include +// #include +// #include +// +// typedef void (*go_fuzz_json_data_fn)(const char *data, size_t size); +// void +// go_fuzz_json_data(void *f, const char *data, size_t size) { +// ((go_fuzz_json_data_fn)f)(data, size); +// } +// +// typedef void (*go_fuzz_flush_fn)(void); +// void +// go_fuzz_flush(void *f) { +// ((go_fuzz_flush_fn)f)(); +// } +// +// typedef uint64_t (*go_fuzz_get_random_fn)(void); +// uint64_t +// go_fuzz_get_random(void *f) { +// return ((go_fuzz_get_random_fn)f)(); +// } +// +// typedef bool (*go_notify_coverage_fn)(size_t); +// int +// go_notify_coverage(void *f, size_t edges) { +// bool b = ((go_notify_coverage_fn)f)(edges); +// return b ? 1 : 0; +// } +// +// typedef uint64_t (*go_init_coverage_fn)(size_t num_edges, const char *symbols); +// uint64_t +// go_init_coverage(void *f, size_t num_edges, const char *symbols) { +// return ((go_init_coverage_fn)f)(num_edges, symbols); +// } +// +import "C" + +const ( + defaultNativeLibraryPath = "/usr/lib/libvoidstar.so" +) + +type voidstarHandler struct { + fuzzJsonData unsafe.Pointer + fuzzFlush unsafe.Pointer + fuzzGetRandom unsafe.Pointer + initCoverage unsafe.Pointer + notifyCoverage unsafe.Pointer +} + +func (h *voidstarHandler) output(message string) { + msg_len := len(message) + if msg_len == 0 { + return + } + cstrMessage := C.CString(message) + defer C.free(unsafe.Pointer(cstrMessage)) + C.go_fuzz_json_data(h.fuzzJsonData, cstrMessage, C.ulong(msg_len)) + C.go_fuzz_flush(h.fuzzFlush) +} + +func (h *voidstarHandler) random() uint64 { + return uint64(C.go_fuzz_get_random(h.fuzzGetRandom)) +} + +func (h *voidstarHandler) init_coverage(num_edge uint64, symbols string) uint64 { + cstrSymbols := C.CString(symbols) + defer C.free(unsafe.Pointer(cstrSymbols)) + return uint64(C.go_init_coverage(h.initCoverage, C.ulong(num_edge), cstrSymbols)) +} + +func (h *voidstarHandler) notify(edge uint64) bool { + ival := int(C.go_notify_coverage(h.notifyCoverage, C.ulong(edge))) + return ival == 1 +} + +// Attempt to load libvoidstar and some symbols from `path` +func openSharedLib(path string) (*voidstarHandler, error) { + cstrPath := C.CString(path) + defer C.free(unsafe.Pointer(cstrPath)) + + dlError := func(message string) error { + return fmt.Errorf("%s: (%s)", message, C.GoString(C.dlerror())) + } + + sharedLib := C.dlopen(cstrPath, C.int(C.RTLD_NOW)) + if sharedLib == nil { + return nil, dlError("Can not load the Antithesis native library") + } + + loadFunc := func(name string) (symbol unsafe.Pointer, err error) { + cstrName := C.CString(name) + defer C.free(unsafe.Pointer(cstrName)) + if symbol = C.dlsym(sharedLib, cstrName); symbol == nil { + err = dlError(fmt.Sprintf("Can not access symbol %s", name)) + } + return + } + + fuzzJsonData, err := loadFunc("fuzz_json_data") + if err != nil { + return nil, err + } + fuzzFlush, err := loadFunc("fuzz_flush") + if err != nil { + return nil, err + } + fuzzGetRandom, err := loadFunc("fuzz_get_random") + if err != nil { + return nil, err + } + notifyCoverage, err := loadFunc("notify_coverage") + if err != nil { + return nil, err + } + initCoverage, err := loadFunc("init_coverage_module") + if err != nil { + return nil, err + } + return &voidstarHandler{fuzzJsonData, fuzzFlush, fuzzGetRandom, initCoverage, notifyCoverage}, nil +} + +// If we have a file at `defaultNativeLibraryPath`, we load the shared library +// (and panic on any error encountered during load). +func init_in_antithesis() libHandler { + if _, err := os.Stat(defaultNativeLibraryPath); err == nil { + handler, err := openSharedLib(defaultNativeLibraryPath) + if err != nil { + panic(err) + } + return handler + } + return nil +} diff --git a/vendor/github.com/antithesishq/antithesis-sdk-go/internal/voidstar_handler_noop.go b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/voidstar_handler_noop.go new file mode 100644 index 0000000..75c67a1 --- /dev/null +++ b/vendor/github.com/antithesishq/antithesis-sdk-go/internal/voidstar_handler_noop.go @@ -0,0 +1,7 @@ +//go:build enable_antithesis_sdk && (!linux || !amd64 || !cgo) + +package internal + +func init_in_antithesis() libHandler { + return nil +} diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE index c836416..bc52e96 100644 --- a/vendor/github.com/davecgh/go-spew/LICENSE +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -2,7 +2,7 @@ ISC License Copyright (c) 2012-2016 Dave Collins -Permission to use, copy, modify, and distribute this software for any +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go index 8a4a658..7929947 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -16,7 +16,9 @@ // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build !js,!appengine,!safe,!disableunsafe +// Go versions prior to 1.4 are disabled because they use a different layout +// for interfaces which make the implementation of unsafeReflectValue more complex. +// +build !js,!appengine,!safe,!disableunsafe,go1.4 package spew @@ -34,80 +36,49 @@ const ( ptrSize = unsafe.Sizeof((*byte)(nil)) ) +type flag uintptr + var ( - // offsetPtr, offsetScalar, and offsetFlag are the offsets for the - // internal reflect.Value fields. These values are valid before golang - // commit ecccf07e7f9d which changed the format. The are also valid - // after commit 82f48826c6c7 which changed the format again to mirror - // the original format. Code in the init function updates these offsets - // as necessary. - offsetPtr = uintptr(ptrSize) - offsetScalar = uintptr(0) - offsetFlag = uintptr(ptrSize * 2) - - // flagKindWidth and flagKindShift indicate various bits that the - // reflect package uses internally to track kind information. - // - // flagRO indicates whether or not the value field of a reflect.Value is - // read-only. - // - // flagIndir indicates whether the value field of a reflect.Value is - // the actual data or a pointer to the data. - // - // These values are valid before golang commit 90a7c3c86944 which - // changed their positions. Code in the init function updates these - // flags as necessary. - flagKindWidth = uintptr(5) - flagKindShift = uintptr(flagKindWidth - 1) - flagRO = uintptr(1 << 0) - flagIndir = uintptr(1 << 1) + // flagRO indicates whether the value field of a reflect.Value + // is read-only. + flagRO flag + + // flagAddr indicates whether the address of the reflect.Value's + // value may be taken. + flagAddr flag ) -func init() { - // Older versions of reflect.Value stored small integers directly in the - // ptr field (which is named val in the older versions). Versions - // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named - // scalar for this purpose which unfortunately came before the flag - // field, so the offset of the flag field is different for those - // versions. - // - // This code constructs a new reflect.Value from a known small integer - // and checks if the size of the reflect.Value struct indicates it has - // the scalar field. When it does, the offsets are updated accordingly. - vv := reflect.ValueOf(0xf00) - if unsafe.Sizeof(vv) == (ptrSize * 4) { - offsetScalar = ptrSize * 2 - offsetFlag = ptrSize * 3 - } +// flagKindMask holds the bits that make up the kind +// part of the flags field. In all the supported versions, +// it is in the lower 5 bits. +const flagKindMask = flag(0x1f) - // Commit 90a7c3c86944 changed the flag positions such that the low - // order bits are the kind. This code extracts the kind from the flags - // field and ensures it's the correct type. When it's not, the flag - // order has been changed to the newer format, so the flags are updated - // accordingly. - upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) - upfv := *(*uintptr)(upf) - flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { - flagKindShift = 0 - flagRO = 1 << 5 - flagIndir = 1 << 6 - - // Commit adf9b30e5594 modified the flags to separate the - // flagRO flag into two bits which specifies whether or not the - // field is embedded. This causes flagIndir to move over a bit - // and means that flagRO is the combination of either of the - // original flagRO bit and the new bit. - // - // This code detects the change by extracting what used to be - // the indirect bit to ensure it's set. When it's not, the flag - // order has been changed to the newer format, so the flags are - // updated accordingly. - if upfv&flagIndir == 0 { - flagRO = 3 << 5 - flagIndir = 1 << 7 - } +// Different versions of Go have used different +// bit layouts for the flags type. This table +// records the known combinations. +var okFlags = []struct { + ro, addr flag +}{{ + // From Go 1.4 to 1.5 + ro: 1 << 5, + addr: 1 << 7, +}, { + // Up to Go tip. + ro: 1<<5 | 1<<6, + addr: 1 << 8, +}} + +var flagValOffset = func() uintptr { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") } + return field.Offset +}() + +// flagField returns a pointer to the flag field of a reflect.Value. +func flagField(v *reflect.Value) *flag { + return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses @@ -119,34 +90,56 @@ func init() { // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { - indirects := 1 - vt := v.Type() - upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) - rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) - if rvf&flagIndir != 0 { - vt = reflect.PtrTo(v.Type()) - indirects++ - } else if offsetScalar != 0 { - // The value is in the scalar field when it's not one of the - // reference types. - switch vt.Kind() { - case reflect.Uintptr: - case reflect.Chan: - case reflect.Func: - case reflect.Map: - case reflect.Ptr: - case reflect.UnsafePointer: - default: - upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + - offsetScalar) - } +func unsafeReflectValue(v reflect.Value) reflect.Value { + if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { + return v } + flagFieldPtr := flagField(&v) + *flagFieldPtr &^= flagRO + *flagFieldPtr |= flagAddr + return v +} - pv := reflect.NewAt(vt, upv) - rv = pv - for i := 0; i < indirects; i++ { - rv = rv.Elem() +// Sanity checks against future reflect package changes +// to the type or semantics of the Value.flag field. +func init() { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") + } + if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { + panic("reflect.Value flag field has changed kind") + } + type t0 int + var t struct { + A t0 + // t0 will have flagEmbedRO set. + t0 + // a will have flagStickyRO set + a t0 + } + vA := reflect.ValueOf(t).FieldByName("A") + va := reflect.ValueOf(t).FieldByName("a") + vt0 := reflect.ValueOf(t).FieldByName("t0") + + // Infer flagRO from the difference between the flags + // for the (otherwise identical) fields in t. + flagPublic := *flagField(&vA) + flagWithRO := *flagField(&va) | *flagField(&vt0) + flagRO = flagPublic ^ flagWithRO + + // Infer flagAddr from the difference between a value + // taken from a pointer and not. + vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") + flagNoPtr := *flagField(&vA) + flagPtr := *flagField(&vPtrA) + flagAddr = flagNoPtr ^ flagPtr + + // Check that the inferred flags tally with one of the known versions. + for _, f := range okFlags { + if flagRO == f.ro && flagAddr == f.addr { + return + } } - return rv + panic("reflect.Value read-only flag has changed semantics") } diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go index 1fe3cf3..205c28d 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -16,7 +16,7 @@ // when the code is running on Google App Engine, compiled by GopherJS, or // "-tags safe" is added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build js appengine safe disableunsafe +// +build js appengine safe disableunsafe !go1.4 package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go index 7c519ff..1be8ce9 100644 --- a/vendor/github.com/davecgh/go-spew/spew/common.go +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) { w.Write(closeParenBytes) } -// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go index df1d582..f78d89f 100644 --- a/vendor/github.com/davecgh/go-spew/spew/dump.go +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -35,16 +35,16 @@ var ( // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. - cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") + cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) ) // dumpState contains information about the state of a dump operation. @@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) { // Display dereferenced value. d.w.Write(openParenBytes) switch { - case nilFound == true: + case nilFound: d.w.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: d.w.Write(circularBytes) default: diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go index c49875b..b04edb7 100644 --- a/vendor/github.com/davecgh/go-spew/spew/format.go +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) { // Display dereferenced value. switch { - case nilFound == true: + case nilFound: f.fs.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: f.fs.Write(circularShortBytes) default: diff --git a/vendor/github.com/google/go-tpm/LICENSE b/vendor/github.com/google/go-tpm/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/github.com/google/go-tpm/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/README.md b/vendor/github.com/google/go-tpm/legacy/tpm2/README.md new file mode 100644 index 0000000..4d0ff8b --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/README.md @@ -0,0 +1,35 @@ +# TPM 2.0 client library + +## Tests + +This library contains unit tests in `github.com/google/go-tpm/tpm2`, which just +tests that various encoding and error checking functions work correctly. It also +contains more comprehensive integration tests in +`github.com/google/go-tpm/tpm2/test`, which run actual commands on a TPM. + +By default, these integration tests are run against the +[`go-tpm-tools`](https://github.com/google/go-tpm-tools) +simulator, which is baesed on the +[Microsoft Reference TPM2 code](https://github.com/microsoft/ms-tpm-20-ref). To +run both the unit and integration tests, run (in this directory) +```bash +go test . ./test +``` + +These integration tests can also be run against a real TPM device. This is +slightly more complex as the tests often need to be built as a normal user and +then executed as root. For example, +```bash +# Build the test binary without running it +go test -c github.com/google/go-tpm/tpm2/test +# Execute the test binary as root +sudo ./test.test --tpm-path=/dev/tpmrm0 +``` +On Linux, The `--tpm-path` causes the integration tests to be run against a +real TPM located at that path (usually `/dev/tpmrm0` or `/dev/tpm0`). On Windows, the story is similar, execept that +the `--use-tbs` flag is used instead. + +Tip: if your TPM host is remote and you don't want to install Go on it, this +same two-step process can be used. The test binary can be copied to a remote +host and run without extra installation (as the test binary has very few +*runtime* dependancies). diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/constants.go b/vendor/github.com/google/go-tpm/legacy/tpm2/constants.go new file mode 100644 index 0000000..1357370 --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/constants.go @@ -0,0 +1,576 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpm2 + +import ( + "crypto" + "crypto/elliptic" + "fmt" + "strings" + + // Register the relevant hash implementations to prevent a runtime failure. + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + + "github.com/google/go-tpm/tpmutil" +) + +var hashInfo = []struct { + alg Algorithm + hash crypto.Hash +}{ + {AlgSHA1, crypto.SHA1}, + {AlgSHA256, crypto.SHA256}, + {AlgSHA384, crypto.SHA384}, + {AlgSHA512, crypto.SHA512}, + {AlgSHA3_256, crypto.SHA3_256}, + {AlgSHA3_384, crypto.SHA3_384}, + {AlgSHA3_512, crypto.SHA3_512}, +} + +// MAX_DIGEST_BUFFER is the maximum size of []byte request or response fields. +// Typically used for chunking of big blobs of data (such as for hashing or +// encryption). +const maxDigestBuffer = 1024 + +// Algorithm represents a TPM_ALG_ID value. +type Algorithm uint16 + +// HashToAlgorithm looks up the TPM2 algorithm corresponding to the provided crypto.Hash +func HashToAlgorithm(hash crypto.Hash) (Algorithm, error) { + for _, info := range hashInfo { + if info.hash == hash { + return info.alg, nil + } + } + return AlgUnknown, fmt.Errorf("go hash algorithm #%d has no TPM2 algorithm", hash) +} + +// IsNull returns true if a is AlgNull or zero (unset). +func (a Algorithm) IsNull() bool { + return a == AlgNull || a == AlgUnknown +} + +// UsesCount returns true if a signature algorithm uses count value. +func (a Algorithm) UsesCount() bool { + return a == AlgECDAA +} + +// UsesHash returns true if the algorithm requires the use of a hash. +func (a Algorithm) UsesHash() bool { + return a == AlgOAEP +} + +// Hash returns a crypto.Hash based on the given TPM_ALG_ID. +// An error is returned if the given algorithm is not a hash algorithm or is not available. +func (a Algorithm) Hash() (crypto.Hash, error) { + for _, info := range hashInfo { + if info.alg == a { + if !info.hash.Available() { + return crypto.Hash(0), fmt.Errorf("go hash algorithm #%d not available", info.hash) + } + return info.hash, nil + } + } + return crypto.Hash(0), fmt.Errorf("hash algorithm not supported: 0x%x", a) +} + +func (a Algorithm) String() string { + var s strings.Builder + var err error + switch a { + case AlgUnknown: + _, err = s.WriteString("AlgUnknown") + case AlgRSA: + _, err = s.WriteString("RSA") + case AlgSHA1: + _, err = s.WriteString("SHA1") + case AlgHMAC: + _, err = s.WriteString("HMAC") + case AlgAES: + _, err = s.WriteString("AES") + case AlgKeyedHash: + _, err = s.WriteString("KeyedHash") + case AlgXOR: + _, err = s.WriteString("XOR") + case AlgSHA256: + _, err = s.WriteString("SHA256") + case AlgSHA384: + _, err = s.WriteString("SHA384") + case AlgSHA512: + _, err = s.WriteString("SHA512") + case AlgNull: + _, err = s.WriteString("AlgNull") + case AlgRSASSA: + _, err = s.WriteString("RSASSA") + case AlgRSAES: + _, err = s.WriteString("RSAES") + case AlgRSAPSS: + _, err = s.WriteString("RSAPSS") + case AlgOAEP: + _, err = s.WriteString("OAEP") + case AlgECDSA: + _, err = s.WriteString("ECDSA") + case AlgECDH: + _, err = s.WriteString("ECDH") + case AlgECDAA: + _, err = s.WriteString("ECDAA") + case AlgKDF2: + _, err = s.WriteString("KDF2") + case AlgECC: + _, err = s.WriteString("ECC") + case AlgSymCipher: + _, err = s.WriteString("SymCipher") + case AlgSHA3_256: + _, err = s.WriteString("SHA3_256") + case AlgSHA3_384: + _, err = s.WriteString("SHA3_384") + case AlgSHA3_512: + _, err = s.WriteString("SHA3_512") + case AlgCTR: + _, err = s.WriteString("CTR") + case AlgOFB: + _, err = s.WriteString("OFB") + case AlgCBC: + _, err = s.WriteString("CBC") + case AlgCFB: + _, err = s.WriteString("CFB") + case AlgECB: + _, err = s.WriteString("ECB") + default: + return fmt.Sprintf("Alg?<%d>", int(a)) + } + if err != nil { + return fmt.Sprintf("Writing to string builder failed: %v", err) + } + return s.String() +} + +// Supported Algorithms. +const ( + AlgUnknown Algorithm = 0x0000 + AlgRSA Algorithm = 0x0001 + AlgSHA1 Algorithm = 0x0004 + AlgHMAC Algorithm = 0x0005 + AlgAES Algorithm = 0x0006 + AlgKeyedHash Algorithm = 0x0008 + AlgXOR Algorithm = 0x000A + AlgSHA256 Algorithm = 0x000B + AlgSHA384 Algorithm = 0x000C + AlgSHA512 Algorithm = 0x000D + AlgNull Algorithm = 0x0010 + AlgRSASSA Algorithm = 0x0014 + AlgRSAES Algorithm = 0x0015 + AlgRSAPSS Algorithm = 0x0016 + AlgOAEP Algorithm = 0x0017 + AlgECDSA Algorithm = 0x0018 + AlgECDH Algorithm = 0x0019 + AlgECDAA Algorithm = 0x001A + AlgKDF2 Algorithm = 0x0021 + AlgECC Algorithm = 0x0023 + AlgSymCipher Algorithm = 0x0025 + AlgSHA3_256 Algorithm = 0x0027 + AlgSHA3_384 Algorithm = 0x0028 + AlgSHA3_512 Algorithm = 0x0029 + AlgCTR Algorithm = 0x0040 + AlgOFB Algorithm = 0x0041 + AlgCBC Algorithm = 0x0042 + AlgCFB Algorithm = 0x0043 + AlgECB Algorithm = 0x0044 +) + +// HandleType defines a type of handle. +type HandleType uint8 + +// Supported handle types +const ( + HandleTypePCR HandleType = 0x00 + HandleTypeNVIndex HandleType = 0x01 + HandleTypeHMACSession HandleType = 0x02 + HandleTypeLoadedSession HandleType = 0x02 + HandleTypePolicySession HandleType = 0x03 + HandleTypeSavedSession HandleType = 0x03 + HandleTypePermanent HandleType = 0x40 + HandleTypeTransient HandleType = 0x80 + HandleTypePersistent HandleType = 0x81 +) + +// SessionType defines the type of session created in StartAuthSession. +type SessionType uint8 + +// Supported session types. +const ( + SessionHMAC SessionType = 0x00 + SessionPolicy SessionType = 0x01 + SessionTrial SessionType = 0x03 +) + +// SessionAttributes represents an attribute of a session. +type SessionAttributes byte + +// Session Attributes (Structures 8.4 TPMA_SESSION) +const ( + AttrContinueSession SessionAttributes = 1 << iota + AttrAuditExclusive + AttrAuditReset + _ // bit 3 reserved + _ // bit 4 reserved + AttrDecrypt + AttrEcrypt + AttrAudit +) + +// EmptyAuth represents the empty authorization value. +var EmptyAuth []byte + +// KeyProp is a bitmask used in Attributes field of key templates. Individual +// flags should be OR-ed to form a full mask. +type KeyProp uint32 + +// Key properties. +const ( + FlagFixedTPM KeyProp = 0x00000002 + FlagStClear KeyProp = 0x00000004 + FlagFixedParent KeyProp = 0x00000010 + FlagSensitiveDataOrigin KeyProp = 0x00000020 + FlagUserWithAuth KeyProp = 0x00000040 + FlagAdminWithPolicy KeyProp = 0x00000080 + FlagNoDA KeyProp = 0x00000400 + FlagRestricted KeyProp = 0x00010000 + FlagDecrypt KeyProp = 0x00020000 + FlagSign KeyProp = 0x00040000 + + FlagSealDefault = FlagFixedTPM | FlagFixedParent + FlagSignerDefault = FlagSign | FlagRestricted | FlagFixedTPM | + FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth + FlagStorageDefault = FlagDecrypt | FlagRestricted | FlagFixedTPM | + FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth +) + +// TPMProp represents a Property Tag (TPM_PT) used with calls to GetCapability(CapabilityTPMProperties). +type TPMProp uint32 + +// TPM Capability Properties, see TPM 2.0 Spec, Rev 1.38, Table 23. +// Fixed TPM Properties (PT_FIXED) +const ( + FamilyIndicator TPMProp = 0x100 + iota + SpecLevel + SpecRevision + SpecDayOfYear + SpecYear + Manufacturer + VendorString1 + VendorString2 + VendorString3 + VendorString4 + VendorTPMType + FirmwareVersion1 + FirmwareVersion2 + InputMaxBufferSize + TransientObjectsMin + PersistentObjectsMin + LoadedObjectsMin + ActiveSessionsMax + PCRCount + PCRSelectMin + ContextGapMax + _ // (PT_FIXED + 21) is skipped + NVCountersMax + NVIndexMax + MemoryMethod + ClockUpdate + ContextHash + ContextSym + ContextSymSize + OrderlyCount + CommandMaxSize + ResponseMaxSize + DigestMaxSize + ObjectContextMaxSize + SessionContextMaxSize + PSFamilyIndicator + PSSpecLevel + PSSpecRevision + PSSpecDayOfYear + PSSpecYear + SplitSigningMax + TotalCommands + LibraryCommands + VendorCommands + NVMaxBufferSize + TPMModes + CapabilityMaxBufferSize +) + +// Variable TPM Properties (PT_VAR) +const ( + TPMAPermanent TPMProp = 0x200 + iota + TPMAStartupClear + HRNVIndex + HRLoaded + HRLoadedAvail + HRActive + HRActiveAvail + HRTransientAvail + CurrentPersistent + AvailPersistent + NVCounters + NVCountersAvail + AlgorithmSet + LoadedCurves + LockoutCounter + MaxAuthFail + LockoutInterval + LockoutRecovery + NVWriteRecovery + AuditCounter0 + AuditCounter1 +) + +// Allowed ranges of different kinds of Handles (TPM_HANDLE) +// These constants have type TPMProp for backwards compatibility. +const ( + PCRFirst TPMProp = 0x00000000 + HMACSessionFirst TPMProp = 0x02000000 + LoadedSessionFirst TPMProp = 0x02000000 + PolicySessionFirst TPMProp = 0x03000000 + ActiveSessionFirst TPMProp = 0x03000000 + TransientFirst TPMProp = 0x80000000 + PersistentFirst TPMProp = 0x81000000 + PersistentLast TPMProp = 0x81FFFFFF + PlatformPersistent TPMProp = 0x81800000 + NVIndexFirst TPMProp = 0x01000000 + NVIndexLast TPMProp = 0x01FFFFFF + PermanentFirst TPMProp = 0x40000000 + PermanentLast TPMProp = 0x4000010F +) + +// Reserved Handles. +const ( + HandleOwner tpmutil.Handle = 0x40000001 + iota + HandleRevoke + HandleTransport + HandleOperator + HandleAdmin + HandleEK + HandleNull + HandleUnassigned + HandlePasswordSession + HandleLockout + HandleEndorsement + HandlePlatform +) + +// Capability identifies some TPM property or state type. +type Capability uint32 + +// TPM Capabilities. +const ( + CapabilityAlgs Capability = iota + CapabilityHandles + CapabilityCommands + CapabilityPPCommands + CapabilityAuditCommands + CapabilityPCRs + CapabilityTPMProperties + CapabilityPCRProperties + CapabilityECCCurves + CapabilityAuthPolicies +) + +// TPM Structure Tags. Tags are used to disambiguate structures, similar to Alg +// values: tag value defines what kind of data lives in a nested field. +const ( + TagNull tpmutil.Tag = 0x8000 + TagNoSessions tpmutil.Tag = 0x8001 + TagSessions tpmutil.Tag = 0x8002 + TagAttestCertify tpmutil.Tag = 0x8017 + TagAttestQuote tpmutil.Tag = 0x8018 + TagAttestCreation tpmutil.Tag = 0x801a + TagAuthSecret tpmutil.Tag = 0x8023 + TagHashCheck tpmutil.Tag = 0x8024 + TagAuthSigned tpmutil.Tag = 0x8025 +) + +// StartupType instructs the TPM on how to handle its state during Shutdown or +// Startup. +type StartupType uint16 + +// Startup types +const ( + StartupClear StartupType = iota + StartupState +) + +// EllipticCurve identifies specific EC curves. +type EllipticCurve uint16 + +// ECC curves supported by TPM 2.0 spec. +const ( + CurveNISTP192 = EllipticCurve(iota + 1) + CurveNISTP224 + CurveNISTP256 + CurveNISTP384 + CurveNISTP521 + + CurveBNP256 = EllipticCurve(iota + 10) + CurveBNP638 + + CurveSM2P256 = EllipticCurve(0x0020) +) + +var toGoCurve = map[EllipticCurve]elliptic.Curve{ + CurveNISTP224: elliptic.P224(), + CurveNISTP256: elliptic.P256(), + CurveNISTP384: elliptic.P384(), + CurveNISTP521: elliptic.P521(), +} + +// Supported TPM operations. +const ( + CmdNVUndefineSpaceSpecial tpmutil.Command = 0x0000011F + CmdEvictControl tpmutil.Command = 0x00000120 + CmdUndefineSpace tpmutil.Command = 0x00000122 + CmdClear tpmutil.Command = 0x00000126 + CmdHierarchyChangeAuth tpmutil.Command = 0x00000129 + CmdDefineSpace tpmutil.Command = 0x0000012A + CmdPCRAllocate tpmutil.Command = 0x0000012B + CmdCreatePrimary tpmutil.Command = 0x00000131 + CmdIncrementNVCounter tpmutil.Command = 0x00000134 + CmdWriteNV tpmutil.Command = 0x00000137 + CmdWriteLockNV tpmutil.Command = 0x00000138 + CmdDictionaryAttackLockReset tpmutil.Command = 0x00000139 + CmdDictionaryAttackParameters tpmutil.Command = 0x0000013A + CmdPCREvent tpmutil.Command = 0x0000013C + CmdPCRReset tpmutil.Command = 0x0000013D + CmdSequenceComplete tpmutil.Command = 0x0000013E + CmdStartup tpmutil.Command = 0x00000144 + CmdShutdown tpmutil.Command = 0x00000145 + CmdActivateCredential tpmutil.Command = 0x00000147 + CmdCertify tpmutil.Command = 0x00000148 + CmdCertifyCreation tpmutil.Command = 0x0000014A + CmdReadNV tpmutil.Command = 0x0000014E + CmdReadLockNV tpmutil.Command = 0x0000014F + CmdPolicySecret tpmutil.Command = 0x00000151 + CmdCreate tpmutil.Command = 0x00000153 + CmdECDHZGen tpmutil.Command = 0x00000154 + CmdImport tpmutil.Command = 0x00000156 + CmdLoad tpmutil.Command = 0x00000157 + CmdQuote tpmutil.Command = 0x00000158 + CmdRSADecrypt tpmutil.Command = 0x00000159 + CmdSequenceUpdate tpmutil.Command = 0x0000015C + CmdSign tpmutil.Command = 0x0000015D + CmdUnseal tpmutil.Command = 0x0000015E + CmdPolicySigned tpmutil.Command = 0x00000160 + CmdContextLoad tpmutil.Command = 0x00000161 + CmdContextSave tpmutil.Command = 0x00000162 + CmdECDHKeyGen tpmutil.Command = 0x00000163 + CmdEncryptDecrypt tpmutil.Command = 0x00000164 + CmdFlushContext tpmutil.Command = 0x00000165 + CmdLoadExternal tpmutil.Command = 0x00000167 + CmdMakeCredential tpmutil.Command = 0x00000168 + CmdReadPublicNV tpmutil.Command = 0x00000169 + CmdPolicyCommandCode tpmutil.Command = 0x0000016C + CmdPolicyOr tpmutil.Command = 0x00000171 + CmdReadPublic tpmutil.Command = 0x00000173 + CmdRSAEncrypt tpmutil.Command = 0x00000174 + CmdStartAuthSession tpmutil.Command = 0x00000176 + CmdGetCapability tpmutil.Command = 0x0000017A + CmdGetRandom tpmutil.Command = 0x0000017B + CmdHash tpmutil.Command = 0x0000017D + CmdPCRRead tpmutil.Command = 0x0000017E + CmdPolicyPCR tpmutil.Command = 0x0000017F + CmdReadClock tpmutil.Command = 0x00000181 + CmdPCRExtend tpmutil.Command = 0x00000182 + CmdEventSequenceComplete tpmutil.Command = 0x00000185 + CmdHashSequenceStart tpmutil.Command = 0x00000186 + CmdPolicyGetDigest tpmutil.Command = 0x00000189 + CmdPolicyPassword tpmutil.Command = 0x0000018C + CmdEncryptDecrypt2 tpmutil.Command = 0x00000193 +) + +// Regular TPM 2.0 devices use 24-bit mask (3 bytes) for PCR selection. +const sizeOfPCRSelect = 3 + +const defaultRSAExponent = 1<<16 + 1 + +// NVAttr is a bitmask used in Attributes field of NV indexes. Individual +// flags should be OR-ed to form a full mask. +type NVAttr uint32 + +// NV Attributes +const ( + AttrPPWrite NVAttr = 0x00000001 + AttrOwnerWrite NVAttr = 0x00000002 + AttrAuthWrite NVAttr = 0x00000004 + AttrPolicyWrite NVAttr = 0x00000008 + AttrPolicyDelete NVAttr = 0x00000400 + AttrWriteLocked NVAttr = 0x00000800 + AttrWriteAll NVAttr = 0x00001000 + AttrWriteDefine NVAttr = 0x00002000 + AttrWriteSTClear NVAttr = 0x00004000 + AttrGlobalLock NVAttr = 0x00008000 + AttrPPRead NVAttr = 0x00010000 + AttrOwnerRead NVAttr = 0x00020000 + AttrAuthRead NVAttr = 0x00040000 + AttrPolicyRead NVAttr = 0x00080000 + AttrNoDA NVAttr = 0x02000000 + AttrOrderly NVAttr = 0x04000000 + AttrClearSTClear NVAttr = 0x08000000 + AttrReadLocked NVAttr = 0x10000000 + AttrWritten NVAttr = 0x20000000 + AttrPlatformCreate NVAttr = 0x40000000 + AttrReadSTClear NVAttr = 0x80000000 +) + +var permMap = map[NVAttr]string{ + AttrPPWrite: "PPWrite", + AttrOwnerWrite: "OwnerWrite", + AttrAuthWrite: "AuthWrite", + AttrPolicyWrite: "PolicyWrite", + AttrPolicyDelete: "PolicyDelete", + AttrWriteLocked: "WriteLocked", + AttrWriteAll: "WriteAll", + AttrWriteDefine: "WriteDefine", + AttrWriteSTClear: "WriteSTClear", + AttrGlobalLock: "GlobalLock", + AttrPPRead: "PPRead", + AttrOwnerRead: "OwnerRead", + AttrAuthRead: "AuthRead", + AttrPolicyRead: "PolicyRead", + AttrNoDA: "No Do", + AttrOrderly: "Oderly", + AttrClearSTClear: "ClearSTClear", + AttrReadLocked: "ReadLocked", + AttrWritten: "Writte", + AttrPlatformCreate: "PlatformCreate", + AttrReadSTClear: "ReadSTClear", +} + +// String returns a textual representation of the set of NVAttr +func (p NVAttr) String() string { + var retString strings.Builder + for iterator, item := range permMap { + if (p & iterator) != 0 { + retString.WriteString(item + " + ") + } + } + if retString.String() == "" { + return "Permission/s not found" + } + return strings.TrimSuffix(retString.String(), " + ") + +} diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/error.go b/vendor/github.com/google/go-tpm/legacy/tpm2/error.go new file mode 100644 index 0000000..e198335 --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/error.go @@ -0,0 +1,362 @@ +package tpm2 + +import ( + "fmt" + + "github.com/google/go-tpm/tpmutil" +) + +type ( + // RCFmt0 holds Format 0 error codes + RCFmt0 uint8 + + // RCFmt1 holds Format 1 error codes + RCFmt1 uint8 + + // RCWarn holds error codes used in warnings + RCWarn uint8 + + // RCIndex is used to reference arguments, handles and sessions in errors + RCIndex uint8 +) + +// Format 0 error codes. +const ( + RCInitialize RCFmt0 = 0x00 + RCFailure RCFmt0 = 0x01 + RCSequence RCFmt0 = 0x03 + RCPrivate RCFmt0 = 0x0B + RCHMAC RCFmt0 = 0x19 + RCDisabled RCFmt0 = 0x20 + RCExclusive RCFmt0 = 0x21 + RCAuthType RCFmt0 = 0x24 + RCAuthMissing RCFmt0 = 0x25 + RCPolicy RCFmt0 = 0x26 + RCPCR RCFmt0 = 0x27 + RCPCRChanged RCFmt0 = 0x28 + RCUpgrade RCFmt0 = 0x2D + RCTooManyContexts RCFmt0 = 0x2E + RCAuthUnavailable RCFmt0 = 0x2F + RCReboot RCFmt0 = 0x30 + RCUnbalanced RCFmt0 = 0x31 + RCCommandSize RCFmt0 = 0x42 + RCCommandCode RCFmt0 = 0x43 + RCAuthSize RCFmt0 = 0x44 + RCAuthContext RCFmt0 = 0x45 + RCNVRange RCFmt0 = 0x46 + RCNVSize RCFmt0 = 0x47 + RCNVLocked RCFmt0 = 0x48 + RCNVAuthorization RCFmt0 = 0x49 + RCNVUninitialized RCFmt0 = 0x4A + RCNVSpace RCFmt0 = 0x4B + RCNVDefined RCFmt0 = 0x4C + RCBadContext RCFmt0 = 0x50 + RCCPHash RCFmt0 = 0x51 + RCParent RCFmt0 = 0x52 + RCNeedsTest RCFmt0 = 0x53 + RCNoResult RCFmt0 = 0x54 + RCSensitive RCFmt0 = 0x55 +) + +var fmt0Msg = map[RCFmt0]string{ + RCInitialize: "TPM not initialized by TPM2_Startup or already initialized", + RCFailure: "commands not being accepted because of a TPM failure", + RCSequence: "improper use of a sequence handle", + RCPrivate: "not currently used", + RCHMAC: "not currently used", + RCDisabled: "the command is disabled", + RCExclusive: "command failed because audit sequence required exclusivity", + RCAuthType: "authorization handle is not correct for command", + RCAuthMissing: "5 command requires an authorization session for handle and it is not present", + RCPolicy: "policy failure in math operation or an invalid authPolicy value", + RCPCR: "PCR check fail", + RCPCRChanged: "PCR have changed since checked", + RCUpgrade: "TPM is in field upgrade mode unless called via TPM2_FieldUpgradeData(), then it is not in field upgrade mode", + RCTooManyContexts: "context ID counter is at maximum", + RCAuthUnavailable: "authValue or authPolicy is not available for selected entity", + RCReboot: "a _TPM_Init and Startup(CLEAR) is required before the TPM can resume operation", + RCUnbalanced: "the protection algorithms (hash and symmetric) are not reasonably balanced; the digest size of the hash must be larger than the key size of the symmetric algorithm", + RCCommandSize: "command commandSize value is inconsistent with contents of the command buffer; either the size is not the same as the octets loaded by the hardware interface layer or the value is not large enough to hold a command header", + RCCommandCode: "command code not supported", + RCAuthSize: "the value of authorizationSize is out of range or the number of octets in the Authorization Area is greater than required", + RCAuthContext: "use of an authorization session with a context command or another command that cannot have an authorization session", + RCNVRange: "NV offset+size is out of range", + RCNVSize: "Requested allocation size is larger than allowed", + RCNVLocked: "NV access locked", + RCNVAuthorization: "NV access authorization fails in command actions", + RCNVUninitialized: "an NV Index is used before being initialized or the state saved by TPM2_Shutdown(STATE) could not be restored", + RCNVSpace: "insufficient space for NV allocation", + RCNVDefined: "NV Index or persistent object already defined", + RCBadContext: "context in TPM2_ContextLoad() is not valid", + RCCPHash: "cpHash value already set or not correct for use", + RCParent: "handle for parent is not a valid parent", + RCNeedsTest: "some function needs testing", + RCNoResult: "returned when an internal function cannot process a request due to an unspecified problem; this code is usually related to invalid parameters that are not properly filtered by the input unmarshaling code", + RCSensitive: "the sensitive area did not unmarshal correctly after decryption", +} + +// Format 1 error codes. +const ( + RCAsymmetric = 0x01 + RCAttributes = 0x02 + RCHash = 0x03 + RCValue = 0x04 + RCHierarchy = 0x05 + RCKeySize = 0x07 + RCMGF = 0x08 + RCMode = 0x09 + RCType = 0x0A + RCHandle = 0x0B + RCKDF = 0x0C + RCRange = 0x0D + RCAuthFail = 0x0E + RCNonce = 0x0F + RCPP = 0x10 + RCScheme = 0x12 + RCSize = 0x15 + RCSymmetric = 0x16 + RCTag = 0x17 + RCSelector = 0x18 + RCInsufficient = 0x1A + RCSignature = 0x1B + RCKey = 0x1C + RCPolicyFail = 0x1D + RCIntegrity = 0x1F + RCTicket = 0x20 + RCReservedBits = 0x21 + RCBadAuth = 0x22 + RCExpired = 0x23 + RCPolicyCC = 0x24 + RCBinding = 0x25 + RCCurve = 0x26 + RCECCPoint = 0x27 +) + +var fmt1Msg = map[RCFmt1]string{ + RCAsymmetric: "asymmetric algorithm not supported or not correct", + RCAttributes: "inconsistent attributes", + RCHash: "hash algorithm not supported or not appropriate", + RCValue: "value is out of range or is not correct for the context", + RCHierarchy: "hierarchy is not enabled or is not correct for the use", + RCKeySize: "key size is not supported", + RCMGF: "mask generation function not supported", + RCMode: "mode of operation not supported", + RCType: "the type of the value is not appropriate for the use", + RCHandle: "the handle is not correct for the use", + RCKDF: "unsupported key derivation function or function not appropriate for use", + RCRange: "value was out of allowed range", + RCAuthFail: "the authorization HMAC check failed and DA counter incremented", + RCNonce: "invalid nonce size or nonce value mismatch", + RCPP: "authorization requires assertion of PP", + RCScheme: "unsupported or incompatible scheme", + RCSize: "structure is the wrong size", + RCSymmetric: "unsupported symmetric algorithm or key size, or not appropriate for instance", + RCTag: "incorrect structure tag", + RCSelector: "union selector is incorrect", + RCInsufficient: "the TPM was unable to unmarshal a value because there were not enough octets in the input buffer", + RCSignature: "the signature is not valid", + RCKey: "key fields are not compatible with the selected use", + RCPolicyFail: "a policy check failed", + RCIntegrity: "integrity check failed", + RCTicket: "invalid ticket", + RCReservedBits: "reserved bits not set to zero as required", + RCBadAuth: "authorization failure without DA implications", + RCExpired: "the policy has expired", + RCPolicyCC: "the commandCode in the policy is not the commandCode of the command or the command code in a policy command references a command that is not implemented", + RCBinding: "public and sensitive portions of an object are not cryptographically bound", + RCCurve: "curve not supported", + RCECCPoint: "point is not on the required curve", +} + +// Warning codes. +const ( + RCContextGap RCWarn = 0x01 + RCObjectMemory RCWarn = 0x02 + RCSessionMemory RCWarn = 0x03 + RCMemory RCWarn = 0x04 + RCSessionHandles RCWarn = 0x05 + RCObjectHandles RCWarn = 0x06 + RCLocality RCWarn = 0x07 + RCYielded RCWarn = 0x08 + RCCanceled RCWarn = 0x09 + RCTesting RCWarn = 0x0A + RCReferenceH0 RCWarn = 0x10 + RCReferenceH1 RCWarn = 0x11 + RCReferenceH2 RCWarn = 0x12 + RCReferenceH3 RCWarn = 0x13 + RCReferenceH4 RCWarn = 0x14 + RCReferenceH5 RCWarn = 0x15 + RCReferenceH6 RCWarn = 0x16 + RCReferenceS0 RCWarn = 0x18 + RCReferenceS1 RCWarn = 0x19 + RCReferenceS2 RCWarn = 0x1A + RCReferenceS3 RCWarn = 0x1B + RCReferenceS4 RCWarn = 0x1C + RCReferenceS5 RCWarn = 0x1D + RCReferenceS6 RCWarn = 0x1E + RCNVRate RCWarn = 0x20 + RCLockout RCWarn = 0x21 + RCRetry RCWarn = 0x22 + RCNVUnavailable RCWarn = 0x23 +) + +var warnMsg = map[RCWarn]string{ + RCContextGap: "gap for context ID is too large", + RCObjectMemory: "out of memory for object contexts", + RCSessionMemory: "out of memory for session contexts", + RCMemory: "out of shared object/session memory or need space for internal operations", + RCSessionHandles: "out of session handles", + RCObjectHandles: "out of object handles", + RCLocality: "bad locality", + RCYielded: "the TPM has suspended operation on the command; forward progress was made and the command may be retried", + RCCanceled: "the command was canceled", + RCTesting: "TPM is performing self-tests", + RCReferenceH0: "the 1st handle in the handle area references a transient object or session that is not loaded", + RCReferenceH1: "the 2nd handle in the handle area references a transient object or session that is not loaded", + RCReferenceH2: "the 3rd handle in the handle area references a transient object or session that is not loaded", + RCReferenceH3: "the 4th handle in the handle area references a transient object or session that is not loaded", + RCReferenceH4: "the 5th handle in the handle area references a transient object or session that is not loaded", + RCReferenceH5: "the 6th handle in the handle area references a transient object or session that is not loaded", + RCReferenceH6: "the 7th handle in the handle area references a transient object or session that is not loaded", + RCReferenceS0: "the 1st authorization session handle references a session that is not loaded", + RCReferenceS1: "the 2nd authorization session handle references a session that is not loaded", + RCReferenceS2: "the 3rd authorization session handle references a session that is not loaded", + RCReferenceS3: "the 4th authorization session handle references a session that is not loaded", + RCReferenceS4: "the 5th authorization session handle references a session that is not loaded", + RCReferenceS5: "the 6th authorization session handle references a session that is not loaded", + RCReferenceS6: "the 7th authorization session handle references a session that is not loaded", + RCNVRate: "the TPM is rate-limiting accesses to prevent wearout of NV", + RCLockout: "authorizations for objects subject to DA protection are not allowed at this time because the TPM is in DA lockout mode", + RCRetry: "the TPM was not able to start the command", + RCNVUnavailable: "the command may require writing of NV and NV is not current accessible", +} + +// Indexes for arguments, handles and sessions. +const ( + RC1 RCIndex = iota + 1 + RC2 + RC3 + RC4 + RC5 + RC6 + RC7 + RC8 + RC9 + RCA + RCB + RCC + RCD + RCE + RCF +) + +const unknownCode = "unknown error code" + +// Error is returned for all Format 0 errors from the TPM. It is used for general +// errors not specific to a parameter, handle or session. +type Error struct { + Code RCFmt0 +} + +func (e Error) Error() string { + msg := fmt0Msg[e.Code] + if msg == "" { + msg = unknownCode + } + return fmt.Sprintf("error code 0x%x : %s", e.Code, msg) +} + +// VendorError represents a vendor-specific error response. These types of responses +// are not decoded and Code contains the complete response code. +type VendorError struct { + Code uint32 +} + +func (e VendorError) Error() string { + return fmt.Sprintf("vendor error code 0x%x", e.Code) +} + +// Warning is typically used to report transient errors. +type Warning struct { + Code RCWarn +} + +func (w Warning) Error() string { + msg := warnMsg[w.Code] + if msg == "" { + msg = unknownCode + } + return fmt.Sprintf("warning code 0x%x : %s", w.Code, msg) +} + +// ParameterError describes an error related to a parameter, and the parameter number. +type ParameterError struct { + Code RCFmt1 + Parameter RCIndex +} + +func (e ParameterError) Error() string { + msg := fmt1Msg[e.Code] + if msg == "" { + msg = unknownCode + } + return fmt.Sprintf("parameter %d, error code 0x%x : %s", e.Parameter, e.Code, msg) +} + +// HandleError describes an error related to a handle, and the handle number. +type HandleError struct { + Code RCFmt1 + Handle RCIndex +} + +func (e HandleError) Error() string { + msg := fmt1Msg[e.Code] + if msg == "" { + msg = unknownCode + } + return fmt.Sprintf("handle %d, error code 0x%x : %s", e.Handle, e.Code, msg) +} + +// SessionError describes an error related to a session, and the session number. +type SessionError struct { + Code RCFmt1 + Session RCIndex +} + +func (e SessionError) Error() string { + msg := fmt1Msg[e.Code] + if msg == "" { + msg = unknownCode + } + return fmt.Sprintf("session %d, error code 0x%x : %s", e.Session, e.Code, msg) +} + +// Decode a TPM2 response code and return the appropriate error. Logic +// according to the "Response Code Evaluation" chart in Part 1 of the TPM 2.0 +// spec. +func decodeResponse(code tpmutil.ResponseCode) error { + if code == tpmutil.RCSuccess { + return nil + } + if code&0x180 == 0 { // Bits 7:8 == 0 is a TPM1 error + return fmt.Errorf("response status 0x%x", code) + } + if code&0x80 == 0 { // Bit 7 unset + if code&0x400 > 0 { // Bit 10 set, vendor specific code + return VendorError{uint32(code)} + } + if code&0x800 > 0 { // Bit 11 set, warning with code in bit 0:6 + return Warning{RCWarn(code & 0x7f)} + } + // error with code in bit 0:6 + return Error{RCFmt0(code & 0x7f)} + } + if code&0x40 > 0 { // Bit 6 set, code in 0:5, parameter number in 8:11 + return ParameterError{RCFmt1(code & 0x3f), RCIndex((code & 0xf00) >> 8)} + } + if code&0x800 == 0 { // Bit 11 unset, code in 0:5, handle in 8:10 + return HandleError{RCFmt1(code & 0x3f), RCIndex((code & 0x700) >> 8)} + } + // Code in 0:5, Session in 8:10 + return SessionError{RCFmt1(code & 0x3f), RCIndex((code & 0x700) >> 8)} +} diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/kdf.go b/vendor/github.com/google/go-tpm/legacy/tpm2/kdf.go new file mode 100644 index 0000000..3a22e8b --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/kdf.go @@ -0,0 +1,116 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpm2 + +import ( + "crypto" + "crypto/hmac" + "encoding/binary" + "hash" +) + +// KDFa implements TPM 2.0's default key derivation function, as defined in +// section 11.4.9.2 of the TPM revision 2 specification part 1. +// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/ +// The key & label parameters must not be zero length. +// The label parameter is a non-null-terminated string. +// The contextU & contextV parameters are optional. +// Deprecated: Use KDFaHash. +func KDFa(hashAlg Algorithm, key []byte, label string, contextU, contextV []byte, bits int) ([]byte, error) { + h, err := hashAlg.Hash() + if err != nil { + return nil, err + } + return KDFaHash(h, key, label, contextU, contextV, bits), nil +} + +// KDFe implements TPM 2.0's ECDH key derivation function, as defined in +// section 11.4.9.3 of the TPM revision 2 specification part 1. +// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/ +// The z parameter is the x coordinate of one party's private ECC key multiplied +// by the other party's public ECC point. +// The use parameter is a non-null-terminated string. +// The partyUInfo and partyVInfo are the x coordinates of the initiator's and +// Deprecated: Use KDFeHash. +func KDFe(hashAlg Algorithm, z []byte, use string, partyUInfo, partyVInfo []byte, bits int) ([]byte, error) { + h, err := hashAlg.Hash() + if err != nil { + return nil, err + } + return KDFeHash(h, z, use, partyUInfo, partyVInfo, bits), nil +} + +// KDFaHash implements TPM 2.0's default key derivation function, as defined in +// section 11.4.9.2 of the TPM revision 2 specification part 1. +// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/ +// The key & label parameters must not be zero length. +// The label parameter is a non-null-terminated string. +// The contextU & contextV parameters are optional. +func KDFaHash(h crypto.Hash, key []byte, label string, contextU, contextV []byte, bits int) []byte { + mac := hmac.New(h.New, key) + + out := kdf(mac, bits, func() { + mac.Write([]byte(label)) + mac.Write([]byte{0}) // Terminating null character for C-string. + mac.Write(contextU) + mac.Write(contextV) + binary.Write(mac, binary.BigEndian, uint32(bits)) + }) + return out +} + +// KDFeHash implements TPM 2.0's ECDH key derivation function, as defined in +// section 11.4.9.3 of the TPM revision 2 specification part 1. +// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/ +// The z parameter is the x coordinate of one party's private ECC key multiplied +// by the other party's public ECC point. +// The use parameter is a non-null-terminated string. +// The partyUInfo and partyVInfo are the x coordinates of the initiator's and +// the responder's ECC points, respectively. +func KDFeHash(h crypto.Hash, z []byte, use string, partyUInfo, partyVInfo []byte, bits int) []byte { + hash := h.New() + + out := kdf(hash, bits, func() { + hash.Write(z) + hash.Write([]byte(use)) + hash.Write([]byte{0}) // Terminating null character for C-string. + hash.Write(partyUInfo) + hash.Write(partyVInfo) + }) + return out +} + +func kdf(h hash.Hash, bits int, update func()) []byte { + bytes := (bits + 7) / 8 + out := []byte{} + + for counter := 1; len(out) < bytes; counter++ { + h.Reset() + binary.Write(h, binary.BigEndian, uint32(counter)) + update() + + out = h.Sum(out) + } + // out's length is a multiple of hash size, so there will be excess + // bytes if bytes isn't a multiple of hash size. + out = out[:bytes] + + // As mentioned in the KDFa and KDFe specs mentioned above, + // the unused bits of the most significant octet are masked off. + if maskBits := uint8(bits % 8); maskBits > 0 { + out[0] &= (1 << maskBits) - 1 + } + return out +} diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/open_other.go b/vendor/github.com/google/go-tpm/legacy/tpm2/open_other.go new file mode 100644 index 0000000..7d6d9a3 --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/open_other.go @@ -0,0 +1,57 @@ +//go:build !windows + +// Copyright (c) 2019, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpm2 + +import ( + "errors" + "fmt" + "io" + "os" + + "github.com/google/go-tpm/tpmutil" +) + +// OpenTPM opens a channel to the TPM at the given path. If the file is a +// device, then it treats it like a normal TPM device, and if the file is a +// Unix domain socket, then it opens a connection to the socket. +// +// This function may also be invoked with no paths, as tpm2.OpenTPM(). In this +// case, the default paths on Linux (/dev/tpmrm0 then /dev/tpm0), will be used. +func OpenTPM(path ...string) (tpm io.ReadWriteCloser, err error) { + switch len(path) { + case 0: + tpm, err = tpmutil.OpenTPM("/dev/tpmrm0") + if errors.Is(err, os.ErrNotExist) { + tpm, err = tpmutil.OpenTPM("/dev/tpm0") + } + case 1: + tpm, err = tpmutil.OpenTPM(path[0]) + default: + return nil, errors.New("cannot specify multiple paths to tpm2.OpenTPM") + } + if err != nil { + return nil, err + } + + // Make sure this is a TPM 2.0 + _, err = GetManufacturer(tpm) + if err != nil { + tpm.Close() + return nil, fmt.Errorf("open %s: device is not a TPM 2.0", path) + } + return tpm, nil +} diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/open_windows.go b/vendor/github.com/google/go-tpm/legacy/tpm2/open_windows.go new file mode 100644 index 0000000..ad37a60 --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/open_windows.go @@ -0,0 +1,39 @@ +//go:build windows + +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpm2 + +import ( + "fmt" + "io" + + "github.com/google/go-tpm/tpmutil" + "github.com/google/go-tpm/tpmutil/tbs" +) + +// OpenTPM opens a channel to the TPM. +func OpenTPM() (io.ReadWriteCloser, error) { + info, err := tbs.GetDeviceInfo() + if err != nil { + return nil, err + } + + if info.TPMVersion != tbs.TPMVersion20 { + return nil, fmt.Errorf("openTPM: device is not a TPM 2.0") + } + + return tpmutil.OpenTPM() +} diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/structures.go b/vendor/github.com/google/go-tpm/legacy/tpm2/structures.go new file mode 100644 index 0000000..6df9f7f --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/structures.go @@ -0,0 +1,1112 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpm2 + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/rsa" + "encoding/binary" + "errors" + "fmt" + "math/big" + "reflect" + + "github.com/google/go-tpm/tpmutil" +) + +// NVPublic contains the public area of an NV index. +type NVPublic struct { + NVIndex tpmutil.Handle + NameAlg Algorithm + Attributes NVAttr + AuthPolicy tpmutil.U16Bytes + DataSize uint16 +} + +type tpmsSensitiveCreate struct { + UserAuth tpmutil.U16Bytes + Data tpmutil.U16Bytes +} + +// PCRSelection contains a slice of PCR indexes and a hash algorithm used in +// them. +type PCRSelection struct { + Hash Algorithm + PCRs []int +} + +type tpmsPCRSelection struct { + Hash Algorithm + Size byte + PCRs tpmutil.RawBytes +} + +// Public contains the public area of an object. +type Public struct { + Type Algorithm + NameAlg Algorithm + Attributes KeyProp + AuthPolicy tpmutil.U16Bytes + + // Exactly one of the following fields should be set + // When encoding/decoding, one will be picked based on Type. + + // RSAParameters contains both [rsa]parameters and [rsa]unique. + RSAParameters *RSAParams + // ECCParameters contains both [ecc]parameters and [ecc]unique. + ECCParameters *ECCParams + // SymCipherParameters contains both [sym]parameters and [sym]unique. + SymCipherParameters *SymCipherParams + // KeyedHashParameters contains both [keyedHash]parameters and [keyedHash]unique. + KeyedHashParameters *KeyedHashParams +} + +// Encode serializes a Public structure in TPM wire format. +func (p Public) Encode() ([]byte, error) { + head, err := tpmutil.Pack(p.Type, p.NameAlg, p.Attributes, p.AuthPolicy) + if err != nil { + return nil, fmt.Errorf("encoding Type, NameAlg, Attributes, AuthPolicy: %v", err) + } + var params []byte + switch p.Type { + case AlgRSA: + params, err = p.RSAParameters.encode() + case AlgKeyedHash: + params, err = p.KeyedHashParameters.encode() + case AlgECC: + params, err = p.ECCParameters.encode() + case AlgSymCipher: + params, err = p.SymCipherParameters.encode() + default: + err = fmt.Errorf("unsupported type in TPMT_PUBLIC: 0x%x", p.Type) + } + if err != nil { + return nil, fmt.Errorf("encoding RSAParameters, ECCParameters, SymCipherParameters or KeyedHash: %v", err) + } + return concat(head, params) +} + +// Key returns the (public) key from the public area of an object. +func (p Public) Key() (crypto.PublicKey, error) { + var pubKey crypto.PublicKey + switch p.Type { + case AlgRSA: + // Endianness of big.Int.Bytes/SetBytes and modulus in the TPM is the same + // (big-endian). + pubKey = &rsa.PublicKey{N: p.RSAParameters.Modulus(), E: int(p.RSAParameters.Exponent())} + case AlgECC: + curve, ok := toGoCurve[p.ECCParameters.CurveID] + if !ok { + return nil, fmt.Errorf("can't map TPM EC curve ID 0x%x to Go elliptic.Curve value", p.ECCParameters.CurveID) + } + pubKey = &ecdsa.PublicKey{ + X: p.ECCParameters.Point.X(), + Y: p.ECCParameters.Point.Y(), + Curve: curve, + } + default: + return nil, fmt.Errorf("unsupported public key type 0x%x", p.Type) + } + return pubKey, nil +} + +// Name computes the Digest-based Name from the public area of an object. +func (p Public) Name() (Name, error) { + pubEncoded, err := p.Encode() + if err != nil { + return Name{}, err + } + hash, err := p.NameAlg.Hash() + if err != nil { + return Name{}, err + } + nameHash := hash.New() + nameHash.Write(pubEncoded) + return Name{ + Digest: &HashValue{ + Alg: p.NameAlg, + Value: nameHash.Sum(nil), + }, + }, nil +} + +// MatchesTemplate checks if the Public area has the same algorithms and +// parameters as the provided template. Note that this does not necessarily +// mean that the key was created from this template, as the Unique field is +// both provided in the template and overridden in the key creation process. +func (p Public) MatchesTemplate(template Public) bool { + if p.Type != template.Type || + p.NameAlg != template.NameAlg || + p.Attributes != template.Attributes || + !bytes.Equal(p.AuthPolicy, template.AuthPolicy) { + return false + } + switch p.Type { + case AlgRSA: + return p.RSAParameters.matchesTemplate(template.RSAParameters) + case AlgECC: + return p.ECCParameters.matchesTemplate(template.ECCParameters) + case AlgSymCipher: + return p.SymCipherParameters.matchesTemplate(template.SymCipherParameters) + case AlgKeyedHash: + return p.KeyedHashParameters.matchesTemplate(template.KeyedHashParameters) + default: + return true + } +} + +// DecodePublic decodes a TPMT_PUBLIC message. No error is returned if +// the input has extra trailing data. +func DecodePublic(buf []byte) (Public, error) { + in := bytes.NewBuffer(buf) + var pub Public + var err error + if err = tpmutil.UnpackBuf(in, &pub.Type, &pub.NameAlg, &pub.Attributes, &pub.AuthPolicy); err != nil { + return pub, fmt.Errorf("decoding TPMT_PUBLIC: %v", err) + } + + switch pub.Type { + case AlgRSA: + pub.RSAParameters, err = decodeRSAParams(in) + case AlgECC: + pub.ECCParameters, err = decodeECCParams(in) + case AlgSymCipher: + pub.SymCipherParameters, err = decodeSymCipherParams(in) + case AlgKeyedHash: + pub.KeyedHashParameters, err = decodeKeyedHashParams(in) + default: + err = fmt.Errorf("unsupported type in TPMT_PUBLIC: 0x%x", pub.Type) + } + return pub, err +} + +// RSAParams represents parameters of an RSA key pair: +// both the TPMS_RSA_PARMS and the TPM2B_PUBLIC_KEY_RSA. +// +// Symmetric and Sign may be nil, depending on key Attributes in Public. +// +// ExponentRaw and ModulusRaw are the actual data encoded in the template, which +// is useful for templates that differ in zero-padding, for example. +type RSAParams struct { + Symmetric *SymScheme + Sign *SigScheme + KeyBits uint16 + ExponentRaw uint32 + ModulusRaw tpmutil.U16Bytes +} + +// Exponent returns the RSA exponent value represented by ExponentRaw, handling +// the fact that an exponent of 0 represents a value of 65537 (2^16 + 1). +func (p *RSAParams) Exponent() uint32 { + if p.ExponentRaw == 0 { + return defaultRSAExponent + } + return p.ExponentRaw +} + +// Modulus returns the RSA modulus value represented by ModulusRaw, handling the +// fact that the same modulus value can have multiple different representations. +func (p *RSAParams) Modulus() *big.Int { + return new(big.Int).SetBytes(p.ModulusRaw) +} + +func (p *RSAParams) matchesTemplate(t *RSAParams) bool { + return reflect.DeepEqual(p.Symmetric, t.Symmetric) && + reflect.DeepEqual(p.Sign, t.Sign) && + p.KeyBits == t.KeyBits && p.ExponentRaw == t.ExponentRaw +} + +func (p *RSAParams) encode() ([]byte, error) { + if p == nil { + return nil, nil + } + sym, err := p.Symmetric.encode() + if err != nil { + return nil, fmt.Errorf("encoding Symmetric: %v", err) + } + sig, err := p.Sign.encode() + if err != nil { + return nil, fmt.Errorf("encoding Sign: %v", err) + } + rest, err := tpmutil.Pack(p.KeyBits, p.ExponentRaw, p.ModulusRaw) + if err != nil { + return nil, fmt.Errorf("encoding KeyBits, Exponent, Modulus: %v", err) + } + return concat(sym, sig, rest) +} + +func decodeRSAParams(in *bytes.Buffer) (*RSAParams, error) { + var params RSAParams + var err error + + if params.Symmetric, err = decodeSymScheme(in); err != nil { + return nil, fmt.Errorf("decoding Symmetric: %v", err) + } + if params.Sign, err = decodeSigScheme(in); err != nil { + return nil, fmt.Errorf("decoding Sign: %v", err) + } + if err := tpmutil.UnpackBuf(in, ¶ms.KeyBits, ¶ms.ExponentRaw, ¶ms.ModulusRaw); err != nil { + return nil, fmt.Errorf("decoding KeyBits, Exponent, Modulus: %v", err) + } + return ¶ms, nil +} + +// ECCParams represents parameters of an ECC key pair: +// both the TPMS_ECC_PARMS and the TPMS_ECC_POINT. +// +// Symmetric, Sign and KDF may be nil, depending on key Attributes in Public. +type ECCParams struct { + Symmetric *SymScheme + Sign *SigScheme + CurveID EllipticCurve + KDF *KDFScheme + Point ECPoint +} + +// ECPoint represents a ECC coordinates for a point using byte buffers. +type ECPoint struct { + XRaw, YRaw tpmutil.U16Bytes +} + +// X returns the X Point value reprsented by XRaw. +func (p ECPoint) X() *big.Int { + return new(big.Int).SetBytes(p.XRaw) +} + +// Y returns the Y Point value reprsented by YRaw. +func (p ECPoint) Y() *big.Int { + return new(big.Int).SetBytes(p.YRaw) +} + +func (p *ECCParams) matchesTemplate(t *ECCParams) bool { + return reflect.DeepEqual(p.Symmetric, t.Symmetric) && + reflect.DeepEqual(p.Sign, t.Sign) && + p.CurveID == t.CurveID && reflect.DeepEqual(p.KDF, t.KDF) +} + +func (p *ECCParams) encode() ([]byte, error) { + if p == nil { + return nil, nil + } + sym, err := p.Symmetric.encode() + if err != nil { + return nil, fmt.Errorf("encoding Symmetric: %v", err) + } + sig, err := p.Sign.encode() + if err != nil { + return nil, fmt.Errorf("encoding Sign: %v", err) + } + curve, err := tpmutil.Pack(p.CurveID) + if err != nil { + return nil, fmt.Errorf("encoding CurveID: %v", err) + } + kdf, err := p.KDF.encode() + if err != nil { + return nil, fmt.Errorf("encoding KDF: %v", err) + } + point, err := tpmutil.Pack(p.Point.XRaw, p.Point.YRaw) + if err != nil { + return nil, fmt.Errorf("encoding Point: %v", err) + } + return concat(sym, sig, curve, kdf, point) +} + +func decodeECCParams(in *bytes.Buffer) (*ECCParams, error) { + var params ECCParams + var err error + + if params.Symmetric, err = decodeSymScheme(in); err != nil { + return nil, fmt.Errorf("decoding Symmetric: %v", err) + } + if params.Sign, err = decodeSigScheme(in); err != nil { + return nil, fmt.Errorf("decoding Sign: %v", err) + } + if err := tpmutil.UnpackBuf(in, ¶ms.CurveID); err != nil { + return nil, fmt.Errorf("decoding CurveID: %v", err) + } + if params.KDF, err = decodeKDFScheme(in); err != nil { + return nil, fmt.Errorf("decoding KDF: %v", err) + } + if err := tpmutil.UnpackBuf(in, ¶ms.Point.XRaw, ¶ms.Point.YRaw); err != nil { + return nil, fmt.Errorf("decoding Point: %v", err) + } + return ¶ms, nil +} + +// SymCipherParams represents parameters of a symmetric block cipher TPM object: +// both the TPMS_SYMCIPHER_PARMS and the TPM2B_DIGEST (hash of the key). +type SymCipherParams struct { + Symmetric *SymScheme + Unique tpmutil.U16Bytes +} + +func (p *SymCipherParams) matchesTemplate(t *SymCipherParams) bool { + return reflect.DeepEqual(p.Symmetric, t.Symmetric) +} + +func (p *SymCipherParams) encode() ([]byte, error) { + sym, err := p.Symmetric.encode() + if err != nil { + return nil, fmt.Errorf("encoding Symmetric: %v", err) + } + unique, err := tpmutil.Pack(p.Unique) + if err != nil { + return nil, fmt.Errorf("encoding Unique: %v", err) + } + return concat(sym, unique) +} + +func decodeSymCipherParams(in *bytes.Buffer) (*SymCipherParams, error) { + var params SymCipherParams + var err error + + if params.Symmetric, err = decodeSymScheme(in); err != nil { + return nil, fmt.Errorf("decoding Symmetric: %v", err) + } + if err := tpmutil.UnpackBuf(in, ¶ms.Unique); err != nil { + return nil, fmt.Errorf("decoding Unique: %v", err) + } + return ¶ms, nil +} + +// KeyedHashParams represents parameters of a keyed hash TPM object: +// both the TPMS_KEYEDHASH_PARMS and the TPM2B_DIGEST (hash of the key). +type KeyedHashParams struct { + Alg Algorithm + Hash Algorithm + KDF Algorithm + Unique tpmutil.U16Bytes +} + +func (p *KeyedHashParams) matchesTemplate(t *KeyedHashParams) bool { + if p.Alg != t.Alg { + return false + } + switch p.Alg { + case AlgHMAC: + return p.Hash == t.Hash + case AlgXOR: + return p.Hash == t.Hash && p.KDF == t.KDF + default: + return true + } +} + +func (p *KeyedHashParams) encode() ([]byte, error) { + if p == nil { + return tpmutil.Pack(AlgNull, tpmutil.U16Bytes(nil)) + } + var params []byte + var err error + switch p.Alg { + case AlgNull: + params, err = tpmutil.Pack(p.Alg) + case AlgHMAC: + params, err = tpmutil.Pack(p.Alg, p.Hash) + case AlgXOR: + params, err = tpmutil.Pack(p.Alg, p.Hash, p.KDF) + default: + err = fmt.Errorf("unsupported KeyedHash Algorithm: 0x%x", p.Alg) + } + if err != nil { + return nil, fmt.Errorf("encoding Alg Params: %v", err) + } + unique, err := tpmutil.Pack(p.Unique) + if err != nil { + return nil, fmt.Errorf("encoding Unique: %v", err) + } + return concat(params, unique) +} + +func decodeKeyedHashParams(in *bytes.Buffer) (*KeyedHashParams, error) { + var p KeyedHashParams + var err error + if err = tpmutil.UnpackBuf(in, &p.Alg); err != nil { + return nil, fmt.Errorf("decoding Alg: %v", err) + } + switch p.Alg { + case AlgNull: + err = nil + case AlgHMAC: + err = tpmutil.UnpackBuf(in, &p.Hash) + case AlgXOR: + err = tpmutil.UnpackBuf(in, &p.Hash, &p.KDF) + default: + err = fmt.Errorf("unsupported KeyedHash Algorithm: 0x%x", p.Alg) + } + if err != nil { + return nil, fmt.Errorf("decoding Alg Params: %v", err) + } + if err = tpmutil.UnpackBuf(in, &p.Unique); err != nil { + return nil, fmt.Errorf("decoding Unique: %v", err) + } + return &p, nil +} + +// SymScheme represents a symmetric encryption scheme. +// Known in the specification by TPMT_SYM_DEF_OBJECT. +type SymScheme struct { + Alg Algorithm + KeyBits uint16 + Mode Algorithm +} + +func (s *SymScheme) encode() ([]byte, error) { + if s == nil || s.Alg.IsNull() { + return tpmutil.Pack(AlgNull) + } + return tpmutil.Pack(s.Alg, s.KeyBits, s.Mode) +} + +func decodeSymScheme(in *bytes.Buffer) (*SymScheme, error) { + var scheme SymScheme + if err := tpmutil.UnpackBuf(in, &scheme.Alg); err != nil { + return nil, fmt.Errorf("decoding Alg: %v", err) + } + if scheme.Alg == AlgNull { + return nil, nil + } + if err := tpmutil.UnpackBuf(in, &scheme.KeyBits, &scheme.Mode); err != nil { + return nil, fmt.Errorf("decoding KeyBits, Mode: %v", err) + } + return &scheme, nil +} + +// AsymScheme represents am asymmetric encryption scheme. +type AsymScheme struct { + Alg Algorithm + Hash Algorithm +} + +func (s *AsymScheme) encode() ([]byte, error) { + if s == nil || s.Alg.IsNull() { + return tpmutil.Pack(AlgNull) + } + if s.Alg.UsesHash() { + return tpmutil.Pack(s.Alg, s.Hash) + } + return tpmutil.Pack(s.Alg) +} + +// SigScheme represents a signing scheme. +type SigScheme struct { + Alg Algorithm + Hash Algorithm + Count uint32 +} + +func (s *SigScheme) encode() ([]byte, error) { + if s == nil || s.Alg.IsNull() { + return tpmutil.Pack(AlgNull) + } + if s.Alg.UsesCount() { + return tpmutil.Pack(s.Alg, s.Hash, s.Count) + } + return tpmutil.Pack(s.Alg, s.Hash) +} + +func decodeSigScheme(in *bytes.Buffer) (*SigScheme, error) { + var scheme SigScheme + if err := tpmutil.UnpackBuf(in, &scheme.Alg); err != nil { + return nil, fmt.Errorf("decoding Alg: %v", err) + } + if scheme.Alg == AlgNull { + return nil, nil + } + if err := tpmutil.UnpackBuf(in, &scheme.Hash); err != nil { + return nil, fmt.Errorf("decoding Hash: %v", err) + } + if scheme.Alg.UsesCount() { + if err := tpmutil.UnpackBuf(in, &scheme.Count); err != nil { + return nil, fmt.Errorf("decoding Count: %v", err) + } + } + return &scheme, nil +} + +// KDFScheme represents a KDF (Key Derivation Function) scheme. +type KDFScheme struct { + Alg Algorithm + Hash Algorithm +} + +func (s *KDFScheme) encode() ([]byte, error) { + if s == nil || s.Alg.IsNull() { + return tpmutil.Pack(AlgNull) + } + return tpmutil.Pack(s.Alg, s.Hash) +} + +func decodeKDFScheme(in *bytes.Buffer) (*KDFScheme, error) { + var scheme KDFScheme + if err := tpmutil.UnpackBuf(in, &scheme.Alg); err != nil { + return nil, fmt.Errorf("decoding Alg: %v", err) + } + if scheme.Alg == AlgNull { + return nil, nil + } + if err := tpmutil.UnpackBuf(in, &scheme.Hash); err != nil { + return nil, fmt.Errorf("decoding Hash: %v", err) + } + return &scheme, nil +} + +// Signature combines all possible signatures from RSA and ECC keys. Only one +// of RSA or ECC will be populated. +type Signature struct { + Alg Algorithm + RSA *SignatureRSA + ECC *SignatureECC +} + +// Encode serializes a Signature structure in TPM wire format. +func (s Signature) Encode() ([]byte, error) { + head, err := tpmutil.Pack(s.Alg) + if err != nil { + return nil, fmt.Errorf("encoding Alg: %v", err) + } + var signature []byte + switch s.Alg { + case AlgRSASSA, AlgRSAPSS: + if signature, err = tpmutil.Pack(s.RSA); err != nil { + return nil, fmt.Errorf("encoding RSA: %v", err) + } + case AlgECDSA: + signature, err = tpmutil.Pack(s.ECC.HashAlg, tpmutil.U16Bytes(s.ECC.R.Bytes()), tpmutil.U16Bytes(s.ECC.S.Bytes())) + if err != nil { + return nil, fmt.Errorf("encoding ECC: %v", err) + } + } + return concat(head, signature) +} + +// DecodeSignature decodes a serialized TPMT_SIGNATURE structure. +func DecodeSignature(in *bytes.Buffer) (*Signature, error) { + var sig Signature + if err := tpmutil.UnpackBuf(in, &sig.Alg); err != nil { + return nil, fmt.Errorf("decoding Alg: %v", err) + } + switch sig.Alg { + case AlgRSASSA, AlgRSAPSS: + sig.RSA = new(SignatureRSA) + if err := tpmutil.UnpackBuf(in, sig.RSA); err != nil { + return nil, fmt.Errorf("decoding RSA: %v", err) + } + case AlgECDSA: + sig.ECC = new(SignatureECC) + var r, s tpmutil.U16Bytes + if err := tpmutil.UnpackBuf(in, &sig.ECC.HashAlg, &r, &s); err != nil { + return nil, fmt.Errorf("decoding ECC: %v", err) + } + sig.ECC.R = big.NewInt(0).SetBytes(r) + sig.ECC.S = big.NewInt(0).SetBytes(s) + default: + return nil, fmt.Errorf("unsupported signature algorithm 0x%x", sig.Alg) + } + return &sig, nil +} + +// SignatureRSA is an RSA-specific signature value. +type SignatureRSA struct { + HashAlg Algorithm + Signature tpmutil.U16Bytes +} + +// SignatureECC is an ECC-specific signature value. +type SignatureECC struct { + HashAlg Algorithm + R *big.Int + S *big.Int +} + +// Private contains private section of a TPM key. +type Private struct { + Type Algorithm + AuthValue tpmutil.U16Bytes + SeedValue tpmutil.U16Bytes + Sensitive tpmutil.U16Bytes +} + +// Encode serializes a Private structure in TPM wire format. +func (p Private) Encode() ([]byte, error) { + if p.Type.IsNull() { + return nil, nil + } + return tpmutil.Pack(p) +} + +// AttestationData contains data attested by TPM commands (like Certify). +type AttestationData struct { + Magic uint32 + Type tpmutil.Tag + QualifiedSigner Name + ExtraData tpmutil.U16Bytes + ClockInfo ClockInfo + FirmwareVersion uint64 + AttestedCertifyInfo *CertifyInfo + AttestedQuoteInfo *QuoteInfo + AttestedCreationInfo *CreationInfo +} + +// DecodeAttestationData decode a TPMS_ATTEST message. No error is returned if +// the input has extra trailing data. +func DecodeAttestationData(in []byte) (*AttestationData, error) { + buf := bytes.NewBuffer(in) + + var ad AttestationData + if err := tpmutil.UnpackBuf(buf, &ad.Magic, &ad.Type); err != nil { + return nil, fmt.Errorf("decoding Magic/Type: %v", err) + } + // All attestation structures have the magic prefix + // TPMS_GENERATED_VALUE to symbolize they were created by + // the TPM when signed with an AK. + if ad.Magic != 0xff544347 { + return nil, fmt.Errorf("incorrect magic value: %x", ad.Magic) + } + + n, err := DecodeName(buf) + if err != nil { + return nil, fmt.Errorf("decoding QualifiedSigner: %v", err) + } + ad.QualifiedSigner = *n + if err := tpmutil.UnpackBuf(buf, &ad.ExtraData, &ad.ClockInfo, &ad.FirmwareVersion); err != nil { + return nil, fmt.Errorf("decoding ExtraData/ClockInfo/FirmwareVersion: %v", err) + } + + // The spec specifies several other types of attestation data. We only need + // parsing of Certify & Creation attestation data for now. If you need + // support for other attestation types, add them here. + switch ad.Type { + case TagAttestCertify: + if ad.AttestedCertifyInfo, err = decodeCertifyInfo(buf); err != nil { + return nil, fmt.Errorf("decoding AttestedCertifyInfo: %v", err) + } + case TagAttestCreation: + if ad.AttestedCreationInfo, err = decodeCreationInfo(buf); err != nil { + return nil, fmt.Errorf("decoding AttestedCreationInfo: %v", err) + } + case TagAttestQuote: + if ad.AttestedQuoteInfo, err = decodeQuoteInfo(buf); err != nil { + return nil, fmt.Errorf("decoding AttestedQuoteInfo: %v", err) + } + default: + return nil, fmt.Errorf("only Quote, Certify & Creation attestation structures are supported, got type 0x%x", ad.Type) + } + + return &ad, nil +} + +// Encode serializes an AttestationData structure in TPM wire format. +func (ad AttestationData) Encode() ([]byte, error) { + head, err := tpmutil.Pack(ad.Magic, ad.Type) + if err != nil { + return nil, fmt.Errorf("encoding Magic, Type: %v", err) + } + signer, err := ad.QualifiedSigner.Encode() + if err != nil { + return nil, fmt.Errorf("encoding QualifiedSigner: %v", err) + } + tail, err := tpmutil.Pack(ad.ExtraData, ad.ClockInfo, ad.FirmwareVersion) + if err != nil { + return nil, fmt.Errorf("encoding ExtraData, ClockInfo, FirmwareVersion: %v", err) + } + + var info []byte + switch ad.Type { + case TagAttestCertify: + if info, err = ad.AttestedCertifyInfo.encode(); err != nil { + return nil, fmt.Errorf("encoding AttestedCertifyInfo: %v", err) + } + case TagAttestCreation: + if info, err = ad.AttestedCreationInfo.encode(); err != nil { + return nil, fmt.Errorf("encoding AttestedCreationInfo: %v", err) + } + case TagAttestQuote: + if info, err = ad.AttestedQuoteInfo.encode(); err != nil { + return nil, fmt.Errorf("encoding AttestedQuoteInfo: %v", err) + } + default: + return nil, fmt.Errorf("only Quote, Certify & Creation attestation structures are supported, got type 0x%x", ad.Type) + } + + return concat(head, signer, tail, info) +} + +// CreationInfo contains Creation-specific data for TPMS_ATTEST. +type CreationInfo struct { + Name Name + // Most TPM2B_Digest structures contain a TPMU_HA structure + // and get parsed to HashValue. This is never the case for the + // digest in TPMS_CREATION_INFO. + OpaqueDigest tpmutil.U16Bytes +} + +func decodeCreationInfo(in *bytes.Buffer) (*CreationInfo, error) { + var ci CreationInfo + + n, err := DecodeName(in) + if err != nil { + return nil, fmt.Errorf("decoding Name: %v", err) + } + ci.Name = *n + + if err := tpmutil.UnpackBuf(in, &ci.OpaqueDigest); err != nil { + return nil, fmt.Errorf("decoding Digest: %v", err) + } + + return &ci, nil +} + +func (ci CreationInfo) encode() ([]byte, error) { + n, err := ci.Name.Encode() + if err != nil { + return nil, fmt.Errorf("encoding Name: %v", err) + } + + d, err := tpmutil.Pack(ci.OpaqueDigest) + if err != nil { + return nil, fmt.Errorf("encoding Digest: %v", err) + } + + return concat(n, d) +} + +// CertifyInfo contains Certify-specific data for TPMS_ATTEST. +type CertifyInfo struct { + Name Name + QualifiedName Name +} + +func decodeCertifyInfo(in *bytes.Buffer) (*CertifyInfo, error) { + var ci CertifyInfo + + n, err := DecodeName(in) + if err != nil { + return nil, fmt.Errorf("decoding Name: %v", err) + } + ci.Name = *n + + n, err = DecodeName(in) + if err != nil { + return nil, fmt.Errorf("decoding QualifiedName: %v", err) + } + ci.QualifiedName = *n + + return &ci, nil +} + +func (ci CertifyInfo) encode() ([]byte, error) { + n, err := ci.Name.Encode() + if err != nil { + return nil, fmt.Errorf("encoding Name: %v", err) + } + qn, err := ci.QualifiedName.Encode() + if err != nil { + return nil, fmt.Errorf("encoding QualifiedName: %v", err) + } + return concat(n, qn) +} + +// QuoteInfo represents a TPMS_QUOTE_INFO structure. +type QuoteInfo struct { + PCRSelection PCRSelection + PCRDigest tpmutil.U16Bytes +} + +func decodeQuoteInfo(in *bytes.Buffer) (*QuoteInfo, error) { + var out QuoteInfo + sel, err := decodeOneTPMLPCRSelection(in) + if err != nil { + return nil, fmt.Errorf("decoding PCRSelection: %v", err) + } + out.PCRSelection = sel + + if err := tpmutil.UnpackBuf(in, &out.PCRDigest); err != nil { + return nil, fmt.Errorf("decoding PCRDigest: %v", err) + } + return &out, nil +} + +func (qi QuoteInfo) encode() ([]byte, error) { + sel, err := encodeTPMLPCRSelection(qi.PCRSelection) + if err != nil { + return nil, fmt.Errorf("encoding PCRSelection: %v", err) + } + + digest, err := tpmutil.Pack(qi.PCRDigest) + if err != nil { + return nil, fmt.Errorf("encoding PCRDigest: %v", err) + } + + return concat(sel, digest) +} + +// IDObject represents an encrypted credential bound to a TPM object. +type IDObject struct { + IntegrityHMAC tpmutil.U16Bytes + // EncIdentity is packed raw, as the bytes representing the size + // of the credential value are present within the encrypted blob. + EncIdentity tpmutil.RawBytes +} + +// CreationData describes the attributes and environment for an object created +// on the TPM. This structure encodes/decodes to/from TPMS_CREATION_DATA. +type CreationData struct { + PCRSelection PCRSelection + PCRDigest tpmutil.U16Bytes + Locality byte + ParentNameAlg Algorithm + ParentName Name + ParentQualifiedName Name + OutsideInfo tpmutil.U16Bytes +} + +// EncodeCreationData encodes byte array to TPMS_CREATION_DATA message. +func (cd *CreationData) EncodeCreationData() ([]byte, error) { + sel, err := encodeTPMLPCRSelection(cd.PCRSelection) + if err != nil { + return nil, fmt.Errorf("encoding PCRSelection: %v", err) + } + d, err := tpmutil.Pack(cd.PCRDigest, cd.Locality, cd.ParentNameAlg) + if err != nil { + return nil, fmt.Errorf("encoding PCRDigest, Locality, ParentNameAlg: %v", err) + } + pn, err := cd.ParentName.Encode() + if err != nil { + return nil, fmt.Errorf("encoding ParentName: %v", err) + } + pqn, err := cd.ParentQualifiedName.Encode() + if err != nil { + return nil, fmt.Errorf("encoding ParentQualifiedName: %v", err) + } + o, err := tpmutil.Pack(cd.OutsideInfo) + if err != nil { + return nil, fmt.Errorf("encoding OutsideInfo: %v", err) + } + return concat(sel, d, pn, pqn, o) +} + +// DecodeCreationData decodes a TPMS_CREATION_DATA message. No error is +// returned if the input has extra trailing data. +func DecodeCreationData(buf []byte) (*CreationData, error) { + in := bytes.NewBuffer(buf) + var out CreationData + + sel, err := decodeOneTPMLPCRSelection(in) + if err != nil { + return nil, fmt.Errorf("decodeOneTPMLPCRSelection returned error %v", err) + } + out.PCRSelection = sel + + if err := tpmutil.UnpackBuf(in, &out.PCRDigest, &out.Locality, &out.ParentNameAlg); err != nil { + return nil, fmt.Errorf("decoding PCRDigest, Locality, ParentNameAlg: %v", err) + } + + n, err := DecodeName(in) + if err != nil { + return nil, fmt.Errorf("decoding ParentName: %v", err) + } + out.ParentName = *n + if n, err = DecodeName(in); err != nil { + return nil, fmt.Errorf("decoding ParentQualifiedName: %v", err) + } + out.ParentQualifiedName = *n + + if err := tpmutil.UnpackBuf(in, &out.OutsideInfo); err != nil { + return nil, fmt.Errorf("decoding OutsideInfo: %v", err) + } + + return &out, nil +} + +// Name represents a TPM2B_NAME, a name for TPM entities. Only one of +// Handle or Digest should be set. +type Name struct { + Handle *tpmutil.Handle + Digest *HashValue +} + +// DecodeName deserializes a Name hash from the TPM wire format. +func DecodeName(in *bytes.Buffer) (*Name, error) { + var nameBuf tpmutil.U16Bytes + if err := tpmutil.UnpackBuf(in, &nameBuf); err != nil { + return nil, err + } + + name := new(Name) + switch len(nameBuf) { + case 0: + // No name is present. + case 4: + name.Handle = new(tpmutil.Handle) + if err := tpmutil.UnpackBuf(bytes.NewBuffer(nameBuf), name.Handle); err != nil { + return nil, fmt.Errorf("decoding Handle: %v", err) + } + default: + var err error + name.Digest, err = decodeHashValue(bytes.NewBuffer(nameBuf)) + if err != nil { + return nil, fmt.Errorf("decoding Digest: %v", err) + } + } + return name, nil +} + +// Encode serializes a Name hash into the TPM wire format. +func (n Name) Encode() ([]byte, error) { + var buf []byte + var err error + switch { + case n.Handle != nil: + if buf, err = tpmutil.Pack(*n.Handle); err != nil { + return nil, fmt.Errorf("encoding Handle: %v", err) + } + case n.Digest != nil: + if buf, err = n.Digest.Encode(); err != nil { + return nil, fmt.Errorf("encoding Digest: %v", err) + } + default: + // Name is empty, which is valid. + } + return tpmutil.Pack(tpmutil.U16Bytes(buf)) +} + +// MatchesPublic compares Digest in Name against given Public structure. Note: +// this only works for regular Names, not Qualified Names. +func (n Name) MatchesPublic(p Public) (bool, error) { + if n.Digest == nil { + return false, errors.New("Name doesn't have a Digest, can't compare to Public") + } + expected, err := p.Name() + if err != nil { + return false, err + } + // No secrets, so no constant-time comparison + return bytes.Equal(expected.Digest.Value, n.Digest.Value), nil +} + +// HashValue is an algorithm-specific hash value. +type HashValue struct { + Alg Algorithm + Value tpmutil.U16Bytes +} + +func decodeHashValue(in *bytes.Buffer) (*HashValue, error) { + var hv HashValue + if err := tpmutil.UnpackBuf(in, &hv.Alg); err != nil { + return nil, fmt.Errorf("decoding Alg: %v", err) + } + hfn, err := hv.Alg.Hash() + if err != nil { + return nil, err + } + hv.Value = make(tpmutil.U16Bytes, hfn.Size()) + if _, err := in.Read(hv.Value); err != nil { + return nil, fmt.Errorf("decoding Value: %v", err) + } + return &hv, nil +} + +// Encode represents the given hash value as a TPMT_HA structure. +func (hv HashValue) Encode() ([]byte, error) { + return tpmutil.Pack(hv.Alg, tpmutil.RawBytes(hv.Value)) +} + +// ClockInfo contains TPM state info included in AttestationData. +type ClockInfo struct { + Clock uint64 + ResetCount uint32 + RestartCount uint32 + Safe byte +} + +// AlgorithmAttributes represents a TPMA_ALGORITHM value. +type AlgorithmAttributes uint32 + +// AlgorithmDescription represents a TPMS_ALGORITHM_DESCRIPTION structure. +type AlgorithmDescription struct { + ID Algorithm + Attributes AlgorithmAttributes +} + +// TaggedProperty represents a TPMS_TAGGED_PROPERTY structure. +type TaggedProperty struct { + Tag TPMProp + Value uint32 +} + +// Ticket represents evidence the TPM previously processed +// information. +type Ticket struct { + Type tpmutil.Tag + Hierarchy tpmutil.Handle + Digest tpmutil.U16Bytes +} + +// AuthCommand represents a TPMS_AUTH_COMMAND. This structure encapsulates parameters +// which authorize the use of a given handle or parameter. +type AuthCommand struct { + Session tpmutil.Handle + Nonce tpmutil.U16Bytes + Attributes SessionAttributes + Auth tpmutil.U16Bytes +} + +// TPMLDigest represents the TPML_Digest structure +// It is used to convey a list of digest values. +// This type is used in TPM2_PolicyOR() and in TPM2_PCR_Read() +type TPMLDigest struct { + Digests []tpmutil.U16Bytes +} + +// Encode converts the TPMLDigest structure into a byte slice +func (list *TPMLDigest) Encode() ([]byte, error) { + res, err := tpmutil.Pack(uint32(len(list.Digests))) + if err != nil { + return nil, err + } + for _, item := range list.Digests { + b, err := tpmutil.Pack(item) + if err != nil { + return nil, err + } + res = append(res, b...) + + } + return res, nil +} + +// DecodeTPMLDigest decodes a TPML_Digest part of a message. +func DecodeTPMLDigest(buf []byte) (*TPMLDigest, error) { + in := bytes.NewBuffer(buf) + var tpmld TPMLDigest + var count uint32 + if err := binary.Read(in, binary.BigEndian, &count); err != nil { + return nil, fmt.Errorf("decoding TPML_Digest: %v", err) + } + for in.Len() > 0 { + var hash tpmutil.U16Bytes + if err := hash.TPMUnmarshal(in); err != nil { + return nil, err + } + tpmld.Digests = append(tpmld.Digests, hash) + } + if count != uint32(len(tpmld.Digests)) { + return nil, fmt.Errorf("expected size and read size does not match") + } + return &tpmld, nil +} diff --git a/vendor/github.com/google/go-tpm/legacy/tpm2/tpm2.go b/vendor/github.com/google/go-tpm/legacy/tpm2/tpm2.go new file mode 100644 index 0000000..0105c37 --- /dev/null +++ b/vendor/github.com/google/go-tpm/legacy/tpm2/tpm2.go @@ -0,0 +1,2354 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package tpm2 supports direct communication with a TPM 2.0 device under Linux. +package tpm2 + +import ( + "bytes" + "crypto" + "fmt" + "io" + + "github.com/google/go-tpm/tpmutil" +) + +// GetRandom gets random bytes from the TPM. +func GetRandom(rw io.ReadWriter, size uint16) ([]byte, error) { + resp, err := runCommand(rw, TagNoSessions, CmdGetRandom, size) + if err != nil { + return nil, err + } + + var randBytes tpmutil.U16Bytes + if _, err := tpmutil.Unpack(resp, &randBytes); err != nil { + return nil, err + } + return randBytes, nil +} + +// FlushContext removes an object or session under handle to be removed from +// the TPM. This must be called for any loaded handle to avoid out-of-memory +// errors in TPM. +func FlushContext(rw io.ReadWriter, handle tpmutil.Handle) error { + _, err := runCommand(rw, TagNoSessions, CmdFlushContext, handle) + return err +} + +func encodeTPMLPCRSelection(sel ...PCRSelection) ([]byte, error) { + if len(sel) == 0 { + return tpmutil.Pack(uint32(0)) + } + + if len(sel) == 1 && len(sel[0].PCRs) == 0 && sel[0].Hash == 0 { + return tpmutil.Pack(uint32(0)) + } + + // PCR selection is a variable-size bitmask, where position of a set bit is + // the selected PCR index. + // Size of the bitmask in bytes is pre-pended. It should be at least + // sizeOfPCRSelect. + // + // For example, selecting PCRs 3 and 9 looks like: + // size(3) mask mask mask + // 00000011 00000000 00000001 00000100 + var retBytes []byte + for _, s := range sel { + ts := tpmsPCRSelection{ + Hash: s.Hash, + Size: sizeOfPCRSelect, + PCRs: make(tpmutil.RawBytes, sizeOfPCRSelect), + } + + // s[i].PCRs parameter is indexes of PCRs, convert that to set bits. + for _, n := range s.PCRs { + if n >= 8*sizeOfPCRSelect { + return nil, fmt.Errorf("PCR index %d is out of range (exceeds maximum value %d)", n, 8*sizeOfPCRSelect-1) + } + byteNum := n / 8 + bytePos := byte(1 << byte(n%8)) + ts.PCRs[byteNum] |= bytePos + } + + tmpBytes, err := tpmutil.Pack(ts) + if err != nil { + return nil, err + } + + retBytes = append(retBytes, tmpBytes...) + } + tmpSize, err := tpmutil.Pack(uint32(len(sel))) + if err != nil { + return nil, err + } + retBytes = append(tmpSize, retBytes...) + + return retBytes, nil +} + +func decodeTPMLPCRSelection(buf *bytes.Buffer) ([]PCRSelection, error) { + var count uint32 + var sel []PCRSelection + + // This unpacks buffer which is of type TPMLPCRSelection + // and returns the count of TPMSPCRSelections. + if err := tpmutil.UnpackBuf(buf, &count); err != nil { + return sel, err + } + + var ts tpmsPCRSelection + for i := 0; i < int(count); i++ { + var s PCRSelection + if err := tpmutil.UnpackBuf(buf, &ts.Hash, &ts.Size); err != nil { + return sel, err + } + ts.PCRs = make(tpmutil.RawBytes, ts.Size) + if _, err := buf.Read(ts.PCRs); err != nil { + return sel, err + } + s.Hash = ts.Hash + for j := 0; j < int(ts.Size); j++ { + for k := 0; k < 8; k++ { + set := ts.PCRs[j] & byte(1< 0, nil + case CapabilityAlgs: + var numAlgs uint32 + if err := tpmutil.UnpackBuf(buf, &numAlgs); err != nil { + return nil, false, fmt.Errorf("could not unpack algorithm count: %v", err) + } + + var algs []interface{} + for i := 0; i < int(numAlgs); i++ { + var alg AlgorithmDescription + if err := tpmutil.UnpackBuf(buf, &alg); err != nil { + return nil, false, fmt.Errorf("could not unpack algorithm description: %v", err) + } + algs = append(algs, alg) + } + return algs, moreData > 0, nil + case CapabilityTPMProperties: + var numProps uint32 + if err := tpmutil.UnpackBuf(buf, &numProps); err != nil { + return nil, false, fmt.Errorf("could not unpack fixed properties count: %v", err) + } + + var props []interface{} + for i := 0; i < int(numProps); i++ { + var prop TaggedProperty + if err := tpmutil.UnpackBuf(buf, &prop); err != nil { + return nil, false, fmt.Errorf("could not unpack tagged property: %v", err) + } + props = append(props, prop) + } + return props, moreData > 0, nil + + case CapabilityPCRs: + var pcrss []interface{} + pcrs, err := decodeTPMLPCRSelection(buf) + if err != nil { + return nil, false, fmt.Errorf("could not unpack pcr selection: %v", err) + } + for i := 0; i < len(pcrs); i++ { + pcrss = append(pcrss, pcrs[i]) + } + + return pcrss, moreData > 0, nil + + default: + return nil, false, fmt.Errorf("unsupported capability %v", capReported) + } +} + +// GetCapability returns various information about the TPM state. +// +// Currently only CapabilityHandles (list active handles) and CapabilityAlgs +// (list supported algorithms) are supported. CapabilityHandles will return +// a []tpmutil.Handle for vals, CapabilityAlgs will return +// []AlgorithmDescription. +// +// moreData is true if the TPM indicated that more data is available. Follow +// the spec for the capability in question on how to query for more data. +func GetCapability(rw io.ReadWriter, capa Capability, count, property uint32) (vals []interface{}, moreData bool, err error) { + resp, err := runCommand(rw, TagNoSessions, CmdGetCapability, capa, property, count) + if err != nil { + return nil, false, err + } + return decodeGetCapability(resp) +} + +// GetManufacturer returns the manufacturer ID +func GetManufacturer(rw io.ReadWriter) ([]byte, error) { + caps, _, err := GetCapability(rw, CapabilityTPMProperties, 1, uint32(Manufacturer)) + if err != nil { + return nil, err + } + + prop := caps[0].(TaggedProperty) + return tpmutil.Pack(prop.Value) +} + +func encodeAuthArea(sections ...AuthCommand) ([]byte, error) { + var res tpmutil.RawBytes + for _, s := range sections { + buf, err := tpmutil.Pack(s) + if err != nil { + return nil, err + } + res = append(res, buf...) + } + + size, err := tpmutil.Pack(uint32(len(res))) + if err != nil { + return nil, err + } + + return concat(size, res) +} + +func encodePCREvent(pcr tpmutil.Handle, eventData []byte) ([]byte, error) { + ha, err := tpmutil.Pack(pcr) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: EmptyAuth}) + if err != nil { + return nil, err + } + event, err := tpmutil.Pack(tpmutil.U16Bytes(eventData)) + if err != nil { + return nil, err + } + return concat(ha, auth, event) +} + +// PCREvent writes an update to the specified PCR. +func PCREvent(rw io.ReadWriter, pcr tpmutil.Handle, eventData []byte) error { + Cmd, err := encodePCREvent(pcr, eventData) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdPCREvent, tpmutil.RawBytes(Cmd)) + return err +} + +func encodeSensitiveArea(s tpmsSensitiveCreate) ([]byte, error) { + // TPMS_SENSITIVE_CREATE + buf, err := tpmutil.Pack(s) + if err != nil { + return nil, err + } + // TPM2B_SENSITIVE_CREATE + return tpmutil.Pack(tpmutil.U16Bytes(buf)) +} + +// encodeCreate works for both TPM2_Create and TPM2_CreatePrimary. +func encodeCreate(owner tpmutil.Handle, sel PCRSelection, auth AuthCommand, ownerPassword string, sensitiveData []byte, pub Public, outsideInfo []byte) ([]byte, error) { + parent, err := tpmutil.Pack(owner) + if err != nil { + return nil, err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return nil, err + } + inSensitive, err := encodeSensitiveArea(tpmsSensitiveCreate{ + UserAuth: []byte(ownerPassword), + Data: sensitiveData, + }) + if err != nil { + return nil, err + } + inPublic, err := pub.Encode() + if err != nil { + return nil, err + } + publicBlob, err := tpmutil.Pack(tpmutil.U16Bytes(inPublic)) + if err != nil { + return nil, err + } + outsideInfoBlob, err := tpmutil.Pack(tpmutil.U16Bytes(outsideInfo)) + if err != nil { + return nil, err + } + creationPCR, err := encodeTPMLPCRSelection(sel) + if err != nil { + return nil, err + } + return concat( + parent, + encodedAuth, + inSensitive, + publicBlob, + outsideInfoBlob, + creationPCR, + ) +} + +func decodeCreatePrimary(in []byte) (handle tpmutil.Handle, public, creationData, creationHash tpmutil.U16Bytes, ticket Ticket, creationName tpmutil.U16Bytes, err error) { + var paramSize uint32 + + buf := bytes.NewBuffer(in) + // Handle and auth data. + if err := tpmutil.UnpackBuf(buf, &handle, ¶mSize); err != nil { + return 0, nil, nil, nil, Ticket{}, nil, fmt.Errorf("decoding handle, paramSize: %v", err) + } + + if err := tpmutil.UnpackBuf(buf, &public, &creationData, &creationHash, &ticket, &creationName); err != nil { + return 0, nil, nil, nil, Ticket{}, nil, fmt.Errorf("decoding public, creationData, creationHash, ticket, creationName: %v", err) + } + + if _, err := DecodeCreationData(creationData); err != nil { + return 0, nil, nil, nil, Ticket{}, nil, fmt.Errorf("parsing CreationData: %v", err) + } + return handle, public, creationData, creationHash, ticket, creationName, err +} + +// CreatePrimary initializes the primary key in a given hierarchy. +// The second return value is the public part of the generated key. +func CreatePrimary(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, p Public) (tpmutil.Handle, crypto.PublicKey, error) { + hnd, public, _, _, _, _, err := CreatePrimaryEx(rw, owner, sel, parentPassword, ownerPassword, p) + if err != nil { + return 0, nil, err + } + + pub, err := DecodePublic(public) + if err != nil { + return 0, nil, fmt.Errorf("parsing public: %v", err) + } + + pubKey, err := pub.Key() + if err != nil { + return 0, nil, fmt.Errorf("extracting cryto.PublicKey from Public part of primary key: %v", err) + } + + return hnd, pubKey, err +} + +// CreatePrimaryEx initializes the primary key in a given hierarchy. +// This function differs from CreatePrimary in that all response elements +// are returned, and they are returned in relatively raw form. +func CreatePrimaryEx(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public) (keyHandle tpmutil.Handle, public, creationData, creationHash []byte, ticket Ticket, creationName []byte, err error) { + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)} + Cmd, err := encodeCreate(owner, sel, auth, ownerPassword, nil /*inSensitive*/, pub, nil /*OutsideInfo*/) + if err != nil { + return 0, nil, nil, nil, Ticket{}, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdCreatePrimary, tpmutil.RawBytes(Cmd)) + if err != nil { + return 0, nil, nil, nil, Ticket{}, nil, err + } + + return decodeCreatePrimary(resp) +} + +// CreatePrimaryRawTemplate is CreatePrimary, but with the public template +// (TPMT_PUBLIC) provided pre-encoded. This is commonly used with key templates +// stored in NV RAM. +func CreatePrimaryRawTemplate(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, public []byte) (tpmutil.Handle, crypto.PublicKey, error) { + pub, err := DecodePublic(public) + if err != nil { + return 0, nil, fmt.Errorf("parsing input template: %v", err) + } + return CreatePrimary(rw, owner, sel, parentPassword, ownerPassword, pub) +} + +func decodeReadPublic(in []byte) (Public, []byte, []byte, error) { + var resp struct { + Public tpmutil.U16Bytes + Name tpmutil.U16Bytes + QualifiedName tpmutil.U16Bytes + } + if _, err := tpmutil.Unpack(in, &resp); err != nil { + return Public{}, nil, nil, err + } + pub, err := DecodePublic(resp.Public) + if err != nil { + return Public{}, nil, nil, err + } + return pub, resp.Name, resp.QualifiedName, nil +} + +// ReadPublic reads the public part of the object under handle. +// Returns the public data, name and qualified name. +func ReadPublic(rw io.ReadWriter, handle tpmutil.Handle) (Public, []byte, []byte, error) { + resp, err := runCommand(rw, TagNoSessions, CmdReadPublic, handle) + if err != nil { + return Public{}, nil, nil, err + } + + return decodeReadPublic(resp) +} + +func decodeCreate(in []byte) (private, public, creationData, creationHash tpmutil.U16Bytes, creationTicket Ticket, err error) { + buf := bytes.NewBuffer(in) + var paramSize uint32 + if err := tpmutil.UnpackBuf(buf, ¶mSize, &private, &public, &creationData, &creationHash, &creationTicket); err != nil { + return nil, nil, nil, nil, Ticket{}, fmt.Errorf("decoding Handle, Private, Public, CreationData, CreationHash, CreationTicket: %v", err) + } + if err != nil { + return nil, nil, nil, nil, Ticket{}, fmt.Errorf("decoding CreationTicket: %v", err) + } + if _, err := DecodeCreationData(creationData); err != nil { + return nil, nil, nil, nil, Ticket{}, fmt.Errorf("decoding CreationData: %v", err) + } + return private, public, creationData, creationHash, creationTicket, nil +} + +func create(rw io.ReadWriter, parentHandle tpmutil.Handle, auth AuthCommand, objectPassword string, sensitiveData []byte, pub Public, pcrSelection PCRSelection, outsideInfo []byte) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) { + cmd, err := encodeCreate(parentHandle, pcrSelection, auth, objectPassword, sensitiveData, pub, outsideInfo) + if err != nil { + return nil, nil, nil, nil, Ticket{}, err + } + resp, err := runCommand(rw, TagSessions, CmdCreate, tpmutil.RawBytes(cmd)) + if err != nil { + return nil, nil, nil, nil, Ticket{}, err + } + return decodeCreate(resp) +} + +// CreateKey creates a new key pair under the owner handle. +// Returns private key and public key blobs as well as the +// creation data, a hash of said data and the creation ticket. +func CreateKey(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) { + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)} + return create(rw, owner, auth, ownerPassword, nil /*inSensitive*/, pub, sel, nil /*OutsideInfo*/) +} + +// CreateKeyUsingAuth creates a new key pair under the owner handle using the +// provided AuthCommand. Returns private key and public key blobs as well as +// the creation data, a hash of said data, and the creation ticket. +func CreateKeyUsingAuth(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, auth AuthCommand, ownerPassword string, pub Public) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) { + return create(rw, owner, auth, ownerPassword, nil /*inSensitive*/, pub, sel, nil /*OutsideInfo*/) +} + +// CreateKeyWithSensitive is very similar to CreateKey, except +// that it can take in a piece of sensitive data. +func CreateKeyWithSensitive(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public, sensitive []byte) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) { + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)} + return create(rw, owner, auth, ownerPassword, sensitive, pub, sel, nil /*OutsideInfo*/) +} + +// CreateKeyWithOutsideInfo is very similar to CreateKey, except +// that it returns the outside information. +func CreateKeyWithOutsideInfo(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public, outsideInfo []byte) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) { + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)} + return create(rw, owner, auth, ownerPassword, nil /*inSensitive*/, pub, sel, outsideInfo) +} + +// Seal creates a data blob object that seals the sensitive data under a parent and with a +// password and auth policy. Access to the parent must be available with a simple password. +// Returns private and public portions of the created object. +func Seal(rw io.ReadWriter, parentHandle tpmutil.Handle, parentPassword, objectPassword string, objectAuthPolicy []byte, sensitiveData []byte) ([]byte, []byte, error) { + inPublic := Public{ + Type: AlgKeyedHash, + NameAlg: AlgSHA256, + Attributes: FlagFixedTPM | FlagFixedParent, + AuthPolicy: objectAuthPolicy, + } + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)} + private, public, _, _, _, err := create(rw, parentHandle, auth, objectPassword, sensitiveData, inPublic, PCRSelection{}, nil /*OutsideInfo*/) + if err != nil { + return nil, nil, err + } + return private, public, nil +} + +func encodeImport(parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob, symSeed, encryptionKey tpmutil.U16Bytes, sym *SymScheme) ([]byte, error) { + ph, err := tpmutil.Pack(parentHandle) + if err != nil { + return nil, err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return nil, err + } + data, err := tpmutil.Pack(encryptionKey, publicBlob, privateBlob, symSeed) + if err != nil { + return nil, err + } + encodedScheme, err := sym.encode() + if err != nil { + return nil, err + } + + return concat(ph, encodedAuth, data, encodedScheme) +} + +func decodeImport(resp []byte) ([]byte, error) { + var paramSize uint32 + var outPrivate tpmutil.U16Bytes + _, err := tpmutil.Unpack(resp, ¶mSize, &outPrivate) + return outPrivate, err +} + +// Import allows a user to import a key created on a different computer +// or in a different TPM. The publicBlob and privateBlob must always be +// provided. symSeed should be non-nil iff an "outer wrapper" is used. Both of +// encryptionKey and sym should be non-nil iff an "inner wrapper" is used. +func Import(rw io.ReadWriter, parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob, symSeed, encryptionKey []byte, sym *SymScheme) ([]byte, error) { + Cmd, err := encodeImport(parentHandle, auth, publicBlob, privateBlob, symSeed, encryptionKey, sym) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdImport, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeImport(resp) +} + +func encodeLoad(parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob tpmutil.U16Bytes) ([]byte, error) { + ah, err := tpmutil.Pack(parentHandle) + if err != nil { + return nil, err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(privateBlob, publicBlob) + if err != nil { + return nil, err + } + return concat(ah, encodedAuth, params) +} + +func decodeLoad(in []byte) (tpmutil.Handle, []byte, error) { + var handle tpmutil.Handle + var paramSize uint32 + var name tpmutil.U16Bytes + + if _, err := tpmutil.Unpack(in, &handle, ¶mSize, &name); err != nil { + return 0, nil, err + } + + // Re-encode the name as a TPM2B_NAME so it can be parsed by DecodeName(). + b := &bytes.Buffer{} + if err := name.TPMMarshal(b); err != nil { + return 0, nil, err + } + return handle, b.Bytes(), nil +} + +// Load loads public/private blobs into an object in the TPM. +// Returns loaded object handle and its name. +func Load(rw io.ReadWriter, parentHandle tpmutil.Handle, parentAuth string, publicBlob, privateBlob []byte) (tpmutil.Handle, []byte, error) { + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentAuth)} + return LoadUsingAuth(rw, parentHandle, auth, publicBlob, privateBlob) +} + +// LoadUsingAuth loads public/private blobs into an object in the TPM using the +// provided AuthCommand. Returns loaded object handle and its name. +func LoadUsingAuth(rw io.ReadWriter, parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob []byte) (tpmutil.Handle, []byte, error) { + Cmd, err := encodeLoad(parentHandle, auth, publicBlob, privateBlob) + if err != nil { + return 0, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdLoad, tpmutil.RawBytes(Cmd)) + if err != nil { + return 0, nil, err + } + return decodeLoad(resp) +} + +func encodeLoadExternal(pub Public, private Private, hierarchy tpmutil.Handle) ([]byte, error) { + privateBlob, err := private.Encode() + if err != nil { + return nil, err + } + publicBlob, err := pub.Encode() + if err != nil { + return nil, err + } + + return tpmutil.Pack(tpmutil.U16Bytes(privateBlob), tpmutil.U16Bytes(publicBlob), hierarchy) +} + +func decodeLoadExternal(in []byte) (tpmutil.Handle, []byte, error) { + var handle tpmutil.Handle + var name tpmutil.U16Bytes + + if _, err := tpmutil.Unpack(in, &handle, &name); err != nil { + return 0, nil, err + } + return handle, name, nil +} + +// LoadExternal loads a public (and optionally a private) key into an object in +// the TPM. Returns loaded object handle and its name. +func LoadExternal(rw io.ReadWriter, pub Public, private Private, hierarchy tpmutil.Handle) (tpmutil.Handle, []byte, error) { + Cmd, err := encodeLoadExternal(pub, private, hierarchy) + if err != nil { + return 0, nil, err + } + resp, err := runCommand(rw, TagNoSessions, CmdLoadExternal, tpmutil.RawBytes(Cmd)) + if err != nil { + return 0, nil, err + } + handle, name, err := decodeLoadExternal(resp) + if err != nil { + return 0, nil, err + } + return handle, name, nil +} + +// PolicyPassword sets password authorization requirement on the object. +func PolicyPassword(rw io.ReadWriter, handle tpmutil.Handle) error { + _, err := runCommand(rw, TagNoSessions, CmdPolicyPassword, handle) + return err +} + +func encodePolicySecret(entityHandle tpmutil.Handle, entityAuth AuthCommand, policyHandle tpmutil.Handle, policyNonce, cpHash, policyRef tpmutil.U16Bytes, expiry int32) ([]byte, error) { + auth, err := encodeAuthArea(entityAuth) + if err != nil { + return nil, err + } + handles, err := tpmutil.Pack(entityHandle, policyHandle) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(policyNonce, cpHash, policyRef, expiry) + if err != nil { + return nil, err + } + return concat(handles, auth, params) +} + +func decodePolicySecret(in []byte) ([]byte, *Ticket, error) { + buf := bytes.NewBuffer(in) + + var paramSize uint32 + var timeout tpmutil.U16Bytes + if err := tpmutil.UnpackBuf(buf, ¶mSize, &timeout); err != nil { + return nil, nil, fmt.Errorf("decoding timeout: %v", err) + } + var t Ticket + if err := tpmutil.UnpackBuf(buf, &t); err != nil { + return nil, nil, fmt.Errorf("decoding ticket: %v", err) + } + return timeout, &t, nil +} + +// PolicySecret sets a secret authorization requirement on the provided entity. +func PolicySecret(rw io.ReadWriter, entityHandle tpmutil.Handle, entityAuth AuthCommand, policyHandle tpmutil.Handle, policyNonce, cpHash, policyRef []byte, expiry int32) ([]byte, *Ticket, error) { + Cmd, err := encodePolicySecret(entityHandle, entityAuth, policyHandle, policyNonce, cpHash, policyRef, expiry) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdPolicySecret, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + return decodePolicySecret(resp) +} + +func encodePolicySigned(validationKeyHandle tpmutil.Handle, policyHandle tpmutil.Handle, policyNonce, cpHash, policyRef tpmutil.U16Bytes, expiry int32, auth []byte) ([]byte, error) { + handles, err := tpmutil.Pack(validationKeyHandle, policyHandle) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(policyNonce, cpHash, policyRef, expiry, auth) + if err != nil { + return nil, err + } + return concat(handles, params) +} + +func decodePolicySigned(in []byte) ([]byte, *Ticket, error) { + buf := bytes.NewBuffer(in) + + var timeout tpmutil.U16Bytes + if err := tpmutil.UnpackBuf(buf, &timeout); err != nil { + return nil, nil, fmt.Errorf("decoding timeout: %v", err) + } + var t Ticket + if err := tpmutil.UnpackBuf(buf, &t); err != nil { + return nil, nil, fmt.Errorf("decoding ticket: %v", err) + } + return timeout, &t, nil +} + +// PolicySigned sets a signed authorization requirement on the provided policy. +func PolicySigned(rw io.ReadWriter, validationKeyHandle tpmutil.Handle, policyHandle tpmutil.Handle, policyNonce, cpHash, policyRef []byte, expiry int32, signedAuth []byte) ([]byte, *Ticket, error) { + Cmd, err := encodePolicySigned(validationKeyHandle, policyHandle, policyNonce, cpHash, policyRef, expiry, signedAuth) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagNoSessions, CmdPolicySigned, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + return decodePolicySigned(resp) +} + +func encodePolicyPCR(session tpmutil.Handle, expectedDigest tpmutil.U16Bytes, sel PCRSelection) ([]byte, error) { + params, err := tpmutil.Pack(session, expectedDigest) + if err != nil { + return nil, err + } + pcrs, err := encodeTPMLPCRSelection(sel) + if err != nil { + return nil, err + } + return concat(params, pcrs) +} + +// PolicyPCR sets PCR state binding for authorization on a session. +// +// expectedDigest is optional. When specified, it's compared against the digest +// of PCRs matched by sel. +// +// Note that expectedDigest must be a *digest* of the expected PCR value. You +// must compute the digest manually. ReadPCR returns raw PCR values, not their +// digests. +// If you wish to select multiple PCRs, concatenate their values before +// computing the digest. See "TPM 2.0 Part 1, Selecting Multiple PCR". +func PolicyPCR(rw io.ReadWriter, session tpmutil.Handle, expectedDigest []byte, sel PCRSelection) error { + Cmd, err := encodePolicyPCR(session, expectedDigest, sel) + if err != nil { + return err + } + _, err = runCommand(rw, TagNoSessions, CmdPolicyPCR, tpmutil.RawBytes(Cmd)) + return err +} + +// PolicyOr compares PolicySession→Digest against the list of provided values. +// If the current Session→Digest does not match any value in the list, +// the TPM shall return TPM_RC_VALUE. Otherwise, the TPM will reset policySession→Digest +// to a Zero Digest. Then policySession→Digest is extended by the concatenation of +// TPM_CC_PolicyOR and the concatenation of all of the digests. +func PolicyOr(rw io.ReadWriter, session tpmutil.Handle, digests TPMLDigest) error { + d, err := digests.Encode() + if err != nil { + return err + } + data, err := tpmutil.Pack(session, d) + if err != nil { + return err + } + _, err = runCommand(rw, TagNoSessions, CmdPolicyOr, data) + return err +} + +// PolicyGetDigest returns the current policyDigest of the session. +func PolicyGetDigest(rw io.ReadWriter, handle tpmutil.Handle) ([]byte, error) { + resp, err := runCommand(rw, TagNoSessions, CmdPolicyGetDigest, handle) + if err != nil { + return nil, err + } + + var digest tpmutil.U16Bytes + _, err = tpmutil.Unpack(resp, &digest) + return digest, err +} + +func encodeStartAuthSession(tpmKey, bindKey tpmutil.Handle, nonceCaller, secret tpmutil.U16Bytes, se SessionType, sym, hashAlg Algorithm) ([]byte, error) { + ha, err := tpmutil.Pack(tpmKey, bindKey) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(nonceCaller, secret, se, sym, hashAlg) + if err != nil { + return nil, err + } + return concat(ha, params) +} + +func decodeStartAuthSession(in []byte) (tpmutil.Handle, []byte, error) { + var handle tpmutil.Handle + var nonce tpmutil.U16Bytes + if _, err := tpmutil.Unpack(in, &handle, &nonce); err != nil { + return 0, nil, err + } + return handle, nonce, nil +} + +// StartAuthSession initializes a session object. +// Returns session handle and the initial nonce from the TPM. +func StartAuthSession(rw io.ReadWriter, tpmKey, bindKey tpmutil.Handle, nonceCaller, secret []byte, se SessionType, sym, hashAlg Algorithm) (tpmutil.Handle, []byte, error) { + Cmd, err := encodeStartAuthSession(tpmKey, bindKey, nonceCaller, secret, se, sym, hashAlg) + if err != nil { + return 0, nil, err + } + resp, err := runCommand(rw, TagNoSessions, CmdStartAuthSession, tpmutil.RawBytes(Cmd)) + if err != nil { + return 0, nil, err + } + return decodeStartAuthSession(resp) +} + +func encodeUnseal(sessionHandle, itemHandle tpmutil.Handle, password string) ([]byte, error) { + ha, err := tpmutil.Pack(itemHandle) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: sessionHandle, Attributes: AttrContinueSession, Auth: []byte(password)}) + if err != nil { + return nil, err + } + return concat(ha, auth) +} + +func decodeUnseal(in []byte) ([]byte, error) { + var paramSize uint32 + var unsealed tpmutil.U16Bytes + + if _, err := tpmutil.Unpack(in, ¶mSize, &unsealed); err != nil { + return nil, err + } + return unsealed, nil +} + +// Unseal returns the data for a loaded sealed object. +func Unseal(rw io.ReadWriter, itemHandle tpmutil.Handle, password string) ([]byte, error) { + return UnsealWithSession(rw, HandlePasswordSession, itemHandle, password) +} + +// UnsealWithSession returns the data for a loaded sealed object. +func UnsealWithSession(rw io.ReadWriter, sessionHandle, itemHandle tpmutil.Handle, password string) ([]byte, error) { + Cmd, err := encodeUnseal(sessionHandle, itemHandle, password) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdUnseal, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeUnseal(resp) +} + +func encodeQuote(signingHandle tpmutil.Handle, signerAuth string, toQuote tpmutil.U16Bytes, sel PCRSelection, sigAlg Algorithm) ([]byte, error) { + ha, err := tpmutil.Pack(signingHandle) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(signerAuth)}) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(toQuote, sigAlg) + if err != nil { + return nil, err + } + pcrs, err := encodeTPMLPCRSelection(sel) + if err != nil { + return nil, err + } + return concat(ha, auth, params, pcrs) +} + +func decodeQuote(in []byte) ([]byte, []byte, error) { + buf := bytes.NewBuffer(in) + var paramSize uint32 + if err := tpmutil.UnpackBuf(buf, ¶mSize); err != nil { + return nil, nil, err + } + buf.Truncate(int(paramSize)) + var attest tpmutil.U16Bytes + if err := tpmutil.UnpackBuf(buf, &attest); err != nil { + return nil, nil, err + } + return attest, buf.Bytes(), nil +} + +// Quote returns a quote of PCR values. A quote is a signature of the PCR +// values, created using a signing TPM key. +// +// Returns attestation data and the decoded signature. +func Quote(rw io.ReadWriter, signingHandle tpmutil.Handle, signerAuth, unused string, toQuote []byte, sel PCRSelection, sigAlg Algorithm) ([]byte, *Signature, error) { + // TODO: Remove "unused" parameter on next breaking change. + attest, sigRaw, err := QuoteRaw(rw, signingHandle, signerAuth, unused, toQuote, sel, sigAlg) + if err != nil { + return nil, nil, err + } + sig, err := DecodeSignature(bytes.NewBuffer(sigRaw)) + if err != nil { + return nil, nil, err + } + return attest, sig, nil +} + +// QuoteRaw is very similar to Quote, except that it will return +// the raw signature in a byte array without decoding. +func QuoteRaw(rw io.ReadWriter, signingHandle tpmutil.Handle, signerAuth, _ string, toQuote []byte, sel PCRSelection, sigAlg Algorithm) ([]byte, []byte, error) { + // TODO: Remove "unused" parameter on next breaking change. + Cmd, err := encodeQuote(signingHandle, signerAuth, toQuote, sel, sigAlg) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdQuote, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + return decodeQuote(resp) +} + +func encodeActivateCredential(auth []AuthCommand, activeHandle tpmutil.Handle, keyHandle tpmutil.Handle, credBlob, secret tpmutil.U16Bytes) ([]byte, error) { + ha, err := tpmutil.Pack(activeHandle, keyHandle) + if err != nil { + return nil, err + } + a, err := encodeAuthArea(auth...) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(credBlob, secret) + if err != nil { + return nil, err + } + return concat(ha, a, params) +} + +func decodeActivateCredential(in []byte) ([]byte, error) { + var paramSize uint32 + var certInfo tpmutil.U16Bytes + + if _, err := tpmutil.Unpack(in, ¶mSize, &certInfo); err != nil { + return nil, err + } + return certInfo, nil +} + +// ActivateCredential associates an object with a credential. +// Returns decrypted certificate information. +func ActivateCredential(rw io.ReadWriter, activeHandle, keyHandle tpmutil.Handle, activePassword, protectorPassword string, credBlob, secret []byte) ([]byte, error) { + return ActivateCredentialUsingAuth(rw, []AuthCommand{ + {Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(activePassword)}, + {Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(protectorPassword)}, + }, activeHandle, keyHandle, credBlob, secret) +} + +// ActivateCredentialUsingAuth associates an object with a credential, using the +// given set of authorizations. Two authorization must be provided. +// Returns decrypted certificate information. +func ActivateCredentialUsingAuth(rw io.ReadWriter, auth []AuthCommand, activeHandle, keyHandle tpmutil.Handle, credBlob, secret []byte) ([]byte, error) { + if len(auth) != 2 { + return nil, fmt.Errorf("len(auth) = %d, want 2", len(auth)) + } + + Cmd, err := encodeActivateCredential(auth, activeHandle, keyHandle, credBlob, secret) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdActivateCredential, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeActivateCredential(resp) +} + +func encodeMakeCredential(protectorHandle tpmutil.Handle, credential, activeName tpmutil.U16Bytes) ([]byte, error) { + ha, err := tpmutil.Pack(protectorHandle) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(credential, activeName) + if err != nil { + return nil, err + } + return concat(ha, params) +} + +func decodeMakeCredential(in []byte) ([]byte, []byte, error) { + var credBlob, encryptedSecret tpmutil.U16Bytes + + if _, err := tpmutil.Unpack(in, &credBlob, &encryptedSecret); err != nil { + return nil, nil, err + } + return credBlob, encryptedSecret, nil +} + +// MakeCredential creates an encrypted credential for use in MakeCredential. +// Returns encrypted credential and wrapped secret used to encrypt it. +func MakeCredential(rw io.ReadWriter, protectorHandle tpmutil.Handle, credential, activeName []byte) ([]byte, []byte, error) { + Cmd, err := encodeMakeCredential(protectorHandle, credential, activeName) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagNoSessions, CmdMakeCredential, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + return decodeMakeCredential(resp) +} + +func encodeEvictControl(ownerAuth string, owner, objectHandle, persistentHandle tpmutil.Handle) ([]byte, error) { + ha, err := tpmutil.Pack(owner, objectHandle) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(ownerAuth)}) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(persistentHandle) + if err != nil { + return nil, err + } + return concat(ha, auth, params) +} + +// EvictControl toggles persistence of an object within the TPM. +func EvictControl(rw io.ReadWriter, ownerAuth string, owner, objectHandle, persistentHandle tpmutil.Handle) error { + Cmd, err := encodeEvictControl(ownerAuth, owner, objectHandle, persistentHandle) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdEvictControl, tpmutil.RawBytes(Cmd)) + return err +} + +func encodeClear(handle tpmutil.Handle, auth AuthCommand) ([]byte, error) { + ah, err := tpmutil.Pack(handle) + if err != nil { + return nil, err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return nil, err + } + return concat(ah, encodedAuth) +} + +// Clear clears lockout, endorsement and owner hierarchy authorization values +func Clear(rw io.ReadWriter, handle tpmutil.Handle, auth AuthCommand) error { + Cmd, err := encodeClear(handle, auth) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdClear, tpmutil.RawBytes(Cmd)) + return err +} + +func encodePCRAllocate(handle tpmutil.Handle, auth AuthCommand, pcrSelection []PCRSelection) ([]byte, error) { + ah, err := tpmutil.Pack(handle) + if err != nil { + return nil, err + } + authEncoded, err := encodeAuthArea(auth) + if err != nil { + return nil, err + } + + pcrEncoded, err := encodeTPMLPCRSelection(pcrSelection...) + if err != nil { + return nil, err + } + return concat(ah, authEncoded, pcrEncoded) +} + +// PCRAllocate sets the desired PCR allocation of PCR and algorithms. +// The changes take effect once the TPM is restarted. +func PCRAllocate(rw io.ReadWriter, handle tpmutil.Handle, auth AuthCommand, pcrSelection []PCRSelection) error { + Cmd, err := encodePCRAllocate(handle, auth, pcrSelection) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdPCRAllocate, tpmutil.RawBytes(Cmd)) + return err +} + +func encodeHierarchyChangeAuth(handle tpmutil.Handle, auth AuthCommand, newAuth string) ([]byte, error) { + ah, err := tpmutil.Pack(handle) + if err != nil { + return nil, err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return nil, err + } + param, err := tpmutil.Pack(tpmutil.U16Bytes(newAuth)) + if err != nil { + return nil, err + } + return concat(ah, encodedAuth, param) +} + +// HierarchyChangeAuth changes the authorization values for a hierarchy or for the lockout authority +func HierarchyChangeAuth(rw io.ReadWriter, handle tpmutil.Handle, auth AuthCommand, newAuth string) error { + Cmd, err := encodeHierarchyChangeAuth(handle, auth, newAuth) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdHierarchyChangeAuth, tpmutil.RawBytes(Cmd)) + return err +} + +// ContextSave returns an encrypted version of the session, object or sequence +// context for storage outside of the TPM. The handle references context to +// store. +func ContextSave(rw io.ReadWriter, handle tpmutil.Handle) ([]byte, error) { + return runCommand(rw, TagNoSessions, CmdContextSave, handle) +} + +// ContextLoad reloads context data created by ContextSave. +func ContextLoad(rw io.ReadWriter, saveArea []byte) (tpmutil.Handle, error) { + resp, err := runCommand(rw, TagNoSessions, CmdContextLoad, tpmutil.RawBytes(saveArea)) + if err != nil { + return 0, err + } + var handle tpmutil.Handle + _, err = tpmutil.Unpack(resp, &handle) + return handle, err +} + +func encodeIncrementNV(handle tpmutil.Handle, authString string) ([]byte, error) { + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(authString)}) + if err != nil { + return nil, err + } + out, err := tpmutil.Pack(handle, handle) + if err != nil { + return nil, err + } + return concat(out, auth) +} + +// NVIncrement increments a counter in NVRAM. +func NVIncrement(rw io.ReadWriter, handle tpmutil.Handle, authString string) error { + Cmd, err := encodeIncrementNV(handle, authString) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdIncrementNVCounter, tpmutil.RawBytes(Cmd)) + return err +} + +// NVUndefineSpace removes an index from TPM's NV storage. +func NVUndefineSpace(rw io.ReadWriter, ownerAuth string, owner, index tpmutil.Handle) error { + authArea := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(ownerAuth)} + return NVUndefineSpaceEx(rw, owner, index, authArea) +} + +// NVUndefineSpaceEx removes an index from NVRAM. Unlike, NVUndefineSpace(), custom command +// authorization can be provided. +func NVUndefineSpaceEx(rw io.ReadWriter, owner, index tpmutil.Handle, authArea AuthCommand) error { + out, err := tpmutil.Pack(owner, index) + if err != nil { + return err + } + auth, err := encodeAuthArea(authArea) + if err != nil { + return err + } + cmd, err := concat(out, auth) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdUndefineSpace, tpmutil.RawBytes(cmd)) + return err +} + +// NVUndefineSpaceSpecial This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE SET. +// The policy to authorize NV index access needs to be created with PolicyCommandCode(rw, sessionHandle, CmdNVUndefineSpaceSpecial) function +// nvAuthCmd takes the session handle for the policy and the AuthValue (which can be emptyAuth) for the authorization. +// platformAuth takes either a sessionHandle for the platform policy or HandlePasswordSession and the platformAuth value for authorization. +func NVUndefineSpaceSpecial(rw io.ReadWriter, nvIndex tpmutil.Handle, nvAuth, platformAuth AuthCommand) error { + authBytes, err := encodeAuthArea(nvAuth, platformAuth) + if err != nil { + return err + } + auth, err := tpmutil.Pack(authBytes) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdNVUndefineSpaceSpecial, nvIndex, HandlePlatform, tpmutil.RawBytes(auth)) + return err +} + +// NVDefineSpace creates an index in TPM's NV storage. +func NVDefineSpace(rw io.ReadWriter, owner, handle tpmutil.Handle, ownerAuth, authString string, policy []byte, attributes NVAttr, dataSize uint16) error { + nvPub := NVPublic{ + NVIndex: handle, + NameAlg: AlgSHA1, + Attributes: attributes, + AuthPolicy: policy, + DataSize: dataSize, + } + authArea := AuthCommand{ + Session: HandlePasswordSession, + Attributes: AttrContinueSession, + Auth: []byte(ownerAuth), + } + return NVDefineSpaceEx(rw, owner, authString, nvPub, authArea) +} + +// NVDefineSpaceEx accepts NVPublic structure and AuthCommand, allowing more flexibility. +func NVDefineSpaceEx(rw io.ReadWriter, owner tpmutil.Handle, authVal string, pubInfo NVPublic, authArea AuthCommand) error { + ha, err := tpmutil.Pack(owner) + if err != nil { + return err + } + auth, err := encodeAuthArea(authArea) + if err != nil { + return err + } + publicInfo, err := tpmutil.Pack(pubInfo) + if err != nil { + return err + } + params, err := tpmutil.Pack(tpmutil.U16Bytes(authVal), tpmutil.U16Bytes(publicInfo)) + if err != nil { + return err + } + cmd, err := concat(ha, auth, params) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdDefineSpace, tpmutil.RawBytes(cmd)) + return err +} + +// NVWrite writes data into the TPM's NV storage. +func NVWrite(rw io.ReadWriter, authHandle, nvIndex tpmutil.Handle, authString string, data tpmutil.U16Bytes, offset uint16) error { + auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(authString)} + return NVWriteEx(rw, authHandle, nvIndex, auth, data, offset) +} + +// NVWriteEx does the same as NVWrite with the exception of letting the user take care of the AuthCommand before calling the function. +// This allows more flexibility and does not limit the AuthCommand to PasswordSession. +func NVWriteEx(rw io.ReadWriter, authHandle, nvIndex tpmutil.Handle, authArea AuthCommand, data tpmutil.U16Bytes, offset uint16) error { + h, err := tpmutil.Pack(authHandle, nvIndex) + if err != nil { + return err + } + authEnc, err := encodeAuthArea(authArea) + if err != nil { + return err + } + + d, err := tpmutil.Pack(data, offset) + if err != nil { + return err + } + + b, err := concat(h, authEnc, d) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdWriteNV, tpmutil.RawBytes(b)) + return err +} + +func encodeLockNV(owner, handle tpmutil.Handle, authString string) ([]byte, error) { + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(authString)}) + if err != nil { + return nil, err + } + out, err := tpmutil.Pack(owner, handle) + if err != nil { + return nil, err + } + return concat(out, auth) +} + +// NVWriteLock inhibits further writes on the given NV index if at least one of +// the AttrWriteSTClear or AttrWriteDefine bits is set. +// +// AttrWriteSTClear causes the index to be locked until the TPM is restarted +// (see the Startup function). +// +// AttrWriteDefine causes the index to be locked permanently if data has been +// written to the index; otherwise the lock is removed on startup. +// +// NVWriteLock returns an error if neither bit is set. +// +// It is not an error to call NVWriteLock for an index that is already locked +// for writing. +func NVWriteLock(rw io.ReadWriter, owner, handle tpmutil.Handle, authString string) error { + Cmd, err := encodeLockNV(owner, handle, authString) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdWriteLockNV, tpmutil.RawBytes(Cmd)) + return err +} + +func decodeNVReadPublic(in []byte) (NVPublic, error) { + var pub NVPublic + var buf tpmutil.U16Bytes + if _, err := tpmutil.Unpack(in, &buf); err != nil { + return pub, err + } + _, err := tpmutil.Unpack(buf, &pub) + return pub, err +} + +// NVReadPublic reads the public data of an NV index. +func NVReadPublic(rw io.ReadWriter, index tpmutil.Handle) (NVPublic, error) { + // Read public area to determine data size. + resp, err := runCommand(rw, TagNoSessions, CmdReadPublicNV, index) + if err != nil { + return NVPublic{}, err + } + return decodeNVReadPublic(resp) +} + +func decodeNVRead(in []byte) ([]byte, error) { + var paramSize uint32 + var data tpmutil.U16Bytes + if _, err := tpmutil.Unpack(in, ¶mSize, &data); err != nil { + return nil, err + } + return data, nil +} + +func encodeNVRead(nvIndex, authHandle tpmutil.Handle, password string, offset, dataSize uint16) ([]byte, error) { + handles, err := tpmutil.Pack(authHandle, nvIndex) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(password)}) + if err != nil { + return nil, err + } + + params, err := tpmutil.Pack(dataSize, offset) + if err != nil { + return nil, err + } + + return concat(handles, auth, params) +} + +// NVRead reads a full data blob from an NV index. This function is +// deprecated; use NVReadEx instead. +func NVRead(rw io.ReadWriter, index tpmutil.Handle) ([]byte, error) { + return NVReadEx(rw, index, index, "", 0) +} + +// NVReadEx reads a full data blob from an NV index, using the given +// authorization handle. NVRead commands are done in blocks of blockSize. +// If blockSize is 0, the TPM is queried for TPM_PT_NV_BUFFER_MAX, and that +// value is used. +func NVReadEx(rw io.ReadWriter, index, authHandle tpmutil.Handle, password string, blockSize int) ([]byte, error) { + if blockSize == 0 { + readBuff, _, err := GetCapability(rw, CapabilityTPMProperties, 1, uint32(NVMaxBufferSize)) + if err != nil { + return nil, fmt.Errorf("GetCapability for TPM_PT_NV_BUFFER_MAX failed: %v", err) + } + if len(readBuff) != 1 { + return nil, fmt.Errorf("could not determine NVRAM read/write buffer size") + } + rb, ok := readBuff[0].(TaggedProperty) + if !ok { + return nil, fmt.Errorf("GetCapability returned unexpected type: %T, expected TaggedProperty", readBuff[0]) + } + blockSize = int(rb.Value) + } + + // Read public area to determine data size. + pub, err := NVReadPublic(rw, index) + if err != nil { + return nil, fmt.Errorf("decoding NV_ReadPublic response: %v", err) + } + + // Read the NVRAM area in blocks. + outBuff := make([]byte, 0, int(pub.DataSize)) + for len(outBuff) < int(pub.DataSize) { + readSize := blockSize + if readSize > (int(pub.DataSize) - len(outBuff)) { + readSize = int(pub.DataSize) - len(outBuff) + } + + Cmd, err := encodeNVRead(index, authHandle, password, uint16(len(outBuff)), uint16(readSize)) + if err != nil { + return nil, fmt.Errorf("building NV_Read command: %v", err) + } + resp, err := runCommand(rw, TagSessions, CmdReadNV, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, fmt.Errorf("running NV_Read command (cursor=%d,size=%d): %v", len(outBuff), readSize, err) + } + data, err := decodeNVRead(resp) + if err != nil { + return nil, fmt.Errorf("decoding NV_Read command: %v", err) + } + outBuff = append(outBuff, data...) + } + return outBuff, nil +} + +// NVReadLock inhibits further reads of the given NV index if AttrReadSTClear +// is set. After the TPM is restarted the index can be read again (see the +// Startup function). +// +// NVReadLock returns an error if the AttrReadSTClear bit is not set. +// +// It is not an error to call NVReadLock for an index that is already locked +// for reading. +func NVReadLock(rw io.ReadWriter, owner, handle tpmutil.Handle, authString string) error { + Cmd, err := encodeLockNV(owner, handle, authString) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdReadLockNV, tpmutil.RawBytes(Cmd)) + return err +} + +// decodeHash unpacks a successful response to TPM2_Hash, returning the computed digest and +// validation ticket. +func decodeHash(resp []byte) ([]byte, *Ticket, error) { + var digest tpmutil.U16Bytes + var validation Ticket + + buf := bytes.NewBuffer(resp) + if err := tpmutil.UnpackBuf(buf, &digest, &validation); err != nil { + return nil, nil, err + } + return digest, &validation, nil +} + +// Hash computes a hash of data in buf using TPM2_Hash, returning the computed +// digest and validation ticket. The validation ticket serves as confirmation +// from the TPM that the data in buf did not begin with TPM_GENERATED_VALUE. +// NOTE: TPM2_Hash can only accept data up to MAX_DIGEST_BUFFER in size, which +// is implementation-dependent, but guaranteed to be at least 1024 octets. +func Hash(rw io.ReadWriter, alg Algorithm, buf tpmutil.U16Bytes, hierarchy tpmutil.Handle) (digest []byte, validation *Ticket, err error) { + resp, err := runCommand(rw, TagNoSessions, CmdHash, buf, alg, hierarchy) + if err != nil { + return nil, nil, err + } + return decodeHash(resp) +} + +// HashSequenceStart starts a hash or an event sequence. If hashAlg is an +// implemented hash, then a hash sequence is started. If hashAlg is +// TPM_ALG_NULL, then an event sequence is started. +func HashSequenceStart(rw io.ReadWriter, sequenceAuth string, hashAlg Algorithm) (seqHandle tpmutil.Handle, err error) { + resp, err := runCommand(rw, TagNoSessions, CmdHashSequenceStart, tpmutil.U16Bytes(sequenceAuth), hashAlg) + if err != nil { + return 0, err + } + var handle tpmutil.Handle + _, err = tpmutil.Unpack(resp, &handle) + return handle, err +} + +func encodeSequenceUpdate(sequenceAuth string, seqHandle tpmutil.Handle, buf tpmutil.U16Bytes) ([]byte, error) { + ha, err := tpmutil.Pack(seqHandle) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(sequenceAuth)}) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(buf) + if err != nil { + return nil, err + } + return concat(ha, auth, params) +} + +// SequenceUpdate is used to add data to a hash or HMAC sequence. +func SequenceUpdate(rw io.ReadWriter, sequenceAuth string, seqHandle tpmutil.Handle, buffer []byte) error { + cmd, err := encodeSequenceUpdate(sequenceAuth, seqHandle, buffer) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdSequenceUpdate, tpmutil.RawBytes(cmd)) + return err +} + +func decodeSequenceComplete(resp []byte) ([]byte, *Ticket, error) { + var digest tpmutil.U16Bytes + var validation Ticket + var paramSize uint32 + + if _, err := tpmutil.Unpack(resp, ¶mSize, &digest, &validation); err != nil { + return nil, nil, err + } + return digest, &validation, nil +} + +func encodeSequenceComplete(sequenceAuth string, seqHandle, hierarchy tpmutil.Handle, buf tpmutil.U16Bytes) ([]byte, error) { + ha, err := tpmutil.Pack(seqHandle) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(sequenceAuth)}) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(buf, hierarchy) + if err != nil { + return nil, err + } + return concat(ha, auth, params) +} + +// SequenceComplete adds the last part of data, if any, to a hash/HMAC sequence +// and returns the result. +func SequenceComplete(rw io.ReadWriter, sequenceAuth string, seqHandle, hierarchy tpmutil.Handle, buffer []byte) (digest []byte, validation *Ticket, err error) { + cmd, err := encodeSequenceComplete(sequenceAuth, seqHandle, hierarchy, buffer) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdSequenceComplete, tpmutil.RawBytes(cmd)) + if err != nil { + return nil, nil, err + } + return decodeSequenceComplete(resp) +} + +func encodeEventSequenceComplete(auths []AuthCommand, pcrHandle, seqHandle tpmutil.Handle, buf tpmutil.U16Bytes) ([]byte, error) { + ha, err := tpmutil.Pack(pcrHandle, seqHandle) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(auths...) + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(buf) + if err != nil { + return nil, err + } + return concat(ha, auth, params) +} + +func decodeEventSequenceComplete(resp []byte) ([]*HashValue, error) { + var paramSize uint32 + var hashCount uint32 + var err error + + buf := bytes.NewBuffer(resp) + if err := tpmutil.UnpackBuf(buf, ¶mSize, &hashCount); err != nil { + return nil, err + } + + buf.Truncate(int(paramSize)) + digests := make([]*HashValue, hashCount) + for i := uint32(0); i < hashCount; i++ { + if digests[i], err = decodeHashValue(buf); err != nil { + return nil, err + } + } + + return digests, nil +} + +// EventSequenceComplete adds the last part of data, if any, to an Event +// Sequence and returns the result in a digest list. If pcrHandle references a +// PCR and not AlgNull, then the returned digest list is processed in the same +// manner as the digest list input parameter to PCRExtend() with the pcrHandle +// in each bank extended with the associated digest value. +func EventSequenceComplete(rw io.ReadWriter, pcrAuth, sequenceAuth string, pcrHandle, seqHandle tpmutil.Handle, buffer []byte) (digests []*HashValue, err error) { + auth := []AuthCommand{ + {Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(pcrAuth)}, + {Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(sequenceAuth)}, + } + cmd, err := encodeEventSequenceComplete(auth, pcrHandle, seqHandle, buffer) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdEventSequenceComplete, tpmutil.RawBytes(cmd)) + if err != nil { + return nil, err + } + return decodeEventSequenceComplete(resp) +} + +// Startup initializes a TPM (usually done by the OS). +func Startup(rw io.ReadWriter, typ StartupType) error { + _, err := runCommand(rw, TagNoSessions, CmdStartup, typ) + return err +} + +// Shutdown shuts down a TPM (usually done by the OS). +func Shutdown(rw io.ReadWriter, typ StartupType) error { + _, err := runCommand(rw, TagNoSessions, CmdShutdown, typ) + return err +} + +// nullTicket is a hard-coded null ticket of type TPMT_TK_HASHCHECK. +// It is for Sign commands that do not require the TPM to verify that the digest +// is not from data that started with TPM_GENERATED_VALUE. +var nullTicket = Ticket{ + Type: TagHashCheck, + Hierarchy: HandleNull, + Digest: tpmutil.U16Bytes{}, +} + +func encodeSign(sessionHandle, key tpmutil.Handle, password string, digest tpmutil.U16Bytes, sigScheme *SigScheme, validation *Ticket) ([]byte, error) { + ha, err := tpmutil.Pack(key) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: sessionHandle, Attributes: AttrContinueSession, Auth: []byte(password)}) + if err != nil { + return nil, err + } + d, err := tpmutil.Pack(digest) + if err != nil { + return nil, err + } + s, err := sigScheme.encode() + if err != nil { + return nil, err + } + if validation == nil { + validation = &nullTicket + } + v, err := tpmutil.Pack(validation) + if err != nil { + return nil, err + } + + return concat(ha, auth, d, s, v) +} + +func decodeSign(buf []byte) (*Signature, error) { + in := bytes.NewBuffer(buf) + var paramSize uint32 + if err := tpmutil.UnpackBuf(in, ¶mSize); err != nil { + return nil, err + } + return DecodeSignature(in) +} + +// SignWithSession computes a signature for digest using a given loaded key. Signature +// algorithm depends on the key type. Used for keys with non-password authorization policies. +// If 'key' references a Restricted Decryption key, 'validation' must be a valid hash verification +// ticket from the TPM, which can be obtained by using Hash() to hash the data with the TPM. +// If 'validation' is nil, a NULL ticket is passed to TPM2_Sign. +func SignWithSession(rw io.ReadWriter, sessionHandle, key tpmutil.Handle, password string, digest []byte, validation *Ticket, sigScheme *SigScheme) (*Signature, error) { + Cmd, err := encodeSign(sessionHandle, key, password, digest, sigScheme, validation) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdSign, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeSign(resp) +} + +// Sign computes a signature for digest using a given loaded key. Signature +// algorithm depends on the key type. +// If 'key' references a Restricted Decryption key, 'validation' must be a valid hash verification +// ticket from the TPM, which can be obtained by using Hash() to hash the data with the TPM. +// If 'validation' is nil, a NULL ticket is passed to TPM2_Sign. +func Sign(rw io.ReadWriter, key tpmutil.Handle, password string, digest []byte, validation *Ticket, sigScheme *SigScheme) (*Signature, error) { + return SignWithSession(rw, HandlePasswordSession, key, password, digest, validation, sigScheme) +} + +func encodeCertify(objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData tpmutil.U16Bytes) ([]byte, error) { + ha, err := tpmutil.Pack(object, signer) + if err != nil { + return nil, err + } + + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(objectAuth)}, AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(signerAuth)}) + if err != nil { + return nil, err + } + + scheme := SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256} + // Use signing key's scheme. + s, err := scheme.encode() + if err != nil { + return nil, err + } + data, err := tpmutil.Pack(qualifyingData) + if err != nil { + return nil, err + } + return concat(ha, auth, data, s) +} + +// This function differs from encodeCertify in that it takes the scheme to be used as an additional argument. +func encodeCertifyEx(objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData tpmutil.U16Bytes, scheme SigScheme) ([]byte, error) { + ha, err := tpmutil.Pack(object, signer) + if err != nil { + return nil, err + } + + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(objectAuth)}, AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(signerAuth)}) + if err != nil { + return nil, err + } + + s, err := scheme.encode() + if err != nil { + return nil, err + } + data, err := tpmutil.Pack(qualifyingData) + if err != nil { + return nil, err + } + return concat(ha, auth, data, s) +} + +func decodeCertify(resp []byte) ([]byte, []byte, error) { + var paramSize uint32 + var attest tpmutil.U16Bytes + + buf := bytes.NewBuffer(resp) + if err := tpmutil.UnpackBuf(buf, ¶mSize); err != nil { + return nil, nil, err + } + buf.Truncate(int(paramSize)) + if err := tpmutil.UnpackBuf(buf, &attest); err != nil { + return nil, nil, err + } + return attest, buf.Bytes(), nil +} + +// Certify generates a signature of a loaded TPM object with a signing key +// signer. This function calls encodeCertify which makes use of the hardcoded +// signing scheme {AlgRSASSA, AlgSHA256}. Returned values are: attestation data (TPMS_ATTEST), +// signature and error, if any. +func Certify(rw io.ReadWriter, objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData []byte) ([]byte, []byte, error) { + cmd, err := encodeCertify(objectAuth, signerAuth, object, signer, qualifyingData) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdCertify, tpmutil.RawBytes(cmd)) + if err != nil { + return nil, nil, err + } + return decodeCertify(resp) +} + +// CertifyEx generates a signature of a loaded TPM object with a signing key +// signer. This function differs from Certify in that it takes the scheme +// to be used as an additional argument and calls encodeCertifyEx instead +// of encodeCertify. Returned values are: attestation data (TPMS_ATTEST), +// signature and error, if any. +func CertifyEx(rw io.ReadWriter, objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData []byte, scheme SigScheme) ([]byte, []byte, error) { + cmd, err := encodeCertifyEx(objectAuth, signerAuth, object, signer, qualifyingData, scheme) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdCertify, tpmutil.RawBytes(cmd)) + if err != nil { + return nil, nil, err + } + return decodeCertify(resp) +} + +func encodeCertifyCreation(objectAuth string, object, signer tpmutil.Handle, qualifyingData, creationHash tpmutil.U16Bytes, scheme SigScheme, ticket Ticket) ([]byte, error) { + handles, err := tpmutil.Pack(signer, object) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(objectAuth)}) + if err != nil { + return nil, err + } + s, err := scheme.encode() + if err != nil { + return nil, err + } + params, err := tpmutil.Pack(qualifyingData, creationHash, tpmutil.RawBytes(s), ticket) + if err != nil { + return nil, err + } + return concat(handles, auth, params) +} + +// CertifyCreation generates a signature of a newly-created & +// loaded TPM object, using signer as the signing key. +func CertifyCreation(rw io.ReadWriter, objectAuth string, object, signer tpmutil.Handle, qualifyingData, creationHash []byte, sigScheme SigScheme, creationTicket Ticket) (attestation, signature []byte, err error) { + Cmd, err := encodeCertifyCreation(objectAuth, object, signer, qualifyingData, creationHash, sigScheme, creationTicket) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdCertifyCreation, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + return decodeCertify(resp) +} + +func runCommand(rw io.ReadWriter, tag tpmutil.Tag, Cmd tpmutil.Command, in ...interface{}) ([]byte, error) { + resp, code, err := tpmutil.RunCommand(rw, tag, Cmd, in...) + if err != nil { + return nil, err + } + if code != tpmutil.RCSuccess { + return nil, decodeResponse(code) + } + return resp, decodeResponse(code) +} + +// concat is a helper for encoding functions that separately encode handle, +// auth and param areas. A nil error is always returned, so that callers can +// simply return concat(a, b, c). +func concat(chunks ...[]byte) ([]byte, error) { + return bytes.Join(chunks, nil), nil +} + +func encodePCRExtend(pcr tpmutil.Handle, hashAlg Algorithm, hash tpmutil.RawBytes, password string) ([]byte, error) { + ha, err := tpmutil.Pack(pcr) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(password)}) + if err != nil { + return nil, err + } + pcrCount := uint32(1) + extend, err := tpmutil.Pack(pcrCount, hashAlg, hash) + if err != nil { + return nil, err + } + return concat(ha, auth, extend) +} + +// PCRExtend extends a value into the selected PCR +func PCRExtend(rw io.ReadWriter, pcr tpmutil.Handle, hashAlg Algorithm, hash []byte, password string) error { + Cmd, err := encodePCRExtend(pcr, hashAlg, hash, password) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdPCRExtend, tpmutil.RawBytes(Cmd)) + return err +} + +// ReadPCR reads the value of the given PCR. +func ReadPCR(rw io.ReadWriter, pcr int, hashAlg Algorithm) ([]byte, error) { + pcrSelection := PCRSelection{ + Hash: hashAlg, + PCRs: []int{pcr}, + } + pcrVals, err := ReadPCRs(rw, pcrSelection) + if err != nil { + return nil, fmt.Errorf("unable to read PCRs from TPM: %v", err) + } + pcrVal, present := pcrVals[pcr] + if !present { + return nil, fmt.Errorf("PCR %d value missing from response", pcr) + } + return pcrVal, nil +} + +func encodePCRReset(pcr tpmutil.Handle) ([]byte, error) { + ha, err := tpmutil.Pack(pcr) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: EmptyAuth}) + if err != nil { + return nil, err + } + return concat(ha, auth) +} + +// PCRReset resets the value of the given PCR. Usually, only PCR 16 (Debug) and +// PCR 23 (Application) are resettable on the default locality. +func PCRReset(rw io.ReadWriter, pcr tpmutil.Handle) error { + Cmd, err := encodePCRReset(pcr) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdPCRReset, tpmutil.RawBytes(Cmd)) + return err +} + +// EncryptSymmetric encrypts data using a symmetric key. +// +// WARNING: This command performs low-level cryptographic operations. +// Secure use of this command is subtle and requires careful analysis. +// Please consult with experts in cryptography for how to use it securely. +// +// The iv is the initialization vector. The iv must not be empty and its size depends on the +// details of the symmetric encryption scheme. +// +// The data may be longer than block size, EncryptSymmetric will chain +// multiple TPM calls to encrypt the entire blob. +// +// Key handle should point at SymCipher object which is a child of the key (and +// not e.g. RSA key itself). +func EncryptSymmetric(rw io.ReadWriteCloser, keyAuth string, key tpmutil.Handle, iv, data []byte) ([]byte, error) { + return encryptDecryptSymmetric(rw, keyAuth, key, iv, data, false) +} + +// DecryptSymmetric decrypts data using a symmetric key. +// +// WARNING: This command performs low-level cryptographic operations. +// Secure use of this command is subtle and requires careful analysis. +// Please consult with experts in cryptography for how to use it securely. +// +// The iv is the initialization vector. The iv must not be empty and its size +// depends on the details of the symmetric encryption scheme. +// +// The data may be longer than block size, DecryptSymmetric will chain multiple +// TPM calls to decrypt the entire blob. +// +// Key handle should point at SymCipher object which is a child of the key (and +// not e.g. RSA key itself). +func DecryptSymmetric(rw io.ReadWriteCloser, keyAuth string, key tpmutil.Handle, iv, data []byte) ([]byte, error) { + return encryptDecryptSymmetric(rw, keyAuth, key, iv, data, true) +} + +func encodeEncryptDecrypt(keyAuth string, key tpmutil.Handle, iv, data tpmutil.U16Bytes, decrypt bool) ([]byte, error) { + ha, err := tpmutil.Pack(key) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(keyAuth)}) + if err != nil { + return nil, err + } + // Use encryption key's mode. + params, err := tpmutil.Pack(decrypt, AlgNull, iv, data) + if err != nil { + return nil, err + } + return concat(ha, auth, params) +} + +func encodeEncryptDecrypt2(keyAuth string, key tpmutil.Handle, iv, data tpmutil.U16Bytes, decrypt bool) ([]byte, error) { + ha, err := tpmutil.Pack(key) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(keyAuth)}) + if err != nil { + return nil, err + } + // Use encryption key's mode. + params, err := tpmutil.Pack(data, decrypt, AlgNull, iv) + if err != nil { + return nil, err + } + return concat(ha, auth, params) +} + +func decodeEncryptDecrypt(resp []byte) ([]byte, []byte, error) { + var paramSize uint32 + var out, nextIV tpmutil.U16Bytes + if _, err := tpmutil.Unpack(resp, ¶mSize, &out, &nextIV); err != nil { + return nil, nil, err + } + return out, nextIV, nil +} + +func encryptDecryptBlockSymmetric(rw io.ReadWriteCloser, keyAuth string, key tpmutil.Handle, iv, data []byte, decrypt bool) ([]byte, []byte, error) { + Cmd, err := encodeEncryptDecrypt2(keyAuth, key, iv, data, decrypt) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagSessions, CmdEncryptDecrypt2, tpmutil.RawBytes(Cmd)) + if err != nil { + fmt0Err, ok := err.(Error) + if ok && fmt0Err.Code == RCCommandCode { + // If TPM2_EncryptDecrypt2 is not supported, fall back to + // TPM2_EncryptDecrypt. + Cmd, _ := encodeEncryptDecrypt(keyAuth, key, iv, data, decrypt) + resp, err = runCommand(rw, TagSessions, CmdEncryptDecrypt, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + } + } + if err != nil { + return nil, nil, err + } + return decodeEncryptDecrypt(resp) +} + +func encryptDecryptSymmetric(rw io.ReadWriteCloser, keyAuth string, key tpmutil.Handle, iv, data []byte, decrypt bool) ([]byte, error) { + var out, block []byte + var err error + + for rest := data; len(rest) > 0; { + if len(rest) > maxDigestBuffer { + block, rest = rest[:maxDigestBuffer], rest[maxDigestBuffer:] + } else { + block, rest = rest, nil + } + block, iv, err = encryptDecryptBlockSymmetric(rw, keyAuth, key, iv, block, decrypt) + if err != nil { + return nil, err + } + out = append(out, block...) + } + + return out, nil +} + +func encodeRSAEncrypt(key tpmutil.Handle, message tpmutil.U16Bytes, scheme *AsymScheme, label string) ([]byte, error) { + ha, err := tpmutil.Pack(key) + if err != nil { + return nil, err + } + m, err := tpmutil.Pack(message) + if err != nil { + return nil, err + } + s, err := scheme.encode() + if err != nil { + return nil, err + } + if label != "" { + label += "\x00" + } + l, err := tpmutil.Pack(tpmutil.U16Bytes(label)) + if err != nil { + return nil, err + } + return concat(ha, m, s, l) +} + +func decodeRSAEncrypt(resp []byte) ([]byte, error) { + var out tpmutil.U16Bytes + _, err := tpmutil.Unpack(resp, &out) + return out, err +} + +// RSAEncrypt performs RSA encryption in the TPM according to RFC 3447. The key must be +// a (public) key loaded into the TPM beforehand. Note that when using OAEP with a label, +// a null byte is appended to the label and the null byte is included in the padding +// scheme. +func RSAEncrypt(rw io.ReadWriter, key tpmutil.Handle, message []byte, scheme *AsymScheme, label string) ([]byte, error) { + Cmd, err := encodeRSAEncrypt(key, message, scheme, label) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagNoSessions, CmdRSAEncrypt, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeRSAEncrypt(resp) +} + +func encodeRSADecrypt(sessionHandle, key tpmutil.Handle, password string, message tpmutil.U16Bytes, scheme *AsymScheme, label string) ([]byte, error) { + ha, err := tpmutil.Pack(key) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: sessionHandle, Attributes: AttrContinueSession, Auth: []byte(password)}) + if err != nil { + return nil, err + } + m, err := tpmutil.Pack(message) + if err != nil { + return nil, err + } + s, err := scheme.encode() + if err != nil { + return nil, err + } + if label != "" { + label += "\x00" + } + l, err := tpmutil.Pack(tpmutil.U16Bytes(label)) + if err != nil { + return nil, err + } + return concat(ha, auth, m, s, l) +} + +func decodeRSADecrypt(resp []byte) ([]byte, error) { + var out tpmutil.U16Bytes + var paramSize uint32 + _, err := tpmutil.Unpack(resp, ¶mSize, &out) + return out, err +} + +// RSADecrypt performs RSA decryption in the TPM according to RFC 3447. The key must be +// a private RSA key in the TPM with FlagDecrypt set. Note that when using OAEP with a +// label, a null byte is appended to the label and the null byte is included in the +// padding scheme. +func RSADecrypt(rw io.ReadWriter, key tpmutil.Handle, password string, message []byte, scheme *AsymScheme, label string) ([]byte, error) { + return RSADecryptWithSession(rw, HandlePasswordSession, key, password, message, scheme, label) +} + +// RSADecryptWithSession performs RSA decryption in the TPM according to RFC 3447. The key must be +// a private RSA key in the TPM with FlagDecrypt set. Note that when using OAEP with a +// label, a null byte is appended to the label and the null byte is included in the +// padding scheme. +func RSADecryptWithSession(rw io.ReadWriter, sessionHandle, key tpmutil.Handle, password string, message []byte, scheme *AsymScheme, label string) ([]byte, error) { + Cmd, err := encodeRSADecrypt(sessionHandle, key, password, message, scheme, label) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdRSADecrypt, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeRSADecrypt(resp) +} + +func encodeECDHKeyGen(key tpmutil.Handle) ([]byte, error) { + return tpmutil.Pack(key) +} + +func decodeECDHKeyGen(resp []byte) (*ECPoint, *ECPoint, error) { + // Unpack z and pub as TPM2B_ECC_POINT, which is a TPMS_ECC_POINT with a total size prepended. + var z2B, pub2B tpmutil.U16Bytes + _, err := tpmutil.Unpack(resp, &z2B, &pub2B) + if err != nil { + return nil, nil, err + } + var zPoint, pubPoint ECPoint + _, err = tpmutil.Unpack(z2B, &zPoint.XRaw, &zPoint.YRaw) + if err != nil { + return nil, nil, err + } + _, err = tpmutil.Unpack(pub2B, &pubPoint.XRaw, &pubPoint.YRaw) + if err != nil { + return nil, nil, err + } + return &zPoint, &pubPoint, nil +} + +// ECDHKeyGen generates an ephemeral ECC key, calculates the ECDH point multiplcation of the +// ephemeral private key and a loaded public key, and returns the public ephemeral point along with +// the coordinates of the resulting point. +func ECDHKeyGen(rw io.ReadWriter, key tpmutil.Handle) (zPoint, pubPoint *ECPoint, err error) { + Cmd, err := encodeECDHKeyGen(key) + if err != nil { + return nil, nil, err + } + resp, err := runCommand(rw, TagNoSessions, CmdECDHKeyGen, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, nil, err + } + return decodeECDHKeyGen(resp) +} + +func encodeECDHZGen(key tpmutil.Handle, password string, inPoint ECPoint) ([]byte, error) { + ha, err := tpmutil.Pack(key) + if err != nil { + return nil, err + } + auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(password)}) + if err != nil { + return nil, err + } + p, err := tpmutil.Pack(inPoint) + if err != nil { + return nil, err + } + // Pack the TPMS_ECC_POINT as a TPM2B_ECC_POINT. + p2B, err := tpmutil.Pack(tpmutil.U16Bytes(p)) + if err != nil { + return nil, err + } + return concat(ha, auth, p2B) +} + +func decodeECDHZGen(resp []byte) (*ECPoint, error) { + var paramSize uint32 + // Unpack a TPM2B_ECC_POINT, which is a TPMS_ECC_POINT with a total size prepended. + var z2B tpmutil.U16Bytes + _, err := tpmutil.Unpack(resp, ¶mSize, &z2B) + if err != nil { + return nil, err + } + var zPoint ECPoint + _, err = tpmutil.Unpack(z2B, &zPoint.XRaw, &zPoint.YRaw) + if err != nil { + return nil, err + } + return &zPoint, nil +} + +// ECDHZGen performs ECDH point multiplication between a private key held in the TPM and a given +// public point, returning the coordinates of the resulting point. The key must have FlagDecrypt +// set. +func ECDHZGen(rw io.ReadWriter, key tpmutil.Handle, password string, inPoint ECPoint) (zPoint *ECPoint, err error) { + Cmd, err := encodeECDHZGen(key, password, inPoint) + if err != nil { + return nil, err + } + resp, err := runCommand(rw, TagSessions, CmdECDHZGen, tpmutil.RawBytes(Cmd)) + if err != nil { + return nil, err + } + return decodeECDHZGen(resp) +} + +// DictionaryAttackLockReset cancels the effect of a TPM lockout due to a number +// of successive authorization failures, by setting the lockout counter to zero. +// The command requires Lockout Authorization and only one lockoutAuth authorization +// failure is allowed for this command during a lockoutRecovery interval. +// Lockout Authorization value by default is empty and can be changed via +// a call to HierarchyChangeAuth(HandleLockout). +func DictionaryAttackLockReset(rw io.ReadWriter, auth AuthCommand) error { + ha, err := tpmutil.Pack(HandleLockout) + if err != nil { + return err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return err + } + Cmd, err := concat(ha, encodedAuth) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdDictionaryAttackLockReset, tpmutil.RawBytes(Cmd)) + return err +} + +// DictionaryAttackParameters changes the lockout parameters. +// The command requires Lockout Authorization and has same authorization policy +// as in DictionaryAttackLockReset. +func DictionaryAttackParameters(rw io.ReadWriter, auth AuthCommand, maxTries, recoveryTime, lockoutRecovery uint32) error { + ha, err := tpmutil.Pack(HandleLockout) + if err != nil { + return err + } + encodedAuth, err := encodeAuthArea(auth) + if err != nil { + return err + } + params, err := tpmutil.Pack(maxTries, recoveryTime, lockoutRecovery) + if err != nil { + return err + } + Cmd, err := concat(ha, encodedAuth, params) + if err != nil { + return err + } + _, err = runCommand(rw, TagSessions, CmdDictionaryAttackParameters, tpmutil.RawBytes(Cmd)) + return err +} + +// PolicyCommandCode indicates that the authorization will be limited to a specific command code +func PolicyCommandCode(rw io.ReadWriter, session tpmutil.Handle, cc tpmutil.Command) error { + data, err := tpmutil.Pack(session, cc) + if err != nil { + return err + } + _, err = runCommand(rw, TagNoSessions, CmdPolicyCommandCode, data) + return err +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/encoding.go b/vendor/github.com/google/go-tpm/tpmutil/encoding.go new file mode 100644 index 0000000..5983cc2 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/encoding.go @@ -0,0 +1,211 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpmutil + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "reflect" +) + +var ( + selfMarshalerType = reflect.TypeOf((*SelfMarshaler)(nil)).Elem() + handlesAreaType = reflect.TypeOf((*[]Handle)(nil)) +) + +// packWithHeader takes a header and a sequence of elements that are either of +// fixed length or slices of fixed-length types and packs them into a single +// byte array using binary.Write. It updates the CommandHeader to have the right +// length. +func packWithHeader(ch commandHeader, cmd ...interface{}) ([]byte, error) { + hdrSize := binary.Size(ch) + body, err := Pack(cmd...) + if err != nil { + return nil, fmt.Errorf("couldn't pack message body: %v", err) + } + bodySize := len(body) + ch.Size = uint32(hdrSize + bodySize) + header, err := Pack(ch) + if err != nil { + return nil, fmt.Errorf("couldn't pack message header: %v", err) + } + return append(header, body...), nil +} + +// Pack encodes a set of elements into a single byte array, using +// encoding/binary. This means that all the elements must be encodeable +// according to the rules of encoding/binary. +// +// It has one difference from encoding/binary: it encodes byte slices with a +// prepended length, to match how the TPM encodes variable-length arrays. If +// you wish to add a byte slice without length prefix, use RawBytes. +func Pack(elts ...interface{}) ([]byte, error) { + buf := new(bytes.Buffer) + if err := packType(buf, elts...); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// tryMarshal attempts to use a TPMMarshal() method defined on the type +// to pack v into buf. True is returned if the method exists and the +// marshal was attempted. +func tryMarshal(buf io.Writer, v reflect.Value) (bool, error) { + t := v.Type() + if t.Implements(selfMarshalerType) { + if v.Kind() == reflect.Ptr && v.IsNil() { + return true, fmt.Errorf("cannot call TPMMarshal on a nil pointer of type %T", v) + } + return true, v.Interface().(SelfMarshaler).TPMMarshal(buf) + } + + // We might have a non-pointer struct field, but we dont have a + // pointer with which to implement the interface. + // If the pointer of the type implements the interface, we should be + // able to construct a value to call TPMMarshal() with. + // TODO(awly): Try and avoid blowing away private data by using Addr() instead of Set() + if reflect.PtrTo(t).Implements(selfMarshalerType) { + tmp := reflect.New(t) + tmp.Elem().Set(v) + return true, tmp.Interface().(SelfMarshaler).TPMMarshal(buf) + } + + return false, nil +} + +func packValue(buf io.Writer, v reflect.Value) error { + if v.Type() == handlesAreaType { + v = v.Convert(reflect.TypeOf((*handleList)(nil))) + } + if canMarshal, err := tryMarshal(buf, v); canMarshal { + return err + } + + switch v.Kind() { + case reflect.Ptr: + if v.IsNil() { + return fmt.Errorf("cannot pack nil %s", v.Type().String()) + } + return packValue(buf, v.Elem()) + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + if err := packValue(buf, f); err != nil { + return err + } + } + default: + return binary.Write(buf, binary.BigEndian, v.Interface()) + } + return nil +} + +func packType(buf io.Writer, elts ...interface{}) error { + for _, e := range elts { + if err := packValue(buf, reflect.ValueOf(e)); err != nil { + return err + } + } + + return nil +} + +// tryUnmarshal attempts to use TPMUnmarshal() to perform the +// unpack, if the given value implements SelfMarshaler. +// True is returned if v implements SelfMarshaler & TPMUnmarshal +// was called, along with an error returned from TPMUnmarshal. +func tryUnmarshal(buf io.Reader, v reflect.Value) (bool, error) { + t := v.Type() + if t.Implements(selfMarshalerType) { + if v.Kind() == reflect.Ptr && v.IsNil() { + return true, fmt.Errorf("cannot call TPMUnmarshal on a nil pointer") + } + return true, v.Interface().(SelfMarshaler).TPMUnmarshal(buf) + } + + // We might have a non-pointer struct field, which is addressable, + // If the pointer of the type implements the interface, and the + // value is addressable, we should be able to call TPMUnmarshal(). + if v.CanAddr() && reflect.PtrTo(t).Implements(selfMarshalerType) { + return true, v.Addr().Interface().(SelfMarshaler).TPMUnmarshal(buf) + } + + return false, nil +} + +// Unpack is a convenience wrapper around UnpackBuf. Unpack returns the number +// of bytes read from b to fill elts and error, if any. +func Unpack(b []byte, elts ...interface{}) (int, error) { + buf := bytes.NewBuffer(b) + err := UnpackBuf(buf, elts...) + read := len(b) - buf.Len() + return read, err +} + +func unpackValue(buf io.Reader, v reflect.Value) error { + if v.Type() == handlesAreaType { + v = v.Convert(reflect.TypeOf((*handleList)(nil))) + } + if didUnmarshal, err := tryUnmarshal(buf, v); didUnmarshal { + return err + } + + switch v.Kind() { + case reflect.Ptr: + if v.IsNil() { + return fmt.Errorf("cannot unpack nil %s", v.Type().String()) + } + return unpackValue(buf, v.Elem()) + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + if err := unpackValue(buf, f); err != nil { + return err + } + } + return nil + default: + // binary.Read can only set pointer values, so we need to take the address. + if !v.CanAddr() { + return fmt.Errorf("cannot unpack unaddressable leaf type %q", v.Type().String()) + } + return binary.Read(buf, binary.BigEndian, v.Addr().Interface()) + } +} + +// UnpackBuf recursively unpacks types from a reader just as encoding/binary +// does under binary.BigEndian, but with one difference: it unpacks a byte +// slice by first reading an integer with lengthPrefixSize bytes, then reading +// that many bytes. It assumes that incoming values are pointers to values so +// that, e.g., underlying slices can be resized as needed. +func UnpackBuf(buf io.Reader, elts ...interface{}) error { + for _, e := range elts { + v := reflect.ValueOf(e) + if v.Kind() != reflect.Ptr { + return fmt.Errorf("non-pointer value %q passed to UnpackBuf", v.Type().String()) + } + if v.IsNil() { + return errors.New("nil pointer passed to UnpackBuf") + } + + if err := unpackValue(buf, v); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/poll_other.go b/vendor/github.com/google/go-tpm/tpmutil/poll_other.go new file mode 100644 index 0000000..ba7e062 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/poll_other.go @@ -0,0 +1,10 @@ +//go:build !linux && !darwin + +package tpmutil + +import ( + "os" +) + +// Not implemented on Windows. +func poll(_ *os.File) error { return nil } diff --git a/vendor/github.com/google/go-tpm/tpmutil/poll_unix.go b/vendor/github.com/google/go-tpm/tpmutil/poll_unix.go new file mode 100644 index 0000000..89d85d3 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/poll_unix.go @@ -0,0 +1,32 @@ +//go:build linux || darwin + +package tpmutil + +import ( + "fmt" + "os" + + "golang.org/x/sys/unix" +) + +// poll blocks until the file descriptor is ready for reading or an error occurs. +func poll(f *os.File) error { + var ( + fds = []unix.PollFd{{ + Fd: int32(f.Fd()), + Events: 0x1, // POLLIN + }} + timeout = -1 // Indefinite timeout + ) + + if _, err := unix.Poll(fds, timeout); err != nil { + return err + } + + // Revents is filled in by the kernel. + // If the expected event happened, Revents should match Events. + if fds[0].Revents != fds[0].Events { + return fmt.Errorf("unexpected poll Revents 0x%x", fds[0].Revents) + } + return nil +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/run.go b/vendor/github.com/google/go-tpm/tpmutil/run.go new file mode 100644 index 0000000..c07e3ab --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/run.go @@ -0,0 +1,113 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package tpmutil provides common utility functions for both TPM 1.2 and TPM +// 2.0 devices. +package tpmutil + +import ( + "errors" + "io" + "os" + "time" +) + +// maxTPMResponse is the largest possible response from the TPM. We need to know +// this because we don't always know the length of the TPM response, and +// /dev/tpm insists on giving it all back in a single value rather than +// returning a header and a body in separate responses. +const maxTPMResponse = 4096 + +// RunCommandRaw executes the given raw command and returns the raw response. +// Does not check the response code except to execute retry logic. +func RunCommandRaw(rw io.ReadWriter, inb []byte) ([]byte, error) { + if rw == nil { + return nil, errors.New("nil TPM handle") + } + + // f(t) = (2^t)ms, up to 2s + var backoffFac uint + var rh responseHeader + var outb []byte + + for { + if _, err := rw.Write(inb); err != nil { + return nil, err + } + + // If the TPM is a real device, it may not be ready for reading + // immediately after writing the command. Wait until the file + // descriptor is ready to be read from. + if f, ok := rw.(*os.File); ok { + if err := poll(f); err != nil { + return nil, err + } + } + + outb = make([]byte, maxTPMResponse) + outlen, err := rw.Read(outb) + if err != nil { + return nil, err + } + // Resize the buffer to match the amount read from the TPM. + outb = outb[:outlen] + + _, err = Unpack(outb, &rh) + if err != nil { + return nil, err + } + + // If TPM is busy, retry the command after waiting a few ms. + if rh.Res == RCRetry { + if backoffFac < 11 { + dur := (1 << backoffFac) * time.Millisecond + time.Sleep(dur) + backoffFac++ + } else { + return nil, err + } + } else { + break + } + } + + return outb, nil +} + +// RunCommand executes cmd with given tag and arguments. Returns TPM response +// body (without response header) and response code from the header. Returned +// error may be nil if response code is not RCSuccess; caller should check +// both. +func RunCommand(rw io.ReadWriter, tag Tag, cmd Command, in ...interface{}) ([]byte, ResponseCode, error) { + inb, err := packWithHeader(commandHeader{tag, 0, cmd}, in...) + if err != nil { + return nil, 0, err + } + + outb, err := RunCommandRaw(rw, inb) + if err != nil { + return nil, 0, err + } + + var rh responseHeader + read, err := Unpack(outb, &rh) + if err != nil { + return nil, 0, err + } + if rh.Res != RCSuccess { + return nil, rh.Res, nil + } + + return outb[read:], rh.Res, nil +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/run_other.go b/vendor/github.com/google/go-tpm/tpmutil/run_other.go new file mode 100644 index 0000000..2a142d3 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/run_other.go @@ -0,0 +1,111 @@ +//go:build !windows + +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpmutil + +import ( + "fmt" + "io" + "net" + "os" +) + +// OpenTPM opens a channel to the TPM at the given path. If the file is a +// device, then it treats it like a normal TPM device, and if the file is a +// Unix domain socket, then it opens a connection to the socket. +func OpenTPM(path string) (io.ReadWriteCloser, error) { + // If it's a regular file, then open it + var rwc io.ReadWriteCloser + fi, err := os.Stat(path) + if err != nil { + return nil, err + } + + if fi.Mode()&os.ModeDevice != 0 { + var f *os.File + f, err = os.OpenFile(path, os.O_RDWR, 0600) + if err != nil { + return nil, err + } + rwc = io.ReadWriteCloser(f) + } else if fi.Mode()&os.ModeSocket != 0 { + rwc = NewEmulatorReadWriteCloser(path) + } else { + return nil, fmt.Errorf("unsupported TPM file mode %s", fi.Mode().String()) + } + + return rwc, nil +} + +// dialer abstracts the net.Dial call so test code can provide its own net.Conn +// implementation. +type dialer func(network, path string) (net.Conn, error) + +// EmulatorReadWriteCloser manages connections with a TPM emulator over a Unix +// domain socket. These emulators often operate in a write/read/disconnect +// sequence, so the Write method always connects, and the Read method always +// closes. EmulatorReadWriteCloser is not thread safe. +type EmulatorReadWriteCloser struct { + path string + conn net.Conn + dialer dialer +} + +// NewEmulatorReadWriteCloser stores information about a Unix domain socket to +// write to and read from. +func NewEmulatorReadWriteCloser(path string) *EmulatorReadWriteCloser { + return &EmulatorReadWriteCloser{ + path: path, + dialer: net.Dial, + } +} + +// Read implements io.Reader by reading from the Unix domain socket and closing +// it. +func (erw *EmulatorReadWriteCloser) Read(p []byte) (int, error) { + // Read is always the second operation in a Write/Read sequence. + if erw.conn == nil { + return 0, fmt.Errorf("must call Write then Read in an alternating sequence") + } + n, err := erw.conn.Read(p) + erw.conn.Close() + erw.conn = nil + return n, err +} + +// Write implements io.Writer by connecting to the Unix domain socket and +// writing. +func (erw *EmulatorReadWriteCloser) Write(p []byte) (int, error) { + if erw.conn != nil { + return 0, fmt.Errorf("must call Write then Read in an alternating sequence") + } + var err error + erw.conn, err = erw.dialer("unix", erw.path) + if err != nil { + return 0, err + } + return erw.conn.Write(p) +} + +// Close implements io.Closer by closing the Unix domain socket if one is open. +func (erw *EmulatorReadWriteCloser) Close() error { + if erw.conn == nil { + return fmt.Errorf("cannot call Close when no connection is open") + } + err := erw.conn.Close() + erw.conn = nil + return err +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/run_windows.go b/vendor/github.com/google/go-tpm/tpmutil/run_windows.go new file mode 100644 index 0000000..f355b81 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/run_windows.go @@ -0,0 +1,84 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpmutil + +import ( + "io" + + "github.com/google/go-tpm/tpmutil/tbs" +) + +// winTPMBuffer is a ReadWriteCloser to access the TPM in Windows. +type winTPMBuffer struct { + context tbs.Context + outBuffer []byte +} + +// Executes the TPM command specified by commandBuffer (at Normal Priority), returning the number +// of bytes in the command and any error code returned by executing the TPM command. Command +// response can be read by calling Read(). +func (rwc *winTPMBuffer) Write(commandBuffer []byte) (int, error) { + // TPM spec defines longest possible response to be maxTPMResponse. + rwc.outBuffer = rwc.outBuffer[:maxTPMResponse] + + outBufferLen, err := rwc.context.SubmitCommand( + tbs.NormalPriority, + commandBuffer, + rwc.outBuffer, + ) + + if err != nil { + rwc.outBuffer = rwc.outBuffer[:0] + return 0, err + } + // Shrink outBuffer so it is length of response. + rwc.outBuffer = rwc.outBuffer[:outBufferLen] + return len(commandBuffer), nil +} + +// Provides TPM response from the command called in the last Write call. +func (rwc *winTPMBuffer) Read(responseBuffer []byte) (int, error) { + if len(rwc.outBuffer) == 0 { + return 0, io.EOF + } + lenCopied := copy(responseBuffer, rwc.outBuffer) + // Cut out the piece of slice which was just read out, maintaining original slice capacity. + rwc.outBuffer = append(rwc.outBuffer[:0], rwc.outBuffer[lenCopied:]...) + return lenCopied, nil +} + +func (rwc *winTPMBuffer) Close() error { + return rwc.context.Close() +} + +// OpenTPM creates a new instance of a ReadWriteCloser which can interact with a +// Windows TPM. +func OpenTPM() (io.ReadWriteCloser, error) { + tpmContext, err := tbs.CreateContext(tbs.TPMVersion20, tbs.IncludeTPM12|tbs.IncludeTPM20) + rwc := &winTPMBuffer{ + context: tpmContext, + outBuffer: make([]byte, 0, maxTPMResponse), + } + return rwc, err +} + +// FromContext creates a new instance of a ReadWriteCloser which can +// interact with a Windows TPM, using the specified TBS handle. +func FromContext(ctx tbs.Context) io.ReadWriteCloser { + return &winTPMBuffer{ + context: ctx, + outBuffer: make([]byte, 0, maxTPMResponse), + } +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/structures.go b/vendor/github.com/google/go-tpm/tpmutil/structures.go new file mode 100644 index 0000000..893b6b6 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/structures.go @@ -0,0 +1,195 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tpmutil + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" +) + +// maxBytesBufferSize sets a sane upper bound on the size of a U32Bytes +// buffer. This limit exists to prevent a maliciously large size prefix +// from resulting in a massive memory allocation, potentially causing +// an OOM condition on the system. +// We expect no buffer from a TPM to approach 1Mb in size. +const maxBytesBufferSize uint32 = 1024 * 1024 // 1Mb. + +// RawBytes is for Pack and RunCommand arguments that are already encoded. +// Compared to []byte, RawBytes will not be prepended with slice length during +// encoding. +type RawBytes []byte + +// U16Bytes is a byte slice with a 16-bit header +type U16Bytes []byte + +// TPMMarshal packs U16Bytes +func (b *U16Bytes) TPMMarshal(out io.Writer) error { + size := len([]byte(*b)) + if err := binary.Write(out, binary.BigEndian, uint16(size)); err != nil { + return err + } + + n, err := out.Write(*b) + if err != nil { + return err + } + if n != size { + return fmt.Errorf("unable to write all contents of U16Bytes") + } + return nil +} + +// TPMUnmarshal unpacks a U16Bytes +func (b *U16Bytes) TPMUnmarshal(in io.Reader) error { + var tmpSize uint16 + if err := binary.Read(in, binary.BigEndian, &tmpSize); err != nil { + return err + } + size := int(tmpSize) + + if len(*b) >= size { + *b = (*b)[:size] + } else { + *b = append(*b, make([]byte, size-len(*b))...) + } + + n, err := in.Read(*b) + if err != nil { + return err + } + if n != size { + return io.ErrUnexpectedEOF + } + return nil +} + +// U32Bytes is a byte slice with a 32-bit header +type U32Bytes []byte + +// TPMMarshal packs U32Bytes +func (b *U32Bytes) TPMMarshal(out io.Writer) error { + size := len([]byte(*b)) + if err := binary.Write(out, binary.BigEndian, uint32(size)); err != nil { + return err + } + + n, err := out.Write(*b) + if err != nil { + return err + } + if n != size { + return fmt.Errorf("unable to write all contents of U32Bytes") + } + return nil +} + +// TPMUnmarshal unpacks a U32Bytes +func (b *U32Bytes) TPMUnmarshal(in io.Reader) error { + var tmpSize uint32 + if err := binary.Read(in, binary.BigEndian, &tmpSize); err != nil { + return err + } + + if tmpSize > maxBytesBufferSize { + return bytes.ErrTooLarge + } + // We can now safely cast to an int on 32-bit or 64-bit machines + size := int(tmpSize) + + if len(*b) >= size { + *b = (*b)[:size] + } else { + *b = append(*b, make([]byte, size-len(*b))...) + } + + n, err := in.Read(*b) + if err != nil { + return err + } + if n != size { + return fmt.Errorf("unable to read all contents in to U32Bytes") + } + return nil +} + +// Tag is a command tag. +type Tag uint16 + +// Command is an identifier of a TPM command. +type Command uint32 + +// A commandHeader is the header for a TPM command. +type commandHeader struct { + Tag Tag + Size uint32 + Cmd Command +} + +// ResponseCode is a response code returned by TPM. +type ResponseCode uint32 + +// RCSuccess is response code for successful command. Identical for TPM 1.2 and +// 2.0. +const RCSuccess ResponseCode = 0x000 + +// RCRetry is response code for TPM is busy. +const RCRetry ResponseCode = 0x922 + +// A responseHeader is a header for TPM responses. +type responseHeader struct { + Tag Tag + Size uint32 + Res ResponseCode +} + +// A Handle is a reference to a TPM object. +type Handle uint32 + +// HandleValue returns the handle value. This behavior is intended to satisfy +// an interface that can be implemented by other, more complex types as well. +func (h Handle) HandleValue() uint32 { + return uint32(h) +} + +type handleList []Handle + +func (l *handleList) TPMMarshal(_ io.Writer) error { + return fmt.Errorf("TPMMarhsal on []Handle is not supported yet") +} + +func (l *handleList) TPMUnmarshal(in io.Reader) error { + var numHandles uint16 + if err := binary.Read(in, binary.BigEndian, &numHandles); err != nil { + return err + } + + // Make len(e) match size exactly. + size := int(numHandles) + if len(*l) >= size { + *l = (*l)[:size] + } else { + *l = append(*l, make([]Handle, size-len(*l))...) + } + return binary.Read(in, binary.BigEndian, *l) +} + +// SelfMarshaler allows custom types to override default encoding/decoding +// behavior in Pack, Unpack and UnpackBuf. +type SelfMarshaler interface { + TPMMarshal(out io.Writer) error + TPMUnmarshal(in io.Reader) error +} diff --git a/vendor/github.com/google/go-tpm/tpmutil/tbs/tbs_windows.go b/vendor/github.com/google/go-tpm/tpmutil/tbs/tbs_windows.go new file mode 100644 index 0000000..b23bf96 --- /dev/null +++ b/vendor/github.com/google/go-tpm/tpmutil/tbs/tbs_windows.go @@ -0,0 +1,267 @@ +// Copyright (c) 2018, Google LLC All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package tbs provides an low-level interface directly mapping to Windows +// Tbs.dll system library commands: +// https://docs.microsoft.com/en-us/windows/desktop/TBS/tpm-base-services-portal +// Public field descriptions contain links to the high-level Windows documentation. +package tbs + +import ( + "fmt" + "syscall" + "unsafe" +) + +// Context references the current TPM context +type Context uintptr + +// Version of TPM being used by the application. +type Version uint32 + +// Flag indicates TPM versions that are supported by the application. +type Flag uint32 + +// CommandPriority is used to determine which pending command to submit whenever the TPM is free. +type CommandPriority uint32 + +// Command parameters: +// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/shared/tbs.h +const ( + // https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/ns-tbs-tdtbs_context_params2 + // OR flags to use multiple. + RequestRaw Flag = 1 << iota // Add flag to request raw context + IncludeTPM12 // Add flag to support TPM 1.2 + IncludeTPM20 // Add flag to support TPM 2 + + TPMVersion12 Version = 1 // For TPM 1.2 applications + TPMVersion20 Version = 2 // For TPM 2 applications or applications using multiple TPM versions + + // https://docs.microsoft.com/en-us/windows/desktop/tbs/command-scheduling + // https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsip_submit_command#parameters + LowPriority CommandPriority = 100 // For low priority application use + NormalPriority CommandPriority = 200 // For normal priority application use + HighPriority CommandPriority = 300 // For high priority application use + SystemPriority CommandPriority = 400 // For system tasks that access the TPM + + commandLocalityZero uint32 = 0 // Windows currently only supports TBS_COMMAND_LOCALITY_ZERO. +) + +// Error is the return type of all functions in this package. +type Error uint32 + +func (err Error) Error() string { + if description, ok := errorDescriptions[err]; ok { + return fmt.Sprintf("TBS Error 0x%X: %s", uint32(err), description) + } + return fmt.Sprintf("Unrecognized TBS Error 0x%X", uint32(err)) +} + +func getError(err uintptr) error { + // tbs.dll uses 0x0 as the return value for success. + if err == 0 { + return nil + } + return Error(err) +} + +// TBS Return Codes: +// https://docs.microsoft.com/en-us/windows/desktop/TBS/tbs-return-codes +const ( + ErrInternalError Error = 0x80284001 + ErrBadParameter Error = 0x80284002 + ErrInvalidOutputPointer Error = 0x80284003 + ErrInvalidContext Error = 0x80284004 + ErrInsufficientBuffer Error = 0x80284005 + ErrIOError Error = 0x80284006 + ErrInvalidContextParam Error = 0x80284007 + ErrServiceNotRunning Error = 0x80284008 + ErrTooManyTBSContexts Error = 0x80284009 + ErrTooManyResources Error = 0x8028400A + ErrServiceStartPending Error = 0x8028400B + ErrPPINotSupported Error = 0x8028400C + ErrCommandCanceled Error = 0x8028400D + ErrBufferTooLarge Error = 0x8028400E + ErrTPMNotFound Error = 0x8028400F + ErrServiceDisabled Error = 0x80284010 + ErrNoEventLog Error = 0x80284011 + ErrAccessDenied Error = 0x80284012 + ErrProvisioningNotAllowed Error = 0x80284013 + ErrPPIFunctionUnsupported Error = 0x80284014 + ErrOwnerauthNotFound Error = 0x80284015 +) + +var errorDescriptions = map[Error]string{ + ErrInternalError: "An internal software error occurred.", + ErrBadParameter: "One or more parameter values are not valid.", + ErrInvalidOutputPointer: "A specified output pointer is bad.", + ErrInvalidContext: "The specified context handle does not refer to a valid context.", + ErrInsufficientBuffer: "The specified output buffer is too small.", + ErrIOError: "An error occurred while communicating with the TPM.", + ErrInvalidContextParam: "A context parameter that is not valid was passed when attempting to create a TBS context.", + ErrServiceNotRunning: "The TBS service is not running and could not be started.", + ErrTooManyTBSContexts: "A new context could not be created because there are too many open contexts.", + ErrTooManyResources: "A new virtual resource could not be created because there are too many open virtual resources.", + ErrServiceStartPending: "The TBS service has been started but is not yet running.", + ErrPPINotSupported: "The physical presence interface is not supported.", + ErrCommandCanceled: "The command was canceled.", + ErrBufferTooLarge: "The input or output buffer is too large.", + ErrTPMNotFound: "A compatible Trusted Platform Module (TPM) Security Device cannot be found on this computer.", + ErrServiceDisabled: "The TBS service has been disabled.", + ErrNoEventLog: "The TBS event log is not available.", + ErrAccessDenied: "The caller does not have the appropriate rights to perform the requested operation.", + ErrProvisioningNotAllowed: "The TPM provisioning action is not allowed by the specified flags.", + ErrPPIFunctionUnsupported: "The Physical Presence Interface of this firmware does not support the requested method.", + ErrOwnerauthNotFound: "The requested TPM OwnerAuth value was not found.", +} + +// Tbs.dll provides an API for making calls to the TPM: +// https://docs.microsoft.com/en-us/windows/desktop/TBS/tpm-base-services-portal +var ( + tbsDLL = syscall.NewLazyDLL("Tbs.dll") + tbsGetDeviceInfo = tbsDLL.NewProc("Tbsi_GetDeviceInfo") + tbsCreateContext = tbsDLL.NewProc("Tbsi_Context_Create") + tbsContextClose = tbsDLL.NewProc("Tbsip_Context_Close") + tbsSubmitCommand = tbsDLL.NewProc("Tbsip_Submit_Command") + tbsGetTCGLog = tbsDLL.NewProc("Tbsi_Get_TCG_Log") +) + +// Returns the address of the beginning of a slice or 0 for a nil slice. +func sliceAddress(s []byte) uintptr { + if len(s) == 0 { + return 0 + } + return uintptr(unsafe.Pointer(&(s[0]))) +} + +// DeviceInfo is TPM_DEVICE_INFO from tbs.h +type DeviceInfo struct { + StructVersion uint32 + TPMVersion Version + TPMInterfaceType uint32 + TPMImpRevision uint32 +} + +// GetDeviceInfo gets the DeviceInfo of the current TPM: +// https://docs.microsoft.com/en-us/windows/win32/api/tbs/nf-tbs-tbsi_getdeviceinfo +func GetDeviceInfo() (*DeviceInfo, error) { + info := DeviceInfo{} + // TBS_RESULT Tbsi_GetDeviceInfo( + // UINT32 Size, + // PVOID Info + // ); + if err := tbsGetDeviceInfo.Find(); err != nil { + return nil, err + } + result, _, _ := tbsGetDeviceInfo.Call( + unsafe.Sizeof(info), + uintptr(unsafe.Pointer(&info)), + ) + return &info, getError(result) +} + +// CreateContext creates a new TPM context: +// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsi_context_create +func CreateContext(version Version, flag Flag) (Context, error) { + var context Context + params := struct { + Version + Flag + }{version, flag} + // TBS_RESULT Tbsi_Context_Create( + // _In_ PCTBS_CONTEXT_PARAMS pContextParams, + // _Out_ PTBS_HCONTEXT *phContext + // ); + if err := tbsCreateContext.Find(); err != nil { + return context, err + } + result, _, _ := tbsCreateContext.Call( + uintptr(unsafe.Pointer(¶ms)), + uintptr(unsafe.Pointer(&context)), + ) + return context, getError(result) +} + +// Close closes an existing TPM context: +// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsip_context_close +func (context Context) Close() error { + // TBS_RESULT Tbsip_Context_Close( + // _In_ TBS_HCONTEXT hContext + // ); + if err := tbsContextClose.Find(); err != nil { + return err + } + result, _, _ := tbsContextClose.Call(uintptr(context)) + return getError(result) +} + +// SubmitCommand sends commandBuffer to the TPM, returning the number of bytes +// written to responseBuffer. ErrInsufficientBuffer is returned if the +// responseBuffer is too short. ErrInvalidOutputPointer is returned if the +// responseBuffer is nil. On failure, the returned length is unspecified. +// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsip_submit_command +func (context Context) SubmitCommand( + priority CommandPriority, + commandBuffer []byte, + responseBuffer []byte, +) (uint32, error) { + responseBufferLen := uint32(len(responseBuffer)) + + // TBS_RESULT Tbsip_Submit_Command( + // _In_ TBS_HCONTEXT hContext, + // _In_ TBS_COMMAND_LOCALITY Locality, + // _In_ TBS_COMMAND_PRIORITY Priority, + // _In_ const PCBYTE *pabCommand, + // _In_ UINT32 cbCommand, + // _Out_ PBYTE *pabResult, + // _Inout_ UINT32 *pcbOutput + // ); + if err := tbsSubmitCommand.Find(); err != nil { + return 0, err + } + result, _, _ := tbsSubmitCommand.Call( + uintptr(context), + uintptr(commandLocalityZero), + uintptr(priority), + sliceAddress(commandBuffer), + uintptr(len(commandBuffer)), + sliceAddress(responseBuffer), + uintptr(unsafe.Pointer(&responseBufferLen)), + ) + return responseBufferLen, getError(result) +} + +// GetTCGLog gets the system event log, returning the number of bytes written +// to logBuffer. If logBuffer is nil, the size of the TCG log is returned. +// ErrInsufficientBuffer is returned if the logBuffer is too short. On failure, +// the returned length is unspecified. +// https://docs.microsoft.com/en-us/windows/desktop/api/Tbs/nf-tbs-tbsi_get_tcg_log +func (context Context) GetTCGLog(logBuffer []byte) (uint32, error) { + logBufferLen := uint32(len(logBuffer)) + + // TBS_RESULT Tbsi_Get_TCG_Log( + // TBS_HCONTEXT hContext, + // PBYTE pOutputBuf, + // PUINT32 pOutputBufLen + // ); + if err := tbsGetTCGLog.Find(); err != nil { + return 0, err + } + result, _, _ := tbsGetTCGLog.Call( + uintptr(context), + sliceAddress(logBuffer), + uintptr(unsafe.Pointer(&logBufferLen)), + ) + return logBufferLen, getError(result) +} diff --git a/vendor/github.com/julienschmidt/httprouter/.travis.yml b/vendor/github.com/julienschmidt/httprouter/.travis.yml index 477807d..ffacfb5 100644 --- a/vendor/github.com/julienschmidt/httprouter/.travis.yml +++ b/vendor/github.com/julienschmidt/httprouter/.travis.yml @@ -1,18 +1,18 @@ sudo: false language: go go: - - 1.7 - - 1.8 - - 1.9 - - "1.10" - - tip + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + - 1.12.x + - 1.13.x + - master before_install: - - go get golang.org/x/tools/cmd/cover - go get github.com/mattn/goveralls - - go get github.com/golang/lint/golint script: - go test -v -covermode=count -coverprofile=coverage.out - go vet ./... - test -z "$(gofmt -d -s . | tee /dev/stderr)" - - test -z "$(golint ./... | tee /dev/stderr)" - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci diff --git a/vendor/github.com/julienschmidt/httprouter/LICENSE b/vendor/github.com/julienschmidt/httprouter/LICENSE index b829abc..875308f 100644 --- a/vendor/github.com/julienschmidt/httprouter/LICENSE +++ b/vendor/github.com/julienschmidt/httprouter/LICENSE @@ -1,24 +1,29 @@ -Copyright (c) 2013 Julien Schmidt. All rights reserved. +BSD 3-Clause License +Copyright (c) 2013, Julien Schmidt +All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of the contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL JULIEN SCHMIDT BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/julienschmidt/httprouter/README.md b/vendor/github.com/julienschmidt/httprouter/README.md index eabf4aa..d1e68b5 100644 --- a/vendor/github.com/julienschmidt/httprouter/README.md +++ b/vendor/github.com/julienschmidt/httprouter/README.md @@ -16,13 +16,13 @@ The router is optimized for high performance and a small memory footprint. It sc **Parameters in your routing pattern:** Stop parsing the requested URL path, just give the path segment a name and the router delivers the dynamic value to you. Because of the design of the router, path parameters are very cheap. -**Zero Garbage:** The matching and dispatching process generates zero bytes of garbage. The only heap allocations that are made are building the slice of the key-value pairs for path parameters, and building new context and request objects (the latter only in the standard `Handler`/`HandlerFunc` api). In the 3-argument API, if the request path contains no parameters not a single heap allocation is necessary. +**Zero Garbage:** The matching and dispatching process generates zero bytes of garbage. The only heap allocations that are made are building the slice of the key-value pairs for path parameters, and building new context and request objects (the latter only in the standard `Handler`/`HandlerFunc` API). In the 3-argument API, if the request path contains no parameters not a single heap allocation is necessary. **Best Performance:** [Benchmarks speak for themselves](https://github.com/julienschmidt/go-http-routing-benchmark). See below for technical details of the implementation. **No more server crashes:** You can set a [Panic handler](https://godoc.org/github.com/julienschmidt/httprouter#Router.PanicHandler) to deal with panics occurring during handling a HTTP request. The router then recovers and lets the `PanicHandler` log what happened and deliver a nice error page. -**Perfect for APIs:** The router design encourages to build sensible, hierarchical RESTful APIs. Moreover it has builtin native support for [OPTIONS requests](http://zacstewart.com/2012/04/14/http-options-method.html) and `405 Method Not Allowed` replies. +**Perfect for APIs:** The router design encourages to build sensible, hierarchical RESTful APIs. Moreover it has built-in native support for [OPTIONS requests](http://zacstewart.com/2012/04/14/http-options-method.html) and `405 Method Not Allowed` replies. Of course you can also set **custom [`NotFound`](https://godoc.org/github.com/julienschmidt/httprouter#Router.NotFound) and [`MethodNotAllowed`](https://godoc.org/github.com/julienschmidt/httprouter#Router.MethodNotAllowed) handlers** and [**serve static files**](https://godoc.org/github.com/julienschmidt/httprouter#Router.ServeFiles). @@ -37,9 +37,10 @@ package main import ( "fmt" - "github.com/julienschmidt/httprouter" "net/http" "log" + + "github.com/julienschmidt/httprouter" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { @@ -61,7 +62,9 @@ func main() { ### Named parameters -As you can see, `:name` is a *named parameter*. The values are accessible via `httprouter.Params`, which is just a slice of `httprouter.Param`s. You can get the value of a parameter either by its index in the slice, or by using the `ByName(name)` method: `:name` can be retrived by `ByName("name")`. +As you can see, `:name` is a *named parameter*. The values are accessible via `httprouter.Params`, which is just a slice of `httprouter.Param`s. You can get the value of a parameter either by its index in the slice, or by using the `ByName(name)` method: `:name` can be retrieved by `ByName("name")`. + +When using a `http.Handler` (using `router.Handler` or `http.HandlerFunc`) instead of HttpRouter's handle API using a 3rd function parameter, the named parameters are stored in the `request.Context`. See more below under [Why doesn't this work with http.Handler?](#why-doesnt-this-work-with-httphandler). Named parameters only match a single path segment: @@ -127,10 +130,41 @@ For even better scalability, the child nodes on each tree level are ordered by p ## Why doesn't this work with `http.Handler`? -**It does!** The router itself implements the `http.Handler` interface. Moreover the router provides convenient [adapters for `http.Handler`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handler)s and [`http.HandlerFunc`](https://godoc.org/github.com/julienschmidt/httprouter#Router.HandlerFunc)s which allows them to be used as a [`httprouter.Handle`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handle) when registering a route. The only disadvantage is, that no parameter values can be retrieved when a `http.Handler` or `http.HandlerFunc` is used, since there is no efficient way to pass the values with the existing function parameters. Therefore [`httprouter.Handle`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handle) has a third function parameter. +**It does!** The router itself implements the `http.Handler` interface. Moreover the router provides convenient [adapters for `http.Handler`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handler)s and [`http.HandlerFunc`](https://godoc.org/github.com/julienschmidt/httprouter#Router.HandlerFunc)s which allows them to be used as a [`httprouter.Handle`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handle) when registering a route. + +Named parameters can be accessed `request.Context`: + +```go +func Hello(w http.ResponseWriter, r *http.Request) { + params := httprouter.ParamsFromContext(r.Context()) + + fmt.Fprintf(w, "hello, %s!\n", params.ByName("name")) +} +``` + +Alternatively, one can also use `params := r.Context().Value(httprouter.ParamsKey)` instead of the helper function. Just try it out for yourself, the usage of HttpRouter is very straightforward. The package is compact and minimalistic, but also probably one of the easiest routers to set up. +## Automatic OPTIONS responses and CORS + +One might wish to modify automatic responses to OPTIONS requests, e.g. to support [CORS preflight requests](https://developer.mozilla.org/en-US/docs/Glossary/preflight_request) or to set other headers. +This can be achieved using the [`Router.GlobalOPTIONS`](https://godoc.org/github.com/julienschmidt/httprouter#Router.GlobalOPTIONS) handler: + +```go +router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Access-Control-Request-Method") != "" { + // Set CORS headers + header := w.Header() + header.Set("Access-Control-Allow-Methods", r.Header.Get("Allow")) + header.Set("Access-Control-Allow-Origin", "*") + } + + // Adjust status code to 204 + w.WriteHeader(http.StatusNoContent) +}) +``` + ## Where can I find Middleware *X*? This package just provides a very efficient request router with a few extra features. The router is just a [`http.Handler`](https://golang.org/pkg/net/http/#Handler), you can chain any http.Handler compatible middleware before the router, for example the [Gorilla handlers](http://www.gorillatoolkit.org/pkg/handlers). Or you could [just write your own](https://justinas.org/writing-http-middleware-in-go/), it's very easy! @@ -260,7 +294,7 @@ If the HttpRouter is a bit too minimalistic for you, you might try one of the fo * [kami](https://github.com/guregu/kami): A tiny web framework using x/net/context * [Medeina](https://github.com/imdario/medeina): Inspired by Ruby's Roda and Cuba * [Neko](https://github.com/rocwong/neko): A lightweight web application framework for Golang +* [pbgo](https://github.com/chai2010/pbgo): pbgo is a mini RPC/REST framework based on Protobuf * [River](https://github.com/abiosoft/river): River is a simple and lightweight REST server -* [Roxanna](https://github.com/iamthemuffinman/Roxanna): An amalgamation of httprouter, better logging, and hot reload * [siesta](https://github.com/VividCortex/siesta): Composable HTTP handlers with contexts * [xmux](https://github.com/rs/xmux): xmux is a httprouter fork on top of xhandler (net/context aware) diff --git a/vendor/github.com/julienschmidt/httprouter/params_go17.go b/vendor/github.com/julienschmidt/httprouter/params_go17.go deleted file mode 100644 index abb4209..0000000 --- a/vendor/github.com/julienschmidt/httprouter/params_go17.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.7 - -package httprouter - -import ( - "context" - "net/http" -) - -type paramsKey struct{} - -// ParamsKey is the request context key under which URL params are stored. -// -// This is only present from go 1.7. -var ParamsKey = paramsKey{} - -// Handler is an adapter which allows the usage of an http.Handler as a -// request handle. With go 1.7+, the Params will be available in the -// request context under ParamsKey. -func (r *Router) Handler(method, path string, handler http.Handler) { - r.Handle(method, path, - func(w http.ResponseWriter, req *http.Request, p Params) { - ctx := req.Context() - ctx = context.WithValue(ctx, ParamsKey, p) - req = req.WithContext(ctx) - handler.ServeHTTP(w, req) - }, - ) -} - -// ParamsFromContext pulls the URL parameters from a request context, -// or returns nil if none are present. -// -// This is only present from go 1.7. -func ParamsFromContext(ctx context.Context) Params { - p, _ := ctx.Value(ParamsKey).(Params) - return p -} diff --git a/vendor/github.com/julienschmidt/httprouter/params_legacy.go b/vendor/github.com/julienschmidt/httprouter/params_legacy.go deleted file mode 100644 index 0278a44..0000000 --- a/vendor/github.com/julienschmidt/httprouter/params_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build !go1.7 - -package httprouter - -import "net/http" - -// Handler is an adapter which allows the usage of an http.Handler as a -// request handle. With go 1.7+, the Params will be available in the -// request context under ParamsKey. -func (r *Router) Handler(method, path string, handler http.Handler) { - r.Handle(method, path, - func(w http.ResponseWriter, req *http.Request, _ Params) { - handler.ServeHTTP(w, req) - }, - ) -} diff --git a/vendor/github.com/julienschmidt/httprouter/router.go b/vendor/github.com/julienschmidt/httprouter/router.go index 558e139..599529d 100644 --- a/vendor/github.com/julienschmidt/httprouter/router.go +++ b/vendor/github.com/julienschmidt/httprouter/router.go @@ -77,7 +77,9 @@ package httprouter import ( + "context" "net/http" + "strings" ) // Handle is a function that can be registered to a route to handle HTTP @@ -107,6 +109,18 @@ func (ps Params) ByName(name string) string { return "" } +type paramsKey struct{} + +// ParamsKey is the request context key under which URL params are stored. +var ParamsKey = paramsKey{} + +// ParamsFromContext pulls the URL parameters from a request context, +// or returns nil if none are present. +func ParamsFromContext(ctx context.Context) Params { + p, _ := ctx.Value(ParamsKey).(Params) + return p +} + // Router is a http.Handler which can be used to dispatch requests to different // handler functions via configurable routes type Router struct { @@ -142,6 +156,15 @@ type Router struct { // Custom OPTIONS handlers take priority over automatic replies. HandleOPTIONS bool + // An optional http.Handler that is called on automatic OPTIONS requests. + // The handler is only called if HandleOPTIONS is true and no OPTIONS + // handler for the specific path was set. + // The "Allowed" header is set before calling the handler. + GlobalOPTIONS http.Handler + + // Cached value of global (*) allowed methods + globalAllowed string + // Configurable http.Handler which is called when no matching route is // found. If it is not set, http.NotFound is used. NotFound http.Handler @@ -175,39 +198,39 @@ func New() *Router { } } -// GET is a shortcut for router.Handle("GET", path, handle) +// GET is a shortcut for router.Handle(http.MethodGet, path, handle) func (r *Router) GET(path string, handle Handle) { - r.Handle("GET", path, handle) + r.Handle(http.MethodGet, path, handle) } -// HEAD is a shortcut for router.Handle("HEAD", path, handle) +// HEAD is a shortcut for router.Handle(http.MethodHead, path, handle) func (r *Router) HEAD(path string, handle Handle) { - r.Handle("HEAD", path, handle) + r.Handle(http.MethodHead, path, handle) } -// OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle) +// OPTIONS is a shortcut for router.Handle(http.MethodOptions, path, handle) func (r *Router) OPTIONS(path string, handle Handle) { - r.Handle("OPTIONS", path, handle) + r.Handle(http.MethodOptions, path, handle) } -// POST is a shortcut for router.Handle("POST", path, handle) +// POST is a shortcut for router.Handle(http.MethodPost, path, handle) func (r *Router) POST(path string, handle Handle) { - r.Handle("POST", path, handle) + r.Handle(http.MethodPost, path, handle) } -// PUT is a shortcut for router.Handle("PUT", path, handle) +// PUT is a shortcut for router.Handle(http.MethodPut, path, handle) func (r *Router) PUT(path string, handle Handle) { - r.Handle("PUT", path, handle) + r.Handle(http.MethodPut, path, handle) } -// PATCH is a shortcut for router.Handle("PATCH", path, handle) +// PATCH is a shortcut for router.Handle(http.MethodPatch, path, handle) func (r *Router) PATCH(path string, handle Handle) { - r.Handle("PATCH", path, handle) + r.Handle(http.MethodPatch, path, handle) } -// DELETE is a shortcut for router.Handle("DELETE", path, handle) +// DELETE is a shortcut for router.Handle(http.MethodDelete, path, handle) func (r *Router) DELETE(path string, handle Handle) { - r.Handle("DELETE", path, handle) + r.Handle(http.MethodDelete, path, handle) } // Handle registers a new request handle with the given path and method. @@ -219,7 +242,7 @@ func (r *Router) DELETE(path string, handle Handle) { // frequently used, non-standardized or custom methods (e.g. for internal // communication with a proxy). func (r *Router) Handle(method, path string, handle Handle) { - if path[0] != '/' { + if len(path) < 1 || path[0] != '/' { panic("path must begin with '/' in path '" + path + "'") } @@ -231,11 +254,29 @@ func (r *Router) Handle(method, path string, handle Handle) { if root == nil { root = new(node) r.trees[method] = root + + r.globalAllowed = r.allowed("*", "") } root.addRoute(path, handle) } +// Handler is an adapter which allows the usage of an http.Handler as a +// request handle. +// The Params are available in the request context under ParamsKey. +func (r *Router) Handler(method, path string, handler http.Handler) { + r.Handle(method, path, + func(w http.ResponseWriter, req *http.Request, p Params) { + if len(p) > 0 { + ctx := req.Context() + ctx = context.WithValue(ctx, ParamsKey, p) + req = req.WithContext(ctx) + } + handler.ServeHTTP(w, req) + }, + ) +} + // HandlerFunc is an adapter which allows the usage of an http.HandlerFunc as a // request handle. func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) { @@ -284,39 +325,51 @@ func (r *Router) Lookup(method, path string) (Handle, Params, bool) { } func (r *Router) allowed(path, reqMethod string) (allow string) { - if path == "*" { // server-wide - for method := range r.trees { - if method == "OPTIONS" { - continue - } + allowed := make([]string, 0, 9) - // add request method to list of allowed methods - if len(allow) == 0 { - allow = method - } else { - allow += ", " + method + if path == "*" { // server-wide + // empty method is used for internal calls to refresh the cache + if reqMethod == "" { + for method := range r.trees { + if method == http.MethodOptions { + continue + } + // Add request method to list of allowed methods + allowed = append(allowed, method) } + } else { + return r.globalAllowed } } else { // specific path for method := range r.trees { // Skip the requested method - we already tried this one - if method == reqMethod || method == "OPTIONS" { + if method == reqMethod || method == http.MethodOptions { continue } handle, _, _ := r.trees[method].getValue(path) if handle != nil { - // add request method to list of allowed methods - if len(allow) == 0 { - allow = method - } else { - allow += ", " + method - } + // Add request method to list of allowed methods + allowed = append(allowed, method) } } } - if len(allow) > 0 { - allow += ", OPTIONS" + + if len(allowed) > 0 { + // Add request method to list of allowed methods + allowed = append(allowed, http.MethodOptions) + + // Sort allowed methods. + // sort.Strings(allowed) unfortunately causes unnecessary allocations + // due to allowed being moved to the heap and interface conversion + for i, l := 1, len(allowed); i < l; i++ { + for j := i; j > 0 && allowed[j] < allowed[j-1]; j-- { + allowed[j], allowed[j-1] = allowed[j-1], allowed[j] + } + } + + // return as comma separated list + return strings.Join(allowed, ", ") } return } @@ -333,9 +386,9 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if handle, ps, tsr := root.getValue(path); handle != nil { handle(w, req, ps) return - } else if req.Method != "CONNECT" && path != "/" { + } else if req.Method != http.MethodConnect && path != "/" { code := 301 // Permanent redirect, request with GET method - if req.Method != "GET" { + if req.Method != http.MethodGet { // Temporary redirect, request with same method // As of Go 1.3, Go does not support status code 308. code = 307 @@ -366,27 +419,27 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { } } - if req.Method == "OPTIONS" && r.HandleOPTIONS { + if req.Method == http.MethodOptions && r.HandleOPTIONS { // Handle OPTIONS requests - if allow := r.allowed(path, req.Method); len(allow) > 0 { + if allow := r.allowed(path, http.MethodOptions); allow != "" { w.Header().Set("Allow", allow) + if r.GlobalOPTIONS != nil { + r.GlobalOPTIONS.ServeHTTP(w, req) + } return } - } else { - // Handle 405 - if r.HandleMethodNotAllowed { - if allow := r.allowed(path, req.Method); len(allow) > 0 { - w.Header().Set("Allow", allow) - if r.MethodNotAllowed != nil { - r.MethodNotAllowed.ServeHTTP(w, req) - } else { - http.Error(w, - http.StatusText(http.StatusMethodNotAllowed), - http.StatusMethodNotAllowed, - ) - } - return + } else if r.HandleMethodNotAllowed { // Handle 405 + if allow := r.allowed(path, req.Method); allow != "" { + w.Header().Set("Allow", allow) + if r.MethodNotAllowed != nil { + r.MethodNotAllowed.ServeHTTP(w, req) + } else { + http.Error(w, + http.StatusText(http.StatusMethodNotAllowed), + http.StatusMethodNotAllowed, + ) } + return } } diff --git a/vendor/github.com/julienschmidt/httprouter/tree.go b/vendor/github.com/julienschmidt/httprouter/tree.go index a8fa98b..c9fdf5b 100644 --- a/vendor/github.com/julienschmidt/httprouter/tree.go +++ b/vendor/github.com/julienschmidt/httprouter/tree.go @@ -17,6 +17,8 @@ func min(a, b int) int { return b } +const maxParamCount uint8 = ^uint8(0) + func countParams(path string) uint8 { var n uint for i := 0; i < len(path); i++ { @@ -25,9 +27,10 @@ func countParams(path string) uint8 { } n++ } - if n >= 255 { - return 255 + if n >= uint(maxParamCount) { + return maxParamCount } + return uint8(n) } @@ -45,10 +48,10 @@ type node struct { wildChild bool nType nodeType maxParams uint8 + priority uint32 indices string children []*node handle Handle - priority uint32 } // increments priority of the given child and reorders if necessary @@ -143,6 +146,8 @@ func (n *node) addRoute(path string, handle Handle) { // Check if the wildcard matches if len(path) >= len(n.path) && n.path == path[:len(n.path)] && + // Adding a child to a catchAll is not possible + n.nType != catchAll && // Check for longer wildcard, e.g. :name and :names (len(n.path) >= len(path) || path[len(n.path)] == '/') { continue walk @@ -298,6 +303,10 @@ func (n *node) insertChild(numParams uint8, path, fullPath string, handle Handle nType: catchAll, maxParams: 1, } + // update maxParams of the parent node + if n.maxParams < 1 { + n.maxParams = 1 + } n.children = []*node{child} n.indices = string(path[i]) n = child @@ -457,7 +466,6 @@ walk: // outer loop for walking the tree func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPath []byte, found bool) { return n.findCaseInsensitivePathRec( path, - strings.ToLower(path), make([]byte, 0, len(path)+1), // preallocate enough memory for new path [4]byte{}, // empty rune buffer fixTrailingSlash, @@ -481,24 +489,24 @@ func shiftNRuneBytes(rb [4]byte, n int) [4]byte { } // recursive case-insensitive lookup function used by n.findCaseInsensitivePath -func (n *node) findCaseInsensitivePathRec(path, loPath string, ciPath []byte, rb [4]byte, fixTrailingSlash bool) ([]byte, bool) { - loNPath := strings.ToLower(n.path) +func (n *node) findCaseInsensitivePathRec(path string, ciPath []byte, rb [4]byte, fixTrailingSlash bool) ([]byte, bool) { + npLen := len(n.path) walk: // outer loop for walking the tree - for len(loPath) >= len(loNPath) && (len(loNPath) == 0 || loPath[1:len(loNPath)] == loNPath[1:]) { - // add common path to result - ciPath = append(ciPath, n.path...) + for len(path) >= npLen && (npLen == 0 || strings.EqualFold(path[1:npLen], n.path[1:])) { + // add common prefix to result - if path = path[len(n.path):]; len(path) > 0 { - loOld := loPath - loPath = loPath[len(loNPath):] + oldPath := path + path = path[npLen:] + ciPath = append(ciPath, n.path...) + if len(path) > 0 { // If this node does not have a wildcard (param or catchAll) child, // we can just look up the next child node and continue to walk down // the tree if !n.wildChild { // skip rune bytes already processed - rb = shiftNRuneBytes(rb, len(loNPath)) + rb = shiftNRuneBytes(rb, npLen) if rb[0] != 0 { // old rune not finished @@ -506,7 +514,7 @@ walk: // outer loop for walking the tree if n.indices[i] == rb[0] { // continue with child node n = n.children[i] - loNPath = strings.ToLower(n.path) + npLen = len(n.path) continue walk } } @@ -518,17 +526,19 @@ walk: // outer loop for walking the tree // runes are up to 4 byte long, // -4 would definitely be another rune var off int - for max := min(len(loNPath), 3); off < max; off++ { - if i := len(loNPath) - off; utf8.RuneStart(loOld[i]) { - // read rune from cached lowercase path - rv, _ = utf8.DecodeRuneInString(loOld[i:]) + for max := min(npLen, 3); off < max; off++ { + if i := npLen - off; utf8.RuneStart(oldPath[i]) { + // read rune from cached path + rv, _ = utf8.DecodeRuneInString(oldPath[i:]) break } } // calculate lowercase bytes of current rune - utf8.EncodeRune(rb[:], rv) - // skipp already processed bytes + lo := unicode.ToLower(rv) + utf8.EncodeRune(rb[:], lo) + + // skip already processed bytes rb = shiftNRuneBytes(rb, off) for i := 0; i < len(n.indices); i++ { @@ -538,7 +548,7 @@ walk: // outer loop for walking the tree // uppercase byte and the lowercase byte might exist // as an index if out, found := n.children[i].findCaseInsensitivePathRec( - path, loPath, ciPath, rb, fixTrailingSlash, + path, ciPath, rb, fixTrailingSlash, ); found { return out, true } @@ -546,17 +556,18 @@ walk: // outer loop for walking the tree } } - // same for uppercase rune, if it differs - if up := unicode.ToUpper(rv); up != rv { + // if we found no match, the same for the uppercase rune, + // if it differs + if up := unicode.ToUpper(rv); up != lo { utf8.EncodeRune(rb[:], up) rb = shiftNRuneBytes(rb, off) - for i := 0; i < len(n.indices); i++ { + for i, c := 0, rb[0]; i < len(n.indices); i++ { // uppercase matches - if n.indices[i] == rb[0] { + if n.indices[i] == c { // continue with child node n = n.children[i] - loNPath = strings.ToLower(n.path) + npLen = len(n.path) continue walk } } @@ -585,8 +596,7 @@ walk: // outer loop for walking the tree if len(n.children) > 0 { // continue with child node n = n.children[0] - loNPath = strings.ToLower(n.path) - loPath = loPath[k:] + npLen = len(n.path) path = path[k:] continue } @@ -647,8 +657,8 @@ walk: // outer loop for walking the tree if path == "/" { return ciPath, true } - if len(loPath)+1 == len(loNPath) && loNPath[len(loPath)] == '/' && - loPath[1:] == loNPath[1:len(loPath)] && n.handle != nil { + if len(path)+1 == npLen && n.path[len(path)] == '/' && + strings.EqualFold(path[1:], n.path[1:len(path)]) && n.handle != nil { return append(ciPath, n.path...), true } } diff --git a/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/klauspost/compress/LICENSE new file mode 100644 index 0000000..87d5574 --- /dev/null +++ b/vendor/github.com/klauspost/compress/LICENSE @@ -0,0 +1,304 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2019 Klaus Post. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------ + +Files: gzhttp/* + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016-2017 The New York Times Company + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +------------------ + +Files: s2/cmd/internal/readahead/* + +The MIT License (MIT) + +Copyright (c) 2015 Klaus Post + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------- +Files: snappy/* +Files: internal/snapref/* + +Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----------------- + +Files: s2/cmd/internal/filepathx/* + +Copyright 2016 The filepathx Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go new file mode 100644 index 0000000..57d17ee --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/deflate.go @@ -0,0 +1,996 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Copyright (c) 2015 Klaus Post +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "errors" + "fmt" + "io" + "math" + + "github.com/klauspost/compress/internal/le" +) + +const ( + NoCompression = 0 + BestSpeed = 1 + BestCompression = 9 + DefaultCompression = -1 + + // HuffmanOnly disables Lempel-Ziv match searching and only performs Huffman + // entropy encoding. This mode is useful in compressing data that has + // already been compressed with an LZ style algorithm (e.g. Snappy or LZ4) + // that lacks an entropy encoder. Compression gains are achieved when + // certain bytes in the input stream occur more frequently than others. + // + // Note that HuffmanOnly produces a compressed output that is + // RFC 1951 compliant. That is, any valid DEFLATE decompressor will + // continue to be able to decompress this output. + HuffmanOnly = -2 + ConstantCompression = HuffmanOnly // compatibility alias. + + logWindowSize = 15 + windowSize = 1 << logWindowSize + windowMask = windowSize - 1 + logMaxOffsetSize = 15 // Standard DEFLATE + minMatchLength = 4 // The smallest match that the compressor looks for + maxMatchLength = 258 // The longest match for the compressor + minOffsetSize = 1 // The shortest offset that makes any sense + + // The maximum number of tokens we will encode at the time. + // Smaller sizes usually creates less optimal blocks. + // Bigger can make context switching slow. + // We use this for levels 7-9, so we make it big. + maxFlateBlockTokens = 1 << 15 + maxStoreBlockSize = 65535 + hashBits = 17 // After 17 performance degrades + hashSize = 1 << hashBits + hashMask = (1 << hashBits) - 1 + hashShift = (hashBits + minMatchLength - 1) / minMatchLength + maxHashOffset = 1 << 28 + + skipNever = math.MaxInt32 + + debugDeflate = false +) + +type compressionLevel struct { + good, lazy, nice, chain, fastSkipHashing, level int +} + +// Compression levels have been rebalanced from zlib deflate defaults +// to give a bigger spread in speed and compression. +// See https://blog.klauspost.com/rebalancing-deflate-compression-levels/ +var levels = []compressionLevel{ + {}, // 0 + // Level 1-6 uses specialized algorithm - values not used + {0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 2}, + {0, 0, 0, 0, 0, 3}, + {0, 0, 0, 0, 0, 4}, + {0, 0, 0, 0, 0, 5}, + {0, 0, 0, 0, 0, 6}, + // Levels 7-9 use increasingly more lazy matching + // and increasingly stringent conditions for "good enough". + {8, 12, 16, 24, skipNever, 7}, + {16, 30, 40, 64, skipNever, 8}, + {32, 258, 258, 1024, skipNever, 9}, +} + +// advancedState contains state for the advanced levels, with bigger hash tables, etc. +type advancedState struct { + // deflate state + length int + offset int + maxInsertIndex int + chainHead int + hashOffset int + + ii uint16 // position of last match, intended to overflow to reset. + + // input window: unprocessed data is window[index:windowEnd] + index int + hashMatch [maxMatchLength + minMatchLength]uint32 + + // Input hash chains + // hashHead[hashValue] contains the largest inputIndex with the specified hash value + // If hashHead[hashValue] is within the current window, then + // hashPrev[hashHead[hashValue] & windowMask] contains the previous index + // with the same hash value. + hashHead [hashSize]uint32 + hashPrev [windowSize]uint32 +} + +type compressor struct { + compressionLevel + + h *huffmanEncoder + w *huffmanBitWriter + + // compression algorithm + fill func(*compressor, []byte) int // copy data to window + step func(*compressor) // process window + + window []byte + windowEnd int + blockStart int // window index where current tokens start + err error + + // queued output tokens + tokens tokens + fast fastEnc + state *advancedState + + sync bool // requesting flush + byteAvailable bool // if true, still need to process window[index-1]. +} + +func (d *compressor) fillDeflate(b []byte) int { + s := d.state + if s.index >= 2*windowSize-(minMatchLength+maxMatchLength) { + // shift the window by windowSize + //copy(d.window[:], d.window[windowSize:2*windowSize]) + *(*[windowSize]byte)(d.window) = *(*[windowSize]byte)(d.window[windowSize:]) + s.index -= windowSize + d.windowEnd -= windowSize + if d.blockStart >= windowSize { + d.blockStart -= windowSize + } else { + d.blockStart = math.MaxInt32 + } + s.hashOffset += windowSize + if s.hashOffset > maxHashOffset { + delta := s.hashOffset - 1 + s.hashOffset -= delta + s.chainHead -= delta + // Iterate over slices instead of arrays to avoid copying + // the entire table onto the stack (Issue #18625). + for i, v := range s.hashPrev[:] { + if int(v) > delta { + s.hashPrev[i] = uint32(int(v) - delta) + } else { + s.hashPrev[i] = 0 + } + } + for i, v := range s.hashHead[:] { + if int(v) > delta { + s.hashHead[i] = uint32(int(v) - delta) + } else { + s.hashHead[i] = 0 + } + } + } + } + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +func (d *compressor) writeBlock(tok *tokens, index int, eof bool) error { + if index > 0 || eof { + var window []byte + if d.blockStart <= index { + window = d.window[d.blockStart:index] + } + d.blockStart = index + //d.w.writeBlock(tok, eof, window) + d.w.writeBlockDynamic(tok, eof, window, d.sync) + return d.w.err + } + return nil +} + +// writeBlockSkip writes the current block and uses the number of tokens +// to determine if the block should be stored on no matches, or +// only huffman encoded. +func (d *compressor) writeBlockSkip(tok *tokens, index int, eof bool) error { + if index > 0 || eof { + if d.blockStart <= index { + window := d.window[d.blockStart:index] + // If we removed less than a 64th of all literals + // we huffman compress the block. + if int(tok.n) > len(window)-int(tok.n>>6) { + d.w.writeBlockHuff(eof, window, d.sync) + } else { + // Write a dynamic huffman block. + d.w.writeBlockDynamic(tok, eof, window, d.sync) + } + } else { + d.w.writeBlock(tok, eof, nil) + } + d.blockStart = index + return d.w.err + } + return nil +} + +// fillWindow will fill the current window with the supplied +// dictionary and calculate all hashes. +// This is much faster than doing a full encode. +// Should only be used after a start/reset. +func (d *compressor) fillWindow(b []byte) { + // Do not fill window if we are in store-only or huffman mode. + if d.level <= 0 && d.level > -MinCustomWindowSize { + return + } + if d.fast != nil { + // encode the last data, but discard the result + if len(b) > maxMatchOffset { + b = b[len(b)-maxMatchOffset:] + } + d.fast.Encode(&d.tokens, b) + d.tokens.Reset() + return + } + s := d.state + // If we are given too much, cut it. + if len(b) > windowSize { + b = b[len(b)-windowSize:] + } + // Add all to window. + n := copy(d.window[d.windowEnd:], b) + + // Calculate 256 hashes at the time (more L1 cache hits) + loops := (n + 256 - minMatchLength) / 256 + for j := range loops { + startindex := j * 256 + end := min(startindex+256+minMatchLength-1, n) + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + + if dstSize <= 0 { + continue + } + + dst := s.hashMatch[:dstSize] + bulkHash4(tocheck, dst) + var newH uint32 + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + s.hashPrev[di&windowMask] = s.hashHead[newH] + // Set the head of the hash chain to us. + s.hashHead[newH] = uint32(di + s.hashOffset) + } + } + // Update window information. + d.windowEnd += n + s.index = n +} + +// Try to find a match starting at index whose length is greater than prevSize. +// We only look at chainCount possibilities before giving up. +// pos = s.index, prevHead = s.chainHead-s.hashOffset, prevLength=minMatchLength-1, lookahead +func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, offset int, ok bool) { + minMatchLook := min(lookahead, maxMatchLength) + + win := d.window[0 : pos+minMatchLook] + + // We quit when we get a match that's at least nice long + nice := min(d.nice, len(win)-pos) + + // If we've got a match that's good enough, only look in 1/4 the chain. + tries := d.chain + length = minMatchLength - 1 + + wEnd := win[pos+length] + wPos := win[pos:] + minIndex := max(pos-windowSize, 0) + offset = 0 + + if d.chain < 100 { + for i := prevHead; tries > 0; tries-- { + if wEnd == win[i+length] { + n := matchLen(win[i:i+minMatchLook], wPos) + if n > length { + length = n + offset = pos - i + ok = true + if n >= nice { + // The match is good enough that we don't try to find a better one. + break + } + wEnd = win[pos+n] + } + } + if i <= minIndex { + // hashPrev[i & windowMask] has already been overwritten, so stop now. + break + } + i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset + if i < minIndex { + break + } + } + return + } + + // Minimum gain to accept a match. + cGain := 4 + + // Some like it higher (CSV), some like it lower (JSON) + const baseCost = 3 + // Base is 4 bytes at with an additional cost. + // Matches must be better than this. + + for i := prevHead; tries > 0; tries-- { + if wEnd == win[i+length] { + n := matchLen(win[i:i+minMatchLook], wPos) + if n > length { + // Calculate gain. Estimate + newGain := d.h.bitLengthRaw(wPos[:n]) - int(offsetExtraBits[offsetCode(uint32(pos-i))]) - baseCost - int(lengthExtraBits[lengthCodes[(n-3)&255]]) + + //fmt.Println("gain:", newGain, "prev:", cGain, "raw:", d.h.bitLengthRaw(wPos[:n]), "this-len:", n, "prev-len:", length) + if newGain > cGain { + length = n + offset = pos - i + cGain = newGain + ok = true + if n >= nice { + // The match is good enough that we don't try to find a better one. + break + } + wEnd = win[pos+n] + } + } + } + if i <= minIndex { + // hashPrev[i & windowMask] has already been overwritten, so stop now. + break + } + i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset + if i < minIndex { + break + } + } + return +} + +func (d *compressor) writeStoredBlock(buf []byte) error { + if d.w.writeStoredHeader(len(buf), false); d.w.err != nil { + return d.w.err + } + d.w.writeBytes(buf) + return d.w.err +} + +// hash4 returns a hash representation of the first 4 bytes +// of the supplied slice. +// The caller must ensure that len(b) >= 4. +func hash4(b []byte) uint32 { + return hash4u(le.Load32(b, 0), hashBits) +} + +// hash4 returns the hash of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <32. +func hash4u(u uint32, h uint8) uint32 { + return (u * prime4bytes) >> (32 - h) +} + +// bulkHash4 will compute hashes using the same +// algorithm as hash4 +func bulkHash4(b []byte, dst []uint32) { + if len(b) < 4 { + return + } + hb := le.Load32(b, 0) + + dst[0] = hash4u(hb, hashBits) + end := len(b) - 4 + 1 + for i := 1; i < end; i++ { + hb = (hb >> 8) | uint32(b[i+3])<<24 + dst[i] = hash4u(hb, hashBits) + } +} + +func (d *compressor) initDeflate() { + d.window = make([]byte, 2*windowSize) + d.byteAvailable = false + d.err = nil + if d.state == nil { + return + } + s := d.state + s.index = 0 + s.hashOffset = 1 + s.length = minMatchLength - 1 + s.offset = 0 + s.chainHead = -1 +} + +// deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever, +// meaning it always has lazy matching on. +func (d *compressor) deflateLazy() { + s := d.state + // Sanity enables additional runtime tests. + // It's intended to be used during development + // to supplement the currently ad-hoc unit tests. + const sanity = debugDeflate + + if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync { + return + } + if d.windowEnd != s.index && d.chain > 100 { + // Get literal huffman coder. + if d.h == nil { + d.h = newHuffmanEncoder(maxFlateBlockTokens) + } + var tmp [256]uint16 + toIndex := d.window[s.index:d.windowEnd] + toIndex = toIndex[:min(len(toIndex), maxFlateBlockTokens)] + for _, v := range toIndex { + tmp[v]++ + } + d.h.generate(tmp[:], 15) + } + + s.maxInsertIndex = d.windowEnd - (minMatchLength - 1) + + for { + if sanity && s.index > d.windowEnd { + panic("index > windowEnd") + } + lookahead := d.windowEnd - s.index + if lookahead < minMatchLength+maxMatchLength { + if !d.sync { + return + } + if sanity && s.index > d.windowEnd { + panic("index > windowEnd") + } + if lookahead == 0 { + // Flush current output block if any. + if d.byteAvailable { + // There is still one pending token that needs to be flushed + d.tokens.AddLiteral(d.window[s.index-1]) + d.byteAvailable = false + } + if d.tokens.n > 0 { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + return + } + } + if s.index < s.maxInsertIndex { + // Update the hash + hash := hash4(d.window[s.index:]) + ch := s.hashHead[hash] + s.chainHead = int(ch) + s.hashPrev[s.index&windowMask] = ch + s.hashHead[hash] = uint32(s.index + s.hashOffset) + } + prevLength := s.length + prevOffset := s.offset + s.length = minMatchLength - 1 + s.offset = 0 + minIndex := max(s.index-windowSize, 0) + + if s.chainHead-s.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy { + if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, lookahead); ok { + s.length = newLength + s.offset = newOffset + } + } + + if prevLength >= minMatchLength && s.length <= prevLength { + // No better match, but check for better match at end... + // + // Skip forward a number of bytes. + // Offset of 2 seems to yield best results. 3 is sometimes better. + const checkOff = 2 + + // Check all, except full length + if prevLength < maxMatchLength-checkOff { + prevIndex := s.index - 1 + if prevIndex+prevLength < s.maxInsertIndex { + end := min(lookahead, maxMatchLength+checkOff) + end += prevIndex + + // Hash at match end. + h := hash4(d.window[prevIndex+prevLength:]) + ch2 := int(s.hashHead[h]) - s.hashOffset - prevLength + if prevIndex-ch2 != prevOffset && ch2 > minIndex+checkOff { + length := matchLen(d.window[prevIndex+checkOff:end], d.window[ch2+checkOff:]) + // It seems like a pure length metric is best. + if length > prevLength { + prevLength = length + prevOffset = prevIndex - ch2 + + // Extend back... + for i := checkOff - 1; i >= 0; i-- { + if prevLength >= maxMatchLength || d.window[prevIndex+i] != d.window[ch2+i] { + // Emit tokens we "owe" + for j := 0; j <= i; j++ { + d.tokens.AddLiteral(d.window[prevIndex+j]) + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + s.index++ + if s.index < s.maxInsertIndex { + h := hash4(d.window[s.index:]) + ch := s.hashHead[h] + s.chainHead = int(ch) + s.hashPrev[s.index&windowMask] = ch + s.hashHead[h] = uint32(s.index + s.hashOffset) + } + } + break + } else { + prevLength++ + } + } + } else if false { + // Check one further ahead. + // Only rarely better, disabled for now. + prevIndex++ + h := hash4(d.window[prevIndex+prevLength:]) + ch2 := int(s.hashHead[h]) - s.hashOffset - prevLength + if prevIndex-ch2 != prevOffset && ch2 > minIndex+checkOff { + length := matchLen(d.window[prevIndex+checkOff:end], d.window[ch2+checkOff:]) + // It seems like a pure length metric is best. + if length > prevLength+checkOff { + prevLength = length + prevOffset = prevIndex - ch2 + prevIndex-- + + // Extend back... + for i := checkOff; i >= 0; i-- { + if prevLength >= maxMatchLength || d.window[prevIndex+i] != d.window[ch2+i-1] { + // Emit tokens we "owe" + for j := 0; j <= i; j++ { + d.tokens.AddLiteral(d.window[prevIndex+j]) + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + s.index++ + if s.index < s.maxInsertIndex { + h := hash4(d.window[s.index:]) + ch := s.hashHead[h] + s.chainHead = int(ch) + s.hashPrev[s.index&windowMask] = ch + s.hashHead[h] = uint32(s.index + s.hashOffset) + } + } + break + } else { + prevLength++ + } + } + } + } + } + } + } + } + // There was a match at the previous step, and the current match is + // not better. Output the previous match. + d.tokens.AddMatch(uint32(prevLength-3), uint32(prevOffset-minOffsetSize)) + + // Insert in the hash table all strings up to the end of the match. + // index and index-1 are already inserted. If there is not enough + // lookahead, the last two strings are not inserted into the hash + // table. + newIndex := s.index + prevLength - 1 + // Calculate missing hashes + end := min(newIndex, s.maxInsertIndex) + end += minMatchLength - 1 + startindex := min(s.index+1, s.maxInsertIndex) + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + if dstSize > 0 { + dst := s.hashMatch[:dstSize] + bulkHash4(tocheck, dst) + var newH uint32 + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + s.hashPrev[di&windowMask] = s.hashHead[newH] + // Set the head of the hash chain to us. + s.hashHead[newH] = uint32(di + s.hashOffset) + } + } + + s.index = newIndex + d.byteAvailable = false + s.length = minMatchLength - 1 + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + s.ii = 0 + } else { + // Reset, if we got a match this run. + if s.length >= minMatchLength { + s.ii = 0 + } + // We have a byte waiting. Emit it. + if d.byteAvailable { + s.ii++ + d.tokens.AddLiteral(d.window[s.index-1]) + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + s.index++ + + // If we have a long run of no matches, skip additional bytes + // Resets when s.ii overflows after 64KB. + if n := int(s.ii) - d.chain; n > 0 { + n = 1 + int(n>>6) + for j := 0; j < n; j++ { + if s.index >= d.windowEnd-1 { + break + } + d.tokens.AddLiteral(d.window[s.index-1]) + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + // Index... + if s.index < s.maxInsertIndex { + h := hash4(d.window[s.index:]) + ch := s.hashHead[h] + s.chainHead = int(ch) + s.hashPrev[s.index&windowMask] = ch + s.hashHead[h] = uint32(s.index + s.hashOffset) + } + s.index++ + } + // Flush last byte + d.tokens.AddLiteral(d.window[s.index-1]) + d.byteAvailable = false + // s.length = minMatchLength - 1 // not needed, since s.ii is reset above, so it should never be > minMatchLength + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + } + } else { + s.index++ + d.byteAvailable = true + } + } + } +} + +func (d *compressor) store() { + if d.windowEnd > 0 && (d.windowEnd == maxStoreBlockSize || d.sync) { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + d.windowEnd = 0 + } +} + +// fillWindow will fill the buffer with data for huffman-only compression. +// The number of bytes copied is returned. +func (d *compressor) fillBlock(b []byte) int { + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +// storeHuff will compress and store the currently added data, +// if enough has been accumulated or we at the end of the stream. +// Any error that occurred will be in d.err +func (d *compressor) storeHuff() { + if d.windowEnd < len(d.window) && !d.sync || d.windowEnd == 0 { + return + } + d.w.writeBlockHuff(false, d.window[:d.windowEnd], d.sync) + d.err = d.w.err + d.windowEnd = 0 +} + +// storeFast will compress and store the currently added data, +// if enough has been accumulated or we at the end of the stream. +// Any error that occurred will be in d.err +func (d *compressor) storeFast() { + // We only compress if we have maxStoreBlockSize. + if d.windowEnd < len(d.window) { + if !d.sync { + return + } + // Handle extremely small sizes. + if d.windowEnd < 128 { + if d.windowEnd == 0 { + return + } + if d.windowEnd <= 32 { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + } else { + d.w.writeBlockHuff(false, d.window[:d.windowEnd], true) + d.err = d.w.err + } + d.tokens.Reset() + d.windowEnd = 0 + d.fast.Reset() + return + } + } + + d.fast.Encode(&d.tokens, d.window[:d.windowEnd]) + // If we made zero matches, store the block as is. + if d.tokens.n == 0 { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + // If we removed less than 1/16th, huffman compress the block. + } else if int(d.tokens.n) > d.windowEnd-(d.windowEnd>>4) { + d.w.writeBlockHuff(false, d.window[:d.windowEnd], d.sync) + d.err = d.w.err + } else { + d.w.writeBlockDynamic(&d.tokens, false, d.window[:d.windowEnd], d.sync) + d.err = d.w.err + } + d.tokens.Reset() + d.windowEnd = 0 +} + +// write will add input byte to the stream. +// Unless an error occurs all bytes will be consumed. +func (d *compressor) write(b []byte) (n int, err error) { + if d.err != nil { + return 0, d.err + } + n = len(b) + for len(b) > 0 { + if d.windowEnd == len(d.window) || d.sync { + d.step(d) + } + b = b[d.fill(d, b):] + if d.err != nil { + return 0, d.err + } + } + return n, d.err +} + +func (d *compressor) syncFlush() error { + d.sync = true + if d.err != nil { + return d.err + } + d.step(d) + if d.err == nil { + d.w.writeStoredHeader(0, false) + d.w.flush() + d.err = d.w.err + } + d.sync = false + return d.err +} + +func (d *compressor) init(w io.Writer, level int) (err error) { + d.w = newHuffmanBitWriter(w) + + switch { + case level == NoCompression: + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillBlock + d.step = (*compressor).store + case level == ConstantCompression: + d.w.logNewTablePenalty = 10 + d.window = make([]byte, 32<<10) + d.fill = (*compressor).fillBlock + d.step = (*compressor).storeHuff + case level == DefaultCompression: + level = 5 + fallthrough + case level >= 1 && level <= 6: + d.w.logNewTablePenalty = 7 + d.fast = newFastEnc(level) + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillBlock + d.step = (*compressor).storeFast + case 7 <= level && level <= 9: + d.w.logNewTablePenalty = 8 + d.state = &advancedState{} + d.compressionLevel = levels[level] + d.initDeflate() + d.fill = (*compressor).fillDeflate + d.step = (*compressor).deflateLazy + case -level >= MinCustomWindowSize && -level <= MaxCustomWindowSize: + d.w.logNewTablePenalty = 7 + d.fast = &fastEncL5Window{maxOffset: int32(-level), cur: maxStoreBlockSize} + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillBlock + d.step = (*compressor).storeFast + default: + return fmt.Errorf("flate: invalid compression level %d: want value in range [-2, 9]", level) + } + d.level = level + return nil +} + +// reset the state of the compressor. +func (d *compressor) reset(w io.Writer) { + d.w.reset(w) + d.sync = false + d.err = nil + // We only need to reset a few things for Snappy. + if d.fast != nil { + d.fast.Reset() + d.windowEnd = 0 + d.tokens.Reset() + return + } + switch d.compressionLevel.chain { + case 0: + // level was NoCompression or ConstantCompression. + d.windowEnd = 0 + default: + s := d.state + s.chainHead = -1 + for i := range s.hashHead { + s.hashHead[i] = 0 + } + for i := range s.hashPrev { + s.hashPrev[i] = 0 + } + s.hashOffset = 1 + s.index, d.windowEnd = 0, 0 + d.blockStart, d.byteAvailable = 0, false + d.tokens.Reset() + s.length = minMatchLength - 1 + s.offset = 0 + s.ii = 0 + s.maxInsertIndex = 0 + } +} + +func (d *compressor) close() error { + if d.err != nil { + return d.err + } + d.sync = true + d.step(d) + if d.err != nil { + return d.err + } + if d.w.writeStoredHeader(0, true); d.w.err != nil { + return d.w.err + } + d.w.flush() + d.w.reset(nil) + return d.w.err +} + +// NewWriter returns a new Writer compressing data at the given level. +// Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression); +// higher levels typically run slower but compress more. +// Level 0 (NoCompression) does not attempt any compression; it only adds the +// necessary DEFLATE framing. +// Level -1 (DefaultCompression) uses the default compression level. +// Level -2 (ConstantCompression) will use Huffman compression only, giving +// a very fast compression for all types of input, but sacrificing considerable +// compression efficiency. +// +// If level is in the range [-2, 9] then the error returned will be nil. +// Otherwise the error returned will be non-nil. +func NewWriter(w io.Writer, level int) (*Writer, error) { + var dw Writer + if err := dw.d.init(w, level); err != nil { + return nil, err + } + return &dw, nil +} + +// NewWriterDict is like NewWriter but initializes the new +// Writer with a preset dictionary. The returned Writer behaves +// as if the dictionary had been written to it without producing +// any compressed output. The compressed data written to w +// can only be decompressed by a Reader initialized with the +// same dictionary. +func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) { + zw, err := NewWriter(w, level) + if err != nil { + return nil, err + } + zw.d.fillWindow(dict) + zw.dict = append(zw.dict, dict...) // duplicate dictionary for Reset method. + return zw, err +} + +// MinCustomWindowSize is the minimum window size that can be sent to NewWriterWindow. +const MinCustomWindowSize = 32 + +// MaxCustomWindowSize is the maximum custom window that can be sent to NewWriterWindow. +const MaxCustomWindowSize = windowSize + +// NewWriterWindow returns a new Writer compressing data with a custom window size. +// windowSize must be from MinCustomWindowSize to MaxCustomWindowSize. +func NewWriterWindow(w io.Writer, windowSize int) (*Writer, error) { + if windowSize < MinCustomWindowSize { + return nil, errors.New("flate: requested window size less than MinWindowSize") + } + if windowSize > MaxCustomWindowSize { + return nil, errors.New("flate: requested window size bigger than MaxCustomWindowSize") + } + var dw Writer + if err := dw.d.init(w, -windowSize); err != nil { + return nil, err + } + return &dw, nil +} + +// A Writer takes data written to it and writes the compressed +// form of that data to an underlying writer (see NewWriter). +type Writer struct { + d compressor + dict []byte +} + +// Write writes data to w, which will eventually write the +// compressed form of data to its underlying writer. +func (w *Writer) Write(data []byte) (n int, err error) { + return w.d.write(data) +} + +// Flush flushes any pending data to the underlying writer. +// It is useful mainly in compressed network protocols, to ensure that +// a remote reader has enough data to reconstruct a packet. +// Flush does not return until the data has been written. +// Calling Flush when there is no pending data still causes the Writer +// to emit a sync marker of at least 4 bytes. +// If the underlying writer returns an error, Flush returns that error. +// +// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. +func (w *Writer) Flush() error { + // For more about flushing: + // http://www.bolet.org/~pornin/deflate-flush.html + return w.d.syncFlush() +} + +// Close flushes and closes the writer. +func (w *Writer) Close() error { + return w.d.close() +} + +// Reset discards the writer's state and makes it equivalent to +// the result of NewWriter or NewWriterDict called with dst +// and w's level and dictionary. +func (w *Writer) Reset(dst io.Writer) { + if len(w.dict) > 0 { + // w was created with NewWriterDict + w.d.reset(dst) + if dst != nil { + w.d.fillWindow(w.dict) + } + } else { + // w was created with NewWriter + w.d.reset(dst) + } +} + +// ResetDict discards the writer's state and makes it equivalent to +// the result of NewWriter or NewWriterDict called with dst +// and w's level, but sets a specific dictionary. +func (w *Writer) ResetDict(dst io.Writer, dict []byte) { + w.dict = dict + w.d.reset(dst) + w.d.fillWindow(w.dict) +} diff --git a/vendor/github.com/klauspost/compress/flate/dict_decoder.go b/vendor/github.com/klauspost/compress/flate/dict_decoder.go new file mode 100644 index 0000000..cb855ab --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/dict_decoder.go @@ -0,0 +1,181 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +// dictDecoder implements the LZ77 sliding dictionary as used in decompression. +// LZ77 decompresses data through sequences of two forms of commands: +// +// - Literal insertions: Runs of one or more symbols are inserted into the data +// stream as is. This is accomplished through the writeByte method for a +// single symbol, or combinations of writeSlice/writeMark for multiple symbols. +// Any valid stream must start with a literal insertion if no preset dictionary +// is used. +// +// - Backward copies: Runs of one or more symbols are copied from previously +// emitted data. Backward copies come as the tuple (dist, length) where dist +// determines how far back in the stream to copy from and length determines how +// many bytes to copy. Note that it is valid for the length to be greater than +// the distance. Since LZ77 uses forward copies, that situation is used to +// perform a form of run-length encoding on repeated runs of symbols. +// The writeCopy and tryWriteCopy are used to implement this command. +// +// For performance reasons, this implementation performs little to no sanity +// checks about the arguments. As such, the invariants documented for each +// method call must be respected. +type dictDecoder struct { + hist []byte // Sliding window history + + // Invariant: 0 <= rdPos <= wrPos <= len(hist) + wrPos int // Current output position in buffer + rdPos int // Have emitted hist[:rdPos] already + full bool // Has a full window length been written yet? +} + +// init initializes dictDecoder to have a sliding window dictionary of the given +// size. If a preset dict is provided, it will initialize the dictionary with +// the contents of dict. +func (dd *dictDecoder) init(size int, dict []byte) { + *dd = dictDecoder{hist: dd.hist} + + if cap(dd.hist) < size { + dd.hist = make([]byte, size) + } + dd.hist = dd.hist[:size] + + if len(dict) > len(dd.hist) { + dict = dict[len(dict)-len(dd.hist):] + } + dd.wrPos = copy(dd.hist, dict) + if dd.wrPos == len(dd.hist) { + dd.wrPos = 0 + dd.full = true + } + dd.rdPos = dd.wrPos +} + +// histSize reports the total amount of historical data in the dictionary. +func (dd *dictDecoder) histSize() int { + if dd.full { + return len(dd.hist) + } + return dd.wrPos +} + +// availRead reports the number of bytes that can be flushed by readFlush. +func (dd *dictDecoder) availRead() int { + return dd.wrPos - dd.rdPos +} + +// availWrite reports the available amount of output buffer space. +func (dd *dictDecoder) availWrite() int { + return len(dd.hist) - dd.wrPos +} + +// writeSlice returns a slice of the available buffer to write data to. +// +// This invariant will be kept: len(s) <= availWrite() +func (dd *dictDecoder) writeSlice() []byte { + return dd.hist[dd.wrPos:] +} + +// writeMark advances the writer pointer by cnt. +// +// This invariant must be kept: 0 <= cnt <= availWrite() +func (dd *dictDecoder) writeMark(cnt int) { + dd.wrPos += cnt +} + +// writeByte writes a single byte to the dictionary. +// +// This invariant must be kept: 0 < availWrite() +func (dd *dictDecoder) writeByte(c byte) { + dd.hist[dd.wrPos] = c + dd.wrPos++ +} + +// writeCopy copies a string at a given (dist, length) to the output. +// This returns the number of bytes copied and may be less than the requested +// length if the available space in the output buffer is too small. +// +// This invariant must be kept: 0 < dist <= histSize() +func (dd *dictDecoder) writeCopy(dist, length int) int { + dstBase := dd.wrPos + dstPos := dstBase + srcPos := dstPos - dist + endPos := min(dstPos+length, len(dd.hist)) + + // Copy non-overlapping section after destination position. + // + // This section is non-overlapping in that the copy length for this section + // is always less than or equal to the backwards distance. This can occur + // if a distance refers to data that wraps-around in the buffer. + // Thus, a backwards copy is performed here; that is, the exact bytes in + // the source prior to the copy is placed in the destination. + if srcPos < 0 { + srcPos += len(dd.hist) + dstPos += copy(dd.hist[dstPos:endPos], dd.hist[srcPos:]) + srcPos = 0 + } + + // Copy possibly overlapping section before destination position. + // + // This section can overlap if the copy length for this section is larger + // than the backwards distance. This is allowed by LZ77 so that repeated + // strings can be succinctly represented using (dist, length) pairs. + // Thus, a forwards copy is performed here; that is, the bytes copied is + // possibly dependent on the resulting bytes in the destination as the copy + // progresses along. This is functionally equivalent to the following: + // + // for i := 0; i < endPos-dstPos; i++ { + // dd.hist[dstPos+i] = dd.hist[srcPos+i] + // } + // dstPos = endPos + // + for dstPos < endPos { + dstPos += copy(dd.hist[dstPos:endPos], dd.hist[srcPos:dstPos]) + } + + dd.wrPos = dstPos + return dstPos - dstBase +} + +// tryWriteCopy tries to copy a string at a given (distance, length) to the +// output. This specialized version is optimized for short distances. +// +// This method is designed to be inlined for performance reasons. +// +// This invariant must be kept: 0 < dist <= histSize() +func (dd *dictDecoder) tryWriteCopy(dist, length int) int { + dstPos := dd.wrPos + endPos := dstPos + length + if dstPos < dist || endPos > len(dd.hist) { + return 0 + } + dstBase := dstPos + srcPos := dstPos - dist + + // Copy possibly overlapping section before destination position. +loop: + dstPos += copy(dd.hist[dstPos:endPos], dd.hist[srcPos:dstPos]) + if dstPos < endPos { + goto loop // Avoid for-loop so that this function can be inlined + } + + dd.wrPos = dstPos + return dstPos - dstBase +} + +// readFlush returns a slice of the historical buffer that is ready to be +// emitted to the user. The data returned by readFlush must be fully consumed +// before calling any other dictDecoder methods. +func (dd *dictDecoder) readFlush() []byte { + toRead := dd.hist[dd.rdPos:dd.wrPos] + dd.rdPos = dd.wrPos + if dd.wrPos == len(dd.hist) { + dd.wrPos, dd.rdPos = 0, 0 + dd.full = true + } + return toRead +} diff --git a/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/vendor/github.com/klauspost/compress/flate/fast_encoder.go new file mode 100644 index 0000000..791c9dc --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/fast_encoder.go @@ -0,0 +1,189 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Modified for deflate by Klaus Post (c) 2015. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "fmt" + + "github.com/klauspost/compress/internal/le" +) + +type fastEnc interface { + Encode(dst *tokens, src []byte) + Reset() +} + +func newFastEnc(level int) fastEnc { + switch level { + case 1: + return &fastEncL1{fastGen: fastGen{cur: maxStoreBlockSize}} + case 2: + return &fastEncL2{fastGen: fastGen{cur: maxStoreBlockSize}} + case 3: + return &fastEncL3{fastGen: fastGen{cur: maxStoreBlockSize}} + case 4: + return &fastEncL4{fastGen: fastGen{cur: maxStoreBlockSize}} + case 5: + return &fastEncL5{fastGen: fastGen{cur: maxStoreBlockSize}} + case 6: + return &fastEncL6{fastGen: fastGen{cur: maxStoreBlockSize}} + default: + panic("invalid level specified") + } +} + +const ( + tableBits = 15 // Bits used in the table + tableSize = 1 << tableBits // Size of the table + tableShift = 32 - tableBits // Right-shift to get the tableBits most significant bits of a uint32. + baseMatchOffset = 1 // The smallest match offset + baseMatchLength = 3 // The smallest match length per the RFC section 3.2.5 + maxMatchOffset = 1 << 15 // The largest match offset + + bTableBits = 17 // Bits used in the big tables + bTableSize = 1 << bTableBits // Size of the table + allocHistory = maxStoreBlockSize * 5 // Size to preallocate for history. + bufferReset = (1 << 31) - allocHistory - maxStoreBlockSize - 1 // Reset the buffer offset when reaching this. +) + +const ( + prime3bytes = 506832829 + prime4bytes = 2654435761 + prime5bytes = 889523592379 + prime6bytes = 227718039650203 + prime7bytes = 58295818150454627 + prime8bytes = 0xcf1bbcdcb7a56463 +) + +func load3232(b []byte, i int32) uint32 { + return le.Load32(b, i) +} + +func load6432(b []byte, i int32) uint64 { + return le.Load64(b, i) +} + +type tableEntry struct { + offset int32 +} + +// fastGen maintains the table for matches, +// and the previous byte block for level 2. +// This is the generic implementation. +type fastGen struct { + hist []byte + cur int32 +} + +func (e *fastGen) addBlock(src []byte) int32 { + // check if we have space already + if len(e.hist)+len(src) > cap(e.hist) { + if cap(e.hist) == 0 { + e.hist = make([]byte, 0, allocHistory) + } else { + if cap(e.hist) < maxMatchOffset*2 { + panic("unexpected buffer size") + } + // Move down + offset := int32(len(e.hist)) - maxMatchOffset + // copy(e.hist[0:maxMatchOffset], e.hist[offset:]) + *(*[maxMatchOffset]byte)(e.hist) = *(*[maxMatchOffset]byte)(e.hist[offset:]) + e.cur += offset + e.hist = e.hist[:maxMatchOffset] + } + } + s := int32(len(e.hist)) + e.hist = append(e.hist, src...) + return s +} + +type tableEntryPrev struct { + Cur tableEntry + Prev tableEntry +} + +// hash7 returns the hash of the lowest 7 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash7(u uint64, h uint8) uint32 { + return uint32(((u << (64 - 56)) * prime7bytes) >> ((64 - h) & reg8SizeMask64)) +} + +// hashLen returns a hash of the lowest mls bytes of with length output bits. +// mls must be >=3 and <=8. Any other value will return hash for 4 bytes. +// length should always be < 32. +// Preferably length and mls should be a constant for inlining. +func hashLen(u uint64, length, mls uint8) uint32 { + switch mls { + case 3: + return (uint32(u<<8) * prime3bytes) >> (32 - length) + case 5: + return uint32(((u << (64 - 40)) * prime5bytes) >> (64 - length)) + case 6: + return uint32(((u << (64 - 48)) * prime6bytes) >> (64 - length)) + case 7: + return uint32(((u << (64 - 56)) * prime7bytes) >> (64 - length)) + case 8: + return uint32((u * prime8bytes) >> (64 - length)) + default: + return (uint32(u) * prime4bytes) >> (32 - length) + } +} + +// matchlen will return the match length between offsets and t in src. +// The maximum length returned is maxMatchLength - 4. +// It is assumed that s > t, that t >=0 and s < len(src). +func (e *fastGen) matchlen(s, t int, src []byte) int32 { + if debugDeflate { + if t >= s { + panic(fmt.Sprint("t >=s:", t, s)) + } + if int(s) >= len(src) { + panic(fmt.Sprint("s >= len(src):", s, len(src))) + } + if t < 0 { + panic(fmt.Sprint("t < 0:", t)) + } + if s-t > maxMatchOffset { + panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) + } + } + a := src[s:min(s+maxMatchLength-4, len(src))] + b := src[t:] + return int32(matchLen(a, b)) +} + +// matchlenLong will return the match length between offsets and t in src. +// It is assumed that s > t, that t >=0 and s < len(src). +func (e *fastGen) matchlenLong(s, t int, src []byte) int32 { + if debugDeflate { + if t >= s { + panic(fmt.Sprint("t >=s:", t, s)) + } + if int(s) >= len(src) { + panic(fmt.Sprint("s >= len(src):", s, len(src))) + } + if t < 0 { + panic(fmt.Sprint("t < 0:", t)) + } + if s-t > maxMatchOffset { + panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) + } + } + return int32(matchLen(src[s:], src[t:])) +} + +// Reset the encoding table. +func (e *fastGen) Reset() { + if cap(e.hist) < allocHistory { + e.hist = make([]byte, 0, allocHistory) + } + // We offset current position so everything will be out of reach. + // If we are above the buffer reset it will be cleared anyway since len(hist) == 0. + if e.cur <= bufferReset { + e.cur += maxMatchOffset + int32(len(e.hist)) + } + e.hist = e.hist[:0] +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go new file mode 100644 index 0000000..7151140 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go @@ -0,0 +1,1174 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "fmt" + "io" + "math" + + "github.com/klauspost/compress/internal/le" +) + +const ( + // The largest offset code. + offsetCodeCount = 30 + + // The special code used to mark the end of a block. + endBlockMarker = 256 + + // The first length code. + lengthCodesStart = 257 + + // The number of codegen codes. + codegenCodeCount = 19 + badCode = 255 + + // maxPredefinedTokens is the maximum number of tokens + // where we check if fixed size is smaller. + maxPredefinedTokens = 250 + + // bufferFlushSize indicates the buffer size + // after which bytes are flushed to the writer. + // Should preferably be a multiple of 6, since + // we accumulate 6 bytes between writes to the buffer. + bufferFlushSize = 246 +) + +// Minimum length code that emits bits. +const lengthExtraBitsMinCode = 8 + +// The number of extra bits needed by length code X - LENGTH_CODES_START. +var lengthExtraBits = [32]uint8{ + /* 257 */ 0, 0, 0, + /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, + /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, + /* 280 */ 4, 5, 5, 5, 5, 0, +} + +// The length indicated by length code X - LENGTH_CODES_START. +var lengthBase = [32]uint8{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, + 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 255, +} + +// Minimum offset code that emits bits. +const offsetExtraBitsMinCode = 4 + +// offset code word extra bits. +var offsetExtraBits = [32]int8{ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, + /* extended window */ + 14, 14, +} + +var offsetCombined = [32]uint32{} + +func init() { + var offsetBase = [32]uint32{ + /* normal deflate */ + 0x000000, 0x000001, 0x000002, 0x000003, 0x000004, + 0x000006, 0x000008, 0x00000c, 0x000010, 0x000018, + 0x000020, 0x000030, 0x000040, 0x000060, 0x000080, + 0x0000c0, 0x000100, 0x000180, 0x000200, 0x000300, + 0x000400, 0x000600, 0x000800, 0x000c00, 0x001000, + 0x001800, 0x002000, 0x003000, 0x004000, 0x006000, + + /* extended window */ + 0x008000, 0x00c000, + } + + for i := range offsetCombined[:] { + // Don't use extended window values... + if offsetExtraBits[i] == 0 || offsetBase[i] > 0x006000 { + continue + } + offsetCombined[i] = uint32(offsetExtraBits[i]) | (offsetBase[i] << 8) + } +} + +// The odd order in which the codegen code sizes are written. +var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} + +type huffmanBitWriter struct { + // writer is the underlying writer. + // Do not use it directly; use the write method, which ensures + // that Write errors are sticky. + writer io.Writer + + // Data waiting to be written is bytes[0:nbytes] + // and then the low nbits of bits. + bits uint64 + nbits uint8 + nbytes uint8 + lastHuffMan bool + literalEncoding *huffmanEncoder + tmpLitEncoding *huffmanEncoder + offsetEncoding *huffmanEncoder + codegenEncoding *huffmanEncoder + err error + lastHeader int + // Set between 0 (reused block can be up to 2x the size) + logNewTablePenalty uint + bytes [256 + 8]byte + literalFreq [lengthCodesStart + 32]uint16 + offsetFreq [32]uint16 + codegenFreq [codegenCodeCount]uint16 + + // codegen must have an extra space for the final symbol. + codegen [literalCount + offsetCodeCount + 1]uint8 +} + +// Huffman reuse. +// +// The huffmanBitWriter supports reusing huffman tables and thereby combining block sections. +// +// This is controlled by several variables: +// +// If lastHeader is non-zero the Huffman table can be reused. +// This also indicates that a Huffman table has been generated that can output all +// possible symbols. +// It also indicates that an EOB has not yet been emitted, so if a new tabel is generated +// an EOB with the previous table must be written. +// +// If lastHuffMan is set, a table for outputting literals has been generated and offsets are invalid. +// +// An incoming block estimates the output size of a new table using a 'fresh' by calculating the +// optimal size and adding a penalty in 'logNewTablePenalty'. +// A Huffman table is not optimal, which is why we add a penalty, and generating a new table +// is slower both for compression and decompression. + +func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter { + return &huffmanBitWriter{ + writer: w, + literalEncoding: newHuffmanEncoder(literalCount), + tmpLitEncoding: newHuffmanEncoder(literalCount), + codegenEncoding: newHuffmanEncoder(codegenCodeCount), + offsetEncoding: newHuffmanEncoder(offsetCodeCount), + } +} + +func (w *huffmanBitWriter) reset(writer io.Writer) { + w.writer = writer + w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil + w.lastHeader = 0 + w.lastHuffMan = false +} + +func (w *huffmanBitWriter) canReuse(t *tokens) (ok bool) { + a := t.offHist[:offsetCodeCount] + b := w.offsetEncoding.codes + b = b[:len(a)] + for i, v := range a { + if v != 0 && b[i].zero() { + return false + } + } + + a = t.extraHist[:literalCount-256] + b = w.literalEncoding.codes[256:literalCount] + b = b[:len(a)] + for i, v := range a { + if v != 0 && b[i].zero() { + return false + } + } + + a = t.litHist[:256] + b = w.literalEncoding.codes[:len(a)] + for i, v := range a { + if v != 0 && b[i].zero() { + return false + } + } + return true +} + +func (w *huffmanBitWriter) flush() { + if w.err != nil { + w.nbits = 0 + return + } + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + n := w.nbytes + for w.nbits != 0 { + w.bytes[n] = byte(w.bits) + w.bits >>= 8 + if w.nbits > 8 { // Avoid underflow + w.nbits -= 8 + } else { + w.nbits = 0 + } + n++ + } + w.bits = 0 + if n > 0 { + w.write(w.bytes[:n]) + } + w.nbytes = 0 +} + +func (w *huffmanBitWriter) write(b []byte) { + if w.err != nil { + return + } + _, w.err = w.writer.Write(b) +} + +func (w *huffmanBitWriter) writeBits(b int32, nb uint8) { + w.bits |= uint64(b) << (w.nbits & 63) + w.nbits += nb + if w.nbits >= 48 { + w.writeOutBits() + } +} + +func (w *huffmanBitWriter) writeBytes(bytes []byte) { + if w.err != nil { + return + } + n := w.nbytes + if w.nbits&7 != 0 { + w.err = InternalError("writeBytes with unfinished bits") + return + } + for w.nbits != 0 { + w.bytes[n] = byte(w.bits) + w.bits >>= 8 + w.nbits -= 8 + n++ + } + if n != 0 { + w.write(w.bytes[:n]) + } + w.nbytes = 0 + w.write(bytes) +} + +// RFC 1951 3.2.7 specifies a special run-length encoding for specifying +// the literal and offset lengths arrays (which are concatenated into a single +// array). This method generates that run-length encoding. +// +// The result is written into the codegen array, and the frequencies +// of each code is written into the codegenFreq array. +// Codes 0-15 are single byte codes. Codes 16-18 are followed by additional +// information. Code badCode is an end marker +// +// numLiterals The number of literals in literalEncoding +// numOffsets The number of offsets in offsetEncoding +// litenc, offenc The literal and offset encoder to use +func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, litEnc, offEnc *huffmanEncoder) { + for i := range w.codegenFreq { + w.codegenFreq[i] = 0 + } + // Note that we are using codegen both as a temporary variable for holding + // a copy of the frequencies, and as the place where we put the result. + // This is fine because the output is always shorter than the input used + // so far. + codegen := w.codegen[:] // cache + // Copy the concatenated code sizes to codegen. Put a marker at the end. + cgnl := codegen[:numLiterals] + for i := range cgnl { + cgnl[i] = litEnc.codes[i].len() + } + + cgnl = codegen[numLiterals : numLiterals+numOffsets] + for i := range cgnl { + cgnl[i] = offEnc.codes[i].len() + } + codegen[numLiterals+numOffsets] = badCode + + size := codegen[0] + count := 1 + outIndex := 0 + for inIndex := 1; size != badCode; inIndex++ { + // INVARIANT: We have seen "count" copies of size that have not yet + // had output generated for them. + nextSize := codegen[inIndex] + if nextSize == size { + count++ + continue + } + // We need to generate codegen indicating "count" of size. + if size != 0 { + codegen[outIndex] = size + outIndex++ + w.codegenFreq[size]++ + count-- + for count >= 3 { + n := min(6, count) + codegen[outIndex] = 16 + outIndex++ + codegen[outIndex] = uint8(n - 3) + outIndex++ + w.codegenFreq[16]++ + count -= n + } + } else { + for count >= 11 { + n := min(138, count) + codegen[outIndex] = 18 + outIndex++ + codegen[outIndex] = uint8(n - 11) + outIndex++ + w.codegenFreq[18]++ + count -= n + } + if count >= 3 { + // count >= 3 && count <= 10 + codegen[outIndex] = 17 + outIndex++ + codegen[outIndex] = uint8(count - 3) + outIndex++ + w.codegenFreq[17]++ + count = 0 + } + } + count-- + for ; count >= 0; count-- { + codegen[outIndex] = size + outIndex++ + w.codegenFreq[size]++ + } + // Set up invariant for next time through the loop. + size = nextSize + count = 1 + } + // Marker indicating the end of the codegen. + codegen[outIndex] = badCode +} + +func (w *huffmanBitWriter) codegens() int { + numCodegens := len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + return numCodegens +} + +func (w *huffmanBitWriter) headerSize() (size, numCodegens int) { + numCodegens = len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + return 3 + 5 + 5 + 4 + (3 * numCodegens) + + w.codegenEncoding.bitLength(w.codegenFreq[:]) + + int(w.codegenFreq[16])*2 + + int(w.codegenFreq[17])*3 + + int(w.codegenFreq[18])*7, numCodegens +} + +// dynamicSize returns the size of dynamically encoded data in bits. +func (w *huffmanBitWriter) dynamicReuseSize(litEnc, offEnc *huffmanEncoder) (size int) { + size = litEnc.bitLength(w.literalFreq[:]) + + offEnc.bitLength(w.offsetFreq[:]) + return size +} + +// dynamicSize returns the size of dynamically encoded data in bits. +func (w *huffmanBitWriter) dynamicSize(litEnc, offEnc *huffmanEncoder, extraBits int) (size, numCodegens int) { + header, numCodegens := w.headerSize() + size = header + + litEnc.bitLength(w.literalFreq[:]) + + offEnc.bitLength(w.offsetFreq[:]) + + extraBits + return size, numCodegens +} + +// extraBitSize will return the number of bits that will be written +// as "extra" bits on matches. +func (w *huffmanBitWriter) extraBitSize() int { + total := 0 + for i, n := range w.literalFreq[257:literalCount] { + total += int(n) * int(lengthExtraBits[i&31]) + } + for i, n := range w.offsetFreq[:offsetCodeCount] { + total += int(n) * int(offsetExtraBits[i&31]) + } + return total +} + +// fixedSize returns the size of dynamically encoded data in bits. +func (w *huffmanBitWriter) fixedSize(extraBits int) int { + return 3 + + fixedLiteralEncoding.bitLength(w.literalFreq[:]) + + fixedOffsetEncoding.bitLength(w.offsetFreq[:]) + + extraBits +} + +// storedSize calculates the stored size, including header. +// The function returns the size in bits and whether the block +// fits inside a single block. +func (w *huffmanBitWriter) storedSize(in []byte) (int, bool) { + if in == nil { + return 0, false + } + if len(in) <= maxStoreBlockSize { + return (len(in) + 5) * 8, true + } + return 0, false +} + +func (w *huffmanBitWriter) writeCode(c hcode) { + // The function does not get inlined if we "& 63" the shift. + w.bits |= c.code64() << (w.nbits & 63) + w.nbits += c.len() + if w.nbits >= 48 { + w.writeOutBits() + } +} + +// writeOutBits will write bits to the buffer. +func (w *huffmanBitWriter) writeOutBits() { + bits := w.bits + w.bits >>= 48 + w.nbits -= 48 + n := w.nbytes + + // We overwrite, but faster... + le.Store64(w.bytes[:], n, bits) + n += 6 + + if n >= bufferFlushSize { + if w.err != nil { + n = 0 + return + } + w.write(w.bytes[:n]) + n = 0 + } + + w.nbytes = n +} + +// Write the header of a dynamic Huffman block to the output stream. +// +// numLiterals The number of literals specified in codegen +// numOffsets The number of offsets specified in codegen +// numCodegens The number of codegens used in codegen +func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) { + if w.err != nil { + return + } + var firstBits int32 = 4 + if isEof { + firstBits = 5 + } + w.writeBits(firstBits, 3) + w.writeBits(int32(numLiterals-257), 5) + w.writeBits(int32(numOffsets-1), 5) + w.writeBits(int32(numCodegens-4), 4) + + for i := range numCodegens { + value := uint(w.codegenEncoding.codes[codegenOrder[i]].len()) + w.writeBits(int32(value), 3) + } + + i := 0 + for { + var codeWord = uint32(w.codegen[i]) + i++ + if codeWord == badCode { + break + } + w.writeCode(w.codegenEncoding.codes[codeWord]) + + switch codeWord { + case 16: + w.writeBits(int32(w.codegen[i]), 2) + i++ + case 17: + w.writeBits(int32(w.codegen[i]), 3) + i++ + case 18: + w.writeBits(int32(w.codegen[i]), 7) + i++ + } + } +} + +// writeStoredHeader will write a stored header. +// If the stored block is only used for EOF, +// it is replaced with a fixed huffman block. +func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) { + if w.err != nil { + return + } + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + + // To write EOF, use a fixed encoding block. 10 bits instead of 5 bytes. + if length == 0 && isEof { + w.writeFixedHeader(isEof) + // EOB: 7 bits, value: 0 + w.writeBits(0, 7) + w.flush() + return + } + + var flag int32 + if isEof { + flag = 1 + } + w.writeBits(flag, 3) + w.flush() + w.writeBits(int32(length), 16) + w.writeBits(int32(^uint16(length)), 16) +} + +func (w *huffmanBitWriter) writeFixedHeader(isEof bool) { + if w.err != nil { + return + } + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + + // Indicate that we are a fixed Huffman block + var value int32 = 2 + if isEof { + value = 3 + } + w.writeBits(value, 3) +} + +// writeBlock will write a block of tokens with the smallest encoding. +// The original input can be supplied, and if the huffman encoded data +// is larger than the original bytes, the data will be written as a +// stored block. +// If the input is nil, the tokens will always be Huffman encoded. +func (w *huffmanBitWriter) writeBlock(tokens *tokens, eof bool, input []byte) { + if w.err != nil { + return + } + + tokens.AddEOB() + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + numLiterals, numOffsets := w.indexTokens(tokens, false) + w.generate() + var extraBits int + storedSize, storable := w.storedSize(input) + if storable { + extraBits = w.extraBitSize() + } + + // Figure out smallest code. + // Fixed Huffman baseline. + var literalEncoding = fixedLiteralEncoding + var offsetEncoding = fixedOffsetEncoding + var size = math.MaxInt32 + if tokens.n < maxPredefinedTokens { + size = w.fixedSize(extraBits) + } + + // Dynamic Huffman? + var numCodegens int + + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding) + w.codegenEncoding.generate(w.codegenFreq[:], 7) + dynamicSize, numCodegens := w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits) + + if dynamicSize < size { + size = dynamicSize + literalEncoding = w.literalEncoding + offsetEncoding = w.offsetEncoding + } + + // Stored bytes? + if storable && storedSize <= size { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + + // Huffman. + if literalEncoding == fixedLiteralEncoding { + w.writeFixedHeader(eof) + } else { + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + } + + // Write the tokens. + w.writeTokens(tokens.Slice(), literalEncoding.codes, offsetEncoding.codes) +} + +// writeBlockDynamic encodes a block using a dynamic Huffman table. +// This should be used if the symbols used have a disproportionate +// histogram distribution. +// If input is supplied and the compression savings are below 1/16th of the +// input size the block is stored. +func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []byte, sync bool) { + if w.err != nil { + return + } + + sync = sync || eof + if sync { + tokens.AddEOB() + } + + // We cannot reuse pure huffman table, and must mark as EOF. + if (w.lastHuffMan || eof) && w.lastHeader > 0 { + // We will not try to reuse. + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + w.lastHuffMan = false + } + + // fillReuse enables filling of empty values. + // This will make encodings always reusable without testing. + // However, this does not appear to benefit on most cases. + const fillReuse = false + + // Check if we can reuse... + if !fillReuse && w.lastHeader > 0 && !w.canReuse(tokens) { + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + + numLiterals, numOffsets := w.indexTokens(tokens, true) + extraBits := 0 + ssize, storable := w.storedSize(input) + + const usePrefs = true + if storable || w.lastHeader > 0 { + extraBits = w.extraBitSize() + } + + var size int + + // Check if we should reuse. + if w.lastHeader > 0 { + // Estimate size for using a new table. + // Use the previous header size as the best estimate. + newSize := w.lastHeader + tokens.EstimatedBits() + newSize += int(w.literalEncoding.codes[endBlockMarker].len()) + newSize>>w.logNewTablePenalty + + // The estimated size is calculated as an optimal table. + // We add a penalty to make it more realistic and re-use a bit more. + reuseSize := w.dynamicReuseSize(w.literalEncoding, w.offsetEncoding) + extraBits + + // Check if a new table is better. + if newSize < reuseSize { + // Write the EOB we owe. + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + size = newSize + w.lastHeader = 0 + } else { + size = reuseSize + } + + if tokens.n < maxPredefinedTokens { + if preSize := w.fixedSize(extraBits) + 7; usePrefs && preSize < size { + // Check if we get a reasonable size decrease. + if storable && ssize <= size { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + w.writeFixedHeader(eof) + if !sync { + tokens.AddEOB() + } + w.writeTokens(tokens.Slice(), fixedLiteralEncoding.codes, fixedOffsetEncoding.codes) + return + } + } + // Check if we get a reasonable size decrease. + if storable && ssize <= size { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + } + + // We want a new block/table + if w.lastHeader == 0 { + if fillReuse && !sync { + w.fillTokens() + numLiterals, numOffsets = maxNumLit, maxNumDist + } else { + w.literalFreq[endBlockMarker] = 1 + } + + w.generate() + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding) + w.codegenEncoding.generate(w.codegenFreq[:], 7) + + var numCodegens int + if fillReuse && !sync { + // Reindex for accurate size... + w.indexTokens(tokens, true) + } + size, numCodegens = w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits) + + // Store predefined, if we don't get a reasonable improvement. + if tokens.n < maxPredefinedTokens { + if preSize := w.fixedSize(extraBits); usePrefs && preSize <= size { + // Store bytes, if we don't get an improvement. + if storable && ssize <= preSize { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + w.writeFixedHeader(eof) + if !sync { + tokens.AddEOB() + } + w.writeTokens(tokens.Slice(), fixedLiteralEncoding.codes, fixedOffsetEncoding.codes) + return + } + } + + if storable && ssize <= size { + // Store bytes, if we don't get an improvement. + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + + // Write Huffman table. + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + if !sync { + w.lastHeader, _ = w.headerSize() + } + w.lastHuffMan = false + } + + if sync { + w.lastHeader = 0 + } + // Write the tokens. + w.writeTokens(tokens.Slice(), w.literalEncoding.codes, w.offsetEncoding.codes) +} + +func (w *huffmanBitWriter) fillTokens() { + for i, v := range w.literalFreq[:literalCount] { + if v == 0 { + w.literalFreq[i] = 1 + } + } + for i, v := range w.offsetFreq[:offsetCodeCount] { + if v == 0 { + w.offsetFreq[i] = 1 + } + } +} + +// indexTokens indexes a slice of tokens, and updates +// literalFreq and offsetFreq, and generates literalEncoding +// and offsetEncoding. +// The number of literal and offset tokens is returned. +func (w *huffmanBitWriter) indexTokens(t *tokens, alwaysEOB bool) (numLiterals, numOffsets int) { + //copy(w.literalFreq[:], t.litHist[:]) + *(*[256]uint16)(w.literalFreq[:]) = t.litHist + //copy(w.literalFreq[256:], t.extraHist[:]) + *(*[32]uint16)(w.literalFreq[256:]) = t.extraHist + w.offsetFreq = t.offHist + + if t.n == 0 { + return + } + if alwaysEOB { + w.literalFreq[endBlockMarker] = 1 + } + + // get the number of literals + numLiterals = len(w.literalFreq) + for w.literalFreq[numLiterals-1] == 0 { + numLiterals-- + } + // get the number of offsets + numOffsets = len(w.offsetFreq) + for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 { + numOffsets-- + } + if numOffsets == 0 { + // We haven't found a single match. If we want to go with the dynamic encoding, + // we should count at least one offset to be sure that the offset huffman tree could be encoded. + w.offsetFreq[0] = 1 + numOffsets = 1 + } + return +} + +func (w *huffmanBitWriter) generate() { + w.literalEncoding.generate(w.literalFreq[:literalCount], 15) + w.offsetEncoding.generate(w.offsetFreq[:offsetCodeCount], 15) +} + +// writeTokens writes a slice of tokens to the output. +// codes for literal and offset encoding must be supplied. +func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) { + if w.err != nil { + return + } + if len(tokens) == 0 { + return + } + + // Only last token should be endBlockMarker. + var deferEOB bool + if tokens[len(tokens)-1] == endBlockMarker { + tokens = tokens[:len(tokens)-1] + deferEOB = true + } + + // Create slices up to the next power of two to avoid bounds checks. + lits := leCodes[:256] + offs := oeCodes[:32] + lengths := leCodes[lengthCodesStart:] + lengths = lengths[:32] + + // Go 1.16 LOVES having these on stack. + bits, nbits, nbytes := w.bits, w.nbits, w.nbytes + + for _, t := range tokens { + if t < 256 { + //w.writeCode(lits[t.literal()]) + c := lits[t] + bits |= c.code64() << (nbits & 63) + nbits += c.len() + if nbits >= 48 { + le.Store64(w.bytes[:], nbytes, bits) + bits >>= 48 + nbits -= 48 + nbytes += 6 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + } + continue + } + + // Write the length + length := t.length() + lengthCode := lengthCode(length) & 31 + if false { + w.writeCode(lengths[lengthCode]) + } else { + // inlined + c := lengths[lengthCode] + bits |= c.code64() << (nbits & 63) + nbits += c.len() + if nbits >= 48 { + le.Store64(w.bytes[:], nbytes, bits) + bits >>= 48 + nbits -= 48 + nbytes += 6 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + } + } + + if lengthCode >= lengthExtraBitsMinCode { + extraLengthBits := lengthExtraBits[lengthCode] + //w.writeBits(extraLength, extraLengthBits) + extraLength := int32(length - lengthBase[lengthCode]) + bits |= uint64(extraLength) << (nbits & 63) + nbits += extraLengthBits + if nbits >= 48 { + le.Store64(w.bytes[:], nbytes, bits) + bits >>= 48 + nbits -= 48 + nbytes += 6 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + } + } + // Write the offset + offset := t.offset() + offsetCode := (offset >> 16) & 31 + if false { + w.writeCode(offs[offsetCode]) + } else { + // inlined + c := offs[offsetCode] + bits |= c.code64() << (nbits & 63) + nbits += c.len() + if nbits >= 48 { + le.Store64(w.bytes[:], nbytes, bits) + bits >>= 48 + nbits -= 48 + nbytes += 6 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + } + } + + if offsetCode >= offsetExtraBitsMinCode { + offsetComb := offsetCombined[offsetCode] + //w.writeBits(extraOffset, extraOffsetBits) + bits |= uint64((offset-(offsetComb>>8))&matchOffsetOnlyMask) << (nbits & 63) + nbits += uint8(offsetComb) + if nbits >= 48 { + le.Store64(w.bytes[:], nbytes, bits) + bits >>= 48 + nbits -= 48 + nbytes += 6 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + } + } + } + // Restore... + w.bits, w.nbits, w.nbytes = bits, nbits, nbytes + + if deferEOB { + w.writeCode(leCodes[endBlockMarker]) + } +} + +// huffOffset is a static offset encoder used for huffman only encoding. +// It can be reused since we will not be encoding offset values. +var huffOffset *huffmanEncoder + +func init() { + w := newHuffmanBitWriter(nil) + w.offsetFreq[0] = 1 + huffOffset = newHuffmanEncoder(offsetCodeCount) + huffOffset.generate(w.offsetFreq[:offsetCodeCount], 15) +} + +// writeBlockHuff encodes a block of bytes as either +// Huffman encoded literals or uncompressed bytes if the +// results only gains very little from compression. +func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) { + if w.err != nil { + return + } + + // Clear histogram + for i := range w.literalFreq[:] { + w.literalFreq[i] = 0 + } + if !w.lastHuffMan { + for i := range w.offsetFreq[:] { + w.offsetFreq[i] = 0 + } + } + + const numLiterals = endBlockMarker + 1 + const numOffsets = 1 + + // Add everything as literals + // We have to estimate the header size. + // Assume header is around 70 bytes: + // https://stackoverflow.com/a/25454430 + const guessHeaderSizeBits = 70 * 8 + histogram(input, w.literalFreq[:numLiterals]) + ssize, storable := w.storedSize(input) + if storable && len(input) > 1024 { + // Quick check for incompressible content. + abs := float64(0) + avg := float64(len(input)) / 256 + max := float64(len(input) * 2) + for _, v := range w.literalFreq[:256] { + diff := float64(v) - avg + abs += diff * diff + if abs > max { + break + } + } + if abs < max { + if debugDeflate { + fmt.Println("stored", abs, "<", max) + } + // No chance we can compress this... + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + } + w.literalFreq[endBlockMarker] = 1 + w.tmpLitEncoding.generate(w.literalFreq[:numLiterals], 15) + estBits := w.tmpLitEncoding.canReuseBits(w.literalFreq[:numLiterals]) + if estBits < math.MaxInt32 { + estBits += w.lastHeader + if w.lastHeader == 0 { + estBits += guessHeaderSizeBits + } + estBits += estBits >> w.logNewTablePenalty + } + + // Store bytes, if we don't get a reasonable improvement. + if storable && ssize <= estBits { + if debugDeflate { + fmt.Println("stored,", ssize, "<=", estBits) + } + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + + if w.lastHeader > 0 { + reuseSize := w.literalEncoding.canReuseBits(w.literalFreq[:256]) + + if estBits < reuseSize { + if debugDeflate { + fmt.Println("NOT reusing, reuse:", reuseSize/8, "> new:", estBits/8, "header est:", w.lastHeader/8, "bytes") + } + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } else if debugDeflate { + fmt.Println("reusing, reuse:", reuseSize/8, "> new:", estBits/8, "- header est:", w.lastHeader/8) + } + } + + count := 0 + if w.lastHeader == 0 { + // Use the temp encoding, so swap. + w.literalEncoding, w.tmpLitEncoding = w.tmpLitEncoding, w.literalEncoding + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, huffOffset) + w.codegenEncoding.generate(w.codegenFreq[:], 7) + numCodegens := w.codegens() + + // Huffman. + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + w.lastHuffMan = true + w.lastHeader, _ = w.headerSize() + if debugDeflate { + count += w.lastHeader + fmt.Println("header:", count/8) + } + } + + encoding := w.literalEncoding.codes[:256] + // Go 1.16 LOVES having these on stack. At least 1.5x the speed. + bits, nbits, nbytes := w.bits, w.nbits, w.nbytes + + if debugDeflate { + count -= int(nbytes)*8 + int(nbits) + } + // Unroll, write 3 codes/loop. + // Fastest number of unrolls. + for len(input) > 3 { + // We must have at least 48 bits free. + if nbits >= 8 { + n := nbits >> 3 + le.Store64(w.bytes[:], nbytes, bits) + bits >>= (n * 8) & 63 + nbits -= n * 8 + nbytes += n + } + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + if debugDeflate { + count += int(nbytes) * 8 + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + a, b := encoding[input[0]], encoding[input[1]] + bits |= a.code64() << (nbits & 63) + bits |= b.code64() << ((nbits + a.len()) & 63) + c := encoding[input[2]] + nbits += b.len() + a.len() + bits |= c.code64() << (nbits & 63) + nbits += c.len() + input = input[3:] + } + + // Remaining... + for _, t := range input { + if nbits >= 48 { + le.Store64(w.bytes[:], nbytes, bits) + bits >>= 48 + nbits -= 48 + nbytes += 6 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return + } + if debugDeflate { + count += int(nbytes) * 8 + } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + } + } + // Bitwriting inlined, ~30% speedup + c := encoding[t] + bits |= c.code64() << (nbits & 63) + + nbits += c.len() + if debugDeflate { + count += int(c.len()) + } + } + // Restore... + w.bits, w.nbits, w.nbytes = bits, nbits, nbytes + + if debugDeflate { + nb := count + int(nbytes)*8 + int(nbits) + fmt.Println("wrote", nb, "bits,", nb/8, "bytes.") + } + // Flush if needed to have space. + if w.nbits >= 48 { + w.writeOutBits() + } + + if eof || sync { + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + w.lastHuffMan = false + } +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go new file mode 100644 index 0000000..5f901bd --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go @@ -0,0 +1,417 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "math" + "math/bits" +) + +const ( + maxBitsLimit = 16 + // number of valid literals + literalCount = 286 +) + +// hcode is a huffman code with a bit code and bit length. +type hcode uint32 + +func (h hcode) len() uint8 { + return uint8(h) +} + +func (h hcode) code64() uint64 { + return uint64(h >> 8) +} + +func (h hcode) zero() bool { + return h == 0 +} + +type huffmanEncoder struct { + codes []hcode + bitCount [17]int32 + + // Allocate a reusable buffer with the longest possible frequency table. + // Possible lengths are codegenCodeCount, offsetCodeCount and literalCount. + // The largest of these is literalCount, so we allocate for that case. + freqcache [literalCount + 1]literalNode +} + +type literalNode struct { + literal uint16 + freq uint16 +} + +// A levelInfo describes the state of the constructed tree for a given depth. +type levelInfo struct { + // Our level. for better printing + level int32 + + // The frequency of the last node at this level + lastFreq int32 + + // The frequency of the next character to add to this level + nextCharFreq int32 + + // The frequency of the next pair (from level below) to add to this level. + // Only valid if the "needed" value of the next lower level is 0. + nextPairFreq int32 + + // The number of chains remaining to generate for this level before moving + // up to the next level + needed int32 +} + +// set sets the code and length of an hcode. +func (h *hcode) set(code uint16, length uint8) { + *h = hcode(length) | (hcode(code) << 8) +} + +func newhcode(code uint16, length uint8) hcode { + return hcode(length) | (hcode(code) << 8) +} + +func reverseBits(number uint16, bitLength byte) uint16 { + return bits.Reverse16(number << ((16 - bitLength) & 15)) +} + +func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxUint16} } + +func newHuffmanEncoder(size int) *huffmanEncoder { + // Make capacity to next power of two. + c := uint(bits.Len32(uint32(size - 1))) + return &huffmanEncoder{codes: make([]hcode, size, 1<= 3 +// The cases of 0, 1, and 2 literals are handled by special case code. +// +// list An array of the literals with non-zero frequencies +// +// and their associated frequencies. The array is in order of increasing +// frequency, and has as its last element a special element with frequency +// MaxInt32 +// +// maxBits The maximum number of bits that should be used to encode any literal. +// +// Must be less than 16. +// +// return An integer array in which array[i] indicates the number of literals +// +// that should be encoded in i bits. +func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { + if maxBits >= maxBitsLimit { + panic("flate: maxBits too large") + } + n := int32(len(list)) + list = list[0 : n+1] + list[n] = maxNode() + + // The tree can't have greater depth than n - 1, no matter what. This + // saves a little bit of work in some small cases + if maxBits > n-1 { + maxBits = n - 1 + } + + // Create information about each of the levels. + // A bogus "Level 0" whose sole purpose is so that + // level1.prev.needed==0. This makes level1.nextPairFreq + // be a legitimate value that never gets chosen. + var levels [maxBitsLimit]levelInfo + // leafCounts[i] counts the number of literals at the left + // of ancestors of the rightmost node at level i. + // leafCounts[i][j] is the number of literals at the left + // of the level j ancestor. + var leafCounts [maxBitsLimit][maxBitsLimit]int32 + + // Descending to only have 1 bounds check. + l2f := int32(list[2].freq) + l1f := int32(list[1].freq) + l0f := int32(list[0].freq) + int32(list[1].freq) + + for level := int32(1); level <= maxBits; level++ { + // For every level, the first two items are the first two characters. + // We initialize the levels as if we had already figured this out. + levels[level] = levelInfo{ + level: level, + lastFreq: l1f, + nextCharFreq: l2f, + nextPairFreq: l0f, + } + leafCounts[level][level] = 2 + if level == 1 { + levels[level].nextPairFreq = math.MaxInt32 + } + } + + // We need a total of 2*n - 2 items at top level and have already generated 2. + levels[maxBits].needed = 2*n - 4 + + level := uint32(maxBits) + for level < 16 { + l := &levels[level] + if l.nextPairFreq == math.MaxInt32 && l.nextCharFreq == math.MaxInt32 { + // We've run out of both leafs and pairs. + // End all calculations for this level. + // To make sure we never come back to this level or any lower level, + // set nextPairFreq impossibly large. + l.needed = 0 + levels[level+1].nextPairFreq = math.MaxInt32 + level++ + continue + } + + prevFreq := l.lastFreq + if l.nextCharFreq < l.nextPairFreq { + // The next item on this row is a leaf node. + n := leafCounts[level][level] + 1 + l.lastFreq = l.nextCharFreq + // Lower leafCounts are the same of the previous node. + leafCounts[level][level] = n + e := list[n] + if e.literal < math.MaxUint16 { + l.nextCharFreq = int32(e.freq) + } else { + l.nextCharFreq = math.MaxInt32 + } + } else { + // The next item on this row is a pair from the previous row. + // nextPairFreq isn't valid until we generate two + // more values in the level below + l.lastFreq = l.nextPairFreq + // Take leaf counts from the lower level, except counts[level] remains the same. + if true { + save := leafCounts[level][level] + leafCounts[level] = leafCounts[level-1] + leafCounts[level][level] = save + } else { + copy(leafCounts[level][:level], leafCounts[level-1][:level]) + } + levels[l.level-1].needed = 2 + } + + if l.needed--; l.needed == 0 { + // We've done everything we need to do for this level. + // Continue calculating one level up. Fill in nextPairFreq + // of that level with the sum of the two nodes we've just calculated on + // this level. + if l.level == maxBits { + // All done! + break + } + levels[l.level+1].nextPairFreq = prevFreq + l.lastFreq + level++ + } else { + // If we stole from below, move down temporarily to replenish it. + for levels[level-1].needed > 0 { + level-- + } + } + } + + // Somethings is wrong if at the end, the top level is null or hasn't used + // all of the leaves. + if leafCounts[maxBits][maxBits] != n { + panic("leafCounts[maxBits][maxBits] != n") + } + + bitCount := h.bitCount[:maxBits+1] + bits := 1 + counts := &leafCounts[maxBits] + for level := maxBits; level > 0; level-- { + // chain.leafCount gives the number of literals requiring at least "bits" + // bits to encode. + bitCount[bits] = counts[level] - counts[level-1] + bits++ + } + return bitCount +} + +// Look at the leaves and assign them a bit count and an encoding as specified +// in RFC 1951 3.2.2 +func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode) { + code := uint16(0) + for n, bits := range bitCount { + code <<= 1 + if n == 0 || bits == 0 { + continue + } + // The literals list[len(list)-bits] .. list[len(list)-bits] + // are encoded using "bits" bits, and get the values + // code, code + 1, .... The code values are + // assigned in literal order (not frequency order). + chunk := list[len(list)-int(bits):] + + sortByLiteral(chunk) + for _, node := range chunk { + h.codes[node.literal] = newhcode(reverseBits(code, uint8(n)), uint8(n)) + code++ + } + list = list[0 : len(list)-int(bits)] + } +} + +// Update this Huffman Code object to be the minimum code for the specified frequency count. +// +// freq An array of frequencies, in which frequency[i] gives the frequency of literal i. +// maxBits The maximum number of bits to use for any literal. +func (h *huffmanEncoder) generate(freq []uint16, maxBits int32) { + list := h.freqcache[:len(freq)+1] + codes := h.codes[:len(freq)] + // Number of non-zero literals + count := 0 + // Set list to be the set of all non-zero literals and their frequencies + for i, f := range freq { + if f != 0 { + list[count] = literalNode{uint16(i), f} + count++ + } else { + codes[i] = 0 + } + } + list[count] = literalNode{} + + list = list[:count] + if count <= 2 { + // Handle the small cases here, because they are awkward for the general case code. With + // two or fewer literals, everything has bit length 1. + for i, node := range list { + // "list" is in order of increasing literal value. + h.codes[node.literal].set(uint16(i), 1) + } + return + } + sortByFreq(list) + + // Get the number of literals for each bit count + bitCount := h.bitCounts(list, maxBits) + // And do the assignment + h.assignEncodingAndSize(bitCount, list) +} + +// atLeastOne clamps the result between 1 and 15. +func atLeastOne(v float32) float32 { + if v < 1 { + return 1 + } + if v > 15 { + return 15 + } + return v +} + +func histogram(b []byte, h []uint16) { + if true && len(b) >= 8<<10 { + // Split for bigger inputs + histogramSplit(b, h) + } else { + h = h[:256] + for _, t := range b { + h[t]++ + } + } +} + +func histogramSplit(b []byte, h []uint16) { + // Tested, and slightly faster than 2-way. + // Writing to separate arrays and combining is also slightly slower. + h = h[:256] + for len(b)&3 != 0 { + h[b[0]]++ + b = b[1:] + } + n := len(b) / 4 + x, y, z, w := b[:n], b[n:], b[n+n:], b[n+n+n:] + y, z, w = y[:len(x)], z[:len(x)], w[:len(x)] + for i, t := range x { + v0 := &h[t] + v1 := &h[y[i]] + v3 := &h[w[i]] + v2 := &h[z[i]] + *v0++ + *v1++ + *v2++ + *v3++ + } +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go b/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go new file mode 100644 index 0000000..6c05ba8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go @@ -0,0 +1,159 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +// Sort sorts data. +// It makes one call to data.Len to determine n, and O(n*log(n)) calls to +// data.Less and data.Swap. The sort is not guaranteed to be stable. +func sortByFreq(data []literalNode) { + n := len(data) + quickSortByFreq(data, 0, n, maxDepth(n)) +} + +func quickSortByFreq(data []literalNode, a, b, maxDepth int) { + for b-a > 12 { // Use ShellSort for slices <= 12 elements + if maxDepth == 0 { + heapSort(data, a, b) + return + } + maxDepth-- + mlo, mhi := doPivotByFreq(data, a, b) + // Avoiding recursion on the larger subproblem guarantees + // a stack depth of at most lg(b-a). + if mlo-a < b-mhi { + quickSortByFreq(data, a, mlo, maxDepth) + a = mhi // i.e., quickSortByFreq(data, mhi, b) + } else { + quickSortByFreq(data, mhi, b, maxDepth) + b = mlo // i.e., quickSortByFreq(data, a, mlo) + } + } + if b-a > 1 { + // Do ShellSort pass with gap 6 + // It could be written in this simplified form cause b-a <= 12 + for i := a + 6; i < b; i++ { + if data[i].freq == data[i-6].freq && data[i].literal < data[i-6].literal || data[i].freq < data[i-6].freq { + data[i], data[i-6] = data[i-6], data[i] + } + } + insertionSortByFreq(data, a, b) + } +} + +func doPivotByFreq(data []literalNode, lo, hi int) (midlo, midhi int) { + m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow. + if hi-lo > 40 { + // Tukey's ``Ninther,'' median of three medians of three. + s := (hi - lo) / 8 + medianOfThreeSortByFreq(data, lo, lo+s, lo+2*s) + medianOfThreeSortByFreq(data, m, m-s, m+s) + medianOfThreeSortByFreq(data, hi-1, hi-1-s, hi-1-2*s) + } + medianOfThreeSortByFreq(data, lo, m, hi-1) + + // Invariants are: + // data[lo] = pivot (set up by ChoosePivot) + // data[lo < i < a] < pivot + // data[a <= i < b] <= pivot + // data[b <= i < c] unexamined + // data[c <= i < hi-1] > pivot + // data[hi-1] >= pivot + pivot := lo + a, c := lo+1, hi-1 + + for ; a < c && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { + } + b := a + for { + for ; b < c && (data[pivot].freq == data[b].freq && data[pivot].literal > data[b].literal || data[pivot].freq > data[b].freq); b++ { // data[b] <= pivot + } + for ; b < c && (data[pivot].freq == data[c-1].freq && data[pivot].literal < data[c-1].literal || data[pivot].freq < data[c-1].freq); c-- { // data[c-1] > pivot + } + if b >= c { + break + } + // data[b] > pivot; data[c-1] <= pivot + data[b], data[c-1] = data[c-1], data[b] + b++ + c-- + } + // If hi-c<3 then there are duplicates (by property of median of nine). + // Let's be a bit more conservative, and set border to 5. + protect := hi-c < 5 + if !protect && hi-c < (hi-lo)/4 { + // Lets test some points for equality to pivot + dups := 0 + if data[pivot].freq == data[hi-1].freq && data[pivot].literal > data[hi-1].literal || data[pivot].freq > data[hi-1].freq { // data[hi-1] = pivot + data[c], data[hi-1] = data[hi-1], data[c] + c++ + dups++ + } + if data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq { // data[b-1] = pivot + b-- + dups++ + } + // m-lo = (hi-lo)/2 > 6 + // b-lo > (hi-lo)*3/4-1 > 8 + // ==> m < b ==> data[m] <= pivot + if data[m].freq == data[pivot].freq && data[m].literal > data[pivot].literal || data[m].freq > data[pivot].freq { // data[m] = pivot + data[m], data[b-1] = data[b-1], data[m] + b-- + dups++ + } + // if at least 2 points are equal to pivot, assume skewed distribution + protect = dups > 1 + } + if protect { + // Protect against a lot of duplicates + // Add invariant: + // data[a <= i < b] unexamined + // data[b <= i < c] = pivot + for { + for ; a < b && (data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq); b-- { // data[b] == pivot + } + for ; a < b && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { // data[a] < pivot + } + if a >= b { + break + } + // data[a] == pivot; data[b-1] < pivot + data[a], data[b-1] = data[b-1], data[a] + a++ + b-- + } + } + // Swap pivot into middle + data[pivot], data[b-1] = data[b-1], data[pivot] + return b - 1, c +} + +// Insertion sort +func insertionSortByFreq(data []literalNode, a, b int) { + for i := a + 1; i < b; i++ { + for j := i; j > a && (data[j].freq == data[j-1].freq && data[j].literal < data[j-1].literal || data[j].freq < data[j-1].freq); j-- { + data[j], data[j-1] = data[j-1], data[j] + } + } +} + +// quickSortByFreq, loosely following Bentley and McIlroy, +// ``Engineering a Sort Function,'' SP&E November 1993. + +// medianOfThreeSortByFreq moves the median of the three values data[m0], data[m1], data[m2] into data[m1]. +func medianOfThreeSortByFreq(data []literalNode, m1, m0, m2 int) { + // sort 3 elements + if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq { + data[m1], data[m0] = data[m0], data[m1] + } + // data[m0] <= data[m1] + if data[m2].freq == data[m1].freq && data[m2].literal < data[m1].literal || data[m2].freq < data[m1].freq { + data[m2], data[m1] = data[m1], data[m2] + // data[m0] <= data[m2] && data[m1] < data[m2] + if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq { + data[m1], data[m0] = data[m0], data[m1] + } + } + // now data[m0] <= data[m1] <= data[m2] +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go b/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go new file mode 100644 index 0000000..93f1aea --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go @@ -0,0 +1,201 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +// Sort sorts data. +// It makes one call to data.Len to determine n, and O(n*log(n)) calls to +// data.Less and data.Swap. The sort is not guaranteed to be stable. +func sortByLiteral(data []literalNode) { + n := len(data) + quickSort(data, 0, n, maxDepth(n)) +} + +func quickSort(data []literalNode, a, b, maxDepth int) { + for b-a > 12 { // Use ShellSort for slices <= 12 elements + if maxDepth == 0 { + heapSort(data, a, b) + return + } + maxDepth-- + mlo, mhi := doPivot(data, a, b) + // Avoiding recursion on the larger subproblem guarantees + // a stack depth of at most lg(b-a). + if mlo-a < b-mhi { + quickSort(data, a, mlo, maxDepth) + a = mhi // i.e., quickSort(data, mhi, b) + } else { + quickSort(data, mhi, b, maxDepth) + b = mlo // i.e., quickSort(data, a, mlo) + } + } + if b-a > 1 { + // Do ShellSort pass with gap 6 + // It could be written in this simplified form cause b-a <= 12 + for i := a + 6; i < b; i++ { + if data[i].literal < data[i-6].literal { + data[i], data[i-6] = data[i-6], data[i] + } + } + insertionSort(data, a, b) + } +} +func heapSort(data []literalNode, a, b int) { + first := a + lo := 0 + hi := b - a + + // Build heap with greatest element at top. + for i := (hi - 1) / 2; i >= 0; i-- { + siftDown(data, i, hi, first) + } + + // Pop elements, largest first, into end of data. + for i := hi - 1; i >= 0; i-- { + data[first], data[first+i] = data[first+i], data[first] + siftDown(data, lo, i, first) + } +} + +// siftDown implements the heap property on data[lo, hi). +// first is an offset into the array where the root of the heap lies. +func siftDown(data []literalNode, lo, hi, first int) { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && data[first+child].literal < data[first+child+1].literal { + child++ + } + if data[first+root].literal > data[first+child].literal { + return + } + data[first+root], data[first+child] = data[first+child], data[first+root] + root = child + } +} +func doPivot(data []literalNode, lo, hi int) (midlo, midhi int) { + m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow. + if hi-lo > 40 { + // Tukey's ``Ninther,'' median of three medians of three. + s := (hi - lo) / 8 + medianOfThree(data, lo, lo+s, lo+2*s) + medianOfThree(data, m, m-s, m+s) + medianOfThree(data, hi-1, hi-1-s, hi-1-2*s) + } + medianOfThree(data, lo, m, hi-1) + + // Invariants are: + // data[lo] = pivot (set up by ChoosePivot) + // data[lo < i < a] < pivot + // data[a <= i < b] <= pivot + // data[b <= i < c] unexamined + // data[c <= i < hi-1] > pivot + // data[hi-1] >= pivot + pivot := lo + a, c := lo+1, hi-1 + + for ; a < c && data[a].literal < data[pivot].literal; a++ { + } + b := a + for { + for ; b < c && data[pivot].literal > data[b].literal; b++ { // data[b] <= pivot + } + for ; b < c && data[pivot].literal < data[c-1].literal; c-- { // data[c-1] > pivot + } + if b >= c { + break + } + // data[b] > pivot; data[c-1] <= pivot + data[b], data[c-1] = data[c-1], data[b] + b++ + c-- + } + // If hi-c<3 then there are duplicates (by property of median of nine). + // Let's be a bit more conservative, and set border to 5. + protect := hi-c < 5 + if !protect && hi-c < (hi-lo)/4 { + // Lets test some points for equality to pivot + dups := 0 + if data[pivot].literal > data[hi-1].literal { // data[hi-1] = pivot + data[c], data[hi-1] = data[hi-1], data[c] + c++ + dups++ + } + if data[b-1].literal > data[pivot].literal { // data[b-1] = pivot + b-- + dups++ + } + // m-lo = (hi-lo)/2 > 6 + // b-lo > (hi-lo)*3/4-1 > 8 + // ==> m < b ==> data[m] <= pivot + if data[m].literal > data[pivot].literal { // data[m] = pivot + data[m], data[b-1] = data[b-1], data[m] + b-- + dups++ + } + // if at least 2 points are equal to pivot, assume skewed distribution + protect = dups > 1 + } + if protect { + // Protect against a lot of duplicates + // Add invariant: + // data[a <= i < b] unexamined + // data[b <= i < c] = pivot + for { + for ; a < b && data[b-1].literal > data[pivot].literal; b-- { // data[b] == pivot + } + for ; a < b && data[a].literal < data[pivot].literal; a++ { // data[a] < pivot + } + if a >= b { + break + } + // data[a] == pivot; data[b-1] < pivot + data[a], data[b-1] = data[b-1], data[a] + a++ + b-- + } + } + // Swap pivot into middle + data[pivot], data[b-1] = data[b-1], data[pivot] + return b - 1, c +} + +// Insertion sort +func insertionSort(data []literalNode, a, b int) { + for i := a + 1; i < b; i++ { + for j := i; j > a && data[j].literal < data[j-1].literal; j-- { + data[j], data[j-1] = data[j-1], data[j] + } + } +} + +// maxDepth returns a threshold at which quicksort should switch +// to heapsort. It returns 2*ceil(lg(n+1)). +func maxDepth(n int) int { + var depth int + for i := n; i > 0; i >>= 1 { + depth++ + } + return depth * 2 +} + +// medianOfThree moves the median of the three values data[m0], data[m1], data[m2] into data[m1]. +func medianOfThree(data []literalNode, m1, m0, m2 int) { + // sort 3 elements + if data[m1].literal < data[m0].literal { + data[m1], data[m0] = data[m0], data[m1] + } + // data[m0] <= data[m1] + if data[m2].literal < data[m1].literal { + data[m2], data[m1] = data[m1], data[m2] + // data[m0] <= data[m2] && data[m1] < data[m2] + if data[m1].literal < data[m0].literal { + data[m1], data[m0] = data[m0], data[m1] + } + } + // now data[m0] <= data[m1] <= data[m2] +} diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go new file mode 100644 index 0000000..6e90126 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -0,0 +1,865 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package flate implements the DEFLATE compressed data format, described in +// RFC 1951. The gzip and zlib packages implement access to DEFLATE-based file +// formats. +package flate + +import ( + "bufio" + "compress/flate" + "fmt" + "io" + "math/bits" + "sync" +) + +const ( + maxCodeLen = 16 // max length of Huffman code + maxCodeLenMask = 15 // mask for max length of Huffman code + // The next three numbers come from the RFC section 3.2.7, with the + // additional proviso in section 3.2.5 which implies that distance codes + // 30 and 31 should never occur in compressed data. + maxNumLit = 286 + maxNumDist = 30 + numCodes = 19 // number of codes in Huffman meta-code + + debugDecode = false +) + +// Value of length - 3 and extra bits. +type lengthExtra struct { + length, extra uint8 +} + +var decCodeToLen = [32]lengthExtra{{length: 0x0, extra: 0x0}, {length: 0x1, extra: 0x0}, {length: 0x2, extra: 0x0}, {length: 0x3, extra: 0x0}, {length: 0x4, extra: 0x0}, {length: 0x5, extra: 0x0}, {length: 0x6, extra: 0x0}, {length: 0x7, extra: 0x0}, {length: 0x8, extra: 0x1}, {length: 0xa, extra: 0x1}, {length: 0xc, extra: 0x1}, {length: 0xe, extra: 0x1}, {length: 0x10, extra: 0x2}, {length: 0x14, extra: 0x2}, {length: 0x18, extra: 0x2}, {length: 0x1c, extra: 0x2}, {length: 0x20, extra: 0x3}, {length: 0x28, extra: 0x3}, {length: 0x30, extra: 0x3}, {length: 0x38, extra: 0x3}, {length: 0x40, extra: 0x4}, {length: 0x50, extra: 0x4}, {length: 0x60, extra: 0x4}, {length: 0x70, extra: 0x4}, {length: 0x80, extra: 0x5}, {length: 0xa0, extra: 0x5}, {length: 0xc0, extra: 0x5}, {length: 0xe0, extra: 0x5}, {length: 0xff, extra: 0x0}, {length: 0x0, extra: 0x0}, {length: 0x0, extra: 0x0}, {length: 0x0, extra: 0x0}} + +var bitMask32 = [32]uint32{ + 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, + 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, + 0x1ffff, 0x3ffff, 0x7FFFF, 0xfFFFF, 0x1fFFFF, 0x3fFFFF, 0x7fFFFF, 0xffFFFF, + 0x1ffFFFF, 0x3ffFFFF, 0x7ffFFFF, 0xfffFFFF, 0x1fffFFFF, 0x3fffFFFF, 0x7fffFFFF, +} // up to 32 bits + +// Initialize the fixedHuffmanDecoder only once upon first use. +var fixedOnce sync.Once +var fixedHuffmanDecoder huffmanDecoder + +// A CorruptInputError reports the presence of corrupt input at a given offset. +type CorruptInputError = flate.CorruptInputError + +// An InternalError reports an error in the flate code itself. +type InternalError string + +func (e InternalError) Error() string { return "flate: internal error: " + string(e) } + +// A ReadError reports an error encountered while reading input. +// +// Deprecated: No longer returned. +type ReadError = flate.ReadError + +// A WriteError reports an error encountered while writing output. +// +// Deprecated: No longer returned. +type WriteError = flate.WriteError + +// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to +// to switch to a new underlying Reader. This permits reusing a ReadCloser +// instead of allocating a new one. +type Resetter interface { + // Reset discards any buffered data and resets the Resetter as if it was + // newly initialized with the given reader. + Reset(r io.Reader, dict []byte) error +} + +// The data structure for decoding Huffman tables is based on that of +// zlib. There is a lookup table of a fixed bit width (huffmanChunkBits), +// For codes smaller than the table width, there are multiple entries +// (each combination of trailing bits has the same value). For codes +// larger than the table width, the table contains a link to an overflow +// table. The width of each entry in the link table is the maximum code +// size minus the chunk width. +// +// Note that you can do a lookup in the table even without all bits +// filled. Since the extra bits are zero, and the DEFLATE Huffman codes +// have the property that shorter codes come before longer ones, the +// bit length estimate in the result is a lower bound on the actual +// number of bits. +// +// See the following: +// http://www.gzip.org/algorithm.txt + +// chunk & 15 is number of bits +// chunk >> 4 is value, including table link + +const ( + huffmanChunkBits = 9 + huffmanNumChunks = 1 << huffmanChunkBits + huffmanCountMask = 15 + huffmanValueShift = 4 +) + +type huffmanDecoder struct { + maxRead int // the maximum number of bits we can read and not overread + chunks *[huffmanNumChunks]uint16 // chunks as described above + links [][]uint16 // overflow links + linkMask uint32 // mask the width of the link table +} + +// Initialize Huffman decoding tables from array of code lengths. +// Following this function, h is guaranteed to be initialized into a complete +// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a +// degenerate case where the tree has only a single symbol with length 1. Empty +// trees are permitted. +func (h *huffmanDecoder) init(lengths []int) bool { + // Sanity enables additional runtime tests during Huffman + // table construction. It's intended to be used during + // development to supplement the currently ad-hoc unit tests. + const sanity = false + + if h.chunks == nil { + h.chunks = new([huffmanNumChunks]uint16) + } + + if h.maxRead != 0 { + *h = huffmanDecoder{chunks: h.chunks, links: h.links} + } + + // Count number of codes of each length, + // compute maxRead and max length. + var count [maxCodeLen]int + var min, max int + for _, n := range lengths { + if n == 0 { + continue + } + if min == 0 || n < min { + min = n + } + if n > max { + max = n + } + count[n&maxCodeLenMask]++ + } + + // Empty tree. The decompressor.huffSym function will fail later if the tree + // is used. Technically, an empty tree is only valid for the HDIST tree and + // not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree + // is guaranteed to fail since it will attempt to use the tree to decode the + // codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is + // guaranteed to fail later since the compressed data section must be + // composed of at least one symbol (the end-of-block marker). + if max == 0 { + return true + } + + code := 0 + var nextcode [maxCodeLen]int + for i := min; i <= max; i++ { + code <<= 1 + nextcode[i&maxCodeLenMask] = code + code += count[i&maxCodeLenMask] + } + + // Check that the coding is complete (i.e., that we've + // assigned all 2-to-the-max possible bit sequences). + // Exception: To be compatible with zlib, we also need to + // accept degenerate single-code codings. See also + // TestDegenerateHuffmanCoding. + if code != 1< huffmanChunkBits { + numLinks := 1 << (uint(max) - huffmanChunkBits) + h.linkMask = uint32(numLinks - 1) + + // create link tables + link := nextcode[huffmanChunkBits+1] >> 1 + if cap(h.links) < huffmanNumChunks-link { + h.links = make([][]uint16, huffmanNumChunks-link) + } else { + h.links = h.links[:huffmanNumChunks-link] + } + for j := uint(link); j < huffmanNumChunks; j++ { + reverse := int(bits.Reverse16(uint16(j))) + reverse >>= uint(16 - huffmanChunkBits) + off := j - uint(link) + if sanity && h.chunks[reverse] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[reverse] = uint16(off<>= uint(16 - n) + if n <= huffmanChunkBits { + for off := reverse; off < len(h.chunks); off += 1 << uint(n) { + // We should never need to overwrite + // an existing chunk. Also, 0 is + // never a valid chunk, because the + // lower 4 "count" bits should be + // between 1 and 15. + if sanity && h.chunks[off] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[off] = chunk + } + } else { + j := reverse & (huffmanNumChunks - 1) + if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 { + // Longer codes should have been + // associated with a link table above. + panic("impossible: not an indirect chunk") + } + value := h.chunks[j] >> huffmanValueShift + linktab := h.links[value] + reverse >>= huffmanChunkBits + for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) { + if sanity && linktab[off] != 0 { + panic("impossible: overwriting existing chunk") + } + linktab[off] = chunk + } + } + } + + if sanity { + // Above we've sanity checked that we never overwrote + // an existing entry. Here we additionally check that + // we filled the tables completely. + for i, chunk := range h.chunks { + if chunk == 0 { + // As an exception, in the degenerate + // single-code case, we allow odd + // chunks to be missing. + if code == 1 && i%2 == 1 { + continue + } + panic("impossible: missing chunk") + } + } + for _, linktab := range h.links { + for _, chunk := range linktab { + if chunk == 0 { + panic("impossible: missing chunk") + } + } + } + } + + return true +} + +// Reader is the actual read interface needed by NewReader. +// If the passed in io.Reader does not also have ReadByte, +// the NewReader will introduce its own buffering. +type Reader interface { + io.Reader + io.ByteReader +} + +type step uint8 + +const ( + copyData step = iota + 1 + nextBlock + huffmanBytesBuffer + huffmanBytesReader + huffmanBufioReader + huffmanStringsReader + huffmanGenericReader +) + +// flushMode tells decompressor when to return data +type flushMode uint8 + +const ( + syncFlush flushMode = iota // return data after sync flush block + partialFlush // return data after each block +) + +// Decompress state. +type decompressor struct { + // Input source. + r Reader + roffset int64 + + // Huffman decoders for literal/length, distance. + h1, h2 huffmanDecoder + + // Length arrays used to define Huffman codes. + bits *[maxNumLit + maxNumDist]int + codebits *[numCodes]int + + // Output history, buffer. + dict dictDecoder + + // Next step in the decompression, + // and decompression state. + step step + stepState int + err error + toRead []byte + hl, hd *huffmanDecoder + copyLen int + copyDist int + + // Temporary buffer (avoids repeated allocation). + buf [4]byte + + // Input bits, in top of b. + b uint32 + + nb uint + final bool + + flushMode flushMode +} + +func (f *decompressor) nextBlock() { + for f.nb < 1+2 { + if f.err = f.moreBits(); f.err != nil { + return + } + } + f.final = f.b&1 == 1 + f.b >>= 1 + typ := f.b & 3 + f.b >>= 2 + f.nb -= 1 + 2 + switch typ { + case 0: + f.dataBlock() + if debugDecode { + fmt.Println("stored block") + } + case 1: + // compressed, fixed Huffman tables + f.hl = &fixedHuffmanDecoder + f.hd = nil + f.huffmanBlockDecoder() + if debugDecode { + fmt.Println("predefinied huffman block") + } + case 2: + // compressed, dynamic Huffman tables + if f.err = f.readHuffman(); f.err != nil { + break + } + f.hl = &f.h1 + f.hd = &f.h2 + f.huffmanBlockDecoder() + if debugDecode { + fmt.Println("dynamic huffman block") + } + default: + // 3 is reserved. + if debugDecode { + fmt.Println("reserved data block encountered") + } + f.err = CorruptInputError(f.roffset) + } +} + +func (f *decompressor) Read(b []byte) (int, error) { + for { + if len(f.toRead) > 0 { + n := copy(b, f.toRead) + f.toRead = f.toRead[n:] + if len(f.toRead) == 0 { + return n, f.err + } + return n, nil + } + if f.err != nil { + return 0, f.err + } + + f.doStep() + + if f.err != nil && len(f.toRead) == 0 { + f.toRead = f.dict.readFlush() // Flush what's left in case of error + } + } +} + +// WriteTo implements the io.WriteTo interface for io.Copy and friends. +func (f *decompressor) WriteTo(w io.Writer) (int64, error) { + total := int64(0) + flushed := false + for { + if len(f.toRead) > 0 { + n, err := w.Write(f.toRead) + total += int64(n) + if err != nil { + f.err = err + return total, err + } + if n != len(f.toRead) { + return total, io.ErrShortWrite + } + f.toRead = f.toRead[:0] + } + if f.err != nil && flushed { + if f.err == io.EOF { + return total, nil + } + return total, f.err + } + if f.err == nil { + f.doStep() + } + if len(f.toRead) == 0 && f.err != nil && !flushed { + f.toRead = f.dict.readFlush() // Flush what's left in case of error + flushed = true + } + } +} + +func (f *decompressor) Close() error { + if f.err == io.EOF { + return nil + } + return f.err +} + +// RFC 1951 section 3.2.7. +// Compression with dynamic Huffman codes + +var codeOrder = [...]int{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} + +func (f *decompressor) readHuffman() error { + // HLIT[5], HDIST[5], HCLEN[4]. + for f.nb < 5+5+4 { + if err := f.moreBits(); err != nil { + return err + } + } + nlit := int(f.b&0x1F) + 257 + if nlit > maxNumLit { + if debugDecode { + fmt.Println("nlit > maxNumLit", nlit) + } + return CorruptInputError(f.roffset) + } + f.b >>= 5 + ndist := int(f.b&0x1F) + 1 + if ndist > maxNumDist { + if debugDecode { + fmt.Println("ndist > maxNumDist", ndist) + } + return CorruptInputError(f.roffset) + } + f.b >>= 5 + nclen := int(f.b&0xF) + 4 + // numCodes is 19, so nclen is always valid. + f.b >>= 4 + f.nb -= 5 + 5 + 4 + + // (HCLEN+4)*3 bits: code lengths in the magic codeOrder order. + for i := range nclen { + for f.nb < 3 { + if err := f.moreBits(); err != nil { + return err + } + } + f.codebits[codeOrder[i]] = int(f.b & 0x7) + f.b >>= 3 + f.nb -= 3 + } + for i := nclen; i < len(codeOrder); i++ { + f.codebits[codeOrder[i]] = 0 + } + if !f.h1.init(f.codebits[0:]) { + if debugDecode { + fmt.Println("init codebits failed") + } + return CorruptInputError(f.roffset) + } + + // HLIT + 257 code lengths, HDIST + 1 code lengths, + // using the code length Huffman code. + for i, n := 0, nlit+ndist; i < n; { + x, err := f.huffSym(&f.h1) + if err != nil { + return err + } + if x < 16 { + // Actual length. + f.bits[i] = x + i++ + continue + } + // Repeat previous length or zero. + var rep int + var nb uint + var b int + switch x { + default: + return InternalError("unexpected length code") + case 16: + rep = 3 + nb = 2 + if i == 0 { + if debugDecode { + fmt.Println("i==0") + } + return CorruptInputError(f.roffset) + } + b = f.bits[i-1] + case 17: + rep = 3 + nb = 3 + b = 0 + case 18: + rep = 11 + nb = 7 + b = 0 + } + for f.nb < nb { + if err := f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits:", err) + } + return err + } + } + rep += int(f.b & uint32(1<<(nb®SizeMaskUint32)-1)) + f.b >>= nb & regSizeMaskUint32 + f.nb -= nb + if i+rep > n { + if debugDecode { + fmt.Println("i+rep > n", i, rep, n) + } + return CorruptInputError(f.roffset) + } + for j := 0; j < rep; j++ { + f.bits[i] = b + i++ + } + } + + if !f.h1.init(f.bits[0:nlit]) || !f.h2.init(f.bits[nlit:nlit+ndist]) { + if debugDecode { + fmt.Println("init2 failed") + } + return CorruptInputError(f.roffset) + } + + // As an optimization, we can initialize the maxRead bits to read at a time + // for the HLIT tree to the length of the EOB marker since we know that + // every block must terminate with one. This preserves the property that + // we never read any extra bytes after the end of the DEFLATE stream. + if f.h1.maxRead < f.bits[endBlockMarker] { + f.h1.maxRead = f.bits[endBlockMarker] + } + if !f.final { + // If not the final block, the smallest block possible is + // a predefined table, BTYPE=01, with a single EOB marker. + // This will take up 3 + 7 bits. + f.h1.maxRead += 10 + } + + return nil +} + +// Copy a single uncompressed data block from input to output. +func (f *decompressor) dataBlock() { + // Uncompressed. + // Discard current half-byte. + left := (f.nb) & 7 + f.nb -= left + f.b >>= left + + offBytes := f.nb >> 3 + // Unfilled values will be overwritten. + f.buf[0] = uint8(f.b) + f.buf[1] = uint8(f.b >> 8) + f.buf[2] = uint8(f.b >> 16) + f.buf[3] = uint8(f.b >> 24) + + f.roffset += int64(offBytes) + f.nb, f.b = 0, 0 + + // Length then ones-complement of length. + nr, err := io.ReadFull(f.r, f.buf[offBytes:4]) + f.roffset += int64(nr) + if err != nil { + f.err = noEOF(err) + return + } + n := uint16(f.buf[0]) | uint16(f.buf[1])<<8 + nn := uint16(f.buf[2]) | uint16(f.buf[3])<<8 + if nn != ^n { + if debugDecode { + ncomp := ^n + fmt.Println("uint16(nn) != uint16(^n)", nn, ncomp) + } + f.err = CorruptInputError(f.roffset) + return + } + + if n == 0 { + if f.flushMode == syncFlush { + f.toRead = f.dict.readFlush() + } + + f.finishBlock() + return + } + + f.copyLen = int(n) + f.copyData() +} + +// copyData copies f.copyLen bytes from the underlying reader into f.hist. +// It pauses for reads when f.hist is full. +func (f *decompressor) copyData() { + buf := f.dict.writeSlice() + if len(buf) > f.copyLen { + buf = buf[:f.copyLen] + } + + cnt, err := io.ReadFull(f.r, buf) + f.roffset += int64(cnt) + f.copyLen -= cnt + f.dict.writeMark(cnt) + if err != nil { + f.err = noEOF(err) + return + } + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = copyData + return + } + f.finishBlock() +} + +func (f *decompressor) finishBlock() { + if f.final { + if f.dict.availRead() > 0 { + f.toRead = f.dict.readFlush() + } + + f.err = io.EOF + } else if f.flushMode == partialFlush && f.dict.availRead() > 0 { + f.toRead = f.dict.readFlush() + } + + f.step = nextBlock +} + +func (f *decompressor) doStep() { + switch f.step { + case copyData: + f.copyData() + case nextBlock: + f.nextBlock() + case huffmanBytesBuffer: + f.huffmanBytesBuffer() + case huffmanBytesReader: + f.huffmanBytesReader() + case huffmanBufioReader: + f.huffmanBufioReader() + case huffmanStringsReader: + f.huffmanStringsReader() + case huffmanGenericReader: + f.huffmanGenericReader() + default: + panic("BUG: unexpected step state") + } +} + +// noEOF returns err, unless err == io.EOF, in which case it returns io.ErrUnexpectedEOF. +func noEOF(e error) error { + if e == io.EOF { + return io.ErrUnexpectedEOF + } + return e +} + +func (f *decompressor) moreBits() error { + c, err := f.r.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << (f.nb & regSizeMaskUint32) + f.nb += 8 + return nil +} + +// Read the next Huffman-encoded symbol from f according to h. +func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(h.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := f.r.ReadByte() + if err != nil { + f.b = b + f.nb = nb + return 0, noEOF(err) + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := h.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return 0, f.err + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + return int(chunk >> huffmanValueShift), nil + } + } +} + +func makeReader(r io.Reader) Reader { + if rr, ok := r.(Reader); ok { + return rr + } + return bufio.NewReader(r) +} + +func fixedHuffmanDecoderInit() { + fixedOnce.Do(func() { + // These come from the RFC section 3.2.6. + var bits [288]int + for i := range 144 { + bits[i] = 8 + } + for i := 144; i < 256; i++ { + bits[i] = 9 + } + for i := 256; i < 280; i++ { + bits[i] = 7 + } + for i := 280; i < 288; i++ { + bits[i] = 8 + } + fixedHuffmanDecoder.init(bits[:]) + }) +} + +func (f *decompressor) Reset(r io.Reader, dict []byte) error { + *f = decompressor{ + r: makeReader(r), + bits: f.bits, + codebits: f.codebits, + h1: f.h1, + h2: f.h2, + dict: f.dict, + step: nextBlock, + } + f.dict.init(maxMatchOffset, dict) + return nil +} + +type ReaderOpt func(*decompressor) + +// WithPartialBlock tells decompressor to return after each block, +// so it can read data written with partial flush +func WithPartialBlock() ReaderOpt { + return func(f *decompressor) { + f.flushMode = partialFlush + } +} + +// WithDict initializes the reader with a preset dictionary +func WithDict(dict []byte) ReaderOpt { + return func(f *decompressor) { + f.dict.init(maxMatchOffset, dict) + } +} + +// NewReaderOpts returns new reader with provided options +func NewReaderOpts(r io.Reader, opts ...ReaderOpt) io.ReadCloser { + fixedHuffmanDecoderInit() + + var f decompressor + f.r = makeReader(r) + f.bits = new([maxNumLit + maxNumDist]int) + f.codebits = new([numCodes]int) + f.step = nextBlock + f.dict.init(maxMatchOffset, nil) + + for _, opt := range opts { + opt(&f) + } + + return &f +} + +// NewReader returns a new ReadCloser that can be used +// to read the uncompressed version of r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. +// It is the caller's responsibility to call Close on the ReadCloser +// when finished reading. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReader(r io.Reader) io.ReadCloser { + return NewReaderOpts(r) +} + +// NewReaderDict is like NewReader but initializes the reader +// with a preset dictionary. The returned Reader behaves as if +// the uncompressed data stream started with the given dictionary, +// which has already been read. NewReaderDict is typically used +// to read data compressed by NewWriterDict. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser { + return NewReaderOpts(r, WithDict(dict)) +} diff --git a/vendor/github.com/klauspost/compress/flate/inflate_gen.go b/vendor/github.com/klauspost/compress/flate/inflate_gen.go new file mode 100644 index 0000000..2b2f993 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/inflate_gen.go @@ -0,0 +1,1283 @@ +// Code generated by go generate gen_inflate.go. DO NOT EDIT. + +package flate + +import ( + "bufio" + "bytes" + "fmt" + "math/bits" + "strings" +) + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBytesBuffer() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*bytes.Buffer) + + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + fnb, fb, dict := f.nb, f.b, &f.dict + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var length int + switch { + case v < 256: + dict.writeByte(byte(v)) + if dict.availWrite() == 0 { + f.toRead = dict.readFlush() + f.step = huffmanBytesBuffer + f.stepState = stateInit + f.b, f.nb = fb, fnb + return + } + goto readLiteral + case v == 256: + f.b, f.nb = fb, fnb + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + case v < maxNumLit: + val := decCodeToLen[(v - 257)] + length = int(val.length) + 3 + n := uint(val.extra) + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + length += int(fb & bitMask32[n]) + fb >>= n & regSizeMaskUint32 + fnb -= n + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + f.b, f.nb = fb, fnb + return + } + + var dist uint32 + if f.hd == nil { + for fnb < 5 { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) + fb >>= 5 + fnb -= 5 + } else { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hd.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hd.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hd.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + dist = uint32(chunk >> huffmanValueShift) + break + } + } + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for fnb < nb { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fnb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + // slower: dist = bitMask32[nb+1] + 2 + extra + default: + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(dict.histSize()) { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist > dict.histSize():", dist, dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = dict.readFlush() + f.step = huffmanBytesBuffer // We need to continue this work + f.stepState = stateDict + f.b, f.nb = fb, fnb + return + } + goto readLiteral + } + // Not reached +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBytesReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*bytes.Reader) + + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + fnb, fb, dict := f.nb, f.b, &f.dict + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var length int + switch { + case v < 256: + dict.writeByte(byte(v)) + if dict.availWrite() == 0 { + f.toRead = dict.readFlush() + f.step = huffmanBytesReader + f.stepState = stateInit + f.b, f.nb = fb, fnb + return + } + goto readLiteral + case v == 256: + f.b, f.nb = fb, fnb + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + case v < maxNumLit: + val := decCodeToLen[(v - 257)] + length = int(val.length) + 3 + n := uint(val.extra) + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + length += int(fb & bitMask32[n]) + fb >>= n & regSizeMaskUint32 + fnb -= n + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + f.b, f.nb = fb, fnb + return + } + + var dist uint32 + if f.hd == nil { + for fnb < 5 { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) + fb >>= 5 + fnb -= 5 + } else { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hd.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hd.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hd.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + dist = uint32(chunk >> huffmanValueShift) + break + } + } + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for fnb < nb { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fnb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + // slower: dist = bitMask32[nb+1] + 2 + extra + default: + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(dict.histSize()) { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist > dict.histSize():", dist, dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = dict.readFlush() + f.step = huffmanBytesReader // We need to continue this work + f.stepState = stateDict + f.b, f.nb = fb, fnb + return + } + goto readLiteral + } + // Not reached +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBufioReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*bufio.Reader) + + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + fnb, fb, dict := f.nb, f.b, &f.dict + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var length int + switch { + case v < 256: + dict.writeByte(byte(v)) + if dict.availWrite() == 0 { + f.toRead = dict.readFlush() + f.step = huffmanBufioReader + f.stepState = stateInit + f.b, f.nb = fb, fnb + return + } + goto readLiteral + case v == 256: + f.b, f.nb = fb, fnb + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + case v < maxNumLit: + val := decCodeToLen[(v - 257)] + length = int(val.length) + 3 + n := uint(val.extra) + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + length += int(fb & bitMask32[n]) + fb >>= n & regSizeMaskUint32 + fnb -= n + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + f.b, f.nb = fb, fnb + return + } + + var dist uint32 + if f.hd == nil { + for fnb < 5 { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) + fb >>= 5 + fnb -= 5 + } else { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hd.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hd.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hd.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + dist = uint32(chunk >> huffmanValueShift) + break + } + } + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for fnb < nb { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fnb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + // slower: dist = bitMask32[nb+1] + 2 + extra + default: + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(dict.histSize()) { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist > dict.histSize():", dist, dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = dict.readFlush() + f.step = huffmanBufioReader // We need to continue this work + f.stepState = stateDict + f.b, f.nb = fb, fnb + return + } + goto readLiteral + } + // Not reached +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanStringsReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*strings.Reader) + + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + fnb, fb, dict := f.nb, f.b, &f.dict + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var length int + switch { + case v < 256: + dict.writeByte(byte(v)) + if dict.availWrite() == 0 { + f.toRead = dict.readFlush() + f.step = huffmanStringsReader + f.stepState = stateInit + f.b, f.nb = fb, fnb + return + } + goto readLiteral + case v == 256: + f.b, f.nb = fb, fnb + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + case v < maxNumLit: + val := decCodeToLen[(v - 257)] + length = int(val.length) + 3 + n := uint(val.extra) + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + length += int(fb & bitMask32[n]) + fb >>= n & regSizeMaskUint32 + fnb -= n + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + f.b, f.nb = fb, fnb + return + } + + var dist uint32 + if f.hd == nil { + for fnb < 5 { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) + fb >>= 5 + fnb -= 5 + } else { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hd.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hd.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hd.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + dist = uint32(chunk >> huffmanValueShift) + break + } + } + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for fnb < nb { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fnb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + // slower: dist = bitMask32[nb+1] + 2 + extra + default: + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(dict.histSize()) { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist > dict.histSize():", dist, dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = dict.readFlush() + f.step = huffmanStringsReader // We need to continue this work + f.stepState = stateDict + f.b, f.nb = fb, fnb + return + } + goto readLiteral + } + // Not reached +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanGenericReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(Reader) + + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + fnb, fb, dict := f.nb, f.b, &f.dict + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var length int + switch { + case v < 256: + dict.writeByte(byte(v)) + if dict.availWrite() == 0 { + f.toRead = dict.readFlush() + f.step = huffmanGenericReader + f.stepState = stateInit + f.b, f.nb = fb, fnb + return + } + goto readLiteral + case v == 256: + f.b, f.nb = fb, fnb + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + case v < maxNumLit: + val := decCodeToLen[(v - 257)] + length = int(val.length) + 3 + n := uint(val.extra) + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + length += int(fb & bitMask32[n]) + fb >>= n & regSizeMaskUint32 + fnb -= n + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + f.b, f.nb = fb, fnb + return + } + + var dist uint32 + if f.hd == nil { + for fnb < 5 { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) + fb >>= 5 + fnb -= 5 + } else { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hd.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + for { + for fnb < n { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } + f.roffset++ + fb |= uint32(c) << (fnb & regSizeMaskUint32) + fnb += 8 + } + chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hd.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hd.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= fnb { + if n == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + fb = fb >> (n & regSizeMaskUint32) + fnb = fnb - n + dist = uint32(chunk >> huffmanValueShift) + break + } + } + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for fnb < nb { + c, err := fr.ReadByte() + if err != nil { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fnb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + // slower: dist = bitMask32[nb+1] + 2 + extra + default: + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(dict.histSize()) { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("dist > dict.histSize():", dist, dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = dict.readFlush() + f.step = huffmanGenericReader // We need to continue this work + f.stepState = stateDict + f.b, f.nb = fb, fnb + return + } + goto readLiteral + } + // Not reached +} + +func (f *decompressor) huffmanBlockDecoder() { + switch f.r.(type) { + case *bytes.Buffer: + f.huffmanBytesBuffer() + case *bytes.Reader: + f.huffmanBytesReader() + case *bufio.Reader: + f.huffmanBufioReader() + case *strings.Reader: + f.huffmanStringsReader() + case Reader: + f.huffmanGenericReader() + default: + f.huffmanGenericReader() + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level1.go b/vendor/github.com/klauspost/compress/flate/level1.go new file mode 100644 index 0000000..c3581a3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level1.go @@ -0,0 +1,215 @@ +package flate + +import ( + "fmt" + + "github.com/klauspost/compress/internal/le" +) + +// fastGen maintains the table for matches, +// and the previous byte block for level 2. +// This is the generic implementation. +type fastEncL1 struct { + fastGen + table [tableSize]tableEntry +} + +// EncodeL1 uses a similar algorithm to level 1 +func (e *fastEncL1) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + hashBytes = 5 + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + + for { + const skipLog = 5 + const doEvery = 2 + + nextS := s + var candidate tableEntry + var t int32 + for { + nextHash := hashLen(cv, tableBits, hashBytes) + candidate = e.table[nextHash] + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + + now := load6432(src, nextS) + e.table[nextHash] = tableEntry{offset: s + e.cur} + nextHash = hashLen(now, tableBits, hashBytes) + t = candidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + e.table[nextHash] = tableEntry{offset: nextS + e.cur} + break + } + + // Do one right away... + cv = now + s = nextS + nextS++ + candidate = e.table[nextHash] + now >>= 8 + e.table[nextHash] = tableEntry{offset: s + e.cur} + + t = candidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + e.table[nextHash] = tableEntry{offset: nextS + e.cur} + break + } + cv = now + s = nextS + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + l := e.matchlenLong(int(s+4), int(t+4), src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && le.Load8(src, t-1) == le.Load8(src, s-1) { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + + // Save the match found + if false { + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + } else { + // Inlined... + xoffset := uint32(s - t - baseMatchOffset) + xlength := l + oc := offsetCode(xoffset) + xoffset |= oc << 16 + for xlength > 0 { + xl := xlength + if xl > 258 { + if xl > 258+baseMatchLength { + xl = 258 + } else { + xl = 258 - baseMatchLength + } + } + xlength -= xl + xl -= baseMatchLength + dst.extraHist[lengthCodes1[uint8(xl)]]++ + dst.offHist[oc]++ + dst.tokens[dst.n] = token(matchType | uint32(xl)<= s { + s = nextS + 1 + } + if s >= sLimit { + // Index first pair after match end. + if int(s+l+8) < len(src) { + cv := load6432(src, s) + e.table[hashLen(cv, tableBits, hashBytes)] = tableEntry{offset: s + e.cur} + } + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load6432(src, s-2) + o := e.cur + s - 2 + prevHash := hashLen(x, tableBits, hashBytes) + e.table[prevHash] = tableEntry{offset: o} + x >>= 16 + currHash := hashLen(x, tableBits, hashBytes) + candidate = e.table[currHash] + e.table[currHash] = tableEntry{offset: o + 2} + + t = candidate.offset - e.cur + if s-t > maxMatchOffset || uint32(x) != load3232(src, t) { + cv = x >> 8 + s++ + break + } + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level2.go b/vendor/github.com/klauspost/compress/flate/level2.go new file mode 100644 index 0000000..c8d047f --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level2.go @@ -0,0 +1,214 @@ +package flate + +import "fmt" + +// fastGen maintains the table for matches, +// and the previous byte block for level 2. +// This is the generic implementation. +type fastEncL2 struct { + fastGen + table [bTableSize]tableEntry +} + +// EncodeL2 uses a similar algorithm to level 1, but is capable +// of matching across blocks giving better compression at a small slowdown. +func (e *fastEncL2) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + hashBytes = 5 + ) + + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + // When should we start skipping if we haven't found matches in a long while. + const skipLog = 5 + const doEvery = 2 + + nextS := s + var candidate tableEntry + for { + nextHash := hashLen(cv, bTableBits, hashBytes) + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + candidate = e.table[nextHash] + now := load6432(src, nextS) + e.table[nextHash] = tableEntry{offset: s + e.cur} + nextHash = hashLen(now, bTableBits, hashBytes) + + offset := s - (candidate.offset - e.cur) + if offset < maxMatchOffset && uint32(cv) == load3232(src, candidate.offset-e.cur) { + e.table[nextHash] = tableEntry{offset: nextS + e.cur} + break + } + + // Do one right away... + cv = now + s = nextS + nextS++ + candidate = e.table[nextHash] + now >>= 8 + e.table[nextHash] = tableEntry{offset: s + e.cur} + + offset = s - (candidate.offset - e.cur) + if offset < maxMatchOffset && uint32(cv) == load3232(src, candidate.offset-e.cur) { + break + } + cv = now + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + t := candidate.offset - e.cur + l := e.matchlenLong(int(s+4), int(t+4), src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + // Index first pair after match end. + if int(s+l+8) < len(src) { + cv := load6432(src, s) + e.table[hashLen(cv, bTableBits, hashBytes)] = tableEntry{offset: s + e.cur} + } + goto emitRemainder + } + + // Store every second hash in-between, but offset by 1. + for i := s - l + 2; i < s-5; i += 7 { + x := load6432(src, i) + nextHash := hashLen(x, bTableBits, hashBytes) + e.table[nextHash] = tableEntry{offset: e.cur + i} + // Skip one + x >>= 16 + nextHash = hashLen(x, bTableBits, hashBytes) + e.table[nextHash] = tableEntry{offset: e.cur + i + 2} + // Skip one + x >>= 16 + nextHash = hashLen(x, bTableBits, hashBytes) + e.table[nextHash] = tableEntry{offset: e.cur + i + 4} + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 to s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load6432(src, s-2) + o := e.cur + s - 2 + prevHash := hashLen(x, bTableBits, hashBytes) + prevHash2 := hashLen(x>>8, bTableBits, hashBytes) + e.table[prevHash] = tableEntry{offset: o} + e.table[prevHash2] = tableEntry{offset: o + 1} + currHash := hashLen(x>>16, bTableBits, hashBytes) + candidate = e.table[currHash] + e.table[currHash] = tableEntry{offset: o + 2} + + offset := s - (candidate.offset - e.cur) + if offset > maxMatchOffset || uint32(x>>16) != load3232(src, candidate.offset-e.cur) { + cv = x >> 24 + s++ + break + } + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level3.go b/vendor/github.com/klauspost/compress/flate/level3.go new file mode 100644 index 0000000..33f9fb1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level3.go @@ -0,0 +1,241 @@ +package flate + +import "fmt" + +// fastEncL3 +type fastEncL3 struct { + fastGen + table [1 << 16]tableEntryPrev +} + +// Encode uses a similar algorithm to level 2, will check up to two candidates. +func (e *fastEncL3) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + tableBits = 16 + tableSize = 1 << tableBits + hashBytes = 5 + ) + + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + } + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + e.table[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // Skip if too small. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + const skipLog = 7 + nextS := s + var candidate tableEntry + for { + nextHash := hashLen(cv, tableBits, hashBytes) + s = nextS + nextS = s + 1 + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + candidates := e.table[nextHash] + now := load6432(src, nextS) + + // Safe offset distance until s + 4... + minOffset := e.cur + s - (maxMatchOffset - 4) + e.table[nextHash] = tableEntryPrev{Prev: candidates.Cur, Cur: tableEntry{offset: s + e.cur}} + + // Check both candidates + candidate = candidates.Cur + if candidate.offset < minOffset { + cv = now + // Previous will also be invalid, we have nothing. + continue + } + + if uint32(cv) == load3232(src, candidate.offset-e.cur) { + if candidates.Prev.offset < minOffset || uint32(cv) != load3232(src, candidates.Prev.offset-e.cur) { + break + } + // Both match and are valid, pick longest. + offset := s - (candidate.offset - e.cur) + o2 := s - (candidates.Prev.offset - e.cur) + l1, l2 := matchLen(src[s+4:], src[s-offset+4:]), matchLen(src[s+4:], src[s-o2+4:]) + if l2 > l1 { + candidate = candidates.Prev + } + break + } else { + // We only check if value mismatches. + // Offset will always be invalid in other cases. + candidate = candidates.Prev + if candidate.offset > minOffset && uint32(cv) == load3232(src, candidate.offset-e.cur) { + break + } + } + cv = now + } + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + // + t := candidate.offset - e.cur + l := e.matchlenLong(int(s+4), int(t+4), src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + t += l + // Index first pair after match end. + if int(t+8) < len(src) && t > 0 { + cv = load6432(src, t) + nextHash := hashLen(cv, tableBits, hashBytes) + e.table[nextHash] = tableEntryPrev{ + Prev: e.table[nextHash].Cur, + Cur: tableEntry{offset: e.cur + t}, + } + } + goto emitRemainder + } + + // Store every 5th hash in-between. + for i := s - l + 2; i < s-5; i += 6 { + nextHash := hashLen(load6432(src, i), tableBits, hashBytes) + e.table[nextHash] = tableEntryPrev{ + Prev: e.table[nextHash].Cur, + Cur: tableEntry{offset: e.cur + i}} + } + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 to s. + x := load6432(src, s-2) + prevHash := hashLen(x, tableBits, hashBytes) + + e.table[prevHash] = tableEntryPrev{ + Prev: e.table[prevHash].Cur, + Cur: tableEntry{offset: e.cur + s - 2}, + } + x >>= 8 + prevHash = hashLen(x, tableBits, hashBytes) + + e.table[prevHash] = tableEntryPrev{ + Prev: e.table[prevHash].Cur, + Cur: tableEntry{offset: e.cur + s - 1}, + } + x >>= 8 + currHash := hashLen(x, tableBits, hashBytes) + candidates := e.table[currHash] + cv = x + e.table[currHash] = tableEntryPrev{ + Prev: candidates.Cur, + Cur: tableEntry{offset: s + e.cur}, + } + + // Check both candidates + candidate = candidates.Cur + minOffset := e.cur + s - (maxMatchOffset - 4) + + if candidate.offset > minOffset { + if uint32(cv) == load3232(src, candidate.offset-e.cur) { + // Found a match... + continue + } + candidate = candidates.Prev + if candidate.offset > minOffset && uint32(cv) == load3232(src, candidate.offset-e.cur) { + // Match at prev... + continue + } + } + cv = x >> 8 + s++ + break + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level4.go b/vendor/github.com/klauspost/compress/flate/level4.go new file mode 100644 index 0000000..88509e1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level4.go @@ -0,0 +1,221 @@ +package flate + +import "fmt" + +type fastEncL4 struct { + fastGen + table [tableSize]tableEntry + bTable [tableSize]tableEntry +} + +func (e *fastEncL4) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + hashShortBytes = 4 + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntry{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.bTable[i].offset = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + const skipLog = 6 + const doEvery = 1 + + nextS := s + var t int32 + for { + nextHashS := hashLen(cv, tableBits, hashShortBytes) + nextHashL := hash7(cv, tableBits) + + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + e.bTable[nextHashL] = entry + + t = lCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // We got a long match. Use that. + break + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Found a 4 match... + lCandidate = e.bTable[hash7(next, tableBits)] + + // If the next long is a candidate, check if we should use that instead... + lOff := lCandidate.offset - e.cur + if nextS-lOff < maxMatchOffset && load3232(src, lOff) == uint32(next) { + l1, l2 := matchLen(src[s+4:], src[t+4:]), matchLen(src[nextS+4:], src[nextS-lOff+4:]) + if l2 > l1 { + s = nextS + t = lCandidate.offset - e.cur + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Extend the 4-byte match as long as possible. + l := e.matchlenLong(int(s+4), int(t+4), src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + if debugDeflate { + if t >= s { + panic("s-t") + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + // Index first pair after match end. + if int(s+8) < len(src) { + cv := load6432(src, s) + e.table[hashLen(cv, tableBits, hashShortBytes)] = tableEntry{offset: s + e.cur} + e.bTable[hash7(cv, tableBits)] = tableEntry{offset: s + e.cur} + } + goto emitRemainder + } + + // Store every 3rd hash in-between + if true { + i := nextS + if i < s-1 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + e.bTable[hash7(cv, tableBits)] = t + e.bTable[hash7(cv>>8, tableBits)] = t2 + e.table[hashLen(cv>>8, tableBits, hashShortBytes)] = t2 + + i += 3 + for ; i < s-1; i += 3 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + e.bTable[hash7(cv, tableBits)] = t + e.bTable[hash7(cv>>8, tableBits)] = t2 + e.table[hashLen(cv>>8, tableBits, hashShortBytes)] = t2 + } + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + x := load6432(src, s-1) + o := e.cur + s - 1 + prevHashS := hashLen(x, tableBits, hashShortBytes) + prevHashL := hash7(x, tableBits) + e.table[prevHashS] = tableEntry{offset: o} + e.bTable[prevHashL] = tableEntry{offset: o} + cv = x >> 8 + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level5.go b/vendor/github.com/klauspost/compress/flate/level5.go new file mode 100644 index 0000000..a22ad7d --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level5.go @@ -0,0 +1,705 @@ +package flate + +import "fmt" + +type fastEncL5 struct { + fastGen + table [tableSize]tableEntry + bTable [tableSize]tableEntryPrev +} + +func (e *fastEncL5) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + hashShortBytes = 4 + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + v.Prev.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + } + e.bTable[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + const skipLog = 6 + const doEvery = 1 + + nextS := s + var l int32 + var t int32 + for { + nextHashS := hashLen(cv, tableBits, hashShortBytes) + nextHashL := hash7(cv, tableBits) + + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = entry, eLong.Cur + + nextHashS = hashLen(next, tableBits, hashShortBytes) + nextHashL = hash7(next, tableBits) + + t = lCandidate.Cur.offset - e.cur + if s-t < maxMatchOffset { + if uint32(cv) == load3232(src, t) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + t2 := lCandidate.Prev.offset - e.cur + if s-t2 < maxMatchOffset && uint32(cv) == load3232(src, t2) { + l = e.matchlen(int(s+4), int(t+4), src) + 4 + ml1 := e.matchlen(int(s+4), int(t2+4), src) + 4 + if ml1 > l { + t = t2 + l = ml1 + break + } + } + break + } + t = lCandidate.Prev.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + break + } + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Found a 4 match... + l = e.matchlen(int(s+4), int(t+4), src) + 4 + lCandidate = e.bTable[nextHashL] + // Store the next match + + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // If the next long is a candidate, use that... + t2 := lCandidate.Cur.offset - e.cur + if nextS-t2 < maxMatchOffset { + if load3232(src, t2) == uint32(next) { + ml := e.matchlen(int(nextS+4), int(t2+4), src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + // If the previous long is a candidate, use that... + t2 = lCandidate.Prev.offset - e.cur + if nextS-t2 < maxMatchOffset && load3232(src, t2) == uint32(next) { + ml := e.matchlen(int(nextS+4), int(t2+4), src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + if l == 0 { + // Extend the 4-byte match as long as possible. + l = e.matchlenLong(int(s+4), int(t+4), src) + 4 + } else if l == maxMatchLength { + l += e.matchlenLong(int(s+l), int(t+l), src) + } + + // Try to locate a better match by checking the end of best match... + if sAt := s + l; l < 30 && sAt < sLimit { + // Allow some bytes at the beginning to mismatch. + // Sweet spot is 2/3 bytes depending on input. + // 3 is only a little better when it is but sometimes a lot worse. + // The skipped bytes are tested in Extend backwards, + // and still picked up as part of the match if they do. + const skipBeginning = 2 + eLong := e.bTable[hash7(load6432(src, sAt), tableBits)].Cur.offset + t2 := eLong - e.cur - l + skipBeginning + s2 := s + skipBeginning + off := s2 - t2 + if t2 >= 0 && off < maxMatchOffset && off > 0 { + if l2 := e.matchlenLong(int(s2), int(t2), src); l2 > l { + t = t2 + l = l2 + s = s2 + } + } + } + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + if debugDeflate { + if t >= s { + panic(fmt.Sprintln("s-t", s, t)) + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", s-t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + goto emitRemainder + } + + // Store every 3rd hash in-between. + if true { + const hashEvery = 3 + i := s - l + 1 + if i < s-1 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + e.table[hashLen(cv, tableBits, hashShortBytes)] = t + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + + // Do an long at i+1 + cv >>= 8 + t = tableEntry{offset: t.offset + 1} + eLong = &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + + // We only have enough bits for a short entry at i+2 + cv >>= 8 + t = tableEntry{offset: t.offset + 1} + e.table[hashLen(cv, tableBits, hashShortBytes)] = t + + // Skip one - otherwise we risk hitting 's' + i += 4 + for ; i < s-1; i += hashEvery { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + e.table[hashLen(cv>>8, tableBits, hashShortBytes)] = t2 + } + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + x := load6432(src, s-1) + o := e.cur + s - 1 + prevHashS := hashLen(x, tableBits, hashShortBytes) + prevHashL := hash7(x, tableBits) + e.table[prevHashS] = tableEntry{offset: o} + eLong := &e.bTable[prevHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: o}, eLong.Cur + cv = x >> 8 + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} + +// fastEncL5Window is a level 5 encoder, +// but with a custom window size. +type fastEncL5Window struct { + hist []byte + cur int32 + maxOffset int32 + table [tableSize]tableEntry + bTable [tableSize]tableEntryPrev +} + +func (e *fastEncL5Window) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + hashShortBytes = 4 + ) + maxMatchOffset := e.maxOffset + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + v.Prev.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + } + e.bTable[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + const skipLog = 6 + const doEvery = 1 + + nextS := s + var l int32 + var t int32 + for { + nextHashS := hashLen(cv, tableBits, hashShortBytes) + nextHashL := hash7(cv, tableBits) + + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = entry, eLong.Cur + + nextHashS = hashLen(next, tableBits, hashShortBytes) + nextHashL = hash7(next, tableBits) + + t = lCandidate.Cur.offset - e.cur + if s-t < maxMatchOffset { + if uint32(cv) == load3232(src, t) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + t2 := lCandidate.Prev.offset - e.cur + if s-t2 < maxMatchOffset && uint32(cv) == load3232(src, t2) { + l = e.matchlen(s+4, t+4, src) + 4 + ml1 := e.matchlen(s+4, t2+4, src) + 4 + if ml1 > l { + t = t2 + l = ml1 + break + } + } + break + } + t = lCandidate.Prev.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + break + } + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Found a 4 match... + l = e.matchlen(s+4, t+4, src) + 4 + lCandidate = e.bTable[nextHashL] + // Store the next match + + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // If the next long is a candidate, use that... + t2 := lCandidate.Cur.offset - e.cur + if nextS-t2 < maxMatchOffset { + if load3232(src, t2) == uint32(next) { + ml := e.matchlen(nextS+4, t2+4, src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + // If the previous long is a candidate, use that... + t2 = lCandidate.Prev.offset - e.cur + if nextS-t2 < maxMatchOffset && load3232(src, t2) == uint32(next) { + ml := e.matchlen(nextS+4, t2+4, src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + if l == 0 { + // Extend the 4-byte match as long as possible. + l = e.matchlenLong(s+4, t+4, src) + 4 + } else if l == maxMatchLength { + l += e.matchlenLong(s+l, t+l, src) + } + + // Try to locate a better match by checking the end of best match... + if sAt := s + l; l < 30 && sAt < sLimit { + // Allow some bytes at the beginning to mismatch. + // Sweet spot is 2/3 bytes depending on input. + // 3 is only a little better when it is but sometimes a lot worse. + // The skipped bytes are tested in Extend backwards, + // and still picked up as part of the match if they do. + const skipBeginning = 2 + eLong := e.bTable[hash7(load6432(src, sAt), tableBits)].Cur.offset + t2 := eLong - e.cur - l + skipBeginning + s2 := s + skipBeginning + off := s2 - t2 + if t2 >= 0 && off < maxMatchOffset && off > 0 { + if l2 := e.matchlenLong(s2, t2, src); l2 > l { + t = t2 + l = l2 + s = s2 + } + } + } + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + if debugDeflate { + if t >= s { + panic(fmt.Sprintln("s-t", s, t)) + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", s-t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + goto emitRemainder + } + + // Store every 3rd hash in-between. + if true { + const hashEvery = 3 + i := s - l + 1 + if i < s-1 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + e.table[hashLen(cv, tableBits, hashShortBytes)] = t + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + + // Do an long at i+1 + cv >>= 8 + t = tableEntry{offset: t.offset + 1} + eLong = &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + + // We only have enough bits for a short entry at i+2 + cv >>= 8 + t = tableEntry{offset: t.offset + 1} + e.table[hashLen(cv, tableBits, hashShortBytes)] = t + + // Skip one - otherwise we risk hitting 's' + i += 4 + for ; i < s-1; i += hashEvery { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + e.table[hashLen(cv>>8, tableBits, hashShortBytes)] = t2 + } + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + x := load6432(src, s-1) + o := e.cur + s - 1 + prevHashS := hashLen(x, tableBits, hashShortBytes) + prevHashL := hash7(x, tableBits) + e.table[prevHashS] = tableEntry{offset: o} + eLong := &e.bTable[prevHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: o}, eLong.Cur + cv = x >> 8 + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} + +// Reset the encoding table. +func (e *fastEncL5Window) Reset() { + // We keep the same allocs, since we are compressing the same block sizes. + if cap(e.hist) < allocHistory { + e.hist = make([]byte, 0, allocHistory) + } + + // We offset current position so everything will be out of reach. + // If we are above the buffer reset it will be cleared anyway since len(hist) == 0. + if e.cur <= int32(bufferReset) { + e.cur += e.maxOffset + int32(len(e.hist)) + } + e.hist = e.hist[:0] +} + +func (e *fastEncL5Window) addBlock(src []byte) int32 { + // check if we have space already + maxMatchOffset := e.maxOffset + + if len(e.hist)+len(src) > cap(e.hist) { + if cap(e.hist) == 0 { + e.hist = make([]byte, 0, allocHistory) + } else { + if cap(e.hist) < int(maxMatchOffset*2) { + panic("unexpected buffer size") + } + // Move down + offset := int32(len(e.hist)) - maxMatchOffset + copy(e.hist[0:maxMatchOffset], e.hist[offset:]) + e.cur += offset + e.hist = e.hist[:maxMatchOffset] + } + } + s := int32(len(e.hist)) + e.hist = append(e.hist, src...) + return s +} + +// matchlen will return the match length between offsets and t in src. +// The maximum length returned is maxMatchLength - 4. +// It is assumed that s > t, that t >=0 and s < len(src). +func (e *fastEncL5Window) matchlen(s, t int32, src []byte) int32 { + if debugDecode { + if t >= s { + panic(fmt.Sprint("t >=s:", t, s)) + } + if int(s) >= len(src) { + panic(fmt.Sprint("s >= len(src):", s, len(src))) + } + if t < 0 { + panic(fmt.Sprint("t < 0:", t)) + } + if s-t > e.maxOffset { + panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) + } + } + s1 := min(int(s)+maxMatchLength-4, len(src)) + + // Extend the match to be as long as possible. + return int32(matchLen(src[s:s1], src[t:])) +} + +// matchlenLong will return the match length between offsets and t in src. +// It is assumed that s > t, that t >=0 and s < len(src). +func (e *fastEncL5Window) matchlenLong(s, t int32, src []byte) int32 { + if debugDeflate { + if t >= s { + panic(fmt.Sprint("t >=s:", t, s)) + } + if int(s) >= len(src) { + panic(fmt.Sprint("s >= len(src):", s, len(src))) + } + if t < 0 { + panic(fmt.Sprint("t < 0:", t)) + } + if s-t > e.maxOffset { + panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) + } + } + // Extend the match to be as long as possible. + return int32(matchLen(src[s:], src[t:])) +} diff --git a/vendor/github.com/klauspost/compress/flate/level6.go b/vendor/github.com/klauspost/compress/flate/level6.go new file mode 100644 index 0000000..96f5bb4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level6.go @@ -0,0 +1,325 @@ +package flate + +import "fmt" + +type fastEncL6 struct { + fastGen + table [tableSize]tableEntry + bTable [tableSize]tableEntryPrev +} + +func (e *fastEncL6) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + hashShortBytes = 4 + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + v.Prev.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + } + e.bTable[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + // Repeat MUST be > 1 and within range + repeat := int32(1) + for { + const skipLog = 7 + const doEvery = 1 + + nextS := s + var l int32 + var t int32 + for { + nextHashS := hashLen(cv, tableBits, hashShortBytes) + nextHashL := hash7(cv, tableBits) + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = entry, eLong.Cur + + // Calculate hashes of 'next' + nextHashS = hashLen(next, tableBits, hashShortBytes) + nextHashL = hash7(next, tableBits) + + t = lCandidate.Cur.offset - e.cur + if s-t < maxMatchOffset { + if uint32(cv) == load3232(src, t) { + // Long candidate matches at least 4 bytes. + + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // Check the previous long candidate as well. + t2 := lCandidate.Prev.offset - e.cur + if s-t2 < maxMatchOffset && uint32(cv) == load3232(src, t2) { + l = e.matchlen(int(s+4), int(t+4), src) + 4 + ml1 := e.matchlen(int(s+4), int(t2+4), src) + 4 + if ml1 > l { + t = t2 + l = ml1 + break + } + } + break + } + // Current value did not match, but check if previous long value does. + t = lCandidate.Prev.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + break + } + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, t) { + // Found a 4 match... + l = e.matchlen(int(s+4), int(t+4), src) + 4 + + // Look up next long candidate (at nextS) + lCandidate = e.bTable[nextHashL] + + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // Check repeat at s + repOff + const repOff = 1 + t2 := s - repeat + repOff + if load3232(src, t2) == uint32(cv>>(8*repOff)) { + ml := e.matchlen(int(s+4+repOff), int(t2+4), src) + 4 + if ml > l { + t = t2 + l = ml + s += repOff + // Not worth checking more. + break + } + } + + // If the next long is a candidate, use that... + t2 = lCandidate.Cur.offset - e.cur + if nextS-t2 < maxMatchOffset { + if load3232(src, t2) == uint32(next) { + ml := e.matchlen(int(nextS+4), int(t2+4), src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + // This is ok, but check previous as well. + } + } + // If the previous long is a candidate, use that... + t2 = lCandidate.Prev.offset - e.cur + if nextS-t2 < maxMatchOffset && load3232(src, t2) == uint32(next) { + ml := e.matchlen(int(nextS+4), int(t2+4), src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Extend the 4-byte match as long as possible. + if l == 0 { + l = e.matchlenLong(int(s+4), int(t+4), src) + 4 + } else if l == maxMatchLength { + l += e.matchlenLong(int(s+l), int(t+l), src) + } + + // Try to locate a better match by checking the end-of-match... + if sAt := s + l; sAt < sLimit { + // Allow some bytes at the beginning to mismatch. + // Sweet spot is 2/3 bytes depending on input. + // 3 is only a little better when it is but sometimes a lot worse. + // The skipped bytes are tested in Extend backwards, + // and still picked up as part of the match if they do. + const skipBeginning = 2 + eLong := &e.bTable[hash7(load6432(src, sAt), tableBits)] + // Test current + t2 := eLong.Cur.offset - e.cur - l + skipBeginning + s2 := s + skipBeginning + off := s2 - t2 + if off < maxMatchOffset { + if off > 0 && t2 >= 0 { + if l2 := e.matchlenLong(int(s2), int(t2), src); l2 > l { + t = t2 + l = l2 + s = s2 + } + } + // Test next: + t2 = eLong.Prev.offset - e.cur - l + skipBeginning + off := s2 - t2 + if off > 0 && off < maxMatchOffset && t2 >= 0 { + if l2 := e.matchlenLong(int(s2), int(t2), src); l2 > l { + t = t2 + l = l2 + s = s2 + } + } + } + } + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + if false { + if t >= s { + panic(fmt.Sprintln("s-t", s, t)) + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", s-t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + repeat = s - t + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + // Index after match end. + for i := nextS + 1; i < int32(len(src))-8; i += 2 { + cv := load6432(src, i) + e.table[hashLen(cv, tableBits, hashShortBytes)] = tableEntry{offset: i + e.cur} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = tableEntry{offset: i + e.cur}, eLong.Cur + } + goto emitRemainder + } + + // Store every long hash in-between and every second short. + if true { + for i := nextS + 1; i < s-1; i += 2 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong2 := &e.bTable[hash7(cv>>8, tableBits)] + e.table[hashLen(cv, tableBits, hashShortBytes)] = t + eLong.Cur, eLong.Prev = t, eLong.Cur + eLong2.Cur, eLong2.Prev = t2, eLong2.Cur + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + cv = load6432(src, s) + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/matchlen_generic.go b/vendor/github.com/klauspost/compress/flate/matchlen_generic.go new file mode 100644 index 0000000..6149384 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/matchlen_generic.go @@ -0,0 +1,34 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +package flate + +import ( + "math/bits" + + "github.com/klauspost/compress/internal/le" +) + +// matchLen returns the maximum common prefix length of a and b. +// a must be the shortest of the two. +func matchLen(a, b []byte) (n int) { + left := len(a) + for left >= 8 { + diff := le.Load64(a, n) ^ le.Load64(b, n) + if diff != 0 { + return n + bits.TrailingZeros64(diff)>>3 + } + n += 8 + left -= 8 + } + + a = a[n:] + b = b[n:] + for i := range a { + if a[i] != b[i] { + break + } + n++ + } + return n +} diff --git a/vendor/github.com/klauspost/compress/flate/regmask_amd64.go b/vendor/github.com/klauspost/compress/flate/regmask_amd64.go new file mode 100644 index 0000000..6ed2806 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/regmask_amd64.go @@ -0,0 +1,37 @@ +package flate + +const ( + // Masks for shifts with register sizes of the shift value. + // This can be used to work around the x86 design of shifting by mod register size. + // It can be used when a variable shift is always smaller than the register size. + + // reg8SizeMaskX - shift value is 8 bits, shifted is X + reg8SizeMask8 = 7 + reg8SizeMask16 = 15 + reg8SizeMask32 = 31 + reg8SizeMask64 = 63 + + // reg16SizeMaskX - shift value is 16 bits, shifted is X + reg16SizeMask8 = reg8SizeMask8 + reg16SizeMask16 = reg8SizeMask16 + reg16SizeMask32 = reg8SizeMask32 + reg16SizeMask64 = reg8SizeMask64 + + // reg32SizeMaskX - shift value is 32 bits, shifted is X + reg32SizeMask8 = reg8SizeMask8 + reg32SizeMask16 = reg8SizeMask16 + reg32SizeMask32 = reg8SizeMask32 + reg32SizeMask64 = reg8SizeMask64 + + // reg64SizeMaskX - shift value is 64 bits, shifted is X + reg64SizeMask8 = reg8SizeMask8 + reg64SizeMask16 = reg8SizeMask16 + reg64SizeMask32 = reg8SizeMask32 + reg64SizeMask64 = reg8SizeMask64 + + // regSizeMaskUintX - shift value is uint, shifted is X + regSizeMaskUint8 = reg8SizeMask8 + regSizeMaskUint16 = reg8SizeMask16 + regSizeMaskUint32 = reg8SizeMask32 + regSizeMaskUint64 = reg8SizeMask64 +) diff --git a/vendor/github.com/klauspost/compress/flate/regmask_other.go b/vendor/github.com/klauspost/compress/flate/regmask_other.go new file mode 100644 index 0000000..1b7a2cb --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/regmask_other.go @@ -0,0 +1,40 @@ +//go:build !amd64 +// +build !amd64 + +package flate + +const ( + // Masks for shifts with register sizes of the shift value. + // This can be used to work around the x86 design of shifting by mod register size. + // It can be used when a variable shift is always smaller than the register size. + + // reg8SizeMaskX - shift value is 8 bits, shifted is X + reg8SizeMask8 = 0xff + reg8SizeMask16 = 0xff + reg8SizeMask32 = 0xff + reg8SizeMask64 = 0xff + + // reg16SizeMaskX - shift value is 16 bits, shifted is X + reg16SizeMask8 = 0xffff + reg16SizeMask16 = 0xffff + reg16SizeMask32 = 0xffff + reg16SizeMask64 = 0xffff + + // reg32SizeMaskX - shift value is 32 bits, shifted is X + reg32SizeMask8 = 0xffffffff + reg32SizeMask16 = 0xffffffff + reg32SizeMask32 = 0xffffffff + reg32SizeMask64 = 0xffffffff + + // reg64SizeMaskX - shift value is 64 bits, shifted is X + reg64SizeMask8 = 0xffffffffffffffff + reg64SizeMask16 = 0xffffffffffffffff + reg64SizeMask32 = 0xffffffffffffffff + reg64SizeMask64 = 0xffffffffffffffff + + // regSizeMaskUintX - shift value is uint, shifted is X + regSizeMaskUint8 = ^uint(0) + regSizeMaskUint16 = ^uint(0) + regSizeMaskUint32 = ^uint(0) + regSizeMaskUint64 = ^uint(0) +) diff --git a/vendor/github.com/klauspost/compress/flate/stateless.go b/vendor/github.com/klauspost/compress/flate/stateless.go new file mode 100644 index 0000000..455ed3e --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/stateless.go @@ -0,0 +1,325 @@ +package flate + +import ( + "io" + "math" + "sync" + + "github.com/klauspost/compress/internal/le" +) + +const ( + maxStatelessBlock = math.MaxInt16 + // dictionary will be taken from maxStatelessBlock, so limit it. + maxStatelessDict = 8 << 10 + + slTableBits = 13 + slTableSize = 1 << slTableBits + slTableShift = 32 - slTableBits +) + +type statelessWriter struct { + dst io.Writer + closed bool +} + +func (s *statelessWriter) Close() error { + if s.closed { + return nil + } + s.closed = true + // Emit EOF block + return StatelessDeflate(s.dst, nil, true, nil) +} + +func (s *statelessWriter) Write(p []byte) (n int, err error) { + err = StatelessDeflate(s.dst, p, false, nil) + if err != nil { + return 0, err + } + return len(p), nil +} + +func (s *statelessWriter) Reset(w io.Writer) { + s.dst = w + s.closed = false +} + +// NewStatelessWriter will do compression but without maintaining any state +// between Write calls. +// There will be no memory kept between Write calls, +// but compression and speed will be suboptimal. +// Because of this, the size of actual Write calls will affect output size. +func NewStatelessWriter(dst io.Writer) io.WriteCloser { + return &statelessWriter{dst: dst} +} + +// bitWriterPool contains bit writers that can be reused. +var bitWriterPool = sync.Pool{ + New: func() any { + return newHuffmanBitWriter(nil) + }, +} + +// tokensPool contains tokens struct objects that can be reused +var tokensPool = sync.Pool{ + New: func() any { + return &tokens{} + }, +} + +// StatelessDeflate allows compressing directly to a Writer without retaining state. +// When returning everything will be flushed. +// Up to 8KB of an optional dictionary can be given which is presumed to precede the block. +// Longer dictionaries will be truncated and will still produce valid output. +// Sending nil dictionary is perfectly fine. +func StatelessDeflate(out io.Writer, in []byte, eof bool, dict []byte) error { + bw := bitWriterPool.Get().(*huffmanBitWriter) + bw.reset(out) + defer func() { + // don't keep a reference to our output + bw.reset(nil) + bitWriterPool.Put(bw) + }() + if eof && len(in) == 0 { + // Just write an EOF block. + // Could be faster... + bw.writeStoredHeader(0, true) + bw.flush() + return bw.err + } + + // Truncate dict + if len(dict) > maxStatelessDict { + dict = dict[len(dict)-maxStatelessDict:] + } + + // For subsequent loops, keep shallow dict reference to avoid alloc+copy. + var inDict []byte + + dst := tokensPool.Get().(*tokens) + dst.Reset() + defer func() { + tokensPool.Put(dst) + }() + + for len(in) > 0 { + todo := in + if len(inDict) > 0 { + if len(todo) > maxStatelessBlock-maxStatelessDict { + todo = todo[:maxStatelessBlock-maxStatelessDict] + } + } else if len(todo) > maxStatelessBlock-len(dict) { + todo = todo[:maxStatelessBlock-len(dict)] + } + inOrg := in + in = in[len(todo):] + uncompressed := todo + if len(dict) > 0 { + // combine dict and source + bufLen := len(todo) + len(dict) + combined := make([]byte, bufLen) + copy(combined, dict) + copy(combined[len(dict):], todo) + todo = combined + } + // Compress + if len(inDict) == 0 { + statelessEnc(dst, todo, int16(len(dict))) + } else { + statelessEnc(dst, inDict[:maxStatelessDict+len(todo)], maxStatelessDict) + } + isEof := eof && len(in) == 0 + + if dst.n == 0 { + bw.writeStoredHeader(len(uncompressed), isEof) + if bw.err != nil { + return bw.err + } + bw.writeBytes(uncompressed) + } else if int(dst.n) > len(uncompressed)-len(uncompressed)>>4 { + // If we removed less than 1/16th, huffman compress the block. + bw.writeBlockHuff(isEof, uncompressed, len(in) == 0) + } else { + bw.writeBlockDynamic(dst, isEof, uncompressed, len(in) == 0) + } + if len(in) > 0 { + // Retain a dict if we have more + inDict = inOrg[len(uncompressed)-maxStatelessDict:] + dict = nil + dst.Reset() + } + if bw.err != nil { + return bw.err + } + } + if !eof { + // Align, only a stored block can do that. + bw.writeStoredHeader(0, false) + } + bw.flush() + return bw.err +} + +func hashSL(u uint32) uint32 { + return (u * 0x1e35a7bd) >> slTableShift +} + +func load3216(b []byte, i int16) uint32 { + return le.Load32(b, i) +} + +func load6416(b []byte, i int16) uint64 { + return le.Load64(b, i) +} + +func statelessEnc(dst *tokens, src []byte, startAt int16) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + + type tableEntry struct { + offset int16 + } + + var table [slTableSize]tableEntry + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src)-int(startAt) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = 0 + return + } + // Index until startAt + if startAt > 0 { + cv := load3232(src, 0) + for i := range startAt { + table[hashSL(cv)] = tableEntry{offset: i} + cv = (cv >> 8) | (uint32(src[i+4]) << 24) + } + } + + s := startAt + 1 + nextEmit := startAt + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int16(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load3216(src, s) + + for { + const skipLog = 5 + const doEvery = 2 + + nextS := s + var candidate tableEntry + for { + nextHash := hashSL(cv) + candidate = table[nextHash] + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit || nextS <= 0 { + goto emitRemainder + } + + now := load6416(src, nextS) + table[nextHash] = tableEntry{offset: s} + nextHash = hashSL(uint32(now)) + + if cv == load3216(src, candidate.offset) { + table[nextHash] = tableEntry{offset: nextS} + break + } + + // Do one right away... + cv = uint32(now) + s = nextS + nextS++ + candidate = table[nextHash] + now >>= 8 + table[nextHash] = tableEntry{offset: s} + + if cv == load3216(src, candidate.offset) { + table[nextHash] = tableEntry{offset: nextS} + break + } + cv = uint32(now) + s = nextS + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + t := candidate.offset + l := int16(matchLen(src[s+4:], src[t+4:]) + 4) + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + if false { + emitLiteral(dst, src[nextEmit:s]) + } else { + for _, v := range src[nextEmit:s] { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } + } + } + + // Save the match found + dst.AddMatchLong(int32(l), uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + if s >= sLimit { + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load6416(src, s-2) + o := s - 2 + prevHash := hashSL(uint32(x)) + table[prevHash] = tableEntry{offset: o} + x >>= 16 + currHash := hashSL(uint32(x)) + candidate = table[currHash] + table[currHash] = tableEntry{offset: o + 2} + + if uint32(x) != load3216(src, candidate.offset) { + cv = uint32(x >> 8) + s++ + break + } + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/token.go b/vendor/github.com/klauspost/compress/flate/token.go new file mode 100644 index 0000000..d818790 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/token.go @@ -0,0 +1,379 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "math" +) + +const ( + // bits 0-16 xoffset = offset - MIN_OFFSET_SIZE, or literal - 16 bits + // bits 16-22 offsetcode - 5 bits + // bits 22-30 xlength = length - MIN_MATCH_LENGTH - 8 bits + // bits 30-32 type 0 = literal 1=EOF 2=Match 3=Unused - 2 bits + lengthShift = 22 + offsetMask = 1<maxnumlit + offHist [32]uint16 // offset codes + litHist [256]uint16 // codes 0->255 + nFilled int + n uint16 // Must be able to contain maxStoreBlockSize + tokens [maxStoreBlockSize + 1]token +} + +func (t *tokens) Reset() { + if t.n == 0 { + return + } + t.n = 0 + t.nFilled = 0 + for i := range t.litHist[:] { + t.litHist[i] = 0 + } + for i := range t.extraHist[:] { + t.extraHist[i] = 0 + } + for i := range t.offHist[:] { + t.offHist[i] = 0 + } +} + +func (t *tokens) Fill() { + if t.n == 0 { + return + } + for i, v := range t.litHist[:] { + if v == 0 { + t.litHist[i] = 1 + t.nFilled++ + } + } + for i, v := range t.extraHist[:literalCount-256] { + if v == 0 { + t.nFilled++ + t.extraHist[i] = 1 + } + } + for i, v := range t.offHist[:offsetCodeCount] { + if v == 0 { + t.offHist[i] = 1 + } + } +} + +func indexTokens(in []token) tokens { + var t tokens + t.indexTokens(in) + return t +} + +func (t *tokens) indexTokens(in []token) { + t.Reset() + for _, tok := range in { + if tok < matchType { + t.AddLiteral(tok.literal()) + continue + } + t.AddMatch(uint32(tok.length()), tok.offset()&matchOffsetOnlyMask) + } +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +func emitLiteral(dst *tokens, lit []byte) { + for _, v := range lit { + dst.tokens[dst.n] = token(v) + dst.litHist[v]++ + dst.n++ + } +} + +func (t *tokens) AddLiteral(lit byte) { + t.tokens[t.n] = token(lit) + t.litHist[lit]++ + t.n++ +} + +// from https://stackoverflow.com/a/28730362 +func mFastLog2(val float32) float32 { + ux := int32(math.Float32bits(val)) + log2 := (float32)(((ux >> 23) & 255) - 128) + ux &= -0x7f800001 + ux += 127 << 23 + uval := math.Float32frombits(uint32(ux)) + log2 += ((-0.34484843)*uval+2.02466578)*uval - 0.67487759 + return log2 +} + +// EstimatedBits will return an minimum size estimated by an *optimal* +// compression of the block. +// The size of the block +func (t *tokens) EstimatedBits() int { + shannon := float32(0) + bits := int(0) + nMatches := 0 + total := int(t.n) + t.nFilled + if total > 0 { + invTotal := 1.0 / float32(total) + for _, v := range t.litHist[:] { + if v > 0 { + n := float32(v) + shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + } + } + // Just add 15 for EOB + shannon += 15 + for i, v := range t.extraHist[1 : literalCount-256] { + if v > 0 { + n := float32(v) + shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + bits += int(lengthExtraBits[i&31]) * int(v) + nMatches += int(v) + } + } + } + if nMatches > 0 { + invTotal := 1.0 / float32(nMatches) + for i, v := range t.offHist[:offsetCodeCount] { + if v > 0 { + n := float32(v) + shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + bits += int(offsetExtraBits[i&31]) * int(v) + } + } + } + return int(shannon) + bits +} + +// AddMatch adds a match to the tokens. +// This function is very sensitive to inlining and right on the border. +func (t *tokens) AddMatch(xlength uint32, xoffset uint32) { + if debugDeflate { + if xlength >= maxMatchLength+baseMatchLength { + panic(fmt.Errorf("invalid length: %v", xlength)) + } + if xoffset >= maxMatchOffset+baseMatchOffset { + panic(fmt.Errorf("invalid offset: %v", xoffset)) + } + } + oCode := offsetCode(xoffset) + xoffset |= oCode << 16 + + t.extraHist[lengthCodes1[uint8(xlength)]]++ + t.offHist[oCode&31]++ + t.tokens[t.n] = token(matchType | xlength<= maxMatchOffset+baseMatchOffset { + panic(fmt.Errorf("invalid offset: %v", xoffset)) + } + } + oc := offsetCode(xoffset) + xoffset |= oc << 16 + for xlength > 0 { + xl := xlength + if xl > 258 { + // We need to have at least baseMatchLength left over for next loop. + if xl > 258+baseMatchLength { + xl = 258 + } else { + xl = 258 - baseMatchLength + } + } + xlength -= xl + xl -= baseMatchLength + t.extraHist[lengthCodes1[uint8(xl)]]++ + t.offHist[oc&31]++ + t.tokens[t.n] = token(matchType | uint32(xl)<> lengthShift) } + +// Convert length to code. +func lengthCode(len uint8) uint8 { return lengthCodes[len] } + +// Returns the offset code corresponding to a specific offset +func offsetCode(off uint32) uint32 { + if false { + if off < uint32(len(offsetCodes)) { + return offsetCodes[off&255] + } else if off>>7 < uint32(len(offsetCodes)) { + return offsetCodes[(off>>7)&255] + 14 + } else { + return offsetCodes[(off>>14)&255] + 28 + } + } + if off < uint32(len(offsetCodes)) { + return offsetCodes[uint8(off)] + } + return offsetCodes14[uint8(off>>7)] +} diff --git a/vendor/github.com/klauspost/compress/internal/le/le.go b/vendor/github.com/klauspost/compress/internal/le/le.go new file mode 100644 index 0000000..e54909e --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/le/le.go @@ -0,0 +1,5 @@ +package le + +type Indexer interface { + int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 +} diff --git a/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go b/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go new file mode 100644 index 0000000..4f2a0d8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go @@ -0,0 +1,42 @@ +//go:build !(amd64 || arm64 || ppc64le || riscv64) || nounsafe || purego || appengine + +package le + +import ( + "encoding/binary" +) + +// Load8 will load from b at index i. +func Load8[I Indexer](b []byte, i I) byte { + return b[i] +} + +// Load16 will load from b at index i. +func Load16[I Indexer](b []byte, i I) uint16 { + return binary.LittleEndian.Uint16(b[i:]) +} + +// Load32 will load from b at index i. +func Load32[I Indexer](b []byte, i I) uint32 { + return binary.LittleEndian.Uint32(b[i:]) +} + +// Load64 will load from b at index i. +func Load64[I Indexer](b []byte, i I) uint64 { + return binary.LittleEndian.Uint64(b[i:]) +} + +// Store16 will store v at b. +func Store16(b []byte, v uint16) { + binary.LittleEndian.PutUint16(b, v) +} + +// Store32 will store v at b. +func Store32(b []byte, v uint32) { + binary.LittleEndian.PutUint32(b, v) +} + +// Store64 will store v at b. +func Store64[I Indexer](b []byte, i I, v uint64) { + binary.LittleEndian.PutUint64(b[i:], v) +} diff --git a/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go b/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go new file mode 100644 index 0000000..218a38b --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go @@ -0,0 +1,52 @@ +// We enable 64 bit LE platforms: + +//go:build (amd64 || arm64 || ppc64le || riscv64) && !nounsafe && !purego && !appengine + +package le + +import ( + "unsafe" +) + +// Load8 will load from b at index i. +func Load8[I Indexer](b []byte, i I) byte { + //return binary.LittleEndian.Uint16(b[i:]) + //return *(*uint16)(unsafe.Pointer(&b[i])) + return *(*byte)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i)) +} + +// Load16 will load from b at index i. +func Load16[I Indexer](b []byte, i I) uint16 { + //return binary.LittleEndian.Uint16(b[i:]) + //return *(*uint16)(unsafe.Pointer(&b[i])) + return *(*uint16)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i)) +} + +// Load32 will load from b at index i. +func Load32[I Indexer](b []byte, i I) uint32 { + //return binary.LittleEndian.Uint32(b[i:]) + //return *(*uint32)(unsafe.Pointer(&b[i])) + return *(*uint32)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i)) +} + +// Load64 will load from b at index i. +func Load64[I Indexer](b []byte, i I) uint64 { + //return binary.LittleEndian.Uint64(b[i:]) + //return *(*uint64)(unsafe.Pointer(&b[i])) + return *(*uint64)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i)) +} + +// Store16 will store v at b. +func Store16(b []byte, v uint16) { + *(*uint16)(unsafe.Pointer(unsafe.SliceData(b))) = v +} + +// Store32 will store v at b. +func Store32(b []byte, v uint32) { + *(*uint32)(unsafe.Pointer(unsafe.SliceData(b))) = v +} + +// Store64 will store v at b[i:]. +func Store64[I Indexer](b []byte, i I, v uint64) { + *(*uint64)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i)) = v +} diff --git a/vendor/github.com/klauspost/compress/internal/race/norace.go b/vendor/github.com/klauspost/compress/internal/race/norace.go new file mode 100644 index 0000000..affbbbb --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/race/norace.go @@ -0,0 +1,13 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !race + +package race + +func ReadSlice[T any](s []T) { +} + +func WriteSlice[T any](s []T) { +} diff --git a/vendor/github.com/klauspost/compress/internal/race/race.go b/vendor/github.com/klauspost/compress/internal/race/race.go new file mode 100644 index 0000000..f5e240d --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/race/race.go @@ -0,0 +1,26 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build race + +package race + +import ( + "runtime" + "unsafe" +) + +func ReadSlice[T any](s []T) { + if len(s) == 0 { + return + } + runtime.RaceReadRange(unsafe.Pointer(&s[0]), len(s)*int(unsafe.Sizeof(s[0]))) +} + +func WriteSlice[T any](s []T) { + if len(s) == 0 { + return + } + runtime.RaceWriteRange(unsafe.Pointer(&s[0]), len(s)*int(unsafe.Sizeof(s[0]))) +} diff --git a/vendor/github.com/klauspost/compress/s2/.gitignore b/vendor/github.com/klauspost/compress/s2/.gitignore new file mode 100644 index 0000000..3a89c6e --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/.gitignore @@ -0,0 +1,15 @@ +testdata/bench + +# These explicitly listed benchmark data files are for an obsolete version of +# snappy_test.go. +testdata/alice29.txt +testdata/asyoulik.txt +testdata/fireworks.jpeg +testdata/geo.protodata +testdata/html +testdata/html_x_4 +testdata/kppkn.gtb +testdata/lcet10.txt +testdata/paper-100k.pdf +testdata/plrabn12.txt +testdata/urls.10K diff --git a/vendor/github.com/klauspost/compress/s2/LICENSE b/vendor/github.com/klauspost/compress/s2/LICENSE new file mode 100644 index 0000000..1d2d645 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. +Copyright (c) 2019 Klaus Post. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/klauspost/compress/s2/README.md b/vendor/github.com/klauspost/compress/s2/README.md new file mode 100644 index 0000000..b0bf59f --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/README.md @@ -0,0 +1,1134 @@ +# MinLZ + +I have taken the experiences from this library and created a backwards compatible compression package called MinLZ. + +That package will seamlessly decode S2 content, making the transition from this package fairly trivial. + +There are many improvements to pretty much all aspects of S2 since we have "broken free" of the Snappy format specification. +You can read a writeup on [Design and Improvements over S2](https://gist.github.com/klauspost/a25b66198cdbdf7b5b224f670c894ed5). + +The only aspect not covered is custom dictionary encoding. While I do intend to fix errors in this package, +I do not expect to make significant improvements, since I consider MinLZ a better basis for going forward. + +See https://github.com/minio/minlz for all details. + +# S2 Compression + +S2 is an extension of [Snappy](https://github.com/google/snappy). + +S2 is aimed for high throughput, which is why it features concurrent compression for bigger payloads. + +Decoding is compatible with Snappy compressed content, but content compressed with S2 cannot be decompressed by Snappy. +This means that S2 can seamlessly replace Snappy without converting compressed content. + +S2 can produce Snappy compatible output, faster and better than Snappy. +If you want full benefit of the changes you should use s2 without Snappy compatibility. + +S2 is designed to have high throughput on content that cannot be compressed. +This is important, so you don't have to worry about spending CPU cycles on already compressed data. + +## Benefits over Snappy + +* Better compression +* Adjustable compression (3 levels) +* Concurrent stream compression +* Faster decompression, even for Snappy compatible content +* Concurrent Snappy/S2 stream decompression +* Skip forward in compressed stream +* Random seeking with indexes +* Compatible with reading Snappy compressed content +* Smaller block size overhead on incompressible blocks +* Block concatenation +* Block Dictionary support +* Uncompressed stream mode +* Automatic stream size padding +* Snappy compatible block compression + +## Drawbacks over Snappy + +* Not optimized for 32 bit systems +* Streams use slightly more memory due to larger blocks and concurrency (configurable) + +# Usage + +Installation: `go get -u github.com/klauspost/compress/s2` + +Full package documentation: + +[![godoc][1]][2] + +[1]: https://godoc.org/github.com/klauspost/compress?status.svg +[2]: https://godoc.org/github.com/klauspost/compress/s2 + +## Compression + +```Go +func EncodeStream(src io.Reader, dst io.Writer) error { + enc := s2.NewWriter(dst) + _, err := io.Copy(enc, src) + if err != nil { + enc.Close() + return err + } + // Blocks until compression is done. + return enc.Close() +} +``` + +You should always call `enc.Close()`, otherwise you will leak resources and your encode will be incomplete. + +For the best throughput, you should attempt to reuse the `Writer` using the `Reset()` method. + +The Writer in S2 is always buffered, therefore `NewBufferedWriter` in Snappy can be replaced with `NewWriter` in S2. +It is possible to flush any buffered data using the `Flush()` method. +This will block until all data sent to the encoder has been written to the output. + +S2 also supports the `io.ReaderFrom` interface, which will consume all input from a reader. + +As a final method to compress data, if you have a single block of data you would like to have encoded as a stream, +a slightly more efficient method is to use the `EncodeBuffer` method. +This will take ownership of the buffer until the stream is closed. + +```Go +func EncodeStream(src []byte, dst io.Writer) error { + enc := s2.NewWriter(dst) + // The encoder owns the buffer until Flush or Close is called. + err := enc.EncodeBuffer(src) + if err != nil { + enc.Close() + return err + } + // Blocks until compression is done. + return enc.Close() +} +``` + +Each call to `EncodeBuffer` will result in discrete blocks being created without buffering, +so it should only be used a single time per stream. +If you need to write several blocks, you should use the regular io.Writer interface. + + +## Decompression + +```Go +func DecodeStream(src io.Reader, dst io.Writer) error { + dec := s2.NewReader(src) + _, err := io.Copy(dst, dec) + return err +} +``` + +Similar to the Writer, a Reader can be reused using the `Reset` method. + +For the best possible throughput, there is a `EncodeBuffer(buf []byte)` function available. +However, it requires that the provided buffer isn't used after it is handed over to S2 and until the stream is flushed or closed. + +For smaller data blocks, there is also a non-streaming interface: `Encode()`, `EncodeBetter()` and `Decode()`. +Do however note that these functions (similar to Snappy) does not provide validation of data, +so data corruption may be undetected. Stream encoding provides CRC checks of data. + +It is possible to efficiently skip forward in a compressed stream using the `Skip()` method. +For big skips the decompressor is able to skip blocks without decompressing them. + +## Single Blocks + +Similar to Snappy S2 offers single block compression. +Blocks do not offer the same flexibility and safety as streams, +but may be preferable for very small payloads, less than 100K. + +Using a simple `dst := s2.Encode(nil, src)` will compress `src` and return the compressed result. +It is possible to provide a destination buffer. +If the buffer has a capacity of `s2.MaxEncodedLen(len(src))` it will be used. +If not a new will be allocated. + +Alternatively `EncodeBetter`/`EncodeBest` can also be used for better, but slightly slower compression. + +Similarly to decompress a block you can use `dst, err := s2.Decode(nil, src)`. +Again an optional destination buffer can be supplied. +The `s2.DecodedLen(src)` can be used to get the minimum capacity needed. +If that is not satisfied a new buffer will be allocated. + +Block function always operate on a single goroutine since it should only be used for small payloads. + +# Commandline tools + +Some very simply commandline tools are provided; `s2c` for compression and `s2d` for decompression. + +Binaries can be downloaded on the [Releases Page](https://github.com/klauspost/compress/releases). + +Installing then requires Go to be installed. To install them, use: + +`go install github.com/klauspost/compress/s2/cmd/s2c@latest && go install github.com/klauspost/compress/s2/cmd/s2d@latest` + +To build binaries to the current folder use: + +`go build github.com/klauspost/compress/s2/cmd/s2c && go build github.com/klauspost/compress/s2/cmd/s2d` + + +## s2c + +``` +Usage: s2c [options] file1 file2 + +Compresses all files supplied as input separately. +Output files are written as 'filename.ext.s2' or 'filename.ext.snappy'. +By default output files will be overwritten. +Use - as the only file name to read from stdin and write to stdout. + +Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt +Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt + +File names beginning with 'http://' and 'https://' will be downloaded and compressed. +Only http response code 200 is accepted. + +Options: + -bench int + Run benchmark n times. No output will be written + -blocksize string + Max block size. Examples: 64K, 256K, 1M, 4M. Must be power of two and <= 4MB (default "4M") + -c Write all output to stdout. Multiple input files will be concatenated + -cpu int + Compress using this amount of threads (default 32) + -faster + Compress faster, but with a minor compression loss + -help + Display help + -index + Add seek index (default true) + -o string + Write output to another file. Single input file only + -pad string + Pad size to a multiple of this value, Examples: 500, 64K, 256K, 1M, 4M, etc (default "1") + -q Don't write any output to terminal, except errors + -rm + Delete source file(s) after successful compression + -safe + Do not overwrite output files + -slower + Compress more, but a lot slower + -snappy + Generate Snappy compatible output stream + -verify + Verify written files + +``` + +## s2d + +``` +Usage: s2d [options] file1 file2 + +Decompresses all files supplied as input. Input files must end with '.s2' or '.snappy'. +Output file names have the extension removed. By default output files will be overwritten. +Use - as the only file name to read from stdin and write to stdout. + +Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt +Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt + +File names beginning with 'http://' and 'https://' will be downloaded and decompressed. +Extensions on downloaded files are ignored. Only http response code 200 is accepted. + +Options: + -bench int + Run benchmark n times. No output will be written + -c Write all output to stdout. Multiple input files will be concatenated + -help + Display help + -o string + Write output to another file. Single input file only + -offset string + Start at offset. Examples: 92, 64K, 256K, 1M, 4M. Requires Index + -q Don't write any output to terminal, except errors + -rm + Delete source file(s) after successful decompression + -safe + Do not overwrite output files + -tail string + Return last of compressed file. Examples: 92, 64K, 256K, 1M, 4M. Requires Index + -verify + Verify files, but do not write output +``` + +## s2sx: self-extracting archives + +s2sx allows creating self-extracting archives with no dependencies. + +By default, executables are created for the same platforms as the host os, +but this can be overridden with `-os` and `-arch` parameters. + +Extracted files have 0666 permissions, except when untar option used. + +``` +Usage: s2sx [options] file1 file2 + +Compresses all files supplied as input separately. +If files have '.s2' extension they are assumed to be compressed already. +Output files are written as 'filename.s2sx' and with '.exe' for windows targets. +If output is big, an additional file with ".more" is written. This must be included as well. +By default output files will be overwritten. + +Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt +Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt + +Options: + -arch string + Destination architecture (default "amd64") + -c Write all output to stdout. Multiple input files will be concatenated + -cpu int + Compress using this amount of threads (default 32) + -help + Display help + -max string + Maximum executable size. Rest will be written to another file. (default "1G") + -os string + Destination operating system (default "windows") + -q Don't write any output to terminal, except errors + -rm + Delete source file(s) after successful compression + -safe + Do not overwrite output files + -untar + Untar on destination +``` + +Available platforms are: + + * darwin-amd64 + * darwin-arm64 + * linux-amd64 + * linux-arm + * linux-arm64 + * linux-mips64 + * linux-ppc64le + * windows-386 + * windows-amd64 + +By default, there is a size limit of 1GB for the output executable. + +When this is exceeded the remaining file content is written to a file called +output+`.more`. This file must be included for a successful extraction and +placed alongside the executable for a successful extraction. + +This file *must* have the same name as the executable, so if the executable is renamed, +so must the `.more` file. + +This functionality is disabled with stdin/stdout. + +### Self-extracting TAR files + +If you wrap a TAR file you can specify `-untar` to make it untar on the destination host. + +Files are extracted to the current folder with the path specified in the tar file. + +Note that tar files are not validated before they are wrapped. + +For security reasons files that move below the root folder are not allowed. + +# Performance + +This section will focus on comparisons to Snappy. +This package is solely aimed at replacing Snappy as a high speed compression package. +If you are mainly looking for better compression [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd) +gives better compression, but typically at speeds slightly below "better" mode in this package. + +Compression is increased compared to Snappy, mostly around 5-20% and the throughput is typically 25-40% increased (single threaded) compared to the Snappy Go implementation. + +Streams are concurrently compressed. The stream will be distributed among all available CPU cores for the best possible throughput. + +A "better" compression mode is also available. This allows to trade a bit of speed for a minor compression gain. +The content compressed in this mode is fully compatible with the standard decoder. + +Snappy vs S2 **compression** speed on 16 core (32 thread) computer, using all threads and a single thread (1 CPU): + +| File | S2 Speed | S2 Throughput | S2 % smaller | S2 "better" | "better" throughput | "better" % smaller | +|---------------------------------------------------------------------------------------------------------|----------|---------------|--------------|-------------|---------------------|--------------------| +| [rawstudio-mint14.tar](https://files.klauspost.com/compress/rawstudio-mint14.7z) | 16.33x | 10556 MB/s | 8.0% | 6.04x | 5252 MB/s | 14.7% | +| (1 CPU) | 1.08x | 940 MB/s | - | 0.46x | 400 MB/s | - | +| [github-june-2days-2019.json](https://files.klauspost.com/compress/github-june-2days-2019.json.zst) | 16.51x | 15224 MB/s | 31.70% | 9.47x | 8734 MB/s | 37.71% | +| (1 CPU) | 1.26x | 1157 MB/s | - | 0.60x | 556 MB/s | - | +| [github-ranks-backup.bin](https://files.klauspost.com/compress/github-ranks-backup.bin.zst) | 15.14x | 12598 MB/s | -5.76% | 6.23x | 5675 MB/s | 3.62% | +| (1 CPU) | 1.02x | 932 MB/s | - | 0.47x | 432 MB/s | - | +| [consensus.db.10gb](https://files.klauspost.com/compress/consensus.db.10gb.zst) | 11.21x | 12116 MB/s | 15.95% | 3.24x | 3500 MB/s | 18.00% | +| (1 CPU) | 1.05x | 1135 MB/s | - | 0.27x | 292 MB/s | - | +| [apache.log](https://files.klauspost.com/compress/apache.log.zst) | 8.55x | 16673 MB/s | 20.54% | 5.85x | 11420 MB/s | 24.97% | +| (1 CPU) | 1.91x | 1771 MB/s | - | 0.53x | 1041 MB/s | - | +| [gob-stream](https://files.klauspost.com/compress/gob-stream.7z) | 15.76x | 14357 MB/s | 24.01% | 8.67x | 7891 MB/s | 33.68% | +| (1 CPU) | 1.17x | 1064 MB/s | - | 0.65x | 595 MB/s | - | +| [10gb.tar](http://mattmahoney.net/dc/10gb.html) | 13.33x | 9835 MB/s | 2.34% | 6.85x | 4863 MB/s | 9.96% | +| (1 CPU) | 0.97x | 689 MB/s | - | 0.55x | 387 MB/s | - | +| sharnd.out.2gb | 9.11x | 13213 MB/s | 0.01% | 1.49x | 9184 MB/s | 0.01% | +| (1 CPU) | 0.88x | 5418 MB/s | - | 0.77x | 5417 MB/s | - | +| [sofia-air-quality-dataset csv](https://files.klauspost.com/compress/sofia-air-quality-dataset.tar.zst) | 22.00x | 11477 MB/s | 18.73% | 11.15x | 5817 MB/s | 27.88% | +| (1 CPU) | 1.23x | 642 MB/s | - | 0.71x | 642 MB/s | - | +| [silesia.tar](http://sun.aei.polsl.pl/~sdeor/corpus/silesia.zip) | 11.23x | 6520 MB/s | 5.9% | 5.35x | 3109 MB/s | 15.88% | +| (1 CPU) | 1.05x | 607 MB/s | - | 0.52x | 304 MB/s | - | +| [enwik9](https://files.klauspost.com/compress/enwik9.zst) | 19.28x | 8440 MB/s | 4.04% | 9.31x | 4076 MB/s | 18.04% | +| (1 CPU) | 1.12x | 488 MB/s | - | 0.57x | 250 MB/s | - | + +### Legend + +* `S2 Speed`: Speed of S2 compared to Snappy, using 16 cores and 1 core. +* `S2 Throughput`: Throughput of S2 in MB/s. +* `S2 % smaller`: How many percent of the Snappy output size is S2 better. +* `S2 "better"`: Speed when enabling "better" compression mode in S2 compared to Snappy. +* `"better" throughput`: Speed when enabling "better" compression mode in S2 compared to Snappy. +* `"better" % smaller`: How many percent of the Snappy output size is S2 better when using "better" compression. + +There is a good speedup across the board when using a single thread and a significant speedup when using multiple threads. + +Machine generated data gets by far the biggest compression boost, with size being reduced by up to 35% of Snappy size. + +The "better" compression mode sees a good improvement in all cases, but usually at a performance cost. + +Incompressible content (`sharnd.out.2gb`, 2GB random data) sees the smallest speedup. +This is likely dominated by synchronization overhead, which is confirmed by the fact that single threaded performance is higher (see above). + +## Decompression + +S2 attempts to create content that is also fast to decompress, except in "better" mode where the smallest representation is used. + +S2 vs Snappy **decompression** speed. Both operating on single core: + +| File | S2 Throughput | vs. Snappy | Better Throughput | vs. Snappy | +|-----------------------------------------------------------------------------------------------------|---------------|------------|-------------------|------------| +| [rawstudio-mint14.tar](https://files.klauspost.com/compress/rawstudio-mint14.7z) | 2117 MB/s | 1.14x | 1738 MB/s | 0.94x | +| [github-june-2days-2019.json](https://files.klauspost.com/compress/github-june-2days-2019.json.zst) | 2401 MB/s | 1.25x | 2307 MB/s | 1.20x | +| [github-ranks-backup.bin](https://files.klauspost.com/compress/github-ranks-backup.bin.zst) | 2075 MB/s | 0.98x | 1764 MB/s | 0.83x | +| [consensus.db.10gb](https://files.klauspost.com/compress/consensus.db.10gb.zst) | 2967 MB/s | 1.05x | 2885 MB/s | 1.02x | +| [adresser.json](https://files.klauspost.com/compress/adresser.json.zst) | 4141 MB/s | 1.07x | 4184 MB/s | 1.08x | +| [gob-stream](https://files.klauspost.com/compress/gob-stream.7z) | 2264 MB/s | 1.12x | 2185 MB/s | 1.08x | +| [10gb.tar](http://mattmahoney.net/dc/10gb.html) | 1525 MB/s | 1.03x | 1347 MB/s | 0.91x | +| sharnd.out.2gb | 3813 MB/s | 0.79x | 3900 MB/s | 0.81x | +| [enwik9](http://mattmahoney.net/dc/textdata.html) | 1246 MB/s | 1.29x | 967 MB/s | 1.00x | +| [silesia.tar](http://sun.aei.polsl.pl/~sdeor/corpus/silesia.zip) | 1433 MB/s | 1.12x | 1203 MB/s | 0.94x | +| [enwik10](https://encode.su/threads/3315-enwik10-benchmark-results) | 1284 MB/s | 1.32x | 1010 MB/s | 1.04x | + +### Legend + +* `S2 Throughput`: Decompression speed of S2 encoded content. +* `Better Throughput`: Decompression speed of S2 "better" encoded content. +* `vs Snappy`: Decompression speed of S2 "better" mode compared to Snappy and absolute speed. + + +While the decompression code hasn't changed, there is a significant speedup in decompression speed. +S2 prefers longer matches and will typically only find matches that are 6 bytes or longer. +While this reduces compression a bit, it improves decompression speed. + +The "better" compression mode will actively look for shorter matches, which is why it has a decompression speed quite similar to Snappy. + +Without assembly decompression is also very fast; single goroutine decompression speed. No assembly: + +| File | S2 Throughput | S2 throughput | +|--------------------------------|---------------|---------------| +| consensus.db.10gb.s2 | 1.84x | 2289.8 MB/s | +| 10gb.tar.s2 | 1.30x | 867.07 MB/s | +| rawstudio-mint14.tar.s2 | 1.66x | 1329.65 MB/s | +| github-june-2days-2019.json.s2 | 2.36x | 1831.59 MB/s | +| github-ranks-backup.bin.s2 | 1.73x | 1390.7 MB/s | +| enwik9.s2 | 1.67x | 681.53 MB/s | +| adresser.json.s2 | 3.41x | 4230.53 MB/s | +| silesia.tar.s2 | 1.52x | 811.58 | + +Even though S2 typically compresses better than Snappy, decompression speed is always better. + +### Concurrent Stream Decompression + +For full stream decompression S2 offers a [DecodeConcurrent](https://pkg.go.dev/github.com/klauspost/compress/s2#Reader.DecodeConcurrent) +that will decode a full stream using multiple goroutines. + +Example scaling, AMD Ryzen 3950X, 16 cores, decompression using `s2d -bench=3 `, best of 3: + +| Input | `-cpu=1` | `-cpu=2` | `-cpu=4` | `-cpu=8` | `-cpu=16` | +|-------------------------------------------|------------|------------|------------|------------|-------------| +| enwik10.snappy | 1098.6MB/s | 1819.8MB/s | 3625.6MB/s | 6910.6MB/s | 10818.2MB/s | +| enwik10.s2 | 1303.5MB/s | 2606.1MB/s | 4847.9MB/s | 8878.4MB/s | 9592.1MB/s | +| sofia-air-quality-dataset.tar.snappy | 1302.0MB/s | 2165.0MB/s | 4244.5MB/s | 8241.0MB/s | 12920.5MB/s | +| sofia-air-quality-dataset.tar.s2 | 1399.2MB/s | 2463.2MB/s | 5196.5MB/s | 9639.8MB/s | 11439.5MB/s | +| sofia-air-quality-dataset.tar.s2 (no asm) | 837.5MB/s | 1652.6MB/s | 3183.6MB/s | 5945.0MB/s | 9620.7MB/s | + +Scaling can be expected to be pretty linear until memory bandwidth is saturated. + +For now the DecodeConcurrent can only be used for full streams without seeking or combining with regular reads. + +## Block compression + + +When compressing blocks no concurrent compression is performed just as Snappy. +This is because blocks are for smaller payloads and generally will not benefit from concurrent compression. + +An important change is that incompressible blocks will not be more than at most 10 bytes bigger than the input. +In rare, worst case scenario Snappy blocks could be significantly bigger than the input. + +### Mixed content blocks + +The most reliable is a wide dataset. +For this we use [`webdevdata.org-2015-01-07-subset`](https://files.klauspost.com/compress/webdevdata.org-2015-01-07-4GB-subset.7z), +53927 files, total input size: 4,014,735,833 bytes. Single goroutine used. + +| * | Input | Output | Reduction | MB/s | +|-------------------|------------|------------|------------|------------| +| S2 | 4014735833 | 1059723369 | 73.60% | **936.73** | +| S2 Better | 4014735833 | 961580539 | 76.05% | 451.10 | +| S2 Best | 4014735833 | 899182886 | **77.60%** | 46.84 | +| Snappy | 4014735833 | 1128706759 | 71.89% | 790.15 | +| S2, Snappy Output | 4014735833 | 1093823291 | 72.75% | 936.60 | +| LZ4 | 4014735833 | 1063768713 | 73.50% | 452.02 | + +S2 delivers both the best single threaded throughput with regular mode and the best compression rate with "best". +"Better" mode provides the same compression speed as LZ4 with better compression ratio. + +When outputting Snappy compatible output it still delivers better throughput (150MB/s more) and better compression. + +As can be seen from the other benchmarks decompression should also be easier on the S2 generated output. + +Though they cannot be compared due to different decompression speeds here are the speed/size comparisons for +other Go compressors: + +| * | Input | Output | Reduction | MB/s | +|-------------------|------------|------------|-----------|--------| +| Zstd Fastest (Go) | 4014735833 | 794608518 | 80.21% | 236.04 | +| Zstd Best (Go) | 4014735833 | 704603356 | 82.45% | 35.63 | +| Deflate (Go) l1 | 4014735833 | 871294239 | 78.30% | 214.04 | +| Deflate (Go) l9 | 4014735833 | 730389060 | 81.81% | 41.17 | + +### Standard block compression + +Benchmarking single block performance is subject to a lot more variation since it only tests a limited number of file patterns. +So individual benchmarks should only be seen as a guideline and the overall picture is more important. + +These micro-benchmarks are with data in cache and trained branch predictors. For a more realistic benchmark see the mixed content above. + +Block compression. Parallel benchmark running on 16 cores, 16 goroutines. + +AMD64 assembly is use for both S2 and Snappy. + +| Absolute Perf | Snappy size | S2 Size | Snappy Speed | S2 Speed | Snappy dec | S2 dec | +|-----------------------|-------------|---------|--------------|-------------|-------------|-------------| +| html | 22843 | 20868 | 16246 MB/s | 18617 MB/s | 40972 MB/s | 49263 MB/s | +| urls.10K | 335492 | 286541 | 7943 MB/s | 10201 MB/s | 22523 MB/s | 26484 MB/s | +| fireworks.jpeg | 123034 | 123100 | 349544 MB/s | 303228 MB/s | 718321 MB/s | 827552 MB/s | +| fireworks.jpeg (200B) | 146 | 155 | 8869 MB/s | 20180 MB/s | 33691 MB/s | 52421 MB/s | +| paper-100k.pdf | 85304 | 84202 | 167546 MB/s | 112988 MB/s | 326905 MB/s | 291944 MB/s | +| html_x_4 | 92234 | 20870 | 15194 MB/s | 54457 MB/s | 30843 MB/s | 32217 MB/s | +| alice29.txt | 88034 | 85934 | 5936 MB/s | 6540 MB/s | 12882 MB/s | 20044 MB/s | +| asyoulik.txt | 77503 | 79575 | 5517 MB/s | 6657 MB/s | 12735 MB/s | 22806 MB/s | +| lcet10.txt | 234661 | 220383 | 6235 MB/s | 6303 MB/s | 14519 MB/s | 18697 MB/s | +| plrabn12.txt | 319267 | 318196 | 5159 MB/s | 6074 MB/s | 11923 MB/s | 19901 MB/s | +| geo.protodata | 23335 | 18606 | 21220 MB/s | 25432 MB/s | 56271 MB/s | 62540 MB/s | +| kppkn.gtb | 69526 | 65019 | 9732 MB/s | 8905 MB/s | 18491 MB/s | 18969 MB/s | +| alice29.txt (128B) | 80 | 82 | 6691 MB/s | 17179 MB/s | 31883 MB/s | 38874 MB/s | +| alice29.txt (1000B) | 774 | 774 | 12204 MB/s | 13273 MB/s | 48056 MB/s | 52341 MB/s | +| alice29.txt (10000B) | 6648 | 6933 | 10044 MB/s | 12824 MB/s | 32378 MB/s | 46322 MB/s | +| alice29.txt (20000B) | 12686 | 13516 | 7733 MB/s | 12160 MB/s | 30566 MB/s | 58969 MB/s | + + +Speed is generally at or above Snappy. Small blocks gets a significant speedup, although at the expense of size. + +Decompression speed is better than Snappy, except in one case. + +Since payloads are very small the variance in terms of size is rather big, so they should only be seen as a general guideline. + +Size is on average around Snappy, but varies on content type. +In cases where compression is worse, it usually is compensated by a speed boost. + + +### Better compression + +Benchmarking single block performance is subject to a lot more variation since it only tests a limited number of file patterns. +So individual benchmarks should only be seen as a guideline and the overall picture is more important. + +| Absolute Perf | Snappy size | Better Size | Snappy Speed | Better Speed | Snappy dec | Better dec | +|-----------------------|-------------|-------------|--------------|--------------|-------------|-------------| +| html | 22843 | 18972 | 16246 MB/s | 8621 MB/s | 40972 MB/s | 40292 MB/s | +| urls.10K | 335492 | 248079 | 7943 MB/s | 5104 MB/s | 22523 MB/s | 20981 MB/s | +| fireworks.jpeg | 123034 | 123100 | 349544 MB/s | 84429 MB/s | 718321 MB/s | 823698 MB/s | +| fireworks.jpeg (200B) | 146 | 149 | 8869 MB/s | 7125 MB/s | 33691 MB/s | 30101 MB/s | +| paper-100k.pdf | 85304 | 82887 | 167546 MB/s | 11087 MB/s | 326905 MB/s | 198869 MB/s | +| html_x_4 | 92234 | 18982 | 15194 MB/s | 29316 MB/s | 30843 MB/s | 30937 MB/s | +| alice29.txt | 88034 | 71611 | 5936 MB/s | 3709 MB/s | 12882 MB/s | 16611 MB/s | +| asyoulik.txt | 77503 | 65941 | 5517 MB/s | 3380 MB/s | 12735 MB/s | 14975 MB/s | +| lcet10.txt | 234661 | 184939 | 6235 MB/s | 3537 MB/s | 14519 MB/s | 16634 MB/s | +| plrabn12.txt | 319267 | 264990 | 5159 MB/s | 2960 MB/s | 11923 MB/s | 13382 MB/s | +| geo.protodata | 23335 | 17689 | 21220 MB/s | 10859 MB/s | 56271 MB/s | 57961 MB/s | +| kppkn.gtb | 69526 | 55398 | 9732 MB/s | 5206 MB/s | 18491 MB/s | 16524 MB/s | +| alice29.txt (128B) | 80 | 78 | 6691 MB/s | 7422 MB/s | 31883 MB/s | 34225 MB/s | +| alice29.txt (1000B) | 774 | 746 | 12204 MB/s | 5734 MB/s | 48056 MB/s | 42068 MB/s | +| alice29.txt (10000B) | 6648 | 6218 | 10044 MB/s | 6055 MB/s | 32378 MB/s | 28813 MB/s | +| alice29.txt (20000B) | 12686 | 11492 | 7733 MB/s | 3143 MB/s | 30566 MB/s | 27315 MB/s | + + +Except for the mostly incompressible JPEG image compression is better and usually in the +double digits in terms of percentage reduction over Snappy. + +The PDF sample shows a significant slowdown compared to Snappy, as this mode tries harder +to compress the data. Very small blocks are also not favorable for better compression, so throughput is way down. + +This mode aims to provide better compression at the expense of performance and achieves that +without a huge performance penalty, except on very small blocks. + +Decompression speed suffers a little compared to the regular S2 mode, +but still manages to be close to Snappy in spite of increased compression. + +# Best compression mode + +S2 offers a "best" compression mode. + +This will compress as much as possible with little regard to CPU usage. + +Mainly for offline compression, but where decompression speed should still +be high and compatible with other S2 compressed data. + +Some examples compared on 16 core CPU, amd64 assembly used: + +``` +* enwik10 +Default... 10000000000 -> 4759950115 [47.60%]; 1.03s, 9263.0MB/s +Better... 10000000000 -> 4084706676 [40.85%]; 2.16s, 4415.4MB/s +Best... 10000000000 -> 3615520079 [36.16%]; 42.259s, 225.7MB/s + +* github-june-2days-2019.json +Default... 6273951764 -> 1041700255 [16.60%]; 431ms, 13882.3MB/s +Better... 6273951764 -> 945841238 [15.08%]; 547ms, 10938.4MB/s +Best... 6273951764 -> 826392576 [13.17%]; 9.455s, 632.8MB/s + +* nyc-taxi-data-10M.csv +Default... 3325605752 -> 1093516949 [32.88%]; 324ms, 9788.7MB/s +Better... 3325605752 -> 885394158 [26.62%]; 491ms, 6459.4MB/s +Best... 3325605752 -> 773681257 [23.26%]; 8.29s, 412.0MB/s + +* 10gb.tar +Default... 10065157632 -> 5915541066 [58.77%]; 1.028s, 9337.4MB/s +Better... 10065157632 -> 5453844650 [54.19%]; 1.597s, 4862.7MB/s +Best... 10065157632 -> 5192495021 [51.59%]; 32.78s, 308.2MB/ + +* consensus.db.10gb +Default... 10737418240 -> 4549762344 [42.37%]; 882ms, 12118.4MB/s +Better... 10737418240 -> 4438535064 [41.34%]; 1.533s, 3500.9MB/s +Best... 10737418240 -> 4210602774 [39.21%]; 42.96s, 254.4MB/s +``` + +Decompression speed should be around the same as using the 'better' compression mode. + +## Dictionaries + +*Note: S2 dictionary compression is currently at an early implementation stage, with no assembly for +neither encoding nor decoding. Performance improvements can be expected in the future.* + +Adding dictionaries allow providing a custom dictionary that will serve as lookup in the beginning of blocks. + +The same dictionary *must* be used for both encoding and decoding. +S2 does not keep track of whether the same dictionary is used, +and using the wrong dictionary will most often not result in an error when decompressing. + +Blocks encoded *without* dictionaries can be decompressed seamlessly *with* a dictionary. +This means it is possible to switch from an encoding without dictionaries to an encoding with dictionaries +and treat the blocks similarly. + +Similar to [zStandard dictionaries](https://github.com/facebook/zstd#the-case-for-small-data-compression), +the same usage scenario applies to S2 dictionaries. + +> Training works if there is some correlation in a family of small data samples. The more data-specific a dictionary is, the more efficient it is (there is no universal dictionary). Hence, deploying one dictionary per type of data will provide the greatest benefits. Dictionary gains are mostly effective in the first few KB. Then, the compression algorithm will gradually use previously decoded content to better compress the rest of the file. + +S2 further limits the dictionary to only be enabled on the first 64KB of a block. +This will remove any negative (speed) impacts of the dictionaries on bigger blocks. + +### Compression + +Using the [github_users_sample_set](https://github.com/facebook/zstd/releases/download/v1.1.3/github_users_sample_set.tar.zst) +and a 64KB dictionary trained with zStandard the following sizes can be achieved. + +| | Default | Better | Best | +|--------------------|------------------|------------------|-----------------------| +| Without Dictionary | 3362023 (44.92%) | 3083163 (41.19%) | 3057944 (40.86%) | +| With Dictionary | 921524 (12.31%) | 873154 (11.67%) | 785503 bytes (10.49%) | + +So for highly repetitive content, this case provides an almost 3x reduction in size. + +For less uniform data we will use the Go source code tree. +Compressing First 64KB of all `.go` files in `go/src`, Go 1.19.5, 8912 files, 51253563 bytes input: + +| | Default | Better | Best | +|--------------------|-------------------|-------------------|-------------------| +| Without Dictionary | 22955767 (44.79%) | 20189613 (39.39% | 19482828 (38.01%) | +| With Dictionary | 19654568 (38.35%) | 16289357 (31.78%) | 15184589 (29.63%) | +| Saving/file | 362 bytes | 428 bytes | 472 bytes | + + +### Creating Dictionaries + +There are no tools to create dictionaries in S2. +However, there are multiple ways to create a useful dictionary: + +#### Using a Sample File + +If your input is very uniform, you can just use a sample file as the dictionary. + +For example in the `github_users_sample_set` above, the average compression only goes up from +10.49% to 11.48% by using the first file as dictionary compared to using a dedicated dictionary. + +```Go + // Read a sample + sample, err := os.ReadFile("sample.json") + + // Create a dictionary. + dict := s2.MakeDict(sample, nil) + + // b := dict.Bytes() will provide a dictionary that can be saved + // and reloaded with s2.NewDict(b). + + // To encode: + encoded := dict.Encode(nil, file) + + // To decode: + decoded, err := dict.Decode(nil, file) +``` + +#### Using Zstandard + +Zstandard dictionaries can easily be converted to S2 dictionaries. + +This can be helpful to generate dictionaries for files that don't have a fixed structure. + + +Example, with training set files placed in `./training-set`: + +`λ zstd -r --train-fastcover training-set/* --maxdict=65536 -o name.dict` + +This will create a dictionary of 64KB, that can be converted to a dictionary like this: + +```Go + // Decode the Zstandard dictionary. + insp, err := zstd.InspectDictionary(zdict) + if err != nil { + panic(err) + } + + // We are only interested in the contents. + // Assume that files start with "// Copyright (c) 2023". + // Search for the longest match for that. + // This may save a few bytes. + dict := s2.MakeDict(insp.Content(), []byte("// Copyright (c) 2023")) + + // b := dict.Bytes() will provide a dictionary that can be saved + // and reloaded with s2.NewDict(b). + + // We can now encode using this dictionary + encodedWithDict := dict.Encode(nil, payload) + + // To decode content: + decoded, err := dict.Decode(nil, encodedWithDict) +``` + +It is recommended to save the dictionary returned by ` b:= dict.Bytes()`, since that will contain only the S2 dictionary. + +This dictionary can later be loaded using `s2.NewDict(b)`. The dictionary then no longer requires `zstd` to be initialized. + +Also note how `s2.MakeDict` allows you to search for a common starting sequence of your files. +This can be omitted, at the expense of a few bytes. + +# Snappy Compatibility + +S2 now offers full compatibility with Snappy. + +This means that the efficient encoders of S2 can be used to generate fully Snappy compatible output. + +There is a [snappy](https://github.com/klauspost/compress/tree/master/snappy) package that can be used by +simply changing imports from `github.com/golang/snappy` to `github.com/klauspost/compress/snappy`. +This uses "better" mode for all operations. +If you would like more control, you can use the s2 package as described below: + +## Blocks + +Snappy compatible blocks can be generated with the S2 encoder. +Compression and speed is typically a bit better `MaxEncodedLen` is also smaller for smaller memory usage. Replace + +| Snappy | S2 replacement | +|---------------------------|-----------------------| +| snappy.Encode(...) | s2.EncodeSnappy(...) | +| snappy.MaxEncodedLen(...) | s2.MaxEncodedLen(...) | + +`s2.EncodeSnappy` can be replaced with `s2.EncodeSnappyBetter` or `s2.EncodeSnappyBest` to get more efficiently compressed snappy compatible output. + +`s2.ConcatBlocks` is compatible with snappy blocks. + +Comparison of [`webdevdata.org-2015-01-07-subset`](https://files.klauspost.com/compress/webdevdata.org-2015-01-07-4GB-subset.7z), +53927 files, total input size: 4,014,735,833 bytes. amd64, single goroutine used: + +| Encoder | Size | MB/s | Reduction | +|-----------------------|------------|------------|------------| +| snappy.Encode | 1128706759 | 725.59 | 71.89% | +| s2.EncodeSnappy | 1093823291 | **899.16** | 72.75% | +| s2.EncodeSnappyBetter | 1001158548 | 578.49 | 75.06% | +| s2.EncodeSnappyBest | 944507998 | 66.00 | **76.47%** | + +## Streams + +For streams, replace `enc = snappy.NewBufferedWriter(w)` with `enc = s2.NewWriter(w, s2.WriterSnappyCompat())`. +All other options are available, but note that block size limit is different for snappy. + +Comparison of different streams, AMD Ryzen 3950x, 16 cores. Size and throughput: + +| File | snappy.NewWriter | S2 Snappy | S2 Snappy, Better | S2 Snappy, Best | +|-----------------------------|--------------------------|---------------------------|--------------------------|-------------------------| +| nyc-taxi-data-10M.csv | 1316042016 - 539.47MB/s | 1307003093 - 10132.73MB/s | 1174534014 - 5002.44MB/s | 1115904679 - 177.97MB/s | +| enwik10 (xml) | 5088294643 - 451.13MB/s | 5175840939 - 9440.69MB/s | 4560784526 - 4487.21MB/s | 4340299103 - 158.92MB/s | +| 10gb.tar (mixed) | 6056946612 - 729.73MB/s | 6208571995 - 9978.05MB/s | 5741646126 - 4919.98MB/s | 5548973895 - 180.44MB/s | +| github-june-2days-2019.json | 1525176492 - 933.00MB/s | 1476519054 - 13150.12MB/s | 1400547532 - 5803.40MB/s | 1321887137 - 204.29MB/s | +| consensus.db.10gb (db) | 5412897703 - 1102.14MB/s | 5354073487 - 13562.91MB/s | 5335069899 - 5294.73MB/s | 5201000954 - 175.72MB/s | + +# Decompression + +All decompression functions map directly to equivalent s2 functions. + +| Snappy | S2 replacement | +|------------------------|--------------------| +| snappy.Decode(...) | s2.Decode(...) | +| snappy.DecodedLen(...) | s2.DecodedLen(...) | +| snappy.NewReader(...) | s2.NewReader(...) | + +Features like [quick forward skipping without decompression](https://pkg.go.dev/github.com/klauspost/compress/s2#Reader.Skip) +are also available for Snappy streams. + +If you know you are only decompressing snappy streams, setting [`ReaderMaxBlockSize(64<<10)`](https://pkg.go.dev/github.com/klauspost/compress/s2#ReaderMaxBlockSize) +on your Reader will reduce memory consumption. + +# Concatenating blocks and streams. + +Concatenating streams will concatenate the output of both without recompressing them. +While this is inefficient in terms of compression it might be usable in certain scenarios. +The 10 byte 'stream identifier' of the second stream can optionally be stripped, but it is not a requirement. + +Blocks can be concatenated using the `ConcatBlocks` function. + +Snappy blocks/streams can safely be concatenated with S2 blocks and streams. +Streams with indexes (see below) will currently not work on concatenated streams. + +# Stream Seek Index + +S2 and Snappy streams can have indexes. These indexes will allow random seeking within the compressed data. + +The index can either be appended to the stream as a skippable block or returned for separate storage. + +When the index is appended to a stream it will be skipped by regular decoders, +so the output remains compatible with other decoders. + +## Creating an Index + +To automatically add an index to a stream, add `WriterAddIndex()` option to your writer. +Then the index will be added to the stream when `Close()` is called. + +``` + // Add Index to stream... + enc := s2.NewWriter(w, s2.WriterAddIndex()) + io.Copy(enc, r) + enc.Close() +``` + +If you want to store the index separately, you can use `CloseIndex()` instead of the regular `Close()`. +This will return the index. Note that `CloseIndex()` should only be called once, and you shouldn't call `Close()`. + +``` + // Get index for separate storage... + enc := s2.NewWriter(w) + io.Copy(enc, r) + index, err := enc.CloseIndex() +``` + +The `index` can then be used needing to read from the stream. +This means the index can be used without needing to seek to the end of the stream +or for manually forwarding streams. See below. + +Finally, an existing S2/Snappy stream can be indexed using the `s2.IndexStream(r io.Reader)` function. + +## Using Indexes + +To use indexes there is a `ReadSeeker(random bool, index []byte) (*ReadSeeker, error)` function available. + +Calling ReadSeeker will return an [io.ReadSeeker](https://pkg.go.dev/io#ReadSeeker) compatible version of the reader. + +If 'random' is specified the returned io.Seeker can be used for random seeking, otherwise only forward seeking is supported. +Enabling random seeking requires the original input to support the [io.Seeker](https://pkg.go.dev/io#Seeker) interface. + +``` + dec := s2.NewReader(r) + rs, err := dec.ReadSeeker(false, nil) + rs.Seek(wantOffset, io.SeekStart) +``` + +Get a seeker to seek forward. Since no index is provided, the index is read from the stream. +This requires that an index was added and that `r` supports the [io.Seeker](https://pkg.go.dev/io#Seeker) interface. + +A custom index can be specified which will be used if supplied. +When using a custom index, it will not be read from the input stream. + +``` + dec := s2.NewReader(r) + rs, err := dec.ReadSeeker(false, index) + rs.Seek(wantOffset, io.SeekStart) +``` + +This will read the index from `index`. Since we specify non-random (forward only) seeking `r` does not have to be an io.Seeker + +``` + dec := s2.NewReader(r) + rs, err := dec.ReadSeeker(true, index) + rs.Seek(wantOffset, io.SeekStart) +``` + +Finally, since we specify that we want to do random seeking `r` must be an io.Seeker. + +The returned [ReadSeeker](https://pkg.go.dev/github.com/klauspost/compress/s2#ReadSeeker) contains a shallow reference to the existing Reader, +meaning changes performed to one is reflected in the other. + +To check if a stream contains an index at the end, the `(*Index).LoadStream(rs io.ReadSeeker) error` can be used. + +## Manually Forwarding Streams + +Indexes can also be read outside the decoder using the [Index](https://pkg.go.dev/github.com/klauspost/compress/s2#Index) type. +This can be used for parsing indexes, either separate or in streams. + +In some cases it may not be possible to serve a seekable stream. +This can for instance be an HTTP stream, where the Range request +is sent at the start of the stream. + +With a little bit of extra code it is still possible to use indexes +to forward to specific offset with a single forward skip. + +It is possible to load the index manually like this: +``` + var index s2.Index + _, err = index.Load(idxBytes) +``` + +This can be used to figure out how much to offset the compressed stream: + +``` + compressedOffset, uncompressedOffset, err := index.Find(wantOffset) +``` + +The `compressedOffset` is the number of bytes that should be skipped +from the beginning of the compressed file. + +The `uncompressedOffset` will then be offset of the uncompressed bytes returned +when decoding from that position. This will always be <= wantOffset. + +When creating a decoder it must be specified that it should *not* expect a stream identifier +at the beginning of the stream. Assuming the io.Reader `r` has been forwarded to `compressedOffset` +we create the decoder like this: + +``` + dec := s2.NewReader(r, s2.ReaderIgnoreStreamIdentifier()) +``` + +We are not completely done. We still need to forward the stream the uncompressed bytes we didn't want. +This is done using the regular "Skip" function: + +``` + err = dec.Skip(wantOffset - uncompressedOffset) +``` + +This will ensure that we are at exactly the offset we want, and reading from `dec` will start at the requested offset. + +# Compact storage + +For compact storage [RemoveIndexHeaders](https://pkg.go.dev/github.com/klauspost/compress/s2#RemoveIndexHeaders) can be used to remove any redundant info from +a serialized index. If you remove the header it must be restored before [Loading](https://pkg.go.dev/github.com/klauspost/compress/s2#Index.Load). + +This is expected to save 20 bytes. These can be restored using [RestoreIndexHeaders](https://pkg.go.dev/github.com/klauspost/compress/s2#RestoreIndexHeaders). This removes a layer of security, but is the most compact representation. Returns nil if headers contains errors. + +## Index Format: + +Each block is structured as a snappy skippable block, with the chunk ID 0x99. + +The block can be read from the front, but contains information so it can be read from the back as well. + +Numbers are stored as fixed size little endian values or [zigzag encoded](https://developers.google.com/protocol-buffers/docs/encoding#signed_integers) [base 128 varints](https://developers.google.com/protocol-buffers/docs/encoding), +with un-encoded value length of 64 bits, unless other limits are specified. + +| Content | Format | +|--------------------------------------|-------------------------------------------------------------------------------------------------------------------------------| +| ID, `[1]byte` | Always 0x99. | +| Data Length, `[3]byte` | 3 byte little-endian length of the chunk in bytes, following this. | +| Header `[6]byte` | Header, must be `[115, 50, 105, 100, 120, 0]` or in text: "s2idx\x00". | +| UncompressedSize, Varint | Total Uncompressed size. | +| CompressedSize, Varint | Total Compressed size if known. Should be -1 if unknown. | +| EstBlockSize, Varint | Block Size, used for guessing uncompressed offsets. Must be >= 0. | +| Entries, Varint | Number of Entries in index, must be < 65536 and >=0. | +| HasUncompressedOffsets `byte` | 0 if no uncompressed offsets are present, 1 if present. Other values are invalid. | +| UncompressedOffsets, [Entries]VarInt | Uncompressed offsets. See below how to decode. | +| CompressedOffsets, [Entries]VarInt | Compressed offsets. See below how to decode. | +| Block Size, `[4]byte` | Little Endian total encoded size (including header and trailer). Can be used for searching backwards to start of block. | +| Trailer `[6]byte` | Trailer, must be `[0, 120, 100, 105, 50, 115]` or in text: "\x00xdi2s". Can be used for identifying block from end of stream. | + +For regular streams the uncompressed offsets are fully predictable, +so `HasUncompressedOffsets` allows to specify that compressed blocks all have +exactly `EstBlockSize` bytes of uncompressed content. + +Entries *must* be in order, starting with the lowest offset, +and there *must* be no uncompressed offset duplicates. +Entries *may* point to the start of a skippable block, +but it is then not allowed to also have an entry for the next block since +that would give an uncompressed offset duplicate. + +There is no requirement for all blocks to be represented in the index. +In fact there is a maximum of 65536 block entries in an index. + +The writer can use any method to reduce the number of entries. +An implicit block start at 0,0 can be assumed. + +### Decoding entries: + +``` +// Read Uncompressed entries. +// Each assumes EstBlockSize delta from previous. +for each entry { + uOff = 0 + if HasUncompressedOffsets == 1 { + uOff = ReadVarInt // Read value from stream + } + + // Except for the first entry, use previous values. + if entryNum == 0 { + entry[entryNum].UncompressedOffset = uOff + continue + } + + // Uncompressed uses previous offset and adds EstBlockSize + entry[entryNum].UncompressedOffset = entry[entryNum-1].UncompressedOffset + EstBlockSize + uOff +} + + +// Guess that the first block will be 50% of uncompressed size. +// Integer truncating division must be used. +CompressGuess := EstBlockSize / 2 + +// Read Compressed entries. +// Each assumes CompressGuess delta from previous. +// CompressGuess is adjusted for each value. +for each entry { + cOff = ReadVarInt // Read value from stream + + // Except for the first entry, use previous values. + if entryNum == 0 { + entry[entryNum].CompressedOffset = cOff + continue + } + + // Compressed uses previous and our estimate. + entry[entryNum].CompressedOffset = entry[entryNum-1].CompressedOffset + CompressGuess + cOff + + // Adjust compressed offset for next loop, integer truncating division must be used. + CompressGuess += cOff/2 +} +``` + +To decode from any given uncompressed offset `(wantOffset)`: + +* Iterate entries until `entry[n].UncompressedOffset > wantOffset`. +* Start decoding from `entry[n-1].CompressedOffset`. +* Discard `entry[n-1].UncompressedOffset - wantOffset` bytes from the decoded stream. + +See [using indexes](https://github.com/klauspost/compress/tree/master/s2#using-indexes) for functions that perform the operations with a simpler interface. + + +# Format Extensions + +* Frame [Stream identifier](https://github.com/google/snappy/blob/master/framing_format.txt#L68) changed from `sNaPpY` to `S2sTwO`. +* [Framed compressed blocks](https://github.com/google/snappy/blob/master/format_description.txt) can be up to 4MB (up from 64KB). +* Compressed blocks can have an offset of `0`, which indicates to repeat the last seen offset. + +Repeat offsets must be encoded as a [2.2.1. Copy with 1-byte offset (01)](https://github.com/google/snappy/blob/master/format_description.txt#L89), where the offset is 0. + +The length is specified by reading the 3-bit length specified in the tag and decode using this table: + +| Length | Actual Length | +|--------|----------------------| +| 0 | 4 | +| 1 | 5 | +| 2 | 6 | +| 3 | 7 | +| 4 | 8 | +| 5 | 8 + read 1 byte | +| 6 | 260 + read 2 bytes | +| 7 | 65540 + read 3 bytes | + +This allows any repeat offset + length to be represented by 2 to 5 bytes. +It also allows to emit matches longer than 64 bytes with one copy + one repeat instead of several 64 byte copies. + +Lengths are stored as little endian values. + +The first copy of a block cannot be a repeat offset and the offset is reset on every block in streams. + +Default streaming block size is 1MB. + +# Dictionary Encoding + +Adding dictionaries allow providing a custom dictionary that will serve as lookup in the beginning of blocks. + +A dictionary provides an initial repeat value that can be used to point to a common header. + +Other than that the dictionary contains values that can be used as back-references. + +Often used data should be placed at the *end* of the dictionary since offsets < 2048 bytes will be smaller. + +## Format + +Dictionary *content* must at least 16 bytes and less or equal to 64KiB (65536 bytes). + +Encoding: `[repeat value (uvarint)][dictionary content...]` + +Before the dictionary content, an unsigned base-128 (uvarint) encoded value specifying the initial repeat offset. +This value is an offset into the dictionary content and not a back-reference offset, +so setting this to 0 will make the repeat value point to the first value of the dictionary. + +The value must be less than the dictionary length-8 + +## Encoding + +From the decoder point of view the dictionary content is seen as preceding the encoded content. + +`[dictionary content][decoded output]` + +Backreferences to the dictionary are encoded as ordinary backreferences that have an offset before the start of the decoded block. + +Matches copying from the dictionary are **not** allowed to cross from the dictionary into the decoded data. +However, if a copy ends at the end of the dictionary the next repeat will point to the start of the decoded buffer, which is allowed. + +The first match can be a repeat value, which will use the repeat offset stored in the dictionary. + +When 64KB (65536 bytes) has been en/decoded it is no longer allowed to reference the dictionary, +neither by a copy nor repeat operations. +If the boundary is crossed while copying from the dictionary, the operation should complete, +but the next instruction is not allowed to reference the dictionary. + +Valid blocks encoded *without* a dictionary can be decoded with any dictionary. +There are no checks whether the supplied dictionary is the correct for a block. +Because of this there is no overhead by using a dictionary. + +## Example + +This is the dictionary content. Elements are separated by `[]`. + +Dictionary: `[0x0a][Yesterday 25 bananas were added to Benjamins brown bag]`. + +Initial repeat offset is set at 10, which is the letter `2`. + +Encoded `[LIT "10"][REPEAT len=10][LIT "hich"][MATCH off=50 len=6][MATCH off=31 len=6][MATCH off=61 len=10]` + +Decoded: `[10][ bananas w][hich][ were ][brown ][were added]` + +Output: `10 bananas which were brown were added` + + +## Streams + +For streams each block can use the dictionary. + +The dictionary cannot not currently be provided on the stream. + + +# LICENSE + +This code is based on the [Snappy-Go](https://github.com/golang/snappy) implementation. + +Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. diff --git a/vendor/github.com/klauspost/compress/s2/decode.go b/vendor/github.com/klauspost/compress/s2/decode.go new file mode 100644 index 0000000..264ffd0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/decode.go @@ -0,0 +1,443 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "encoding/binary" + "errors" + "fmt" + "strconv" + + "github.com/klauspost/compress/internal/race" +) + +var ( + // ErrCorrupt reports that the input is invalid. + ErrCorrupt = errors.New("s2: corrupt input") + // ErrCRC reports that the input failed CRC validation (streams only) + ErrCRC = errors.New("s2: corrupt input, crc mismatch") + // ErrTooLarge reports that the uncompressed length is too large. + ErrTooLarge = errors.New("s2: decoded block is too large") + // ErrUnsupported reports that the input isn't supported. + ErrUnsupported = errors.New("s2: unsupported input") +) + +// DecodedLen returns the length of the decoded block. +func DecodedLen(src []byte) (int, error) { + v, _, err := decodedLen(src) + return v, err +} + +// decodedLen returns the length of the decoded block and the number of bytes +// that the length header occupied. +func decodedLen(src []byte) (blockLen, headerLen int, err error) { + v, n := binary.Uvarint(src) + if n <= 0 || v > 0xffffffff { + return 0, 0, ErrCorrupt + } + + const wordSize = 32 << (^uint(0) >> 32 & 1) + if wordSize == 32 && v > 0x7fffffff { + return 0, 0, ErrTooLarge + } + return int(v), n, nil +} + +const ( + decodeErrCodeCorrupt = 1 +) + +// Decode returns the decoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire decoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +func Decode(dst, src []byte) ([]byte, error) { + dLen, s, err := decodedLen(src) + if err != nil { + return nil, err + } + if dLen <= cap(dst) { + dst = dst[:dLen] + } else { + dst = make([]byte, dLen) + } + + race.WriteSlice(dst) + race.ReadSlice(src[s:]) + + if s2Decode(dst, src[s:]) != 0 { + return nil, ErrCorrupt + } + return dst, nil +} + +// s2DecodeDict writes the decoding of src to dst. It assumes that the varint-encoded +// length of the decompressed bytes has already been read, and that len(dst) +// equals that length. +// +// It returns 0 on success or a decodeErrCodeXxx error code on failure. +func s2DecodeDict(dst, src []byte, dict *Dict) int { + if dict == nil { + return s2Decode(dst, src) + } + const debug = false + const debugErrs = debug + + if debug { + fmt.Println("Starting decode, dst len:", len(dst)) + } + var d, s, length int + offset := len(dict.dict) - dict.repeat + + // As long as we can read at least 5 bytes... + for s < len(src)-5 { + // Removing bounds checks is SLOWER, when if doing + // in := src[s:s+5] + // Checked on Go 1.18 + switch src[s] & 0x03 { + case tagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + x = uint32(src[s-1]) + case x == 61: + in := src[s : s+3] + x = uint32(in[1]) | uint32(in[2])<<8 + s += 3 + case x == 62: + in := src[s : s+4] + // Load as 32 bit and shift down. + x = uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + x >>= 8 + s += 4 + case x == 63: + in := src[s : s+5] + x = uint32(in[1]) | uint32(in[2])<<8 | uint32(in[3])<<16 | uint32(in[4])<<24 + s += 5 + } + length = int(x) + 1 + if debug { + fmt.Println("literals, length:", length, "d-after:", d+length) + } + if length > len(dst)-d || length > len(src)-s || (strconv.IntSize == 32 && length <= 0) { + if debugErrs { + fmt.Println("corrupt literal: length:", length, "d-left:", len(dst)-d, "src-left:", len(src)-s) + } + return decodeErrCodeCorrupt + } + + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + + case tagCopy1: + s += 2 + toffset := int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + length = int(src[s-2]) >> 2 & 0x7 + if toffset == 0 { + if debug { + fmt.Print("(repeat) ") + } + // keep last offset + switch length { + case 5: + length = int(src[s]) + 4 + s += 1 + case 6: + in := src[s : s+2] + length = int(uint32(in[0])|(uint32(in[1])<<8)) + (1 << 8) + s += 2 + case 7: + in := src[s : s+3] + length = int((uint32(in[2])<<16)|(uint32(in[1])<<8)|uint32(in[0])) + (1 << 16) + s += 3 + default: // 0-> 4 + } + } else { + offset = toffset + } + length += 4 + case tagCopy2: + in := src[s : s+3] + offset = int(uint32(in[1]) | uint32(in[2])<<8) + length = 1 + int(in[0])>>2 + s += 3 + + case tagCopy4: + in := src[s : s+5] + offset = int(uint32(in[1]) | uint32(in[2])<<8 | uint32(in[3])<<16 | uint32(in[4])<<24) + length = 1 + int(in[0])>>2 + s += 5 + } + + if offset <= 0 || length > len(dst)-d { + if debugErrs { + fmt.Println("match error; offset:", offset, "length:", length, "dst-left:", len(dst)-d) + } + return decodeErrCodeCorrupt + } + + // copy from dict + if d < offset { + if d > MaxDictSrcOffset { + if debugErrs { + fmt.Println("dict after", MaxDictSrcOffset, "d:", d, "offset:", offset, "length:", length) + } + return decodeErrCodeCorrupt + } + startOff := len(dict.dict) - offset + d + if startOff < 0 || startOff+length > len(dict.dict) { + if debugErrs { + fmt.Printf("offset (%d) + length (%d) bigger than dict (%d)\n", offset, length, len(dict.dict)) + } + return decodeErrCodeCorrupt + } + if debug { + fmt.Println("dict copy, length:", length, "offset:", offset, "d-after:", d+length, "dict start offset:", startOff) + } + copy(dst[d:d+length], dict.dict[startOff:]) + d += length + continue + } + + if debug { + fmt.Println("copy, length:", length, "offset:", offset, "d-after:", d+length) + } + + // Copy from an earlier sub-slice of dst to a later sub-slice. + // If no overlap, use the built-in copy: + if offset > length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + + // Unlike the built-in copy function, this byte-by-byte copy always runs + // forwards, even if the slices overlap. Conceptually, this is: + // + // d += forwardCopy(dst[d:d+length], dst[d-offset:]) + // + // We align the slices into a and b and show the compiler they are the same size. + // This allows the loop to run without bounds checks. + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] + } + d += length + } + + // Remaining with extra checks... + for s < len(src) { + switch src[s] & 0x03 { + case tagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + x = uint32(src[s-1]) + case x == 61: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + x = uint32(src[s-2]) | uint32(src[s-1])<<8 + case x == 62: + s += 4 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + case x == 63: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + length = int(x) + 1 + if length > len(dst)-d || length > len(src)-s || (strconv.IntSize == 32 && length <= 0) { + if debugErrs { + fmt.Println("corrupt literal: length:", length, "d-left:", len(dst)-d, "src-left:", len(src)-s) + } + return decodeErrCodeCorrupt + } + if debug { + fmt.Println("literals, length:", length, "d-after:", d+length) + } + + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + + case tagCopy1: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + length = int(src[s-2]) >> 2 & 0x7 + toffset := int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + if toffset == 0 { + if debug { + fmt.Print("(repeat) ") + } + // keep last offset + switch length { + case 5: + s += 1 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + length = int(uint32(src[s-1])) + 4 + case 6: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + length = int(uint32(src[s-2])|(uint32(src[s-1])<<8)) + (1 << 8) + case 7: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + length = int(uint32(src[s-3])|(uint32(src[s-2])<<8)|(uint32(src[s-1])<<16)) + (1 << 16) + default: // 0-> 4 + } + } else { + offset = toffset + } + length += 4 + case tagCopy2: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-3])>>2 + offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + + case tagCopy4: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + if debugErrs { + fmt.Println("src went oob") + } + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-5])>>2 + offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + } + + if offset <= 0 || length > len(dst)-d { + if debugErrs { + fmt.Println("match error; offset:", offset, "length:", length, "dst-left:", len(dst)-d) + } + return decodeErrCodeCorrupt + } + + // copy from dict + if d < offset { + if d > MaxDictSrcOffset { + if debugErrs { + fmt.Println("dict after", MaxDictSrcOffset, "d:", d, "offset:", offset, "length:", length) + } + return decodeErrCodeCorrupt + } + rOff := len(dict.dict) - (offset - d) + if debug { + fmt.Println("starting dict entry from dict offset", len(dict.dict)-rOff) + } + if rOff+length > len(dict.dict) { + if debugErrs { + fmt.Println("err: END offset", rOff+length, "bigger than dict", len(dict.dict), "dict offset:", rOff, "length:", length) + } + return decodeErrCodeCorrupt + } + if rOff < 0 { + if debugErrs { + fmt.Println("err: START offset", rOff, "less than 0", len(dict.dict), "dict offset:", rOff, "length:", length) + } + return decodeErrCodeCorrupt + } + copy(dst[d:d+length], dict.dict[rOff:]) + d += length + continue + } + + if debug { + fmt.Println("copy, length:", length, "offset:", offset, "d-after:", d+length) + } + + // Copy from an earlier sub-slice of dst to a later sub-slice. + // If no overlap, use the built-in copy: + if offset > length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + + // Unlike the built-in copy function, this byte-by-byte copy always runs + // forwards, even if the slices overlap. Conceptually, this is: + // + // d += forwardCopy(dst[d:d+length], dst[d-offset:]) + // + // We align the slices into a and b and show the compiler they are the same size. + // This allows the loop to run without bounds checks. + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] + } + d += length + } + + if d != len(dst) { + if debugErrs { + fmt.Println("wanted length", len(dst), "got", d) + } + return decodeErrCodeCorrupt + } + return 0 +} diff --git a/vendor/github.com/klauspost/compress/s2/decode_amd64.s b/vendor/github.com/klauspost/compress/s2/decode_amd64.s new file mode 100644 index 0000000..9b105e0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/decode_amd64.s @@ -0,0 +1,568 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +#define R_TMP0 AX +#define R_TMP1 BX +#define R_LEN CX +#define R_OFF DX +#define R_SRC SI +#define R_DST DI +#define R_DBASE R8 +#define R_DLEN R9 +#define R_DEND R10 +#define R_SBASE R11 +#define R_SLEN R12 +#define R_SEND R13 +#define R_TMP2 R14 +#define R_TMP3 R15 + +// The asm code generally follows the pure Go code in decode_other.go, except +// where marked with a "!!!". + +// func decode(dst, src []byte) int +// +// All local variables fit into registers. The non-zero stack size is only to +// spill registers and push args when issuing a CALL. The register allocation: +// - R_TMP0 scratch +// - R_TMP1 scratch +// - R_LEN length or x (shared) +// - R_OFF offset +// - R_SRC &src[s] +// - R_DST &dst[d] +// + R_DBASE dst_base +// + R_DLEN dst_len +// + R_DEND dst_base + dst_len +// + R_SBASE src_base +// + R_SLEN src_len +// + R_SEND src_base + src_len +// - R_TMP2 used by doCopy +// - R_TMP3 used by doCopy +// +// The registers R_DBASE-R_SEND (marked with a "+") are set at the start of the +// function, and after a CALL returns, and are not otherwise modified. +// +// The d variable is implicitly R_DST - R_DBASE, and len(dst)-d is R_DEND - R_DST. +// The s variable is implicitly R_SRC - R_SBASE, and len(src)-s is R_SEND - R_SRC. +TEXT ·s2Decode(SB), NOSPLIT, $48-56 + // Initialize R_SRC, R_DST and R_DBASE-R_SEND. + MOVQ dst_base+0(FP), R_DBASE + MOVQ dst_len+8(FP), R_DLEN + MOVQ R_DBASE, R_DST + MOVQ R_DBASE, R_DEND + ADDQ R_DLEN, R_DEND + MOVQ src_base+24(FP), R_SBASE + MOVQ src_len+32(FP), R_SLEN + MOVQ R_SBASE, R_SRC + MOVQ R_SBASE, R_SEND + ADDQ R_SLEN, R_SEND + XORQ R_OFF, R_OFF + +loop: + // for s < len(src) + CMPQ R_SRC, R_SEND + JEQ end + + // R_LEN = uint32(src[s]) + // + // switch src[s] & 0x03 + MOVBLZX (R_SRC), R_LEN + MOVL R_LEN, R_TMP1 + ANDL $3, R_TMP1 + CMPL R_TMP1, $1 + JAE tagCopy + + // ---------------------------------------- + // The code below handles literal tags. + + // case tagLiteral: + // x := uint32(src[s] >> 2) + // switch + SHRL $2, R_LEN + CMPL R_LEN, $60 + JAE tagLit60Plus + + // case x < 60: + // s++ + INCQ R_SRC + +doLit: + // This is the end of the inner "switch", when we have a literal tag. + // + // We assume that R_LEN == x and x fits in a uint32, where x is the variable + // used in the pure Go decode_other.go code. + + // length = int(x) + 1 + // + // Unlike the pure Go code, we don't need to check if length <= 0 because + // R_LEN can hold 64 bits, so the increment cannot overflow. + INCQ R_LEN + + // Prepare to check if copying length bytes will run past the end of dst or + // src. + // + // R_TMP0 = len(dst) - d + // R_TMP1 = len(src) - s + MOVQ R_DEND, R_TMP0 + SUBQ R_DST, R_TMP0 + MOVQ R_SEND, R_TMP1 + SUBQ R_SRC, R_TMP1 + + // !!! Try a faster technique for short (16 or fewer bytes) copies. + // + // if length > 16 || len(dst)-d < 16 || len(src)-s < 16 { + // goto callMemmove // Fall back on calling runtime·memmove. + // } + // + // The C++ snappy code calls this TryFastAppend. It also checks len(src)-s + // against 21 instead of 16, because it cannot assume that all of its input + // is contiguous in memory and so it needs to leave enough source bytes to + // read the next tag without refilling buffers, but Go's Decode assumes + // contiguousness (the src argument is a []byte). + CMPQ R_LEN, $16 + JGT callMemmove + CMPQ R_TMP0, $16 + JLT callMemmove + CMPQ R_TMP1, $16 + JLT callMemmove + + // !!! Implement the copy from src to dst as a 16-byte load and store. + // (Decode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only length bytes, but that's + // OK. If the input is a valid Snappy encoding then subsequent iterations + // will fix up the overrun. Otherwise, Decode returns a nil []byte (and a + // non-nil error), so the overrun will be ignored. + // + // Note that on amd64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + MOVOU 0(R_SRC), X0 + MOVOU X0, 0(R_DST) + + // d += length + // s += length + ADDQ R_LEN, R_DST + ADDQ R_LEN, R_SRC + JMP loop + +callMemmove: + // if length > len(dst)-d || length > len(src)-s { etc } + CMPQ R_LEN, R_TMP0 + JGT errCorrupt + CMPQ R_LEN, R_TMP1 + JGT errCorrupt + + // copy(dst[d:], src[s:s+length]) + // + // This means calling runtime·memmove(&dst[d], &src[s], length), so we push + // R_DST, R_SRC and R_LEN as arguments. Coincidentally, we also need to spill those + // three registers to the stack, to save local variables across the CALL. + MOVQ R_DST, 0(SP) + MOVQ R_SRC, 8(SP) + MOVQ R_LEN, 16(SP) + MOVQ R_DST, 24(SP) + MOVQ R_SRC, 32(SP) + MOVQ R_LEN, 40(SP) + MOVQ R_OFF, 48(SP) + CALL runtime·memmove(SB) + + // Restore local variables: unspill registers from the stack and + // re-calculate R_DBASE-R_SEND. + MOVQ 24(SP), R_DST + MOVQ 32(SP), R_SRC + MOVQ 40(SP), R_LEN + MOVQ 48(SP), R_OFF + MOVQ dst_base+0(FP), R_DBASE + MOVQ dst_len+8(FP), R_DLEN + MOVQ R_DBASE, R_DEND + ADDQ R_DLEN, R_DEND + MOVQ src_base+24(FP), R_SBASE + MOVQ src_len+32(FP), R_SLEN + MOVQ R_SBASE, R_SEND + ADDQ R_SLEN, R_SEND + + // d += length + // s += length + ADDQ R_LEN, R_DST + ADDQ R_LEN, R_SRC + JMP loop + +tagLit60Plus: + // !!! This fragment does the + // + // s += x - 58; if uint(s) > uint(len(src)) { etc } + // + // checks. In the asm version, we code it once instead of once per switch case. + ADDQ R_LEN, R_SRC + SUBQ $58, R_SRC + CMPQ R_SRC, R_SEND + JA errCorrupt + + // case x == 60: + CMPL R_LEN, $61 + JEQ tagLit61 + JA tagLit62Plus + + // x = uint32(src[s-1]) + MOVBLZX -1(R_SRC), R_LEN + JMP doLit + +tagLit61: + // case x == 61: + // x = uint32(src[s-2]) | uint32(src[s-1])<<8 + MOVWLZX -2(R_SRC), R_LEN + JMP doLit + +tagLit62Plus: + CMPL R_LEN, $62 + JA tagLit63 + + // case x == 62: + // x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + // We read one byte, safe to read one back, since we are just reading tag. + // x = binary.LittleEndian.Uint32(src[s-1:]) >> 8 + MOVL -4(R_SRC), R_LEN + SHRL $8, R_LEN + JMP doLit + +tagLit63: + // case x == 63: + // x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + MOVL -4(R_SRC), R_LEN + JMP doLit + +// The code above handles literal tags. +// ---------------------------------------- +// The code below handles copy tags. + +tagCopy4: + // case tagCopy4: + // s += 5 + ADDQ $5, R_SRC + + // if uint(s) > uint(len(src)) { etc } + CMPQ R_SRC, R_SEND + JA errCorrupt + + // length = 1 + int(src[s-5])>>2 + SHRQ $2, R_LEN + INCQ R_LEN + + // offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + MOVLQZX -4(R_SRC), R_OFF + JMP doCopy + +tagCopy2: + // case tagCopy2: + // s += 3 + ADDQ $3, R_SRC + + // if uint(s) > uint(len(src)) { etc } + CMPQ R_SRC, R_SEND + JA errCorrupt + + // length = 1 + int(src[s-3])>>2 + SHRQ $2, R_LEN + INCQ R_LEN + + // offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + MOVWQZX -2(R_SRC), R_OFF + JMP doCopy + +tagCopy: + // We have a copy tag. We assume that: + // - R_TMP1 == src[s] & 0x03 + // - R_LEN == src[s] + CMPQ R_TMP1, $2 + JEQ tagCopy2 + JA tagCopy4 + + // case tagCopy1: + // s += 2 + ADDQ $2, R_SRC + + // if uint(s) > uint(len(src)) { etc } + CMPQ R_SRC, R_SEND + JA errCorrupt + + // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + // length = 4 + int(src[s-2])>>2&0x7 + MOVBQZX -1(R_SRC), R_TMP1 + MOVQ R_LEN, R_TMP0 + SHRQ $2, R_LEN + ANDQ $0xe0, R_TMP0 + ANDQ $7, R_LEN + SHLQ $3, R_TMP0 + ADDQ $4, R_LEN + ORQ R_TMP1, R_TMP0 + + // check if repeat code, ZF set by ORQ. + JZ repeatCode + + // This is a regular copy, transfer our temporary value to R_OFF (length) + MOVQ R_TMP0, R_OFF + JMP doCopy + +// This is a repeat code. +repeatCode: + // If length < 9, reuse last offset, with the length already calculated. + CMPQ R_LEN, $9 + JL doCopyRepeat + + // Read additional bytes for length. + JE repeatLen1 + + // Rare, so the extra branch shouldn't hurt too much. + CMPQ R_LEN, $10 + JE repeatLen2 + JMP repeatLen3 + +// Read repeat lengths. +repeatLen1: + // s ++ + ADDQ $1, R_SRC + + // if uint(s) > uint(len(src)) { etc } + CMPQ R_SRC, R_SEND + JA errCorrupt + + // length = src[s-1] + 8 + MOVBQZX -1(R_SRC), R_LEN + ADDL $8, R_LEN + JMP doCopyRepeat + +repeatLen2: + // s +=2 + ADDQ $2, R_SRC + + // if uint(s) > uint(len(src)) { etc } + CMPQ R_SRC, R_SEND + JA errCorrupt + + // length = uint32(src[s-2]) | (uint32(src[s-1])<<8) + (1 << 8) + MOVWQZX -2(R_SRC), R_LEN + ADDL $260, R_LEN + JMP doCopyRepeat + +repeatLen3: + // s +=3 + ADDQ $3, R_SRC + + // if uint(s) > uint(len(src)) { etc } + CMPQ R_SRC, R_SEND + JA errCorrupt + + // length = uint32(src[s-3]) | (uint32(src[s-2])<<8) | (uint32(src[s-1])<<16) + (1 << 16) + // Read one byte further back (just part of the tag, shifted out) + MOVL -4(R_SRC), R_LEN + SHRL $8, R_LEN + ADDL $65540, R_LEN + JMP doCopyRepeat + +doCopy: + // This is the end of the outer "switch", when we have a copy tag. + // + // We assume that: + // - R_LEN == length && R_LEN > 0 + // - R_OFF == offset + + // if d < offset { etc } + MOVQ R_DST, R_TMP1 + SUBQ R_DBASE, R_TMP1 + CMPQ R_TMP1, R_OFF + JLT errCorrupt + + // Repeat values can skip the test above, since any offset > 0 will be in dst. +doCopyRepeat: + // if offset <= 0 { etc } + CMPQ R_OFF, $0 + JLE errCorrupt + + // if length > len(dst)-d { etc } + MOVQ R_DEND, R_TMP1 + SUBQ R_DST, R_TMP1 + CMPQ R_LEN, R_TMP1 + JGT errCorrupt + + // forwardCopy(dst[d:d+length], dst[d-offset:]); d += length + // + // Set: + // - R_TMP2 = len(dst)-d + // - R_TMP3 = &dst[d-offset] + MOVQ R_DEND, R_TMP2 + SUBQ R_DST, R_TMP2 + MOVQ R_DST, R_TMP3 + SUBQ R_OFF, R_TMP3 + + // !!! Try a faster technique for short (16 or fewer bytes) forward copies. + // + // First, try using two 8-byte load/stores, similar to the doLit technique + // above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is + // still OK if offset >= 8. Note that this has to be two 8-byte load/stores + // and not one 16-byte load/store, and the first store has to be before the + // second load, due to the overlap if offset is in the range [8, 16). + // + // if length > 16 || offset < 8 || len(dst)-d < 16 { + // goto slowForwardCopy + // } + // copy 16 bytes + // d += length + CMPQ R_LEN, $16 + JGT slowForwardCopy + CMPQ R_OFF, $8 + JLT slowForwardCopy + CMPQ R_TMP2, $16 + JLT slowForwardCopy + MOVQ 0(R_TMP3), R_TMP0 + MOVQ R_TMP0, 0(R_DST) + MOVQ 8(R_TMP3), R_TMP1 + MOVQ R_TMP1, 8(R_DST) + ADDQ R_LEN, R_DST + JMP loop + +slowForwardCopy: + // !!! If the forward copy is longer than 16 bytes, or if offset < 8, we + // can still try 8-byte load stores, provided we can overrun up to 10 extra + // bytes. As above, the overrun will be fixed up by subsequent iterations + // of the outermost loop. + // + // The C++ snappy code calls this technique IncrementalCopyFastPath. Its + // commentary says: + // + // ---- + // + // The main part of this loop is a simple copy of eight bytes at a time + // until we've copied (at least) the requested amount of bytes. However, + // if d and d-offset are less than eight bytes apart (indicating a + // repeating pattern of length < 8), we first need to expand the pattern in + // order to get the correct results. For instance, if the buffer looks like + // this, with the eight-byte and patterns marked as + // intervals: + // + // abxxxxxxxxxxxx + // [------] d-offset + // [------] d + // + // a single eight-byte copy from to will repeat the pattern + // once, after which we can move two bytes without moving : + // + // ababxxxxxxxxxx + // [------] d-offset + // [------] d + // + // and repeat the exercise until the two no longer overlap. + // + // This allows us to do very well in the special case of one single byte + // repeated many times, without taking a big hit for more general cases. + // + // The worst case of extra writing past the end of the match occurs when + // offset == 1 and length == 1; the last copy will read from byte positions + // [0..7] and write to [4..11], whereas it was only supposed to write to + // position 1. Thus, ten excess bytes. + // + // ---- + // + // That "10 byte overrun" worst case is confirmed by Go's + // TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy + // and finishSlowForwardCopy algorithm. + // + // if length > len(dst)-d-10 { + // goto verySlowForwardCopy + // } + SUBQ $10, R_TMP2 + CMPQ R_LEN, R_TMP2 + JGT verySlowForwardCopy + + // We want to keep the offset, so we use R_TMP2 from here. + MOVQ R_OFF, R_TMP2 + +makeOffsetAtLeast8: + // !!! As above, expand the pattern so that offset >= 8 and we can use + // 8-byte load/stores. + // + // for offset < 8 { + // copy 8 bytes from dst[d-offset:] to dst[d:] + // length -= offset + // d += offset + // offset += offset + // // The two previous lines together means that d-offset, and therefore + // // R_TMP3, is unchanged. + // } + CMPQ R_TMP2, $8 + JGE fixUpSlowForwardCopy + MOVQ (R_TMP3), R_TMP1 + MOVQ R_TMP1, (R_DST) + SUBQ R_TMP2, R_LEN + ADDQ R_TMP2, R_DST + ADDQ R_TMP2, R_TMP2 + JMP makeOffsetAtLeast8 + +fixUpSlowForwardCopy: + // !!! Add length (which might be negative now) to d (implied by R_DST being + // &dst[d]) so that d ends up at the right place when we jump back to the + // top of the loop. Before we do that, though, we save R_DST to R_TMP0 so that, if + // length is positive, copying the remaining length bytes will write to the + // right place. + MOVQ R_DST, R_TMP0 + ADDQ R_LEN, R_DST + +finishSlowForwardCopy: + // !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative + // length means that we overrun, but as above, that will be fixed up by + // subsequent iterations of the outermost loop. + CMPQ R_LEN, $0 + JLE loop + MOVQ (R_TMP3), R_TMP1 + MOVQ R_TMP1, (R_TMP0) + ADDQ $8, R_TMP3 + ADDQ $8, R_TMP0 + SUBQ $8, R_LEN + JMP finishSlowForwardCopy + +verySlowForwardCopy: + // verySlowForwardCopy is a simple implementation of forward copy. In C + // parlance, this is a do/while loop instead of a while loop, since we know + // that length > 0. In Go syntax: + // + // for { + // dst[d] = dst[d - offset] + // d++ + // length-- + // if length == 0 { + // break + // } + // } + MOVB (R_TMP3), R_TMP1 + MOVB R_TMP1, (R_DST) + INCQ R_TMP3 + INCQ R_DST + DECQ R_LEN + JNZ verySlowForwardCopy + JMP loop + +// The code above handles copy tags. +// ---------------------------------------- + +end: + // This is the end of the "for s < len(src)". + // + // if d != len(dst) { etc } + CMPQ R_DST, R_DEND + JNE errCorrupt + + // return 0 + MOVQ $0, ret+48(FP) + RET + +errCorrupt: + // return decodeErrCodeCorrupt + MOVQ $1, ret+48(FP) + RET diff --git a/vendor/github.com/klauspost/compress/s2/decode_arm64.s b/vendor/github.com/klauspost/compress/s2/decode_arm64.s new file mode 100644 index 0000000..78e463f --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/decode_arm64.s @@ -0,0 +1,574 @@ +// 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. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +#define R_TMP0 R2 +#define R_TMP1 R3 +#define R_LEN R4 +#define R_OFF R5 +#define R_SRC R6 +#define R_DST R7 +#define R_DBASE R8 +#define R_DLEN R9 +#define R_DEND R10 +#define R_SBASE R11 +#define R_SLEN R12 +#define R_SEND R13 +#define R_TMP2 R14 +#define R_TMP3 R15 + +// TEST_SRC will check if R_SRC is <= SRC_END +#define TEST_SRC() \ + CMP R_SEND, R_SRC \ + BGT errCorrupt + +// MOVD R_SRC, R_TMP1 +// SUB R_SBASE, R_TMP1, R_TMP1 +// CMP R_SLEN, R_TMP1 +// BGT errCorrupt + +// The asm code generally follows the pure Go code in decode_other.go, except +// where marked with a "!!!". + +// func decode(dst, src []byte) int +// +// All local variables fit into registers. The non-zero stack size is only to +// spill registers and push args when issuing a CALL. The register allocation: +// - R_TMP0 scratch +// - R_TMP1 scratch +// - R_LEN length or x +// - R_OFF offset +// - R_SRC &src[s] +// - R_DST &dst[d] +// + R_DBASE dst_base +// + R_DLEN dst_len +// + R_DEND dst_base + dst_len +// + R_SBASE src_base +// + R_SLEN src_len +// + R_SEND src_base + src_len +// - R_TMP2 used by doCopy +// - R_TMP3 used by doCopy +// +// The registers R_DBASE-R_SEND (marked with a "+") are set at the start of the +// function, and after a CALL returns, and are not otherwise modified. +// +// The d variable is implicitly R_DST - R_DBASE, and len(dst)-d is R_DEND - R_DST. +// The s variable is implicitly R_SRC - R_SBASE, and len(src)-s is R_SEND - R_SRC. +TEXT ·s2Decode(SB), NOSPLIT, $56-56 + // Initialize R_SRC, R_DST and R_DBASE-R_SEND. + MOVD dst_base+0(FP), R_DBASE + MOVD dst_len+8(FP), R_DLEN + MOVD R_DBASE, R_DST + MOVD R_DBASE, R_DEND + ADD R_DLEN, R_DEND, R_DEND + MOVD src_base+24(FP), R_SBASE + MOVD src_len+32(FP), R_SLEN + MOVD R_SBASE, R_SRC + MOVD R_SBASE, R_SEND + ADD R_SLEN, R_SEND, R_SEND + MOVD $0, R_OFF + +loop: + // for s < len(src) + CMP R_SEND, R_SRC + BEQ end + + // R_LEN = uint32(src[s]) + // + // switch src[s] & 0x03 + MOVBU (R_SRC), R_LEN + MOVW R_LEN, R_TMP1 + ANDW $3, R_TMP1 + MOVW $1, R1 + CMPW R1, R_TMP1 + BGE tagCopy + + // ---------------------------------------- + // The code below handles literal tags. + + // case tagLiteral: + // x := uint32(src[s] >> 2) + // switch + MOVW $60, R1 + LSRW $2, R_LEN, R_LEN + CMPW R_LEN, R1 + BLS tagLit60Plus + + // case x < 60: + // s++ + ADD $1, R_SRC, R_SRC + +doLit: + // This is the end of the inner "switch", when we have a literal tag. + // + // We assume that R_LEN == x and x fits in a uint32, where x is the variable + // used in the pure Go decode_other.go code. + + // length = int(x) + 1 + // + // Unlike the pure Go code, we don't need to check if length <= 0 because + // R_LEN can hold 64 bits, so the increment cannot overflow. + ADD $1, R_LEN, R_LEN + + // Prepare to check if copying length bytes will run past the end of dst or + // src. + // + // R_TMP0 = len(dst) - d + // R_TMP1 = len(src) - s + MOVD R_DEND, R_TMP0 + SUB R_DST, R_TMP0, R_TMP0 + MOVD R_SEND, R_TMP1 + SUB R_SRC, R_TMP1, R_TMP1 + + // !!! Try a faster technique for short (16 or fewer bytes) copies. + // + // if length > 16 || len(dst)-d < 16 || len(src)-s < 16 { + // goto callMemmove // Fall back on calling runtime·memmove. + // } + // + // The C++ snappy code calls this TryFastAppend. It also checks len(src)-s + // against 21 instead of 16, because it cannot assume that all of its input + // is contiguous in memory and so it needs to leave enough source bytes to + // read the next tag without refilling buffers, but Go's Decode assumes + // contiguousness (the src argument is a []byte). + CMP $16, R_LEN + BGT callMemmove + CMP $16, R_TMP0 + BLT callMemmove + CMP $16, R_TMP1 + BLT callMemmove + + // !!! Implement the copy from src to dst as a 16-byte load and store. + // (Decode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only length bytes, but that's + // OK. If the input is a valid Snappy encoding then subsequent iterations + // will fix up the overrun. Otherwise, Decode returns a nil []byte (and a + // non-nil error), so the overrun will be ignored. + // + // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + LDP 0(R_SRC), (R_TMP2, R_TMP3) + STP (R_TMP2, R_TMP3), 0(R_DST) + + // d += length + // s += length + ADD R_LEN, R_DST, R_DST + ADD R_LEN, R_SRC, R_SRC + B loop + +callMemmove: + // if length > len(dst)-d || length > len(src)-s { etc } + CMP R_TMP0, R_LEN + BGT errCorrupt + CMP R_TMP1, R_LEN + BGT errCorrupt + + // copy(dst[d:], src[s:s+length]) + // + // This means calling runtime·memmove(&dst[d], &src[s], length), so we push + // R_DST, R_SRC and R_LEN as arguments. Coincidentally, we also need to spill those + // three registers to the stack, to save local variables across the CALL. + MOVD R_DST, 8(RSP) + MOVD R_SRC, 16(RSP) + MOVD R_LEN, 24(RSP) + MOVD R_DST, 32(RSP) + MOVD R_SRC, 40(RSP) + MOVD R_LEN, 48(RSP) + MOVD R_OFF, 56(RSP) + CALL runtime·memmove(SB) + + // Restore local variables: unspill registers from the stack and + // re-calculate R_DBASE-R_SEND. + MOVD 32(RSP), R_DST + MOVD 40(RSP), R_SRC + MOVD 48(RSP), R_LEN + MOVD 56(RSP), R_OFF + MOVD dst_base+0(FP), R_DBASE + MOVD dst_len+8(FP), R_DLEN + MOVD R_DBASE, R_DEND + ADD R_DLEN, R_DEND, R_DEND + MOVD src_base+24(FP), R_SBASE + MOVD src_len+32(FP), R_SLEN + MOVD R_SBASE, R_SEND + ADD R_SLEN, R_SEND, R_SEND + + // d += length + // s += length + ADD R_LEN, R_DST, R_DST + ADD R_LEN, R_SRC, R_SRC + B loop + +tagLit60Plus: + // !!! This fragment does the + // + // s += x - 58; if uint(s) > uint(len(src)) { etc } + // + // checks. In the asm version, we code it once instead of once per switch case. + ADD R_LEN, R_SRC, R_SRC + SUB $58, R_SRC, R_SRC + TEST_SRC() + + // case x == 60: + MOVW $61, R1 + CMPW R1, R_LEN + BEQ tagLit61 + BGT tagLit62Plus + + // x = uint32(src[s-1]) + MOVBU -1(R_SRC), R_LEN + B doLit + +tagLit61: + // case x == 61: + // x = uint32(src[s-2]) | uint32(src[s-1])<<8 + MOVHU -2(R_SRC), R_LEN + B doLit + +tagLit62Plus: + CMPW $62, R_LEN + BHI tagLit63 + + // case x == 62: + // x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + MOVHU -3(R_SRC), R_LEN + MOVBU -1(R_SRC), R_TMP1 + ORR R_TMP1<<16, R_LEN + B doLit + +tagLit63: + // case x == 63: + // x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + MOVWU -4(R_SRC), R_LEN + B doLit + + // The code above handles literal tags. + // ---------------------------------------- + // The code below handles copy tags. + +tagCopy4: + // case tagCopy4: + // s += 5 + ADD $5, R_SRC, R_SRC + + // if uint(s) > uint(len(src)) { etc } + MOVD R_SRC, R_TMP1 + SUB R_SBASE, R_TMP1, R_TMP1 + CMP R_SLEN, R_TMP1 + BGT errCorrupt + + // length = 1 + int(src[s-5])>>2 + MOVD $1, R1 + ADD R_LEN>>2, R1, R_LEN + + // offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + MOVWU -4(R_SRC), R_OFF + B doCopy + +tagCopy2: + // case tagCopy2: + // s += 3 + ADD $3, R_SRC, R_SRC + + // if uint(s) > uint(len(src)) { etc } + TEST_SRC() + + // length = 1 + int(src[s-3])>>2 + MOVD $1, R1 + ADD R_LEN>>2, R1, R_LEN + + // offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + MOVHU -2(R_SRC), R_OFF + B doCopy + +tagCopy: + // We have a copy tag. We assume that: + // - R_TMP1 == src[s] & 0x03 + // - R_LEN == src[s] + CMP $2, R_TMP1 + BEQ tagCopy2 + BGT tagCopy4 + + // case tagCopy1: + // s += 2 + ADD $2, R_SRC, R_SRC + + // if uint(s) > uint(len(src)) { etc } + TEST_SRC() + + // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + // Calculate offset in R_TMP0 in case it is a repeat. + MOVD R_LEN, R_TMP0 + AND $0xe0, R_TMP0 + MOVBU -1(R_SRC), R_TMP1 + ORR R_TMP0<<3, R_TMP1, R_TMP0 + + // length = 4 + int(src[s-2])>>2&0x7 + MOVD $7, R1 + AND R_LEN>>2, R1, R_LEN + ADD $4, R_LEN, R_LEN + + // check if repeat code with offset 0. + CMP $0, R_TMP0 + BEQ repeatCode + + // This is a regular copy, transfer our temporary value to R_OFF (offset) + MOVD R_TMP0, R_OFF + B doCopy + + // This is a repeat code. +repeatCode: + // If length < 9, reuse last offset, with the length already calculated. + CMP $9, R_LEN + BLT doCopyRepeat + BEQ repeatLen1 + CMP $10, R_LEN + BEQ repeatLen2 + +repeatLen3: + // s +=3 + ADD $3, R_SRC, R_SRC + + // if uint(s) > uint(len(src)) { etc } + TEST_SRC() + + // length = uint32(src[s-3]) | (uint32(src[s-2])<<8) | (uint32(src[s-1])<<16) + 65540 + MOVBU -1(R_SRC), R_TMP0 + MOVHU -3(R_SRC), R_LEN + ORR R_TMP0<<16, R_LEN, R_LEN + ADD $65540, R_LEN, R_LEN + B doCopyRepeat + +repeatLen2: + // s +=2 + ADD $2, R_SRC, R_SRC + + // if uint(s) > uint(len(src)) { etc } + TEST_SRC() + + // length = uint32(src[s-2]) | (uint32(src[s-1])<<8) + 260 + MOVHU -2(R_SRC), R_LEN + ADD $260, R_LEN, R_LEN + B doCopyRepeat + +repeatLen1: + // s +=1 + ADD $1, R_SRC, R_SRC + + // if uint(s) > uint(len(src)) { etc } + TEST_SRC() + + // length = src[s-1] + 8 + MOVBU -1(R_SRC), R_LEN + ADD $8, R_LEN, R_LEN + B doCopyRepeat + +doCopy: + // This is the end of the outer "switch", when we have a copy tag. + // + // We assume that: + // - R_LEN == length && R_LEN > 0 + // - R_OFF == offset + + // if d < offset { etc } + MOVD R_DST, R_TMP1 + SUB R_DBASE, R_TMP1, R_TMP1 + CMP R_OFF, R_TMP1 + BLT errCorrupt + + // Repeat values can skip the test above, since any offset > 0 will be in dst. +doCopyRepeat: + + // if offset <= 0 { etc } + CMP $0, R_OFF + BLE errCorrupt + + // if length > len(dst)-d { etc } + MOVD R_DEND, R_TMP1 + SUB R_DST, R_TMP1, R_TMP1 + CMP R_TMP1, R_LEN + BGT errCorrupt + + // forwardCopy(dst[d:d+length], dst[d-offset:]); d += length + // + // Set: + // - R_TMP2 = len(dst)-d + // - R_TMP3 = &dst[d-offset] + MOVD R_DEND, R_TMP2 + SUB R_DST, R_TMP2, R_TMP2 + MOVD R_DST, R_TMP3 + SUB R_OFF, R_TMP3, R_TMP3 + + // !!! Try a faster technique for short (16 or fewer bytes) forward copies. + // + // First, try using two 8-byte load/stores, similar to the doLit technique + // above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is + // still OK if offset >= 8. Note that this has to be two 8-byte load/stores + // and not one 16-byte load/store, and the first store has to be before the + // second load, due to the overlap if offset is in the range [8, 16). + // + // if length > 16 || offset < 8 || len(dst)-d < 16 { + // goto slowForwardCopy + // } + // copy 16 bytes + // d += length + CMP $16, R_LEN + BGT slowForwardCopy + CMP $8, R_OFF + BLT slowForwardCopy + CMP $16, R_TMP2 + BLT slowForwardCopy + MOVD 0(R_TMP3), R_TMP0 + MOVD R_TMP0, 0(R_DST) + MOVD 8(R_TMP3), R_TMP1 + MOVD R_TMP1, 8(R_DST) + ADD R_LEN, R_DST, R_DST + B loop + +slowForwardCopy: + // !!! If the forward copy is longer than 16 bytes, or if offset < 8, we + // can still try 8-byte load stores, provided we can overrun up to 10 extra + // bytes. As above, the overrun will be fixed up by subsequent iterations + // of the outermost loop. + // + // The C++ snappy code calls this technique IncrementalCopyFastPath. Its + // commentary says: + // + // ---- + // + // The main part of this loop is a simple copy of eight bytes at a time + // until we've copied (at least) the requested amount of bytes. However, + // if d and d-offset are less than eight bytes apart (indicating a + // repeating pattern of length < 8), we first need to expand the pattern in + // order to get the correct results. For instance, if the buffer looks like + // this, with the eight-byte and patterns marked as + // intervals: + // + // abxxxxxxxxxxxx + // [------] d-offset + // [------] d + // + // a single eight-byte copy from to will repeat the pattern + // once, after which we can move two bytes without moving : + // + // ababxxxxxxxxxx + // [------] d-offset + // [------] d + // + // and repeat the exercise until the two no longer overlap. + // + // This allows us to do very well in the special case of one single byte + // repeated many times, without taking a big hit for more general cases. + // + // The worst case of extra writing past the end of the match occurs when + // offset == 1 and length == 1; the last copy will read from byte positions + // [0..7] and write to [4..11], whereas it was only supposed to write to + // position 1. Thus, ten excess bytes. + // + // ---- + // + // That "10 byte overrun" worst case is confirmed by Go's + // TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy + // and finishSlowForwardCopy algorithm. + // + // if length > len(dst)-d-10 { + // goto verySlowForwardCopy + // } + SUB $10, R_TMP2, R_TMP2 + CMP R_TMP2, R_LEN + BGT verySlowForwardCopy + + // We want to keep the offset, so we use R_TMP2 from here. + MOVD R_OFF, R_TMP2 + +makeOffsetAtLeast8: + // !!! As above, expand the pattern so that offset >= 8 and we can use + // 8-byte load/stores. + // + // for offset < 8 { + // copy 8 bytes from dst[d-offset:] to dst[d:] + // length -= offset + // d += offset + // offset += offset + // // The two previous lines together means that d-offset, and therefore + // // R_TMP3, is unchanged. + // } + CMP $8, R_TMP2 + BGE fixUpSlowForwardCopy + MOVD (R_TMP3), R_TMP1 + MOVD R_TMP1, (R_DST) + SUB R_TMP2, R_LEN, R_LEN + ADD R_TMP2, R_DST, R_DST + ADD R_TMP2, R_TMP2, R_TMP2 + B makeOffsetAtLeast8 + +fixUpSlowForwardCopy: + // !!! Add length (which might be negative now) to d (implied by R_DST being + // &dst[d]) so that d ends up at the right place when we jump back to the + // top of the loop. Before we do that, though, we save R_DST to R_TMP0 so that, if + // length is positive, copying the remaining length bytes will write to the + // right place. + MOVD R_DST, R_TMP0 + ADD R_LEN, R_DST, R_DST + +finishSlowForwardCopy: + // !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative + // length means that we overrun, but as above, that will be fixed up by + // subsequent iterations of the outermost loop. + MOVD $0, R1 + CMP R1, R_LEN + BLE loop + MOVD (R_TMP3), R_TMP1 + MOVD R_TMP1, (R_TMP0) + ADD $8, R_TMP3, R_TMP3 + ADD $8, R_TMP0, R_TMP0 + SUB $8, R_LEN, R_LEN + B finishSlowForwardCopy + +verySlowForwardCopy: + // verySlowForwardCopy is a simple implementation of forward copy. In C + // parlance, this is a do/while loop instead of a while loop, since we know + // that length > 0. In Go syntax: + // + // for { + // dst[d] = dst[d - offset] + // d++ + // length-- + // if length == 0 { + // break + // } + // } + MOVB (R_TMP3), R_TMP1 + MOVB R_TMP1, (R_DST) + ADD $1, R_TMP3, R_TMP3 + ADD $1, R_DST, R_DST + SUB $1, R_LEN, R_LEN + CBNZ R_LEN, verySlowForwardCopy + B loop + + // The code above handles copy tags. + // ---------------------------------------- + +end: + // This is the end of the "for s < len(src)". + // + // if d != len(dst) { etc } + CMP R_DEND, R_DST + BNE errCorrupt + + // return 0 + MOVD $0, ret+48(FP) + RET + +errCorrupt: + // return decodeErrCodeCorrupt + MOVD $1, R_TMP0 + MOVD R_TMP0, ret+48(FP) + RET diff --git a/vendor/github.com/klauspost/compress/s2/decode_asm.go b/vendor/github.com/klauspost/compress/s2/decode_asm.go new file mode 100644 index 0000000..cb3576e --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/decode_asm.go @@ -0,0 +1,17 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. 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 (amd64 || arm64) && !appengine && gc && !noasm +// +build amd64 arm64 +// +build !appengine +// +build gc +// +build !noasm + +package s2 + +// decode has the same semantics as in decode_other.go. +// +//go:noescape +func s2Decode(dst, src []byte) int diff --git a/vendor/github.com/klauspost/compress/s2/decode_other.go b/vendor/github.com/klauspost/compress/s2/decode_other.go new file mode 100644 index 0000000..c99d40b --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/decode_other.go @@ -0,0 +1,288 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. 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 (!amd64 && !arm64) || appengine || !gc || noasm +// +build !amd64,!arm64 appengine !gc noasm + +package s2 + +import ( + "fmt" + "strconv" + + "github.com/klauspost/compress/internal/le" +) + +// decode writes the decoding of src to dst. It assumes that the varint-encoded +// length of the decompressed bytes has already been read, and that len(dst) +// equals that length. +// +// It returns 0 on success or a decodeErrCodeXxx error code on failure. +func s2Decode(dst, src []byte) int { + const debug = false + if debug { + fmt.Println("Starting decode, dst len:", len(dst)) + } + var d, s, length int + offset := 0 + + // As long as we can read at least 5 bytes... + for s < len(src)-5 { + // Removing bounds checks is SLOWER, when if doing + // in := src[s:s+5] + // Checked on Go 1.18 + switch src[s] & 0x03 { + case tagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + x = uint32(src[s+1]) + s += 2 + case x == 61: + x = uint32(le.Load16(src, s+1)) + s += 3 + case x == 62: + // Load as 32 bit and shift down. + x = le.Load32(src, s) + x >>= 8 + s += 4 + case x == 63: + x = le.Load32(src, s+1) + s += 5 + } + length = int(x) + 1 + if length > len(dst)-d || length > len(src)-s || (strconv.IntSize == 32 && length <= 0) { + if debug { + fmt.Println("corrupt: lit size", length) + } + return decodeErrCodeCorrupt + } + if debug { + fmt.Println("literals, length:", length, "d-after:", d+length) + } + + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + + case tagCopy1: + s += 2 + toffset := int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + length = int(src[s-2]) >> 2 & 0x7 + if toffset == 0 { + if debug { + fmt.Print("(repeat) ") + } + // keep last offset + switch length { + case 5: + length = int(src[s]) + 4 + s += 1 + case 6: + length = int(le.Load16(src, s)) + 1<<8 + s += 2 + case 7: + in := src[s : s+3] + length = int((uint32(in[2])<<16)|(uint32(in[1])<<8)|uint32(in[0])) + (1 << 16) + s += 3 + default: // 0-> 4 + } + } else { + offset = toffset + } + length += 4 + case tagCopy2: + offset = int(le.Load16(src, s+1)) + length = 1 + int(src[s])>>2 + s += 3 + + case tagCopy4: + offset = int(le.Load32(src, s+1)) + length = 1 + int(src[s])>>2 + s += 5 + } + + if offset <= 0 || d < offset || length > len(dst)-d { + if debug { + fmt.Println("corrupt: match, length", length, "offset:", offset, "dst avail:", len(dst)-d, "dst pos:", d) + } + + return decodeErrCodeCorrupt + } + + if debug { + fmt.Println("copy, length:", length, "offset:", offset, "d-after:", d+length) + } + + // Copy from an earlier sub-slice of dst to a later sub-slice. + // If no overlap, use the built-in copy: + if offset > length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + + // Unlike the built-in copy function, this byte-by-byte copy always runs + // forwards, even if the slices overlap. Conceptually, this is: + // + // d += forwardCopy(dst[d:d+length], dst[d-offset:]) + // + // We align the slices into a and b and show the compiler they are the same size. + // This allows the loop to run without bounds checks. + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] + } + d += length + } + + // Remaining with extra checks... + for s < len(src) { + switch src[s] & 0x03 { + case tagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-1]) + case x == 61: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-2]) | uint32(src[s-1])<<8 + case x == 62: + s += 4 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + case x == 63: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + length = int(x) + 1 + if length > len(dst)-d || length > len(src)-s || (strconv.IntSize == 32 && length <= 0) { + if debug { + fmt.Println("corrupt: lit size", length) + } + return decodeErrCodeCorrupt + } + if debug { + fmt.Println("literals, length:", length, "d-after:", d+length) + } + + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + + case tagCopy1: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = int(src[s-2]) >> 2 & 0x7 + toffset := int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + if toffset == 0 { + if debug { + fmt.Print("(repeat) ") + } + // keep last offset + switch length { + case 5: + s += 1 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = int(uint32(src[s-1])) + 4 + case 6: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = int(uint32(src[s-2])|(uint32(src[s-1])<<8)) + (1 << 8) + case 7: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = int(uint32(src[s-3])|(uint32(src[s-2])<<8)|(uint32(src[s-1])<<16)) + (1 << 16) + default: // 0-> 4 + } + } else { + offset = toffset + } + length += 4 + case tagCopy2: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-3])>>2 + offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + + case tagCopy4: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-5])>>2 + offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + } + + if offset <= 0 || d < offset || length > len(dst)-d { + if debug { + fmt.Println("corrupt: match, length", length, "offset:", offset, "dst avail:", len(dst)-d, "dst pos:", d) + } + return decodeErrCodeCorrupt + } + + if debug { + fmt.Println("copy, length:", length, "offset:", offset, "d-after:", d+length) + } + + // Copy from an earlier sub-slice of dst to a later sub-slice. + // If no overlap, use the built-in copy: + if offset > length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + + // Unlike the built-in copy function, this byte-by-byte copy always runs + // forwards, even if the slices overlap. Conceptually, this is: + // + // d += forwardCopy(dst[d:d+length], dst[d-offset:]) + // + // We align the slices into a and b and show the compiler they are the same size. + // This allows the loop to run without bounds checks. + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] + } + d += length + } + + if d != len(dst) { + return decodeErrCodeCorrupt + } + return 0 +} diff --git a/vendor/github.com/klauspost/compress/s2/dict.go b/vendor/github.com/klauspost/compress/s2/dict.go new file mode 100644 index 0000000..f125ad0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/dict.go @@ -0,0 +1,350 @@ +// Copyright (c) 2022+ Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "bytes" + "encoding/binary" + "sync" +) + +const ( + // MinDictSize is the minimum dictionary size when repeat has been read. + MinDictSize = 16 + + // MaxDictSize is the maximum dictionary size when repeat has been read. + MaxDictSize = 65536 + + // MaxDictSrcOffset is the maximum offset where a dictionary entry can start. + MaxDictSrcOffset = 65535 +) + +// Dict contains a dictionary that can be used for encoding and decoding s2 +type Dict struct { + dict []byte + repeat int // Repeat as index of dict + + fast, better, best sync.Once + fastTable *[1 << 14]uint16 + + betterTableShort *[1 << 14]uint16 + betterTableLong *[1 << 17]uint16 + + bestTableShort *[1 << 16]uint32 + bestTableLong *[1 << 19]uint32 +} + +// NewDict will read a dictionary. +// It will return nil if the dictionary is invalid. +func NewDict(dict []byte) *Dict { + if len(dict) == 0 { + return nil + } + var d Dict + // Repeat is the first value of the dict + r, n := binary.Uvarint(dict) + if n <= 0 { + return nil + } + dict = dict[n:] + d.dict = dict + if cap(d.dict) < len(d.dict)+16 { + d.dict = append(make([]byte, 0, len(d.dict)+16), d.dict...) + } + if len(dict) < MinDictSize || len(dict) > MaxDictSize { + return nil + } + d.repeat = int(r) + if d.repeat > len(dict) { + return nil + } + return &d +} + +// Bytes will return a serialized version of the dictionary. +// The output can be sent to NewDict. +func (d *Dict) Bytes() []byte { + dst := make([]byte, binary.MaxVarintLen16+len(d.dict)) + return append(dst[:binary.PutUvarint(dst, uint64(d.repeat))], d.dict...) +} + +// MakeDict will create a dictionary. +// 'data' must be at least MinDictSize. +// If data is longer than MaxDictSize only the last MaxDictSize bytes will be used. +// If searchStart is set the start repeat value will be set to the last +// match of this content. +// If no matches are found, it will attempt to find shorter matches. +// This content should match the typical start of a block. +// If at least 4 bytes cannot be matched, repeat is set to start of block. +func MakeDict(data []byte, searchStart []byte) *Dict { + if len(data) == 0 { + return nil + } + if len(data) > MaxDictSize { + data = data[len(data)-MaxDictSize:] + } + var d Dict + dict := data + d.dict = dict + if cap(d.dict) < len(d.dict)+16 { + d.dict = append(make([]byte, 0, len(d.dict)+16), d.dict...) + } + if len(dict) < MinDictSize { + return nil + } + + // Find the longest match possible, last entry if multiple. + for s := len(searchStart); s > 4; s-- { + if idx := bytes.LastIndex(data, searchStart[:s]); idx >= 0 && idx <= len(data)-8 { + d.repeat = idx + break + } + } + + return &d +} + +// MakeDictManual will create a dictionary. +// 'data' must be at least MinDictSize and less than or equal to MaxDictSize. +// A manual first repeat index into data must be provided. +// It must be less than len(data)-8. +func MakeDictManual(data []byte, firstIdx uint16) *Dict { + if len(data) < MinDictSize || int(firstIdx) >= len(data)-8 || len(data) > MaxDictSize { + return nil + } + var d Dict + dict := data + d.dict = dict + if cap(d.dict) < len(d.dict)+16 { + d.dict = append(make([]byte, 0, len(d.dict)+16), d.dict...) + } + + d.repeat = int(firstIdx) + return &d +} + +// Encode returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func (d *Dict) Encode(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + dstP := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:dstP] + } + if len(src) < minNonLiteralBlockSize { + dstP += emitLiteral(dst[dstP:], src) + return dst[:dstP] + } + n := encodeBlockDictGo(dst[dstP:], src, d) + if n > 0 { + dstP += n + return dst[:dstP] + } + // Not compressible + dstP += emitLiteral(dst[dstP:], src) + return dst[:dstP] +} + +// EncodeBetter returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// EncodeBetter compresses better than Encode but typically with a +// 10-40% speed decrease on both compression and decompression. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func (d *Dict) EncodeBetter(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if len(dst) < n { + dst = make([]byte, n) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + dstP := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:dstP] + } + if len(src) < minNonLiteralBlockSize { + dstP += emitLiteral(dst[dstP:], src) + return dst[:dstP] + } + n := encodeBlockBetterDict(dst[dstP:], src, d) + if n > 0 { + dstP += n + return dst[:dstP] + } + // Not compressible + dstP += emitLiteral(dst[dstP:], src) + return dst[:dstP] +} + +// EncodeBest returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// EncodeBest compresses as good as reasonably possible but with a +// big speed decrease. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func (d *Dict) EncodeBest(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if len(dst) < n { + dst = make([]byte, n) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + dstP := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:dstP] + } + if len(src) < minNonLiteralBlockSize { + dstP += emitLiteral(dst[dstP:], src) + return dst[:dstP] + } + n := encodeBlockBest(dst[dstP:], src, d) + if n > 0 { + dstP += n + return dst[:dstP] + } + // Not compressible + dstP += emitLiteral(dst[dstP:], src) + return dst[:dstP] +} + +// Decode returns the decoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire decoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +func (d *Dict) Decode(dst, src []byte) ([]byte, error) { + dLen, s, err := decodedLen(src) + if err != nil { + return nil, err + } + if dLen <= cap(dst) { + dst = dst[:dLen] + } else { + dst = make([]byte, dLen) + } + if s2DecodeDict(dst, src[s:], d) != 0 { + return nil, ErrCorrupt + } + return dst, nil +} + +func (d *Dict) initFast() { + d.fast.Do(func() { + const ( + tableBits = 14 + maxTableSize = 1 << tableBits + ) + + var table [maxTableSize]uint16 + // We stop so any entry of length 8 can always be read. + for i := 0; i < len(d.dict)-8-2; i += 3 { + x0 := load64(d.dict, i) + h0 := hash6(x0, tableBits) + h1 := hash6(x0>>8, tableBits) + h2 := hash6(x0>>16, tableBits) + table[h0] = uint16(i) + table[h1] = uint16(i + 1) + table[h2] = uint16(i + 2) + } + d.fastTable = &table + }) +} + +func (d *Dict) initBetter() { + d.better.Do(func() { + const ( + // Long hash matches. + lTableBits = 17 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 14 + maxSTableSize = 1 << sTableBits + ) + + var lTable [maxLTableSize]uint16 + var sTable [maxSTableSize]uint16 + + // We stop so any entry of length 8 can always be read. + for i := 0; i < len(d.dict)-8; i++ { + cv := load64(d.dict, i) + lTable[hash7(cv, lTableBits)] = uint16(i) + sTable[hash4(cv, sTableBits)] = uint16(i) + } + d.betterTableShort = &sTable + d.betterTableLong = &lTable + }) +} + +func (d *Dict) initBest() { + d.best.Do(func() { + const ( + // Long hash matches. + lTableBits = 19 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 16 + maxSTableSize = 1 << sTableBits + ) + + var lTable [maxLTableSize]uint32 + var sTable [maxSTableSize]uint32 + + // We stop so any entry of length 8 can always be read. + for i := 0; i < len(d.dict)-8; i++ { + cv := load64(d.dict, i) + hashL := hash8(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL := lTable[hashL] + candidateS := sTable[hashS] + lTable[hashL] = uint32(i) | candidateL<<16 + sTable[hashS] = uint32(i) | candidateS<<16 + } + d.bestTableShort = &sTable + d.bestTableLong = &lTable + }) +} diff --git a/vendor/github.com/klauspost/compress/s2/encode.go b/vendor/github.com/klauspost/compress/s2/encode.go new file mode 100644 index 0000000..330e755 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encode.go @@ -0,0 +1,418 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "encoding/binary" + "math" + "math/bits" + "sync" + + "github.com/klauspost/compress/internal/race" +) + +// Encode returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func Encode(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + n := encodeBlock(dst[d:], src) + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +var estblockPool [2]sync.Pool + +// EstimateBlockSize will perform a very fast compression +// without outputting the result and return the compressed output size. +// The function returns -1 if no improvement could be achieved. +// Using actual compression will most often produce better compression than the estimate. +func EstimateBlockSize(src []byte) (d int) { + if len(src) <= inputMargin || int64(len(src)) > 0xffffffff { + return -1 + } + if len(src) <= 1024 { + const sz, pool = 2048, 0 + tmp, ok := estblockPool[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer estblockPool[pool].Put(tmp) + + d = calcBlockSizeSmall(src, tmp) + } else { + const sz, pool = 32768, 1 + tmp, ok := estblockPool[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer estblockPool[pool].Put(tmp) + + d = calcBlockSize(src, tmp) + } + + if d == 0 { + return -1 + } + // Size of the varint encoded block size. + d += (bits.Len64(uint64(len(src))) + 7) / 7 + + if d >= len(src) { + return -1 + } + return d +} + +// EncodeBetter returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// EncodeBetter compresses better than Encode but typically with a +// 10-40% speed decrease on both compression and decompression. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func EncodeBetter(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + n := encodeBlockBetter(dst[d:], src) + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +// EncodeBest returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// EncodeBest compresses as good as reasonably possible but with a +// big speed decrease. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func EncodeBest(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + n := encodeBlockBest(dst[d:], src, nil) + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +// EncodeSnappy returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The output is Snappy compatible and will likely decompress faster. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func EncodeSnappy(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + + n := encodeBlockSnappy(dst[d:], src) + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +// EncodeSnappyBetter returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The output is Snappy compatible and will likely decompress faster. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func EncodeSnappyBetter(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + + n := encodeBlockBetterSnappy(dst[d:], src) + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +// EncodeSnappyBest returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The output is Snappy compatible and will likely decompress faster. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// The blocks will require the same amount of memory to decode as encoding, +// and does not make for concurrent decoding. +// Also note that blocks do not contain CRC information, so corruption may be undetected. +// +// If you need to encode larger amounts of data, consider using +// the streaming interface which gives all of these features. +func EncodeSnappyBest(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if cap(dst) < n { + dst = make([]byte, n) + } else { + dst = dst[:n] + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + + n := encodeBlockBestSnappy(dst[d:], src) + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +// ConcatBlocks will concatenate the supplied blocks and append them to the supplied destination. +// If the destination is nil or too small, a new will be allocated. +// The blocks are not validated, so garbage in = garbage out. +// dst may not overlap block data. +// Any data in dst is preserved as is, so it will not be considered a block. +func ConcatBlocks(dst []byte, blocks ...[]byte) ([]byte, error) { + totalSize := uint64(0) + compSize := 0 + for _, b := range blocks { + l, hdr, err := decodedLen(b) + if err != nil { + return nil, err + } + totalSize += uint64(l) + compSize += len(b) - hdr + } + if totalSize == 0 { + dst = append(dst, 0) + return dst, nil + } + if totalSize > math.MaxUint32 { + return nil, ErrTooLarge + } + var tmp [binary.MaxVarintLen32]byte + hdrSize := binary.PutUvarint(tmp[:], totalSize) + wantSize := hdrSize + compSize + + if cap(dst)-len(dst) < wantSize { + dst = append(make([]byte, 0, wantSize+len(dst)), dst...) + } + dst = append(dst, tmp[:hdrSize]...) + for _, b := range blocks { + _, hdr, err := decodedLen(b) + if err != nil { + return nil, err + } + dst = append(dst, b[hdr:]...) + } + return dst, nil +} + +// inputMargin is the minimum number of extra input bytes to keep, inside +// encodeBlock's inner loop. On some architectures, this margin lets us +// implement a fast path for emitLiteral, where the copy of short (<= 16 byte) +// literals can be implemented as a single load to and store from a 16-byte +// register. That literal's actual length can be as short as 1 byte, so this +// can copy up to 15 bytes too much, but that's OK as subsequent iterations of +// the encoding loop will fix up the copy overrun, and this inputMargin ensures +// that we don't overrun the dst and src buffers. +const inputMargin = 8 + +// minNonLiteralBlockSize is the minimum size of the input to encodeBlock that +// will be accepted by the encoder. +const minNonLiteralBlockSize = 32 + +const intReduction = 2 - (1 << (^uint(0) >> 63)) // 1 (32 bits) or 0 (64 bits) + +// MaxBlockSize is the maximum value where MaxEncodedLen will return a valid block size. +// Blocks this big are highly discouraged, though. +// Half the size on 32 bit systems. +const MaxBlockSize = (1<<(32-intReduction) - 1) - binary.MaxVarintLen32 - 5 + +// MaxEncodedLen returns the maximum length of a snappy block, given its +// uncompressed length. +// +// It will return a negative value if srcLen is too large to encode. +// 32 bit platforms will have lower thresholds for rejecting big content. +func MaxEncodedLen(srcLen int) int { + n := uint64(srcLen) + if intReduction == 1 { + // 32 bits + if n > math.MaxInt32 { + // Also includes negative. + return -1 + } + } else if n > 0xffffffff { + // 64 bits + // Also includes negative. + return -1 + } + // Size of the varint encoded block size. + n = n + uint64((bits.Len64(n)+7)/7) + + // Add maximum size of encoding block as literals. + n += uint64(literalExtraSize(int64(srcLen))) + if intReduction == 1 { + // 32 bits + if n > math.MaxInt32 { + return -1 + } + } else if n > 0xffffffff { + // 64 bits + // Also includes negative. + return -1 + } + return int(n) +} diff --git a/vendor/github.com/klauspost/compress/s2/encode_all.go b/vendor/github.com/klauspost/compress/s2/encode_all.go new file mode 100644 index 0000000..9d12c44 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encode_all.go @@ -0,0 +1,1477 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "bytes" + "encoding/binary" + "fmt" + "math/bits" + + "github.com/klauspost/compress/internal/le" +) + +func load32(b []byte, i int) uint32 { + return le.Load32(b, i) +} + +func load64(b []byte, i int) uint64 { + return le.Load64(b, i) +} + +// hash6 returns the hash of the lowest 6 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash6(u uint64, h uint8) uint32 { + const prime6bytes = 227718039650203 + return uint32(((u << (64 - 48)) * prime6bytes) >> ((64 - h) & 63)) +} + +func encodeGo(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if len(dst) < n { + dst = make([]byte, n) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + if len(src) == 0 { + return dst[:d] + } + if len(src) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], src) + return dst[:d] + } + var n int + if len(src) < 64<<10 { + n = encodeBlockGo64K(dst[d:], src) + } else { + n = encodeBlockGo(dst[d:], src) + } + if n > 0 { + d += n + return dst[:d] + } + // Not compressible + d += emitLiteral(dst[d:], src) + return dst[:d] +} + +// encodeBlockGo encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockGo(dst, src []byte) (d int) { + // Initialize the hash table. + const ( + tableBits = 14 + maxTableSize = 1 << tableBits + + debug = false + ) + var table [maxTableSize]uint32 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>6 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint32(s) + table[hash1] = uint32(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + if nextEmit > 0 { + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + } else { + // First match, cannot be repeat. + d += emitCopy(dst[d:], repeat, s-base) + } + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint32(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint32(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards. + // The top bytes will be rechecked to get the full match. + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopy(dst[d:], repeat, s-base) + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s) + if debug && s == candidate { + panic("s == candidate") + } + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockGo64K is a specialized version for compressing blocks <= 64KB +func encodeBlockGo64K(dst, src []byte) (d int) { + // Initialize the hash table. + const ( + tableBits = 14 + maxTableSize = 1 << tableBits + + debug = false + ) + + var table [maxTableSize]uint16 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>5 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint16(s) + table[hash1] = uint16(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + if nextEmit > 0 { + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + } else { + // First match, cannot be repeat. + d += emitCopy(dst[d:], repeat, s-base) + } + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint16(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint16(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards. + // The top bytes will be rechecked to get the full match. + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopy(dst[d:], repeat, s-base) + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint16(s - 2) + table[currHash] = uint16(s) + if debug && s == candidate { + panic("s == candidate") + } + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +func encodeBlockSnappyGo(dst, src []byte) (d int) { + // Initialize the hash table. + const ( + tableBits = 14 + maxTableSize = 1 << tableBits + ) + var table [maxTableSize]uint32 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>6 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint32(s) + table[hash1] = uint32(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeat(dst[d:], repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint32(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint32(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeat(dst[d:], repeat, s-base) + if false { + // Validate match. + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s) + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockSnappyGo64K is a special version of encodeBlockSnappyGo for sizes <64KB +func encodeBlockSnappyGo64K(dst, src []byte) (d int) { + // Initialize the hash table. + const ( + tableBits = 14 + maxTableSize = 1 << tableBits + ) + + var table [maxTableSize]uint16 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>5 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint16(s) + table[hash1] = uint16(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeat(dst[d:], repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint16(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint16(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeat(dst[d:], repeat, s-base) + if false { + // Validate match. + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint16(s - 2) + table[currHash] = uint16(s) + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockGo encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockDictGo(dst, src []byte, dict *Dict) (d int) { + // Initialize the hash table. + const ( + tableBits = 14 + maxTableSize = 1 << tableBits + maxAhead = 8 // maximum bytes ahead without checking sLimit + + debug = false + ) + dict.initFast() + + var table [maxTableSize]uint32 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := min(len(src)-inputMargin, MaxDictSrcOffset-maxAhead) + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form can start with a dict entry (copy or repeat). + s := 0 + + // Convert dict repeat to offset + repeat := len(dict.dict) - dict.repeat + cv := load64(src, 0) + + // While in dict +searchDict: + for { + // Next src position to check + nextS := s + (s-nextEmit)>>6 + 4 + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + if nextS > sLimit { + if debug { + fmt.Println("slimit reached", s, nextS) + } + break searchDict + } + candidateDict := int(dict.fastTable[hash0]) + candidateDict2 := int(dict.fastTable[hash1]) + candidate2 := int(table[hash1]) + candidate := int(table[hash0]) + table[hash0] = uint32(s) + table[hash1] = uint32(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + + if repeat > s { + candidate := len(dict.dict) - repeat + s + if repeat-s >= 4 && uint32(cv) == load32(dict.dict, candidate) { + // Extend back + base := s + for i := candidate; base > nextEmit && i > 0 && dict.dict[i-1] == src[base-1]; { + i-- + base-- + } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + if debug && nextEmit != base { + fmt.Println("emitted ", base-nextEmit, "literals") + } + s += 4 + candidate += 4 + for candidate < len(dict.dict)-8 && s <= len(src)-8 { + if diff := load64(src, s) ^ load64(dict.dict, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + d += emitRepeat(dst[d:], repeat, s-base) + if debug { + fmt.Println("emitted dict repeat length", s-base, "offset:", repeat, "s:", s) + } + nextEmit = s + if s >= sLimit { + break searchDict + } + cv = load64(src, s) + continue + } + } else if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + if debug && nextEmit != base { + fmt.Println("emitted ", base-nextEmit, "literals") + } + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + if nextEmit > 0 { + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + } else { + // First match, cannot be repeat. + d += emitCopy(dst[d:], repeat, s-base) + } + + nextEmit = s + if s >= sLimit { + break searchDict + } + if debug { + fmt.Println("emitted reg repeat", s-base, "s:", s) + } + cv = load64(src, s) + continue searchDict + } + if s == 0 { + cv = load64(src, nextS) + s = nextS + continue searchDict + } + // Start with table. These matches will always be closer. + if uint32(cv) == load32(src, candidate) { + goto emitMatch + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint32(s + 2) + candidate = candidate2 + s++ + goto emitMatch + } + + // Check dict. Dicts have longer offsets, so we want longer matches. + if cv == load64(dict.dict, candidateDict) { + table[hash2] = uint32(s + 2) + goto emitDict + } + + candidateDict = int(dict.fastTable[hash2]) + // Check if upper 7 bytes match + if candidateDict2 >= 1 { + if cv^load64(dict.dict, candidateDict2-1) < (1 << 8) { + table[hash2] = uint32(s + 2) + candidateDict = candidateDict2 + s++ + goto emitDict + } + } + + table[hash2] = uint32(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + goto emitMatch + } + if candidateDict >= 2 { + // Check if upper 6 bytes match + if cv^load64(dict.dict, candidateDict-2) < (1 << 16) { + s += 2 + goto emitDict + } + } + + cv = load64(src, nextS) + s = nextS + continue searchDict + + emitDict: + { + if debug { + if load32(dict.dict, candidateDict) != load32(src, s) { + panic("dict emit mismatch") + } + } + // Extend backwards. + // The top bytes will be rechecked to get the full match. + for candidateDict > 0 && s > nextEmit && dict.dict[candidateDict-1] == src[s-1] { + candidateDict-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + if debug && nextEmit != s { + fmt.Println("emitted ", s-nextEmit, "literals") + } + { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = s + (len(dict.dict)) - candidateDict + + // Extend the 4-byte match as long as possible. + s += 4 + candidateDict += 4 + for s <= len(src)-8 && len(dict.dict)-candidateDict >= 8 { + if diff := load64(src, s) ^ load64(dict.dict, candidateDict); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateDict += 8 + } + + // Matches longer than 64 are split. + if s <= sLimit || s-base < 8 { + d += emitCopy(dst[d:], repeat, s-base) + } else { + // Split to ensure we don't start a copy within next block + d += emitCopy(dst[d:], repeat, 4) + d += emitRepeat(dst[d:], repeat, s-base-4) + } + if false { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := dict.dict[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + if debug { + fmt.Println("emitted dict copy, length", s-base, "offset:", repeat, "s:", s) + } + nextEmit = s + if s >= sLimit { + break searchDict + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index and continue loop to try new candidate. + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>8, tableBits) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s - 1) + cv = load64(src, s) + } + continue + } + emitMatch: + + // Extend backwards. + // The top bytes will be rechecked to get the full match. + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + if debug && nextEmit != s { + fmt.Println("emitted ", s-nextEmit, "literals") + } + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopy(dst[d:], repeat, s-base) + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + if debug { + fmt.Println("emitted src copy, length", s-base, "offset:", repeat, "s:", s) + } + nextEmit = s + if s >= sLimit { + break searchDict + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s) + if debug && s == candidate { + panic("s == candidate") + } + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + + // Search without dict: + if repeat > s { + repeat = 0 + } + + // No more dict + sLimit = len(src) - inputMargin + if s >= sLimit { + goto emitRemainder + } + if debug { + fmt.Println("non-dict matching at", s, "repeat:", repeat) + } + cv = load64(src, s) + if debug { + fmt.Println("now", s, "->", sLimit, "out:", d, "left:", len(src)-s, "nextemit:", nextEmit, "dstLimit:", dstLimit, "s:", s) + } + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>6 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint32(s) + table[hash1] = uint32(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if repeat > 0 && uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + if debug && nextEmit != base { + fmt.Println("emitted ", base-nextEmit, "literals") + } + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + if nextEmit > 0 { + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + } else { + // First match, cannot be repeat. + d += emitCopy(dst[d:], repeat, s-base) + } + if debug { + fmt.Println("emitted src repeat length", s-base, "offset:", repeat, "s:", s) + } + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint32(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint32(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards. + // The top bytes will be rechecked to get the full match. + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + if debug && nextEmit != s { + fmt.Println("emitted ", s-nextEmit, "literals") + } + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopy(dst[d:], repeat, s-base) + if debug { + // Validate match. + if s <= candidate { + panic("s <= candidate") + } + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + if debug { + fmt.Println("emitted src copy, length", s-base, "offset:", repeat, "s:", s) + } + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s) + if debug && s == candidate { + panic("s == candidate") + } + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + if debug && nextEmit != s { + fmt.Println("emitted ", len(src)-nextEmit, "literals") + } + } + return d +} diff --git a/vendor/github.com/klauspost/compress/s2/encode_amd64.go b/vendor/github.com/klauspost/compress/s2/encode_amd64.go new file mode 100644 index 0000000..7aadd25 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encode_amd64.go @@ -0,0 +1,317 @@ +//go:build !appengine && !noasm && gc +// +build !appengine,!noasm,gc + +package s2 + +import ( + "sync" + + "github.com/klauspost/compress/internal/race" +) + +const hasAmd64Asm = true + +var encPools [4]sync.Pool + +// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlock(dst, src []byte) (d int) { + race.ReadSlice(src) + race.WriteSlice(dst) + + const ( + // Use 12 bit table when less than... + limit12B = 16 << 10 + // Use 10 bit table when less than... + limit10B = 4 << 10 + // Use 8 bit table when less than... + limit8B = 512 + ) + + if len(src) >= 4<<20 { + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm(dst, src, tmp) + } + if len(src) >= limit12B { + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm4MB(dst, src, tmp) + } + if len(src) >= limit10B { + const sz, pool = 16384, 1 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm12B(dst, src, tmp) + } + if len(src) >= limit8B { + const sz, pool = 4096, 2 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm10B(dst, src, tmp) + } + if len(src) < minNonLiteralBlockSize { + return 0 + } + const sz, pool = 1024, 3 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm8B(dst, src, tmp) +} + +var encBetterPools [5]sync.Pool + +// encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBetter(dst, src []byte) (d int) { + race.ReadSlice(src) + race.WriteSlice(dst) + + const ( + // Use 12 bit table when less than... + limit12B = 16 << 10 + // Use 10 bit table when less than... + limit10B = 4 << 10 + // Use 8 bit table when less than... + limit8B = 512 + ) + + if len(src) > 4<<20 { + const sz, pool = 589824, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeBetterBlockAsm(dst, src, tmp) + } + if len(src) >= limit12B { + const sz, pool = 589824, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeBetterBlockAsm4MB(dst, src, tmp) + } + if len(src) >= limit10B { + const sz, pool = 81920, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeBetterBlockAsm12B(dst, src, tmp) + } + if len(src) >= limit8B { + const sz, pool = 20480, 1 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeBetterBlockAsm10B(dst, src, tmp) + } + if len(src) < minNonLiteralBlockSize { + return 0 + } + + const sz, pool = 5120, 2 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeBetterBlockAsm8B(dst, src, tmp) +} + +// encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockSnappy(dst, src []byte) (d int) { + race.ReadSlice(src) + race.WriteSlice(dst) + + const ( + // Use 12 bit table when less than... + limit12B = 16 << 10 + // Use 10 bit table when less than... + limit10B = 4 << 10 + // Use 8 bit table when less than... + limit8B = 512 + ) + if len(src) > 65536 { + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm(dst, src, tmp) + } + if len(src) >= limit12B { + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm64K(dst, src, tmp) + } + if len(src) >= limit10B { + const sz, pool = 16384, 1 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm12B(dst, src, tmp) + } + if len(src) >= limit8B { + const sz, pool = 4096, 2 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm10B(dst, src, tmp) + } + if len(src) < minNonLiteralBlockSize { + return 0 + } + const sz, pool = 1024, 3 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm8B(dst, src, tmp) +} + +// encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBetterSnappy(dst, src []byte) (d int) { + race.ReadSlice(src) + race.WriteSlice(dst) + + const ( + // Use 12 bit table when less than... + limit12B = 16 << 10 + // Use 10 bit table when less than... + limit10B = 4 << 10 + // Use 8 bit table when less than... + limit8B = 512 + ) + if len(src) > 65536 { + const sz, pool = 589824, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeSnappyBetterBlockAsm(dst, src, tmp) + } + + if len(src) >= limit12B { + const sz, pool = 294912, 4 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeSnappyBetterBlockAsm64K(dst, src, tmp) + } + if len(src) >= limit10B { + const sz, pool = 81920, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeSnappyBetterBlockAsm12B(dst, src, tmp) + } + if len(src) >= limit8B { + const sz, pool = 20480, 1 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeSnappyBetterBlockAsm10B(dst, src, tmp) + } + if len(src) < minNonLiteralBlockSize { + return 0 + } + + const sz, pool = 5120, 2 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeSnappyBetterBlockAsm8B(dst, src, tmp) +} diff --git a/vendor/github.com/klauspost/compress/s2/encode_best.go b/vendor/github.com/klauspost/compress/s2/encode_best.go new file mode 100644 index 0000000..c857c5c --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encode_best.go @@ -0,0 +1,793 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "fmt" + "math" + "math/bits" +) + +// encodeBlockBest encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBest(dst, src []byte, dict *Dict) (d int) { + // Initialize the hash tables. + const ( + // Long hash matches. + lTableBits = 19 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 16 + maxSTableSize = 1 << sTableBits + + inputMargin = 8 + 2 + + debug = false + ) + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + if len(src) < minNonLiteralBlockSize { + return 0 + } + sLimitDict := min(len(src)-inputMargin, MaxDictSrcOffset-inputMargin) + + var lTable [maxLTableSize]uint64 + var sTable [maxSTableSize]uint64 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + repeat := 1 + if dict != nil { + dict.initBest() + s = 0 + repeat = len(dict.dict) - dict.repeat + } + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + const lowbitMask = 0xffffffff + getCur := func(x uint64) int { + return int(x & lowbitMask) + } + getPrev := func(x uint64) int { + return int(x >> 32) + } + const maxSkip = 64 + + for { + type match struct { + offset int + s int + length int + score int + rep, dict bool + } + var best match + for { + // Next src position to check + nextS := (s-nextEmit)>>8 + 1 + if nextS > maxSkip { + nextS = s + maxSkip + } else { + nextS += s + } + if nextS > sLimit { + goto emitRemainder + } + if dict != nil && s >= MaxDictSrcOffset { + dict = nil + if repeat > s { + repeat = math.MinInt32 + } + } + hashL := hash8(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL := lTable[hashL] + candidateS := sTable[hashS] + + score := func(m match) int { + // Matches that are longer forward are penalized since we must emit it as a literal. + score := m.length - m.s + if nextEmit == m.s { + // If we do not have to emit literals, we save 1 byte + score++ + } + offset := m.s - m.offset + if m.rep { + return score - emitRepeatSize(offset, m.length) + } + return score - emitCopySize(offset, m.length) + } + + matchAt := func(offset, s int, first uint32, rep bool) match { + if best.length != 0 && best.s-best.offset == s-offset { + // Don't retest if we have the same offset. + return match{offset: offset, s: s} + } + if load32(src, offset) != first { + return match{offset: offset, s: s} + } + m := match{offset: offset, s: s, length: 4 + offset, rep: rep} + s += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[m.length] { + m.length++ + s++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, m.length); diff != 0 { + m.length += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + m.length += 8 + } + m.length -= offset + m.score = score(m) + if m.score <= -m.s { + // Eliminate if no savings, we might find a better one. + m.length = 0 + } + return m + } + matchDict := func(candidate, s int, first uint32, rep bool) match { + if s >= MaxDictSrcOffset { + return match{offset: candidate, s: s} + } + // Calculate offset as if in continuous array with s + offset := -len(dict.dict) + candidate + if best.length != 0 && best.s-best.offset == s-offset && !rep { + // Don't retest if we have the same offset. + return match{offset: offset, s: s} + } + + if load32(dict.dict, candidate) != first { + return match{offset: offset, s: s} + } + m := match{offset: offset, s: s, length: 4 + candidate, rep: rep, dict: true} + s += 4 + if !rep { + for s < sLimitDict && m.length < len(dict.dict) { + if len(src)-s < 8 || len(dict.dict)-m.length < 8 { + if src[s] == dict.dict[m.length] { + m.length++ + s++ + continue + } + break + } + if diff := load64(src, s) ^ load64(dict.dict, m.length); diff != 0 { + m.length += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + m.length += 8 + } + } else { + for s < len(src) && m.length < len(dict.dict) { + if len(src)-s < 8 || len(dict.dict)-m.length < 8 { + if src[s] == dict.dict[m.length] { + m.length++ + s++ + continue + } + break + } + if diff := load64(src, s) ^ load64(dict.dict, m.length); diff != 0 { + m.length += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + m.length += 8 + } + } + m.length -= candidate + m.score = score(m) + if m.score <= -m.s { + // Eliminate if no savings, we might find a better one. + m.length = 0 + } + return m + } + + bestOf := func(a, b match) match { + if b.length == 0 { + return a + } + if a.length == 0 { + return b + } + as := a.score + b.s + bs := b.score + a.s + if as >= bs { + return a + } + return b + } + + if s > 0 { + best = bestOf(matchAt(getCur(candidateL), s, uint32(cv), false), matchAt(getPrev(candidateL), s, uint32(cv), false)) + best = bestOf(best, matchAt(getCur(candidateS), s, uint32(cv), false)) + best = bestOf(best, matchAt(getPrev(candidateS), s, uint32(cv), false)) + } + if dict != nil { + candidateL := dict.bestTableLong[hashL] + candidateS := dict.bestTableShort[hashS] + best = bestOf(best, matchDict(int(candidateL&0xffff), s, uint32(cv), false)) + best = bestOf(best, matchDict(int(candidateL>>16), s, uint32(cv), false)) + best = bestOf(best, matchDict(int(candidateS&0xffff), s, uint32(cv), false)) + best = bestOf(best, matchDict(int(candidateS>>16), s, uint32(cv), false)) + } + { + if (dict == nil || repeat <= s) && repeat > 0 { + best = bestOf(best, matchAt(s-repeat+1, s+1, uint32(cv>>8), true)) + } else if s-repeat < -4 && dict != nil { + candidate := len(dict.dict) - (repeat - s) + best = bestOf(best, matchDict(candidate, s, uint32(cv), true)) + candidate++ + best = bestOf(best, matchDict(candidate, s+1, uint32(cv>>8), true)) + } + + if best.length > 0 { + hashS := hash4(cv>>8, sTableBits) + // s+1 + nextShort := sTable[hashS] + s := s + 1 + cv := load64(src, s) + hashL := hash8(cv, lTableBits) + nextLong := lTable[hashL] + best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv), false)) + best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv), false)) + best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv), false)) + best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv), false)) + + // Dict at + 1 + if dict != nil { + candidateL := dict.bestTableLong[hashL] + candidateS := dict.bestTableShort[hashS] + + best = bestOf(best, matchDict(int(candidateL&0xffff), s, uint32(cv), false)) + best = bestOf(best, matchDict(int(candidateS&0xffff), s, uint32(cv), false)) + } + + // s+2 + if true { + hashS := hash4(cv>>8, sTableBits) + + nextShort = sTable[hashS] + s++ + cv = load64(src, s) + hashL := hash8(cv, lTableBits) + nextLong = lTable[hashL] + + if (dict == nil || repeat <= s) && repeat > 0 { + // Repeat at + 2 + best = bestOf(best, matchAt(s-repeat, s, uint32(cv), true)) + } else if repeat-s > 4 && dict != nil { + candidate := len(dict.dict) - (repeat - s) + best = bestOf(best, matchDict(candidate, s, uint32(cv), true)) + } + best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv), false)) + best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv), false)) + best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv), false)) + best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv), false)) + + // Dict at +2 + // Very small gain + if dict != nil { + candidateL := dict.bestTableLong[hashL] + candidateS := dict.bestTableShort[hashS] + + best = bestOf(best, matchDict(int(candidateL&0xffff), s, uint32(cv), false)) + best = bestOf(best, matchDict(int(candidateS&0xffff), s, uint32(cv), false)) + } + } + // Search for a match at best match end, see if that is better. + // Allow some bytes at the beginning to mismatch. + // Sweet spot is around 1-2 bytes, but depends on input. + // The skipped bytes are tested in Extend backwards, + // and still picked up as part of the match if they do. + const skipBeginning = 2 + const skipEnd = 1 + if sAt := best.s + best.length - skipEnd; sAt < sLimit { + + sBack := best.s + skipBeginning - skipEnd + backL := best.length - skipBeginning + // Load initial values + cv = load64(src, sBack) + + // Grab candidates... + next := lTable[hash8(load64(src, sAt), lTableBits)] + + if checkAt := getCur(next) - backL; checkAt > 0 { + best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false)) + } + if checkAt := getPrev(next) - backL; checkAt > 0 { + best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false)) + } + // Disabled: Extremely small gain + if false { + next = sTable[hash4(load64(src, sAt), sTableBits)] + if checkAt := getCur(next) - backL; checkAt > 0 { + best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false)) + } + if checkAt := getPrev(next) - backL; checkAt > 0 { + best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false)) + } + } + } + } + } + + // Update table + lTable[hashL] = uint64(s) | candidateL<<32 + sTable[hashS] = uint64(s) | candidateS<<32 + + if best.length > 0 { + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards, not needed for repeats... + s = best.s + if !best.rep && !best.dict { + for best.offset > 0 && s > nextEmit && src[best.offset-1] == src[s-1] { + best.offset-- + best.length++ + s-- + } + } + if false && best.offset >= s { + panic(fmt.Errorf("t %d >= s %d", best.offset, s)) + } + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := s - best.offset + s += best.length + + if offset > 65535 && s-base <= 5 && !best.rep { + // Bail if the match is equal or worse to the encoding. + s = best.s + 1 + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + if debug && nextEmit != base { + fmt.Println("EMIT", base-nextEmit, "literals. base-after:", base) + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + if best.rep { + if nextEmit > 0 || best.dict { + if debug { + fmt.Println("REPEAT, length", best.length, "offset:", offset, "s-after:", s, "dict:", best.dict, "best:", best) + } + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], offset, best.length) + } else { + // First match without dict cannot be a repeat. + if debug { + fmt.Println("COPY, length", best.length, "offset:", offset, "s-after:", s, "dict:", best.dict, "best:", best) + } + d += emitCopy(dst[d:], offset, best.length) + } + } else { + if debug { + fmt.Println("COPY, length", best.length, "offset:", offset, "s-after:", s, "dict:", best.dict, "best:", best) + } + d += emitCopy(dst[d:], offset, best.length) + } + repeat = offset + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Fill tables... + for i := best.s + 1; i < s; i++ { + cv0 := load64(src, i) + long0 := hash8(cv0, lTableBits) + short0 := hash4(cv0, sTableBits) + lTable[long0] = uint64(i) | lTable[long0]<<32 + sTable[short0] = uint64(i) | sTable[short0]<<32 + } + cv = load64(src, s) + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + if debug && nextEmit != s { + fmt.Println("emitted ", len(src)-nextEmit, "literals") + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockBestSnappy encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBestSnappy(dst, src []byte) (d int) { + // Initialize the hash tables. + const ( + // Long hash matches. + lTableBits = 19 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 16 + maxSTableSize = 1 << sTableBits + + inputMargin = 8 + 2 + ) + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + if len(src) < minNonLiteralBlockSize { + return 0 + } + + var lTable [maxLTableSize]uint64 + var sTable [maxSTableSize]uint64 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + const lowbitMask = 0xffffffff + getCur := func(x uint64) int { + return int(x & lowbitMask) + } + getPrev := func(x uint64) int { + return int(x >> 32) + } + const maxSkip = 64 + + for { + type match struct { + offset int + s int + length int + score int + } + var best match + for { + // Next src position to check + nextS := (s-nextEmit)>>8 + 1 + if nextS > maxSkip { + nextS = s + maxSkip + } else { + nextS += s + } + if nextS > sLimit { + goto emitRemainder + } + hashL := hash8(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL := lTable[hashL] + candidateS := sTable[hashS] + + score := func(m match) int { + // Matches that are longer forward are penalized since we must emit it as a literal. + score := m.length - m.s + if nextEmit == m.s { + // If we do not have to emit literals, we save 1 byte + score++ + } + offset := m.s - m.offset + + return score - emitCopyNoRepeatSize(offset, m.length) + } + + matchAt := func(offset, s int, first uint32) match { + if best.length != 0 && best.s-best.offset == s-offset { + // Don't retest if we have the same offset. + return match{offset: offset, s: s} + } + if load32(src, offset) != first { + return match{offset: offset, s: s} + } + m := match{offset: offset, s: s, length: 4 + offset} + s += 4 + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, m.length); diff != 0 { + m.length += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + m.length += 8 + } + m.length -= offset + m.score = score(m) + if m.score <= -m.s { + // Eliminate if no savings, we might find a better one. + m.length = 0 + } + return m + } + + bestOf := func(a, b match) match { + if b.length == 0 { + return a + } + if a.length == 0 { + return b + } + as := a.score + b.s + bs := b.score + a.s + if as >= bs { + return a + } + return b + } + + best = bestOf(matchAt(getCur(candidateL), s, uint32(cv)), matchAt(getPrev(candidateL), s, uint32(cv))) + best = bestOf(best, matchAt(getCur(candidateS), s, uint32(cv))) + best = bestOf(best, matchAt(getPrev(candidateS), s, uint32(cv))) + + { + best = bestOf(best, matchAt(s-repeat+1, s+1, uint32(cv>>8))) + if best.length > 0 { + // s+1 + nextShort := sTable[hash4(cv>>8, sTableBits)] + s := s + 1 + cv := load64(src, s) + nextLong := lTable[hash8(cv, lTableBits)] + best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv))) + best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv))) + best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv))) + best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv))) + // Repeat at + 2 + best = bestOf(best, matchAt(s-repeat+1, s+1, uint32(cv>>8))) + + // s+2 + if true { + nextShort = sTable[hash4(cv>>8, sTableBits)] + s++ + cv = load64(src, s) + nextLong = lTable[hash8(cv, lTableBits)] + best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv))) + best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv))) + best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv))) + best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv))) + } + // Search for a match at best match end, see if that is better. + if sAt := best.s + best.length; sAt < sLimit { + sBack := best.s + backL := best.length + // Load initial values + cv = load64(src, sBack) + // Search for mismatch + next := lTable[hash8(load64(src, sAt), lTableBits)] + //next := sTable[hash4(load64(src, sAt), sTableBits)] + + if checkAt := getCur(next) - backL; checkAt > 0 { + best = bestOf(best, matchAt(checkAt, sBack, uint32(cv))) + } + if checkAt := getPrev(next) - backL; checkAt > 0 { + best = bestOf(best, matchAt(checkAt, sBack, uint32(cv))) + } + } + } + } + + // Update table + lTable[hashL] = uint64(s) | candidateL<<32 + sTable[hashS] = uint64(s) | candidateS<<32 + + if best.length > 0 { + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards, not needed for repeats... + s = best.s + if true { + for best.offset > 0 && s > nextEmit && src[best.offset-1] == src[s-1] { + best.offset-- + best.length++ + s-- + } + } + if false && best.offset >= s { + panic(fmt.Errorf("t %d >= s %d", best.offset, s)) + } + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := s - best.offset + + s += best.length + + if offset > 65535 && s-base <= 5 { + // Bail if the match is equal or worse to the encoding. + s = best.s + 1 + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + d += emitCopyNoRepeat(dst[d:], offset, best.length) + repeat = offset + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Fill tables... + for i := best.s + 1; i < s; i++ { + cv0 := load64(src, i) + long0 := hash8(cv0, lTableBits) + short0 := hash4(cv0, sTableBits) + lTable[long0] = uint64(i) | lTable[long0]<<32 + sTable[short0] = uint64(i) | sTable[short0]<<32 + } + cv = load64(src, s) + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// emitCopySize returns the size to encode the offset+length +// +// It assumes that: +// +// 1 <= offset && offset <= math.MaxUint32 +// 4 <= length && length <= 1 << 24 +func emitCopySize(offset, length int) int { + if offset >= 65536 { + i := 0 + if length > 64 { + length -= 64 + if length >= 4 { + // Emit remaining as repeats + return 5 + emitRepeatSize(offset, length) + } + i = 5 + } + if length == 0 { + return i + } + return i + 5 + } + + // Offset no more than 2 bytes. + if length > 64 { + if offset < 2048 { + // Emit 8 bytes, then rest as repeats... + return 2 + emitRepeatSize(offset, length-8) + } + // Emit remaining as repeats, at least 4 bytes remain. + return 3 + emitRepeatSize(offset, length-60) + } + if length >= 12 || offset >= 2048 { + return 3 + } + // Emit the remaining copy, encoded as 2 bytes. + return 2 +} + +// emitCopyNoRepeatSize returns the size to encode the offset+length +// +// It assumes that: +// +// 1 <= offset && offset <= math.MaxUint32 +// 4 <= length && length <= 1 << 24 +func emitCopyNoRepeatSize(offset, length int) int { + if offset >= 65536 { + return 5 + 5*(length/64) + } + + // Offset no more than 2 bytes. + if length > 64 { + // Emit remaining as repeats, at least 4 bytes remain. + return 3 + 3*(length/60) + } + if length >= 12 || offset >= 2048 { + return 3 + } + // Emit the remaining copy, encoded as 2 bytes. + return 2 +} + +// emitRepeatSize returns the number of bytes required to encode a repeat. +// Length must be at least 4 and < 1<<24 +func emitRepeatSize(offset, length int) int { + // Repeat offset, make length cheaper + if length <= 4+4 || (length < 8+4 && offset < 2048) { + return 2 + } + if length < (1<<8)+4+4 { + return 3 + } + if length < (1<<16)+(1<<8)+4 { + return 4 + } + const maxRepeat = (1 << 24) - 1 + length -= (1 << 16) - 4 + left := 0 + if length > maxRepeat { + left = length - maxRepeat + 4 + } + if left > 0 { + return 5 + emitRepeatSize(offset, left) + } + return 5 +} diff --git a/vendor/github.com/klauspost/compress/s2/encode_better.go b/vendor/github.com/klauspost/compress/s2/encode_better.go new file mode 100644 index 0000000..1e30fb7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encode_better.go @@ -0,0 +1,1507 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "bytes" + "fmt" + "math/bits" +) + +// hash4 returns the hash of the lowest 4 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <32. +func hash4(u uint64, h uint8) uint32 { + const prime4bytes = 2654435761 + return (uint32(u) * prime4bytes) >> ((32 - h) & 31) +} + +// hash5 returns the hash of the lowest 5 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash5(u uint64, h uint8) uint32 { + const prime5bytes = 889523592379 + return uint32(((u << (64 - 40)) * prime5bytes) >> ((64 - h) & 63)) +} + +// hash7 returns the hash of the lowest 7 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash7(u uint64, h uint8) uint32 { + const prime7bytes = 58295818150454627 + return uint32(((u << (64 - 56)) * prime7bytes) >> ((64 - h) & 63)) +} + +// hash8 returns the hash of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash8(u uint64, h uint8) uint32 { + const prime8bytes = 0xcf1bbcdcb7a56463 + return uint32((u * prime8bytes) >> ((64 - h) & 63)) +} + +// encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBetterGo(dst, src []byte) (d int) { + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + if len(src) < minNonLiteralBlockSize { + return 0 + } + + // Initialize the hash tables. + const ( + // Long hash matches. + lTableBits = 17 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 14 + maxSTableSize = 1 << sTableBits + ) + + var lTable [maxLTableSize]uint32 + var sTable [maxSTableSize]uint32 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We initialize repeat to 0, so we never match on first attempt + repeat := 0 + + for { + candidateL := 0 + nextS := 0 + for { + // Next src position to check + nextS = s + (s-nextEmit)>>7 + 1 + if nextS > sLimit { + goto emitRemainder + } + hashL := hash7(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL = int(lTable[hashL]) + candidateS := int(sTable[hashS]) + lTable[hashL] = uint32(s) + sTable[hashS] = uint32(s) + + valLong := load64(src, candidateL) + valShort := load64(src, candidateS) + + // If long matches at least 8 bytes, use that. + if cv == valLong { + break + } + if cv == valShort { + candidateL = candidateS + break + } + + // Check repeat at offset checkRep. + const checkRep = 1 + // Minimum length of a repeat. Tested with various values. + // While 4-5 offers improvements in some, 6 reduces + // regressions significantly. + const wantRepeatBytes = 6 + const repeatMask = ((1 << (wantRepeatBytes * 8)) - 1) << (8 * checkRep) + if false && repeat > 0 && cv&repeatMask == load64(src, s-repeat)&repeatMask { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + wantRepeatBytes + checkRep + s += wantRepeatBytes + checkRep + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidate] { + s++ + candidate++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + // Index in-between + index0 := base + 1 + index1 := s - 2 + + for index0 < index1 { + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 2 + index1 -= 2 + } + + cv = load64(src, s) + continue + } + + // Long likely matches 7, so take that. + if uint32(cv) == uint32(valLong) { + break + } + + // Check our short candidate + if uint32(cv) == uint32(valShort) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint32(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + break + } + // Use our short candidate. + candidateL = candidateS + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := base - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidateL] { + s++ + candidateL++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + if offset > 65535 && s-base <= 5 && repeat != offset { + // Bail if the match is equal or worse to the encoding. + s = nextS + 1 + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + if repeat == offset { + d += emitRepeat(dst[d:], offset, s-base) + } else { + d += emitCopy(dst[d:], offset, s-base) + repeat = offset + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + // lTable could be postponed, but very minor difference. + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // Index large values sparsely in between. + // We do two starting from different offsets for speed. + index2 := (index0 + index1 + 1) >> 1 + for index2 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0) + lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2) + index0 += 2 + index2 += 2 + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockBetterSnappyGo encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBetterSnappyGo(dst, src []byte) (d int) { + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + if len(src) < minNonLiteralBlockSize { + return 0 + } + + // Initialize the hash tables. + const ( + // Long hash matches. + lTableBits = 16 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 14 + maxSTableSize = 1 << sTableBits + ) + + var lTable [maxLTableSize]uint32 + var sTable [maxSTableSize]uint32 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We initialize repeat to 0, so we never match on first attempt + repeat := 0 + const maxSkip = 100 + + for { + candidateL := 0 + nextS := 0 + for { + // Next src position to check + nextS = min(s+(s-nextEmit)>>7+1, s+maxSkip) + + if nextS > sLimit { + goto emitRemainder + } + hashL := hash7(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL = int(lTable[hashL]) + candidateS := int(sTable[hashS]) + lTable[hashL] = uint32(s) + sTable[hashS] = uint32(s) + + if uint32(cv) == load32(src, candidateL) { + break + } + + // Check our short candidate + if uint32(cv) == load32(src, candidateS) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint32(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + break + } + // Use our short candidate. + candidateL = candidateS + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := base - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidateL] { + s++ + candidateL++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + if offset > 65535 && s-base <= 5 && repeat != offset { + // Bail if the match is equal or worse to the encoding. + s = nextS + 1 + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + d += emitCopyNoRepeat(dst[d:], offset, s-base) + repeat = offset + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // Index large values sparsely in between. + // We do two starting from different offsets for speed. + index2 := (index0 + index1 + 1) >> 1 + for index2 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0) + lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2) + index0 += 2 + index2 += 2 + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +func encodeBlockBetterGo64K(dst, src []byte) (d int) { + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + if len(src) < minNonLiteralBlockSize { + return 0 + } + // Initialize the hash tables. + // Use smaller tables for smaller blocks + const ( + // Long hash matches. + lTableBits = 16 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 13 + maxSTableSize = 1 << sTableBits + ) + + var lTable [maxLTableSize]uint16 + var sTable [maxSTableSize]uint16 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We initialize repeat to 0, so we never match on first attempt + repeat := 0 + + for { + candidateL := 0 + nextS := 0 + for { + // Next src position to check + nextS = s + (s-nextEmit)>>6 + 1 + if nextS > sLimit { + goto emitRemainder + } + hashL := hash7(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL = int(lTable[hashL]) + candidateS := int(sTable[hashS]) + lTable[hashL] = uint16(s) + sTable[hashS] = uint16(s) + + valLong := load64(src, candidateL) + valShort := load64(src, candidateS) + + // If long matches at least 8 bytes, use that. + if cv == valLong { + break + } + if cv == valShort { + candidateL = candidateS + break + } + + // Check repeat at offset checkRep. + const checkRep = 1 + // Minimum length of a repeat. Tested with various values. + // While 4-5 offers improvements in some, 6 reduces + // regressions significantly. + const wantRepeatBytes = 6 + const repeatMask = ((1 << (wantRepeatBytes * 8)) - 1) << (8 * checkRep) + if false && repeat > 0 && cv&repeatMask == load64(src, s-repeat)&repeatMask { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + wantRepeatBytes + checkRep + s += wantRepeatBytes + checkRep + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidate] { + s++ + candidate++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + // Index in-between + index0 := base + 1 + index1 := s - 2 + + for index0 < index1 { + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint16(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint16(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint16(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint16(index1 + 1) + index0 += 2 + index1 -= 2 + } + + cv = load64(src, s) + continue + } + + // Long likely matches 7, so take that. + if uint32(cv) == uint32(valLong) { + break + } + + // Check our short candidate + if uint32(cv) == uint32(valShort) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint16(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + break + } + // Use our short candidate. + candidateL = candidateS + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := base - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidateL] { + s++ + candidateL++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + if repeat == offset { + d += emitRepeat(dst[d:], offset, s-base) + } else { + d += emitCopy(dst[d:], offset, s-base) + repeat = offset + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint16(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint16(index0 + 1) + + // lTable could be postponed, but very minor difference. + lTable[hash7(cv1, lTableBits)] = uint16(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint16(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // Index large values sparsely in between. + // We do two starting from different offsets for speed. + index2 := (index0 + index1 + 1) >> 1 + for index2 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint16(index0) + lTable[hash7(load64(src, index2), lTableBits)] = uint16(index2) + index0 += 2 + index2 += 2 + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockBetterSnappyGo encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBetterSnappyGo64K(dst, src []byte) (d int) { + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + if len(src) < minNonLiteralBlockSize { + return 0 + } + + // Initialize the hash tables. + // Use smaller tables for smaller blocks + const ( + // Long hash matches. + lTableBits = 15 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 13 + maxSTableSize = 1 << sTableBits + ) + + var lTable [maxLTableSize]uint16 + var sTable [maxSTableSize]uint16 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + const maxSkip = 100 + + for { + candidateL := 0 + nextS := 0 + for { + // Next src position to check + nextS = min(s+(s-nextEmit)>>6+1, s+maxSkip) + + if nextS > sLimit { + goto emitRemainder + } + hashL := hash7(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL = int(lTable[hashL]) + candidateS := int(sTable[hashS]) + lTable[hashL] = uint16(s) + sTable[hashS] = uint16(s) + + if uint32(cv) == load32(src, candidateL) { + break + } + + // Check our short candidate + if uint32(cv) == load32(src, candidateS) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint16(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + break + } + // Use our short candidate. + candidateL = candidateS + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := base - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidateL] { + s++ + candidateL++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + d += emitCopyNoRepeat(dst[d:], offset, s-base) + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint16(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint16(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint16(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint16(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // Index large values sparsely in between. + // We do two starting from different offsets for speed. + index2 := (index0 + index1 + 1) >> 1 + for index2 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint16(index0) + lTable[hash7(load64(src, index2), lTableBits)] = uint16(index2) + index0 += 2 + index2 += 2 + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} + +// encodeBlockBetterDict encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlockBetterDict(dst, src []byte, dict *Dict) (d int) { + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + // Initialize the hash tables. + const ( + // Long hash matches. + lTableBits = 17 + maxLTableSize = 1 << lTableBits + + // Short hash matches. + sTableBits = 14 + maxSTableSize = 1 << sTableBits + + maxAhead = 8 // maximum bytes ahead without checking sLimit + + debug = false + ) + + sLimit := min(len(src)-inputMargin, MaxDictSrcOffset-maxAhead) + if len(src) < minNonLiteralBlockSize { + return 0 + } + + dict.initBetter() + + var lTable [maxLTableSize]uint32 + var sTable [maxSTableSize]uint32 + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 0 + cv := load64(src, s) + + // We initialize repeat to 0, so we never match on first attempt + repeat := len(dict.dict) - dict.repeat + + // While in dict +searchDict: + for { + candidateL := 0 + nextS := 0 + for { + // Next src position to check + nextS = s + (s-nextEmit)>>7 + 1 + if nextS > sLimit { + break searchDict + } + hashL := hash7(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL = int(lTable[hashL]) + candidateS := int(sTable[hashS]) + dictL := int(dict.betterTableLong[hashL]) + dictS := int(dict.betterTableShort[hashS]) + lTable[hashL] = uint32(s) + sTable[hashS] = uint32(s) + + valLong := load64(src, candidateL) + valShort := load64(src, candidateS) + + // If long matches at least 8 bytes, use that. + if s != 0 { + if cv == valLong { + goto emitMatch + } + if cv == valShort { + candidateL = candidateS + goto emitMatch + } + } + + // Check dict repeat. + if repeat >= s+4 { + candidate := len(dict.dict) - repeat + s + if candidate > 0 && uint32(cv) == load32(dict.dict, candidate) { + // Extend back + base := s + for i := candidate; base > nextEmit && i > 0 && dict.dict[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + if debug && nextEmit != base { + fmt.Println("emitted ", base-nextEmit, "literals") + } + s += 4 + candidate += 4 + for candidate < len(dict.dict)-8 && s <= len(src)-8 { + if diff := load64(src, s) ^ load64(dict.dict, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + d += emitRepeat(dst[d:], repeat, s-base) + if debug { + fmt.Println("emitted dict repeat length", s-base, "offset:", repeat, "s:", s) + } + nextEmit = s + if s >= sLimit { + break searchDict + } + // Index in-between + index0 := base + 1 + index1 := s - 2 + + cv = load64(src, s) + for index0 < index1 { + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 2 + index1 -= 2 + } + continue + } + } + // Don't try to find match at s==0 + if s == 0 { + cv = load64(src, nextS) + s = nextS + continue + } + + // Long likely matches 7, so take that. + if uint32(cv) == uint32(valLong) { + goto emitMatch + } + + // Long dict... + if uint32(cv) == load32(dict.dict, dictL) { + candidateL = dictL + goto emitDict + } + + // Check our short candidate + if uint32(cv) == uint32(valShort) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint32(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + goto emitMatch + } + // Use our short candidate. + candidateL = candidateS + goto emitMatch + } + if uint32(cv) == load32(dict.dict, dictS) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint32(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + goto emitMatch + } + candidateL = dictS + goto emitDict + } + cv = load64(src, nextS) + s = nextS + } + emitDict: + { + if debug { + if load32(dict.dict, candidateL) != load32(src, s) { + panic("dict emit mismatch") + } + } + // Extend backwards. + // The top bytes will be rechecked to get the full match. + for candidateL > 0 && s > nextEmit && dict.dict[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteral(dst[d:], src[nextEmit:s]) + if debug && nextEmit != s { + fmt.Println("emitted ", s-nextEmit, "literals") + } + { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + offset := s + (len(dict.dict)) - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s <= len(src)-8 && len(dict.dict)-candidateL >= 8 { + if diff := load64(src, s) ^ load64(dict.dict, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + if repeat == offset { + if debug { + fmt.Println("emitted dict repeat, length", s-base, "offset:", offset, "s:", s, "dict offset:", candidateL) + } + d += emitRepeat(dst[d:], offset, s-base) + } else { + if debug { + fmt.Println("emitted dict copy, length", s-base, "offset:", offset, "s:", s, "dict offset:", candidateL) + } + // Matches longer than 64 are split. + if s <= sLimit || s-base < 8 { + d += emitCopy(dst[d:], offset, s-base) + } else { + // Split to ensure we don't start a copy within next block. + d += emitCopy(dst[d:], offset, 4) + d += emitRepeat(dst[d:], offset, s-base-4) + } + repeat = offset + } + if false { + // Validate match. + if s <= candidateL { + panic("s <= candidate") + } + a := src[base:s] + b := dict.dict[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + break searchDict + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // index every second long in between. + for index0 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0) + lTable[hash7(load64(src, index1), lTableBits)] = uint32(index1) + index0 += 2 + index1 -= 2 + } + } + continue + } + emitMatch: + + // Extend backwards + for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := base - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidateL] { + s++ + candidateL++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + if offset > 65535 && s-base <= 5 && repeat != offset { + // Bail if the match is equal or worse to the encoding. + s = nextS + 1 + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + if debug && nextEmit != s { + fmt.Println("emitted ", s-nextEmit, "literals") + } + if repeat == offset { + if debug { + fmt.Println("emitted match repeat, length", s-base, "offset:", offset, "s:", s) + } + d += emitRepeat(dst[d:], offset, s-base) + } else { + if debug { + fmt.Println("emitted match copy, length", s-base, "offset:", offset, "s:", s) + } + d += emitCopy(dst[d:], offset, s-base) + repeat = offset + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // Index large values sparsely in between. + // We do two starting from different offsets for speed. + index2 := (index0 + index1 + 1) >> 1 + for index2 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0) + lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2) + index0 += 2 + index2 += 2 + } + } + + // Search without dict: + if repeat > s { + repeat = 0 + } + + // No more dict + sLimit = len(src) - inputMargin + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + if debug { + fmt.Println("now", s, "->", sLimit, "out:", d, "left:", len(src)-s, "nextemit:", nextEmit, "dstLimit:", dstLimit, "s:", s) + } + for { + candidateL := 0 + nextS := 0 + for { + // Next src position to check + nextS = s + (s-nextEmit)>>7 + 1 + if nextS > sLimit { + goto emitRemainder + } + hashL := hash7(cv, lTableBits) + hashS := hash4(cv, sTableBits) + candidateL = int(lTable[hashL]) + candidateS := int(sTable[hashS]) + lTable[hashL] = uint32(s) + sTable[hashS] = uint32(s) + + valLong := load64(src, candidateL) + valShort := load64(src, candidateS) + + // If long matches at least 8 bytes, use that. + if cv == valLong { + break + } + if cv == valShort { + candidateL = candidateS + break + } + + // Check repeat at offset checkRep. + const checkRep = 1 + // Minimum length of a repeat. Tested with various values. + // While 4-5 offers improvements in some, 6 reduces + // regressions significantly. + const wantRepeatBytes = 6 + const repeatMask = ((1 << (wantRepeatBytes * 8)) - 1) << (8 * checkRep) + if false && repeat > 0 && cv&repeatMask == load64(src, s-repeat)&repeatMask { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteral(dst[d:], src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + wantRepeatBytes + checkRep + s += wantRepeatBytes + checkRep + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidate] { + s++ + candidate++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset. + d += emitRepeat(dst[d:], repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + // Index in-between + index0 := base + 1 + index1 := s - 2 + + for index0 < index1 { + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 2 + index1 -= 2 + } + + cv = load64(src, s) + continue + } + + // Long likely matches 7, so take that. + if uint32(cv) == uint32(valLong) { + break + } + + // Check our short candidate + if uint32(cv) == uint32(valShort) { + // Try a long candidate at s+1 + hashL = hash7(cv>>8, lTableBits) + candidateL = int(lTable[hashL]) + lTable[hashL] = uint32(s + 1) + if uint32(cv>>8) == load32(src, candidateL) { + s++ + break + } + // Use our short candidate. + candidateL = candidateS + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] { + candidateL-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + base := s + offset := base - candidateL + + // Extend the 4-byte match as long as possible. + s += 4 + candidateL += 4 + for s < len(src) { + if len(src)-s < 8 { + if src[s] == src[candidateL] { + s++ + candidateL++ + continue + } + break + } + if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidateL += 8 + } + + if offset > 65535 && s-base <= 5 && repeat != offset { + // Bail if the match is equal or worse to the encoding. + s = nextS + 1 + if s >= sLimit { + goto emitRemainder + } + cv = load64(src, s) + continue + } + + d += emitLiteral(dst[d:], src[nextEmit:base]) + if repeat == offset { + d += emitRepeat(dst[d:], offset, s-base) + } else { + d += emitCopy(dst[d:], offset, s-base) + repeat = offset + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + + // Index short & long + index0 := base + 1 + index1 := s - 2 + + cv0 := load64(src, index0) + cv1 := load64(src, index1) + lTable[hash7(cv0, lTableBits)] = uint32(index0) + sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1) + + lTable[hash7(cv1, lTableBits)] = uint32(index1) + sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1) + index0 += 1 + index1 -= 1 + cv = load64(src, s) + + // Index large values sparsely in between. + // We do two starting from different offsets for speed. + index2 := (index0 + index1 + 1) >> 1 + for index2 < index1 { + lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0) + lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2) + index0 += 2 + index2 += 2 + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} diff --git a/vendor/github.com/klauspost/compress/s2/encode_go.go b/vendor/github.com/klauspost/compress/s2/encode_go.go new file mode 100644 index 0000000..e25b784 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encode_go.go @@ -0,0 +1,741 @@ +//go:build !amd64 || appengine || !gc || noasm +// +build !amd64 appengine !gc noasm + +package s2 + +import ( + "bytes" + "math/bits" +) + +const hasAmd64Asm = false + +// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) +func encodeBlock(dst, src []byte) (d int) { + if len(src) < minNonLiteralBlockSize { + return 0 + } + if len(src) <= 64<<10 { + return encodeBlockGo64K(dst, src) + } + return encodeBlockGo(dst, src) +} + +// encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) +func encodeBlockBetter(dst, src []byte) (d int) { + if len(src) <= 64<<10 { + return encodeBlockBetterGo64K(dst, src) + } + return encodeBlockBetterGo(dst, src) +} + +// encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) +func encodeBlockBetterSnappy(dst, src []byte) (d int) { + if len(src) <= 64<<10 { + return encodeBlockBetterSnappyGo64K(dst, src) + } + return encodeBlockBetterSnappyGo(dst, src) +} + +// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) +func encodeBlockSnappy(dst, src []byte) (d int) { + if len(src) < minNonLiteralBlockSize { + return 0 + } + if len(src) <= 64<<10 { + return encodeBlockSnappyGo64K(dst, src) + } + return encodeBlockSnappyGo(dst, src) +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 0 <= len(lit) && len(lit) <= math.MaxUint32 +func emitLiteral(dst, lit []byte) int { + if len(lit) == 0 { + return 0 + } + const num = 63<<2 | tagLiteral + i, n := 0, uint(len(lit)-1) + switch { + case n < 60: + dst[0] = uint8(n)<<2 | tagLiteral + i = 1 + case n < 1<<8: + dst[1] = uint8(n) + dst[0] = 60<<2 | tagLiteral + i = 2 + case n < 1<<16: + dst[2] = uint8(n >> 8) + dst[1] = uint8(n) + dst[0] = 61<<2 | tagLiteral + i = 3 + case n < 1<<24: + dst[3] = uint8(n >> 16) + dst[2] = uint8(n >> 8) + dst[1] = uint8(n) + dst[0] = 62<<2 | tagLiteral + i = 4 + default: + dst[4] = uint8(n >> 24) + dst[3] = uint8(n >> 16) + dst[2] = uint8(n >> 8) + dst[1] = uint8(n) + dst[0] = 63<<2 | tagLiteral + i = 5 + } + return i + copy(dst[i:], lit) +} + +// emitRepeat writes a repeat chunk and returns the number of bytes written. +// Length must be at least 4 and < 1<<24 +func emitRepeat(dst []byte, offset, length int) int { + // Repeat offset, make length cheaper + length -= 4 + if length <= 4 { + dst[0] = uint8(length)<<2 | tagCopy1 + dst[1] = 0 + return 2 + } + if length < 8 && offset < 2048 { + // Encode WITH offset + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length)<<2 | tagCopy1 + return 2 + } + if length < (1<<8)+4 { + length -= 4 + dst[2] = uint8(length) + dst[1] = 0 + dst[0] = 5<<2 | tagCopy1 + return 3 + } + if length < (1<<16)+(1<<8) { + length -= 1 << 8 + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 6<<2 | tagCopy1 + return 4 + } + const maxRepeat = (1 << 24) - 1 + length -= 1 << 16 + left := 0 + if length > maxRepeat { + left = length - maxRepeat + 4 + length = maxRepeat - 4 + } + dst[4] = uint8(length >> 16) + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 7<<2 | tagCopy1 + if left > 0 { + return 5 + emitRepeat(dst[5:], offset, left) + } + return 5 +} + +// emitCopy writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= math.MaxUint32 +// 4 <= length && length <= 1 << 24 +func emitCopy(dst []byte, offset, length int) int { + if offset >= 65536 { + i := 0 + if length > 64 { + // Emit a length 64 copy, encoded as 5 bytes. + dst[4] = uint8(offset >> 24) + dst[3] = uint8(offset >> 16) + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 63<<2 | tagCopy4 + length -= 64 + if length >= 4 { + // Emit remaining as repeats + return 5 + emitRepeat(dst[5:], offset, length) + } + i = 5 + } + if length == 0 { + return i + } + // Emit a copy, offset encoded as 4 bytes. + dst[i+0] = uint8(length-1)<<2 | tagCopy4 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + dst[i+3] = uint8(offset >> 16) + dst[i+4] = uint8(offset >> 24) + return i + 5 + } + + // Offset no more than 2 bytes. + if length > 64 { + off := 3 + if offset < 2048 { + // emit 8 bytes as tagCopy1, rest as repeats. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(8-4)<<2 | tagCopy1 + length -= 8 + off = 2 + } else { + // Emit a length 60 copy, encoded as 3 bytes. + // Emit remaining as repeat value (minimum 4 bytes). + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 59<<2 | tagCopy2 + length -= 60 + } + // Emit remaining as repeats, at least 4 bytes remain. + return off + emitRepeat(dst[off:], offset, length) + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = uint8(length-1)<<2 | tagCopy2 + return 3 + } + // Emit the remaining copy, encoded as 2 bytes. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + return 2 +} + +// emitCopyNoRepeat writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= math.MaxUint32 +// 4 <= length && length <= 1 << 24 +func emitCopyNoRepeat(dst []byte, offset, length int) int { + if offset >= 65536 { + i := 0 + if length > 64 { + // Emit a length 64 copy, encoded as 5 bytes. + dst[4] = uint8(offset >> 24) + dst[3] = uint8(offset >> 16) + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 63<<2 | tagCopy4 + length -= 64 + if length >= 4 { + // Emit remaining as repeats + return 5 + emitCopyNoRepeat(dst[5:], offset, length) + } + i = 5 + } + if length == 0 { + return i + } + // Emit a copy, offset encoded as 4 bytes. + dst[i+0] = uint8(length-1)<<2 | tagCopy4 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + dst[i+3] = uint8(offset >> 16) + dst[i+4] = uint8(offset >> 24) + return i + 5 + } + + // Offset no more than 2 bytes. + if length > 64 { + // Emit a length 60 copy, encoded as 3 bytes. + // Emit remaining as repeat value (minimum 4 bytes). + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 59<<2 | tagCopy2 + length -= 60 + // Emit remaining as repeats, at least 4 bytes remain. + return 3 + emitCopyNoRepeat(dst[3:], offset, length) + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = uint8(length-1)<<2 | tagCopy2 + return 3 + } + // Emit the remaining copy, encoded as 2 bytes. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + return 2 +} + +// matchLen returns how many bytes match in a and b +// +// It assumes that: +// +// len(a) <= len(b) +func matchLen(a []byte, b []byte) int { + b = b[:len(a)] + var checked int + if len(a) > 4 { + // Try 4 bytes first + if diff := load32(a, 0) ^ load32(b, 0); diff != 0 { + return bits.TrailingZeros32(diff) >> 3 + } + // Switch to 8 byte matching. + checked = 4 + a = a[4:] + b = b[4:] + for len(a) >= 8 { + b = b[:len(a)] + if diff := load64(a, 0) ^ load64(b, 0); diff != 0 { + return checked + (bits.TrailingZeros64(diff) >> 3) + } + checked += 8 + a = a[8:] + b = b[8:] + } + } + b = b[:len(a)] + for i := range a { + if a[i] != b[i] { + return int(i) + checked + } + } + return len(a) + checked +} + +// input must be > inputMargin +func calcBlockSize(src []byte, _ *[32768]byte) (d int) { + // Initialize the hash table. + const ( + tableBits = 13 + maxTableSize = 1 << tableBits + ) + + var table [maxTableSize]uint32 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>6 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint32(s) + table[hash1] = uint32(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteralSize(src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeatSize(repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint32(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint32(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteralSize(src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeatSize(repeat, s-base) + if false { + // Validate match. + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s) + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteralSize(src[nextEmit:]) + } + return d +} + +// length must be > inputMargin. +func calcBlockSizeSmall(src []byte, _ *[2048]byte) (d int) { + // Initialize the hash table. + const ( + tableBits = 9 + maxTableSize = 1 << tableBits + ) + + var table [maxTableSize]uint32 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // Bail if we can't compress to at least this. + dstLimit := len(src) - len(src)>>5 - 5 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + cv := load64(src, s) + + // We search for a repeat at -1, but don't output repeats when nextEmit == 0 + repeat := 1 + + for { + candidate := 0 + for { + // Next src position to check + nextS := s + (s-nextEmit)>>6 + 4 + if nextS > sLimit { + goto emitRemainder + } + hash0 := hash6(cv, tableBits) + hash1 := hash6(cv>>8, tableBits) + candidate = int(table[hash0]) + candidate2 := int(table[hash1]) + table[hash0] = uint32(s) + table[hash1] = uint32(s + 1) + hash2 := hash6(cv>>16, tableBits) + + // Check repeat at offset checkRep. + const checkRep = 1 + if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + base := s + checkRep + // Extend back + for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { + i-- + base-- + } + d += emitLiteralSize(src[nextEmit:base]) + + // Extend forward + candidate := s - repeat + 4 + checkRep + s += 4 + checkRep + for s <= sLimit { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeatSize(repeat, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + cv = load64(src, s) + continue + } + + if uint32(cv) == load32(src, candidate) { + break + } + candidate = int(table[hash2]) + if uint32(cv>>8) == load32(src, candidate2) { + table[hash2] = uint32(s + 2) + candidate = candidate2 + s++ + break + } + table[hash2] = uint32(s + 2) + if uint32(cv>>16) == load32(src, candidate) { + s += 2 + break + } + + cv = load64(src, nextS) + s = nextS + } + + // Extend backwards + for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] { + candidate-- + s-- + } + + // Bail if we exceed the maximum size. + if d+(s-nextEmit) > dstLimit { + return 0 + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + d += emitLiteralSize(src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + repeat = base - candidate + + // Extend the 4-byte match as long as possible. + s += 4 + candidate += 4 + for s <= len(src)-8 { + if diff := load64(src, s) ^ load64(src, candidate); diff != 0 { + s += bits.TrailingZeros64(diff) >> 3 + break + } + s += 8 + candidate += 8 + } + + d += emitCopyNoRepeatSize(repeat, s-base) + if false { + // Validate match. + a := src[base:s] + b := src[base-repeat : base-repeat+(s-base)] + if !bytes.Equal(a, b) { + panic("mismatch") + } + } + + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + if d > dstLimit { + // Do we have space for more, if not bail. + return 0 + } + // Check for an immediate match, otherwise start search at s+1 + x := load64(src, s-2) + m2Hash := hash6(x, tableBits) + currHash := hash6(x>>16, tableBits) + candidate = int(table[currHash]) + table[m2Hash] = uint32(s - 2) + table[currHash] = uint32(s) + if uint32(x>>16) != load32(src, candidate) { + cv = load64(src, s+1) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + // Bail if we exceed the maximum size. + if d+len(src)-nextEmit > dstLimit { + return 0 + } + d += emitLiteralSize(src[nextEmit:]) + } + return d +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 0 <= len(lit) && len(lit) <= math.MaxUint32 +func emitLiteralSize(lit []byte) int { + if len(lit) == 0 { + return 0 + } + switch { + case len(lit) <= 60: + return len(lit) + 1 + case len(lit) <= 1<<8: + return len(lit) + 2 + case len(lit) <= 1<<16: + return len(lit) + 3 + case len(lit) <= 1<<24: + return len(lit) + 4 + default: + return len(lit) + 5 + } +} + +func cvtLZ4BlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) { + panic("cvtLZ4BlockAsm should be unreachable") +} + +func cvtLZ4BlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) { + panic("cvtLZ4BlockSnappyAsm should be unreachable") +} + +func cvtLZ4sBlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) { + panic("cvtLZ4sBlockAsm should be unreachable") +} + +func cvtLZ4sBlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) { + panic("cvtLZ4sBlockSnappyAsm should be unreachable") +} diff --git a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go new file mode 100644 index 0000000..f43aa81 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go @@ -0,0 +1,228 @@ +// Code generated by command: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_amd64.go -pkg=s2. DO NOT EDIT. + +//go:build !appengine && !noasm && gc && !noasm + +package s2 + +func _dummy_() + +// encodeBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4294967295 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int + +// encodeBlockAsm4MB encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4194304 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBlockAsm4MB(dst []byte, src []byte, tmp *[65536]byte) int + +// encodeBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 16383 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int + +// encodeBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4095 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int + +// encodeBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 511 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int + +// encodeBetterBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4294967295 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int + +// encodeBetterBlockAsm4MB encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4194304 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBetterBlockAsm4MB(dst []byte, src []byte, tmp *[589824]byte) int + +// encodeBetterBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 16383 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int + +// encodeBetterBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4095 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int + +// encodeBetterBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 511 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int + +// encodeSnappyBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4294967295 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int + +// encodeSnappyBlockAsm64K encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 65535 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBlockAsm64K(dst []byte, src []byte, tmp *[65536]byte) int + +// encodeSnappyBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 16383 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int + +// encodeSnappyBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4095 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int + +// encodeSnappyBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 511 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int + +// encodeSnappyBetterBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4294967295 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int + +// encodeSnappyBetterBlockAsm64K encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 65535 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte, tmp *[294912]byte) int + +// encodeSnappyBetterBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 16383 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int + +// encodeSnappyBetterBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4095 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int + +// encodeSnappyBetterBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 511 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int + +// calcBlockSize encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 4294967295 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func calcBlockSize(src []byte, tmp *[32768]byte) int + +// calcBlockSizeSmall encodes a non-empty src to a guaranteed-large-enough dst. +// Maximum input 1024 bytes. +// It assumes that the varint-encoded length of the decompressed bytes has already been written. +// +//go:noescape +func calcBlockSizeSmall(src []byte, tmp *[2048]byte) int + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes with margin of 0 bytes +// 0 <= len(lit) && len(lit) <= math.MaxUint32 +// +//go:noescape +func emitLiteral(dst []byte, lit []byte) int + +// emitRepeat writes a repeat chunk and returns the number of bytes written. +// Length must be at least 4 and < 1<<32 +// +//go:noescape +func emitRepeat(dst []byte, offset int, length int) int + +// emitCopy writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= math.MaxUint32 +// 4 <= length && length <= 1 << 24 +// +//go:noescape +func emitCopy(dst []byte, offset int, length int) int + +// emitCopyNoRepeat writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= math.MaxUint32 +// 4 <= length && length <= 1 << 24 +// +//go:noescape +func emitCopyNoRepeat(dst []byte, offset int, length int) int + +// matchLen returns how many bytes match in a and b +// +// It assumes that: +// +// len(a) <= len(b) +// +//go:noescape +func matchLen(a []byte, b []byte) int + +// cvtLZ4Block converts an LZ4 block to S2 +// +//go:noescape +func cvtLZ4BlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) + +// cvtLZ4sBlock converts an LZ4s block to S2 +// +//go:noescape +func cvtLZ4sBlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) + +// cvtLZ4Block converts an LZ4 block to Snappy +// +//go:noescape +func cvtLZ4BlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) + +// cvtLZ4sBlock converts an LZ4s block to Snappy +// +//go:noescape +func cvtLZ4sBlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) diff --git a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s new file mode 100644 index 0000000..df9be68 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s @@ -0,0 +1,21303 @@ +// Code generated by command: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_amd64.go -pkg=s2. DO NOT EDIT. + +//go:build !appengine && !noasm && gc && !noasm + +#include "textflag.h" + +// func _dummy_() +TEXT ·_dummy_(SB), $0 +#ifdef GOAMD64_v4 +#ifndef GOAMD64_v3 +#define GOAMD64_v3 +#endif +#endif + RET + +// func encodeBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBlockAsm: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBlockAsm + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBlockAsm: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBlockAsm + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeBlockAsm + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI + JZ repeat_extend_back_end_encodeBlockAsm + +repeat_extend_back_loop_encodeBlockAsm: + CMPL DI, R8 + JBE repeat_extend_back_end_encodeBlockAsm + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeBlockAsm + LEAL -1(DI), DI + DECL SI + JNZ repeat_extend_back_loop_encodeBlockAsm + +repeat_extend_back_end_encodeBlockAsm: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 5(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeBlockAsm + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeBlockAsm + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeBlockAsm + CMPL SI, $0x00010000 + JB three_bytes_repeat_emit_encodeBlockAsm + CMPL SI, $0x01000000 + JB four_bytes_repeat_emit_encodeBlockAsm + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_repeat_emit_encodeBlockAsm + +four_bytes_repeat_emit_encodeBlockAsm: + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_repeat_emit_encodeBlockAsm + +three_bytes_repeat_emit_encodeBlockAsm: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeBlockAsm + +two_bytes_repeat_emit_encodeBlockAsm: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeBlockAsm + JMP memmove_long_repeat_emit_encodeBlockAsm + +one_byte_repeat_emit_encodeBlockAsm: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_repeat_emit_encodeBlockAsm: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeBlockAsm + +memmove_long_repeat_emit_encodeBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 + JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeBlockAsm: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm: + CMPL R9, $0x10 + JB matchlen_match8_repeat_extend_encodeBlockAsm + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm + XORQ 8(SI)(R12*1), R13 + JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm + LEAL -16(R9), R9 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm + +matchlen_bsf_16repeat_extend_encodeBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm + +matchlen_match8_repeat_extend_encodeBlockAsm: + CMPL R9, $0x08 + JB matchlen_match4_repeat_extend_encodeBlockAsm + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm + LEAL -8(R9), R9 + LEAL 8(R12), R12 + JMP matchlen_match4_repeat_extend_encodeBlockAsm + +matchlen_bsf_8_repeat_extend_encodeBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm + +matchlen_match4_repeat_extend_encodeBlockAsm: + CMPL R9, $0x04 + JB matchlen_match2_repeat_extend_encodeBlockAsm + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 + JNE matchlen_match2_repeat_extend_encodeBlockAsm + LEAL -4(R9), R9 + LEAL 4(R12), R12 + +matchlen_match2_repeat_extend_encodeBlockAsm: + CMPL R9, $0x01 + JE matchlen_match1_repeat_extend_encodeBlockAsm + JB repeat_extend_forward_end_encodeBlockAsm + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 + JNE matchlen_match1_repeat_extend_encodeBlockAsm + LEAL 2(R12), R12 + SUBL $0x02, R9 + JZ repeat_extend_forward_end_encodeBlockAsm + +matchlen_match1_repeat_extend_encodeBlockAsm: + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 + JNE repeat_extend_forward_end_encodeBlockAsm + LEAL 1(R12), R12 + +repeat_extend_forward_end_encodeBlockAsm: + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 + JZ repeat_as_copy_encodeBlockAsm + + // emitRepeat +emit_repeat_again_match_repeat_encodeBlockAsm: + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_match_repeat_encodeBlockAsm + CMPL R8, $0x0c + JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm + CMPL DI, $0x00000800 + JB repeat_two_offset_match_repeat_encodeBlockAsm + +cant_repeat_two_offset_match_repeat_encodeBlockAsm: + CMPL SI, $0x00000104 + JB repeat_three_match_repeat_encodeBlockAsm + CMPL SI, $0x00010100 + JB repeat_four_match_repeat_encodeBlockAsm + CMPL SI, $0x0100ffff + JB repeat_five_match_repeat_encodeBlockAsm + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_repeat_encodeBlockAsm + +repeat_five_match_repeat_encodeBlockAsm: + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_match_repeat_encodeBlockAsm: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_match_repeat_encodeBlockAsm: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_match_repeat_encodeBlockAsm: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_match_repeat_encodeBlockAsm: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_as_copy_encodeBlockAsm: + // emitCopy + CMPL DI, $0x00010000 + JB two_byte_offset_repeat_as_copy_encodeBlockAsm + CMPL SI, $0x40 + JBE four_bytes_remain_repeat_as_copy_encodeBlockAsm + MOVB $0xff, (CX) + MOVL DI, 1(CX) + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 + JB four_bytes_remain_repeat_as_copy_encodeBlockAsm + + // emitRepeat +emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy: + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy + CMPL SI, $0x00010100 + JB repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy + CMPL SI, $0x0100ffff + JB repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy + +repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy: + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +four_bytes_remain_repeat_as_copy_encodeBlockAsm: + TESTL SI, SI + JZ repeat_end_emit_encodeBlockAsm + XORL R8, R8 + LEAL -1(R8)(SI*4), SI + MOVB SI, (CX) + MOVL DI, 1(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm + +two_byte_offset_repeat_as_copy_encodeBlockAsm: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm + CMPL DI, $0x00000800 + JAE long_offset_short_repeat_as_copy_encodeBlockAsm + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + MOVL DI, R9 + SHRL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI + + // emitRepeat + LEAL -4(SI), SI + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + +emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPL SI, $0x00010100 + JB repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPL SI, $0x0100ffff + JB repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + +repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +long_offset_short_repeat_as_copy_encodeBlockAsm: + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + + // emitRepeat +emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short: + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPL SI, $0x00010100 + JB repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPL SI, $0x0100ffff + JB repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short + +repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short: + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm + +emit_copy_three_repeat_as_copy_encodeBlockAsm: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeBlockAsm: + MOVL DX, 12(SP) + JMP search_loop_encodeBlockAsm + +no_repeat_found_encodeBlockAsm: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBlockAsm + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeBlockAsm + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeBlockAsm + MOVL 20(SP), DX + JMP search_loop_encodeBlockAsm + +candidate3_match_encodeBlockAsm: + ADDL $0x02, DX + JMP candidate_match_encodeBlockAsm + +candidate2_match_encodeBlockAsm: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeBlockAsm: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBlockAsm + +match_extend_back_loop_encodeBlockAsm: + CMPL DX, DI + JBE match_extend_back_end_encodeBlockAsm + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBlockAsm + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBlockAsm + JMP match_extend_back_loop_encodeBlockAsm + +match_extend_back_end_encodeBlockAsm: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeBlockAsm + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeBlockAsm + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeBlockAsm + CMPL R8, $0x00010000 + JB three_bytes_match_emit_encodeBlockAsm + CMPL R8, $0x01000000 + JB four_bytes_match_emit_encodeBlockAsm + MOVB $0xfc, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_match_emit_encodeBlockAsm + +four_bytes_match_emit_encodeBlockAsm: + MOVL R8, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW R8, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_encodeBlockAsm + +three_bytes_match_emit_encodeBlockAsm: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBlockAsm + +two_bytes_match_emit_encodeBlockAsm: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeBlockAsm + JMP memmove_long_match_emit_encodeBlockAsm + +one_byte_match_emit_encodeBlockAsm: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBlockAsm: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeBlockAsm + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBlockAsm: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeBlockAsm + +memmove_long_match_emit_encodeBlockAsm: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeBlockAsm: +match_nolit_loop_encodeBlockAsm: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeBlockAsm: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeBlockAsm + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeBlockAsm + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm + +matchlen_bsf_16match_nolit_encodeBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm + +matchlen_match8_match_nolit_encodeBlockAsm: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeBlockAsm + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeBlockAsm + +matchlen_bsf_8_match_nolit_encodeBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm + +matchlen_match4_match_nolit_encodeBlockAsm: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeBlockAsm + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeBlockAsm + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeBlockAsm: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeBlockAsm + JB match_nolit_end_encodeBlockAsm + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeBlockAsm + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeBlockAsm + +matchlen_match1_match_nolit_encodeBlockAsm: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeBlockAsm + LEAL 1(R10), R10 + +match_nolit_end_encodeBlockAsm: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL SI, $0x00010000 + JB two_byte_offset_match_nolit_encodeBlockAsm + CMPL R10, $0x40 + JBE four_bytes_remain_match_nolit_encodeBlockAsm + MOVB $0xff, (CX) + MOVL SI, 1(CX) + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 + JB four_bytes_remain_match_nolit_encodeBlockAsm + + // emitRepeat +emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy: + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm_emit_copy + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm_emit_copy + CMPL R10, $0x00010100 + JB repeat_four_match_nolit_encodeBlockAsm_emit_copy + CMPL R10, $0x0100ffff + JB repeat_five_match_nolit_encodeBlockAsm_emit_copy + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy + +repeat_five_match_nolit_encodeBlockAsm_emit_copy: + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_four_match_nolit_encodeBlockAsm_emit_copy: + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_three_match_nolit_encodeBlockAsm_emit_copy: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_match_nolit_encodeBlockAsm_emit_copy: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +four_bytes_remain_match_nolit_encodeBlockAsm: + TESTL R10, R10 + JZ match_nolit_emitcopy_end_encodeBlockAsm + XORL DI, DI + LEAL -1(DI)(R10*4), R10 + MOVB R10, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +two_byte_offset_match_nolit_encodeBlockAsm: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBlockAsm + CMPL SI, $0x00000800 + JAE long_offset_short_match_nolit_encodeBlockAsm + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + MOVL SI, R8 + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b + +emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short_2b: + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPL R10, $0x00010100 + JB repeat_four_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPL R10, $0x0100ffff + JB repeat_five_match_nolit_encodeBlockAsm_emit_copy_short_2b + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short_2b + +repeat_five_match_nolit_encodeBlockAsm_emit_copy_short_2b: + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_four_match_nolit_encodeBlockAsm_emit_copy_short_2b: + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_three_match_nolit_encodeBlockAsm_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_match_nolit_encodeBlockAsm_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +long_offset_short_match_nolit_encodeBlockAsm: + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + + // emitRepeat +emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short: + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm_emit_copy_short + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm_emit_copy_short + CMPL R10, $0x00010100 + JB repeat_four_match_nolit_encodeBlockAsm_emit_copy_short + CMPL R10, $0x0100ffff + JB repeat_five_match_nolit_encodeBlockAsm_emit_copy_short + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short + +repeat_five_match_nolit_encodeBlockAsm_emit_copy_short: + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_four_match_nolit_encodeBlockAsm_emit_copy_short: + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_three_match_nolit_encodeBlockAsm_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_match_nolit_encodeBlockAsm_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +two_byte_offset_short_match_nolit_encodeBlockAsm: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeBlockAsm + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBlockAsm + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm + +emit_copy_three_match_nolit_encodeBlockAsm: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeBlockAsm: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBlockAsm + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm: + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeBlockAsm + INCL DX + JMP search_loop_encodeBlockAsm + +emit_remainder_encodeBlockAsm: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBlockAsm + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBlockAsm + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBlockAsm + CMPL DX, $0x00010000 + JB three_bytes_emit_remainder_encodeBlockAsm + CMPL DX, $0x01000000 + JB four_bytes_emit_remainder_encodeBlockAsm + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_emit_remainder_encodeBlockAsm + +four_bytes_emit_remainder_encodeBlockAsm: + MOVL DX, BX + SHRL $0x10, BX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_encodeBlockAsm + +three_bytes_emit_remainder_encodeBlockAsm: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBlockAsm + +two_bytes_emit_remainder_encodeBlockAsm: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBlockAsm + JMP memmove_long_emit_remainder_encodeBlockAsm + +one_byte_emit_remainder_encodeBlockAsm: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBlockAsm: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBlockAsm + +memmove_long_emit_remainder_encodeBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBlockAsm: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBlockAsm4MB(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm4MB(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBlockAsm4MB: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBlockAsm4MB + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBlockAsm4MB: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBlockAsm4MB + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeBlockAsm4MB + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI + JZ repeat_extend_back_end_encodeBlockAsm4MB + +repeat_extend_back_loop_encodeBlockAsm4MB: + CMPL DI, R8 + JBE repeat_extend_back_end_encodeBlockAsm4MB + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeBlockAsm4MB + LEAL -1(DI), DI + DECL SI + JNZ repeat_extend_back_loop_encodeBlockAsm4MB + +repeat_extend_back_end_encodeBlockAsm4MB: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 4(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm4MB: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeBlockAsm4MB + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeBlockAsm4MB + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeBlockAsm4MB + CMPL SI, $0x00010000 + JB three_bytes_repeat_emit_encodeBlockAsm4MB + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_repeat_emit_encodeBlockAsm4MB + +three_bytes_repeat_emit_encodeBlockAsm4MB: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeBlockAsm4MB + +two_bytes_repeat_emit_encodeBlockAsm4MB: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeBlockAsm4MB + JMP memmove_long_repeat_emit_encodeBlockAsm4MB + +one_byte_repeat_emit_encodeBlockAsm4MB: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeBlockAsm4MB: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_repeat_emit_encodeBlockAsm4MB: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeBlockAsm4MB + +memmove_long_repeat_emit_encodeBlockAsm4MB: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32: + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 + JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeBlockAsm4MB: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB: + CMPL R9, $0x10 + JB matchlen_match8_repeat_extend_encodeBlockAsm4MB + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB + XORQ 8(SI)(R12*1), R13 + JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm4MB + LEAL -16(R9), R9 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB + +matchlen_bsf_16repeat_extend_encodeBlockAsm4MB: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm4MB + +matchlen_match8_repeat_extend_encodeBlockAsm4MB: + CMPL R9, $0x08 + JB matchlen_match4_repeat_extend_encodeBlockAsm4MB + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB + LEAL -8(R9), R9 + LEAL 8(R12), R12 + JMP matchlen_match4_repeat_extend_encodeBlockAsm4MB + +matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm4MB + +matchlen_match4_repeat_extend_encodeBlockAsm4MB: + CMPL R9, $0x04 + JB matchlen_match2_repeat_extend_encodeBlockAsm4MB + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 + JNE matchlen_match2_repeat_extend_encodeBlockAsm4MB + LEAL -4(R9), R9 + LEAL 4(R12), R12 + +matchlen_match2_repeat_extend_encodeBlockAsm4MB: + CMPL R9, $0x01 + JE matchlen_match1_repeat_extend_encodeBlockAsm4MB + JB repeat_extend_forward_end_encodeBlockAsm4MB + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 + JNE matchlen_match1_repeat_extend_encodeBlockAsm4MB + LEAL 2(R12), R12 + SUBL $0x02, R9 + JZ repeat_extend_forward_end_encodeBlockAsm4MB + +matchlen_match1_repeat_extend_encodeBlockAsm4MB: + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 + JNE repeat_extend_forward_end_encodeBlockAsm4MB + LEAL 1(R12), R12 + +repeat_extend_forward_end_encodeBlockAsm4MB: + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 + JZ repeat_as_copy_encodeBlockAsm4MB + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_match_repeat_encodeBlockAsm4MB + CMPL R8, $0x0c + JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm4MB + CMPL DI, $0x00000800 + JB repeat_two_offset_match_repeat_encodeBlockAsm4MB + +cant_repeat_two_offset_match_repeat_encodeBlockAsm4MB: + CMPL SI, $0x00000104 + JB repeat_three_match_repeat_encodeBlockAsm4MB + CMPL SI, $0x00010100 + JB repeat_four_match_repeat_encodeBlockAsm4MB + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_match_repeat_encodeBlockAsm4MB: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_match_repeat_encodeBlockAsm4MB: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_match_repeat_encodeBlockAsm4MB: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_match_repeat_encodeBlockAsm4MB: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_as_copy_encodeBlockAsm4MB: + // emitCopy + CMPL DI, $0x00010000 + JB two_byte_offset_repeat_as_copy_encodeBlockAsm4MB + CMPL SI, $0x40 + JBE four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB + MOVB $0xff, (CX) + MOVL DI, 1(CX) + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 + JB four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy + CMPL SI, $0x00010100 + JB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB: + TESTL SI, SI + JZ repeat_end_emit_encodeBlockAsm4MB + XORL R8, R8 + LEAL -1(R8)(SI*4), SI + MOVB SI, (CX) + MOVL DI, 1(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +two_byte_offset_repeat_as_copy_encodeBlockAsm4MB: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm4MB + CMPL DI, $0x00000800 + JAE long_offset_short_repeat_as_copy_encodeBlockAsm4MB + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI + + // emitRepeat + LEAL -4(SI), SI + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + CMPL SI, $0x00010100 + JB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +long_offset_short_repeat_as_copy_encodeBlockAsm4MB: + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + CMPL SI, $0x00010100 + JB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm4MB: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm4MB + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm4MB + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm4MB + +emit_copy_three_repeat_as_copy_encodeBlockAsm4MB: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeBlockAsm4MB: + MOVL DX, 12(SP) + JMP search_loop_encodeBlockAsm4MB + +no_repeat_found_encodeBlockAsm4MB: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBlockAsm4MB + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeBlockAsm4MB + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeBlockAsm4MB + MOVL 20(SP), DX + JMP search_loop_encodeBlockAsm4MB + +candidate3_match_encodeBlockAsm4MB: + ADDL $0x02, DX + JMP candidate_match_encodeBlockAsm4MB + +candidate2_match_encodeBlockAsm4MB: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeBlockAsm4MB: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBlockAsm4MB + +match_extend_back_loop_encodeBlockAsm4MB: + CMPL DX, DI + JBE match_extend_back_end_encodeBlockAsm4MB + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBlockAsm4MB + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBlockAsm4MB + JMP match_extend_back_loop_encodeBlockAsm4MB + +match_extend_back_end_encodeBlockAsm4MB: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 4(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm4MB: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeBlockAsm4MB + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeBlockAsm4MB + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeBlockAsm4MB + CMPL R8, $0x00010000 + JB three_bytes_match_emit_encodeBlockAsm4MB + MOVL R8, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW R8, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_encodeBlockAsm4MB + +three_bytes_match_emit_encodeBlockAsm4MB: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBlockAsm4MB + +two_bytes_match_emit_encodeBlockAsm4MB: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeBlockAsm4MB + JMP memmove_long_match_emit_encodeBlockAsm4MB + +one_byte_match_emit_encodeBlockAsm4MB: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBlockAsm4MB: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBlockAsm4MB: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeBlockAsm4MB + +memmove_long_match_emit_encodeBlockAsm4MB: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeBlockAsm4MB: +match_nolit_loop_encodeBlockAsm4MB: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeBlockAsm4MB: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeBlockAsm4MB + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm4MB + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeBlockAsm4MB + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm4MB + +matchlen_bsf_16match_nolit_encodeBlockAsm4MB: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm4MB + +matchlen_match8_match_nolit_encodeBlockAsm4MB: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeBlockAsm4MB + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm4MB + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeBlockAsm4MB + +matchlen_bsf_8_match_nolit_encodeBlockAsm4MB: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm4MB + +matchlen_match4_match_nolit_encodeBlockAsm4MB: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeBlockAsm4MB + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeBlockAsm4MB + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeBlockAsm4MB: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeBlockAsm4MB + JB match_nolit_end_encodeBlockAsm4MB + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeBlockAsm4MB + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeBlockAsm4MB + +matchlen_match1_match_nolit_encodeBlockAsm4MB: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeBlockAsm4MB + LEAL 1(R10), R10 + +match_nolit_end_encodeBlockAsm4MB: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL SI, $0x00010000 + JB two_byte_offset_match_nolit_encodeBlockAsm4MB + CMPL R10, $0x40 + JBE four_bytes_remain_match_nolit_encodeBlockAsm4MB + MOVB $0xff, (CX) + MOVL SI, 1(CX) + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 + JB four_bytes_remain_match_nolit_encodeBlockAsm4MB + + // emitRepeat + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy + CMPL R10, $0x00010100 + JB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy: + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +four_bytes_remain_match_nolit_encodeBlockAsm4MB: + TESTL R10, R10 + JZ match_nolit_emitcopy_end_encodeBlockAsm4MB + XORL DI, DI + LEAL -1(DI)(R10*4), R10 + MOVB R10, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +two_byte_offset_match_nolit_encodeBlockAsm4MB: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBlockAsm4MB + CMPL SI, $0x00000800 + JAE long_offset_short_match_nolit_encodeBlockAsm4MB + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + CMPL R10, $0x00010100 + JB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +long_offset_short_match_nolit_encodeBlockAsm4MB: + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + + // emitRepeat + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short + CMPL R10, $0x00010100 + JB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short: + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +two_byte_offset_short_match_nolit_encodeBlockAsm4MB: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeBlockAsm4MB + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBlockAsm4MB + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +emit_copy_three_match_nolit_encodeBlockAsm4MB: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeBlockAsm4MB: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBlockAsm4MB + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm4MB: + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeBlockAsm4MB + INCL DX + JMP search_loop_encodeBlockAsm4MB + +emit_remainder_encodeBlockAsm4MB: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 4(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm4MB: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBlockAsm4MB + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBlockAsm4MB + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBlockAsm4MB + CMPL DX, $0x00010000 + JB three_bytes_emit_remainder_encodeBlockAsm4MB + MOVL DX, BX + SHRL $0x10, BX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_encodeBlockAsm4MB + +three_bytes_emit_remainder_encodeBlockAsm4MB: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBlockAsm4MB + +two_bytes_emit_remainder_encodeBlockAsm4MB: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBlockAsm4MB + JMP memmove_long_emit_remainder_encodeBlockAsm4MB + +one_byte_emit_remainder_encodeBlockAsm4MB: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBlockAsm4MB: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBlockAsm4MB: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBlockAsm4MB + +memmove_long_emit_remainder_encodeBlockAsm4MB: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBlockAsm4MB: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000080, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBlockAsm12B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBlockAsm12B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBlockAsm12B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBlockAsm12B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x18, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + SHLQ $0x18, R11 + IMULQ R9, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x18, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeBlockAsm12B + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI + JZ repeat_extend_back_end_encodeBlockAsm12B + +repeat_extend_back_loop_encodeBlockAsm12B: + CMPL DI, R8 + JBE repeat_extend_back_end_encodeBlockAsm12B + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeBlockAsm12B + LEAL -1(DI), DI + DECL SI + JNZ repeat_extend_back_loop_encodeBlockAsm12B + +repeat_extend_back_end_encodeBlockAsm12B: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm12B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeBlockAsm12B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeBlockAsm12B + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeBlockAsm12B + JB three_bytes_repeat_emit_encodeBlockAsm12B + +three_bytes_repeat_emit_encodeBlockAsm12B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeBlockAsm12B + +two_bytes_repeat_emit_encodeBlockAsm12B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeBlockAsm12B + JMP memmove_long_repeat_emit_encodeBlockAsm12B + +one_byte_repeat_emit_encodeBlockAsm12B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_repeat_emit_encodeBlockAsm12B: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeBlockAsm12B + +memmove_long_repeat_emit_encodeBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 + JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeBlockAsm12B: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm12B: + CMPL R9, $0x10 + JB matchlen_match8_repeat_extend_encodeBlockAsm12B + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm12B + XORQ 8(SI)(R12*1), R13 + JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm12B + LEAL -16(R9), R9 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm12B + +matchlen_bsf_16repeat_extend_encodeBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm12B + +matchlen_match8_repeat_extend_encodeBlockAsm12B: + CMPL R9, $0x08 + JB matchlen_match4_repeat_extend_encodeBlockAsm12B + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm12B + LEAL -8(R9), R9 + LEAL 8(R12), R12 + JMP matchlen_match4_repeat_extend_encodeBlockAsm12B + +matchlen_bsf_8_repeat_extend_encodeBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm12B + +matchlen_match4_repeat_extend_encodeBlockAsm12B: + CMPL R9, $0x04 + JB matchlen_match2_repeat_extend_encodeBlockAsm12B + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 + JNE matchlen_match2_repeat_extend_encodeBlockAsm12B + LEAL -4(R9), R9 + LEAL 4(R12), R12 + +matchlen_match2_repeat_extend_encodeBlockAsm12B: + CMPL R9, $0x01 + JE matchlen_match1_repeat_extend_encodeBlockAsm12B + JB repeat_extend_forward_end_encodeBlockAsm12B + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 + JNE matchlen_match1_repeat_extend_encodeBlockAsm12B + LEAL 2(R12), R12 + SUBL $0x02, R9 + JZ repeat_extend_forward_end_encodeBlockAsm12B + +matchlen_match1_repeat_extend_encodeBlockAsm12B: + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 + JNE repeat_extend_forward_end_encodeBlockAsm12B + LEAL 1(R12), R12 + +repeat_extend_forward_end_encodeBlockAsm12B: + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 + JZ repeat_as_copy_encodeBlockAsm12B + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_match_repeat_encodeBlockAsm12B + CMPL R8, $0x0c + JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm12B + CMPL DI, $0x00000800 + JB repeat_two_offset_match_repeat_encodeBlockAsm12B + +cant_repeat_two_offset_match_repeat_encodeBlockAsm12B: + CMPL SI, $0x00000104 + JB repeat_three_match_repeat_encodeBlockAsm12B + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_three_match_repeat_encodeBlockAsm12B: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_match_repeat_encodeBlockAsm12B: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_offset_match_repeat_encodeBlockAsm12B: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_as_copy_encodeBlockAsm12B: + // emitCopy + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm12B + CMPL DI, $0x00000800 + JAE long_offset_short_repeat_as_copy_encodeBlockAsm12B + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI + + // emitRepeat + LEAL -4(SI), SI + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +long_offset_short_repeat_as_copy_encodeBlockAsm12B: + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm12B: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm12B + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm12B + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm12B + +emit_copy_three_repeat_as_copy_encodeBlockAsm12B: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeBlockAsm12B: + MOVL DX, 12(SP) + JMP search_loop_encodeBlockAsm12B + +no_repeat_found_encodeBlockAsm12B: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBlockAsm12B + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeBlockAsm12B + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeBlockAsm12B + MOVL 20(SP), DX + JMP search_loop_encodeBlockAsm12B + +candidate3_match_encodeBlockAsm12B: + ADDL $0x02, DX + JMP candidate_match_encodeBlockAsm12B + +candidate2_match_encodeBlockAsm12B: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeBlockAsm12B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBlockAsm12B + +match_extend_back_loop_encodeBlockAsm12B: + CMPL DX, DI + JBE match_extend_back_end_encodeBlockAsm12B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBlockAsm12B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBlockAsm12B + JMP match_extend_back_loop_encodeBlockAsm12B + +match_extend_back_end_encodeBlockAsm12B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm12B: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeBlockAsm12B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeBlockAsm12B + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeBlockAsm12B + JB three_bytes_match_emit_encodeBlockAsm12B + +three_bytes_match_emit_encodeBlockAsm12B: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBlockAsm12B + +two_bytes_match_emit_encodeBlockAsm12B: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeBlockAsm12B + JMP memmove_long_match_emit_encodeBlockAsm12B + +one_byte_match_emit_encodeBlockAsm12B: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBlockAsm12B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeBlockAsm12B + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm12B + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm12B + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBlockAsm12B: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeBlockAsm12B + +memmove_long_match_emit_encodeBlockAsm12B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeBlockAsm12B: +match_nolit_loop_encodeBlockAsm12B: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeBlockAsm12B: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeBlockAsm12B + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm12B + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeBlockAsm12B + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm12B + +matchlen_bsf_16match_nolit_encodeBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm12B + +matchlen_match8_match_nolit_encodeBlockAsm12B: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeBlockAsm12B + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm12B + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm12B + +matchlen_match4_match_nolit_encodeBlockAsm12B: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeBlockAsm12B + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeBlockAsm12B + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeBlockAsm12B: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeBlockAsm12B + JB match_nolit_end_encodeBlockAsm12B + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeBlockAsm12B + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeBlockAsm12B + +matchlen_match1_match_nolit_encodeBlockAsm12B: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeBlockAsm12B + LEAL 1(R10), R10 + +match_nolit_end_encodeBlockAsm12B: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBlockAsm12B + CMPL SI, $0x00000800 + JAE long_offset_short_match_nolit_encodeBlockAsm12B + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +long_offset_short_match_nolit_encodeBlockAsm12B: + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + + // emitRepeat + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +two_byte_offset_short_match_nolit_encodeBlockAsm12B: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeBlockAsm12B + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBlockAsm12B + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +emit_copy_three_match_nolit_encodeBlockAsm12B: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeBlockAsm12B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBlockAsm12B + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm12B: + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x18, R8 + IMULQ R9, R8 + SHRQ $0x34, R8 + SHLQ $0x18, SI + IMULQ R9, SI + SHRQ $0x34, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeBlockAsm12B + INCL DX + JMP search_loop_encodeBlockAsm12B + +emit_remainder_encodeBlockAsm12B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm12B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBlockAsm12B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBlockAsm12B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBlockAsm12B + JB three_bytes_emit_remainder_encodeBlockAsm12B + +three_bytes_emit_remainder_encodeBlockAsm12B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBlockAsm12B + +two_bytes_emit_remainder_encodeBlockAsm12B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBlockAsm12B + JMP memmove_long_emit_remainder_encodeBlockAsm12B + +one_byte_emit_remainder_encodeBlockAsm12B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBlockAsm12B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBlockAsm12B + +memmove_long_emit_remainder_encodeBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBlockAsm12B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000020, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBlockAsm10B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBlockAsm10B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBlockAsm10B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBlockAsm10B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeBlockAsm10B + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI + JZ repeat_extend_back_end_encodeBlockAsm10B + +repeat_extend_back_loop_encodeBlockAsm10B: + CMPL DI, R8 + JBE repeat_extend_back_end_encodeBlockAsm10B + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeBlockAsm10B + LEAL -1(DI), DI + DECL SI + JNZ repeat_extend_back_loop_encodeBlockAsm10B + +repeat_extend_back_end_encodeBlockAsm10B: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm10B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeBlockAsm10B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeBlockAsm10B + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeBlockAsm10B + JB three_bytes_repeat_emit_encodeBlockAsm10B + +three_bytes_repeat_emit_encodeBlockAsm10B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeBlockAsm10B + +two_bytes_repeat_emit_encodeBlockAsm10B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeBlockAsm10B + JMP memmove_long_repeat_emit_encodeBlockAsm10B + +one_byte_repeat_emit_encodeBlockAsm10B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_repeat_emit_encodeBlockAsm10B: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeBlockAsm10B + +memmove_long_repeat_emit_encodeBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 + JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeBlockAsm10B: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm10B: + CMPL R9, $0x10 + JB matchlen_match8_repeat_extend_encodeBlockAsm10B + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm10B + XORQ 8(SI)(R12*1), R13 + JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm10B + LEAL -16(R9), R9 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm10B + +matchlen_bsf_16repeat_extend_encodeBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm10B + +matchlen_match8_repeat_extend_encodeBlockAsm10B: + CMPL R9, $0x08 + JB matchlen_match4_repeat_extend_encodeBlockAsm10B + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm10B + LEAL -8(R9), R9 + LEAL 8(R12), R12 + JMP matchlen_match4_repeat_extend_encodeBlockAsm10B + +matchlen_bsf_8_repeat_extend_encodeBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm10B + +matchlen_match4_repeat_extend_encodeBlockAsm10B: + CMPL R9, $0x04 + JB matchlen_match2_repeat_extend_encodeBlockAsm10B + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 + JNE matchlen_match2_repeat_extend_encodeBlockAsm10B + LEAL -4(R9), R9 + LEAL 4(R12), R12 + +matchlen_match2_repeat_extend_encodeBlockAsm10B: + CMPL R9, $0x01 + JE matchlen_match1_repeat_extend_encodeBlockAsm10B + JB repeat_extend_forward_end_encodeBlockAsm10B + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 + JNE matchlen_match1_repeat_extend_encodeBlockAsm10B + LEAL 2(R12), R12 + SUBL $0x02, R9 + JZ repeat_extend_forward_end_encodeBlockAsm10B + +matchlen_match1_repeat_extend_encodeBlockAsm10B: + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 + JNE repeat_extend_forward_end_encodeBlockAsm10B + LEAL 1(R12), R12 + +repeat_extend_forward_end_encodeBlockAsm10B: + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 + JZ repeat_as_copy_encodeBlockAsm10B + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_match_repeat_encodeBlockAsm10B + CMPL R8, $0x0c + JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm10B + CMPL DI, $0x00000800 + JB repeat_two_offset_match_repeat_encodeBlockAsm10B + +cant_repeat_two_offset_match_repeat_encodeBlockAsm10B: + CMPL SI, $0x00000104 + JB repeat_three_match_repeat_encodeBlockAsm10B + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_three_match_repeat_encodeBlockAsm10B: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_match_repeat_encodeBlockAsm10B: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_offset_match_repeat_encodeBlockAsm10B: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_as_copy_encodeBlockAsm10B: + // emitCopy + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm10B + CMPL DI, $0x00000800 + JAE long_offset_short_repeat_as_copy_encodeBlockAsm10B + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI + + // emitRepeat + LEAL -4(SI), SI + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +long_offset_short_repeat_as_copy_encodeBlockAsm10B: + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + + // emitRepeat + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + CMPL R8, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + CMPL DI, $0x00000800 + JB repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm10B: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm10B + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm10B + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm10B + +emit_copy_three_repeat_as_copy_encodeBlockAsm10B: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeBlockAsm10B: + MOVL DX, 12(SP) + JMP search_loop_encodeBlockAsm10B + +no_repeat_found_encodeBlockAsm10B: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBlockAsm10B + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeBlockAsm10B + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeBlockAsm10B + MOVL 20(SP), DX + JMP search_loop_encodeBlockAsm10B + +candidate3_match_encodeBlockAsm10B: + ADDL $0x02, DX + JMP candidate_match_encodeBlockAsm10B + +candidate2_match_encodeBlockAsm10B: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeBlockAsm10B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBlockAsm10B + +match_extend_back_loop_encodeBlockAsm10B: + CMPL DX, DI + JBE match_extend_back_end_encodeBlockAsm10B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBlockAsm10B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBlockAsm10B + JMP match_extend_back_loop_encodeBlockAsm10B + +match_extend_back_end_encodeBlockAsm10B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm10B: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeBlockAsm10B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeBlockAsm10B + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeBlockAsm10B + JB three_bytes_match_emit_encodeBlockAsm10B + +three_bytes_match_emit_encodeBlockAsm10B: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBlockAsm10B + +two_bytes_match_emit_encodeBlockAsm10B: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeBlockAsm10B + JMP memmove_long_match_emit_encodeBlockAsm10B + +one_byte_match_emit_encodeBlockAsm10B: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBlockAsm10B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeBlockAsm10B + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm10B + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm10B + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBlockAsm10B: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeBlockAsm10B + +memmove_long_match_emit_encodeBlockAsm10B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeBlockAsm10B: +match_nolit_loop_encodeBlockAsm10B: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeBlockAsm10B: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeBlockAsm10B + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm10B + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeBlockAsm10B + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm10B + +matchlen_bsf_16match_nolit_encodeBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm10B + +matchlen_match8_match_nolit_encodeBlockAsm10B: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeBlockAsm10B + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm10B + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm10B + +matchlen_match4_match_nolit_encodeBlockAsm10B: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeBlockAsm10B + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeBlockAsm10B + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeBlockAsm10B: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeBlockAsm10B + JB match_nolit_end_encodeBlockAsm10B + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeBlockAsm10B + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeBlockAsm10B + +matchlen_match1_match_nolit_encodeBlockAsm10B: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeBlockAsm10B + LEAL 1(R10), R10 + +match_nolit_end_encodeBlockAsm10B: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBlockAsm10B + CMPL SI, $0x00000800 + JAE long_offset_short_match_nolit_encodeBlockAsm10B + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +long_offset_short_match_nolit_encodeBlockAsm10B: + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + + // emitRepeat + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short + CMPL SI, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short: + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +two_byte_offset_short_match_nolit_encodeBlockAsm10B: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeBlockAsm10B + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBlockAsm10B + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +emit_copy_three_match_nolit_encodeBlockAsm10B: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeBlockAsm10B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBlockAsm10B + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm10B: + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x36, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x36, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeBlockAsm10B + INCL DX + JMP search_loop_encodeBlockAsm10B + +emit_remainder_encodeBlockAsm10B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm10B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBlockAsm10B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBlockAsm10B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBlockAsm10B + JB three_bytes_emit_remainder_encodeBlockAsm10B + +three_bytes_emit_remainder_encodeBlockAsm10B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBlockAsm10B + +two_bytes_emit_remainder_encodeBlockAsm10B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBlockAsm10B + JMP memmove_long_emit_remainder_encodeBlockAsm10B + +one_byte_emit_remainder_encodeBlockAsm10B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBlockAsm10B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBlockAsm10B + +memmove_long_emit_remainder_encodeBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBlockAsm10B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000008, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBlockAsm8B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBlockAsm8B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBlockAsm8B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBlockAsm8B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x38, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x38, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeBlockAsm8B + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI + JZ repeat_extend_back_end_encodeBlockAsm8B + +repeat_extend_back_loop_encodeBlockAsm8B: + CMPL DI, R8 + JBE repeat_extend_back_end_encodeBlockAsm8B + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeBlockAsm8B + LEAL -1(DI), DI + DECL SI + JNZ repeat_extend_back_loop_encodeBlockAsm8B + +repeat_extend_back_end_encodeBlockAsm8B: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm8B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeBlockAsm8B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeBlockAsm8B + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeBlockAsm8B + JB three_bytes_repeat_emit_encodeBlockAsm8B + +three_bytes_repeat_emit_encodeBlockAsm8B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeBlockAsm8B + +two_bytes_repeat_emit_encodeBlockAsm8B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeBlockAsm8B + JMP memmove_long_repeat_emit_encodeBlockAsm8B + +one_byte_repeat_emit_encodeBlockAsm8B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeBlockAsm8B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_repeat_emit_encodeBlockAsm8B: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeBlockAsm8B + +memmove_long_repeat_emit_encodeBlockAsm8B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 + JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeBlockAsm8B: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm8B: + CMPL R9, $0x10 + JB matchlen_match8_repeat_extend_encodeBlockAsm8B + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm8B + XORQ 8(SI)(R12*1), R13 + JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm8B + LEAL -16(R9), R9 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm8B + +matchlen_bsf_16repeat_extend_encodeBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm8B + +matchlen_match8_repeat_extend_encodeBlockAsm8B: + CMPL R9, $0x08 + JB matchlen_match4_repeat_extend_encodeBlockAsm8B + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 + JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm8B + LEAL -8(R9), R9 + LEAL 8(R12), R12 + JMP matchlen_match4_repeat_extend_encodeBlockAsm8B + +matchlen_bsf_8_repeat_extend_encodeBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm8B + +matchlen_match4_repeat_extend_encodeBlockAsm8B: + CMPL R9, $0x04 + JB matchlen_match2_repeat_extend_encodeBlockAsm8B + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 + JNE matchlen_match2_repeat_extend_encodeBlockAsm8B + LEAL -4(R9), R9 + LEAL 4(R12), R12 + +matchlen_match2_repeat_extend_encodeBlockAsm8B: + CMPL R9, $0x01 + JE matchlen_match1_repeat_extend_encodeBlockAsm8B + JB repeat_extend_forward_end_encodeBlockAsm8B + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 + JNE matchlen_match1_repeat_extend_encodeBlockAsm8B + LEAL 2(R12), R12 + SUBL $0x02, R9 + JZ repeat_extend_forward_end_encodeBlockAsm8B + +matchlen_match1_repeat_extend_encodeBlockAsm8B: + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 + JNE repeat_extend_forward_end_encodeBlockAsm8B + LEAL 1(R12), R12 + +repeat_extend_forward_end_encodeBlockAsm8B: + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 + JZ repeat_as_copy_encodeBlockAsm8B + + // emitRepeat + MOVL SI, DI + LEAL -4(SI), SI + CMPL DI, $0x08 + JBE repeat_two_match_repeat_encodeBlockAsm8B + CMPL DI, $0x0c + JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm8B + +cant_repeat_two_offset_match_repeat_encodeBlockAsm8B: + CMPL SI, $0x00000104 + JB repeat_three_match_repeat_encodeBlockAsm8B + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_three_match_repeat_encodeBlockAsm8B: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_two_match_repeat_encodeBlockAsm8B: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_as_copy_encodeBlockAsm8B: + // emitCopy + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm8B + CMPL DI, $0x00000800 + JAE long_offset_short_repeat_as_copy_encodeBlockAsm8B + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI + + // emitRepeat + LEAL -4(SI), SI + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + MOVL SI, DI + LEAL -4(SI), SI + CMPL DI, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + CMPL DI, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + +long_offset_short_repeat_as_copy_encodeBlockAsm8B: + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + + // emitRepeat + MOVL SI, DI + LEAL -4(SI), SI + CMPL DI, $0x08 + JBE repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short + CMPL DI, $0x0c + JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: + CMPL SI, $0x00000104 + JB repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm8B: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeBlockAsm8B + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeBlockAsm8B + +emit_copy_three_repeat_as_copy_encodeBlockAsm8B: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeBlockAsm8B: + MOVL DX, 12(SP) + JMP search_loop_encodeBlockAsm8B + +no_repeat_found_encodeBlockAsm8B: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBlockAsm8B + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeBlockAsm8B + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeBlockAsm8B + MOVL 20(SP), DX + JMP search_loop_encodeBlockAsm8B + +candidate3_match_encodeBlockAsm8B: + ADDL $0x02, DX + JMP candidate_match_encodeBlockAsm8B + +candidate2_match_encodeBlockAsm8B: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeBlockAsm8B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBlockAsm8B + +match_extend_back_loop_encodeBlockAsm8B: + CMPL DX, DI + JBE match_extend_back_end_encodeBlockAsm8B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBlockAsm8B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBlockAsm8B + JMP match_extend_back_loop_encodeBlockAsm8B + +match_extend_back_end_encodeBlockAsm8B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm8B: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeBlockAsm8B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeBlockAsm8B + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeBlockAsm8B + JB three_bytes_match_emit_encodeBlockAsm8B + +three_bytes_match_emit_encodeBlockAsm8B: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBlockAsm8B + +two_bytes_match_emit_encodeBlockAsm8B: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeBlockAsm8B + JMP memmove_long_match_emit_encodeBlockAsm8B + +one_byte_match_emit_encodeBlockAsm8B: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBlockAsm8B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeBlockAsm8B + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm8B + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBlockAsm8B + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBlockAsm8B: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeBlockAsm8B + +memmove_long_match_emit_encodeBlockAsm8B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeBlockAsm8B: +match_nolit_loop_encodeBlockAsm8B: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeBlockAsm8B: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeBlockAsm8B + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm8B + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeBlockAsm8B + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm8B + +matchlen_bsf_16match_nolit_encodeBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm8B + +matchlen_match8_match_nolit_encodeBlockAsm8B: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeBlockAsm8B + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm8B + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm8B + +matchlen_match4_match_nolit_encodeBlockAsm8B: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeBlockAsm8B + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeBlockAsm8B + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeBlockAsm8B: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeBlockAsm8B + JB match_nolit_end_encodeBlockAsm8B + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeBlockAsm8B + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeBlockAsm8B + +matchlen_match1_match_nolit_encodeBlockAsm8B: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeBlockAsm8B + LEAL 1(R10), R10 + +match_nolit_end_encodeBlockAsm8B: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBlockAsm8B + CMPL SI, $0x00000800 + JAE long_offset_short_match_nolit_encodeBlockAsm8B + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + MOVL R10, SI + LEAL -4(R10), R10 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +long_offset_short_match_nolit_encodeBlockAsm8B: + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + + // emitRepeat + MOVL R10, SI + LEAL -4(R10), R10 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +two_byte_offset_short_match_nolit_encodeBlockAsm8B: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeBlockAsm8B + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +emit_copy_three_match_nolit_encodeBlockAsm8B: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeBlockAsm8B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBlockAsm8B + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm8B: + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x38, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x38, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeBlockAsm8B + INCL DX + JMP search_loop_encodeBlockAsm8B + +emit_remainder_encodeBlockAsm8B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm8B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBlockAsm8B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBlockAsm8B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBlockAsm8B + JB three_bytes_emit_remainder_encodeBlockAsm8B + +three_bytes_emit_remainder_encodeBlockAsm8B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBlockAsm8B + +two_bytes_emit_remainder_encodeBlockAsm8B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBlockAsm8B + JMP memmove_long_emit_remainder_encodeBlockAsm8B + +one_byte_emit_remainder_encodeBlockAsm8B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBlockAsm8B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBlockAsm8B + +memmove_long_emit_remainder_encodeBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBlockAsm8B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00001200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBetterBlockAsm: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBetterBlockAsm + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBetterBlockAsm: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + CMPL SI, $0x63 + JBE check_maxskip_ok_encodeBetterBlockAsm + LEAL 100(DX), SI + JMP check_maxskip_cont_encodeBetterBlockAsm + +check_maxskip_ok_encodeBetterBlockAsm: + LEAL 1(DX)(SI*1), SI + +check_maxskip_cont_encodeBetterBlockAsm: + CMPL SI, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL 524288(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 524288(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeBetterBlockAsm + CMPQ R11, DI + JNE no_short_found_encodeBetterBlockAsm + MOVL R8, SI + JMP candidate_match_encodeBetterBlockAsm + +no_short_found_encodeBetterBlockAsm: + CMPL R10, DI + JEQ candidate_match_encodeBetterBlockAsm + CMPL R11, DI + JEQ candidateS_match_encodeBetterBlockAsm + MOVL 20(SP), DX + JMP search_loop_encodeBetterBlockAsm + +candidateS_match_encodeBetterBlockAsm: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBetterBlockAsm + DECL DX + MOVL R8, SI + +candidate_match_encodeBetterBlockAsm: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBetterBlockAsm + +match_extend_back_loop_encodeBetterBlockAsm: + CMPL DX, DI + JBE match_extend_back_end_encodeBetterBlockAsm + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBetterBlockAsm + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBetterBlockAsm + JMP match_extend_back_loop_encodeBetterBlockAsm + +match_extend_back_end_encodeBetterBlockAsm: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeBetterBlockAsm + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm + +matchlen_match8_match_nolit_encodeBetterBlockAsm: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeBetterBlockAsm + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm + +matchlen_match4_match_nolit_encodeBetterBlockAsm: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeBetterBlockAsm + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeBetterBlockAsm + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeBetterBlockAsm: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeBetterBlockAsm + JB match_nolit_end_encodeBetterBlockAsm + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeBetterBlockAsm + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeBetterBlockAsm + +matchlen_match1_match_nolit_encodeBetterBlockAsm: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeBetterBlockAsm + LEAL 1(R12), R12 + +match_nolit_end_encodeBetterBlockAsm: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + CMPL 16(SP), R8 + JEQ match_is_repeat_encodeBetterBlockAsm + CMPL R12, $0x01 + JA match_length_ok_encodeBetterBlockAsm + CMPL R8, $0x0000ffff + JBE match_length_ok_encodeBetterBlockAsm + MOVL 20(SP), DX + INCL DX + JMP search_loop_encodeBetterBlockAsm + +match_length_ok_encodeBetterBlockAsm: + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeBetterBlockAsm + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeBetterBlockAsm + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeBetterBlockAsm + CMPL SI, $0x00010000 + JB three_bytes_match_emit_encodeBetterBlockAsm + CMPL SI, $0x01000000 + JB four_bytes_match_emit_encodeBetterBlockAsm + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm + +four_bytes_match_emit_encodeBetterBlockAsm: + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm + +three_bytes_match_emit_encodeBetterBlockAsm: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm + +two_bytes_match_emit_encodeBetterBlockAsm: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeBetterBlockAsm + JMP memmove_long_match_emit_encodeBetterBlockAsm + +one_byte_match_emit_encodeBetterBlockAsm: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBetterBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBetterBlockAsm: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeBetterBlockAsm + +memmove_long_match_emit_encodeBetterBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeBetterBlockAsm: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy + CMPL R8, $0x00010000 + JB two_byte_offset_match_nolit_encodeBetterBlockAsm + CMPL R12, $0x40 + JBE four_bytes_remain_match_nolit_encodeBetterBlockAsm + MOVB $0xff, (CX) + MOVL R8, 1(CX) + LEAL -64(R12), R12 + ADDQ $0x05, CX + CMPL R12, $0x04 + JB four_bytes_remain_match_nolit_encodeBetterBlockAsm + + // emitRepeat +emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy: + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy + CMPL R12, $0x0100ffff + JB repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy + +repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy: + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +four_bytes_remain_match_nolit_encodeBetterBlockAsm: + TESTL R12, R12 + JZ match_nolit_emitcopy_end_encodeBetterBlockAsm + XORL SI, SI + LEAL -1(SI)(R12*4), R12 + MOVB R12, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +two_byte_offset_match_nolit_encodeBetterBlockAsm: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm + CMPL R8, $0x00000800 + JAE long_offset_short_match_nolit_encodeBetterBlockAsm + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + MOVL R8, R9 + SHRL $0x08, R9 + SHLL $0x05, R9 + ORL R9, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 + + // emitRepeat + LEAL -4(R12), R12 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + +emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPL R12, $0x0100ffff + JB repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + +repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +long_offset_short_match_nolit_encodeBetterBlockAsm: + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + + // emitRepeat +emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short: + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPL R12, $0x0100ffff + JB repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short + +repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short: + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +emit_copy_three_match_nolit_encodeBetterBlockAsm: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +match_is_repeat_encodeBetterBlockAsm: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_repeat_encodeBetterBlockAsm + CMPL SI, $0x00000100 + JB two_bytes_match_emit_repeat_encodeBetterBlockAsm + CMPL SI, $0x00010000 + JB three_bytes_match_emit_repeat_encodeBetterBlockAsm + CMPL SI, $0x01000000 + JB four_bytes_match_emit_repeat_encodeBetterBlockAsm + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +four_bytes_match_emit_repeat_encodeBetterBlockAsm: + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +three_bytes_match_emit_repeat_encodeBetterBlockAsm: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +two_bytes_match_emit_repeat_encodeBetterBlockAsm: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_repeat_encodeBetterBlockAsm + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +one_byte_match_emit_repeat_encodeBetterBlockAsm: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_repeat_encodeBetterBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm: + MOVQ SI, CX + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm + +memmove_long_match_emit_repeat_encodeBetterBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitRepeat +emit_repeat_again_match_nolit_repeat_encodeBetterBlockAsm: + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_repeat_encodeBetterBlockAsm + CMPL R12, $0x0100ffff + JB repeat_five_match_nolit_repeat_encodeBetterBlockAsm + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX + JMP emit_repeat_again_match_nolit_repeat_encodeBetterBlockAsm + +repeat_five_match_nolit_repeat_encodeBetterBlockAsm: + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_repeat_encodeBetterBlockAsm: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + +match_nolit_emitcopy_end_encodeBetterBlockAsm: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm: + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x32, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x2f, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x32, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 524288(AX)(R11*4) + MOVL R14, 524288(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeBetterBlockAsm: + CMPQ R8, R9 + JAE search_loop_encodeBetterBlockAsm + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x2f, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeBetterBlockAsm + +emit_remainder_encodeBetterBlockAsm: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBetterBlockAsm + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBetterBlockAsm + CMPL DX, $0x00010000 + JB three_bytes_emit_remainder_encodeBetterBlockAsm + CMPL DX, $0x01000000 + JB four_bytes_emit_remainder_encodeBetterBlockAsm + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +four_bytes_emit_remainder_encodeBetterBlockAsm: + MOVL DX, BX + SHRL $0x10, BX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +three_bytes_emit_remainder_encodeBetterBlockAsm: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +two_bytes_emit_remainder_encodeBetterBlockAsm: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBetterBlockAsm + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +one_byte_emit_remainder_encodeBetterBlockAsm: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBetterBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm + +memmove_long_emit_remainder_encodeBetterBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBetterBlockAsm: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBetterBlockAsm4MB(dst []byte, src []byte, tmp *[589824]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm4MB(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00001200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBetterBlockAsm4MB: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBetterBlockAsm4MB + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBetterBlockAsm4MB: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + CMPL SI, $0x63 + JBE check_maxskip_ok_encodeBetterBlockAsm4MB + LEAL 100(DX), SI + JMP check_maxskip_cont_encodeBetterBlockAsm4MB + +check_maxskip_ok_encodeBetterBlockAsm4MB: + LEAL 1(DX)(SI*1), SI + +check_maxskip_cont_encodeBetterBlockAsm4MB: + CMPL SI, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm4MB + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL 524288(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 524288(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeBetterBlockAsm4MB + CMPQ R11, DI + JNE no_short_found_encodeBetterBlockAsm4MB + MOVL R8, SI + JMP candidate_match_encodeBetterBlockAsm4MB + +no_short_found_encodeBetterBlockAsm4MB: + CMPL R10, DI + JEQ candidate_match_encodeBetterBlockAsm4MB + CMPL R11, DI + JEQ candidateS_match_encodeBetterBlockAsm4MB + MOVL 20(SP), DX + JMP search_loop_encodeBetterBlockAsm4MB + +candidateS_match_encodeBetterBlockAsm4MB: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBetterBlockAsm4MB + DECL DX + MOVL R8, SI + +candidate_match_encodeBetterBlockAsm4MB: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBetterBlockAsm4MB + +match_extend_back_loop_encodeBetterBlockAsm4MB: + CMPL DX, DI + JBE match_extend_back_end_encodeBetterBlockAsm4MB + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBetterBlockAsm4MB + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBetterBlockAsm4MB + JMP match_extend_back_loop_encodeBetterBlockAsm4MB + +match_extend_back_end_encodeBetterBlockAsm4MB: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 4(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBetterBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm4MB: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeBetterBlockAsm4MB + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm4MB + +matchlen_match8_match_nolit_encodeBetterBlockAsm4MB: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeBetterBlockAsm4MB + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm4MB + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm4MB + +matchlen_match4_match_nolit_encodeBetterBlockAsm4MB: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeBetterBlockAsm4MB + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeBetterBlockAsm4MB + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeBetterBlockAsm4MB: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeBetterBlockAsm4MB + JB match_nolit_end_encodeBetterBlockAsm4MB + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeBetterBlockAsm4MB + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeBetterBlockAsm4MB + +matchlen_match1_match_nolit_encodeBetterBlockAsm4MB: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeBetterBlockAsm4MB + LEAL 1(R12), R12 + +match_nolit_end_encodeBetterBlockAsm4MB: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + CMPL 16(SP), R8 + JEQ match_is_repeat_encodeBetterBlockAsm4MB + CMPL R12, $0x01 + JA match_length_ok_encodeBetterBlockAsm4MB + CMPL R8, $0x0000ffff + JBE match_length_ok_encodeBetterBlockAsm4MB + MOVL 20(SP), DX + INCL DX + JMP search_loop_encodeBetterBlockAsm4MB + +match_length_ok_encodeBetterBlockAsm4MB: + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeBetterBlockAsm4MB + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeBetterBlockAsm4MB + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeBetterBlockAsm4MB + CMPL SI, $0x00010000 + JB three_bytes_match_emit_encodeBetterBlockAsm4MB + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm4MB + +three_bytes_match_emit_encodeBetterBlockAsm4MB: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm4MB + +two_bytes_match_emit_encodeBetterBlockAsm4MB: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeBetterBlockAsm4MB + JMP memmove_long_match_emit_encodeBetterBlockAsm4MB + +one_byte_match_emit_encodeBetterBlockAsm4MB: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBetterBlockAsm4MB: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBetterBlockAsm4MB: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeBetterBlockAsm4MB + +memmove_long_match_emit_encodeBetterBlockAsm4MB: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeBetterBlockAsm4MB: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy + CMPL R8, $0x00010000 + JB two_byte_offset_match_nolit_encodeBetterBlockAsm4MB + CMPL R12, $0x40 + JBE four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB + MOVB $0xff, (CX) + MOVL R8, 1(CX) + LEAL -64(R12), R12 + ADDQ $0x05, CX + CMPL R12, $0x04 + JB four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB: + TESTL R12, R12 + JZ match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + XORL SI, SI + LEAL -1(SI)(R12*4), R12 + MOVB R12, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +two_byte_offset_match_nolit_encodeBetterBlockAsm4MB: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm4MB + CMPL R8, $0x00000800 + JAE long_offset_short_match_nolit_encodeBetterBlockAsm4MB + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 + + // emitRepeat + LEAL -4(R12), R12 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +long_offset_short_match_nolit_encodeBetterBlockAsm4MB: + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm4MB: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm4MB + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm4MB + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +emit_copy_three_match_nolit_encodeBetterBlockAsm4MB: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +match_is_repeat_encodeBetterBlockAsm4MB: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_repeat_encodeBetterBlockAsm4MB + CMPL SI, $0x00000100 + JB two_bytes_match_emit_repeat_encodeBetterBlockAsm4MB + CMPL SI, $0x00010000 + JB three_bytes_match_emit_repeat_encodeBetterBlockAsm4MB + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB + +three_bytes_match_emit_repeat_encodeBetterBlockAsm4MB: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB + +two_bytes_match_emit_repeat_encodeBetterBlockAsm4MB: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_repeat_encodeBetterBlockAsm4MB + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB + +one_byte_match_emit_repeat_encodeBetterBlockAsm4MB: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_repeat_encodeBetterBlockAsm4MB: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB: + MOVQ SI, CX + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB + +memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_big_loop_back + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm4MB + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm4MB + CMPL R12, $0x00010100 + JB repeat_four_match_nolit_repeat_encodeBetterBlockAsm4MB + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_repeat_encodeBetterBlockAsm4MB: + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm4MB: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm4MB: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + +match_nolit_emitcopy_end_encodeBetterBlockAsm4MB: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm4MB + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBetterBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm4MB: + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x32, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x2f, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x32, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 524288(AX)(R11*4) + MOVL R14, 524288(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeBetterBlockAsm4MB: + CMPQ R8, R9 + JAE search_loop_encodeBetterBlockAsm4MB + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x2f, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeBetterBlockAsm4MB + +emit_remainder_encodeBetterBlockAsm4MB: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 4(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBetterBlockAsm4MB + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm4MB: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBetterBlockAsm4MB + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBetterBlockAsm4MB + CMPL DX, $0x00010000 + JB three_bytes_emit_remainder_encodeBetterBlockAsm4MB + MOVL DX, BX + SHRL $0x10, BX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB + +three_bytes_emit_remainder_encodeBetterBlockAsm4MB: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB + +two_bytes_emit_remainder_encodeBetterBlockAsm4MB: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBetterBlockAsm4MB + JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB + +one_byte_emit_remainder_encodeBetterBlockAsm4MB: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBetterBlockAsm4MB: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB + +memmove_long_emit_remainder_encodeBetterBlockAsm4MB: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000280, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBetterBlockAsm12B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBetterBlockAsm12B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBetterBlockAsm12B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm12B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL 65536(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 65536(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeBetterBlockAsm12B + CMPQ R11, DI + JNE no_short_found_encodeBetterBlockAsm12B + MOVL R8, SI + JMP candidate_match_encodeBetterBlockAsm12B + +no_short_found_encodeBetterBlockAsm12B: + CMPL R10, DI + JEQ candidate_match_encodeBetterBlockAsm12B + CMPL R11, DI + JEQ candidateS_match_encodeBetterBlockAsm12B + MOVL 20(SP), DX + JMP search_loop_encodeBetterBlockAsm12B + +candidateS_match_encodeBetterBlockAsm12B: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBetterBlockAsm12B + DECL DX + MOVL R8, SI + +candidate_match_encodeBetterBlockAsm12B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBetterBlockAsm12B + +match_extend_back_loop_encodeBetterBlockAsm12B: + CMPL DX, DI + JBE match_extend_back_end_encodeBetterBlockAsm12B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBetterBlockAsm12B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBetterBlockAsm12B + JMP match_extend_back_loop_encodeBetterBlockAsm12B + +match_extend_back_end_encodeBetterBlockAsm12B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBetterBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm12B: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeBetterBlockAsm12B + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm12B + +matchlen_match8_match_nolit_encodeBetterBlockAsm12B: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeBetterBlockAsm12B + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm12B + +matchlen_match4_match_nolit_encodeBetterBlockAsm12B: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeBetterBlockAsm12B + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeBetterBlockAsm12B + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeBetterBlockAsm12B: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeBetterBlockAsm12B + JB match_nolit_end_encodeBetterBlockAsm12B + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeBetterBlockAsm12B + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeBetterBlockAsm12B + +matchlen_match1_match_nolit_encodeBetterBlockAsm12B: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeBetterBlockAsm12B + LEAL 1(R12), R12 + +match_nolit_end_encodeBetterBlockAsm12B: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + CMPL 16(SP), R8 + JEQ match_is_repeat_encodeBetterBlockAsm12B + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeBetterBlockAsm12B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeBetterBlockAsm12B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeBetterBlockAsm12B + JB three_bytes_match_emit_encodeBetterBlockAsm12B + +three_bytes_match_emit_encodeBetterBlockAsm12B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm12B + +two_bytes_match_emit_encodeBetterBlockAsm12B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeBetterBlockAsm12B + JMP memmove_long_match_emit_encodeBetterBlockAsm12B + +one_byte_match_emit_encodeBetterBlockAsm12B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBetterBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBetterBlockAsm12B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeBetterBlockAsm12B + +memmove_long_match_emit_encodeBetterBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeBetterBlockAsm12B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm12B + CMPL R8, $0x00000800 + JAE long_offset_short_match_nolit_encodeBetterBlockAsm12B + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 + + // emitRepeat + LEAL -4(R12), R12 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +long_offset_short_match_nolit_encodeBetterBlockAsm12B: + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm12B: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm12B + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm12B + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +emit_copy_three_match_nolit_encodeBetterBlockAsm12B: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +match_is_repeat_encodeBetterBlockAsm12B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_repeat_encodeBetterBlockAsm12B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_repeat_encodeBetterBlockAsm12B + JB three_bytes_match_emit_repeat_encodeBetterBlockAsm12B + +three_bytes_match_emit_repeat_encodeBetterBlockAsm12B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm12B + +two_bytes_match_emit_repeat_encodeBetterBlockAsm12B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_repeat_encodeBetterBlockAsm12B + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm12B + +one_byte_match_emit_repeat_encodeBetterBlockAsm12B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_repeat_encodeBetterBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B + +memmove_long_match_emit_repeat_encodeBetterBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm12B + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm12B + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm12B: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm12B: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + +match_nolit_emitcopy_end_encodeBetterBlockAsm12B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm12B + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBetterBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm12B: + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x34, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x32, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x34, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 65536(AX)(R11*4) + MOVL R14, 65536(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeBetterBlockAsm12B: + CMPQ R8, R9 + JAE search_loop_encodeBetterBlockAsm12B + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x32, R10 + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeBetterBlockAsm12B + +emit_remainder_encodeBetterBlockAsm12B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBetterBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm12B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm12B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBetterBlockAsm12B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBetterBlockAsm12B + JB three_bytes_emit_remainder_encodeBetterBlockAsm12B + +three_bytes_emit_remainder_encodeBetterBlockAsm12B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm12B + +two_bytes_emit_remainder_encodeBetterBlockAsm12B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBetterBlockAsm12B + JMP memmove_long_emit_remainder_encodeBetterBlockAsm12B + +one_byte_emit_remainder_encodeBetterBlockAsm12B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBetterBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm12B + +memmove_long_emit_remainder_encodeBetterBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBetterBlockAsm12B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x000000a0, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBetterBlockAsm10B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBetterBlockAsm10B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBetterBlockAsm10B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm10B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL 16384(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 16384(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeBetterBlockAsm10B + CMPQ R11, DI + JNE no_short_found_encodeBetterBlockAsm10B + MOVL R8, SI + JMP candidate_match_encodeBetterBlockAsm10B + +no_short_found_encodeBetterBlockAsm10B: + CMPL R10, DI + JEQ candidate_match_encodeBetterBlockAsm10B + CMPL R11, DI + JEQ candidateS_match_encodeBetterBlockAsm10B + MOVL 20(SP), DX + JMP search_loop_encodeBetterBlockAsm10B + +candidateS_match_encodeBetterBlockAsm10B: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBetterBlockAsm10B + DECL DX + MOVL R8, SI + +candidate_match_encodeBetterBlockAsm10B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBetterBlockAsm10B + +match_extend_back_loop_encodeBetterBlockAsm10B: + CMPL DX, DI + JBE match_extend_back_end_encodeBetterBlockAsm10B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBetterBlockAsm10B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBetterBlockAsm10B + JMP match_extend_back_loop_encodeBetterBlockAsm10B + +match_extend_back_end_encodeBetterBlockAsm10B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBetterBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm10B: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeBetterBlockAsm10B + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm10B + +matchlen_match8_match_nolit_encodeBetterBlockAsm10B: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeBetterBlockAsm10B + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm10B + +matchlen_match4_match_nolit_encodeBetterBlockAsm10B: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeBetterBlockAsm10B + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeBetterBlockAsm10B + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeBetterBlockAsm10B: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeBetterBlockAsm10B + JB match_nolit_end_encodeBetterBlockAsm10B + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeBetterBlockAsm10B + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeBetterBlockAsm10B + +matchlen_match1_match_nolit_encodeBetterBlockAsm10B: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeBetterBlockAsm10B + LEAL 1(R12), R12 + +match_nolit_end_encodeBetterBlockAsm10B: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + CMPL 16(SP), R8 + JEQ match_is_repeat_encodeBetterBlockAsm10B + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeBetterBlockAsm10B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeBetterBlockAsm10B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeBetterBlockAsm10B + JB three_bytes_match_emit_encodeBetterBlockAsm10B + +three_bytes_match_emit_encodeBetterBlockAsm10B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm10B + +two_bytes_match_emit_encodeBetterBlockAsm10B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeBetterBlockAsm10B + JMP memmove_long_match_emit_encodeBetterBlockAsm10B + +one_byte_match_emit_encodeBetterBlockAsm10B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBetterBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBetterBlockAsm10B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeBetterBlockAsm10B + +memmove_long_match_emit_encodeBetterBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeBetterBlockAsm10B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm10B + CMPL R8, $0x00000800 + JAE long_offset_short_match_nolit_encodeBetterBlockAsm10B + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 + + // emitRepeat + LEAL -4(R12), R12 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +long_offset_short_match_nolit_encodeBetterBlockAsm10B: + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm10B: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm10B + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm10B + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +emit_copy_three_match_nolit_encodeBetterBlockAsm10B: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +match_is_repeat_encodeBetterBlockAsm10B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_repeat_encodeBetterBlockAsm10B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_repeat_encodeBetterBlockAsm10B + JB three_bytes_match_emit_repeat_encodeBetterBlockAsm10B + +three_bytes_match_emit_repeat_encodeBetterBlockAsm10B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm10B + +two_bytes_match_emit_repeat_encodeBetterBlockAsm10B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_repeat_encodeBetterBlockAsm10B + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm10B + +one_byte_match_emit_repeat_encodeBetterBlockAsm10B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_repeat_encodeBetterBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B + +memmove_long_match_emit_repeat_encodeBetterBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm10B + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B + CMPL R8, $0x00000800 + JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm10B + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm10B: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm10B: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B: + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + +match_nolit_emitcopy_end_encodeBetterBlockAsm10B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm10B + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBetterBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm10B: + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x36, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x34, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x36, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 16384(AX)(R11*4) + MOVL R14, 16384(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeBetterBlockAsm10B: + CMPQ R8, R9 + JAE search_loop_encodeBetterBlockAsm10B + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x34, R10 + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeBetterBlockAsm10B + +emit_remainder_encodeBetterBlockAsm10B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBetterBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm10B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm10B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBetterBlockAsm10B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBetterBlockAsm10B + JB three_bytes_emit_remainder_encodeBetterBlockAsm10B + +three_bytes_emit_remainder_encodeBetterBlockAsm10B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm10B + +two_bytes_emit_remainder_encodeBetterBlockAsm10B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBetterBlockAsm10B + JMP memmove_long_emit_remainder_encodeBetterBlockAsm10B + +one_byte_emit_remainder_encodeBetterBlockAsm10B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBetterBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm10B + +memmove_long_emit_remainder_encodeBetterBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBetterBlockAsm10B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000028, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeBetterBlockAsm8B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeBetterBlockAsm8B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeBetterBlockAsm8B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm8B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL 4096(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 4096(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeBetterBlockAsm8B + CMPQ R11, DI + JNE no_short_found_encodeBetterBlockAsm8B + MOVL R8, SI + JMP candidate_match_encodeBetterBlockAsm8B + +no_short_found_encodeBetterBlockAsm8B: + CMPL R10, DI + JEQ candidate_match_encodeBetterBlockAsm8B + CMPL R11, DI + JEQ candidateS_match_encodeBetterBlockAsm8B + MOVL 20(SP), DX + JMP search_loop_encodeBetterBlockAsm8B + +candidateS_match_encodeBetterBlockAsm8B: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeBetterBlockAsm8B + DECL DX + MOVL R8, SI + +candidate_match_encodeBetterBlockAsm8B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeBetterBlockAsm8B + +match_extend_back_loop_encodeBetterBlockAsm8B: + CMPL DX, DI + JBE match_extend_back_end_encodeBetterBlockAsm8B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeBetterBlockAsm8B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeBetterBlockAsm8B + JMP match_extend_back_loop_encodeBetterBlockAsm8B + +match_extend_back_end_encodeBetterBlockAsm8B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeBetterBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm8B: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeBetterBlockAsm8B + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm8B + +matchlen_match8_match_nolit_encodeBetterBlockAsm8B: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeBetterBlockAsm8B + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm8B + +matchlen_match4_match_nolit_encodeBetterBlockAsm8B: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeBetterBlockAsm8B + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeBetterBlockAsm8B + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeBetterBlockAsm8B: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeBetterBlockAsm8B + JB match_nolit_end_encodeBetterBlockAsm8B + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeBetterBlockAsm8B + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeBetterBlockAsm8B + +matchlen_match1_match_nolit_encodeBetterBlockAsm8B: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeBetterBlockAsm8B + LEAL 1(R12), R12 + +match_nolit_end_encodeBetterBlockAsm8B: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + CMPL 16(SP), R8 + JEQ match_is_repeat_encodeBetterBlockAsm8B + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeBetterBlockAsm8B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeBetterBlockAsm8B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeBetterBlockAsm8B + JB three_bytes_match_emit_encodeBetterBlockAsm8B + +three_bytes_match_emit_encodeBetterBlockAsm8B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeBetterBlockAsm8B + +two_bytes_match_emit_encodeBetterBlockAsm8B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeBetterBlockAsm8B + JMP memmove_long_match_emit_encodeBetterBlockAsm8B + +one_byte_match_emit_encodeBetterBlockAsm8B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeBetterBlockAsm8B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x04 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4 + CMPQ R9, $0x08 + JB emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4through7 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4: + MOVL (R10), R11 + MOVL R11, (CX) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4through7: + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeBetterBlockAsm8B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeBetterBlockAsm8B + +memmove_long_match_emit_encodeBetterBlockAsm8B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeBetterBlockAsm8B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm8B + CMPL R8, $0x00000800 + JAE long_offset_short_match_nolit_encodeBetterBlockAsm8B + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 + + // emitRepeat + LEAL -4(R12), R12 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +long_offset_short_match_nolit_encodeBetterBlockAsm8B: + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm8B: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeBetterBlockAsm8B + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +emit_copy_three_match_nolit_encodeBetterBlockAsm8B: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +match_is_repeat_encodeBetterBlockAsm8B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_match_emit_repeat_encodeBetterBlockAsm8B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_repeat_encodeBetterBlockAsm8B + JB three_bytes_match_emit_repeat_encodeBetterBlockAsm8B + +three_bytes_match_emit_repeat_encodeBetterBlockAsm8B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm8B + +two_bytes_match_emit_repeat_encodeBetterBlockAsm8B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_repeat_encodeBetterBlockAsm8B + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm8B + +one_byte_match_emit_repeat_encodeBetterBlockAsm8B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_repeat_encodeBetterBlockAsm8B: + LEAQ (CX)(R8*1), SI + + // genMemMoveShort + CMPQ R8, $0x04 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4 + CMPQ R8, $0x08 + JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4through7 + CMPQ R8, $0x10 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4: + MOVL (R9), R10 + MOVL R10, (CX) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4through7: + MOVL (R9), R10 + MOVL -4(R9)(R8*1), R9 + MOVL R10, (CX) + MOVL R9, -4(CX)(R8*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_8through16: + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_17through32: + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_33through64: + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B + +memmove_long_match_emit_repeat_encodeBetterBlockAsm8B: + LEAQ (CX)(R8*1), SI + + // genMemMoveLong + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R13 + SUBQ R10, R13 + DECQ R11 + JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(R9)(R13*1), R10 + LEAQ -32(CX)(R13*1), R14 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R10 + ADDQ $0x20, R13 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(R9)(R13*1), X4 + MOVOU -16(R9)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R8, R13 + JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitRepeat + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 + JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm8B + CMPL SI, $0x0c + JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm8B + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm8B: + CMPL R12, $0x00000104 + JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm8B + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm8B: + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm8B: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX + +match_nolit_emitcopy_end_encodeBetterBlockAsm8B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeBetterBlockAsm8B + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBetterBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm8B: + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x38, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x36, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x38, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 4096(AX)(R11*4) + MOVL R14, 4096(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeBetterBlockAsm8B: + CMPQ R8, R9 + JAE search_loop_encodeBetterBlockAsm8B + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x36, R10 + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeBetterBlockAsm8B + +emit_remainder_encodeBetterBlockAsm8B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeBetterBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm8B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm8B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeBetterBlockAsm8B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeBetterBlockAsm8B + JB three_bytes_emit_remainder_encodeBetterBlockAsm8B + +three_bytes_emit_remainder_encodeBetterBlockAsm8B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeBetterBlockAsm8B + +two_bytes_emit_remainder_encodeBetterBlockAsm8B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeBetterBlockAsm8B + JMP memmove_long_emit_remainder_encodeBetterBlockAsm8B + +one_byte_emit_remainder_encodeBetterBlockAsm8B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeBetterBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm8B + +memmove_long_emit_remainder_encodeBetterBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeBetterBlockAsm8B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBlockAsm: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBlockAsm + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBlockAsm: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeSnappyBlockAsm + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_encodeSnappyBlockAsm + +repeat_extend_back_loop_encodeSnappyBlockAsm: + CMPL DI, SI + JBE repeat_extend_back_end_encodeSnappyBlockAsm + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeSnappyBlockAsm + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_encodeSnappyBlockAsm + +repeat_extend_back_end_encodeSnappyBlockAsm: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 5(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeSnappyBlockAsm + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeSnappyBlockAsm + CMPL SI, $0x00010000 + JB three_bytes_repeat_emit_encodeSnappyBlockAsm + CMPL SI, $0x01000000 + JB four_bytes_repeat_emit_encodeSnappyBlockAsm + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +four_bytes_repeat_emit_encodeSnappyBlockAsm: + MOVL SI, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +three_bytes_repeat_emit_encodeSnappyBlockAsm: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +two_bytes_repeat_emit_encodeSnappyBlockAsm: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeSnappyBlockAsm + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +one_byte_repeat_emit_encodeSnappyBlockAsm: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeSnappyBlockAsm: + LEAQ (CX)(R8*1), SI + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8: + MOVQ (R9), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8through16: + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_17through32: + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_33through64: + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm + +memmove_long_repeat_emit_encodeSnappyBlockAsm: + LEAQ (CX)(R8*1), SI + + // genMemMoveLong + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 + JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm + JB repeat_extend_forward_end_encodeSnappyBlockAsm + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_encodeSnappyBlockAsm + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_encodeSnappyBlockAsm + LEAL 1(R11), R11 + +repeat_extend_forward_end_encodeSnappyBlockAsm: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy + CMPL DI, $0x00010000 + JB two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm + +four_bytes_loop_back_repeat_as_copy_encodeSnappyBlockAsm: + CMPL SI, $0x40 + JBE four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm + MOVB $0xff, (CX) + MOVL DI, 1(CX) + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 + JB four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm + JMP four_bytes_loop_back_repeat_as_copy_encodeSnappyBlockAsm + +four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm: + TESTL SI, SI + JZ repeat_end_emit_encodeSnappyBlockAsm + XORL R8, R8 + LEAL -1(R8)(SI*4), SI + MOVB SI, (CX) + MOVL DI, 1(CX) + ADDQ $0x05, CX + JMP repeat_end_emit_encodeSnappyBlockAsm + +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeSnappyBlockAsm + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeSnappyBlockAsm: + MOVL DX, 12(SP) + JMP search_loop_encodeSnappyBlockAsm + +no_repeat_found_encodeSnappyBlockAsm: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBlockAsm + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeSnappyBlockAsm + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeSnappyBlockAsm + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBlockAsm + +candidate3_match_encodeSnappyBlockAsm: + ADDL $0x02, DX + JMP candidate_match_encodeSnappyBlockAsm + +candidate2_match_encodeSnappyBlockAsm: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeSnappyBlockAsm: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBlockAsm + +match_extend_back_loop_encodeSnappyBlockAsm: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBlockAsm + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBlockAsm + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBlockAsm + JMP match_extend_back_loop_encodeSnappyBlockAsm + +match_extend_back_end_encodeSnappyBlockAsm: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeSnappyBlockAsm + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBlockAsm + CMPL R8, $0x00010000 + JB three_bytes_match_emit_encodeSnappyBlockAsm + CMPL R8, $0x01000000 + JB four_bytes_match_emit_encodeSnappyBlockAsm + MOVB $0xfc, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +four_bytes_match_emit_encodeSnappyBlockAsm: + MOVL R8, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW R8, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +three_bytes_match_emit_encodeSnappyBlockAsm: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +two_bytes_match_emit_encodeSnappyBlockAsm: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeSnappyBlockAsm + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +one_byte_match_emit_encodeSnappyBlockAsm: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBlockAsm: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm + +memmove_long_match_emit_encodeSnappyBlockAsm: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeSnappyBlockAsm: +match_nolit_loop_encodeSnappyBlockAsm: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBlockAsm + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm + +matchlen_match8_match_nolit_encodeSnappyBlockAsm: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBlockAsm + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm + +matchlen_match4_match_nolit_encodeSnappyBlockAsm: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBlockAsm + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBlockAsm + JB match_nolit_end_encodeSnappyBlockAsm + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeSnappyBlockAsm + +matchlen_match1_match_nolit_encodeSnappyBlockAsm: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeSnappyBlockAsm + LEAL 1(R10), R10 + +match_nolit_end_encodeSnappyBlockAsm: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL SI, $0x00010000 + JB two_byte_offset_match_nolit_encodeSnappyBlockAsm + +four_bytes_loop_back_match_nolit_encodeSnappyBlockAsm: + CMPL R10, $0x40 + JBE four_bytes_remain_match_nolit_encodeSnappyBlockAsm + MOVB $0xff, (CX) + MOVL SI, 1(CX) + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 + JB four_bytes_remain_match_nolit_encodeSnappyBlockAsm + JMP four_bytes_loop_back_match_nolit_encodeSnappyBlockAsm + +four_bytes_remain_match_nolit_encodeSnappyBlockAsm: + TESTL R10, R10 + JZ match_nolit_emitcopy_end_encodeSnappyBlockAsm + XORL DI, DI + LEAL -1(DI)(R10*4), R10 + MOVB R10, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm + +two_byte_offset_match_nolit_encodeSnappyBlockAsm: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm + +emit_copy_three_match_nolit_encodeSnappyBlockAsm: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBlockAsm: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm: + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeSnappyBlockAsm + INCL DX + JMP search_loop_encodeSnappyBlockAsm + +emit_remainder_encodeSnappyBlockAsm: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBlockAsm + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBlockAsm + CMPL DX, $0x00010000 + JB three_bytes_emit_remainder_encodeSnappyBlockAsm + CMPL DX, $0x01000000 + JB four_bytes_emit_remainder_encodeSnappyBlockAsm + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +four_bytes_emit_remainder_encodeSnappyBlockAsm: + MOVL DX, BX + SHRL $0x10, BX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +three_bytes_emit_remainder_encodeSnappyBlockAsm: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +two_bytes_emit_remainder_encodeSnappyBlockAsm: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBlockAsm + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +one_byte_emit_remainder_encodeSnappyBlockAsm: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm + +memmove_long_emit_remainder_encodeSnappyBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBlockAsm64K(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm64K(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBlockAsm64K: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBlockAsm64K + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBlockAsm64K: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm64K + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeSnappyBlockAsm64K + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_encodeSnappyBlockAsm64K + +repeat_extend_back_loop_encodeSnappyBlockAsm64K: + CMPL DI, SI + JBE repeat_extend_back_end_encodeSnappyBlockAsm64K + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeSnappyBlockAsm64K + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_encodeSnappyBlockAsm64K + +repeat_extend_back_end_encodeSnappyBlockAsm64K: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm64K: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeSnappyBlockAsm64K + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeSnappyBlockAsm64K + JB three_bytes_repeat_emit_encodeSnappyBlockAsm64K + +three_bytes_repeat_emit_encodeSnappyBlockAsm64K: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm64K + +two_bytes_repeat_emit_encodeSnappyBlockAsm64K: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeSnappyBlockAsm64K + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm64K + +one_byte_repeat_emit_encodeSnappyBlockAsm64K: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeSnappyBlockAsm64K: + LEAQ (CX)(R8*1), SI + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8: + MOVQ (R9), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8through16: + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_17through32: + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_33through64: + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K + +memmove_long_repeat_emit_encodeSnappyBlockAsm64K: + LEAQ (CX)(R8*1), SI + + // genMemMoveLong + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32: + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 + JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K + JB repeat_extend_forward_end_encodeSnappyBlockAsm64K + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_encodeSnappyBlockAsm64K + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_encodeSnappyBlockAsm64K + LEAL 1(R11), R11 + +repeat_extend_forward_end_encodeSnappyBlockAsm64K: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm64K: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm64K + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm64K + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm64K: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeSnappyBlockAsm64K + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeSnappyBlockAsm64K: + MOVL DX, 12(SP) + JMP search_loop_encodeSnappyBlockAsm64K + +no_repeat_found_encodeSnappyBlockAsm64K: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBlockAsm64K + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeSnappyBlockAsm64K + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeSnappyBlockAsm64K + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBlockAsm64K + +candidate3_match_encodeSnappyBlockAsm64K: + ADDL $0x02, DX + JMP candidate_match_encodeSnappyBlockAsm64K + +candidate2_match_encodeSnappyBlockAsm64K: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeSnappyBlockAsm64K: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBlockAsm64K + +match_extend_back_loop_encodeSnappyBlockAsm64K: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBlockAsm64K + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBlockAsm64K + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBlockAsm64K + JMP match_extend_back_loop_encodeSnappyBlockAsm64K + +match_extend_back_end_encodeSnappyBlockAsm64K: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm64K: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm64K + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeSnappyBlockAsm64K + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBlockAsm64K + JB three_bytes_match_emit_encodeSnappyBlockAsm64K + +three_bytes_match_emit_encodeSnappyBlockAsm64K: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm64K + +two_bytes_match_emit_encodeSnappyBlockAsm64K: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeSnappyBlockAsm64K + JMP memmove_long_match_emit_encodeSnappyBlockAsm64K + +one_byte_match_emit_encodeSnappyBlockAsm64K: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBlockAsm64K: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm64K: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm64K + +memmove_long_match_emit_encodeSnappyBlockAsm64K: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeSnappyBlockAsm64K: +match_nolit_loop_encodeSnappyBlockAsm64K: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBlockAsm64K + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm64K + +matchlen_match8_match_nolit_encodeSnappyBlockAsm64K: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBlockAsm64K + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm64K + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm64K + +matchlen_match4_match_nolit_encodeSnappyBlockAsm64K: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBlockAsm64K + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm64K + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm64K: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBlockAsm64K + JB match_nolit_end_encodeSnappyBlockAsm64K + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm64K + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeSnappyBlockAsm64K + +matchlen_match1_match_nolit_encodeSnappyBlockAsm64K: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeSnappyBlockAsm64K + LEAL 1(R10), R10 + +match_nolit_end_encodeSnappyBlockAsm64K: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm64K: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm64K + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm64K + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm64K: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm64K + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm64K + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm64K + +emit_copy_three_match_nolit_encodeSnappyBlockAsm64K: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBlockAsm64K: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm64K + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm64K: + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeSnappyBlockAsm64K + INCL DX + JMP search_loop_encodeSnappyBlockAsm64K + +emit_remainder_encodeSnappyBlockAsm64K: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm64K: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBlockAsm64K + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBlockAsm64K + JB three_bytes_emit_remainder_encodeSnappyBlockAsm64K + +three_bytes_emit_remainder_encodeSnappyBlockAsm64K: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm64K + +two_bytes_emit_remainder_encodeSnappyBlockAsm64K: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBlockAsm64K + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm64K + +one_byte_emit_remainder_encodeSnappyBlockAsm64K: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBlockAsm64K: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K + +memmove_long_emit_remainder_encodeSnappyBlockAsm64K: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000080, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBlockAsm12B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBlockAsm12B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBlockAsm12B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm12B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x18, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + SHLQ $0x18, R11 + IMULQ R9, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x18, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeSnappyBlockAsm12B + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_encodeSnappyBlockAsm12B + +repeat_extend_back_loop_encodeSnappyBlockAsm12B: + CMPL DI, SI + JBE repeat_extend_back_end_encodeSnappyBlockAsm12B + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeSnappyBlockAsm12B + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_encodeSnappyBlockAsm12B + +repeat_extend_back_end_encodeSnappyBlockAsm12B: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm12B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeSnappyBlockAsm12B + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeSnappyBlockAsm12B + JB three_bytes_repeat_emit_encodeSnappyBlockAsm12B + +three_bytes_repeat_emit_encodeSnappyBlockAsm12B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm12B + +two_bytes_repeat_emit_encodeSnappyBlockAsm12B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeSnappyBlockAsm12B + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm12B + +one_byte_repeat_emit_encodeSnappyBlockAsm12B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeSnappyBlockAsm12B: + LEAQ (CX)(R8*1), SI + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8: + MOVQ (R9), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8through16: + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_17through32: + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_33through64: + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B + +memmove_long_repeat_emit_encodeSnappyBlockAsm12B: + LEAQ (CX)(R8*1), SI + + // genMemMoveLong + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 + JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B + JB repeat_extend_forward_end_encodeSnappyBlockAsm12B + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_encodeSnappyBlockAsm12B + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_encodeSnappyBlockAsm12B + LEAL 1(R11), R11 + +repeat_extend_forward_end_encodeSnappyBlockAsm12B: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm12B: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm12B + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm12B + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm12B: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeSnappyBlockAsm12B + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeSnappyBlockAsm12B: + MOVL DX, 12(SP) + JMP search_loop_encodeSnappyBlockAsm12B + +no_repeat_found_encodeSnappyBlockAsm12B: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBlockAsm12B + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeSnappyBlockAsm12B + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeSnappyBlockAsm12B + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBlockAsm12B + +candidate3_match_encodeSnappyBlockAsm12B: + ADDL $0x02, DX + JMP candidate_match_encodeSnappyBlockAsm12B + +candidate2_match_encodeSnappyBlockAsm12B: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeSnappyBlockAsm12B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBlockAsm12B + +match_extend_back_loop_encodeSnappyBlockAsm12B: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBlockAsm12B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBlockAsm12B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBlockAsm12B + JMP match_extend_back_loop_encodeSnappyBlockAsm12B + +match_extend_back_end_encodeSnappyBlockAsm12B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm12B: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm12B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeSnappyBlockAsm12B + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBlockAsm12B + JB three_bytes_match_emit_encodeSnappyBlockAsm12B + +three_bytes_match_emit_encodeSnappyBlockAsm12B: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm12B + +two_bytes_match_emit_encodeSnappyBlockAsm12B: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeSnappyBlockAsm12B + JMP memmove_long_match_emit_encodeSnappyBlockAsm12B + +one_byte_match_emit_encodeSnappyBlockAsm12B: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBlockAsm12B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm12B: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm12B + +memmove_long_match_emit_encodeSnappyBlockAsm12B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeSnappyBlockAsm12B: +match_nolit_loop_encodeSnappyBlockAsm12B: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBlockAsm12B + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm12B + +matchlen_match8_match_nolit_encodeSnappyBlockAsm12B: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBlockAsm12B + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm12B + +matchlen_match4_match_nolit_encodeSnappyBlockAsm12B: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBlockAsm12B + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm12B + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm12B: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBlockAsm12B + JB match_nolit_end_encodeSnappyBlockAsm12B + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm12B + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeSnappyBlockAsm12B + +matchlen_match1_match_nolit_encodeSnappyBlockAsm12B: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeSnappyBlockAsm12B + LEAL 1(R10), R10 + +match_nolit_end_encodeSnappyBlockAsm12B: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm12B: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm12B + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm12B + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm12B: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm12B + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm12B + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm12B + +emit_copy_three_match_nolit_encodeSnappyBlockAsm12B: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBlockAsm12B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm12B + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm12B: + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x18, R8 + IMULQ R9, R8 + SHRQ $0x34, R8 + SHLQ $0x18, SI + IMULQ R9, SI + SHRQ $0x34, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeSnappyBlockAsm12B + INCL DX + JMP search_loop_encodeSnappyBlockAsm12B + +emit_remainder_encodeSnappyBlockAsm12B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm12B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBlockAsm12B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBlockAsm12B + JB three_bytes_emit_remainder_encodeSnappyBlockAsm12B + +three_bytes_emit_remainder_encodeSnappyBlockAsm12B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm12B + +two_bytes_emit_remainder_encodeSnappyBlockAsm12B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBlockAsm12B + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm12B + +one_byte_emit_remainder_encodeSnappyBlockAsm12B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B + +memmove_long_emit_remainder_encodeSnappyBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000020, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBlockAsm10B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBlockAsm10B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBlockAsm10B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm10B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeSnappyBlockAsm10B + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_encodeSnappyBlockAsm10B + +repeat_extend_back_loop_encodeSnappyBlockAsm10B: + CMPL DI, SI + JBE repeat_extend_back_end_encodeSnappyBlockAsm10B + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeSnappyBlockAsm10B + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_encodeSnappyBlockAsm10B + +repeat_extend_back_end_encodeSnappyBlockAsm10B: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm10B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeSnappyBlockAsm10B + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeSnappyBlockAsm10B + JB three_bytes_repeat_emit_encodeSnappyBlockAsm10B + +three_bytes_repeat_emit_encodeSnappyBlockAsm10B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm10B + +two_bytes_repeat_emit_encodeSnappyBlockAsm10B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeSnappyBlockAsm10B + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm10B + +one_byte_repeat_emit_encodeSnappyBlockAsm10B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeSnappyBlockAsm10B: + LEAQ (CX)(R8*1), SI + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8: + MOVQ (R9), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8through16: + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_17through32: + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_33through64: + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B + +memmove_long_repeat_emit_encodeSnappyBlockAsm10B: + LEAQ (CX)(R8*1), SI + + // genMemMoveLong + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 + JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B + JB repeat_extend_forward_end_encodeSnappyBlockAsm10B + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_encodeSnappyBlockAsm10B + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_encodeSnappyBlockAsm10B + LEAL 1(R11), R11 + +repeat_extend_forward_end_encodeSnappyBlockAsm10B: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm10B: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm10B + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm10B + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm10B: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeSnappyBlockAsm10B + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeSnappyBlockAsm10B: + MOVL DX, 12(SP) + JMP search_loop_encodeSnappyBlockAsm10B + +no_repeat_found_encodeSnappyBlockAsm10B: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBlockAsm10B + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeSnappyBlockAsm10B + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeSnappyBlockAsm10B + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBlockAsm10B + +candidate3_match_encodeSnappyBlockAsm10B: + ADDL $0x02, DX + JMP candidate_match_encodeSnappyBlockAsm10B + +candidate2_match_encodeSnappyBlockAsm10B: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeSnappyBlockAsm10B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBlockAsm10B + +match_extend_back_loop_encodeSnappyBlockAsm10B: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBlockAsm10B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBlockAsm10B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBlockAsm10B + JMP match_extend_back_loop_encodeSnappyBlockAsm10B + +match_extend_back_end_encodeSnappyBlockAsm10B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm10B: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm10B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeSnappyBlockAsm10B + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBlockAsm10B + JB three_bytes_match_emit_encodeSnappyBlockAsm10B + +three_bytes_match_emit_encodeSnappyBlockAsm10B: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm10B + +two_bytes_match_emit_encodeSnappyBlockAsm10B: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeSnappyBlockAsm10B + JMP memmove_long_match_emit_encodeSnappyBlockAsm10B + +one_byte_match_emit_encodeSnappyBlockAsm10B: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBlockAsm10B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm10B: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm10B + +memmove_long_match_emit_encodeSnappyBlockAsm10B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeSnappyBlockAsm10B: +match_nolit_loop_encodeSnappyBlockAsm10B: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBlockAsm10B + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm10B + +matchlen_match8_match_nolit_encodeSnappyBlockAsm10B: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBlockAsm10B + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm10B + +matchlen_match4_match_nolit_encodeSnappyBlockAsm10B: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBlockAsm10B + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm10B + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm10B: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBlockAsm10B + JB match_nolit_end_encodeSnappyBlockAsm10B + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm10B + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeSnappyBlockAsm10B + +matchlen_match1_match_nolit_encodeSnappyBlockAsm10B: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeSnappyBlockAsm10B + LEAL 1(R10), R10 + +match_nolit_end_encodeSnappyBlockAsm10B: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm10B: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm10B + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm10B + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm10B: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm10B + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm10B + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm10B + +emit_copy_three_match_nolit_encodeSnappyBlockAsm10B: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBlockAsm10B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm10B + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm10B: + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x36, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x36, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeSnappyBlockAsm10B + INCL DX + JMP search_loop_encodeSnappyBlockAsm10B + +emit_remainder_encodeSnappyBlockAsm10B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm10B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBlockAsm10B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBlockAsm10B + JB three_bytes_emit_remainder_encodeSnappyBlockAsm10B + +three_bytes_emit_remainder_encodeSnappyBlockAsm10B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm10B + +two_bytes_emit_remainder_encodeSnappyBlockAsm10B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBlockAsm10B + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm10B + +one_byte_emit_remainder_encodeSnappyBlockAsm10B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B + +memmove_long_emit_remainder_encodeSnappyBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000008, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBlockAsm8B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBlockAsm8B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBlockAsm8B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm8B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x38, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x38, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeSnappyBlockAsm8B + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_encodeSnappyBlockAsm8B + +repeat_extend_back_loop_encodeSnappyBlockAsm8B: + CMPL DI, SI + JBE repeat_extend_back_end_encodeSnappyBlockAsm8B + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_encodeSnappyBlockAsm8B + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_encodeSnappyBlockAsm8B + +repeat_extend_back_end_encodeSnappyBlockAsm8B: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm8B: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_encodeSnappyBlockAsm8B + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_encodeSnappyBlockAsm8B + JB three_bytes_repeat_emit_encodeSnappyBlockAsm8B + +three_bytes_repeat_emit_encodeSnappyBlockAsm8B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm8B + +two_bytes_repeat_emit_encodeSnappyBlockAsm8B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_encodeSnappyBlockAsm8B + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm8B + +one_byte_repeat_emit_encodeSnappyBlockAsm8B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_repeat_emit_encodeSnappyBlockAsm8B: + LEAQ (CX)(R8*1), SI + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8: + MOVQ (R9), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8through16: + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_17through32: + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_33through64: + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B: + MOVQ SI, CX + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B + +memmove_long_repeat_emit_encodeSnappyBlockAsm8B: + LEAQ (CX)(R8*1), SI + + // genMemMoveLong + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 + JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B + JB repeat_extend_forward_end_encodeSnappyBlockAsm8B + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_encodeSnappyBlockAsm8B + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_encodeSnappyBlockAsm8B + LEAL 1(R11), R11 + +repeat_extend_forward_end_encodeSnappyBlockAsm8B: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm8B: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm8B + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm8B + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm8B: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm8B + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + JMP repeat_end_emit_encodeSnappyBlockAsm8B + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm8B: + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX + +repeat_end_emit_encodeSnappyBlockAsm8B: + MOVL DX, 12(SP) + JMP search_loop_encodeSnappyBlockAsm8B + +no_repeat_found_encodeSnappyBlockAsm8B: + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBlockAsm8B + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_encodeSnappyBlockAsm8B + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_encodeSnappyBlockAsm8B + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBlockAsm8B + +candidate3_match_encodeSnappyBlockAsm8B: + ADDL $0x02, DX + JMP candidate_match_encodeSnappyBlockAsm8B + +candidate2_match_encodeSnappyBlockAsm8B: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_encodeSnappyBlockAsm8B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBlockAsm8B + +match_extend_back_loop_encodeSnappyBlockAsm8B: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBlockAsm8B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBlockAsm8B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBlockAsm8B + JMP match_extend_back_loop_encodeSnappyBlockAsm8B + +match_extend_back_end_encodeSnappyBlockAsm8B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm8B: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm8B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c + JB one_byte_match_emit_encodeSnappyBlockAsm8B + CMPL R8, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBlockAsm8B + JB three_bytes_match_emit_encodeSnappyBlockAsm8B + +three_bytes_match_emit_encodeSnappyBlockAsm8B: + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBlockAsm8B + +two_bytes_match_emit_encodeSnappyBlockAsm8B: + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 + JB memmove_match_emit_encodeSnappyBlockAsm8B + JMP memmove_long_match_emit_encodeSnappyBlockAsm8B + +one_byte_match_emit_encodeSnappyBlockAsm8B: + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBlockAsm8B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8: + MOVQ (DI), R10 + MOVQ R10, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8through16: + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_17through32: + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_33through64: + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm8B: + MOVQ R8, CX + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm8B + +memmove_long_match_emit_encodeSnappyBlockAsm8B: + LEAQ (CX)(R9*1), R8 + + // genMemMoveLong + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 + JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_big_loop_back: + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX + +emit_literal_done_match_emit_encodeSnappyBlockAsm8B: +match_nolit_loop_encodeSnappyBlockAsm8B: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBlockAsm8B + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm8B + +matchlen_match8_match_nolit_encodeSnappyBlockAsm8B: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBlockAsm8B + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm8B + +matchlen_match4_match_nolit_encodeSnappyBlockAsm8B: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBlockAsm8B + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm8B + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm8B: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBlockAsm8B + JB match_nolit_end_encodeSnappyBlockAsm8B + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm8B + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_encodeSnappyBlockAsm8B + +matchlen_match1_match_nolit_encodeSnappyBlockAsm8B: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_encodeSnappyBlockAsm8B + LEAL 1(R10), R10 + +match_nolit_end_encodeSnappyBlockAsm8B: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm8B: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm8B + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm8B + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm8B: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm8B + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm8B + +emit_copy_three_match_nolit_encodeSnappyBlockAsm8B: + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBlockAsm8B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBlockAsm8B + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm8B: + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x38, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x38, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_encodeSnappyBlockAsm8B + INCL DX + JMP search_loop_encodeSnappyBlockAsm8B + +emit_remainder_encodeSnappyBlockAsm8B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm8B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBlockAsm8B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBlockAsm8B + JB three_bytes_emit_remainder_encodeSnappyBlockAsm8B + +three_bytes_emit_remainder_encodeSnappyBlockAsm8B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm8B + +two_bytes_emit_remainder_encodeSnappyBlockAsm8B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBlockAsm8B + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm8B + +one_byte_emit_remainder_encodeSnappyBlockAsm8B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B + +memmove_long_emit_remainder_encodeSnappyBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00001200, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBetterBlockAsm: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBetterBlockAsm + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBetterBlockAsm: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + CMPL SI, $0x63 + JBE check_maxskip_ok_encodeSnappyBetterBlockAsm + LEAL 100(DX), SI + JMP check_maxskip_cont_encodeSnappyBetterBlockAsm + +check_maxskip_ok_encodeSnappyBetterBlockAsm: + LEAL 1(DX)(SI*1), SI + +check_maxskip_cont_encodeSnappyBetterBlockAsm: + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL 524288(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 524288(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm + CMPQ R11, DI + JNE no_short_found_encodeSnappyBetterBlockAsm + MOVL R8, SI + JMP candidate_match_encodeSnappyBetterBlockAsm + +no_short_found_encodeSnappyBetterBlockAsm: + CMPL R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm + CMPL R11, DI + JEQ candidateS_match_encodeSnappyBetterBlockAsm + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBetterBlockAsm + +candidateS_match_encodeSnappyBetterBlockAsm: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBetterBlockAsm + DECL DX + MOVL R8, SI + +candidate_match_encodeSnappyBetterBlockAsm: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm + +match_extend_back_loop_encodeSnappyBetterBlockAsm: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBetterBlockAsm + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBetterBlockAsm + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm + +match_extend_back_end_encodeSnappyBetterBlockAsm: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm + JB match_nolit_end_encodeSnappyBetterBlockAsm + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeSnappyBetterBlockAsm + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeSnappyBetterBlockAsm + LEAL 1(R12), R12 + +match_nolit_end_encodeSnappyBetterBlockAsm: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + CMPL R12, $0x01 + JA match_length_ok_encodeSnappyBetterBlockAsm + CMPL R8, $0x0000ffff + JBE match_length_ok_encodeSnappyBetterBlockAsm + MOVL 20(SP), DX + INCL DX + JMP search_loop_encodeSnappyBetterBlockAsm + +match_length_ok_encodeSnappyBetterBlockAsm: + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeSnappyBetterBlockAsm + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBetterBlockAsm + CMPL SI, $0x00010000 + JB three_bytes_match_emit_encodeSnappyBetterBlockAsm + CMPL SI, $0x01000000 + JB four_bytes_match_emit_encodeSnappyBetterBlockAsm + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +four_bytes_match_emit_encodeSnappyBetterBlockAsm: + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +three_bytes_match_emit_encodeSnappyBetterBlockAsm: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +two_bytes_match_emit_encodeSnappyBetterBlockAsm: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeSnappyBetterBlockAsm + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +one_byte_match_emit_encodeSnappyBetterBlockAsm: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBetterBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm + +memmove_long_match_emit_encodeSnappyBetterBlockAsm: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy + CMPL R8, $0x00010000 + JB two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm + +four_bytes_loop_back_match_nolit_encodeSnappyBetterBlockAsm: + CMPL R12, $0x40 + JBE four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm + MOVB $0xff, (CX) + MOVL R8, 1(CX) + LEAL -64(R12), R12 + ADDQ $0x05, CX + CMPL R12, $0x04 + JB four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm + JMP four_bytes_loop_back_match_nolit_encodeSnappyBetterBlockAsm + +four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm: + TESTL R12, R12 + JZ match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm + XORL SI, SI + LEAL -1(SI)(R12*4), R12 + MOVB R12, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm + +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm: + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x32, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x2f, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x32, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 524288(AX)(R11*4) + MOVL R14, 524288(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeSnappyBetterBlockAsm: + CMPQ R8, R9 + JAE search_loop_encodeSnappyBetterBlockAsm + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x2f, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeSnappyBetterBlockAsm + +emit_remainder_encodeSnappyBetterBlockAsm: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBetterBlockAsm + CMPL DX, $0x00010000 + JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm + CMPL DX, $0x01000000 + JB four_bytes_emit_remainder_encodeSnappyBetterBlockAsm + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +four_bytes_emit_remainder_encodeSnappyBetterBlockAsm: + MOVL DX, BX + SHRL $0x10, BX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBetterBlockAsm + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBetterBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte, tmp *[294912]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm64K(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000900, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBetterBlockAsm64K: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBetterBlockAsm64K + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBetterBlockAsm64K: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm64K + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x30, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x33, R11 + MOVL (AX)(R10*4), SI + MOVL 262144(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 262144(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm64K + CMPQ R11, DI + JNE no_short_found_encodeSnappyBetterBlockAsm64K + MOVL R8, SI + JMP candidate_match_encodeSnappyBetterBlockAsm64K + +no_short_found_encodeSnappyBetterBlockAsm64K: + CMPL R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm64K + CMPL R11, DI + JEQ candidateS_match_encodeSnappyBetterBlockAsm64K + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBetterBlockAsm64K + +candidateS_match_encodeSnappyBetterBlockAsm64K: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x30, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBetterBlockAsm64K + DECL DX + MOVL R8, SI + +candidate_match_encodeSnappyBetterBlockAsm64K: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm64K + +match_extend_back_loop_encodeSnappyBetterBlockAsm64K: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBetterBlockAsm64K + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBetterBlockAsm64K + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm64K + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm64K + +match_extend_back_end_encodeSnappyBetterBlockAsm64K: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBetterBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm64K: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm64K + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm64K + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K + JB match_nolit_end_encodeSnappyBetterBlockAsm64K + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeSnappyBetterBlockAsm64K + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeSnappyBetterBlockAsm64K + LEAL 1(R12), R12 + +match_nolit_end_encodeSnappyBetterBlockAsm64K: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeSnappyBetterBlockAsm64K + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBetterBlockAsm64K + JB three_bytes_match_emit_encodeSnappyBetterBlockAsm64K + +three_bytes_match_emit_encodeSnappyBetterBlockAsm64K: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm64K + +two_bytes_match_emit_encodeSnappyBetterBlockAsm64K: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeSnappyBetterBlockAsm64K + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm64K + +one_byte_match_emit_encodeSnappyBetterBlockAsm64K: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBetterBlockAsm64K: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K + +memmove_long_match_emit_encodeSnappyBetterBlockAsm64K: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm64K + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm64K + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm64K: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm64K + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm64K: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm64K + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm64K: + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x30, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x33, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x30, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x33, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 262144(AX)(R11*4) + MOVL R14, 262144(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeSnappyBetterBlockAsm64K: + CMPQ R8, R9 + JAE search_loop_encodeSnappyBetterBlockAsm64K + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x30, R10 + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x30, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeSnappyBetterBlockAsm64K + +emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBetterBlockAsm64K + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm64K: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm64K + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K + JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBetterBlockAsm64K + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm64K: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBetterBlockAsm64K: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000280, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBetterBlockAsm12B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBetterBlockAsm12B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBetterBlockAsm12B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm12B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL 65536(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 65536(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm12B + CMPQ R11, DI + JNE no_short_found_encodeSnappyBetterBlockAsm12B + MOVL R8, SI + JMP candidate_match_encodeSnappyBetterBlockAsm12B + +no_short_found_encodeSnappyBetterBlockAsm12B: + CMPL R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm12B + CMPL R11, DI + JEQ candidateS_match_encodeSnappyBetterBlockAsm12B + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBetterBlockAsm12B + +candidateS_match_encodeSnappyBetterBlockAsm12B: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBetterBlockAsm12B + DECL DX + MOVL R8, SI + +candidate_match_encodeSnappyBetterBlockAsm12B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm12B + +match_extend_back_loop_encodeSnappyBetterBlockAsm12B: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBetterBlockAsm12B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBetterBlockAsm12B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm12B + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm12B + +match_extend_back_end_encodeSnappyBetterBlockAsm12B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBetterBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm12B: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm12B + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm12B + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B + JB match_nolit_end_encodeSnappyBetterBlockAsm12B + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeSnappyBetterBlockAsm12B + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeSnappyBetterBlockAsm12B + LEAL 1(R12), R12 + +match_nolit_end_encodeSnappyBetterBlockAsm12B: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeSnappyBetterBlockAsm12B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBetterBlockAsm12B + JB three_bytes_match_emit_encodeSnappyBetterBlockAsm12B + +three_bytes_match_emit_encodeSnappyBetterBlockAsm12B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm12B + +two_bytes_match_emit_encodeSnappyBetterBlockAsm12B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeSnappyBetterBlockAsm12B + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm12B + +one_byte_match_emit_encodeSnappyBetterBlockAsm12B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBetterBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B + +memmove_long_match_emit_encodeSnappyBetterBlockAsm12B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm12B + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm12B + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm12B: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm12B + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm12B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm12B + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm12B: + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x34, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x32, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x34, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 65536(AX)(R11*4) + MOVL R14, 65536(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeSnappyBetterBlockAsm12B: + CMPQ R8, R9 + JAE search_loop_encodeSnappyBetterBlockAsm12B + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x32, R10 + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeSnappyBetterBlockAsm12B + +emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBetterBlockAsm12B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm12B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm12B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B + JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBetterBlockAsm12B + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm12B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBetterBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x000000a0, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBetterBlockAsm10B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBetterBlockAsm10B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBetterBlockAsm10B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm10B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL 16384(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 16384(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm10B + CMPQ R11, DI + JNE no_short_found_encodeSnappyBetterBlockAsm10B + MOVL R8, SI + JMP candidate_match_encodeSnappyBetterBlockAsm10B + +no_short_found_encodeSnappyBetterBlockAsm10B: + CMPL R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm10B + CMPL R11, DI + JEQ candidateS_match_encodeSnappyBetterBlockAsm10B + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBetterBlockAsm10B + +candidateS_match_encodeSnappyBetterBlockAsm10B: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBetterBlockAsm10B + DECL DX + MOVL R8, SI + +candidate_match_encodeSnappyBetterBlockAsm10B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm10B + +match_extend_back_loop_encodeSnappyBetterBlockAsm10B: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBetterBlockAsm10B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBetterBlockAsm10B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm10B + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm10B + +match_extend_back_end_encodeSnappyBetterBlockAsm10B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBetterBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm10B: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm10B + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm10B + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B + JB match_nolit_end_encodeSnappyBetterBlockAsm10B + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeSnappyBetterBlockAsm10B + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeSnappyBetterBlockAsm10B + LEAL 1(R12), R12 + +match_nolit_end_encodeSnappyBetterBlockAsm10B: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeSnappyBetterBlockAsm10B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBetterBlockAsm10B + JB three_bytes_match_emit_encodeSnappyBetterBlockAsm10B + +three_bytes_match_emit_encodeSnappyBetterBlockAsm10B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm10B + +two_bytes_match_emit_encodeSnappyBetterBlockAsm10B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeSnappyBetterBlockAsm10B + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm10B + +one_byte_match_emit_encodeSnappyBetterBlockAsm10B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBetterBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B + +memmove_long_match_emit_encodeSnappyBetterBlockAsm10B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm10B + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm10B + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm10B: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B + CMPL R8, $0x00000800 + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm10B + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm10B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm10B + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm10B: + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x36, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x34, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x36, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 16384(AX)(R11*4) + MOVL R14, 16384(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeSnappyBetterBlockAsm10B: + CMPQ R8, R9 + JAE search_loop_encodeSnappyBetterBlockAsm10B + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x34, R10 + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeSnappyBetterBlockAsm10B + +emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBetterBlockAsm10B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm10B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm10B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B + JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBetterBlockAsm10B + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm10B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBetterBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000028, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_encodeSnappyBetterBlockAsm8B: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_encodeSnappyBetterBlockAsm8B + MOVL $0x00000000, 12(SP) + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL $0x00000000, 16(SP) + MOVQ src_base+24(FP), BX + +search_loop_encodeSnappyBetterBlockAsm8B: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm8B + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL 4096(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 4096(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm8B + CMPQ R11, DI + JNE no_short_found_encodeSnappyBetterBlockAsm8B + MOVL R8, SI + JMP candidate_match_encodeSnappyBetterBlockAsm8B + +no_short_found_encodeSnappyBetterBlockAsm8B: + CMPL R10, DI + JEQ candidate_match_encodeSnappyBetterBlockAsm8B + CMPL R11, DI + JEQ candidateS_match_encodeSnappyBetterBlockAsm8B + MOVL 20(SP), DX + JMP search_loop_encodeSnappyBetterBlockAsm8B + +candidateS_match_encodeSnappyBetterBlockAsm8B: + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI + JEQ candidate_match_encodeSnappyBetterBlockAsm8B + DECL DX + MOVL R8, SI + +candidate_match_encodeSnappyBetterBlockAsm8B: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm8B + +match_extend_back_loop_encodeSnappyBetterBlockAsm8B: + CMPL DX, DI + JBE match_extend_back_end_encodeSnappyBetterBlockAsm8B + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_encodeSnappyBetterBlockAsm8B + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_encodeSnappyBetterBlockAsm8B + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm8B + +match_extend_back_end_encodeSnappyBetterBlockAsm8B: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_encodeSnappyBetterBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm8B: + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 + + // matchLen + XORL R12, R12 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPL R8, $0x10 + JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B + XORQ 8(R10)(R12*1), R13 + JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B + LEAL -16(R8), R8 + LEAL 16(R12), R12 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R13, R13 + +#else + BSFQ R13, R13 + +#endif + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm8B + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPL R8, $0x08 + JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 + JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B + LEAL -8(R8), R8 + LEAL 8(R12), R12 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm8B + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPL R8, $0x04 + JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B + LEAL -4(R8), R8 + LEAL 4(R12), R12 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPL R8, $0x01 + JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B + JB match_nolit_end_encodeSnappyBetterBlockAsm8B + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 + JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B + LEAL 2(R12), R12 + SUBL $0x02, R8 + JZ match_nolit_end_encodeSnappyBetterBlockAsm8B + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B: + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 + JNE match_nolit_end_encodeSnappyBetterBlockAsm8B + LEAL 1(R12), R12 + +match_nolit_end_encodeSnappyBetterBlockAsm8B: + MOVL DX, R8 + SUBL SI, R8 + + // Check if repeat + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c + JB one_byte_match_emit_encodeSnappyBetterBlockAsm8B + CMPL SI, $0x00000100 + JB two_bytes_match_emit_encodeSnappyBetterBlockAsm8B + JB three_bytes_match_emit_encodeSnappyBetterBlockAsm8B + +three_bytes_match_emit_encodeSnappyBetterBlockAsm8B: + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm8B + +two_bytes_match_emit_encodeSnappyBetterBlockAsm8B: + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_match_emit_encodeSnappyBetterBlockAsm8B + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm8B + +one_byte_match_emit_encodeSnappyBetterBlockAsm8B: + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX + +memmove_match_emit_encodeSnappyBetterBlockAsm8B: + LEAQ (CX)(R9*1), SI + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8: + MOVQ (R10), R11 + MOVQ R11, (CX) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8through16: + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_17through32: + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_33through64: + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B: + MOVQ SI, CX + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B + +memmove_long_match_emit_encodeSnappyBetterBlockAsm8B: + LEAQ (CX)(R9*1), SI + + // genMemMoveLong + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 + JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B: + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPL R12, $0x40 + JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm8B + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm8B + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm8B: + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c + JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm8B + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm8B + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm8B: + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm8B: + CMPL DX, 8(SP) + JAE emit_remainder_encodeSnappyBetterBlockAsm8B + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm8B: + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x38, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x36, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x38, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 4096(AX)(R11*4) + MOVL R14, 4096(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 + +index_loop_encodeSnappyBetterBlockAsm8B: + CMPQ R8, R9 + JAE search_loop_encodeSnappyBetterBlockAsm8B + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x36, R10 + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) + ADDQ $0x02, DI + ADDQ $0x02, R8 + JMP index_loop_encodeSnappyBetterBlockAsm8B + +emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_encodeSnappyBetterBlockAsm8B + MOVQ $0x00000000, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm8B: + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), DX + CMPL DX, $0x3c + JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm8B + CMPL DX, $0x00000100 + JB two_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B + JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX + CMPL DX, $0x40 + JB memmove_emit_remainder_encodeSnappyBetterBlockAsm8B + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm8B: + SHLB $0x02, DL + MOVB DL, (CX) + ADDQ $0x01, CX + +memmove_emit_remainder_encodeSnappyBetterBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveShort + CMPQ BX, $0x03 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_1or2 + JE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_3 + CMPQ BX, $0x08 + JB emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_4through7 + CMPQ BX, $0x10 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_8through16 + CMPQ BX, $0x20 + JBE emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_1or2: + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_3: + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_8through16: + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_17through32: + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVQ DX, CX + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B: + LEAQ (CX)(SI*1), DX + MOVL SI, BX + + // genMemMoveLong + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVQ BX, DI + SHRQ $0x05, DI + MOVQ CX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_back + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32: + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) + ADDQ $0x20, R8 + CMPQ BX, R8 + JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) + RET + +// func calcBlockSize(src []byte, tmp *[32768]byte) int +// Requires: BMI, SSE2 +TEXT ·calcBlockSize(SB), $24-40 + MOVQ tmp+24(FP), AX + XORQ CX, CX + MOVQ $0x00000100, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_calcBlockSize: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_calcBlockSize + MOVL $0x00000000, 12(SP) + MOVQ src_len+8(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+0(FP), BX + +search_loop_calcBlockSize: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_calcBlockSize + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x33, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x33, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x33, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_calcBlockSize + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_calcBlockSize + +repeat_extend_back_loop_calcBlockSize: + CMPL DI, SI + JBE repeat_extend_back_end_calcBlockSize + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_calcBlockSize + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_calcBlockSize + +repeat_extend_back_end_calcBlockSize: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 5(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_calcBlockSize + MOVQ $0x00000000, ret+32(FP) + RET + +repeat_dst_size_check_calcBlockSize: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_calcBlockSize + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_calcBlockSize + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_calcBlockSize + CMPL SI, $0x00010000 + JB three_bytes_repeat_emit_calcBlockSize + CMPL SI, $0x01000000 + JB four_bytes_repeat_emit_calcBlockSize + ADDQ $0x05, CX + JMP memmove_long_repeat_emit_calcBlockSize + +four_bytes_repeat_emit_calcBlockSize: + ADDQ $0x04, CX + JMP memmove_long_repeat_emit_calcBlockSize + +three_bytes_repeat_emit_calcBlockSize: + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_calcBlockSize + +two_bytes_repeat_emit_calcBlockSize: + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_calcBlockSize + JMP memmove_long_repeat_emit_calcBlockSize + +one_byte_repeat_emit_calcBlockSize: + ADDQ $0x01, CX + +memmove_repeat_emit_calcBlockSize: + LEAQ (CX)(R8*1), CX + JMP emit_literal_done_repeat_emit_calcBlockSize + +memmove_long_repeat_emit_calcBlockSize: + LEAQ (CX)(R8*1), CX + +emit_literal_done_repeat_emit_calcBlockSize: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+8(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_calcBlockSize: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_calcBlockSize + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_calcBlockSize + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_calcBlockSize + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_calcBlockSize + +matchlen_bsf_16repeat_extend_calcBlockSize: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_calcBlockSize + +matchlen_match8_repeat_extend_calcBlockSize: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_calcBlockSize + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_calcBlockSize + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_calcBlockSize + +matchlen_bsf_8_repeat_extend_calcBlockSize: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_calcBlockSize + +matchlen_match4_repeat_extend_calcBlockSize: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_calcBlockSize + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_calcBlockSize + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_calcBlockSize: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_calcBlockSize + JB repeat_extend_forward_end_calcBlockSize + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_calcBlockSize + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_calcBlockSize + +matchlen_match1_repeat_extend_calcBlockSize: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_calcBlockSize + LEAL 1(R11), R11 + +repeat_extend_forward_end_calcBlockSize: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy + CMPL DI, $0x00010000 + JB two_byte_offset_repeat_as_copy_calcBlockSize + +four_bytes_loop_back_repeat_as_copy_calcBlockSize: + CMPL SI, $0x40 + JBE four_bytes_remain_repeat_as_copy_calcBlockSize + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 + JB four_bytes_remain_repeat_as_copy_calcBlockSize + JMP four_bytes_loop_back_repeat_as_copy_calcBlockSize + +four_bytes_remain_repeat_as_copy_calcBlockSize: + TESTL SI, SI + JZ repeat_end_emit_calcBlockSize + XORL SI, SI + ADDQ $0x05, CX + JMP repeat_end_emit_calcBlockSize + +two_byte_offset_repeat_as_copy_calcBlockSize: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_calcBlockSize + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_calcBlockSize + +two_byte_offset_short_repeat_as_copy_calcBlockSize: + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_calcBlockSize + CMPL DI, $0x00000800 + JAE emit_copy_three_repeat_as_copy_calcBlockSize + ADDQ $0x02, CX + JMP repeat_end_emit_calcBlockSize + +emit_copy_three_repeat_as_copy_calcBlockSize: + ADDQ $0x03, CX + +repeat_end_emit_calcBlockSize: + MOVL DX, 12(SP) + JMP search_loop_calcBlockSize + +no_repeat_found_calcBlockSize: + CMPL (BX)(SI*1), DI + JEQ candidate_match_calcBlockSize + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_calcBlockSize + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_calcBlockSize + MOVL 20(SP), DX + JMP search_loop_calcBlockSize + +candidate3_match_calcBlockSize: + ADDL $0x02, DX + JMP candidate_match_calcBlockSize + +candidate2_match_calcBlockSize: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_calcBlockSize: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_calcBlockSize + +match_extend_back_loop_calcBlockSize: + CMPL DX, DI + JBE match_extend_back_end_calcBlockSize + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_calcBlockSize + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_calcBlockSize + JMP match_extend_back_loop_calcBlockSize + +match_extend_back_end_calcBlockSize: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_calcBlockSize + MOVQ $0x00000000, ret+32(FP) + RET + +match_dst_size_check_calcBlockSize: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_calcBlockSize + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), DI + CMPL DI, $0x3c + JB one_byte_match_emit_calcBlockSize + CMPL DI, $0x00000100 + JB two_bytes_match_emit_calcBlockSize + CMPL DI, $0x00010000 + JB three_bytes_match_emit_calcBlockSize + CMPL DI, $0x01000000 + JB four_bytes_match_emit_calcBlockSize + ADDQ $0x05, CX + JMP memmove_long_match_emit_calcBlockSize + +four_bytes_match_emit_calcBlockSize: + ADDQ $0x04, CX + JMP memmove_long_match_emit_calcBlockSize + +three_bytes_match_emit_calcBlockSize: + ADDQ $0x03, CX + JMP memmove_long_match_emit_calcBlockSize + +two_bytes_match_emit_calcBlockSize: + ADDQ $0x02, CX + CMPL DI, $0x40 + JB memmove_match_emit_calcBlockSize + JMP memmove_long_match_emit_calcBlockSize + +one_byte_match_emit_calcBlockSize: + ADDQ $0x01, CX + +memmove_match_emit_calcBlockSize: + LEAQ (CX)(R9*1), CX + JMP emit_literal_done_match_emit_calcBlockSize + +memmove_long_match_emit_calcBlockSize: + LEAQ (CX)(R9*1), CX + +emit_literal_done_match_emit_calcBlockSize: +match_nolit_loop_calcBlockSize: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+8(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_calcBlockSize: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_calcBlockSize + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_calcBlockSize + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_calcBlockSize + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_calcBlockSize + +matchlen_bsf_16match_nolit_calcBlockSize: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_calcBlockSize + +matchlen_match8_match_nolit_calcBlockSize: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_calcBlockSize + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_calcBlockSize + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_calcBlockSize + +matchlen_bsf_8_match_nolit_calcBlockSize: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_calcBlockSize + +matchlen_match4_match_nolit_calcBlockSize: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_calcBlockSize + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_calcBlockSize + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_calcBlockSize: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_calcBlockSize + JB match_nolit_end_calcBlockSize + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_calcBlockSize + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_calcBlockSize + +matchlen_match1_match_nolit_calcBlockSize: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_calcBlockSize + LEAL 1(R10), R10 + +match_nolit_end_calcBlockSize: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy + CMPL SI, $0x00010000 + JB two_byte_offset_match_nolit_calcBlockSize + +four_bytes_loop_back_match_nolit_calcBlockSize: + CMPL R10, $0x40 + JBE four_bytes_remain_match_nolit_calcBlockSize + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 + JB four_bytes_remain_match_nolit_calcBlockSize + JMP four_bytes_loop_back_match_nolit_calcBlockSize + +four_bytes_remain_match_nolit_calcBlockSize: + TESTL R10, R10 + JZ match_nolit_emitcopy_end_calcBlockSize + XORL SI, SI + ADDQ $0x05, CX + JMP match_nolit_emitcopy_end_calcBlockSize + +two_byte_offset_match_nolit_calcBlockSize: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_calcBlockSize + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_calcBlockSize + +two_byte_offset_short_match_nolit_calcBlockSize: + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_calcBlockSize + CMPL SI, $0x00000800 + JAE emit_copy_three_match_nolit_calcBlockSize + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_calcBlockSize + +emit_copy_three_match_nolit_calcBlockSize: + ADDQ $0x03, CX + +match_nolit_emitcopy_end_calcBlockSize: + CMPL DX, 8(SP) + JAE emit_remainder_calcBlockSize + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_calcBlockSize + MOVQ $0x00000000, ret+32(FP) + RET + +match_nolit_dst_ok_calcBlockSize: + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x33, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x33, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_calcBlockSize + INCL DX + JMP search_loop_calcBlockSize + +emit_remainder_calcBlockSize: + MOVQ src_len+8(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_calcBlockSize + MOVQ $0x00000000, ret+32(FP) + RET + +emit_remainder_ok_calcBlockSize: + MOVQ src_len+8(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_calcBlockSize + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), AX + CMPL AX, $0x3c + JB one_byte_emit_remainder_calcBlockSize + CMPL AX, $0x00000100 + JB two_bytes_emit_remainder_calcBlockSize + CMPL AX, $0x00010000 + JB three_bytes_emit_remainder_calcBlockSize + CMPL AX, $0x01000000 + JB four_bytes_emit_remainder_calcBlockSize + ADDQ $0x05, CX + JMP memmove_long_emit_remainder_calcBlockSize + +four_bytes_emit_remainder_calcBlockSize: + ADDQ $0x04, CX + JMP memmove_long_emit_remainder_calcBlockSize + +three_bytes_emit_remainder_calcBlockSize: + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_calcBlockSize + +two_bytes_emit_remainder_calcBlockSize: + ADDQ $0x02, CX + CMPL AX, $0x40 + JB memmove_emit_remainder_calcBlockSize + JMP memmove_long_emit_remainder_calcBlockSize + +one_byte_emit_remainder_calcBlockSize: + ADDQ $0x01, CX + +memmove_emit_remainder_calcBlockSize: + LEAQ (CX)(SI*1), AX + MOVQ AX, CX + JMP emit_literal_done_emit_remainder_calcBlockSize + +memmove_long_emit_remainder_calcBlockSize: + LEAQ (CX)(SI*1), AX + MOVQ AX, CX + +emit_literal_done_emit_remainder_calcBlockSize: + MOVQ CX, ret+32(FP) + RET + +// func calcBlockSizeSmall(src []byte, tmp *[2048]byte) int +// Requires: BMI, SSE2 +TEXT ·calcBlockSizeSmall(SB), $24-40 + MOVQ tmp+24(FP), AX + XORQ CX, CX + MOVQ $0x00000010, DX + MOVQ AX, BX + PXOR X0, X0 + +zero_loop_calcBlockSizeSmall: + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX + JNZ zero_loop_calcBlockSizeSmall + MOVL $0x00000000, 12(SP) + MOVQ src_len+8(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+0(FP), BX + +search_loop_calcBlockSizeSmall: + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) + JAE emit_remainder_calcBlockSizeSmall + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x37, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x37, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x37, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_calcBlockSizeSmall + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 + JZ repeat_extend_back_end_calcBlockSizeSmall + +repeat_extend_back_loop_calcBlockSizeSmall: + CMPL DI, SI + JBE repeat_extend_back_end_calcBlockSizeSmall + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 + JNE repeat_extend_back_end_calcBlockSizeSmall + LEAL -1(DI), DI + DECL R8 + JNZ repeat_extend_back_loop_calcBlockSizeSmall + +repeat_extend_back_end_calcBlockSizeSmall: + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) + JB repeat_dst_size_check_calcBlockSizeSmall + MOVQ $0x00000000, ret+32(FP) + RET + +repeat_dst_size_check_calcBlockSizeSmall: + MOVL 12(SP), SI + CMPL SI, DI + JEQ emit_literal_done_repeat_emit_calcBlockSizeSmall + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c + JB one_byte_repeat_emit_calcBlockSizeSmall + CMPL SI, $0x00000100 + JB two_bytes_repeat_emit_calcBlockSizeSmall + JB three_bytes_repeat_emit_calcBlockSizeSmall + +three_bytes_repeat_emit_calcBlockSizeSmall: + ADDQ $0x03, CX + JMP memmove_long_repeat_emit_calcBlockSizeSmall + +two_bytes_repeat_emit_calcBlockSizeSmall: + ADDQ $0x02, CX + CMPL SI, $0x40 + JB memmove_repeat_emit_calcBlockSizeSmall + JMP memmove_long_repeat_emit_calcBlockSizeSmall + +one_byte_repeat_emit_calcBlockSizeSmall: + ADDQ $0x01, CX + +memmove_repeat_emit_calcBlockSizeSmall: + LEAQ (CX)(R8*1), CX + JMP emit_literal_done_repeat_emit_calcBlockSizeSmall + +memmove_long_repeat_emit_calcBlockSizeSmall: + LEAQ (CX)(R8*1), CX + +emit_literal_done_repeat_emit_calcBlockSizeSmall: + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+8(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R11, R11 + +matchlen_loopback_16_repeat_extend_calcBlockSizeSmall: + CMPL R8, $0x10 + JB matchlen_match8_repeat_extend_calcBlockSizeSmall + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_calcBlockSizeSmall + XORQ 8(SI)(R11*1), R12 + JNZ matchlen_bsf_16repeat_extend_calcBlockSizeSmall + LEAL -16(R8), R8 + LEAL 16(R11), R11 + JMP matchlen_loopback_16_repeat_extend_calcBlockSizeSmall + +matchlen_bsf_16repeat_extend_calcBlockSizeSmall: +#ifdef GOAMD64_v3 + TZCNTQ R12, R12 + +#else + BSFQ R12, R12 + +#endif + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_calcBlockSizeSmall + +matchlen_match8_repeat_extend_calcBlockSizeSmall: + CMPL R8, $0x08 + JB matchlen_match4_repeat_extend_calcBlockSizeSmall + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 + JNZ matchlen_bsf_8_repeat_extend_calcBlockSizeSmall + LEAL -8(R8), R8 + LEAL 8(R11), R11 + JMP matchlen_match4_repeat_extend_calcBlockSizeSmall + +matchlen_bsf_8_repeat_extend_calcBlockSizeSmall: +#ifdef GOAMD64_v3 + TZCNTQ R10, R10 + +#else + BSFQ R10, R10 + +#endif + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_calcBlockSizeSmall + +matchlen_match4_repeat_extend_calcBlockSizeSmall: + CMPL R8, $0x04 + JB matchlen_match2_repeat_extend_calcBlockSizeSmall + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 + JNE matchlen_match2_repeat_extend_calcBlockSizeSmall + LEAL -4(R8), R8 + LEAL 4(R11), R11 + +matchlen_match2_repeat_extend_calcBlockSizeSmall: + CMPL R8, $0x01 + JE matchlen_match1_repeat_extend_calcBlockSizeSmall + JB repeat_extend_forward_end_calcBlockSizeSmall + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 + JNE matchlen_match1_repeat_extend_calcBlockSizeSmall + LEAL 2(R11), R11 + SUBL $0x02, R8 + JZ repeat_extend_forward_end_calcBlockSizeSmall + +matchlen_match1_repeat_extend_calcBlockSizeSmall: + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 + JNE repeat_extend_forward_end_calcBlockSizeSmall + LEAL 1(R11), R11 + +repeat_extend_forward_end_calcBlockSizeSmall: + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + + // emitCopy +two_byte_offset_repeat_as_copy_calcBlockSizeSmall: + CMPL SI, $0x40 + JBE two_byte_offset_short_repeat_as_copy_calcBlockSizeSmall + LEAL -60(SI), SI + ADDQ $0x03, CX + JMP two_byte_offset_repeat_as_copy_calcBlockSizeSmall + +two_byte_offset_short_repeat_as_copy_calcBlockSizeSmall: + MOVL SI, DI + SHLL $0x02, DI + CMPL SI, $0x0c + JAE emit_copy_three_repeat_as_copy_calcBlockSizeSmall + ADDQ $0x02, CX + JMP repeat_end_emit_calcBlockSizeSmall + +emit_copy_three_repeat_as_copy_calcBlockSizeSmall: + ADDQ $0x03, CX + +repeat_end_emit_calcBlockSizeSmall: + MOVL DX, 12(SP) + JMP search_loop_calcBlockSizeSmall + +no_repeat_found_calcBlockSizeSmall: + CMPL (BX)(SI*1), DI + JEQ candidate_match_calcBlockSizeSmall + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI + JEQ candidate2_match_calcBlockSizeSmall + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI + JEQ candidate3_match_calcBlockSizeSmall + MOVL 20(SP), DX + JMP search_loop_calcBlockSizeSmall + +candidate3_match_calcBlockSizeSmall: + ADDL $0x02, DX + JMP candidate_match_calcBlockSizeSmall + +candidate2_match_calcBlockSizeSmall: + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI + +candidate_match_calcBlockSizeSmall: + MOVL 12(SP), DI + TESTL SI, SI + JZ match_extend_back_end_calcBlockSizeSmall + +match_extend_back_loop_calcBlockSizeSmall: + CMPL DX, DI + JBE match_extend_back_end_calcBlockSizeSmall + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 + JNE match_extend_back_end_calcBlockSizeSmall + LEAL -1(DX), DX + DECL SI + JZ match_extend_back_end_calcBlockSizeSmall + JMP match_extend_back_loop_calcBlockSizeSmall + +match_extend_back_end_calcBlockSizeSmall: + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) + JB match_dst_size_check_calcBlockSizeSmall + MOVQ $0x00000000, ret+32(FP) + RET + +match_dst_size_check_calcBlockSizeSmall: + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI + JEQ emit_literal_done_match_emit_calcBlockSizeSmall + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), DI + CMPL DI, $0x3c + JB one_byte_match_emit_calcBlockSizeSmall + CMPL DI, $0x00000100 + JB two_bytes_match_emit_calcBlockSizeSmall + JB three_bytes_match_emit_calcBlockSizeSmall + +three_bytes_match_emit_calcBlockSizeSmall: + ADDQ $0x03, CX + JMP memmove_long_match_emit_calcBlockSizeSmall + +two_bytes_match_emit_calcBlockSizeSmall: + ADDQ $0x02, CX + CMPL DI, $0x40 + JB memmove_match_emit_calcBlockSizeSmall + JMP memmove_long_match_emit_calcBlockSizeSmall + +one_byte_match_emit_calcBlockSizeSmall: + ADDQ $0x01, CX + +memmove_match_emit_calcBlockSizeSmall: + LEAQ (CX)(R9*1), CX + JMP emit_literal_done_match_emit_calcBlockSizeSmall + +memmove_long_match_emit_calcBlockSizeSmall: + LEAQ (CX)(R9*1), CX + +emit_literal_done_match_emit_calcBlockSizeSmall: +match_nolit_loop_calcBlockSizeSmall: + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+8(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI + + // matchLen + XORL R10, R10 + +matchlen_loopback_16_match_nolit_calcBlockSizeSmall: + CMPL DI, $0x10 + JB matchlen_match8_match_nolit_calcBlockSizeSmall + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_calcBlockSizeSmall + XORQ 8(SI)(R10*1), R11 + JNZ matchlen_bsf_16match_nolit_calcBlockSizeSmall + LEAL -16(DI), DI + LEAL 16(R10), R10 + JMP matchlen_loopback_16_match_nolit_calcBlockSizeSmall + +matchlen_bsf_16match_nolit_calcBlockSizeSmall: +#ifdef GOAMD64_v3 + TZCNTQ R11, R11 + +#else + BSFQ R11, R11 + +#endif + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_calcBlockSizeSmall + +matchlen_match8_match_nolit_calcBlockSizeSmall: + CMPL DI, $0x08 + JB matchlen_match4_match_nolit_calcBlockSizeSmall + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 + JNZ matchlen_bsf_8_match_nolit_calcBlockSizeSmall + LEAL -8(DI), DI + LEAL 8(R10), R10 + JMP matchlen_match4_match_nolit_calcBlockSizeSmall + +matchlen_bsf_8_match_nolit_calcBlockSizeSmall: +#ifdef GOAMD64_v3 + TZCNTQ R9, R9 + +#else + BSFQ R9, R9 + +#endif + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_calcBlockSizeSmall + +matchlen_match4_match_nolit_calcBlockSizeSmall: + CMPL DI, $0x04 + JB matchlen_match2_match_nolit_calcBlockSizeSmall + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 + JNE matchlen_match2_match_nolit_calcBlockSizeSmall + LEAL -4(DI), DI + LEAL 4(R10), R10 + +matchlen_match2_match_nolit_calcBlockSizeSmall: + CMPL DI, $0x01 + JE matchlen_match1_match_nolit_calcBlockSizeSmall + JB match_nolit_end_calcBlockSizeSmall + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 + JNE matchlen_match1_match_nolit_calcBlockSizeSmall + LEAL 2(R10), R10 + SUBL $0x02, DI + JZ match_nolit_end_calcBlockSizeSmall + +matchlen_match1_match_nolit_calcBlockSizeSmall: + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 + JNE match_nolit_end_calcBlockSizeSmall + LEAL 1(R10), R10 + +match_nolit_end_calcBlockSizeSmall: + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) + + // emitCopy +two_byte_offset_match_nolit_calcBlockSizeSmall: + CMPL R10, $0x40 + JBE two_byte_offset_short_match_nolit_calcBlockSizeSmall + LEAL -60(R10), R10 + ADDQ $0x03, CX + JMP two_byte_offset_match_nolit_calcBlockSizeSmall + +two_byte_offset_short_match_nolit_calcBlockSizeSmall: + MOVL R10, SI + SHLL $0x02, SI + CMPL R10, $0x0c + JAE emit_copy_three_match_nolit_calcBlockSizeSmall + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_calcBlockSizeSmall + +emit_copy_three_match_nolit_calcBlockSizeSmall: + ADDQ $0x03, CX + +match_nolit_emitcopy_end_calcBlockSizeSmall: + CMPL DX, 8(SP) + JAE emit_remainder_calcBlockSizeSmall + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) + JB match_nolit_dst_ok_calcBlockSizeSmall + MOVQ $0x00000000, ret+32(FP) + RET + +match_nolit_dst_ok_calcBlockSizeSmall: + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x37, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x37, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI + JEQ match_nolit_loop_calcBlockSizeSmall + INCL DX + JMP search_loop_calcBlockSizeSmall + +emit_remainder_calcBlockSizeSmall: + MOVQ src_len+8(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) + JB emit_remainder_ok_calcBlockSizeSmall + MOVQ $0x00000000, ret+32(FP) + RET + +emit_remainder_ok_calcBlockSizeSmall: + MOVQ src_len+8(FP), AX + MOVL 12(SP), DX + CMPL DX, AX + JEQ emit_literal_done_emit_remainder_calcBlockSizeSmall + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), AX + CMPL AX, $0x3c + JB one_byte_emit_remainder_calcBlockSizeSmall + CMPL AX, $0x00000100 + JB two_bytes_emit_remainder_calcBlockSizeSmall + JB three_bytes_emit_remainder_calcBlockSizeSmall + +three_bytes_emit_remainder_calcBlockSizeSmall: + ADDQ $0x03, CX + JMP memmove_long_emit_remainder_calcBlockSizeSmall + +two_bytes_emit_remainder_calcBlockSizeSmall: + ADDQ $0x02, CX + CMPL AX, $0x40 + JB memmove_emit_remainder_calcBlockSizeSmall + JMP memmove_long_emit_remainder_calcBlockSizeSmall + +one_byte_emit_remainder_calcBlockSizeSmall: + ADDQ $0x01, CX + +memmove_emit_remainder_calcBlockSizeSmall: + LEAQ (CX)(SI*1), AX + MOVQ AX, CX + JMP emit_literal_done_emit_remainder_calcBlockSizeSmall + +memmove_long_emit_remainder_calcBlockSizeSmall: + LEAQ (CX)(SI*1), AX + MOVQ AX, CX + +emit_literal_done_emit_remainder_calcBlockSizeSmall: + MOVQ CX, ret+32(FP) + RET + +// func emitLiteral(dst []byte, lit []byte) int +// Requires: SSE2 +TEXT ·emitLiteral(SB), NOSPLIT, $0-56 + MOVQ lit_len+32(FP), DX + MOVQ dst_base+0(FP), AX + MOVQ lit_base+24(FP), CX + TESTQ DX, DX + JZ emit_literal_end_standalone_skip + MOVL DX, BX + LEAL -1(DX), SI + CMPL SI, $0x3c + JB one_byte_standalone + CMPL SI, $0x00000100 + JB two_bytes_standalone + CMPL SI, $0x00010000 + JB three_bytes_standalone + CMPL SI, $0x01000000 + JB four_bytes_standalone + MOVB $0xfc, (AX) + MOVL SI, 1(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP memmove_long_standalone + +four_bytes_standalone: + MOVL SI, DI + SHRL $0x10, DI + MOVB $0xf8, (AX) + MOVW SI, 1(AX) + MOVB DI, 3(AX) + ADDQ $0x04, BX + ADDQ $0x04, AX + JMP memmove_long_standalone + +three_bytes_standalone: + MOVB $0xf4, (AX) + MOVW SI, 1(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + JMP memmove_long_standalone + +two_bytes_standalone: + MOVB $0xf0, (AX) + MOVB SI, 1(AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + CMPL SI, $0x40 + JB memmove_standalone + JMP memmove_long_standalone + +one_byte_standalone: + SHLB $0x02, SI + MOVB SI, (AX) + ADDQ $0x01, BX + ADDQ $0x01, AX + +memmove_standalone: + // genMemMoveShort + CMPQ DX, $0x03 + JB emit_lit_memmove_standalone_memmove_move_1or2 + JE emit_lit_memmove_standalone_memmove_move_3 + CMPQ DX, $0x08 + JB emit_lit_memmove_standalone_memmove_move_4through7 + CMPQ DX, $0x10 + JBE emit_lit_memmove_standalone_memmove_move_8through16 + CMPQ DX, $0x20 + JBE emit_lit_memmove_standalone_memmove_move_17through32 + JMP emit_lit_memmove_standalone_memmove_move_33through64 + +emit_lit_memmove_standalone_memmove_move_1or2: + MOVB (CX), SI + MOVB -1(CX)(DX*1), CL + MOVB SI, (AX) + MOVB CL, -1(AX)(DX*1) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_3: + MOVW (CX), SI + MOVB 2(CX), CL + MOVW SI, (AX) + MOVB CL, 2(AX) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_4through7: + MOVL (CX), SI + MOVL -4(CX)(DX*1), CX + MOVL SI, (AX) + MOVL CX, -4(AX)(DX*1) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_8through16: + MOVQ (CX), SI + MOVQ -8(CX)(DX*1), CX + MOVQ SI, (AX) + MOVQ CX, -8(AX)(DX*1) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_17through32: + MOVOU (CX), X0 + MOVOU -16(CX)(DX*1), X1 + MOVOU X0, (AX) + MOVOU X1, -16(AX)(DX*1) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_33through64: + MOVOU (CX), X0 + MOVOU 16(CX), X1 + MOVOU -32(CX)(DX*1), X2 + MOVOU -16(CX)(DX*1), X3 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(DX*1) + MOVOU X3, -16(AX)(DX*1) + JMP emit_literal_end_standalone + JMP emit_literal_end_standalone + +memmove_long_standalone: + // genMemMoveLong + MOVOU (CX), X0 + MOVOU 16(CX), X1 + MOVOU -32(CX)(DX*1), X2 + MOVOU -16(CX)(DX*1), X3 + MOVQ DX, DI + SHRQ $0x05, DI + MOVQ AX, SI + ANDL $0x0000001f, SI + MOVQ $0x00000040, R8 + SUBQ SI, R8 + DECQ DI + JA emit_lit_memmove_long_standalonelarge_forward_sse_loop_32 + LEAQ -32(CX)(R8*1), SI + LEAQ -32(AX)(R8*1), R9 + +emit_lit_memmove_long_standalonelarge_big_loop_back: + MOVOU (SI), X4 + MOVOU 16(SI), X5 + MOVOA X4, (R9) + MOVOA X5, 16(R9) + ADDQ $0x20, R9 + ADDQ $0x20, SI + ADDQ $0x20, R8 + DECQ DI + JNA emit_lit_memmove_long_standalonelarge_big_loop_back + +emit_lit_memmove_long_standalonelarge_forward_sse_loop_32: + MOVOU -32(CX)(R8*1), X4 + MOVOU -16(CX)(R8*1), X5 + MOVOA X4, -32(AX)(R8*1) + MOVOA X5, -16(AX)(R8*1) + ADDQ $0x20, R8 + CMPQ DX, R8 + JAE emit_lit_memmove_long_standalonelarge_forward_sse_loop_32 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(DX*1) + MOVOU X3, -16(AX)(DX*1) + JMP emit_literal_end_standalone + JMP emit_literal_end_standalone + +emit_literal_end_standalone_skip: + XORQ BX, BX + +emit_literal_end_standalone: + MOVQ BX, ret+48(FP) + RET + +// func emitRepeat(dst []byte, offset int, length int) int +TEXT ·emitRepeat(SB), NOSPLIT, $0-48 + XORQ BX, BX + MOVQ dst_base+0(FP), AX + MOVQ offset+24(FP), CX + MOVQ length+32(FP), DX + + // emitRepeat +emit_repeat_again_standalone: + MOVL DX, SI + LEAL -4(DX), DX + CMPL SI, $0x08 + JBE repeat_two_standalone + CMPL SI, $0x0c + JAE cant_repeat_two_offset_standalone + CMPL CX, $0x00000800 + JB repeat_two_offset_standalone + +cant_repeat_two_offset_standalone: + CMPL DX, $0x00000104 + JB repeat_three_standalone + CMPL DX, $0x00010100 + JB repeat_four_standalone + CMPL DX, $0x0100ffff + JB repeat_five_standalone + LEAL -16842747(DX), DX + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + ADDQ $0x05, BX + JMP emit_repeat_again_standalone + +repeat_five_standalone: + LEAL -65536(DX), DX + MOVL DX, CX + MOVW $0x001d, (AX) + MOVW DX, 2(AX) + SARL $0x10, CX + MOVB CL, 4(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP gen_emit_repeat_end + +repeat_four_standalone: + LEAL -256(DX), DX + MOVW $0x0019, (AX) + MOVW DX, 2(AX) + ADDQ $0x04, BX + ADDQ $0x04, AX + JMP gen_emit_repeat_end + +repeat_three_standalone: + LEAL -4(DX), DX + MOVW $0x0015, (AX) + MOVB DL, 2(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + JMP gen_emit_repeat_end + +repeat_two_standalone: + SHLL $0x02, DX + ORL $0x01, DX + MOVW DX, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_repeat_end + +repeat_two_offset_standalone: + XORQ SI, SI + LEAL 1(SI)(DX*4), DX + MOVB CL, 1(AX) + SARL $0x08, CX + SHLL $0x05, CX + ORL CX, DX + MOVB DL, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + +gen_emit_repeat_end: + MOVQ BX, ret+40(FP) + RET + +// func emitCopy(dst []byte, offset int, length int) int +TEXT ·emitCopy(SB), NOSPLIT, $0-48 + XORQ BX, BX + MOVQ dst_base+0(FP), AX + MOVQ offset+24(FP), CX + MOVQ length+32(FP), DX + + // emitCopy + CMPL CX, $0x00010000 + JB two_byte_offset_standalone + CMPL DX, $0x40 + JBE four_bytes_remain_standalone + MOVB $0xff, (AX) + MOVL CX, 1(AX) + LEAL -64(DX), DX + ADDQ $0x05, BX + ADDQ $0x05, AX + CMPL DX, $0x04 + JB four_bytes_remain_standalone + + // emitRepeat +emit_repeat_again_standalone_emit_copy: + MOVL DX, SI + LEAL -4(DX), DX + CMPL SI, $0x08 + JBE repeat_two_standalone_emit_copy + CMPL SI, $0x0c + JAE cant_repeat_two_offset_standalone_emit_copy + CMPL CX, $0x00000800 + JB repeat_two_offset_standalone_emit_copy + +cant_repeat_two_offset_standalone_emit_copy: + CMPL DX, $0x00000104 + JB repeat_three_standalone_emit_copy + CMPL DX, $0x00010100 + JB repeat_four_standalone_emit_copy + CMPL DX, $0x0100ffff + JB repeat_five_standalone_emit_copy + LEAL -16842747(DX), DX + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + ADDQ $0x05, BX + JMP emit_repeat_again_standalone_emit_copy + +repeat_five_standalone_emit_copy: + LEAL -65536(DX), DX + MOVL DX, CX + MOVW $0x001d, (AX) + MOVW DX, 2(AX) + SARL $0x10, CX + MOVB CL, 4(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP gen_emit_copy_end + +repeat_four_standalone_emit_copy: + LEAL -256(DX), DX + MOVW $0x0019, (AX) + MOVW DX, 2(AX) + ADDQ $0x04, BX + ADDQ $0x04, AX + JMP gen_emit_copy_end + +repeat_three_standalone_emit_copy: + LEAL -4(DX), DX + MOVW $0x0015, (AX) + MOVB DL, 2(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + JMP gen_emit_copy_end + +repeat_two_standalone_emit_copy: + SHLL $0x02, DX + ORL $0x01, DX + MOVW DX, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +repeat_two_offset_standalone_emit_copy: + XORQ SI, SI + LEAL 1(SI)(DX*4), DX + MOVB CL, 1(AX) + SARL $0x08, CX + SHLL $0x05, CX + ORL CX, DX + MOVB DL, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +four_bytes_remain_standalone: + TESTL DX, DX + JZ gen_emit_copy_end + XORL SI, SI + LEAL -1(SI)(DX*4), DX + MOVB DL, (AX) + MOVL CX, 1(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP gen_emit_copy_end + +two_byte_offset_standalone: + CMPL DX, $0x40 + JBE two_byte_offset_short_standalone + CMPL CX, $0x00000800 + JAE long_offset_short_standalone + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB CL, 1(AX) + MOVL CX, DI + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + SUBL $0x08, DX + + // emitRepeat + LEAL -4(DX), DX + JMP cant_repeat_two_offset_standalone_emit_copy_short_2b + +emit_repeat_again_standalone_emit_copy_short_2b: + MOVL DX, SI + LEAL -4(DX), DX + CMPL SI, $0x08 + JBE repeat_two_standalone_emit_copy_short_2b + CMPL SI, $0x0c + JAE cant_repeat_two_offset_standalone_emit_copy_short_2b + CMPL CX, $0x00000800 + JB repeat_two_offset_standalone_emit_copy_short_2b + +cant_repeat_two_offset_standalone_emit_copy_short_2b: + CMPL DX, $0x00000104 + JB repeat_three_standalone_emit_copy_short_2b + CMPL DX, $0x00010100 + JB repeat_four_standalone_emit_copy_short_2b + CMPL DX, $0x0100ffff + JB repeat_five_standalone_emit_copy_short_2b + LEAL -16842747(DX), DX + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + ADDQ $0x05, BX + JMP emit_repeat_again_standalone_emit_copy_short_2b + +repeat_five_standalone_emit_copy_short_2b: + LEAL -65536(DX), DX + MOVL DX, CX + MOVW $0x001d, (AX) + MOVW DX, 2(AX) + SARL $0x10, CX + MOVB CL, 4(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP gen_emit_copy_end + +repeat_four_standalone_emit_copy_short_2b: + LEAL -256(DX), DX + MOVW $0x0019, (AX) + MOVW DX, 2(AX) + ADDQ $0x04, BX + ADDQ $0x04, AX + JMP gen_emit_copy_end + +repeat_three_standalone_emit_copy_short_2b: + LEAL -4(DX), DX + MOVW $0x0015, (AX) + MOVB DL, 2(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + JMP gen_emit_copy_end + +repeat_two_standalone_emit_copy_short_2b: + SHLL $0x02, DX + ORL $0x01, DX + MOVW DX, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +repeat_two_offset_standalone_emit_copy_short_2b: + XORQ SI, SI + LEAL 1(SI)(DX*4), DX + MOVB CL, 1(AX) + SARL $0x08, CX + SHLL $0x05, CX + ORL CX, DX + MOVB DL, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +long_offset_short_standalone: + MOVB $0xee, (AX) + MOVW CX, 1(AX) + LEAL -60(DX), DX + ADDQ $0x03, AX + ADDQ $0x03, BX + + // emitRepeat +emit_repeat_again_standalone_emit_copy_short: + MOVL DX, SI + LEAL -4(DX), DX + CMPL SI, $0x08 + JBE repeat_two_standalone_emit_copy_short + CMPL SI, $0x0c + JAE cant_repeat_two_offset_standalone_emit_copy_short + CMPL CX, $0x00000800 + JB repeat_two_offset_standalone_emit_copy_short + +cant_repeat_two_offset_standalone_emit_copy_short: + CMPL DX, $0x00000104 + JB repeat_three_standalone_emit_copy_short + CMPL DX, $0x00010100 + JB repeat_four_standalone_emit_copy_short + CMPL DX, $0x0100ffff + JB repeat_five_standalone_emit_copy_short + LEAL -16842747(DX), DX + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + ADDQ $0x05, BX + JMP emit_repeat_again_standalone_emit_copy_short + +repeat_five_standalone_emit_copy_short: + LEAL -65536(DX), DX + MOVL DX, CX + MOVW $0x001d, (AX) + MOVW DX, 2(AX) + SARL $0x10, CX + MOVB CL, 4(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP gen_emit_copy_end + +repeat_four_standalone_emit_copy_short: + LEAL -256(DX), DX + MOVW $0x0019, (AX) + MOVW DX, 2(AX) + ADDQ $0x04, BX + ADDQ $0x04, AX + JMP gen_emit_copy_end + +repeat_three_standalone_emit_copy_short: + LEAL -4(DX), DX + MOVW $0x0015, (AX) + MOVB DL, 2(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + JMP gen_emit_copy_end + +repeat_two_standalone_emit_copy_short: + SHLL $0x02, DX + ORL $0x01, DX + MOVW DX, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +repeat_two_offset_standalone_emit_copy_short: + XORQ SI, SI + LEAL 1(SI)(DX*4), DX + MOVB CL, 1(AX) + SARL $0x08, CX + SHLL $0x05, CX + ORL CX, DX + MOVB DL, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +two_byte_offset_short_standalone: + MOVL DX, SI + SHLL $0x02, SI + CMPL DX, $0x0c + JAE emit_copy_three_standalone + CMPL CX, $0x00000800 + JAE emit_copy_three_standalone + LEAL -15(SI), SI + MOVB CL, 1(AX) + SHRL $0x08, CX + SHLL $0x05, CX + ORL CX, SI + MOVB SI, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end + +emit_copy_three_standalone: + LEAL -2(SI), SI + MOVB SI, (AX) + MOVW CX, 1(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + +gen_emit_copy_end: + MOVQ BX, ret+40(FP) + RET + +// func emitCopyNoRepeat(dst []byte, offset int, length int) int +TEXT ·emitCopyNoRepeat(SB), NOSPLIT, $0-48 + XORQ BX, BX + MOVQ dst_base+0(FP), AX + MOVQ offset+24(FP), CX + MOVQ length+32(FP), DX + + // emitCopy + CMPL CX, $0x00010000 + JB two_byte_offset_standalone_snappy + +four_bytes_loop_back_standalone_snappy: + CMPL DX, $0x40 + JBE four_bytes_remain_standalone_snappy + MOVB $0xff, (AX) + MOVL CX, 1(AX) + LEAL -64(DX), DX + ADDQ $0x05, BX + ADDQ $0x05, AX + CMPL DX, $0x04 + JB four_bytes_remain_standalone_snappy + JMP four_bytes_loop_back_standalone_snappy + +four_bytes_remain_standalone_snappy: + TESTL DX, DX + JZ gen_emit_copy_end_snappy + XORL SI, SI + LEAL -1(SI)(DX*4), DX + MOVB DL, (AX) + MOVL CX, 1(AX) + ADDQ $0x05, BX + ADDQ $0x05, AX + JMP gen_emit_copy_end_snappy + +two_byte_offset_standalone_snappy: + CMPL DX, $0x40 + JBE two_byte_offset_short_standalone_snappy + MOVB $0xee, (AX) + MOVW CX, 1(AX) + LEAL -60(DX), DX + ADDQ $0x03, AX + ADDQ $0x03, BX + JMP two_byte_offset_standalone_snappy + +two_byte_offset_short_standalone_snappy: + MOVL DX, SI + SHLL $0x02, SI + CMPL DX, $0x0c + JAE emit_copy_three_standalone_snappy + CMPL CX, $0x00000800 + JAE emit_copy_three_standalone_snappy + LEAL -15(SI), SI + MOVB CL, 1(AX) + SHRL $0x08, CX + SHLL $0x05, CX + ORL CX, SI + MOVB SI, (AX) + ADDQ $0x02, BX + ADDQ $0x02, AX + JMP gen_emit_copy_end_snappy + +emit_copy_three_standalone_snappy: + LEAL -2(SI), SI + MOVB SI, (AX) + MOVW CX, 1(AX) + ADDQ $0x03, BX + ADDQ $0x03, AX + +gen_emit_copy_end_snappy: + MOVQ BX, ret+40(FP) + RET + +// func matchLen(a []byte, b []byte) int +// Requires: BMI +TEXT ·matchLen(SB), NOSPLIT, $0-56 + MOVQ a_base+0(FP), AX + MOVQ b_base+24(FP), CX + MOVQ a_len+8(FP), DX + + // matchLen + XORL SI, SI + +matchlen_loopback_16_standalone: + CMPL DX, $0x10 + JB matchlen_match8_standalone + MOVQ (AX)(SI*1), BX + MOVQ 8(AX)(SI*1), DI + XORQ (CX)(SI*1), BX + JNZ matchlen_bsf_8_standalone + XORQ 8(CX)(SI*1), DI + JNZ matchlen_bsf_16standalone + LEAL -16(DX), DX + LEAL 16(SI), SI + JMP matchlen_loopback_16_standalone + +matchlen_bsf_16standalone: +#ifdef GOAMD64_v3 + TZCNTQ DI, DI + +#else + BSFQ DI, DI + +#endif + SARQ $0x03, DI + LEAL 8(SI)(DI*1), SI + JMP gen_match_len_end + +matchlen_match8_standalone: + CMPL DX, $0x08 + JB matchlen_match4_standalone + MOVQ (AX)(SI*1), BX + XORQ (CX)(SI*1), BX + JNZ matchlen_bsf_8_standalone + LEAL -8(DX), DX + LEAL 8(SI), SI + JMP matchlen_match4_standalone + +matchlen_bsf_8_standalone: +#ifdef GOAMD64_v3 + TZCNTQ BX, BX + +#else + BSFQ BX, BX + +#endif + SARQ $0x03, BX + LEAL (SI)(BX*1), SI + JMP gen_match_len_end + +matchlen_match4_standalone: + CMPL DX, $0x04 + JB matchlen_match2_standalone + MOVL (AX)(SI*1), BX + CMPL (CX)(SI*1), BX + JNE matchlen_match2_standalone + LEAL -4(DX), DX + LEAL 4(SI), SI + +matchlen_match2_standalone: + CMPL DX, $0x01 + JE matchlen_match1_standalone + JB gen_match_len_end + MOVW (AX)(SI*1), BX + CMPW (CX)(SI*1), BX + JNE matchlen_match1_standalone + LEAL 2(SI), SI + SUBL $0x02, DX + JZ gen_match_len_end + +matchlen_match1_standalone: + MOVB (AX)(SI*1), BL + CMPB (CX)(SI*1), BL + JNE gen_match_len_end + LEAL 1(SI), SI + +gen_match_len_end: + MOVQ SI, ret+48(FP) + RET + +// func cvtLZ4BlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4BlockAsm(SB), NOSPLIT, $0-64 + XORQ SI, SI + MOVQ dst_base+0(FP), AX + MOVQ dst_len+8(FP), CX + MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), BX + LEAQ (DX)(BX*1), BX + LEAQ -8(AX)(CX*1), CX + XORQ DI, DI + +lz4_s2_loop: + CMPQ DX, BX + JAE lz4_s2_corrupt + CMPQ AX, CX + JAE lz4_s2_dstfull + MOVBQZX (DX), R8 + MOVQ R8, R9 + MOVQ R8, R10 + SHRQ $0x04, R9 + ANDQ $0x0f, R10 + CMPQ R8, $0xf0 + JB lz4_s2_ll_end + +lz4_s2_ll_loop: + INCQ DX + CMPQ DX, BX + JAE lz4_s2_corrupt + MOVBQZX (DX), R8 + ADDQ R8, R9 + CMPQ R8, $0xff + JEQ lz4_s2_ll_loop + +lz4_s2_ll_end: + LEAQ (DX)(R9*1), R8 + ADDQ $0x04, R10 + CMPQ R8, BX + JAE lz4_s2_corrupt + INCQ DX + INCQ R8 + TESTQ R9, R9 + JZ lz4_s2_lits_done + LEAQ (AX)(R9*1), R11 + CMPQ R11, CX + JAE lz4_s2_dstfull + ADDQ R9, SI + LEAL -1(R9), R11 + CMPL R11, $0x3c + JB one_byte_lz4_s2 + CMPL R11, $0x00000100 + JB two_bytes_lz4_s2 + CMPL R11, $0x00010000 + JB three_bytes_lz4_s2 + CMPL R11, $0x01000000 + JB four_bytes_lz4_s2 + MOVB $0xfc, (AX) + MOVL R11, 1(AX) + ADDQ $0x05, AX + JMP memmove_long_lz4_s2 + +four_bytes_lz4_s2: + MOVL R11, R12 + SHRL $0x10, R12 + MOVB $0xf8, (AX) + MOVW R11, 1(AX) + MOVB R12, 3(AX) + ADDQ $0x04, AX + JMP memmove_long_lz4_s2 + +three_bytes_lz4_s2: + MOVB $0xf4, (AX) + MOVW R11, 1(AX) + ADDQ $0x03, AX + JMP memmove_long_lz4_s2 + +two_bytes_lz4_s2: + MOVB $0xf0, (AX) + MOVB R11, 1(AX) + ADDQ $0x02, AX + CMPL R11, $0x40 + JB memmove_lz4_s2 + JMP memmove_long_lz4_s2 + +one_byte_lz4_s2: + SHLB $0x02, R11 + MOVB R11, (AX) + ADDQ $0x01, AX + +memmove_lz4_s2: + LEAQ (AX)(R9*1), R11 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_lz4_s2_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_lz4_s2_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_lz4_s2_memmove_move_17through32 + JMP emit_lit_memmove_lz4_s2_memmove_move_33through64 + +emit_lit_memmove_lz4_s2_memmove_move_8: + MOVQ (DX), R12 + MOVQ R12, (AX) + JMP memmove_end_copy_lz4_s2 + +emit_lit_memmove_lz4_s2_memmove_move_8through16: + MOVQ (DX), R12 + MOVQ -8(DX)(R9*1), DX + MOVQ R12, (AX) + MOVQ DX, -8(AX)(R9*1) + JMP memmove_end_copy_lz4_s2 + +emit_lit_memmove_lz4_s2_memmove_move_17through32: + MOVOU (DX), X0 + MOVOU -16(DX)(R9*1), X1 + MOVOU X0, (AX) + MOVOU X1, -16(AX)(R9*1) + JMP memmove_end_copy_lz4_s2 + +emit_lit_memmove_lz4_s2_memmove_move_33through64: + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R9*1), X2 + MOVOU -16(DX)(R9*1), X3 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R9*1) + MOVOU X3, -16(AX)(R9*1) + +memmove_end_copy_lz4_s2: + MOVQ R11, AX + JMP lz4_s2_lits_emit_done + +memmove_long_lz4_s2: + LEAQ (AX)(R9*1), R11 + + // genMemMoveLong + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R9*1), X2 + MOVOU -16(DX)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ AX, R12 + ANDL $0x0000001f, R12 + MOVQ $0x00000040, R14 + SUBQ R12, R14 + DECQ R13 + JA emit_lit_memmove_long_lz4_s2large_forward_sse_loop_32 + LEAQ -32(DX)(R14*1), R12 + LEAQ -32(AX)(R14*1), R15 + +emit_lit_memmove_long_lz4_s2large_big_loop_back: + MOVOU (R12), X4 + MOVOU 16(R12), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R12 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_lz4_s2large_big_loop_back + +emit_lit_memmove_long_lz4_s2large_forward_sse_loop_32: + MOVOU -32(DX)(R14*1), X4 + MOVOU -16(DX)(R14*1), X5 + MOVOA X4, -32(AX)(R14*1) + MOVOA X5, -16(AX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_lz4_s2large_forward_sse_loop_32 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R9*1) + MOVOU X3, -16(AX)(R9*1) + MOVQ R11, AX + +lz4_s2_lits_emit_done: + MOVQ R8, DX + +lz4_s2_lits_done: + CMPQ DX, BX + JNE lz4_s2_match + CMPQ R10, $0x04 + JEQ lz4_s2_done + JMP lz4_s2_corrupt + +lz4_s2_match: + LEAQ 2(DX), R8 + CMPQ R8, BX + JAE lz4_s2_corrupt + MOVWQZX (DX), R9 + MOVQ R8, DX + TESTQ R9, R9 + JZ lz4_s2_corrupt + CMPQ R9, SI + JA lz4_s2_corrupt + CMPQ R10, $0x13 + JNE lz4_s2_ml_done + +lz4_s2_ml_loop: + MOVBQZX (DX), R8 + INCQ DX + ADDQ R8, R10 + CMPQ DX, BX + JAE lz4_s2_corrupt + CMPQ R8, $0xff + JEQ lz4_s2_ml_loop + +lz4_s2_ml_done: + ADDQ R10, SI + CMPQ R9, DI + JNE lz4_s2_docopy + + // emitRepeat +emit_repeat_again_lz4_s2: + MOVL R10, R8 + LEAL -4(R10), R10 + CMPL R8, $0x08 + JBE repeat_two_lz4_s2 + CMPL R8, $0x0c + JAE cant_repeat_two_offset_lz4_s2 + CMPL R9, $0x00000800 + JB repeat_two_offset_lz4_s2 + +cant_repeat_two_offset_lz4_s2: + CMPL R10, $0x00000104 + JB repeat_three_lz4_s2 + CMPL R10, $0x00010100 + JB repeat_four_lz4_s2 + CMPL R10, $0x0100ffff + JB repeat_five_lz4_s2 + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + JMP emit_repeat_again_lz4_s2 + +repeat_five_lz4_s2: + LEAL -65536(R10), R10 + MOVL R10, R9 + MOVW $0x001d, (AX) + MOVW R10, 2(AX) + SARL $0x10, R9 + MOVB R9, 4(AX) + ADDQ $0x05, AX + JMP lz4_s2_loop + +repeat_four_lz4_s2: + LEAL -256(R10), R10 + MOVW $0x0019, (AX) + MOVW R10, 2(AX) + ADDQ $0x04, AX + JMP lz4_s2_loop + +repeat_three_lz4_s2: + LEAL -4(R10), R10 + MOVW $0x0015, (AX) + MOVB R10, 2(AX) + ADDQ $0x03, AX + JMP lz4_s2_loop + +repeat_two_lz4_s2: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +repeat_two_offset_lz4_s2: + XORQ R8, R8 + LEAL 1(R8)(R10*4), R10 + MOVB R9, 1(AX) + SARL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R10 + MOVB R10, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +lz4_s2_docopy: + MOVQ R9, DI + + // emitCopy + CMPL R10, $0x40 + JBE two_byte_offset_short_lz4_s2 + CMPL R9, $0x00000800 + JAE long_offset_short_lz4_s2 + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB R9, 1(AX) + MOVL R9, R11 + SHRL $0x08, R11 + SHLL $0x05, R11 + ORL R11, R8 + MOVB R8, (AX) + ADDQ $0x02, AX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + +emit_repeat_again_lz4_s2_emit_copy_short_2b: + MOVL R10, R8 + LEAL -4(R10), R10 + CMPL R8, $0x08 + JBE repeat_two_lz4_s2_emit_copy_short_2b + CMPL R8, $0x0c + JAE cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + CMPL R9, $0x00000800 + JB repeat_two_offset_lz4_s2_emit_copy_short_2b + +cant_repeat_two_offset_lz4_s2_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_lz4_s2_emit_copy_short_2b + CMPL R10, $0x00010100 + JB repeat_four_lz4_s2_emit_copy_short_2b + CMPL R10, $0x0100ffff + JB repeat_five_lz4_s2_emit_copy_short_2b + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + JMP emit_repeat_again_lz4_s2_emit_copy_short_2b + +repeat_five_lz4_s2_emit_copy_short_2b: + LEAL -65536(R10), R10 + MOVL R10, R9 + MOVW $0x001d, (AX) + MOVW R10, 2(AX) + SARL $0x10, R9 + MOVB R9, 4(AX) + ADDQ $0x05, AX + JMP lz4_s2_loop + +repeat_four_lz4_s2_emit_copy_short_2b: + LEAL -256(R10), R10 + MOVW $0x0019, (AX) + MOVW R10, 2(AX) + ADDQ $0x04, AX + JMP lz4_s2_loop + +repeat_three_lz4_s2_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (AX) + MOVB R10, 2(AX) + ADDQ $0x03, AX + JMP lz4_s2_loop + +repeat_two_lz4_s2_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short_2b: + XORQ R8, R8 + LEAL 1(R8)(R10*4), R10 + MOVB R9, 1(AX) + SARL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R10 + MOVB R10, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +long_offset_short_lz4_s2: + MOVB $0xee, (AX) + MOVW R9, 1(AX) + LEAL -60(R10), R10 + ADDQ $0x03, AX + + // emitRepeat +emit_repeat_again_lz4_s2_emit_copy_short: + MOVL R10, R8 + LEAL -4(R10), R10 + CMPL R8, $0x08 + JBE repeat_two_lz4_s2_emit_copy_short + CMPL R8, $0x0c + JAE cant_repeat_two_offset_lz4_s2_emit_copy_short + CMPL R9, $0x00000800 + JB repeat_two_offset_lz4_s2_emit_copy_short + +cant_repeat_two_offset_lz4_s2_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_lz4_s2_emit_copy_short + CMPL R10, $0x00010100 + JB repeat_four_lz4_s2_emit_copy_short + CMPL R10, $0x0100ffff + JB repeat_five_lz4_s2_emit_copy_short + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + JMP emit_repeat_again_lz4_s2_emit_copy_short + +repeat_five_lz4_s2_emit_copy_short: + LEAL -65536(R10), R10 + MOVL R10, R9 + MOVW $0x001d, (AX) + MOVW R10, 2(AX) + SARL $0x10, R9 + MOVB R9, 4(AX) + ADDQ $0x05, AX + JMP lz4_s2_loop + +repeat_four_lz4_s2_emit_copy_short: + LEAL -256(R10), R10 + MOVW $0x0019, (AX) + MOVW R10, 2(AX) + ADDQ $0x04, AX + JMP lz4_s2_loop + +repeat_three_lz4_s2_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (AX) + MOVB R10, 2(AX) + ADDQ $0x03, AX + JMP lz4_s2_loop + +repeat_two_lz4_s2_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short: + XORQ R8, R8 + LEAL 1(R8)(R10*4), R10 + MOVB R9, 1(AX) + SARL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R10 + MOVB R10, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +two_byte_offset_short_lz4_s2: + MOVL R10, R8 + SHLL $0x02, R8 + CMPL R10, $0x0c + JAE emit_copy_three_lz4_s2 + CMPL R9, $0x00000800 + JAE emit_copy_three_lz4_s2 + LEAL -15(R8), R8 + MOVB R9, 1(AX) + SHRL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R8 + MOVB R8, (AX) + ADDQ $0x02, AX + JMP lz4_s2_loop + +emit_copy_three_lz4_s2: + LEAL -2(R8), R8 + MOVB R8, (AX) + MOVW R9, 1(AX) + ADDQ $0x03, AX + JMP lz4_s2_loop + +lz4_s2_done: + MOVQ dst_base+0(FP), CX + SUBQ CX, AX + MOVQ SI, uncompressed+48(FP) + MOVQ AX, dstUsed+56(FP) + RET + +lz4_s2_corrupt: + XORQ AX, AX + LEAQ -1(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +lz4_s2_dstfull: + XORQ AX, AX + LEAQ -2(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +// func cvtLZ4sBlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4sBlockAsm(SB), NOSPLIT, $0-64 + XORQ SI, SI + MOVQ dst_base+0(FP), AX + MOVQ dst_len+8(FP), CX + MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), BX + LEAQ (DX)(BX*1), BX + LEAQ -8(AX)(CX*1), CX + XORQ DI, DI + +lz4s_s2_loop: + CMPQ DX, BX + JAE lz4s_s2_corrupt + CMPQ AX, CX + JAE lz4s_s2_dstfull + MOVBQZX (DX), R8 + MOVQ R8, R9 + MOVQ R8, R10 + SHRQ $0x04, R9 + ANDQ $0x0f, R10 + CMPQ R8, $0xf0 + JB lz4s_s2_ll_end + +lz4s_s2_ll_loop: + INCQ DX + CMPQ DX, BX + JAE lz4s_s2_corrupt + MOVBQZX (DX), R8 + ADDQ R8, R9 + CMPQ R8, $0xff + JEQ lz4s_s2_ll_loop + +lz4s_s2_ll_end: + LEAQ (DX)(R9*1), R8 + ADDQ $0x03, R10 + CMPQ R8, BX + JAE lz4s_s2_corrupt + INCQ DX + INCQ R8 + TESTQ R9, R9 + JZ lz4s_s2_lits_done + LEAQ (AX)(R9*1), R11 + CMPQ R11, CX + JAE lz4s_s2_dstfull + ADDQ R9, SI + LEAL -1(R9), R11 + CMPL R11, $0x3c + JB one_byte_lz4s_s2 + CMPL R11, $0x00000100 + JB two_bytes_lz4s_s2 + CMPL R11, $0x00010000 + JB three_bytes_lz4s_s2 + CMPL R11, $0x01000000 + JB four_bytes_lz4s_s2 + MOVB $0xfc, (AX) + MOVL R11, 1(AX) + ADDQ $0x05, AX + JMP memmove_long_lz4s_s2 + +four_bytes_lz4s_s2: + MOVL R11, R12 + SHRL $0x10, R12 + MOVB $0xf8, (AX) + MOVW R11, 1(AX) + MOVB R12, 3(AX) + ADDQ $0x04, AX + JMP memmove_long_lz4s_s2 + +three_bytes_lz4s_s2: + MOVB $0xf4, (AX) + MOVW R11, 1(AX) + ADDQ $0x03, AX + JMP memmove_long_lz4s_s2 + +two_bytes_lz4s_s2: + MOVB $0xf0, (AX) + MOVB R11, 1(AX) + ADDQ $0x02, AX + CMPL R11, $0x40 + JB memmove_lz4s_s2 + JMP memmove_long_lz4s_s2 + +one_byte_lz4s_s2: + SHLB $0x02, R11 + MOVB R11, (AX) + ADDQ $0x01, AX + +memmove_lz4s_s2: + LEAQ (AX)(R9*1), R11 + + // genMemMoveShort + CMPQ R9, $0x08 + JBE emit_lit_memmove_lz4s_s2_memmove_move_8 + CMPQ R9, $0x10 + JBE emit_lit_memmove_lz4s_s2_memmove_move_8through16 + CMPQ R9, $0x20 + JBE emit_lit_memmove_lz4s_s2_memmove_move_17through32 + JMP emit_lit_memmove_lz4s_s2_memmove_move_33through64 + +emit_lit_memmove_lz4s_s2_memmove_move_8: + MOVQ (DX), R12 + MOVQ R12, (AX) + JMP memmove_end_copy_lz4s_s2 + +emit_lit_memmove_lz4s_s2_memmove_move_8through16: + MOVQ (DX), R12 + MOVQ -8(DX)(R9*1), DX + MOVQ R12, (AX) + MOVQ DX, -8(AX)(R9*1) + JMP memmove_end_copy_lz4s_s2 + +emit_lit_memmove_lz4s_s2_memmove_move_17through32: + MOVOU (DX), X0 + MOVOU -16(DX)(R9*1), X1 + MOVOU X0, (AX) + MOVOU X1, -16(AX)(R9*1) + JMP memmove_end_copy_lz4s_s2 + +emit_lit_memmove_lz4s_s2_memmove_move_33through64: + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R9*1), X2 + MOVOU -16(DX)(R9*1), X3 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R9*1) + MOVOU X3, -16(AX)(R9*1) + +memmove_end_copy_lz4s_s2: + MOVQ R11, AX + JMP lz4s_s2_lits_emit_done + +memmove_long_lz4s_s2: + LEAQ (AX)(R9*1), R11 + + // genMemMoveLong + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R9*1), X2 + MOVOU -16(DX)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ AX, R12 + ANDL $0x0000001f, R12 + MOVQ $0x00000040, R14 + SUBQ R12, R14 + DECQ R13 + JA emit_lit_memmove_long_lz4s_s2large_forward_sse_loop_32 + LEAQ -32(DX)(R14*1), R12 + LEAQ -32(AX)(R14*1), R15 + +emit_lit_memmove_long_lz4s_s2large_big_loop_back: + MOVOU (R12), X4 + MOVOU 16(R12), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R12 + ADDQ $0x20, R14 + DECQ R13 + JNA emit_lit_memmove_long_lz4s_s2large_big_loop_back + +emit_lit_memmove_long_lz4s_s2large_forward_sse_loop_32: + MOVOU -32(DX)(R14*1), X4 + MOVOU -16(DX)(R14*1), X5 + MOVOA X4, -32(AX)(R14*1) + MOVOA X5, -16(AX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 + JAE emit_lit_memmove_long_lz4s_s2large_forward_sse_loop_32 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R9*1) + MOVOU X3, -16(AX)(R9*1) + MOVQ R11, AX + +lz4s_s2_lits_emit_done: + MOVQ R8, DX + +lz4s_s2_lits_done: + CMPQ DX, BX + JNE lz4s_s2_match + CMPQ R10, $0x03 + JEQ lz4s_s2_done + JMP lz4s_s2_corrupt + +lz4s_s2_match: + CMPQ R10, $0x03 + JEQ lz4s_s2_loop + LEAQ 2(DX), R8 + CMPQ R8, BX + JAE lz4s_s2_corrupt + MOVWQZX (DX), R9 + MOVQ R8, DX + TESTQ R9, R9 + JZ lz4s_s2_corrupt + CMPQ R9, SI + JA lz4s_s2_corrupt + CMPQ R10, $0x12 + JNE lz4s_s2_ml_done + +lz4s_s2_ml_loop: + MOVBQZX (DX), R8 + INCQ DX + ADDQ R8, R10 + CMPQ DX, BX + JAE lz4s_s2_corrupt + CMPQ R8, $0xff + JEQ lz4s_s2_ml_loop + +lz4s_s2_ml_done: + ADDQ R10, SI + CMPQ R9, DI + JNE lz4s_s2_docopy + + // emitRepeat +emit_repeat_again_lz4_s2: + MOVL R10, R8 + LEAL -4(R10), R10 + CMPL R8, $0x08 + JBE repeat_two_lz4_s2 + CMPL R8, $0x0c + JAE cant_repeat_two_offset_lz4_s2 + CMPL R9, $0x00000800 + JB repeat_two_offset_lz4_s2 + +cant_repeat_two_offset_lz4_s2: + CMPL R10, $0x00000104 + JB repeat_three_lz4_s2 + CMPL R10, $0x00010100 + JB repeat_four_lz4_s2 + CMPL R10, $0x0100ffff + JB repeat_five_lz4_s2 + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + JMP emit_repeat_again_lz4_s2 + +repeat_five_lz4_s2: + LEAL -65536(R10), R10 + MOVL R10, R9 + MOVW $0x001d, (AX) + MOVW R10, 2(AX) + SARL $0x10, R9 + MOVB R9, 4(AX) + ADDQ $0x05, AX + JMP lz4s_s2_loop + +repeat_four_lz4_s2: + LEAL -256(R10), R10 + MOVW $0x0019, (AX) + MOVW R10, 2(AX) + ADDQ $0x04, AX + JMP lz4s_s2_loop + +repeat_three_lz4_s2: + LEAL -4(R10), R10 + MOVW $0x0015, (AX) + MOVB R10, 2(AX) + ADDQ $0x03, AX + JMP lz4s_s2_loop + +repeat_two_lz4_s2: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +repeat_two_offset_lz4_s2: + XORQ R8, R8 + LEAL 1(R8)(R10*4), R10 + MOVB R9, 1(AX) + SARL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R10 + MOVB R10, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +lz4s_s2_docopy: + MOVQ R9, DI + + // emitCopy + CMPL R10, $0x40 + JBE two_byte_offset_short_lz4_s2 + CMPL R9, $0x00000800 + JAE long_offset_short_lz4_s2 + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB R9, 1(AX) + MOVL R9, R11 + SHRL $0x08, R11 + SHLL $0x05, R11 + ORL R11, R8 + MOVB R8, (AX) + ADDQ $0x02, AX + SUBL $0x08, R10 + + // emitRepeat + LEAL -4(R10), R10 + JMP cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + +emit_repeat_again_lz4_s2_emit_copy_short_2b: + MOVL R10, R8 + LEAL -4(R10), R10 + CMPL R8, $0x08 + JBE repeat_two_lz4_s2_emit_copy_short_2b + CMPL R8, $0x0c + JAE cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + CMPL R9, $0x00000800 + JB repeat_two_offset_lz4_s2_emit_copy_short_2b + +cant_repeat_two_offset_lz4_s2_emit_copy_short_2b: + CMPL R10, $0x00000104 + JB repeat_three_lz4_s2_emit_copy_short_2b + CMPL R10, $0x00010100 + JB repeat_four_lz4_s2_emit_copy_short_2b + CMPL R10, $0x0100ffff + JB repeat_five_lz4_s2_emit_copy_short_2b + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + JMP emit_repeat_again_lz4_s2_emit_copy_short_2b + +repeat_five_lz4_s2_emit_copy_short_2b: + LEAL -65536(R10), R10 + MOVL R10, R9 + MOVW $0x001d, (AX) + MOVW R10, 2(AX) + SARL $0x10, R9 + MOVB R9, 4(AX) + ADDQ $0x05, AX + JMP lz4s_s2_loop + +repeat_four_lz4_s2_emit_copy_short_2b: + LEAL -256(R10), R10 + MOVW $0x0019, (AX) + MOVW R10, 2(AX) + ADDQ $0x04, AX + JMP lz4s_s2_loop + +repeat_three_lz4_s2_emit_copy_short_2b: + LEAL -4(R10), R10 + MOVW $0x0015, (AX) + MOVB R10, 2(AX) + ADDQ $0x03, AX + JMP lz4s_s2_loop + +repeat_two_lz4_s2_emit_copy_short_2b: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short_2b: + XORQ R8, R8 + LEAL 1(R8)(R10*4), R10 + MOVB R9, 1(AX) + SARL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R10 + MOVB R10, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +long_offset_short_lz4_s2: + MOVB $0xee, (AX) + MOVW R9, 1(AX) + LEAL -60(R10), R10 + ADDQ $0x03, AX + + // emitRepeat +emit_repeat_again_lz4_s2_emit_copy_short: + MOVL R10, R8 + LEAL -4(R10), R10 + CMPL R8, $0x08 + JBE repeat_two_lz4_s2_emit_copy_short + CMPL R8, $0x0c + JAE cant_repeat_two_offset_lz4_s2_emit_copy_short + CMPL R9, $0x00000800 + JB repeat_two_offset_lz4_s2_emit_copy_short + +cant_repeat_two_offset_lz4_s2_emit_copy_short: + CMPL R10, $0x00000104 + JB repeat_three_lz4_s2_emit_copy_short + CMPL R10, $0x00010100 + JB repeat_four_lz4_s2_emit_copy_short + CMPL R10, $0x0100ffff + JB repeat_five_lz4_s2_emit_copy_short + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (AX) + MOVB $0xff, 4(AX) + ADDQ $0x05, AX + JMP emit_repeat_again_lz4_s2_emit_copy_short + +repeat_five_lz4_s2_emit_copy_short: + LEAL -65536(R10), R10 + MOVL R10, R9 + MOVW $0x001d, (AX) + MOVW R10, 2(AX) + SARL $0x10, R9 + MOVB R9, 4(AX) + ADDQ $0x05, AX + JMP lz4s_s2_loop + +repeat_four_lz4_s2_emit_copy_short: + LEAL -256(R10), R10 + MOVW $0x0019, (AX) + MOVW R10, 2(AX) + ADDQ $0x04, AX + JMP lz4s_s2_loop + +repeat_three_lz4_s2_emit_copy_short: + LEAL -4(R10), R10 + MOVW $0x0015, (AX) + MOVB R10, 2(AX) + ADDQ $0x03, AX + JMP lz4s_s2_loop + +repeat_two_lz4_s2_emit_copy_short: + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short: + XORQ R8, R8 + LEAL 1(R8)(R10*4), R10 + MOVB R9, 1(AX) + SARL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R10 + MOVB R10, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +two_byte_offset_short_lz4_s2: + MOVL R10, R8 + SHLL $0x02, R8 + CMPL R10, $0x0c + JAE emit_copy_three_lz4_s2 + CMPL R9, $0x00000800 + JAE emit_copy_three_lz4_s2 + LEAL -15(R8), R8 + MOVB R9, 1(AX) + SHRL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R8 + MOVB R8, (AX) + ADDQ $0x02, AX + JMP lz4s_s2_loop + +emit_copy_three_lz4_s2: + LEAL -2(R8), R8 + MOVB R8, (AX) + MOVW R9, 1(AX) + ADDQ $0x03, AX + JMP lz4s_s2_loop + +lz4s_s2_done: + MOVQ dst_base+0(FP), CX + SUBQ CX, AX + MOVQ SI, uncompressed+48(FP) + MOVQ AX, dstUsed+56(FP) + RET + +lz4s_s2_corrupt: + XORQ AX, AX + LEAQ -1(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +lz4s_s2_dstfull: + XORQ AX, AX + LEAQ -2(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +// func cvtLZ4BlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4BlockSnappyAsm(SB), NOSPLIT, $0-64 + XORQ SI, SI + MOVQ dst_base+0(FP), AX + MOVQ dst_len+8(FP), CX + MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), BX + LEAQ (DX)(BX*1), BX + LEAQ -8(AX)(CX*1), CX + +lz4_snappy_loop: + CMPQ DX, BX + JAE lz4_snappy_corrupt + CMPQ AX, CX + JAE lz4_snappy_dstfull + MOVBQZX (DX), DI + MOVQ DI, R8 + MOVQ DI, R9 + SHRQ $0x04, R8 + ANDQ $0x0f, R9 + CMPQ DI, $0xf0 + JB lz4_snappy_ll_end + +lz4_snappy_ll_loop: + INCQ DX + CMPQ DX, BX + JAE lz4_snappy_corrupt + MOVBQZX (DX), DI + ADDQ DI, R8 + CMPQ DI, $0xff + JEQ lz4_snappy_ll_loop + +lz4_snappy_ll_end: + LEAQ (DX)(R8*1), DI + ADDQ $0x04, R9 + CMPQ DI, BX + JAE lz4_snappy_corrupt + INCQ DX + INCQ DI + TESTQ R8, R8 + JZ lz4_snappy_lits_done + LEAQ (AX)(R8*1), R10 + CMPQ R10, CX + JAE lz4_snappy_dstfull + ADDQ R8, SI + LEAL -1(R8), R10 + CMPL R10, $0x3c + JB one_byte_lz4_snappy + CMPL R10, $0x00000100 + JB two_bytes_lz4_snappy + CMPL R10, $0x00010000 + JB three_bytes_lz4_snappy + CMPL R10, $0x01000000 + JB four_bytes_lz4_snappy + MOVB $0xfc, (AX) + MOVL R10, 1(AX) + ADDQ $0x05, AX + JMP memmove_long_lz4_snappy + +four_bytes_lz4_snappy: + MOVL R10, R11 + SHRL $0x10, R11 + MOVB $0xf8, (AX) + MOVW R10, 1(AX) + MOVB R11, 3(AX) + ADDQ $0x04, AX + JMP memmove_long_lz4_snappy + +three_bytes_lz4_snappy: + MOVB $0xf4, (AX) + MOVW R10, 1(AX) + ADDQ $0x03, AX + JMP memmove_long_lz4_snappy + +two_bytes_lz4_snappy: + MOVB $0xf0, (AX) + MOVB R10, 1(AX) + ADDQ $0x02, AX + CMPL R10, $0x40 + JB memmove_lz4_snappy + JMP memmove_long_lz4_snappy + +one_byte_lz4_snappy: + SHLB $0x02, R10 + MOVB R10, (AX) + ADDQ $0x01, AX + +memmove_lz4_snappy: + LEAQ (AX)(R8*1), R10 + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_lz4_snappy_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_lz4_snappy_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_lz4_snappy_memmove_move_17through32 + JMP emit_lit_memmove_lz4_snappy_memmove_move_33through64 + +emit_lit_memmove_lz4_snappy_memmove_move_8: + MOVQ (DX), R11 + MOVQ R11, (AX) + JMP memmove_end_copy_lz4_snappy + +emit_lit_memmove_lz4_snappy_memmove_move_8through16: + MOVQ (DX), R11 + MOVQ -8(DX)(R8*1), DX + MOVQ R11, (AX) + MOVQ DX, -8(AX)(R8*1) + JMP memmove_end_copy_lz4_snappy + +emit_lit_memmove_lz4_snappy_memmove_move_17through32: + MOVOU (DX), X0 + MOVOU -16(DX)(R8*1), X1 + MOVOU X0, (AX) + MOVOU X1, -16(AX)(R8*1) + JMP memmove_end_copy_lz4_snappy + +emit_lit_memmove_lz4_snappy_memmove_move_33through64: + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R8*1), X2 + MOVOU -16(DX)(R8*1), X3 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R8*1) + MOVOU X3, -16(AX)(R8*1) + +memmove_end_copy_lz4_snappy: + MOVQ R10, AX + JMP lz4_snappy_lits_emit_done + +memmove_long_lz4_snappy: + LEAQ (AX)(R8*1), R10 + + // genMemMoveLong + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R8*1), X2 + MOVOU -16(DX)(R8*1), X3 + MOVQ R8, R12 + SHRQ $0x05, R12 + MOVQ AX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_lz4_snappylarge_forward_sse_loop_32 + LEAQ -32(DX)(R13*1), R11 + LEAQ -32(AX)(R13*1), R14 + +emit_lit_memmove_long_lz4_snappylarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_lz4_snappylarge_big_loop_back + +emit_lit_memmove_long_lz4_snappylarge_forward_sse_loop_32: + MOVOU -32(DX)(R13*1), X4 + MOVOU -16(DX)(R13*1), X5 + MOVOA X4, -32(AX)(R13*1) + MOVOA X5, -16(AX)(R13*1) + ADDQ $0x20, R13 + CMPQ R8, R13 + JAE emit_lit_memmove_long_lz4_snappylarge_forward_sse_loop_32 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R8*1) + MOVOU X3, -16(AX)(R8*1) + MOVQ R10, AX + +lz4_snappy_lits_emit_done: + MOVQ DI, DX + +lz4_snappy_lits_done: + CMPQ DX, BX + JNE lz4_snappy_match + CMPQ R9, $0x04 + JEQ lz4_snappy_done + JMP lz4_snappy_corrupt + +lz4_snappy_match: + LEAQ 2(DX), DI + CMPQ DI, BX + JAE lz4_snappy_corrupt + MOVWQZX (DX), R8 + MOVQ DI, DX + TESTQ R8, R8 + JZ lz4_snappy_corrupt + CMPQ R8, SI + JA lz4_snappy_corrupt + CMPQ R9, $0x13 + JNE lz4_snappy_ml_done + +lz4_snappy_ml_loop: + MOVBQZX (DX), DI + INCQ DX + ADDQ DI, R9 + CMPQ DX, BX + JAE lz4_snappy_corrupt + CMPQ DI, $0xff + JEQ lz4_snappy_ml_loop + +lz4_snappy_ml_done: + ADDQ R9, SI + + // emitCopy +two_byte_offset_lz4_s2: + CMPL R9, $0x40 + JBE two_byte_offset_short_lz4_s2 + MOVB $0xee, (AX) + MOVW R8, 1(AX) + LEAL -60(R9), R9 + ADDQ $0x03, AX + CMPQ AX, CX + JAE lz4_snappy_loop + JMP two_byte_offset_lz4_s2 + +two_byte_offset_short_lz4_s2: + MOVL R9, DI + SHLL $0x02, DI + CMPL R9, $0x0c + JAE emit_copy_three_lz4_s2 + CMPL R8, $0x00000800 + JAE emit_copy_three_lz4_s2 + LEAL -15(DI), DI + MOVB R8, 1(AX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, DI + MOVB DI, (AX) + ADDQ $0x02, AX + JMP lz4_snappy_loop + +emit_copy_three_lz4_s2: + LEAL -2(DI), DI + MOVB DI, (AX) + MOVW R8, 1(AX) + ADDQ $0x03, AX + JMP lz4_snappy_loop + +lz4_snappy_done: + MOVQ dst_base+0(FP), CX + SUBQ CX, AX + MOVQ SI, uncompressed+48(FP) + MOVQ AX, dstUsed+56(FP) + RET + +lz4_snappy_corrupt: + XORQ AX, AX + LEAQ -1(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +lz4_snappy_dstfull: + XORQ AX, AX + LEAQ -2(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +// func cvtLZ4sBlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4sBlockSnappyAsm(SB), NOSPLIT, $0-64 + XORQ SI, SI + MOVQ dst_base+0(FP), AX + MOVQ dst_len+8(FP), CX + MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), BX + LEAQ (DX)(BX*1), BX + LEAQ -8(AX)(CX*1), CX + +lz4s_snappy_loop: + CMPQ DX, BX + JAE lz4s_snappy_corrupt + CMPQ AX, CX + JAE lz4s_snappy_dstfull + MOVBQZX (DX), DI + MOVQ DI, R8 + MOVQ DI, R9 + SHRQ $0x04, R8 + ANDQ $0x0f, R9 + CMPQ DI, $0xf0 + JB lz4s_snappy_ll_end + +lz4s_snappy_ll_loop: + INCQ DX + CMPQ DX, BX + JAE lz4s_snappy_corrupt + MOVBQZX (DX), DI + ADDQ DI, R8 + CMPQ DI, $0xff + JEQ lz4s_snappy_ll_loop + +lz4s_snappy_ll_end: + LEAQ (DX)(R8*1), DI + ADDQ $0x03, R9 + CMPQ DI, BX + JAE lz4s_snappy_corrupt + INCQ DX + INCQ DI + TESTQ R8, R8 + JZ lz4s_snappy_lits_done + LEAQ (AX)(R8*1), R10 + CMPQ R10, CX + JAE lz4s_snappy_dstfull + ADDQ R8, SI + LEAL -1(R8), R10 + CMPL R10, $0x3c + JB one_byte_lz4s_snappy + CMPL R10, $0x00000100 + JB two_bytes_lz4s_snappy + CMPL R10, $0x00010000 + JB three_bytes_lz4s_snappy + CMPL R10, $0x01000000 + JB four_bytes_lz4s_snappy + MOVB $0xfc, (AX) + MOVL R10, 1(AX) + ADDQ $0x05, AX + JMP memmove_long_lz4s_snappy + +four_bytes_lz4s_snappy: + MOVL R10, R11 + SHRL $0x10, R11 + MOVB $0xf8, (AX) + MOVW R10, 1(AX) + MOVB R11, 3(AX) + ADDQ $0x04, AX + JMP memmove_long_lz4s_snappy + +three_bytes_lz4s_snappy: + MOVB $0xf4, (AX) + MOVW R10, 1(AX) + ADDQ $0x03, AX + JMP memmove_long_lz4s_snappy + +two_bytes_lz4s_snappy: + MOVB $0xf0, (AX) + MOVB R10, 1(AX) + ADDQ $0x02, AX + CMPL R10, $0x40 + JB memmove_lz4s_snappy + JMP memmove_long_lz4s_snappy + +one_byte_lz4s_snappy: + SHLB $0x02, R10 + MOVB R10, (AX) + ADDQ $0x01, AX + +memmove_lz4s_snappy: + LEAQ (AX)(R8*1), R10 + + // genMemMoveShort + CMPQ R8, $0x08 + JBE emit_lit_memmove_lz4s_snappy_memmove_move_8 + CMPQ R8, $0x10 + JBE emit_lit_memmove_lz4s_snappy_memmove_move_8through16 + CMPQ R8, $0x20 + JBE emit_lit_memmove_lz4s_snappy_memmove_move_17through32 + JMP emit_lit_memmove_lz4s_snappy_memmove_move_33through64 + +emit_lit_memmove_lz4s_snappy_memmove_move_8: + MOVQ (DX), R11 + MOVQ R11, (AX) + JMP memmove_end_copy_lz4s_snappy + +emit_lit_memmove_lz4s_snappy_memmove_move_8through16: + MOVQ (DX), R11 + MOVQ -8(DX)(R8*1), DX + MOVQ R11, (AX) + MOVQ DX, -8(AX)(R8*1) + JMP memmove_end_copy_lz4s_snappy + +emit_lit_memmove_lz4s_snappy_memmove_move_17through32: + MOVOU (DX), X0 + MOVOU -16(DX)(R8*1), X1 + MOVOU X0, (AX) + MOVOU X1, -16(AX)(R8*1) + JMP memmove_end_copy_lz4s_snappy + +emit_lit_memmove_lz4s_snappy_memmove_move_33through64: + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R8*1), X2 + MOVOU -16(DX)(R8*1), X3 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R8*1) + MOVOU X3, -16(AX)(R8*1) + +memmove_end_copy_lz4s_snappy: + MOVQ R10, AX + JMP lz4s_snappy_lits_emit_done + +memmove_long_lz4s_snappy: + LEAQ (AX)(R8*1), R10 + + // genMemMoveLong + MOVOU (DX), X0 + MOVOU 16(DX), X1 + MOVOU -32(DX)(R8*1), X2 + MOVOU -16(DX)(R8*1), X3 + MOVQ R8, R12 + SHRQ $0x05, R12 + MOVQ AX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 + JA emit_lit_memmove_long_lz4s_snappylarge_forward_sse_loop_32 + LEAQ -32(DX)(R13*1), R11 + LEAQ -32(AX)(R13*1), R14 + +emit_lit_memmove_long_lz4s_snappylarge_big_loop_back: + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 + ADDQ $0x20, R13 + DECQ R12 + JNA emit_lit_memmove_long_lz4s_snappylarge_big_loop_back + +emit_lit_memmove_long_lz4s_snappylarge_forward_sse_loop_32: + MOVOU -32(DX)(R13*1), X4 + MOVOU -16(DX)(R13*1), X5 + MOVOA X4, -32(AX)(R13*1) + MOVOA X5, -16(AX)(R13*1) + ADDQ $0x20, R13 + CMPQ R8, R13 + JAE emit_lit_memmove_long_lz4s_snappylarge_forward_sse_loop_32 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, -32(AX)(R8*1) + MOVOU X3, -16(AX)(R8*1) + MOVQ R10, AX + +lz4s_snappy_lits_emit_done: + MOVQ DI, DX + +lz4s_snappy_lits_done: + CMPQ DX, BX + JNE lz4s_snappy_match + CMPQ R9, $0x03 + JEQ lz4s_snappy_done + JMP lz4s_snappy_corrupt + +lz4s_snappy_match: + CMPQ R9, $0x03 + JEQ lz4s_snappy_loop + LEAQ 2(DX), DI + CMPQ DI, BX + JAE lz4s_snappy_corrupt + MOVWQZX (DX), R8 + MOVQ DI, DX + TESTQ R8, R8 + JZ lz4s_snappy_corrupt + CMPQ R8, SI + JA lz4s_snappy_corrupt + CMPQ R9, $0x12 + JNE lz4s_snappy_ml_done + +lz4s_snappy_ml_loop: + MOVBQZX (DX), DI + INCQ DX + ADDQ DI, R9 + CMPQ DX, BX + JAE lz4s_snappy_corrupt + CMPQ DI, $0xff + JEQ lz4s_snappy_ml_loop + +lz4s_snappy_ml_done: + ADDQ R9, SI + + // emitCopy +two_byte_offset_lz4_s2: + CMPL R9, $0x40 + JBE two_byte_offset_short_lz4_s2 + MOVB $0xee, (AX) + MOVW R8, 1(AX) + LEAL -60(R9), R9 + ADDQ $0x03, AX + CMPQ AX, CX + JAE lz4s_snappy_loop + JMP two_byte_offset_lz4_s2 + +two_byte_offset_short_lz4_s2: + MOVL R9, DI + SHLL $0x02, DI + CMPL R9, $0x0c + JAE emit_copy_three_lz4_s2 + CMPL R8, $0x00000800 + JAE emit_copy_three_lz4_s2 + LEAL -15(DI), DI + MOVB R8, 1(AX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, DI + MOVB DI, (AX) + ADDQ $0x02, AX + JMP lz4s_snappy_loop + +emit_copy_three_lz4_s2: + LEAL -2(DI), DI + MOVB DI, (AX) + MOVW R8, 1(AX) + ADDQ $0x03, AX + JMP lz4s_snappy_loop + +lz4s_snappy_done: + MOVQ dst_base+0(FP), CX + SUBQ CX, AX + MOVQ SI, uncompressed+48(FP) + MOVQ AX, dstUsed+56(FP) + RET + +lz4s_snappy_corrupt: + XORQ AX, AX + LEAQ -1(AX), SI + MOVQ SI, uncompressed+48(FP) + RET + +lz4s_snappy_dstfull: + XORQ AX, AX + LEAQ -2(AX), SI + MOVQ SI, uncompressed+48(FP) + RET diff --git a/vendor/github.com/klauspost/compress/s2/index.go b/vendor/github.com/klauspost/compress/s2/index.go new file mode 100644 index 0000000..fb7db25 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/index.go @@ -0,0 +1,602 @@ +// Copyright (c) 2022+ Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "io" + "sort" +) + +const ( + S2IndexHeader = "s2idx\x00" + S2IndexTrailer = "\x00xdi2s" + maxIndexEntries = 1 << 16 + // If distance is less than this, we do not add the entry. + minIndexDist = 1 << 20 +) + +// Index represents an S2/Snappy index. +type Index struct { + TotalUncompressed int64 // Total Uncompressed size if known. Will be -1 if unknown. + TotalCompressed int64 // Total Compressed size if known. Will be -1 if unknown. + info []struct { + compressedOffset int64 + uncompressedOffset int64 + } + estBlockUncomp int64 +} + +func (i *Index) reset(maxBlock int) { + i.estBlockUncomp = int64(maxBlock) + i.TotalCompressed = -1 + i.TotalUncompressed = -1 + if len(i.info) > 0 { + i.info = i.info[:0] + } +} + +// allocInfos will allocate an empty slice of infos. +func (i *Index) allocInfos(n int) { + if n > maxIndexEntries { + panic("n > maxIndexEntries") + } + i.info = make([]struct { + compressedOffset int64 + uncompressedOffset int64 + }, 0, n) +} + +// add an uncompressed and compressed pair. +// Entries must be sent in order. +func (i *Index) add(compressedOffset, uncompressedOffset int64) error { + if i == nil { + return nil + } + lastIdx := len(i.info) - 1 + if lastIdx >= 0 { + latest := i.info[lastIdx] + if latest.uncompressedOffset == uncompressedOffset { + // Uncompressed didn't change, don't add entry, + // but update start index. + latest.compressedOffset = compressedOffset + i.info[lastIdx] = latest + return nil + } + if latest.uncompressedOffset > uncompressedOffset { + return fmt.Errorf("internal error: Earlier uncompressed received (%d > %d)", latest.uncompressedOffset, uncompressedOffset) + } + if latest.compressedOffset > compressedOffset { + return fmt.Errorf("internal error: Earlier compressed received (%d > %d)", latest.compressedOffset, compressedOffset) + } + if latest.uncompressedOffset+minIndexDist > uncompressedOffset { + // Only add entry if distance is large enough. + return nil + } + } + i.info = append(i.info, struct { + compressedOffset int64 + uncompressedOffset int64 + }{compressedOffset: compressedOffset, uncompressedOffset: uncompressedOffset}) + return nil +} + +// Find the offset at or before the wanted (uncompressed) offset. +// If offset is 0 or positive it is the offset from the beginning of the file. +// If the uncompressed size is known, the offset must be within the file. +// If an offset outside the file is requested io.ErrUnexpectedEOF is returned. +// If the offset is negative, it is interpreted as the distance from the end of the file, +// where -1 represents the last byte. +// If offset from the end of the file is requested, but size is unknown, +// ErrUnsupported will be returned. +func (i *Index) Find(offset int64) (compressedOff, uncompressedOff int64, err error) { + if i.TotalUncompressed < 0 { + return 0, 0, ErrCorrupt + } + if offset < 0 { + offset = i.TotalUncompressed + offset + if offset < 0 { + return 0, 0, io.ErrUnexpectedEOF + } + } + if offset > i.TotalUncompressed { + return 0, 0, io.ErrUnexpectedEOF + } + if len(i.info) > 200 { + n := sort.Search(len(i.info), func(n int) bool { + return i.info[n].uncompressedOffset > offset + }) + if n == 0 { + n = 1 + } + return i.info[n-1].compressedOffset, i.info[n-1].uncompressedOffset, nil + } + for _, info := range i.info { + if info.uncompressedOffset > offset { + break + } + compressedOff = info.compressedOffset + uncompressedOff = info.uncompressedOffset + } + return compressedOff, uncompressedOff, nil +} + +// reduce to stay below maxIndexEntries +func (i *Index) reduce() { + if len(i.info) < maxIndexEntries && i.estBlockUncomp >= minIndexDist { + return + } + + // Algorithm, keep 1, remove removeN entries... + removeN := (len(i.info) + 1) / maxIndexEntries + src := i.info + j := 0 + + // Each block should be at least 1MB, but don't reduce below 1000 entries. + for i.estBlockUncomp*(int64(removeN)+1) < minIndexDist && len(i.info)/(removeN+1) > 1000 { + removeN++ + } + for idx := 0; idx < len(src); idx++ { + i.info[j] = src[idx] + j++ + idx += removeN + } + i.info = i.info[:j] + // Update maxblock estimate. + i.estBlockUncomp += i.estBlockUncomp * int64(removeN) +} + +func (i *Index) appendTo(b []byte, uncompTotal, compTotal int64) []byte { + i.reduce() + var tmp [binary.MaxVarintLen64]byte + + initSize := len(b) + // We make the start a skippable header+size. + b = append(b, ChunkTypeIndex, 0, 0, 0) + b = append(b, []byte(S2IndexHeader)...) + // Total Uncompressed size + n := binary.PutVarint(tmp[:], uncompTotal) + b = append(b, tmp[:n]...) + // Total Compressed size + n = binary.PutVarint(tmp[:], compTotal) + b = append(b, tmp[:n]...) + // Put EstBlockUncomp size + n = binary.PutVarint(tmp[:], i.estBlockUncomp) + b = append(b, tmp[:n]...) + // Put length + n = binary.PutVarint(tmp[:], int64(len(i.info))) + b = append(b, tmp[:n]...) + + // Check if we should add uncompressed offsets + var hasUncompressed byte + for idx, info := range i.info { + if idx == 0 { + if info.uncompressedOffset != 0 { + hasUncompressed = 1 + break + } + continue + } + if info.uncompressedOffset != i.info[idx-1].uncompressedOffset+i.estBlockUncomp { + hasUncompressed = 1 + break + } + } + b = append(b, hasUncompressed) + + // Add each entry + if hasUncompressed == 1 { + for idx, info := range i.info { + uOff := info.uncompressedOffset + if idx > 0 { + prev := i.info[idx-1] + uOff -= prev.uncompressedOffset + (i.estBlockUncomp) + } + n = binary.PutVarint(tmp[:], uOff) + b = append(b, tmp[:n]...) + } + } + + // Initial compressed size estimate. + cPredict := i.estBlockUncomp / 2 + + for idx, info := range i.info { + cOff := info.compressedOffset + if idx > 0 { + prev := i.info[idx-1] + cOff -= prev.compressedOffset + cPredict + // Update compressed size prediction, with half the error. + cPredict += cOff / 2 + } + n = binary.PutVarint(tmp[:], cOff) + b = append(b, tmp[:n]...) + } + + // Add Total Size. + // Stored as fixed size for easier reading. + binary.LittleEndian.PutUint32(tmp[:], uint32(len(b)-initSize+4+len(S2IndexTrailer))) + b = append(b, tmp[:4]...) + // Trailer + b = append(b, []byte(S2IndexTrailer)...) + + // Update size + chunkLen := len(b) - initSize - skippableFrameHeader + b[initSize+1] = uint8(chunkLen >> 0) + b[initSize+2] = uint8(chunkLen >> 8) + b[initSize+3] = uint8(chunkLen >> 16) + //fmt.Printf("chunklen: 0x%x Uncomp:%d, Comp:%d\n", chunkLen, uncompTotal, compTotal) + return b +} + +// Load a binary index. +// A zero value Index can be used or a previous one can be reused. +func (i *Index) Load(b []byte) ([]byte, error) { + if len(b) <= 4+len(S2IndexHeader)+len(S2IndexTrailer) { + return b, io.ErrUnexpectedEOF + } + if b[0] != ChunkTypeIndex { + return b, ErrCorrupt + } + chunkLen := int(b[1]) | int(b[2])<<8 | int(b[3])<<16 + b = b[4:] + + // Validate we have enough... + if len(b) < chunkLen { + return b, io.ErrUnexpectedEOF + } + if !bytes.Equal(b[:len(S2IndexHeader)], []byte(S2IndexHeader)) { + return b, ErrUnsupported + } + b = b[len(S2IndexHeader):] + + // Total Uncompressed + if v, n := binary.Varint(b); n <= 0 || v < 0 { + return b, ErrCorrupt + } else { + i.TotalUncompressed = v + b = b[n:] + } + + // Total Compressed + if v, n := binary.Varint(b); n <= 0 { + return b, ErrCorrupt + } else { + i.TotalCompressed = v + b = b[n:] + } + + // Read EstBlockUncomp + if v, n := binary.Varint(b); n <= 0 { + return b, ErrCorrupt + } else { + if v < 0 { + return b, ErrCorrupt + } + i.estBlockUncomp = v + b = b[n:] + } + + var entries int + if v, n := binary.Varint(b); n <= 0 { + return b, ErrCorrupt + } else { + if v < 0 || v > maxIndexEntries { + return b, ErrCorrupt + } + entries = int(v) + b = b[n:] + } + if cap(i.info) < entries { + i.allocInfos(entries) + } + i.info = i.info[:entries] + + if len(b) < 1 { + return b, io.ErrUnexpectedEOF + } + hasUncompressed := b[0] + b = b[1:] + if hasUncompressed&1 != hasUncompressed { + return b, ErrCorrupt + } + + // Add each uncompressed entry + for idx := range i.info { + var uOff int64 + if hasUncompressed != 0 { + // Load delta + if v, n := binary.Varint(b); n <= 0 { + return b, ErrCorrupt + } else { + uOff = v + b = b[n:] + } + } + + if idx > 0 { + prev := i.info[idx-1].uncompressedOffset + uOff += prev + (i.estBlockUncomp) + if uOff <= prev { + return b, ErrCorrupt + } + } + if uOff < 0 { + return b, ErrCorrupt + } + i.info[idx].uncompressedOffset = uOff + } + + // Initial compressed size estimate. + cPredict := i.estBlockUncomp / 2 + + // Add each compressed entry + for idx := range i.info { + var cOff int64 + if v, n := binary.Varint(b); n <= 0 { + return b, ErrCorrupt + } else { + cOff = v + b = b[n:] + } + + if idx > 0 { + // Update compressed size prediction, with half the error. + cPredictNew := cPredict + cOff/2 + + prev := i.info[idx-1].compressedOffset + cOff += prev + cPredict + if cOff <= prev { + return b, ErrCorrupt + } + cPredict = cPredictNew + } + if cOff < 0 { + return b, ErrCorrupt + } + i.info[idx].compressedOffset = cOff + } + if len(b) < 4+len(S2IndexTrailer) { + return b, io.ErrUnexpectedEOF + } + // Skip size... + b = b[4:] + + // Check trailer... + if !bytes.Equal(b[:len(S2IndexTrailer)], []byte(S2IndexTrailer)) { + return b, ErrCorrupt + } + return b[len(S2IndexTrailer):], nil +} + +// LoadStream will load an index from the end of the supplied stream. +// ErrUnsupported will be returned if the signature cannot be found. +// ErrCorrupt will be returned if unexpected values are found. +// io.ErrUnexpectedEOF is returned if there are too few bytes. +// IO errors are returned as-is. +func (i *Index) LoadStream(rs io.ReadSeeker) error { + // Go to end. + _, err := rs.Seek(-10, io.SeekEnd) + if err != nil { + return err + } + var tmp [10]byte + _, err = io.ReadFull(rs, tmp[:]) + if err != nil { + return err + } + // Check trailer... + if !bytes.Equal(tmp[4:4+len(S2IndexTrailer)], []byte(S2IndexTrailer)) { + return ErrUnsupported + } + sz := binary.LittleEndian.Uint32(tmp[:4]) + if sz > maxChunkSize+skippableFrameHeader { + return ErrCorrupt + } + _, err = rs.Seek(-int64(sz), io.SeekEnd) + if err != nil { + return err + } + + // Read index. + buf := make([]byte, sz) + _, err = io.ReadFull(rs, buf) + if err != nil { + return err + } + _, err = i.Load(buf) + return err +} + +// IndexStream will return an index for a stream. +// The stream structure will be checked, but +// data within blocks is not verified. +// The returned index can either be appended to the end of the stream +// or stored separately. +func IndexStream(r io.Reader) ([]byte, error) { + var i Index + var buf [maxChunkSize]byte + var readHeader bool + for { + _, err := io.ReadFull(r, buf[:4]) + if err != nil { + if err == io.EOF { + return i.appendTo(nil, i.TotalUncompressed, i.TotalCompressed), nil + } + return nil, err + } + // Start of this chunk. + startChunk := i.TotalCompressed + i.TotalCompressed += 4 + + chunkType := buf[0] + if !readHeader { + if chunkType != chunkTypeStreamIdentifier { + return nil, ErrCorrupt + } + readHeader = true + } + chunkLen := int(buf[1]) | int(buf[2])<<8 | int(buf[3])<<16 + if chunkLen < checksumSize { + return nil, ErrCorrupt + } + + i.TotalCompressed += int64(chunkLen) + _, err = io.ReadFull(r, buf[:chunkLen]) + if err != nil { + return nil, io.ErrUnexpectedEOF + } + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + // Section 4.2. Compressed data (chunk type 0x00). + // Skip checksum. + dLen, err := DecodedLen(buf[checksumSize:]) + if err != nil { + return nil, err + } + if dLen > maxBlockSize { + return nil, ErrCorrupt + } + if i.estBlockUncomp == 0 { + // Use first block for estimate... + i.estBlockUncomp = int64(dLen) + } + err = i.add(startChunk, i.TotalUncompressed) + if err != nil { + return nil, err + } + i.TotalUncompressed += int64(dLen) + continue + case chunkTypeUncompressedData: + n2 := chunkLen - checksumSize + if n2 > maxBlockSize { + return nil, ErrCorrupt + } + if i.estBlockUncomp == 0 { + // Use first block for estimate... + i.estBlockUncomp = int64(n2) + } + err = i.add(startChunk, i.TotalUncompressed) + if err != nil { + return nil, err + } + i.TotalUncompressed += int64(n2) + continue + case chunkTypeStreamIdentifier: + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(magicBody) { + return nil, ErrCorrupt + } + + if string(buf[:len(magicBody)]) != magicBody { + if string(buf[:len(magicBody)]) != magicBodySnappy { + return nil, ErrCorrupt + } + } + + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + return nil, ErrUnsupported + } + if chunkLen > maxChunkSize { + return nil, ErrUnsupported + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + } +} + +// JSON returns the index as JSON text. +func (i *Index) JSON() []byte { + type offset struct { + CompressedOffset int64 `json:"compressed"` + UncompressedOffset int64 `json:"uncompressed"` + } + x := struct { + TotalUncompressed int64 `json:"total_uncompressed"` // Total Uncompressed size if known. Will be -1 if unknown. + TotalCompressed int64 `json:"total_compressed"` // Total Compressed size if known. Will be -1 if unknown. + Offsets []offset `json:"offsets"` + EstBlockUncomp int64 `json:"est_block_uncompressed"` + }{ + TotalUncompressed: i.TotalUncompressed, + TotalCompressed: i.TotalCompressed, + EstBlockUncomp: i.estBlockUncomp, + } + for _, v := range i.info { + x.Offsets = append(x.Offsets, offset{CompressedOffset: v.compressedOffset, UncompressedOffset: v.uncompressedOffset}) + } + b, _ := json.MarshalIndent(x, "", " ") + return b +} + +// RemoveIndexHeaders will trim all headers and trailers from a given index. +// This is expected to save 20 bytes. +// These can be restored using RestoreIndexHeaders. +// This removes a layer of security, but is the most compact representation. +// Returns nil if headers contains errors. +// The returned slice references the provided slice. +func RemoveIndexHeaders(b []byte) []byte { + const save = 4 + len(S2IndexHeader) + len(S2IndexTrailer) + 4 + if len(b) <= save { + return nil + } + if b[0] != ChunkTypeIndex { + return nil + } + chunkLen := int(b[1]) | int(b[2])<<8 | int(b[3])<<16 + b = b[4:] + + // Validate we have enough... + if len(b) < chunkLen { + return nil + } + b = b[:chunkLen] + + if !bytes.Equal(b[:len(S2IndexHeader)], []byte(S2IndexHeader)) { + return nil + } + b = b[len(S2IndexHeader):] + if !bytes.HasSuffix(b, []byte(S2IndexTrailer)) { + return nil + } + b = bytes.TrimSuffix(b, []byte(S2IndexTrailer)) + + if len(b) < 4 { + return nil + } + return b[:len(b)-4] +} + +// RestoreIndexHeaders will index restore headers removed by RemoveIndexHeaders. +// No error checking is performed on the input. +// If a 0 length slice is sent, it is returned without modification. +func RestoreIndexHeaders(in []byte) []byte { + if len(in) == 0 { + return in + } + b := make([]byte, 0, 4+len(S2IndexHeader)+len(in)+len(S2IndexTrailer)+4) + b = append(b, ChunkTypeIndex, 0, 0, 0) + b = append(b, []byte(S2IndexHeader)...) + b = append(b, in...) + + var tmp [4]byte + binary.LittleEndian.PutUint32(tmp[:], uint32(len(b)+4+len(S2IndexTrailer))) + b = append(b, tmp[:4]...) + // Trailer + b = append(b, []byte(S2IndexTrailer)...) + + chunkLen := len(b) - skippableFrameHeader + b[1] = uint8(chunkLen >> 0) + b[2] = uint8(chunkLen >> 8) + b[3] = uint8(chunkLen >> 16) + return b +} diff --git a/vendor/github.com/klauspost/compress/s2/lz4convert.go b/vendor/github.com/klauspost/compress/s2/lz4convert.go new file mode 100644 index 0000000..46ed908 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/lz4convert.go @@ -0,0 +1,585 @@ +// Copyright (c) 2022 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "encoding/binary" + "errors" + "fmt" +) + +// LZ4Converter provides conversion from LZ4 blocks as defined here: +// https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md +type LZ4Converter struct { +} + +// ErrDstTooSmall is returned when provided destination is too small. +var ErrDstTooSmall = errors.New("s2: destination too small") + +// ConvertBlock will convert an LZ4 block and append it as an S2 +// block without block length to dst. +// The uncompressed size is returned as well. +// dst must have capacity to contain the entire compressed block. +func (l *LZ4Converter) ConvertBlock(dst, src []byte) ([]byte, int, error) { + if len(src) == 0 { + return dst, 0, nil + } + const debug = false + const inline = true + const lz4MinMatch = 4 + + s, d := 0, len(dst) + dst = dst[:cap(dst)] + if !debug && hasAmd64Asm { + res, sz := cvtLZ4BlockAsm(dst[d:], src) + if res < 0 { + const ( + errCorrupt = -1 + errDstTooSmall = -2 + ) + switch res { + case errCorrupt: + return nil, 0, ErrCorrupt + case errDstTooSmall: + return nil, 0, ErrDstTooSmall + default: + return nil, 0, fmt.Errorf("unexpected result: %d", res) + } + } + if d+sz > len(dst) { + return nil, 0, ErrDstTooSmall + } + return dst[:d+sz], res, nil + } + + dLimit := len(dst) - 10 + var lastOffset uint16 + var uncompressed int + if debug { + fmt.Printf("convert block start: len(src): %d, len(dst):%d \n", len(src), len(dst)) + } + + for { + if s >= len(src) { + return dst[:d], 0, ErrCorrupt + } + // Read literal info + token := src[s] + ll := int(token >> 4) + ml := int(lz4MinMatch + (token & 0xf)) + + // If upper nibble is 15, literal length is extended + if token >= 0xf0 { + for { + s++ + if s >= len(src) { + if debug { + fmt.Printf("error reading ll: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return dst[:d], 0, ErrCorrupt + } + val := src[s] + ll += int(val) + if val != 255 { + break + } + } + } + // Skip past token + if s+ll >= len(src) { + if debug { + fmt.Printf("error literals: s+ll (%d+%d) >= len(src) (%d)\n", s, ll, len(src)) + } + return nil, 0, ErrCorrupt + } + s++ + if ll > 0 { + if d+ll > dLimit { + return nil, 0, ErrDstTooSmall + } + if debug { + fmt.Printf("emit %d literals\n", ll) + } + d += emitLiteralGo(dst[d:], src[s:s+ll]) + s += ll + uncompressed += ll + } + + // Check if we are done... + if s == len(src) && ml == lz4MinMatch { + break + } + // 2 byte offset + if s >= len(src)-2 { + if debug { + fmt.Printf("s (%d) >= len(src)-2 (%d)", s, len(src)-2) + } + return nil, 0, ErrCorrupt + } + offset := binary.LittleEndian.Uint16(src[s:]) + s += 2 + if offset == 0 { + if debug { + fmt.Printf("error: offset 0, ml: %d, len(src)-s: %d\n", ml, len(src)-s) + } + return nil, 0, ErrCorrupt + } + if int(offset) > uncompressed { + if debug { + fmt.Printf("error: offset (%d)> uncompressed (%d)\n", offset, uncompressed) + } + return nil, 0, ErrCorrupt + } + + if ml == lz4MinMatch+15 { + for { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + val := src[s] + s++ + ml += int(val) + if val != 255 { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + break + } + } + } + if offset == lastOffset { + if debug { + fmt.Printf("emit repeat, length: %d, offset: %d\n", ml, offset) + } + if !inline { + d += emitRepeat16(dst[d:], offset, ml) + } else { + length := ml + dst := dst[d:] + for len(dst) > 5 { + // Repeat offset, make length cheaper + length -= 4 + if length <= 4 { + dst[0] = uint8(length)<<2 | tagCopy1 + dst[1] = 0 + d += 2 + break + } + if length < 8 && offset < 2048 { + // Encode WITH offset + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length)<<2 | tagCopy1 + d += 2 + break + } + if length < (1<<8)+4 { + length -= 4 + dst[2] = uint8(length) + dst[1] = 0 + dst[0] = 5<<2 | tagCopy1 + d += 3 + break + } + if length < (1<<16)+(1<<8) { + length -= 1 << 8 + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 6<<2 | tagCopy1 + d += 4 + break + } + const maxRepeat = (1 << 24) - 1 + length -= 1 << 16 + left := 0 + if length > maxRepeat { + left = length - maxRepeat + 4 + length = maxRepeat - 4 + } + dst[4] = uint8(length >> 16) + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 7<<2 | tagCopy1 + if left > 0 { + d += 5 + emitRepeat16(dst[5:], offset, left) + break + } + d += 5 + break + } + } + } else { + if debug { + fmt.Printf("emit copy, length: %d, offset: %d\n", ml, offset) + } + if !inline { + d += emitCopy16(dst[d:], offset, ml) + } else { + length := ml + dst := dst[d:] + for len(dst) > 5 { + // Offset no more than 2 bytes. + if length > 64 { + off := 3 + if offset < 2048 { + // emit 8 bytes as tagCopy1, rest as repeats. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(8-4)<<2 | tagCopy1 + length -= 8 + off = 2 + } else { + // Emit a length 60 copy, encoded as 3 bytes. + // Emit remaining as repeat value (minimum 4 bytes). + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 59<<2 | tagCopy2 + length -= 60 + } + // Emit remaining as repeats, at least 4 bytes remain. + d += off + emitRepeat16(dst[off:], offset, length) + break + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = uint8(length-1)<<2 | tagCopy2 + d += 3 + break + } + // Emit the remaining copy, encoded as 2 bytes. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + d += 2 + break + } + } + lastOffset = offset + } + uncompressed += ml + if d > dLimit { + return nil, 0, ErrDstTooSmall + } + } + + return dst[:d], uncompressed, nil +} + +// ConvertBlockSnappy will convert an LZ4 block and append it +// as a Snappy block without block length to dst. +// The uncompressed size is returned as well. +// dst must have capacity to contain the entire compressed block. +func (l *LZ4Converter) ConvertBlockSnappy(dst, src []byte) ([]byte, int, error) { + if len(src) == 0 { + return dst, 0, nil + } + const debug = false + const lz4MinMatch = 4 + + s, d := 0, len(dst) + dst = dst[:cap(dst)] + // Use assembly when possible + if !debug && hasAmd64Asm { + res, sz := cvtLZ4BlockSnappyAsm(dst[d:], src) + if res < 0 { + const ( + errCorrupt = -1 + errDstTooSmall = -2 + ) + switch res { + case errCorrupt: + return nil, 0, ErrCorrupt + case errDstTooSmall: + return nil, 0, ErrDstTooSmall + default: + return nil, 0, fmt.Errorf("unexpected result: %d", res) + } + } + if d+sz > len(dst) { + return nil, 0, ErrDstTooSmall + } + return dst[:d+sz], res, nil + } + + dLimit := len(dst) - 10 + var uncompressed int + if debug { + fmt.Printf("convert block start: len(src): %d, len(dst):%d \n", len(src), len(dst)) + } + + for { + if s >= len(src) { + return nil, 0, ErrCorrupt + } + // Read literal info + token := src[s] + ll := int(token >> 4) + ml := int(lz4MinMatch + (token & 0xf)) + + // If upper nibble is 15, literal length is extended + if token >= 0xf0 { + for { + s++ + if s >= len(src) { + if debug { + fmt.Printf("error reading ll: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + val := src[s] + ll += int(val) + if val != 255 { + break + } + } + } + // Skip past token + if s+ll >= len(src) { + if debug { + fmt.Printf("error literals: s+ll (%d+%d) >= len(src) (%d)\n", s, ll, len(src)) + } + return nil, 0, ErrCorrupt + } + s++ + if ll > 0 { + if d+ll > dLimit { + return nil, 0, ErrDstTooSmall + } + if debug { + fmt.Printf("emit %d literals\n", ll) + } + d += emitLiteralGo(dst[d:], src[s:s+ll]) + s += ll + uncompressed += ll + } + + // Check if we are done... + if s == len(src) && ml == lz4MinMatch { + break + } + // 2 byte offset + if s >= len(src)-2 { + if debug { + fmt.Printf("s (%d) >= len(src)-2 (%d)", s, len(src)-2) + } + return nil, 0, ErrCorrupt + } + offset := binary.LittleEndian.Uint16(src[s:]) + s += 2 + if offset == 0 { + if debug { + fmt.Printf("error: offset 0, ml: %d, len(src)-s: %d\n", ml, len(src)-s) + } + return nil, 0, ErrCorrupt + } + if int(offset) > uncompressed { + if debug { + fmt.Printf("error: offset (%d)> uncompressed (%d)\n", offset, uncompressed) + } + return nil, 0, ErrCorrupt + } + + if ml == lz4MinMatch+15 { + for { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + val := src[s] + s++ + ml += int(val) + if val != 255 { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + break + } + } + } + if debug { + fmt.Printf("emit copy, length: %d, offset: %d\n", ml, offset) + } + length := ml + // d += emitCopyNoRepeat(dst[d:], int(offset), ml) + for length > 0 { + if d >= dLimit { + return nil, 0, ErrDstTooSmall + } + + // Offset no more than 2 bytes. + if length > 64 { + // Emit a length 64 copy, encoded as 3 bytes. + dst[d+2] = uint8(offset >> 8) + dst[d+1] = uint8(offset) + dst[d+0] = 63<<2 | tagCopy2 + length -= 64 + d += 3 + continue + } + if length >= 12 || offset >= 2048 || length < 4 { + // Emit the remaining copy, encoded as 3 bytes. + dst[d+2] = uint8(offset >> 8) + dst[d+1] = uint8(offset) + dst[d+0] = uint8(length-1)<<2 | tagCopy2 + d += 3 + break + } + // Emit the remaining copy, encoded as 2 bytes. + dst[d+1] = uint8(offset) + dst[d+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + d += 2 + break + } + uncompressed += ml + if d > dLimit { + return nil, 0, ErrDstTooSmall + } + } + + return dst[:d], uncompressed, nil +} + +// emitRepeat writes a repeat chunk and returns the number of bytes written. +// Length must be at least 4 and < 1<<24 +func emitRepeat16(dst []byte, offset uint16, length int) int { + // Repeat offset, make length cheaper + length -= 4 + if length <= 4 { + dst[0] = uint8(length)<<2 | tagCopy1 + dst[1] = 0 + return 2 + } + if length < 8 && offset < 2048 { + // Encode WITH offset + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length)<<2 | tagCopy1 + return 2 + } + if length < (1<<8)+4 { + length -= 4 + dst[2] = uint8(length) + dst[1] = 0 + dst[0] = 5<<2 | tagCopy1 + return 3 + } + if length < (1<<16)+(1<<8) { + length -= 1 << 8 + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 6<<2 | tagCopy1 + return 4 + } + const maxRepeat = (1 << 24) - 1 + length -= 1 << 16 + left := 0 + if length > maxRepeat { + left = length - maxRepeat + 4 + length = maxRepeat - 4 + } + dst[4] = uint8(length >> 16) + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 7<<2 | tagCopy1 + if left > 0 { + return 5 + emitRepeat16(dst[5:], offset, left) + } + return 5 +} + +// emitCopy writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= math.MaxUint16 +// 4 <= length && length <= math.MaxUint32 +func emitCopy16(dst []byte, offset uint16, length int) int { + // Offset no more than 2 bytes. + if length > 64 { + off := 3 + if offset < 2048 { + // emit 8 bytes as tagCopy1, rest as repeats. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(8-4)<<2 | tagCopy1 + length -= 8 + off = 2 + } else { + // Emit a length 60 copy, encoded as 3 bytes. + // Emit remaining as repeat value (minimum 4 bytes). + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 59<<2 | tagCopy2 + length -= 60 + } + // Emit remaining as repeats, at least 4 bytes remain. + return off + emitRepeat16(dst[off:], offset, length) + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = uint8(length-1)<<2 | tagCopy2 + return 3 + } + // Emit the remaining copy, encoded as 2 bytes. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + return 2 +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 0 <= len(lit) && len(lit) <= math.MaxUint32 +func emitLiteralGo(dst, lit []byte) int { + if len(lit) == 0 { + return 0 + } + i, n := 0, uint(len(lit)-1) + switch { + case n < 60: + dst[0] = uint8(n)<<2 | tagLiteral + i = 1 + case n < 1<<8: + dst[1] = uint8(n) + dst[0] = 60<<2 | tagLiteral + i = 2 + case n < 1<<16: + dst[2] = uint8(n >> 8) + dst[1] = uint8(n) + dst[0] = 61<<2 | tagLiteral + i = 3 + case n < 1<<24: + dst[3] = uint8(n >> 16) + dst[2] = uint8(n >> 8) + dst[1] = uint8(n) + dst[0] = 62<<2 | tagLiteral + i = 4 + default: + dst[4] = uint8(n >> 24) + dst[3] = uint8(n >> 16) + dst[2] = uint8(n >> 8) + dst[1] = uint8(n) + dst[0] = 63<<2 | tagLiteral + i = 5 + } + return i + copy(dst[i:], lit) +} diff --git a/vendor/github.com/klauspost/compress/s2/lz4sconvert.go b/vendor/github.com/klauspost/compress/s2/lz4sconvert.go new file mode 100644 index 0000000..000f397 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/lz4sconvert.go @@ -0,0 +1,467 @@ +// Copyright (c) 2022 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "encoding/binary" + "fmt" +) + +// LZ4sConverter provides conversion from LZ4s. +// (Intel modified LZ4 Blocks) +// https://cdrdv2-public.intel.com/743912/743912-qat-programmers-guide-v2.0.pdf +// LZ4s is a variant of LZ4 block format. LZ4s should be considered as an intermediate compressed block format. +// The LZ4s format is selected when the application sets the compType to CPA_DC_LZ4S in CpaDcSessionSetupData. +// The LZ4s block returned by the Intel® QAT hardware can be used by an external +// software post-processing to generate other compressed data formats. +// The following table lists the differences between LZ4 and LZ4s block format. LZ4s block format uses +// the same high-level formatting as LZ4 block format with the following encoding changes: +// For Min Match of 4 bytes, Copy length value 1-15 means length 4-18 with 18 bytes adding an extra byte. +// ONLY "Min match of 4 bytes" is supported. +type LZ4sConverter struct { +} + +// ConvertBlock will convert an LZ4s block and append it as an S2 +// block without block length to dst. +// The uncompressed size is returned as well. +// dst must have capacity to contain the entire compressed block. +func (l *LZ4sConverter) ConvertBlock(dst, src []byte) ([]byte, int, error) { + if len(src) == 0 { + return dst, 0, nil + } + const debug = false + const inline = true + const lz4MinMatch = 3 + + s, d := 0, len(dst) + dst = dst[:cap(dst)] + if !debug && hasAmd64Asm { + res, sz := cvtLZ4sBlockAsm(dst[d:], src) + if res < 0 { + const ( + errCorrupt = -1 + errDstTooSmall = -2 + ) + switch res { + case errCorrupt: + return nil, 0, ErrCorrupt + case errDstTooSmall: + return nil, 0, ErrDstTooSmall + default: + return nil, 0, fmt.Errorf("unexpected result: %d", res) + } + } + if d+sz > len(dst) { + return nil, 0, ErrDstTooSmall + } + return dst[:d+sz], res, nil + } + + dLimit := len(dst) - 10 + var lastOffset uint16 + var uncompressed int + if debug { + fmt.Printf("convert block start: len(src): %d, len(dst):%d \n", len(src), len(dst)) + } + + for { + if s >= len(src) { + return dst[:d], 0, ErrCorrupt + } + // Read literal info + token := src[s] + ll := int(token >> 4) + ml := int(lz4MinMatch + (token & 0xf)) + + // If upper nibble is 15, literal length is extended + if token >= 0xf0 { + for { + s++ + if s >= len(src) { + if debug { + fmt.Printf("error reading ll: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return dst[:d], 0, ErrCorrupt + } + val := src[s] + ll += int(val) + if val != 255 { + break + } + } + } + // Skip past token + if s+ll >= len(src) { + if debug { + fmt.Printf("error literals: s+ll (%d+%d) >= len(src) (%d)\n", s, ll, len(src)) + } + return nil, 0, ErrCorrupt + } + s++ + if ll > 0 { + if d+ll > dLimit { + return nil, 0, ErrDstTooSmall + } + if debug { + fmt.Printf("emit %d literals\n", ll) + } + d += emitLiteralGo(dst[d:], src[s:s+ll]) + s += ll + uncompressed += ll + } + + // Check if we are done... + if ml == lz4MinMatch { + if s == len(src) { + break + } + // 0 bytes. + continue + } + // 2 byte offset + if s >= len(src)-2 { + if debug { + fmt.Printf("s (%d) >= len(src)-2 (%d)", s, len(src)-2) + } + return nil, 0, ErrCorrupt + } + offset := binary.LittleEndian.Uint16(src[s:]) + s += 2 + if offset == 0 { + if debug { + fmt.Printf("error: offset 0, ml: %d, len(src)-s: %d\n", ml, len(src)-s) + } + return nil, 0, ErrCorrupt + } + if int(offset) > uncompressed { + if debug { + fmt.Printf("error: offset (%d)> uncompressed (%d)\n", offset, uncompressed) + } + return nil, 0, ErrCorrupt + } + + if ml == lz4MinMatch+15 { + for { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + val := src[s] + s++ + ml += int(val) + if val != 255 { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + break + } + } + } + if offset == lastOffset { + if debug { + fmt.Printf("emit repeat, length: %d, offset: %d\n", ml, offset) + } + if !inline { + d += emitRepeat16(dst[d:], offset, ml) + } else { + length := ml + dst := dst[d:] + for len(dst) > 5 { + // Repeat offset, make length cheaper + length -= 4 + if length <= 4 { + dst[0] = uint8(length)<<2 | tagCopy1 + dst[1] = 0 + d += 2 + break + } + if length < 8 && offset < 2048 { + // Encode WITH offset + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length)<<2 | tagCopy1 + d += 2 + break + } + if length < (1<<8)+4 { + length -= 4 + dst[2] = uint8(length) + dst[1] = 0 + dst[0] = 5<<2 | tagCopy1 + d += 3 + break + } + if length < (1<<16)+(1<<8) { + length -= 1 << 8 + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 6<<2 | tagCopy1 + d += 4 + break + } + const maxRepeat = (1 << 24) - 1 + length -= 1 << 16 + left := 0 + if length > maxRepeat { + left = length - maxRepeat + 4 + length = maxRepeat - 4 + } + dst[4] = uint8(length >> 16) + dst[3] = uint8(length >> 8) + dst[2] = uint8(length >> 0) + dst[1] = 0 + dst[0] = 7<<2 | tagCopy1 + if left > 0 { + d += 5 + emitRepeat16(dst[5:], offset, left) + break + } + d += 5 + break + } + } + } else { + if debug { + fmt.Printf("emit copy, length: %d, offset: %d\n", ml, offset) + } + if !inline { + d += emitCopy16(dst[d:], offset, ml) + } else { + length := ml + dst := dst[d:] + for len(dst) > 5 { + // Offset no more than 2 bytes. + if length > 64 { + off := 3 + if offset < 2048 { + // emit 8 bytes as tagCopy1, rest as repeats. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(8-4)<<2 | tagCopy1 + length -= 8 + off = 2 + } else { + // Emit a length 60 copy, encoded as 3 bytes. + // Emit remaining as repeat value (minimum 4 bytes). + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = 59<<2 | tagCopy2 + length -= 60 + } + // Emit remaining as repeats, at least 4 bytes remain. + d += off + emitRepeat16(dst[off:], offset, length) + break + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[2] = uint8(offset >> 8) + dst[1] = uint8(offset) + dst[0] = uint8(length-1)<<2 | tagCopy2 + d += 3 + break + } + // Emit the remaining copy, encoded as 2 bytes. + dst[1] = uint8(offset) + dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + d += 2 + break + } + } + lastOffset = offset + } + uncompressed += ml + if d > dLimit { + return nil, 0, ErrDstTooSmall + } + } + + return dst[:d], uncompressed, nil +} + +// ConvertBlockSnappy will convert an LZ4s block and append it +// as a Snappy block without block length to dst. +// The uncompressed size is returned as well. +// dst must have capacity to contain the entire compressed block. +func (l *LZ4sConverter) ConvertBlockSnappy(dst, src []byte) ([]byte, int, error) { + if len(src) == 0 { + return dst, 0, nil + } + const debug = false + const lz4MinMatch = 3 + + s, d := 0, len(dst) + dst = dst[:cap(dst)] + // Use assembly when possible + if !debug && hasAmd64Asm { + res, sz := cvtLZ4sBlockSnappyAsm(dst[d:], src) + if res < 0 { + const ( + errCorrupt = -1 + errDstTooSmall = -2 + ) + switch res { + case errCorrupt: + return nil, 0, ErrCorrupt + case errDstTooSmall: + return nil, 0, ErrDstTooSmall + default: + return nil, 0, fmt.Errorf("unexpected result: %d", res) + } + } + if d+sz > len(dst) { + return nil, 0, ErrDstTooSmall + } + return dst[:d+sz], res, nil + } + + dLimit := len(dst) - 10 + var uncompressed int + if debug { + fmt.Printf("convert block start: len(src): %d, len(dst):%d \n", len(src), len(dst)) + } + + for { + if s >= len(src) { + return nil, 0, ErrCorrupt + } + // Read literal info + token := src[s] + ll := int(token >> 4) + ml := int(lz4MinMatch + (token & 0xf)) + + // If upper nibble is 15, literal length is extended + if token >= 0xf0 { + for { + s++ + if s >= len(src) { + if debug { + fmt.Printf("error reading ll: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + val := src[s] + ll += int(val) + if val != 255 { + break + } + } + } + // Skip past token + if s+ll >= len(src) { + if debug { + fmt.Printf("error literals: s+ll (%d+%d) >= len(src) (%d)\n", s, ll, len(src)) + } + return nil, 0, ErrCorrupt + } + s++ + if ll > 0 { + if d+ll > dLimit { + return nil, 0, ErrDstTooSmall + } + if debug { + fmt.Printf("emit %d literals\n", ll) + } + d += emitLiteralGo(dst[d:], src[s:s+ll]) + s += ll + uncompressed += ll + } + + // Check if we are done... + if ml == lz4MinMatch { + if s == len(src) { + break + } + // 0 bytes. + continue + } + // 2 byte offset + if s >= len(src)-2 { + if debug { + fmt.Printf("s (%d) >= len(src)-2 (%d)", s, len(src)-2) + } + return nil, 0, ErrCorrupt + } + offset := binary.LittleEndian.Uint16(src[s:]) + s += 2 + if offset == 0 { + if debug { + fmt.Printf("error: offset 0, ml: %d, len(src)-s: %d\n", ml, len(src)-s) + } + return nil, 0, ErrCorrupt + } + if int(offset) > uncompressed { + if debug { + fmt.Printf("error: offset (%d)> uncompressed (%d)\n", offset, uncompressed) + } + return nil, 0, ErrCorrupt + } + + if ml == lz4MinMatch+15 { + for { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + val := src[s] + s++ + ml += int(val) + if val != 255 { + if s >= len(src) { + if debug { + fmt.Printf("error reading ml: s (%d) >= len(src) (%d)\n", s, len(src)) + } + return nil, 0, ErrCorrupt + } + break + } + } + } + if debug { + fmt.Printf("emit copy, length: %d, offset: %d\n", ml, offset) + } + length := ml + // d += emitCopyNoRepeat(dst[d:], int(offset), ml) + for length > 0 { + if d >= dLimit { + return nil, 0, ErrDstTooSmall + } + + // Offset no more than 2 bytes. + if length > 64 { + // Emit a length 64 copy, encoded as 3 bytes. + dst[d+2] = uint8(offset >> 8) + dst[d+1] = uint8(offset) + dst[d+0] = 63<<2 | tagCopy2 + length -= 64 + d += 3 + continue + } + if length >= 12 || offset >= 2048 || length < 4 { + // Emit the remaining copy, encoded as 3 bytes. + dst[d+2] = uint8(offset >> 8) + dst[d+1] = uint8(offset) + dst[d+0] = uint8(length-1)<<2 | tagCopy2 + d += 3 + break + } + // Emit the remaining copy, encoded as 2 bytes. + dst[d+1] = uint8(offset) + dst[d+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + d += 2 + break + } + uncompressed += ml + if d > dLimit { + return nil, 0, ErrDstTooSmall + } + } + + return dst[:d], uncompressed, nil +} diff --git a/vendor/github.com/klauspost/compress/s2/reader.go b/vendor/github.com/klauspost/compress/s2/reader.go new file mode 100644 index 0000000..4d01c41 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/reader.go @@ -0,0 +1,1075 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019+ Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "math" + "runtime" + "sync" +) + +// ErrCantSeek is returned if the stream cannot be seeked. +type ErrCantSeek struct { + Reason string +} + +// Error returns the error as string. +func (e ErrCantSeek) Error() string { + return fmt.Sprintf("s2: Can't seek because %s", e.Reason) +} + +// NewReader returns a new Reader that decompresses from r, using the framing +// format described at +// https://github.com/google/snappy/blob/master/framing_format.txt with S2 changes. +func NewReader(r io.Reader, opts ...ReaderOption) *Reader { + nr := Reader{ + r: r, + maxBlock: maxBlockSize, + } + for _, opt := range opts { + if err := opt(&nr); err != nil { + nr.err = err + return &nr + } + } + nr.maxBufSize = MaxEncodedLen(nr.maxBlock) + checksumSize + if nr.lazyBuf > 0 { + nr.buf = make([]byte, MaxEncodedLen(nr.lazyBuf)+checksumSize) + } else { + nr.buf = make([]byte, MaxEncodedLen(defaultBlockSize)+checksumSize) + } + nr.readHeader = nr.ignoreStreamID + nr.paramsOK = true + return &nr +} + +// ReaderOption is an option for creating a decoder. +type ReaderOption func(*Reader) error + +// ReaderMaxBlockSize allows to control allocations if the stream +// has been compressed with a smaller WriterBlockSize, or with the default 1MB. +// Blocks must be this size or smaller to decompress, +// otherwise the decoder will return ErrUnsupported. +// +// For streams compressed with Snappy this can safely be set to 64KB (64 << 10). +// +// Default is the maximum limit of 4MB. +func ReaderMaxBlockSize(blockSize int) ReaderOption { + return func(r *Reader) error { + if blockSize > maxBlockSize || blockSize <= 0 { + return errors.New("s2: block size too large. Must be <= 4MB and > 0") + } + if r.lazyBuf == 0 && blockSize < defaultBlockSize { + r.lazyBuf = blockSize + } + r.maxBlock = blockSize + return nil + } +} + +// ReaderAllocBlock allows to control upfront stream allocations +// and not allocate for frames bigger than this initially. +// If frames bigger than this is seen a bigger buffer will be allocated. +// +// Default is 1MB, which is default output size. +func ReaderAllocBlock(blockSize int) ReaderOption { + return func(r *Reader) error { + if blockSize > maxBlockSize || blockSize < 1024 { + return errors.New("s2: invalid ReaderAllocBlock. Must be <= 4MB and >= 1024") + } + r.lazyBuf = blockSize + return nil + } +} + +// ReaderIgnoreStreamIdentifier will make the reader skip the expected +// stream identifier at the beginning of the stream. +// This can be used when serving a stream that has been forwarded to a specific point. +func ReaderIgnoreStreamIdentifier() ReaderOption { + return func(r *Reader) error { + r.ignoreStreamID = true + return nil + } +} + +// ReaderSkippableCB will register a callback for chuncks with the specified ID. +// ID must be a Reserved skippable chunks ID, 0x80-0xfd (inclusive). +// For each chunk with the ID, the callback is called with the content. +// Any returned non-nil error will abort decompression. +// Only one callback per ID is supported, latest sent will be used. +// You can peek the stream, triggering the callback, by doing a Read with a 0 +// byte buffer. +func ReaderSkippableCB(id uint8, fn func(r io.Reader) error) ReaderOption { + return func(r *Reader) error { + if id < 0x80 || id > 0xfd { + return fmt.Errorf("ReaderSkippableCB: Invalid id provided, must be 0x80-0xfd (inclusive)") + } + r.skippableCB[id-0x80] = fn + return nil + } +} + +// ReaderIgnoreCRC will make the reader skip CRC calculation and checks. +func ReaderIgnoreCRC() ReaderOption { + return func(r *Reader) error { + r.ignoreCRC = true + return nil + } +} + +// Reader is an io.Reader that can read Snappy-compressed bytes. +type Reader struct { + r io.Reader + err error + decoded []byte + buf []byte + skippableCB [0xff - 0x80]func(r io.Reader) error + blockStart int64 // Uncompressed offset at start of current. + index *Index + + // decoded[i:j] contains decoded bytes that have not yet been passed on. + i, j int + // maximum block size allowed. + maxBlock int + // maximum expected buffer size. + maxBufSize int + // alloc a buffer this size if > 0. + lazyBuf int + readHeader bool + paramsOK bool + snappyFrame bool + ignoreStreamID bool + ignoreCRC bool +} + +// GetBufferCapacity returns the capacity of the internal buffer. +// This might be useful to know when reusing the same reader in combination +// with the lazy buffer option. +func (r *Reader) GetBufferCapacity() int { + return cap(r.buf) +} + +// ensureBufferSize will ensure that the buffer can take at least n bytes. +// If false is returned the buffer exceeds maximum allowed size. +func (r *Reader) ensureBufferSize(n int) bool { + if n > r.maxBufSize { + r.err = ErrCorrupt + return false + } + if cap(r.buf) >= n { + return true + } + // Realloc buffer. + r.buf = make([]byte, n) + return true +} + +// Reset discards any buffered data, resets all state, and switches the Snappy +// reader to read from r. This permits reusing a Reader rather than allocating +// a new one. +func (r *Reader) Reset(reader io.Reader) { + if !r.paramsOK { + return + } + r.index = nil + r.r = reader + r.err = nil + r.i = 0 + r.j = 0 + r.blockStart = 0 + r.readHeader = r.ignoreStreamID +} + +func (r *Reader) readFull(p []byte, allowEOF bool) (ok bool) { + if _, r.err = io.ReadFull(r.r, p); r.err != nil { + if r.err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { + r.err = ErrCorrupt + } + return false + } + return true +} + +// skippable will skip n bytes. +// If the supplied reader supports seeking that is used. +// tmp is used as a temporary buffer for reading. +// The supplied slice does not need to be the size of the read. +func (r *Reader) skippable(tmp []byte, n int, allowEOF bool, id uint8) (ok bool) { + if id < 0x80 { + r.err = fmt.Errorf("internal error: skippable id < 0x80") + return false + } + if fn := r.skippableCB[id-0x80]; fn != nil { + rd := io.LimitReader(r.r, int64(n)) + r.err = fn(rd) + if r.err != nil { + return false + } + _, r.err = io.CopyBuffer(ioutil.Discard, rd, tmp) + return r.err == nil + } + if rs, ok := r.r.(io.ReadSeeker); ok { + _, err := rs.Seek(int64(n), io.SeekCurrent) + if err == nil { + return true + } + if err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { + r.err = ErrCorrupt + return false + } + } + for n > 0 { + if n < len(tmp) { + tmp = tmp[:n] + } + if _, r.err = io.ReadFull(r.r, tmp); r.err != nil { + if r.err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { + r.err = ErrCorrupt + } + return false + } + n -= len(tmp) + } + return true +} + +// Read satisfies the io.Reader interface. +func (r *Reader) Read(p []byte) (int, error) { + if r.err != nil { + return 0, r.err + } + for { + if r.i < r.j { + n := copy(p, r.decoded[r.i:r.j]) + r.i += n + return n, nil + } + if !r.readFull(r.buf[:4], true) { + return 0, r.err + } + chunkType := r.buf[0] + if !r.readHeader { + if chunkType != chunkTypeStreamIdentifier { + r.err = ErrCorrupt + return 0, r.err + } + r.readHeader = true + } + chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 + + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + r.blockStart += int64(r.j) + // Section 4.2. Compressed data (chunk type 0x00). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return 0, r.err + } + if !r.ensureBufferSize(chunkLen) { + if r.err == nil { + r.err = ErrUnsupported + } + return 0, r.err + } + buf := r.buf[:chunkLen] + if !r.readFull(buf, false) { + return 0, r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + buf = buf[checksumSize:] + + n, err := DecodedLen(buf) + if err != nil { + r.err = err + return 0, r.err + } + if r.snappyFrame && n > maxSnappyBlockSize { + r.err = ErrCorrupt + return 0, r.err + } + + if n > len(r.decoded) { + if n > r.maxBlock { + r.err = ErrCorrupt + return 0, r.err + } + r.decoded = make([]byte, n) + } + if _, err := Decode(r.decoded, buf); err != nil { + r.err = err + return 0, r.err + } + if !r.ignoreCRC && crc(r.decoded[:n]) != checksum { + r.err = ErrCRC + return 0, r.err + } + r.i, r.j = 0, n + continue + + case chunkTypeUncompressedData: + r.blockStart += int64(r.j) + // Section 4.3. Uncompressed data (chunk type 0x01). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return 0, r.err + } + if !r.ensureBufferSize(chunkLen) { + if r.err == nil { + r.err = ErrUnsupported + } + return 0, r.err + } + buf := r.buf[:checksumSize] + if !r.readFull(buf, false) { + return 0, r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + // Read directly into r.decoded instead of via r.buf. + n := chunkLen - checksumSize + if r.snappyFrame && n > maxSnappyBlockSize { + r.err = ErrCorrupt + return 0, r.err + } + if n > len(r.decoded) { + if n > r.maxBlock { + r.err = ErrCorrupt + return 0, r.err + } + r.decoded = make([]byte, n) + } + if !r.readFull(r.decoded[:n], false) { + return 0, r.err + } + if !r.ignoreCRC && crc(r.decoded[:n]) != checksum { + r.err = ErrCRC + return 0, r.err + } + r.i, r.j = 0, n + continue + + case chunkTypeStreamIdentifier: + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(magicBody) { + r.err = ErrCorrupt + return 0, r.err + } + if !r.readFull(r.buf[:len(magicBody)], false) { + return 0, r.err + } + if string(r.buf[:len(magicBody)]) != magicBody { + if string(r.buf[:len(magicBody)]) != magicBodySnappy { + r.err = ErrCorrupt + return 0, r.err + } else { + r.snappyFrame = true + } + } else { + r.snappyFrame = false + } + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + // fmt.Printf("ERR chunktype: 0x%x\n", chunkType) + r.err = ErrUnsupported + return 0, r.err + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + if chunkLen > maxChunkSize { + // fmt.Printf("ERR chunkLen: 0x%x\n", chunkLen) + r.err = ErrUnsupported + return 0, r.err + } + + // fmt.Printf("skippable: ID: 0x%x, len: 0x%x\n", chunkType, chunkLen) + if !r.skippable(r.buf, chunkLen, false, chunkType) { + return 0, r.err + } + } +} + +// DecodeConcurrent will decode the full stream to w. +// This function should not be combined with reading, seeking or other operations. +// Up to 'concurrent' goroutines will be used. +// If <= 0, runtime.NumCPU will be used. +// On success the number of bytes decompressed nil and is returned. +// This is mainly intended for bigger streams. +func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, err error) { + if r.i > 0 || r.j > 0 || r.blockStart > 0 { + return 0, errors.New("DecodeConcurrent called after ") + } + if concurrent <= 0 { + concurrent = runtime.NumCPU() + } + + // Write to output + var errMu sync.Mutex + var aErr error + setErr := func(e error) (ok bool) { + errMu.Lock() + defer errMu.Unlock() + if e == nil { + return aErr == nil + } + if aErr == nil { + aErr = e + } + return false + } + hasErr := func() (ok bool) { + errMu.Lock() + v := aErr != nil + errMu.Unlock() + return v + } + + var aWritten int64 + toRead := make(chan []byte, concurrent) + writtenBlocks := make(chan []byte, concurrent) + queue := make(chan chan []byte, concurrent) + reUse := make(chan chan []byte, concurrent) + for i := 0; i < concurrent; i++ { + toRead <- make([]byte, 0, r.maxBufSize) + writtenBlocks <- make([]byte, 0, r.maxBufSize) + reUse <- make(chan []byte, 1) + } + // Writer + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + for toWrite := range queue { + entry := <-toWrite + reUse <- toWrite + if hasErr() || entry == nil { + if entry != nil { + writtenBlocks <- entry + } + continue + } + if hasErr() { + writtenBlocks <- entry + continue + } + n, err := w.Write(entry) + want := len(entry) + writtenBlocks <- entry + if err != nil { + setErr(err) + continue + } + if n != want { + setErr(io.ErrShortWrite) + continue + } + aWritten += int64(n) + } + }() + + defer func() { + if r.err != nil { + setErr(r.err) + } else if err != nil { + setErr(err) + } + close(queue) + wg.Wait() + if err == nil { + err = aErr + } + written = aWritten + }() + + // Reader + for !hasErr() { + if !r.readFull(r.buf[:4], true) { + if r.err == io.EOF { + r.err = nil + } + return 0, r.err + } + chunkType := r.buf[0] + if !r.readHeader { + if chunkType != chunkTypeStreamIdentifier { + r.err = ErrCorrupt + return 0, r.err + } + r.readHeader = true + } + chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 + + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + r.blockStart += int64(r.j) + // Section 4.2. Compressed data (chunk type 0x00). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return 0, r.err + } + if chunkLen > r.maxBufSize { + r.err = ErrCorrupt + return 0, r.err + } + orgBuf := <-toRead + buf := orgBuf[:chunkLen] + + if !r.readFull(buf, false) { + return 0, r.err + } + + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + buf = buf[checksumSize:] + + n, err := DecodedLen(buf) + if err != nil { + r.err = err + return 0, r.err + } + if r.snappyFrame && n > maxSnappyBlockSize { + r.err = ErrCorrupt + return 0, r.err + } + + if n > r.maxBlock { + r.err = ErrCorrupt + return 0, r.err + } + wg.Add(1) + + decoded := <-writtenBlocks + entry := <-reUse + queue <- entry + go func() { + defer wg.Done() + decoded = decoded[:n] + _, err := Decode(decoded, buf) + toRead <- orgBuf + if err != nil { + writtenBlocks <- decoded + setErr(err) + entry <- nil + return + } + if !r.ignoreCRC && crc(decoded) != checksum { + writtenBlocks <- decoded + setErr(ErrCRC) + entry <- nil + return + } + entry <- decoded + }() + continue + + case chunkTypeUncompressedData: + + // Section 4.3. Uncompressed data (chunk type 0x01). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return 0, r.err + } + if chunkLen > r.maxBufSize { + r.err = ErrCorrupt + return 0, r.err + } + // Grab write buffer + orgBuf := <-writtenBlocks + buf := orgBuf[:checksumSize] + if !r.readFull(buf, false) { + return 0, r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + // Read content. + n := chunkLen - checksumSize + + if r.snappyFrame && n > maxSnappyBlockSize { + r.err = ErrCorrupt + return 0, r.err + } + if n > r.maxBlock { + r.err = ErrCorrupt + return 0, r.err + } + // Read uncompressed + buf = orgBuf[:n] + if !r.readFull(buf, false) { + return 0, r.err + } + + if !r.ignoreCRC && crc(buf) != checksum { + r.err = ErrCRC + return 0, r.err + } + entry := <-reUse + queue <- entry + entry <- buf + continue + + case chunkTypeStreamIdentifier: + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(magicBody) { + r.err = ErrCorrupt + return 0, r.err + } + if !r.readFull(r.buf[:len(magicBody)], false) { + return 0, r.err + } + if string(r.buf[:len(magicBody)]) != magicBody { + if string(r.buf[:len(magicBody)]) != magicBodySnappy { + r.err = ErrCorrupt + return 0, r.err + } else { + r.snappyFrame = true + } + } else { + r.snappyFrame = false + } + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + // fmt.Printf("ERR chunktype: 0x%x\n", chunkType) + r.err = ErrUnsupported + return 0, r.err + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + if chunkLen > maxChunkSize { + // fmt.Printf("ERR chunkLen: 0x%x\n", chunkLen) + r.err = ErrUnsupported + return 0, r.err + } + + // fmt.Printf("skippable: ID: 0x%x, len: 0x%x\n", chunkType, chunkLen) + if !r.skippable(r.buf, chunkLen, false, chunkType) { + return 0, r.err + } + } + return 0, r.err +} + +// Skip will skip n bytes forward in the decompressed output. +// For larger skips this consumes less CPU and is faster than reading output and discarding it. +// CRC is not checked on skipped blocks. +// io.ErrUnexpectedEOF is returned if the stream ends before all bytes have been skipped. +// If a decoding error is encountered subsequent calls to Read will also fail. +func (r *Reader) Skip(n int64) error { + if n < 0 { + return errors.New("attempted negative skip") + } + if r.err != nil { + return r.err + } + + for n > 0 { + if r.i < r.j { + // Skip in buffer. + // decoded[i:j] contains decoded bytes that have not yet been passed on. + left := int64(r.j - r.i) + if left >= n { + tmp := int64(r.i) + n + if tmp > math.MaxInt32 { + return errors.New("s2: internal overflow in skip") + } + r.i = int(tmp) + return nil + } + n -= int64(r.j - r.i) + r.i = r.j + } + + // Buffer empty; read blocks until we have content. + if !r.readFull(r.buf[:4], true) { + if r.err == io.EOF { + r.err = io.ErrUnexpectedEOF + } + return r.err + } + chunkType := r.buf[0] + if !r.readHeader { + if chunkType != chunkTypeStreamIdentifier { + r.err = ErrCorrupt + return r.err + } + r.readHeader = true + } + chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 + + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + r.blockStart += int64(r.j) + // Section 4.2. Compressed data (chunk type 0x00). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return r.err + } + if !r.ensureBufferSize(chunkLen) { + if r.err == nil { + r.err = ErrUnsupported + } + return r.err + } + buf := r.buf[:chunkLen] + if !r.readFull(buf, false) { + return r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + buf = buf[checksumSize:] + + dLen, err := DecodedLen(buf) + if err != nil { + r.err = err + return r.err + } + if dLen > r.maxBlock { + r.err = ErrCorrupt + return r.err + } + // Check if destination is within this block + if int64(dLen) > n { + if len(r.decoded) < dLen { + r.decoded = make([]byte, dLen) + } + if _, err := Decode(r.decoded, buf); err != nil { + r.err = err + return r.err + } + if crc(r.decoded[:dLen]) != checksum { + r.err = ErrCorrupt + return r.err + } + } else { + // Skip block completely + n -= int64(dLen) + r.blockStart += int64(dLen) + dLen = 0 + } + r.i, r.j = 0, dLen + continue + case chunkTypeUncompressedData: + r.blockStart += int64(r.j) + // Section 4.3. Uncompressed data (chunk type 0x01). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return r.err + } + if !r.ensureBufferSize(chunkLen) { + if r.err != nil { + r.err = ErrUnsupported + } + return r.err + } + buf := r.buf[:checksumSize] + if !r.readFull(buf, false) { + return r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + // Read directly into r.decoded instead of via r.buf. + n2 := chunkLen - checksumSize + if n2 > len(r.decoded) { + if n2 > r.maxBlock { + r.err = ErrCorrupt + return r.err + } + r.decoded = make([]byte, n2) + } + if !r.readFull(r.decoded[:n2], false) { + return r.err + } + if int64(n2) < n { + if crc(r.decoded[:n2]) != checksum { + r.err = ErrCorrupt + return r.err + } + } + r.i, r.j = 0, n2 + continue + case chunkTypeStreamIdentifier: + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(magicBody) { + r.err = ErrCorrupt + return r.err + } + if !r.readFull(r.buf[:len(magicBody)], false) { + return r.err + } + if string(r.buf[:len(magicBody)]) != magicBody { + if string(r.buf[:len(magicBody)]) != magicBodySnappy { + r.err = ErrCorrupt + return r.err + } + } + + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + r.err = ErrUnsupported + return r.err + } + if chunkLen > maxChunkSize { + r.err = ErrUnsupported + return r.err + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + if !r.skippable(r.buf, chunkLen, false, chunkType) { + return r.err + } + } + return nil +} + +// ReadSeeker provides random or forward seeking in compressed content. +// See Reader.ReadSeeker +type ReadSeeker struct { + *Reader + readAtMu sync.Mutex +} + +// ReadSeeker will return an io.ReadSeeker and io.ReaderAt +// compatible version of the reader. +// If 'random' is specified the returned io.Seeker can be used for +// random seeking, otherwise only forward seeking is supported. +// Enabling random seeking requires the original input to support +// the io.Seeker interface. +// A custom index can be specified which will be used if supplied. +// When using a custom index, it will not be read from the input stream. +// The ReadAt position will affect regular reads and the current position of Seek. +// So using Read after ReadAt will continue from where the ReadAt stopped. +// No functions should be used concurrently. +// The returned ReadSeeker contains a shallow reference to the existing Reader, +// meaning changes performed to one is reflected in the other. +func (r *Reader) ReadSeeker(random bool, index []byte) (*ReadSeeker, error) { + // Read index if provided. + if len(index) != 0 { + if r.index == nil { + r.index = &Index{} + } + if _, err := r.index.Load(index); err != nil { + return nil, ErrCantSeek{Reason: "loading index returned: " + err.Error()} + } + } + + // Check if input is seekable + rs, ok := r.r.(io.ReadSeeker) + if !ok { + if !random { + return &ReadSeeker{Reader: r}, nil + } + return nil, ErrCantSeek{Reason: "input stream isn't seekable"} + } + + if r.index != nil { + // Seekable and index, ok... + return &ReadSeeker{Reader: r}, nil + } + + // Load from stream. + r.index = &Index{} + + // Read current position. + pos, err := rs.Seek(0, io.SeekCurrent) + if err != nil { + return nil, ErrCantSeek{Reason: "seeking input returned: " + err.Error()} + } + err = r.index.LoadStream(rs) + if err != nil { + if err == ErrUnsupported { + // If we don't require random seeking, reset input and return. + if !random { + _, err = rs.Seek(pos, io.SeekStart) + if err != nil { + return nil, ErrCantSeek{Reason: "resetting stream returned: " + err.Error()} + } + r.index = nil + return &ReadSeeker{Reader: r}, nil + } + return nil, ErrCantSeek{Reason: "input stream does not contain an index"} + } + return nil, ErrCantSeek{Reason: "reading index returned: " + err.Error()} + } + + // reset position. + _, err = rs.Seek(pos, io.SeekStart) + if err != nil { + return nil, ErrCantSeek{Reason: "seeking input returned: " + err.Error()} + } + return &ReadSeeker{Reader: r}, nil +} + +// Seek allows seeking in compressed data. +func (r *ReadSeeker) Seek(offset int64, whence int) (int64, error) { + if r.err != nil { + if !errors.Is(r.err, io.EOF) { + return 0, r.err + } + // Reset on EOF + r.err = nil + } + + // Calculate absolute offset. + absOffset := offset + + switch whence { + case io.SeekStart: + case io.SeekCurrent: + absOffset = r.blockStart + int64(r.i) + offset + case io.SeekEnd: + if r.index == nil { + return 0, ErrUnsupported + } + absOffset = r.index.TotalUncompressed + offset + default: + r.err = ErrUnsupported + return 0, r.err + } + + if absOffset < 0 { + return 0, errors.New("seek before start of file") + } + + if !r.readHeader { + // Make sure we read the header. + _, r.err = r.Read([]byte{}) + if r.err != nil { + return 0, r.err + } + } + + // If we are inside current block no need to seek. + // This includes no offset changes. + if absOffset >= r.blockStart && absOffset < r.blockStart+int64(r.j) { + r.i = int(absOffset - r.blockStart) + return r.blockStart + int64(r.i), nil + } + + rs, ok := r.r.(io.ReadSeeker) + if r.index == nil || !ok { + currOffset := r.blockStart + int64(r.i) + if absOffset >= currOffset { + err := r.Skip(absOffset - currOffset) + return r.blockStart + int64(r.i), err + } + return 0, ErrUnsupported + } + + // We can seek and we have an index. + c, u, err := r.index.Find(absOffset) + if err != nil { + return r.blockStart + int64(r.i), err + } + + // Seek to next block + _, err = rs.Seek(c, io.SeekStart) + if err != nil { + return 0, err + } + + r.i = r.j // Remove rest of current block. + r.blockStart = u - int64(r.j) // Adjust current block start for accounting. + if u < absOffset { + // Forward inside block + return absOffset, r.Skip(absOffset - u) + } + if u > absOffset { + return 0, fmt.Errorf("s2 seek: (internal error) u (%d) > absOffset (%d)", u, absOffset) + } + return absOffset, nil +} + +// ReadAt reads len(p) bytes into p starting at offset off in the +// underlying input source. It returns the number of bytes +// read (0 <= n <= len(p)) and any error encountered. +// +// When ReadAt returns n < len(p), it returns a non-nil error +// explaining why more bytes were not returned. In this respect, +// ReadAt is stricter than Read. +// +// Even if ReadAt returns n < len(p), it may use all of p as scratch +// space during the call. If some data is available but not len(p) bytes, +// ReadAt blocks until either all the data is available or an error occurs. +// In this respect ReadAt is different from Read. +// +// If the n = len(p) bytes returned by ReadAt are at the end of the +// input source, ReadAt may return either err == EOF or err == nil. +// +// If ReadAt is reading from an input source with a seek offset, +// ReadAt should not affect nor be affected by the underlying +// seek offset. +// +// Clients of ReadAt can execute parallel ReadAt calls on the +// same input source. This is however not recommended. +func (r *ReadSeeker) ReadAt(p []byte, offset int64) (int, error) { + r.readAtMu.Lock() + defer r.readAtMu.Unlock() + _, err := r.Seek(offset, io.SeekStart) + if err != nil { + return 0, err + } + n := 0 + for n < len(p) { + n2, err := r.Read(p[n:]) + if err != nil { + // This will include io.EOF + return n + n2, err + } + n += n2 + } + return n, nil +} + +// ReadByte satisfies the io.ByteReader interface. +func (r *Reader) ReadByte() (byte, error) { + if r.err != nil { + return 0, r.err + } + if r.i < r.j { + c := r.decoded[r.i] + r.i++ + return c, nil + } + var tmp [1]byte + for range 10 { + n, err := r.Read(tmp[:]) + if err != nil { + return 0, err + } + if n == 1 { + return tmp[0], nil + } + } + return 0, io.ErrNoProgress +} + +// SkippableCB will register a callback for chunks with the specified ID. +// ID must be a Reserved skippable chunks ID, 0x80-0xfd (inclusive). +// For each chunk with the ID, the callback is called with the content. +// Any returned non-nil error will abort decompression. +// Only one callback per ID is supported, latest sent will be used. +// Sending a nil function will disable previous callbacks. +// You can peek the stream, triggering the callback, by doing a Read with a 0 +// byte buffer. +func (r *Reader) SkippableCB(id uint8, fn func(r io.Reader) error) error { + if id < 0x80 || id >= chunkTypePadding { + return fmt.Errorf("ReaderSkippableCB: Invalid id provided, must be 0x80-0xfe (inclusive)") + } + r.skippableCB[id-0x80] = fn + return nil +} diff --git a/vendor/github.com/klauspost/compress/s2/s2.go b/vendor/github.com/klauspost/compress/s2/s2.go new file mode 100644 index 0000000..cbd1ed6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/s2.go @@ -0,0 +1,151 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package s2 implements the S2 compression format. +// +// S2 is an extension of Snappy. Similar to Snappy S2 is aimed for high throughput, +// which is why it features concurrent compression for bigger payloads. +// +// Decoding is compatible with Snappy compressed content, +// but content compressed with S2 cannot be decompressed by Snappy. +// +// For more information on Snappy/S2 differences see README in: https://github.com/klauspost/compress/tree/master/s2 +// +// There are actually two S2 formats: block and stream. They are related, +// but different: trying to decompress block-compressed data as a S2 stream +// will fail, and vice versa. The block format is the Decode and Encode +// functions and the stream format is the Reader and Writer types. +// +// A "better" compression option is available. This will trade some compression +// speed +// +// The block format, the more common case, is used when the complete size (the +// number of bytes) of the original data is known upfront, at the time +// compression starts. The stream format, also known as the framing format, is +// for when that isn't always true. +// +// Blocks to not offer much data protection, so it is up to you to +// add data validation of decompressed blocks. +// +// Streams perform CRC validation of the decompressed data. +// Stream compression will also be performed on multiple CPU cores concurrently +// significantly improving throughput. +package s2 + +import ( + "bytes" + "hash/crc32" + + "github.com/klauspost/compress/internal/race" +) + +/* +Each encoded block begins with the varint-encoded length of the decoded data, +followed by a sequence of chunks. Chunks begin and end on byte boundaries. The +first byte of each chunk is broken into its 2 least and 6 most significant bits +called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag. +Zero means a literal tag. All other values mean a copy tag. + +For literal tags: + - If m < 60, the next 1 + m bytes are literal bytes. + - Otherwise, let n be the little-endian unsigned integer denoted by the next + m - 59 bytes. The next 1 + n bytes after that are literal bytes. + +For copy tags, length bytes are copied from offset bytes ago, in the style of +Lempel-Ziv compression algorithms. In particular: + - For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12). + The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10 + of the offset. The next byte is bits 0-7 of the offset. + - For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65). + The length is 1 + m. The offset is the little-endian unsigned integer + denoted by the next 2 bytes. + - For l == 3, the offset ranges in [0, 1<<32) and the length in + [1, 65). The length is 1 + m. The offset is the little-endian unsigned + integer denoted by the next 4 bytes. +*/ +const ( + tagLiteral = 0x00 + tagCopy1 = 0x01 + tagCopy2 = 0x02 + tagCopy4 = 0x03 +) + +const ( + checksumSize = 4 + chunkHeaderSize = 4 + magicChunk = "\xff\x06\x00\x00" + magicBody + magicChunkSnappy = "\xff\x06\x00\x00" + magicBodySnappy + magicBodySnappy = "sNaPpY" + magicBody = "S2sTwO" + + // maxBlockSize is the maximum size of the input to encodeBlock. + // + // For the framing format (Writer type instead of Encode function), + // this is the maximum uncompressed size of a block. + maxBlockSize = 4 << 20 + + // minBlockSize is the minimum size of block setting when creating a writer. + minBlockSize = 4 << 10 + + skippableFrameHeader = 4 + maxChunkSize = 1<<24 - 1 // 16777215 + + // Default block size + defaultBlockSize = 1 << 20 + + // maxSnappyBlockSize is the maximum snappy block size. + maxSnappyBlockSize = 1 << 16 + + obufHeaderLen = checksumSize + chunkHeaderSize +) + +const ( + chunkTypeCompressedData = 0x00 + chunkTypeUncompressedData = 0x01 + ChunkTypeIndex = 0x99 + chunkTypePadding = 0xfe + chunkTypeStreamIdentifier = 0xff +) + +var ( + crcTable = crc32.MakeTable(crc32.Castagnoli) + magicChunkSnappyBytes = []byte(magicChunkSnappy) // Can be passed to functions where it escapes. + magicChunkBytes = []byte(magicChunk) // Can be passed to functions where it escapes. +) + +// crc implements the checksum specified in section 3 of +// https://github.com/google/snappy/blob/master/framing_format.txt +func crc(b []byte) uint32 { + race.ReadSlice(b) + + c := crc32.Update(0, crcTable, b) + return c>>15 | c<<17 + 0xa282ead8 +} + +// literalExtraSize returns the extra size of encoding n literals. +// n should be >= 0 and <= math.MaxUint32. +func literalExtraSize(n int64) int64 { + if n == 0 { + return 0 + } + switch { + case n < 60: + return 1 + case n < 1<<8: + return 2 + case n < 1<<16: + return 3 + case n < 1<<24: + return 4 + default: + return 5 + } +} + +type byter interface { + Bytes() []byte +} + +var _ byter = &bytes.Buffer{} diff --git a/vendor/github.com/klauspost/compress/s2/writer.go b/vendor/github.com/klauspost/compress/s2/writer.go new file mode 100644 index 0000000..09f1cff --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2/writer.go @@ -0,0 +1,1064 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Copyright (c) 2019+ Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s2 + +import ( + "crypto/rand" + "encoding/binary" + "errors" + "fmt" + "io" + "runtime" + "sync" + + "github.com/klauspost/compress/internal/race" +) + +const ( + levelUncompressed = iota + 1 + levelFast + levelBetter + levelBest +) + +// NewWriter returns a new Writer that compresses to w, using the +// framing format described at +// https://github.com/google/snappy/blob/master/framing_format.txt +// +// Users must call Close to guarantee all data has been forwarded to +// the underlying io.Writer and that resources are released. +// They may also call Flush zero or more times before calling Close. +func NewWriter(w io.Writer, opts ...WriterOption) *Writer { + w2 := Writer{ + blockSize: defaultBlockSize, + concurrency: runtime.GOMAXPROCS(0), + randSrc: rand.Reader, + level: levelFast, + } + for _, opt := range opts { + if err := opt(&w2); err != nil { + w2.errState = err + return &w2 + } + } + w2.obufLen = obufHeaderLen + MaxEncodedLen(w2.blockSize) + w2.paramsOK = true + w2.ibuf = make([]byte, 0, w2.blockSize) + w2.buffers.New = func() any { + return make([]byte, w2.obufLen) + } + w2.Reset(w) + return &w2 +} + +// Writer is an io.Writer that can write Snappy-compressed bytes. +type Writer struct { + errMu sync.Mutex + errState error + + // ibuf is a buffer for the incoming (uncompressed) bytes. + ibuf []byte + + blockSize int + obufLen int + concurrency int + written int64 + uncompWritten int64 // Bytes sent to compression + output chan chan result + buffers sync.Pool + pad int + + writer io.Writer + randSrc io.Reader + writerWg sync.WaitGroup + index Index + customEnc func(dst, src []byte) int + + // wroteStreamHeader is whether we have written the stream header. + wroteStreamHeader bool + paramsOK bool + snappy bool + flushOnWrite bool + appendIndex bool + bufferCB func([]byte) + level uint8 +} + +type result struct { + b []byte + // return when writing + ret []byte + // Uncompressed start offset + startOffset int64 +} + +// err returns the previously set error. +// If no error has been set it is set to err if not nil. +func (w *Writer) err(err error) error { + w.errMu.Lock() + errSet := w.errState + if errSet == nil && err != nil { + w.errState = err + errSet = err + } + w.errMu.Unlock() + return errSet +} + +// Reset discards the writer's state and switches the Snappy writer to write to w. +// This permits reusing a Writer rather than allocating a new one. +func (w *Writer) Reset(writer io.Writer) { + if !w.paramsOK { + return + } + // Close previous writer, if any. + if w.output != nil { + close(w.output) + w.writerWg.Wait() + w.output = nil + } + w.errState = nil + w.ibuf = w.ibuf[:0] + w.wroteStreamHeader = false + w.written = 0 + w.writer = writer + w.uncompWritten = 0 + w.index.reset(w.blockSize) + + // If we didn't get a writer, stop here. + if writer == nil { + return + } + // If no concurrency requested, don't spin up writer goroutine. + if w.concurrency == 1 { + return + } + + toWrite := make(chan chan result, w.concurrency) + w.output = toWrite + w.writerWg.Add(1) + + // Start a writer goroutine that will write all output in order. + go func() { + defer w.writerWg.Done() + + // Get a queued write. + for write := range toWrite { + // Wait for the data to be available. + input := <-write + if input.ret != nil && w.bufferCB != nil { + w.bufferCB(input.ret) + input.ret = nil + } + in := input.b + if len(in) > 0 { + if w.err(nil) == nil { + // Don't expose data from previous buffers. + toWrite := in[:len(in):len(in)] + // Write to output. + n, err := writer.Write(toWrite) + if err == nil && n != len(toWrite) { + err = io.ErrShortBuffer + } + _ = w.err(err) + w.err(w.index.add(w.written, input.startOffset)) + w.written += int64(n) + } + } + if cap(in) >= w.obufLen { + w.buffers.Put(in) + } + // close the incoming write request. + // This can be used for synchronizing flushes. + close(write) + } + }() +} + +// Write satisfies the io.Writer interface. +func (w *Writer) Write(p []byte) (nRet int, errRet error) { + if err := w.err(nil); err != nil { + return 0, err + } + if w.flushOnWrite { + return w.write(p) + } + // If we exceed the input buffer size, start writing + for len(p) > (cap(w.ibuf)-len(w.ibuf)) && w.err(nil) == nil { + var n int + if len(w.ibuf) == 0 { + // Large write, empty buffer. + // Write directly from p to avoid copy. + n, _ = w.write(p) + } else { + n = copy(w.ibuf[len(w.ibuf):cap(w.ibuf)], p) + w.ibuf = w.ibuf[:len(w.ibuf)+n] + w.write(w.ibuf) + w.ibuf = w.ibuf[:0] + } + nRet += n + p = p[n:] + } + if err := w.err(nil); err != nil { + return nRet, err + } + // p should always be able to fit into w.ibuf now. + n := copy(w.ibuf[len(w.ibuf):cap(w.ibuf)], p) + w.ibuf = w.ibuf[:len(w.ibuf)+n] + nRet += n + return nRet, nil +} + +// ReadFrom implements the io.ReaderFrom interface. +// Using this is typically more efficient since it avoids a memory copy. +// ReadFrom reads data from r until EOF or error. +// The return value n is the number of bytes read. +// Any error except io.EOF encountered during the read is also returned. +func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { + if err := w.err(nil); err != nil { + return 0, err + } + if len(w.ibuf) > 0 { + err := w.AsyncFlush() + if err != nil { + return 0, err + } + } + if br, ok := r.(byter); ok { + buf := br.Bytes() + if err := w.EncodeBuffer(buf); err != nil { + return 0, err + } + return int64(len(buf)), w.AsyncFlush() + } + for { + inbuf := w.buffers.Get().([]byte)[:w.blockSize+obufHeaderLen] + n2, err := io.ReadFull(r, inbuf[obufHeaderLen:]) + if err != nil { + if err == io.ErrUnexpectedEOF { + err = io.EOF + } + if err != io.EOF { + return n, w.err(err) + } + } + if n2 == 0 { + if cap(inbuf) >= w.obufLen { + w.buffers.Put(inbuf) + } + break + } + n += int64(n2) + err2 := w.writeFull(inbuf[:n2+obufHeaderLen]) + if w.err(err2) != nil { + break + } + + if err != nil { + // We got EOF and wrote everything + break + } + } + + return n, w.err(nil) +} + +// AddSkippableBlock will add a skippable block to the stream. +// The ID must be 0x80-0xfe (inclusive). +// Length of the skippable block must be <= 16777215 bytes. +func (w *Writer) AddSkippableBlock(id uint8, data []byte) (err error) { + if err := w.err(nil); err != nil { + return err + } + if len(data) == 0 { + return nil + } + if id < 0x80 || id > chunkTypePadding { + return fmt.Errorf("invalid skippable block id %x", id) + } + if len(data) > maxChunkSize { + return fmt.Errorf("skippable block excessed maximum size") + } + var header [4]byte + chunkLen := len(data) + header[0] = id + header[1] = uint8(chunkLen >> 0) + header[2] = uint8(chunkLen >> 8) + header[3] = uint8(chunkLen >> 16) + if w.concurrency == 1 { + write := func(b []byte) error { + n, err := w.writer.Write(b) + if err = w.err(err); err != nil { + return err + } + if n != len(b) { + return w.err(io.ErrShortWrite) + } + w.written += int64(n) + return w.err(nil) + } + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + if w.snappy { + if err := write([]byte(magicChunkSnappy)); err != nil { + return err + } + } else { + if err := write([]byte(magicChunk)); err != nil { + return err + } + } + } + if err := write(header[:]); err != nil { + return err + } + return write(data) + } + + // Create output... + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + hWriter := make(chan result) + w.output <- hWriter + if w.snappy { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} + } else { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} + } + } + + // Copy input. + inbuf := w.buffers.Get().([]byte)[:4] + copy(inbuf, header[:]) + inbuf = append(inbuf, data...) + + output := make(chan result, 1) + // Queue output. + w.output <- output + output <- result{startOffset: w.uncompWritten, b: inbuf} + + return nil +} + +// EncodeBuffer will add a buffer to the stream. +// This is the fastest way to encode a stream, +// but the input buffer cannot be written to by the caller +// until Flush or Close has been called when concurrency != 1. +// +// Use the WriterBufferDone to receive a callback when the buffer is done +// Processing. +// +// Note that input is not buffered. +// This means that each write will result in discrete blocks being created. +// For buffered writes, use the regular Write function. +func (w *Writer) EncodeBuffer(buf []byte) (err error) { + if err := w.err(nil); err != nil { + return err + } + + if w.flushOnWrite { + _, err := w.write(buf) + return err + } + // Flush queued data first. + if len(w.ibuf) > 0 { + err := w.AsyncFlush() + if err != nil { + return err + } + } + if w.concurrency == 1 { + _, err := w.writeSync(buf) + if w.bufferCB != nil { + w.bufferCB(buf) + } + return err + } + + // Spawn goroutine and write block to output channel. + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + hWriter := make(chan result) + w.output <- hWriter + if w.snappy { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} + } else { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} + } + } + orgBuf := buf + for len(buf) > 0 { + // Cut input. + uncompressed := buf + if len(uncompressed) > w.blockSize { + uncompressed = uncompressed[:w.blockSize] + } + buf = buf[len(uncompressed):] + // Get an output buffer. + obuf := w.buffers.Get().([]byte)[:len(uncompressed)+obufHeaderLen] + race.WriteSlice(obuf) + + output := make(chan result) + // Queue output now, so we keep order. + w.output <- output + res := result{ + startOffset: w.uncompWritten, + } + w.uncompWritten += int64(len(uncompressed)) + if len(buf) == 0 && w.bufferCB != nil { + res.ret = orgBuf + } + go func() { + race.ReadSlice(uncompressed) + + checksum := crc(uncompressed) + + // Set to uncompressed. + chunkType := uint8(chunkTypeUncompressedData) + chunkLen := 4 + len(uncompressed) + + // Attempt compressing. + n := binary.PutUvarint(obuf[obufHeaderLen:], uint64(len(uncompressed))) + n2 := w.encodeBlock(obuf[obufHeaderLen+n:], uncompressed) + + // Check if we should use this, or store as uncompressed instead. + if n2 > 0 { + chunkType = uint8(chunkTypeCompressedData) + chunkLen = 4 + n + n2 + obuf = obuf[:obufHeaderLen+n+n2] + } else { + // copy uncompressed + copy(obuf[obufHeaderLen:], uncompressed) + } + + // Fill in the per-chunk header that comes before the body. + obuf[0] = chunkType + obuf[1] = uint8(chunkLen >> 0) + obuf[2] = uint8(chunkLen >> 8) + obuf[3] = uint8(chunkLen >> 16) + obuf[4] = uint8(checksum >> 0) + obuf[5] = uint8(checksum >> 8) + obuf[6] = uint8(checksum >> 16) + obuf[7] = uint8(checksum >> 24) + + // Queue final output. + res.b = obuf + output <- res + }() + } + return nil +} + +func (w *Writer) encodeBlock(obuf, uncompressed []byte) int { + if w.customEnc != nil { + if ret := w.customEnc(obuf, uncompressed); ret >= 0 { + return ret + } + } + if w.snappy { + switch w.level { + case levelFast: + return encodeBlockSnappy(obuf, uncompressed) + case levelBetter: + return encodeBlockBetterSnappy(obuf, uncompressed) + case levelBest: + return encodeBlockBestSnappy(obuf, uncompressed) + } + return 0 + } + switch w.level { + case levelFast: + return encodeBlock(obuf, uncompressed) + case levelBetter: + return encodeBlockBetter(obuf, uncompressed) + case levelBest: + return encodeBlockBest(obuf, uncompressed, nil) + } + return 0 +} + +func (w *Writer) write(p []byte) (nRet int, errRet error) { + if err := w.err(nil); err != nil { + return 0, err + } + if w.concurrency == 1 { + return w.writeSync(p) + } + + // Spawn goroutine and write block to output channel. + for len(p) > 0 { + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + hWriter := make(chan result) + w.output <- hWriter + if w.snappy { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} + } else { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} + } + } + + var uncompressed []byte + if len(p) > w.blockSize { + uncompressed, p = p[:w.blockSize], p[w.blockSize:] + } else { + uncompressed, p = p, nil + } + + // Copy input. + // If the block is incompressible, this is used for the result. + inbuf := w.buffers.Get().([]byte)[:len(uncompressed)+obufHeaderLen] + obuf := w.buffers.Get().([]byte)[:w.obufLen] + copy(inbuf[obufHeaderLen:], uncompressed) + uncompressed = inbuf[obufHeaderLen:] + + output := make(chan result) + // Queue output now, so we keep order. + w.output <- output + res := result{ + startOffset: w.uncompWritten, + } + w.uncompWritten += int64(len(uncompressed)) + + go func() { + checksum := crc(uncompressed) + + // Set to uncompressed. + chunkType := uint8(chunkTypeUncompressedData) + chunkLen := 4 + len(uncompressed) + + // Attempt compressing. + n := binary.PutUvarint(obuf[obufHeaderLen:], uint64(len(uncompressed))) + n2 := w.encodeBlock(obuf[obufHeaderLen+n:], uncompressed) + + // Check if we should use this, or store as uncompressed instead. + if n2 > 0 { + chunkType = uint8(chunkTypeCompressedData) + chunkLen = 4 + n + n2 + obuf = obuf[:obufHeaderLen+n+n2] + } else { + // Use input as output. + obuf, inbuf = inbuf, obuf + } + + // Fill in the per-chunk header that comes before the body. + obuf[0] = chunkType + obuf[1] = uint8(chunkLen >> 0) + obuf[2] = uint8(chunkLen >> 8) + obuf[3] = uint8(chunkLen >> 16) + obuf[4] = uint8(checksum >> 0) + obuf[5] = uint8(checksum >> 8) + obuf[6] = uint8(checksum >> 16) + obuf[7] = uint8(checksum >> 24) + + // Queue final output. + res.b = obuf + output <- res + + // Put unused buffer back in pool. + w.buffers.Put(inbuf) + }() + nRet += len(uncompressed) + } + return nRet, nil +} + +// writeFull is a special version of write that will always write the full buffer. +// Data to be compressed should start at offset obufHeaderLen and fill the remainder of the buffer. +// The data will be written as a single block. +// The caller is not allowed to use inbuf after this function has been called. +func (w *Writer) writeFull(inbuf []byte) (errRet error) { + if err := w.err(nil); err != nil { + return err + } + + if w.concurrency == 1 { + _, err := w.writeSync(inbuf[obufHeaderLen:]) + if cap(inbuf) >= w.obufLen { + w.buffers.Put(inbuf) + } + return err + } + + // Spawn goroutine and write block to output channel. + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + hWriter := make(chan result) + w.output <- hWriter + if w.snappy { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} + } else { + hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} + } + } + + // Get an output buffer. + obuf := w.buffers.Get().([]byte)[:w.obufLen] + uncompressed := inbuf[obufHeaderLen:] + + output := make(chan result) + // Queue output now, so we keep order. + w.output <- output + res := result{ + startOffset: w.uncompWritten, + } + w.uncompWritten += int64(len(uncompressed)) + + go func() { + checksum := crc(uncompressed) + + // Set to uncompressed. + chunkType := uint8(chunkTypeUncompressedData) + chunkLen := 4 + len(uncompressed) + + // Attempt compressing. + n := binary.PutUvarint(obuf[obufHeaderLen:], uint64(len(uncompressed))) + n2 := w.encodeBlock(obuf[obufHeaderLen+n:], uncompressed) + + // Check if we should use this, or store as uncompressed instead. + if n2 > 0 { + chunkType = uint8(chunkTypeCompressedData) + chunkLen = 4 + n + n2 + obuf = obuf[:obufHeaderLen+n+n2] + } else { + // Use input as output. + obuf, inbuf = inbuf, obuf + } + + // Fill in the per-chunk header that comes before the body. + obuf[0] = chunkType + obuf[1] = uint8(chunkLen >> 0) + obuf[2] = uint8(chunkLen >> 8) + obuf[3] = uint8(chunkLen >> 16) + obuf[4] = uint8(checksum >> 0) + obuf[5] = uint8(checksum >> 8) + obuf[6] = uint8(checksum >> 16) + obuf[7] = uint8(checksum >> 24) + + // Queue final output. + res.b = obuf + output <- res + + // Put unused buffer back in pool. + w.buffers.Put(inbuf) + }() + return nil +} + +func (w *Writer) writeSync(p []byte) (nRet int, errRet error) { + if err := w.err(nil); err != nil { + return 0, err + } + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + var n int + var err error + if w.snappy { + n, err = w.writer.Write(magicChunkSnappyBytes) + } else { + n, err = w.writer.Write(magicChunkBytes) + } + if err != nil { + return 0, w.err(err) + } + if n != len(magicChunk) { + return 0, w.err(io.ErrShortWrite) + } + w.written += int64(n) + } + + for len(p) > 0 { + var uncompressed []byte + if len(p) > w.blockSize { + uncompressed, p = p[:w.blockSize], p[w.blockSize:] + } else { + uncompressed, p = p, nil + } + + obuf := w.buffers.Get().([]byte)[:w.obufLen] + checksum := crc(uncompressed) + + // Set to uncompressed. + chunkType := uint8(chunkTypeUncompressedData) + chunkLen := 4 + len(uncompressed) + + // Attempt compressing. + n := binary.PutUvarint(obuf[obufHeaderLen:], uint64(len(uncompressed))) + n2 := w.encodeBlock(obuf[obufHeaderLen+n:], uncompressed) + + if n2 > 0 { + chunkType = uint8(chunkTypeCompressedData) + chunkLen = 4 + n + n2 + obuf = obuf[:obufHeaderLen+n+n2] + } else { + obuf = obuf[:8] + } + + // Fill in the per-chunk header that comes before the body. + obuf[0] = chunkType + obuf[1] = uint8(chunkLen >> 0) + obuf[2] = uint8(chunkLen >> 8) + obuf[3] = uint8(chunkLen >> 16) + obuf[4] = uint8(checksum >> 0) + obuf[5] = uint8(checksum >> 8) + obuf[6] = uint8(checksum >> 16) + obuf[7] = uint8(checksum >> 24) + + n, err := w.writer.Write(obuf) + if err != nil { + return 0, w.err(err) + } + if n != len(obuf) { + return 0, w.err(io.ErrShortWrite) + } + w.err(w.index.add(w.written, w.uncompWritten)) + w.written += int64(n) + w.uncompWritten += int64(len(uncompressed)) + + if chunkType == chunkTypeUncompressedData { + // Write uncompressed data. + n, err := w.writer.Write(uncompressed) + if err != nil { + return 0, w.err(err) + } + if n != len(uncompressed) { + return 0, w.err(io.ErrShortWrite) + } + w.written += int64(n) + } + w.buffers.Put(obuf) + // Queue final output. + nRet += len(uncompressed) + } + return nRet, nil +} + +// AsyncFlush writes any buffered bytes to a block and starts compressing it. +// It does not wait for the output has been written as Flush() does. +func (w *Writer) AsyncFlush() error { + if err := w.err(nil); err != nil { + return err + } + + // Queue any data still in input buffer. + if len(w.ibuf) != 0 { + if !w.wroteStreamHeader { + _, err := w.writeSync(w.ibuf) + w.ibuf = w.ibuf[:0] + return w.err(err) + } else { + _, err := w.write(w.ibuf) + w.ibuf = w.ibuf[:0] + err = w.err(err) + if err != nil { + return err + } + } + } + return w.err(nil) +} + +// Flush flushes the Writer to its underlying io.Writer. +// This does not apply padding. +func (w *Writer) Flush() error { + if err := w.AsyncFlush(); err != nil { + return err + } + if w.output == nil { + return w.err(nil) + } + + // Send empty buffer + res := make(chan result) + w.output <- res + // Block until this has been picked up. + res <- result{b: nil, startOffset: w.uncompWritten} + // When it is closed, we have flushed. + <-res + return w.err(nil) +} + +// Close calls Flush and then closes the Writer. +// Calling Close multiple times is ok, +// but calling CloseIndex after this will make it not return the index. +func (w *Writer) Close() error { + _, err := w.closeIndex(w.appendIndex) + return err +} + +// CloseIndex calls Close and returns an index on first call. +// This is not required if you are only adding index to a stream. +func (w *Writer) CloseIndex() ([]byte, error) { + return w.closeIndex(true) +} + +func (w *Writer) closeIndex(idx bool) ([]byte, error) { + err := w.Flush() + if w.output != nil { + close(w.output) + w.writerWg.Wait() + w.output = nil + } + + var index []byte + if w.err(err) == nil && w.writer != nil { + // Create index. + if idx { + compSize := int64(-1) + if w.pad <= 1 { + compSize = w.written + } + index = w.index.appendTo(w.ibuf[:0], w.uncompWritten, compSize) + // Count as written for padding. + if w.appendIndex { + w.written += int64(len(index)) + } + } + + if w.pad > 1 { + tmp := w.ibuf[:0] + if len(index) > 0 { + // Allocate another buffer. + tmp = w.buffers.Get().([]byte)[:0] + defer w.buffers.Put(tmp) + } + add := calcSkippableFrame(w.written, int64(w.pad)) + frame, err := skippableFrame(tmp, add, w.randSrc) + if err = w.err(err); err != nil { + return nil, err + } + n, err2 := w.writer.Write(frame) + if err2 == nil && n != len(frame) { + err2 = io.ErrShortWrite + } + _ = w.err(err2) + } + if len(index) > 0 && w.appendIndex { + n, err2 := w.writer.Write(index) + if err2 == nil && n != len(index) { + err2 = io.ErrShortWrite + } + _ = w.err(err2) + } + } + err = w.err(errClosed) + if err == errClosed { + return index, nil + } + return nil, err +} + +// calcSkippableFrame will return a total size to be added for written +// to be divisible by multiple. +// The value will always be > skippableFrameHeader. +// The function will panic if written < 0 or wantMultiple <= 0. +func calcSkippableFrame(written, wantMultiple int64) int { + if wantMultiple <= 0 { + panic("wantMultiple <= 0") + } + if written < 0 { + panic("written < 0") + } + leftOver := written % wantMultiple + if leftOver == 0 { + return 0 + } + toAdd := wantMultiple - leftOver + for toAdd < skippableFrameHeader { + toAdd += wantMultiple + } + return int(toAdd) +} + +// skippableFrame will add a skippable frame with a total size of bytes. +// total should be >= skippableFrameHeader and < maxBlockSize + skippableFrameHeader +func skippableFrame(dst []byte, total int, r io.Reader) ([]byte, error) { + if total == 0 { + return dst, nil + } + if total < skippableFrameHeader { + return dst, fmt.Errorf("s2: requested skippable frame (%d) < 4", total) + } + if int64(total) >= maxBlockSize+skippableFrameHeader { + return dst, fmt.Errorf("s2: requested skippable frame (%d) >= max 1<<24", total) + } + // Chunk type 0xfe "Section 4.4 Padding (chunk type 0xfe)" + dst = append(dst, chunkTypePadding) + f := uint32(total - skippableFrameHeader) + // Add chunk length. + dst = append(dst, uint8(f), uint8(f>>8), uint8(f>>16)) + // Add data + start := len(dst) + dst = append(dst, make([]byte, f)...) + _, err := io.ReadFull(r, dst[start:]) + return dst, err +} + +var errClosed = errors.New("s2: Writer is closed") + +// WriterOption is an option for creating a encoder. +type WriterOption func(*Writer) error + +// WriterConcurrency will set the concurrency, +// meaning the maximum number of decoders to run concurrently. +// The value supplied must be at least 1. +// By default this will be set to GOMAXPROCS. +func WriterConcurrency(n int) WriterOption { + return func(w *Writer) error { + if n <= 0 { + return errors.New("concurrency must be at least 1") + } + w.concurrency = n + return nil + } +} + +// WriterAddIndex will append an index to the end of a stream +// when it is closed. +func WriterAddIndex() WriterOption { + return func(w *Writer) error { + w.appendIndex = true + return nil + } +} + +// WriterBetterCompression will enable better compression. +// EncodeBetter compresses better than Encode but typically with a +// 10-40% speed decrease on both compression and decompression. +func WriterBetterCompression() WriterOption { + return func(w *Writer) error { + w.level = levelBetter + return nil + } +} + +// WriterBestCompression will enable better compression. +// EncodeBest compresses better than Encode but typically with a +// big speed decrease on compression. +func WriterBestCompression() WriterOption { + return func(w *Writer) error { + w.level = levelBest + return nil + } +} + +// WriterUncompressed will bypass compression. +// The stream will be written as uncompressed blocks only. +// If concurrency is > 1 CRC and output will still be done async. +func WriterUncompressed() WriterOption { + return func(w *Writer) error { + w.level = levelUncompressed + return nil + } +} + +// WriterBufferDone will perform a callback when EncodeBuffer has finished +// writing a buffer to the output and the buffer can safely be reused. +// If the buffer was split into several blocks, it will be sent after the last block. +// Callbacks will not be done concurrently. +func WriterBufferDone(fn func(b []byte)) WriterOption { + return func(w *Writer) error { + w.bufferCB = fn + return nil + } +} + +// WriterBlockSize allows to override the default block size. +// Blocks will be this size or smaller. +// Minimum size is 4KB and maximum size is 4MB. +// +// Bigger blocks may give bigger throughput on systems with many cores, +// and will increase compression slightly, but it will limit the possible +// concurrency for smaller payloads for both encoding and decoding. +// Default block size is 1MB. +// +// When writing Snappy compatible output using WriterSnappyCompat, +// the maximum block size is 64KB. +func WriterBlockSize(n int) WriterOption { + return func(w *Writer) error { + if w.snappy && n > maxSnappyBlockSize || n < minBlockSize { + return errors.New("s2: block size too large. Must be <= 64K and >=4KB on for snappy compatible output") + } + if n > maxBlockSize || n < minBlockSize { + return errors.New("s2: block size too large. Must be <= 4MB and >=4KB") + } + w.blockSize = n + return nil + } +} + +// WriterPadding will add padding to all output so the size will be a multiple of n. +// This can be used to obfuscate the exact output size or make blocks of a certain size. +// The contents will be a skippable frame, so it will be invisible by the decoder. +// n must be > 0 and <= 4MB. +// The padded area will be filled with data from crypto/rand.Reader. +// The padding will be applied whenever Close is called on the writer. +func WriterPadding(n int) WriterOption { + return func(w *Writer) error { + if n <= 0 { + return fmt.Errorf("s2: padding must be at least 1") + } + // No need to waste our time. + if n == 1 { + w.pad = 0 + } + if n > maxBlockSize { + return fmt.Errorf("s2: padding must less than 4MB") + } + w.pad = n + return nil + } +} + +// WriterPaddingSrc will get random data for padding from the supplied source. +// By default crypto/rand is used. +func WriterPaddingSrc(reader io.Reader) WriterOption { + return func(w *Writer) error { + w.randSrc = reader + return nil + } +} + +// WriterSnappyCompat will write snappy compatible output. +// The output can be decompressed using either snappy or s2. +// If block size is more than 64KB it is set to that. +func WriterSnappyCompat() WriterOption { + return func(w *Writer) error { + w.snappy = true + if w.blockSize > 64<<10 { + // We choose 8 bytes less than 64K, since that will make literal emits slightly more effective. + // And allows us to skip some size checks. + w.blockSize = (64 << 10) - 8 + } + return nil + } +} + +// WriterFlushOnWrite will compress blocks on each call to the Write function. +// +// This is quite inefficient as blocks size will depend on the write size. +// +// Use WriterConcurrency(1) to also make sure that output is flushed. +// When Write calls return, otherwise they will be written when compression is done. +func WriterFlushOnWrite() WriterOption { + return func(w *Writer) error { + w.flushOnWrite = true + return nil + } +} + +// WriterCustomEncoder allows to override the encoder for blocks on the stream. +// The function must compress 'src' into 'dst' and return the bytes used in dst as an integer. +// Block size (initial varint) should not be added by the encoder. +// Returning value 0 indicates the block could not be compressed. +// Returning a negative value indicates that compression should be attempted. +// The function should expect to be called concurrently. +func WriterCustomEncoder(fn func(dst, src []byte) int) WriterOption { + return func(w *Writer) error { + w.customEnc = fn + return nil + } +} diff --git a/vendor/github.com/minio/highwayhash/.golangci.yml b/vendor/github.com/minio/highwayhash/.golangci.yml new file mode 100644 index 0000000..39310d0 --- /dev/null +++ b/vendor/github.com/minio/highwayhash/.golangci.yml @@ -0,0 +1,28 @@ +linters-settings: + golint: + min-confidence: 0 + + misspell: + locale: US + +linters: + disable-all: true + enable: + - typecheck + - goimports + - misspell + - govet + - revive + - ineffassign + - gosimple + - unparam + - unused + +issues: + exclude-use-default: false + exclude: + - should have a package comment + - error strings should not be capitalized or end with punctuation or a newline + - should have comment # TODO(aead): Remove once all exported ident. have comments! +service: + golangci-lint-version: 1.51.2 # use the fixed version to not introduce new linters unexpectedly diff --git a/vendor/github.com/minio/highwayhash/.travis.yml b/vendor/github.com/minio/highwayhash/.travis.yml deleted file mode 100644 index d62c80e..0000000 --- a/vendor/github.com/minio/highwayhash/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -go_import_path: github.com/minio/highwayhash -sudo: required - -dist: trusty - -language: go - -os: -- linux - -env: -- ARCH=x86_64 -- ARCH=i686 - -go: -- "1.7" -- "1.8.7" -- "1.9.4" -- "1.10" - -script: -- diff -au <(gofmt -d .) <(printf "") -- go vet ./... -- go test -v ./... diff --git a/vendor/github.com/minio/highwayhash/LICENSE b/vendor/github.com/minio/highwayhash/LICENSE index e3a0a95..d645695 100644 --- a/vendor/github.com/minio/highwayhash/LICENSE +++ b/vendor/github.com/minio/highwayhash/LICENSE @@ -1,21 +1,202 @@ -MIT License - -Copyright (c) 2017 Minio Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/minio/highwayhash/README.md b/vendor/github.com/minio/highwayhash/README.md index 18e179c..0504822 100644 --- a/vendor/github.com/minio/highwayhash/README.md +++ b/vendor/github.com/minio/highwayhash/README.md @@ -42,13 +42,18 @@ So for moderately sized messages it tops out at about 15 GB/sec. Also for small ### ARM Performance -On an 8 core 1.2 GHz ARM Cortex-A53 (running Debian 8.0 Jessie with Go 1.7.4) the following results were obtained: +Below are the single core results on an EC2 c7g.4xlarge (Graviton3) instance for 256 bit outputs: -Platform/CPU | Write 64 | Write 1024 | Write 8192 ------------------ | ---------------- | ----------------- | ----------------- -ARM64 NEON | 384 MB/s | 955 MB/s | 1053 MB/s - -*Note: For now just the (main) update loop is implemented in assembly, so for small messages there is still considerable overhead due to initialization and finalization.* +``` +BenchmarkSum256_16 143.66 MB/s +BenchmarkSum256_64 628.75 MB/s +BenchmarkSum256_1K 3621.71 MB/s +BenchmarkSum256_8K 5039.64 MB/s +BenchmarkSum256_1M 5279.79 MB/s +BenchmarkSum256_5M 5474.60 MB/s +BenchmarkSum256_10M 5621.73 MB/s +BenchmarkSum256_25M 5250.47 MB/s +``` ### ppc64le Performance @@ -87,7 +92,7 @@ More information can be found in [HashCompare](https://github.com/fwessels/HashC ### Requirements -All Go versions >= 1.7 are supported. Notice that the amd64 AVX2 implementation is only available with Go 1.8 and newer. +All Go versions >= 1.11 are supported (needed for required assembly support for the different platforms). ### Contributing diff --git a/vendor/github.com/minio/highwayhash/go.mod b/vendor/github.com/minio/highwayhash/go.mod deleted file mode 100644 index 311d0a0..0000000 --- a/vendor/github.com/minio/highwayhash/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/minio/highwayhash - -require golang.org/x/sys v0.0.0-20190130150945-aca44879d564 diff --git a/vendor/github.com/minio/highwayhash/go.sum b/vendor/github.com/minio/highwayhash/go.sum deleted file mode 100644 index b45a8e1..0000000 --- a/vendor/github.com/minio/highwayhash/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -golang.org/x/sys v0.0.0-20190130150945-aca44879d564 h1:o6ENHFwwr1TZ9CUPQcfo1HGvLP1OPsPOTB7xCIOPNmU= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/minio/highwayhash/highwayhash.go b/vendor/github.com/minio/highwayhash/highwayhash.go index 629fdf2..2e59a61 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash.go +++ b/vendor/github.com/minio/highwayhash/highwayhash.go @@ -25,39 +25,64 @@ const ( Size64 = 8 ) +// These will error at compile time if the interface is not conformant. +var _ hash.Hash = &Digest{} +var _ hash.Hash = &Digest64{} + var errKeySize = errors.New("highwayhash: invalid key size") // New returns a hash.Hash computing the HighwayHash-256 checksum. // It returns a non-nil error if the key is not 32 bytes long. func New(key []byte) (hash.Hash, error) { + return NewDigest(key) +} + +// New128 returns a hash.Hash computing the HighwayHash-128 checksum. +// It returns a non-nil error if the key is not 32 bytes long. +func New128(key []byte) (hash.Hash, error) { + return NewDigest128(key) +} + +// New64 returns a hash.Hash64 computing the HighwayHash-64 checksum. +// It returns a non-nil error if the key is not 32 bytes long. +func New64(key []byte) (hash.Hash64, error) { + return NewDigest64(key) +} + +// NewDigest returns a *Digest that conforms to hash.Hash computing +// the HighwayHash-256 checksum. +// It returns a non-nil error if the key is not 32 bytes long. +func NewDigest(key []byte) (*Digest, error) { if len(key) != Size { return nil, errKeySize } - h := &digest{size: Size} + h := &Digest{size: Size} copy(h.key[:], key) h.Reset() return h, nil } -// New128 returns a hash.Hash computing the HighwayHash-128 checksum. +// NewDigest128 returns a *Digest that conforms to hash.Hash computing +// the HighwayHash-128 checksum. // It returns a non-nil error if the key is not 32 bytes long. -func New128(key []byte) (hash.Hash, error) { +func NewDigest128(key []byte) (*Digest, error) { if len(key) != Size { return nil, errKeySize } - h := &digest{size: Size128} + h := &Digest{size: Size128} copy(h.key[:], key) h.Reset() return h, nil } -// New64 returns a hash.Hash computing the HighwayHash-64 checksum. +// NewDigest64 returns a *Digest that conforms to hash.Hash computing +// the HighwayHash-64 checksum. // It returns a non-nil error if the key is not 32 bytes long. -func New64(key []byte) (hash.Hash64, error) { +func NewDigest64(key []byte) (*Digest64, error) { if len(key) != Size { return nil, errKeySize } - h := new(digest64) + h := new(Digest64) h.size = Size64 copy(h.key[:], key) h.Reset() @@ -130,9 +155,9 @@ func Sum64(data, key []byte) uint64 { return binary.LittleEndian.Uint64(hash[:]) } -type digest64 struct{ digest } +type Digest64 struct{ Digest } -func (d *digest64) Sum64() uint64 { +func (d *Digest64) Sum64() uint64 { state := d.state if d.offset > 0 { hashBuffer(&state, &d.buffer, d.offset) @@ -142,7 +167,7 @@ func (d *digest64) Sum64() uint64 { return binary.LittleEndian.Uint64(hash[:]) } -type digest struct { +type Digest struct { state [16]uint64 // v0 | v1 | mul0 | mul1 key, buffer [Size]byte @@ -151,16 +176,16 @@ type digest struct { size int } -func (d *digest) Size() int { return d.size } +func (d *Digest) Size() int { return d.size } -func (d *digest) BlockSize() int { return Size } +func (d *Digest) BlockSize() int { return Size } -func (d *digest) Reset() { +func (d *Digest) Reset() { initialize(&d.state, d.key[:]) d.offset = 0 } -func (d *digest) Write(p []byte) (n int, err error) { +func (d *Digest) Write(p []byte) (n int, err error) { n = len(p) if d.offset > 0 { remaining := Size - d.offset @@ -183,7 +208,7 @@ func (d *digest) Write(p []byte) (n int, err error) { return } -func (d *digest) Sum(b []byte) []byte { +func (d *Digest) Sum(b []byte) []byte { state := d.state if d.offset > 0 { hashBuffer(&state, &d.buffer, d.offset) diff --git a/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.go b/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.go deleted file mode 100644 index d2b03d7..0000000 --- a/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2017 Minio Inc. All rights reserved. -// Use of this source code is governed by a license that can be -// found in the LICENSE file. - -// +build go1.8 -// +build amd64 !gccgo !appengine !nacl - -package highwayhash - -import "golang.org/x/sys/cpu" - -var ( - useSSE4 = cpu.X86.HasSSE41 - useAVX2 = cpu.X86.HasAVX2 - useNEON = false - useVMX = false -) - -//go:noescape -func initializeSSE4(state *[16]uint64, key []byte) - -//go:noescape -func initializeAVX2(state *[16]uint64, key []byte) - -//go:noescape -func updateSSE4(state *[16]uint64, msg []byte) - -//go:noescape -func updateAVX2(state *[16]uint64, msg []byte) - -//go:noescape -func finalizeSSE4(out []byte, state *[16]uint64) - -//go:noescape -func finalizeAVX2(out []byte, state *[16]uint64) - -func initialize(state *[16]uint64, key []byte) { - switch { - case useAVX2: - initializeAVX2(state, key) - case useSSE4: - initializeSSE4(state, key) - default: - initializeGeneric(state, key) - } -} - -func update(state *[16]uint64, msg []byte) { - switch { - case useAVX2: - updateAVX2(state, msg) - case useSSE4: - updateSSE4(state, msg) - default: - updateGeneric(state, msg) - } -} - -func finalize(out []byte, state *[16]uint64) { - switch { - case useAVX2: - finalizeAVX2(out, state) - case useSSE4: - finalizeSSE4(out, state) - default: - finalizeGeneric(out, state) - } -} diff --git a/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.s b/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.s index 03a1eb3..e6e4263 100644 --- a/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.s +++ b/vendor/github.com/minio/highwayhash/highwayhashAVX2_amd64.s @@ -2,8 +2,7 @@ // Use of this source code is governed by a license that can be // found in the LICENSE file. -// +build go1.8 -// +build amd64 !gccgo !appengine !nacl +// +build amd64,!gccgo,!appengine,!nacl,!noasm #include "textflag.h" diff --git a/vendor/github.com/minio/highwayhash/highwayhashSVE_arm64.s b/vendor/github.com/minio/highwayhash/highwayhashSVE_arm64.s new file mode 100644 index 0000000..e9b6eb0 --- /dev/null +++ b/vendor/github.com/minio/highwayhash/highwayhashSVE_arm64.s @@ -0,0 +1,132 @@ +// +// Copyright (c) 2024 Minio Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//+build !noasm,!appengine + +#include "textflag.h" + +TEXT ·getVectorLength(SB), NOSPLIT, $0 + WORD $0xd2800002 // mov x2, #0 + WORD $0x04225022 // addvl x2, x2, #1 + WORD $0xd37df042 // lsl x2, x2, #3 + WORD $0xd2800003 // mov x3, #0 + WORD $0x04635023 // addpl x3, x3, #1 + WORD $0xd37df063 // lsl x3, x3, #3 + MOVD R2, vl+0(FP) + MOVD R3, pl+8(FP) + RET + +TEXT ·updateArm64Sve(SB), NOSPLIT, $0 + MOVD state+0(FP), R0 + MOVD msg_base+8(FP), R1 + MOVD msg_len+16(FP), R2 // length of message + SUBS $32, R2 + BMI completeSve + + WORD $0x2518e3e1 // ptrue p1.b + WORD $0xa5e0a401 // ld1d z1.d, p1/z, [x0] + WORD $0xa5e1a402 // ld1d z2.d, p1/z, [x0, #1, MUL VL] + WORD $0xa5e2a403 // ld1d z3.d, p1/z, [x0, #2, MUL VL] + WORD $0xa5e3a404 // ld1d z4.d, p1/z, [x0, #3, MUL VL] + + // Load zipper merge constants table pointer + MOVD $·zipperMergeSve(SB), R3 + WORD $0xa5e0a465 // ld1d z5.d, p1/z, [x3] + WORD $0x25b8c006 // mov z6.s, #0 + WORD $0x25d8e3e2 // ptrue p2.d /* set every other lane for "s" type */ + +loopSve: + WORD $0xa5e0a420 // ld1d z0.d, p1/z, [x1] + ADD $32, R1 + + WORD $0x04e00042 // add z2.d, z2.d, z0.d + WORD $0x04e30042 // add z2.d, z2.d, z3.d + WORD $0x04e09420 // lsr z0.d, z1.d, #32 + WORD $0x05a6c847 // sel z7.s, p2, z2.s, z6.s + WORD $0x04d004e0 // mul z0.d, p1/m, z0.d, z7.d + WORD $0x04a33003 // eor z3.d, z0.d, z3.d + WORD $0x04e10081 // add z1.d, z4.d, z1.d + WORD $0x04e09440 // lsr z0.d, z2.d, #32 + WORD $0x05a6c827 // sel z7.s, p2, z1.s, z6.s + WORD $0x04d004e0 // mul z0.d, p1/m, z0.d, z7.d + WORD $0x04a43004 // eor z4.d, z0.d, z4.d + WORD $0x05253040 // tbl z0.b, z2.b, z5.b + WORD $0x04e00021 // add z1.d, z1.d, z0.d + WORD $0x05253020 // tbl z0.b, z1.b, z5.b + WORD $0x04e00042 // add z2.d, z2.d, z0.d + + SUBS $32, R2 + BPL loopSve + + WORD $0xe5e0e401 // st1d z1.d, p1, [x0] + WORD $0xe5e1e402 // st1d z2.d, p1, [x0, #1, MUL VL] + WORD $0xe5e2e403 // st1d z3.d, p1, [x0, #2, MUL VL] + WORD $0xe5e3e404 // st1d z4.d, p1, [x0, #3, MUL VL] + +completeSve: + RET + +TEXT ·updateArm64Sve2(SB), NOSPLIT, $0 + MOVD state+0(FP), R0 + MOVD msg_base+8(FP), R1 + MOVD msg_len+16(FP), R2 // length of message + SUBS $32, R2 + BMI completeSve2 + + WORD $0x2518e3e1 // ptrue p1.b + WORD $0xa5e0a401 // ld1d z1.d, p1/z, [x0] + WORD $0xa5e1a402 // ld1d z2.d, p1/z, [x0, #1, MUL VL] + WORD $0xa5e2a403 // ld1d z3.d, p1/z, [x0, #2, MUL VL] + WORD $0xa5e3a404 // ld1d z4.d, p1/z, [x0, #3, MUL VL] + + // Load zipper merge constants table pointer + MOVD $·zipperMergeSve(SB), R3 + WORD $0xa5e0a465 // ld1d z5.d, p1/z, [x3] + +loopSve2: + WORD $0xa5e0a420 // ld1d z0.d, p1/z, [x1] + ADD $32, R1 + + WORD $0x04e00042 // add z2.d, z2.d, z0.d + WORD $0x04e30042 // add z2.d, z2.d, z3.d + WORD $0x04e09420 // lsr z0.d, z1.d, #32 + WORD $0x45c27800 // umullb z0.d, z0.s, z2.s + WORD $0x04a33003 // eor z3.d, z0.d, z3.d + WORD $0x04e10081 // add z1.d, z4.d, z1.d + WORD $0x04e09440 // lsr z0.d, z2.d, #32 + WORD $0x45c17800 // umullb z0.d, z0.s, z1.s + WORD $0x04a43004 // eor z4.d, z0.d, z4.d + WORD $0x05253040 // tbl z0.b, z2.b, z5.b + WORD $0x04e00021 // add z1.d, z1.d, z0.d + WORD $0x05253020 // tbl z0.b, z1.b, z5.b + WORD $0x04e00042 // add z2.d, z2.d, z0.d + + SUBS $32, R2 + BPL loopSve2 + + WORD $0xe5e0e401 // st1d z1.d, p1, [x0] + WORD $0xe5e1e402 // st1d z2.d, p1, [x0, #1, MUL VL] + WORD $0xe5e2e403 // st1d z3.d, p1, [x0, #2, MUL VL] + WORD $0xe5e3e404 // st1d z4.d, p1, [x0, #3, MUL VL] + +completeSve2: + RET + +DATA ·zipperMergeSve+0x00(SB)/8, $0x000f010e05020c03 +DATA ·zipperMergeSve+0x08(SB)/8, $0x070806090d0a040b +DATA ·zipperMergeSve+0x10(SB)/8, $0x101f111e15121c13 +DATA ·zipperMergeSve+0x18(SB)/8, $0x171816191d1a141b +GLOBL ·zipperMergeSve(SB), (NOPTR+RODATA), $32 diff --git a/vendor/github.com/minio/highwayhash/highwayhash_amd64.go b/vendor/github.com/minio/highwayhash/highwayhash_amd64.go index 703635b..b771783 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_amd64.go +++ b/vendor/github.com/minio/highwayhash/highwayhash_amd64.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a license that can be // found in the LICENSE file. -// +build !go1.8 -// +build amd64 !gccgo !appengine !nacl +//go:build amd64 && !gccgo && !appengine && !nacl && !noasm +// +build amd64,!gccgo,!appengine,!nacl,!noasm package highwayhash @@ -11,40 +11,60 @@ import "golang.org/x/sys/cpu" var ( useSSE4 = cpu.X86.HasSSE41 - useAVX2 = false + useAVX2 = cpu.X86.HasAVX2 useNEON = false + useSVE = false + useSVE2 = false useVMX = false ) //go:noescape func initializeSSE4(state *[16]uint64, key []byte) +//go:noescape +func initializeAVX2(state *[16]uint64, key []byte) + //go:noescape func updateSSE4(state *[16]uint64, msg []byte) +//go:noescape +func updateAVX2(state *[16]uint64, msg []byte) + //go:noescape func finalizeSSE4(out []byte, state *[16]uint64) +//go:noescape +func finalizeAVX2(out []byte, state *[16]uint64) + func initialize(state *[16]uint64, key []byte) { - if useSSE4 { + switch { + case useAVX2: + initializeAVX2(state, key) + case useSSE4: initializeSSE4(state, key) - } else { + default: initializeGeneric(state, key) } } func update(state *[16]uint64, msg []byte) { - if useSSE4 { + switch { + case useAVX2: + updateAVX2(state, msg) + case useSSE4: updateSSE4(state, msg) - } else { + default: updateGeneric(state, msg) } } func finalize(out []byte, state *[16]uint64) { - if useSSE4 { + switch { + case useAVX2: + finalizeAVX2(out, state) + case useSSE4: finalizeSSE4(out, state) - } else { + default: finalizeGeneric(out, state) } } diff --git a/vendor/github.com/minio/highwayhash/highwayhash_amd64.s b/vendor/github.com/minio/highwayhash/highwayhash_amd64.s index ff8ac2a..43ecf3b 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_amd64.s +++ b/vendor/github.com/minio/highwayhash/highwayhash_amd64.s @@ -6,19 +6,19 @@ #include "textflag.h" -DATA ·cons<>+0x00(SB)/8, $0xdbe6d5d5fe4cce2f -DATA ·cons<>+0x08(SB)/8, $0xa4093822299f31d0 -DATA ·cons<>+0x10(SB)/8, $0x13198a2e03707344 -DATA ·cons<>+0x18(SB)/8, $0x243f6a8885a308d3 -DATA ·cons<>+0x20(SB)/8, $0x3bd39e10cb0ef593 -DATA ·cons<>+0x28(SB)/8, $0xc0acf169b5f18a8c -DATA ·cons<>+0x30(SB)/8, $0xbe5466cf34e90c6c -DATA ·cons<>+0x38(SB)/8, $0x452821e638d01377 -GLOBL ·cons<>(SB), (NOPTR+RODATA), $64 - -DATA ·zipperMerge<>+0x00(SB)/8, $0xf010e05020c03 -DATA ·zipperMerge<>+0x08(SB)/8, $0x70806090d0a040b -GLOBL ·zipperMerge<>(SB), (NOPTR+RODATA), $16 +DATA ·asmConstants<>+0x00(SB)/8, $0xdbe6d5d5fe4cce2f +DATA ·asmConstants<>+0x08(SB)/8, $0xa4093822299f31d0 +DATA ·asmConstants<>+0x10(SB)/8, $0x13198a2e03707344 +DATA ·asmConstants<>+0x18(SB)/8, $0x243f6a8885a308d3 +DATA ·asmConstants<>+0x20(SB)/8, $0x3bd39e10cb0ef593 +DATA ·asmConstants<>+0x28(SB)/8, $0xc0acf169b5f18a8c +DATA ·asmConstants<>+0x30(SB)/8, $0xbe5466cf34e90c6c +DATA ·asmConstants<>+0x38(SB)/8, $0x452821e638d01377 +GLOBL ·asmConstants<>(SB), (NOPTR+RODATA), $64 + +DATA ·asmZipperMerge<>+0x00(SB)/8, $0xf010e05020c03 +DATA ·asmZipperMerge<>+0x08(SB)/8, $0x70806090d0a040b +GLOBL ·asmZipperMerge<>(SB), (NOPTR+RODATA), $16 #define v00 X0 #define v01 X1 @@ -104,10 +104,10 @@ GLOBL ·zipperMerge<>(SB), (NOPTR+RODATA), $16 PADDQ t1, v11 // func initializeSSE4(state *[16]uint64, key []byte) -TEXT ·initializeSSE4(SB), 4, $0-32 +TEXT ·initializeSSE4(SB), NOSPLIT, $0-32 MOVQ state+0(FP), AX MOVQ key_base+8(FP), BX - MOVQ $·cons<>(SB), CX + MOVQ $·asmConstants<>(SB), CX MOVOU 0(BX), v00 MOVOU 16(BX), v01 @@ -136,7 +136,7 @@ TEXT ·initializeSSE4(SB), 4, $0-32 RET // func updateSSE4(state *[16]uint64, msg []byte) -TEXT ·updateSSE4(SB), 4, $0-32 +TEXT ·updateSSE4(SB), NOSPLIT, $0-32 MOVQ state+0(FP), AX MOVQ msg_base+8(FP), BX MOVQ msg_len+16(FP), CX @@ -153,7 +153,7 @@ TEXT ·updateSSE4(SB), 4, $0-32 MOVOU 96(AX), m10 MOVOU 112(AX), m11 - MOVOU ·zipperMerge<>(SB), t2 + MOVOU ·asmZipperMerge<>(SB), t2 LOOP: MOVOU 0(BX), t0 @@ -178,7 +178,7 @@ DONE: RET // func finalizeSSE4(out []byte, state *[16]uint64) -TEXT ·finalizeSSE4(SB), 4, $0-32 +TEXT ·finalizeSSE4(SB), NOSPLIT, $0-32 MOVQ state+24(FP), AX MOVQ out_base+0(FP), BX MOVQ out_len+8(FP), CX @@ -192,7 +192,7 @@ TEXT ·finalizeSSE4(SB), 4, $0-32 MOVOU 96(AX), m10 MOVOU 112(AX), m11 - MOVOU ·zipperMerge<>(SB), t2 + MOVOU ·asmZipperMerge<>(SB), t2 PSHUFD $177, v01, t0 PSHUFD $177, v00, t1 diff --git a/vendor/github.com/minio/highwayhash/highwayhash_arm64.go b/vendor/github.com/minio/highwayhash/highwayhash_arm64.go index 387e46d..dfff06e 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_arm64.go +++ b/vendor/github.com/minio/highwayhash/highwayhash_arm64.go @@ -1,27 +1,71 @@ -//+build !noasm - -// Copyright (c) 2017 Minio Inc. All rights reserved. +// Copyright (c) 2017-2024 Minio Inc. All rights reserved. // Use of this source code is governed by a license that can be // found in the LICENSE file. +//go:build !noasm && !appengine +// +build !noasm,!appengine + package highwayhash +import ( + "golang.org/x/sys/cpu" +) + var ( useSSE4 = false useAVX2 = false - useNEON = true + useNEON = cpu.ARM64.HasASIMD + useSVE = cpu.ARM64.HasSVE + useSVE2 = false // cpu.ARM64.HasSVE2 -- disable until tested on real hardware useVMX = false ) +func init() { + if useSVE { + if vl, _ := getVectorLength(); vl != 256 { + // + // Since HighwayHash is designed for AVX2, + // SVE/SVE2 instructions only run correctly + // for vector length of 256 + // + useSVE2 = false + useSVE = false + } + } +} + +//go:noescape +func initializeArm64(state *[16]uint64, key []byte) + //go:noescape func updateArm64(state *[16]uint64, msg []byte) +//go:noescape +func getVectorLength() (vl, pl uint64) + +//go:noescape +func updateArm64Sve(state *[16]uint64, msg []byte) + +//go:noescape +func updateArm64Sve2(state *[16]uint64, msg []byte) + +//go:noescape +func finalizeArm64(out []byte, state *[16]uint64) + func initialize(state *[16]uint64, key []byte) { - initializeGeneric(state, key) + if useNEON { + initializeArm64(state, key) + } else { + initializeGeneric(state, key) + } } func update(state *[16]uint64, msg []byte) { - if useNEON { + if useSVE2 { + updateArm64Sve2(state, msg) + } else if useSVE { + updateArm64Sve(state, msg) + } else if useNEON { updateArm64(state, msg) } else { updateGeneric(state, msg) @@ -29,5 +73,9 @@ func update(state *[16]uint64, msg []byte) { } func finalize(out []byte, state *[16]uint64) { - finalizeGeneric(out, state) + if useNEON { + finalizeArm64(out, state) + } else { + finalizeGeneric(out, state) + } } diff --git a/vendor/github.com/minio/highwayhash/highwayhash_arm64.s b/vendor/github.com/minio/highwayhash/highwayhash_arm64.s index 6498b4c..5e97a28 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_arm64.s +++ b/vendor/github.com/minio/highwayhash/highwayhash_arm64.s @@ -1,5 +1,3 @@ -//+build !noasm !appengine - // // Minio Cloud Storage, (C) 2017 Minio, Inc. // @@ -16,10 +14,115 @@ // limitations under the License. // +//+build !noasm,!appengine + // Use github.com/minio/asm2plan9s on this file to assemble ARM instructions to // the opcodes of their Plan9 equivalents -TEXT ·updateArm64(SB), 7, $0 +#include "textflag.h" + +#define REDUCE_MOD(x0, x1, x2, x3, tmp0, tmp1, y0, y1) \ + MOVD $0x3FFFFFFFFFFFFFFF, tmp0 \ + AND tmp0, x3 \ + MOVD x2, y0 \ + MOVD x3, y1 \ + \ + MOVD x2, tmp0 \ + MOVD x3, tmp1 \ + LSL $1, tmp1 \ + LSR $63, tmp0 \ + MOVD tmp1, x3 \ + ORR tmp0, x3 \ + \ + LSL $1, x2 \ + \ + MOVD y0, tmp0 \ + MOVD y1, tmp1 \ + LSL $2, tmp1 \ + LSR $62, tmp0 \ + MOVD tmp1, y1 \ + ORR tmp0, y1 \ + \ + LSL $2, y0 \ + \ + EOR x0, y0 \ + EOR x2, y0 \ + EOR x1, y1 \ + EOR x3, y1 + +#define UPDATE(MSG1, MSG2) \ + \ // Add message + VADD MSG1.D2, V2.D2, V2.D2 \ + VADD MSG2.D2, V3.D2, V3.D2 \ + \ + \ // v1 += mul0 + VADD V4.D2, V2.D2, V2.D2 \ + VADD V5.D2, V3.D2, V3.D2 \ + \ + \ // First pair of multiplies + VTBL V29.B16, [V0.B16, V1.B16], V10.B16 \ + VTBL V30.B16, [V2.B16, V3.B16], V11.B16 \ + \ + \ // VUMULL V10.S2, V11.S2, V12.D2 /* assembler support missing */ + \ // VUMULL2 V10.S4, V11.S4, V13.D2 /* assembler support missing */ + WORD $0x2eaac16c \ // umull v12.2d, v11.2s, v10.2s + WORD $0x6eaac16d \ // umull2 v13.2d, v11.4s, v10.4s + \ + \ // v0 += mul1 + VADD V6.D2, V0.D2, V0.D2 \ + VADD V7.D2, V1.D2, V1.D2 \ + \ + \ // Second pair of multiplies + VTBL V29.B16, [V2.B16, V3.B16], V15.B16 \ + VTBL V30.B16, [V0.B16, V1.B16], V14.B16 \ + \ + \ // EOR multiplication result in + VEOR V12.B16, V4.B16, V4.B16 \ + VEOR V13.B16, V5.B16, V5.B16 \ + \ + \ // VUMULL V14.S2, V15.S2, V16.D2 /* assembler support missing */ + \ // VUMULL2 V14.S4, V15.S4, V17.D2 /* assembler support missing */ + WORD $0x2eaec1f0 \ // umull v16.2d, v15.2s, v14.2s + WORD $0x6eaec1f1 \ // umull2 v17.2d, v15.4s, v14.4s + \ + \ // First pair of zipper-merges + VTBL V28.B16, [V2.B16], V18.B16 \ + VADD V18.D2, V0.D2, V0.D2 \ + VTBL V28.B16, [V3.B16], V19.B16 \ + VADD V19.D2, V1.D2, V1.D2 \ + \ + \ // Second pair of zipper-merges + VTBL V28.B16, [V0.B16], V20.B16 \ + VADD V20.D2, V2.D2, V2.D2 \ + VTBL V28.B16, [V1.B16], V21.B16 \ + VADD V21.D2, V3.D2, V3.D2 \ + \ + \ // EOR multiplication result in + VEOR V16.B16, V6.B16, V6.B16 \ + VEOR V17.B16, V7.B16, V7.B16 + +// func initializeArm64(state *[16]uint64, key []byte) +TEXT ·initializeArm64(SB), NOSPLIT, $0 + MOVD state+0(FP), R0 + MOVD key_base+8(FP), R1 + + VLD1 (R1), [V1.S4, V2.S4] + + VREV64 V1.S4, V3.S4 + VREV64 V2.S4, V4.S4 + + MOVD $·asmConstants(SB), R3 + VLD1 (R3), [V5.S4, V6.S4, V7.S4, V8.S4] + VEOR V5.B16, V1.B16, V1.B16 + VEOR V6.B16, V2.B16, V2.B16 + VEOR V7.B16, V3.B16, V3.B16 + VEOR V8.B16, V4.B16, V4.B16 + + VST1.P [V1.D2, V2.D2, V3.D2, V4.D2], 64(R0) + VST1 [V5.D2, V6.D2, V7.D2, V8.D2], (R0) + RET + +TEXT ·updateArm64(SB), NOSPLIT, $0 MOVD state+0(FP), R0 MOVD msg_base+8(FP), R1 MOVD msg_len+16(FP), R2 // length of message @@ -36,81 +139,186 @@ TEXT ·updateArm64(SB), 7, $0 // v6 = mul1.lo // v7 = mul1.hi - // Load constants table pointer - MOVD $·constants(SB), R3 + // Load zipper merge constants table pointer + MOVD $·asmZipperMerge(SB), R3 - // and load constants into v28, v29, and v30 - WORD $0x4c40607c // ld1 {v28.16b-v30.16b}, [x3] + // and load zipper merge constants into v28, v29, and v30 + VLD1 (R3), [V28.B16, V29.B16, V30.B16] - WORD $0x4cdf2c00 // ld1 {v0.2d-v3.2d}, [x0], #64 - WORD $0x4c402c04 // ld1 {v4.2d-v7.2d}, [x0] - SUBS $64, R0 + VLD1.P 64(R0), [V0.D2, V1.D2, V2.D2, V3.D2] + VLD1 (R0), [V4.D2, V5.D2, V6.D2, V7.D2] + SUBS $64, R0 loop: // Main loop - WORD $0x4cdfa83a // ld1 {v26.4s-v27.4s}, [x1], #32 + VLD1.P 32(R1), [V26.S4, V27.S4] - // Add message - WORD $0x4efa8442 // add v2.2d, v2.2d, v26.2d - WORD $0x4efb8463 // add v3.2d, v3.2d, v27.2d + UPDATE(V26, V27) - // v1 += mul0 - WORD $0x4ee48442 // add v2.2d, v2.2d, v4.2d - WORD $0x4ee58463 // add v3.2d, v3.2d, v5.2d + SUBS $32, R2 + BPL loop - // First pair of multiplies - WORD $0x4e1d200a // tbl v10.16b,{v0.16b,v1.16b},v29.16b - WORD $0x4e1e204b // tbl v11.16b,{v2.16b,v3.16b},v30.16b - WORD $0x2eaac16c // umull v12.2d, v11.2s, v10.2s - WORD $0x6eaac16d // umull2 v13.2d, v11.4s, v10.4s + // Store result + VST1.P [V0.D2, V1.D2, V2.D2, V3.D2], 64(R0) + VST1 [V4.D2, V5.D2, V6.D2, V7.D2], (R0) - // v0 += mul1 - WORD $0x4ee68400 // add v0.2d, v0.2d, v6.2d - WORD $0x4ee78421 // add v1.2d, v1.2d, v7.2d +complete: + RET - // Second pair of multiplies - WORD $0x4e1d204f // tbl v15.16b,{v2.16b,v3.16b},v29.16b - WORD $0x4e1e200e // tbl v14.16b,{v0.16b,v1.16b},v30.16b +// func finalizeArm64(out []byte, state *[16]uint64) +TEXT ·finalizeArm64(SB), NOSPLIT, $0-32 + MOVD state+24(FP), R0 + MOVD out_base+0(FP), R1 + MOVD out_len+8(FP), R2 - // EOR multiplication result in - WORD $0x6e2c1c84 // eor v4.16b,v4.16b,v12.16b - WORD $0x6e2d1ca5 // eor v5.16b,v5.16b,v13.16b + // Load zipper merge constants table pointer + MOVD $·asmZipperMerge(SB), R3 - WORD $0x2eaec1f0 // umull v16.2d, v15.2s, v14.2s - WORD $0x6eaec1f1 // umull2 v17.2d, v15.4s, v14.4s + // and load zipper merge constants into v28, v29, and v30 + VLD1 (R3), [V28.B16, V29.B16, V30.B16] - // First pair of zipper-merges - WORD $0x4e1c0052 // tbl v18.16b,{v2.16b},v28.16b - WORD $0x4ef28400 // add v0.2d, v0.2d, v18.2d - WORD $0x4e1c0073 // tbl v19.16b,{v3.16b},v28.16b - WORD $0x4ef38421 // add v1.2d, v1.2d, v19.2d + VLD1.P 64(R0), [V0.D2, V1.D2, V2.D2, V3.D2] + VLD1 (R0), [V4.D2, V5.D2, V6.D2, V7.D2] + SUB $64, R0 - // Second pair of zipper-merges - WORD $0x4e1c0014 // tbl v20.16b,{v0.16b},v28.16b - WORD $0x4ef48442 // add v2.2d, v2.2d, v20.2d - WORD $0x4e1c0035 // tbl v21.16b,{v1.16b},v28.16b - WORD $0x4ef58463 // add v3.2d, v3.2d, v21.2d + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) - // EOR multiplication result in - WORD $0x6e301cc6 // eor v6.16b,v6.16b,v16.16b - WORD $0x6e311ce7 // eor v7.16b,v7.16b,v17.16b + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) - SUBS $32, R2 - BPL loop + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + + CMP $8, R2 + BEQ skipUpdate // Just 4 rounds for 64-bit checksum + + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + + CMP $16, R2 + BEQ skipUpdate // 6 rounds for 128-bit checksum + + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + + VREV64 V1.S4, V26.S4 + VREV64 V0.S4, V27.S4 + UPDATE(V26, V27) + +skipUpdate: // Store result - WORD $0x4c9f2c00 // st1 {v0.2d-v3.2d}, [x0], #64 - WORD $0x4c002c04 // st1 {v4.2d-v7.2d}, [x0] + VST1.P [V0.D2, V1.D2, V2.D2, V3.D2], 64(R0) + VST1 [V4.D2, V5.D2, V6.D2, V7.D2], (R0) + SUB $64, R0 -complete: + CMP $8, R2 + BEQ hash64 + CMP $16, R2 + BEQ hash128 + + // 256-bit checksum + MOVD 0*8(R0), R8 + MOVD 1*8(R0), R9 + MOVD 4*8(R0), R10 + MOVD 5*8(R0), R11 + MOVD 8*8(R0), R4 + MOVD 9*8(R0), R5 + MOVD 12*8(R0), R6 + MOVD 13*8(R0), R7 + ADD R4, R8 + ADD R5, R9 + ADD R6, R10 + ADD R7, R11 + + REDUCE_MOD(R8, R9, R10, R11, R4, R5, R6, R7) + MOVD R6, 0(R1) + MOVD R7, 8(R1) + + MOVD 2*8(R0), R8 + MOVD 3*8(R0), R9 + MOVD 6*8(R0), R10 + MOVD 7*8(R0), R11 + MOVD 10*8(R0), R4 + MOVD 11*8(R0), R5 + MOVD 14*8(R0), R6 + MOVD 15*8(R0), R7 + ADD R4, R8 + ADD R5, R9 + ADD R6, R10 + ADD R7, R11 + + REDUCE_MOD(R8, R9, R10, R11, R4, R5, R6, R7) + MOVD R6, 16(R1) + MOVD R7, 24(R1) RET +hash128: + MOVD 0*8(R0), R8 + MOVD 1*8(R0), R9 + MOVD 6*8(R0), R10 + MOVD 7*8(R0), R11 + ADD R10, R8 + ADD R11, R9 + MOVD 8*8(R0), R10 + MOVD 9*8(R0), R11 + ADD R10, R8 + ADD R11, R9 + MOVD 14*8(R0), R10 + MOVD 15*8(R0), R11 + ADD R10, R8 + ADD R11, R9 + MOVD R8, 0(R1) + MOVD R9, 8(R1) + RET + +hash64: + MOVD 0*8(R0), R4 + MOVD 4*8(R0), R5 + MOVD 8*8(R0), R6 + MOVD 12*8(R0), R7 + ADD R5, R4 + ADD R7, R6 + ADD R6, R4 + MOVD R4, (R1) + RET + +DATA ·asmConstants+0x00(SB)/8, $0xdbe6d5d5fe4cce2f +DATA ·asmConstants+0x08(SB)/8, $0xa4093822299f31d0 +DATA ·asmConstants+0x10(SB)/8, $0x13198a2e03707344 +DATA ·asmConstants+0x18(SB)/8, $0x243f6a8885a308d3 +DATA ·asmConstants+0x20(SB)/8, $0x3bd39e10cb0ef593 +DATA ·asmConstants+0x28(SB)/8, $0xc0acf169b5f18a8c +DATA ·asmConstants+0x30(SB)/8, $0xbe5466cf34e90c6c +DATA ·asmConstants+0x38(SB)/8, $0x452821e638d01377 +GLOBL ·asmConstants(SB), 8, $64 + // Constants for TBL instructions -DATA ·constants+0x0(SB)/8, $0x000f010e05020c03 // zipper merge constant -DATA ·constants+0x8(SB)/8, $0x070806090d0a040b -DATA ·constants+0x10(SB)/8, $0x0f0e0d0c07060504 // setup first register for multiply -DATA ·constants+0x18(SB)/8, $0x1f1e1d1c17161514 -DATA ·constants+0x20(SB)/8, $0x0b0a090803020100 // setup second register for multiply -DATA ·constants+0x28(SB)/8, $0x1b1a191813121110 - -GLOBL ·constants(SB), 8, $48 +DATA ·asmZipperMerge+0x0(SB)/8, $0x000f010e05020c03 // zipper merge constant +DATA ·asmZipperMerge+0x8(SB)/8, $0x070806090d0a040b +DATA ·asmZipperMerge+0x10(SB)/8, $0x0f0e0d0c07060504 // setup first register for multiply +DATA ·asmZipperMerge+0x18(SB)/8, $0x1f1e1d1c17161514 +DATA ·asmZipperMerge+0x20(SB)/8, $0x0b0a090803020100 // setup second register for multiply +DATA ·asmZipperMerge+0x28(SB)/8, $0x1b1a191813121110 +GLOBL ·asmZipperMerge(SB), 8, $48 diff --git a/vendor/github.com/minio/highwayhash/highwayhash_generic.go b/vendor/github.com/minio/highwayhash/highwayhash_generic.go index 3909e79..1f66e22 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_generic.go +++ b/vendor/github.com/minio/highwayhash/highwayhash_generic.go @@ -46,40 +46,113 @@ func initializeGeneric(state *[16]uint64, k []byte) { } func updateGeneric(state *[16]uint64, msg []byte) { - for len(msg) > 0 { - // add message - state[v1+0] += binary.LittleEndian.Uint64(msg) - state[v1+1] += binary.LittleEndian.Uint64(msg[8:]) - state[v1+2] += binary.LittleEndian.Uint64(msg[16:]) - state[v1+3] += binary.LittleEndian.Uint64(msg[24:]) - - // v1 += mul0 - state[v1+0] += state[mul0+0] - state[v1+1] += state[mul0+1] - state[v1+2] += state[mul0+2] - state[v1+3] += state[mul0+3] + for len(msg) >= 32 { + m := msg[:32] + // add message + mul0 + // Interleave operations to hide multiplication + state[v1+0] += binary.LittleEndian.Uint64(m) + state[mul0+0] state[mul0+0] ^= uint64(uint32(state[v1+0])) * (state[v0+0] >> 32) - state[mul0+1] ^= uint64(uint32(state[v1+1])) * (state[v0+1] >> 32) - state[mul0+2] ^= uint64(uint32(state[v1+2])) * (state[v0+2] >> 32) - state[mul0+3] ^= uint64(uint32(state[v1+3])) * (state[v0+3] >> 32) - - // v0 += mul1 state[v0+0] += state[mul1+0] - state[v0+1] += state[mul1+1] - state[v0+2] += state[mul1+2] - state[v0+3] += state[mul1+3] - state[mul1+0] ^= uint64(uint32(state[v0+0])) * (state[v1+0] >> 32) + + state[v1+1] += binary.LittleEndian.Uint64(m[8:]) + state[mul0+1] + state[mul0+1] ^= uint64(uint32(state[v1+1])) * (state[v0+1] >> 32) + state[v0+1] += state[mul1+1] state[mul1+1] ^= uint64(uint32(state[v0+1])) * (state[v1+1] >> 32) + + state[v1+2] += binary.LittleEndian.Uint64(m[16:]) + state[mul0+2] + state[mul0+2] ^= uint64(uint32(state[v1+2])) * (state[v0+2] >> 32) + state[v0+2] += state[mul1+2] state[mul1+2] ^= uint64(uint32(state[v0+2])) * (state[v1+2] >> 32) + + state[v1+3] += binary.LittleEndian.Uint64(m[24:]) + state[mul0+3] + state[mul0+3] ^= uint64(uint32(state[v1+3])) * (state[v0+3] >> 32) + state[v0+3] += state[mul1+3] state[mul1+3] ^= uint64(uint32(state[v0+3])) * (state[v1+3] >> 32) - zipperMerge(state[v1+0], state[v1+1], &state[v0+0], &state[v0+1]) - zipperMerge(state[v1+2], state[v1+3], &state[v0+2], &state[v0+3]) + // inlined: zipperMerge(state[v1+0], state[v1+1], &state[v0+0], &state[v0+1]) + { + val0 := state[v1+0] + val1 := state[v1+1] + res := val0 & (0xff << (2 * 8)) + res2 := (val0 & (0xff << (7 * 8))) + (val1 & (0xff << (2 * 8))) + res += (val1 & (0xff << (7 * 8))) >> 8 + res2 += (val0 & (0xff << (6 * 8))) >> 8 + res += ((val0 & (0xff << (5 * 8))) + (val1 & (0xff << (6 * 8)))) >> 16 + res2 += (val1 & (0xff << (5 * 8))) >> 16 + res += ((val0 & (0xff << (3 * 8))) + (val1 & (0xff << (4 * 8)))) >> 24 + res2 += ((val1 & (0xff << (3 * 8))) + (val0 & (0xff << (4 * 8)))) >> 24 + res += (val0 & (0xff << (1 * 8))) << 32 + res2 += (val1 & 0xff) << 48 + res += val0 << 56 + res2 += (val1 & (0xff << (1 * 8))) << 24 + + state[v0+0] += res + state[v0+1] += res2 + } + // zipperMerge(state[v1+2], state[v1+3], &state[v0+2], &state[v0+3]) + { + val0 := state[v1+2] + val1 := state[v1+3] + res := val0 & (0xff << (2 * 8)) + res2 := (val0 & (0xff << (7 * 8))) + (val1 & (0xff << (2 * 8))) + res += (val1 & (0xff << (7 * 8))) >> 8 + res2 += (val0 & (0xff << (6 * 8))) >> 8 + res += ((val0 & (0xff << (5 * 8))) + (val1 & (0xff << (6 * 8)))) >> 16 + res2 += (val1 & (0xff << (5 * 8))) >> 16 + res += ((val0 & (0xff << (3 * 8))) + (val1 & (0xff << (4 * 8)))) >> 24 + res2 += ((val1 & (0xff << (3 * 8))) + (val0 & (0xff << (4 * 8)))) >> 24 + res += (val0 & (0xff << (1 * 8))) << 32 + res2 += (val1 & 0xff) << 48 + res += val0 << 56 + res2 += (val1 & (0xff << (1 * 8))) << 24 + + state[v0+2] += res + state[v0+3] += res2 + } + + // inlined: zipperMerge(state[v0+0], state[v0+1], &state[v1+0], &state[v1+1]) + { + val0 := state[v0+0] + val1 := state[v0+1] + res := val0 & (0xff << (2 * 8)) + res2 := (val0 & (0xff << (7 * 8))) + (val1 & (0xff << (2 * 8))) + res += (val1 & (0xff << (7 * 8))) >> 8 + res2 += (val0 & (0xff << (6 * 8))) >> 8 + res += ((val0 & (0xff << (5 * 8))) + (val1 & (0xff << (6 * 8)))) >> 16 + res2 += (val1 & (0xff << (5 * 8))) >> 16 + res += ((val0 & (0xff << (3 * 8))) + (val1 & (0xff << (4 * 8)))) >> 24 + res2 += ((val1 & (0xff << (3 * 8))) + (val0 & (0xff << (4 * 8)))) >> 24 + res += (val0 & (0xff << (1 * 8))) << 32 + res2 += (val1 & 0xff) << 48 + res += val0 << 56 + res2 += (val1 & (0xff << (1 * 8))) << 24 + + state[v1+0] += res + state[v1+1] += res2 + } + + //inlined: zipperMerge(state[v0+2], state[v0+3], &state[v1+2], &state[v1+3]) + { + val0 := state[v0+2] + val1 := state[v0+3] + res := val0 & (0xff << (2 * 8)) + res2 := (val0 & (0xff << (7 * 8))) + (val1 & (0xff << (2 * 8))) + res += (val1 & (0xff << (7 * 8))) >> 8 + res2 += (val0 & (0xff << (6 * 8))) >> 8 + res += ((val0 & (0xff << (5 * 8))) + (val1 & (0xff << (6 * 8)))) >> 16 + res2 += (val1 & (0xff << (5 * 8))) >> 16 + res += ((val0 & (0xff << (3 * 8))) + (val1 & (0xff << (4 * 8)))) >> 24 + res2 += ((val1 & (0xff << (3 * 8))) + (val0 & (0xff << (4 * 8)))) >> 24 + res += (val0 & (0xff << (1 * 8))) << 32 + res2 += (val1 & 0xff) << 48 + res += val0 << 56 + res2 += (val1 & (0xff << (1 * 8))) << 24 - zipperMerge(state[v0+0], state[v0+1], &state[v1+0], &state[v1+1]) - zipperMerge(state[v0+2], state[v0+3], &state[v1+2], &state[v1+3]) + state[v1+2] += res + state[v1+3] += res2 + } msg = msg[32:] } } @@ -124,25 +197,129 @@ func finalizeGeneric(out []byte, state *[16]uint64) { } } +// Experiments on variations left for future reference... +/* func zipperMerge(v0, v1 uint64, d0, d1 *uint64) { - m0 := v0 & (0xFF << (2 * 8)) - m1 := (v1 & (0xFF << (7 * 8))) >> 8 - m2 := ((v0 & (0xFF << (5 * 8))) + (v1 & (0xFF << (6 * 8)))) >> 16 - m3 := ((v0 & (0xFF << (3 * 8))) + (v1 & (0xFF << (4 * 8)))) >> 24 - m4 := (v0 & (0xFF << (1 * 8))) << 32 - m5 := v0 << 56 - - *d0 += m0 + m1 + m2 + m3 + m4 + m5 - - m0 = (v0 & (0xFF << (7 * 8))) + (v1 & (0xFF << (2 * 8))) - m1 = (v0 & (0xFF << (6 * 8))) >> 8 - m2 = (v1 & (0xFF << (5 * 8))) >> 16 - m3 = ((v1 & (0xFF << (3 * 8))) + (v0 & (0xFF << (4 * 8)))) >> 24 - m4 = (v1 & 0xFF) << 48 - m5 = (v1 & (0xFF << (1 * 8))) << 24 - - *d1 += m3 + m2 + m5 + m1 + m4 + m0 + if true { + // fastest. original interleaved... + res := v0 & (0xff << (2 * 8)) + res2 := (v0 & (0xff << (7 * 8))) + (v1 & (0xff << (2 * 8))) + res += (v1 & (0xff << (7 * 8))) >> 8 + res2 += (v0 & (0xff << (6 * 8))) >> 8 + res += ((v0 & (0xff << (5 * 8))) + (v1 & (0xff << (6 * 8)))) >> 16 + res2 += (v1 & (0xff << (5 * 8))) >> 16 + res += ((v0 & (0xff << (3 * 8))) + (v1 & (0xff << (4 * 8)))) >> 24 + res2 += ((v1 & (0xff << (3 * 8))) + (v0 & (0xff << (4 * 8)))) >> 24 + res += (v0 & (0xff << (1 * 8))) << 32 + res2 += (v1 & 0xff) << 48 + res += v0 << 56 + res2 += (v1 & (0xff << (1 * 8))) << 24 + + *d0 += res + *d1 += res2 + } else if false { + // Reading bytes and combining into uint64 + var v0b [8]byte + binary.LittleEndian.PutUint64(v0b[:], v0) + var v1b [8]byte + binary.LittleEndian.PutUint64(v1b[:], v1) + var res, res2 uint64 + + res = uint64(v0b[0]) << (7 * 8) + res2 = uint64(v1b[0]) << (6 * 8) + res |= uint64(v0b[1]) << (5 * 8) + res2 |= uint64(v1b[1]) << (4 * 8) + res |= uint64(v0b[2]) << (2 * 8) + res2 |= uint64(v1b[2]) << (2 * 8) + res |= uint64(v0b[3]) + res2 |= uint64(v0b[4]) << (1 * 8) + res |= uint64(v0b[5]) << (3 * 8) + res2 |= uint64(v0b[6]) << (5 * 8) + res |= uint64(v1b[4]) << (1 * 8) + res2 |= uint64(v0b[7]) << (7 * 8) + res |= uint64(v1b[6]) << (4 * 8) + res2 |= uint64(v1b[3]) + res |= uint64(v1b[7]) << (6 * 8) + res2 |= uint64(v1b[5]) << (3 * 8) + + *d0 += res + *d1 += res2 + + } else if false { + // bytes to bytes shuffle + var v0b [8]byte + binary.LittleEndian.PutUint64(v0b[:], v0) + var v1b [8]byte + binary.LittleEndian.PutUint64(v1b[:], v1) + var res [8]byte + + //res += ((v0 & (0xff << (3 * 8))) + (v1 & (0xff << (4 * 8)))) >> 24 + res[0] = v0b[3] + res[1] = v1b[4] + + // res := v0 & (0xff << (2 * 8)) + res[2] = v0b[2] + + //res += ((v0 & (0xff << (5 * 8))) + (v1 & (0xff << (6 * 8)))) >> 16 + res[3] = v0b[5] + res[4] = v1b[6] + + //res += (v0 & (0xff << (1 * 8))) << 32 + res[5] = v0b[1] + + //res += (v1 & (0xff << (7 * 8))) >> 8 + res[6] += v1b[7] + + //res += v0 << 56 + res[7] = v0b[0] + v0 = binary.LittleEndian.Uint64(res[:]) + *d0 += v0 + + //res += ((v1 & (0xff << (3 * 8))) + (v0 & (0xff << (4 * 8)))) >> 24 + res[0] = v1b[3] + res[1] = v0b[4] + + res[2] = v1b[2] + + // res += (v1 & (0xff << (5 * 8))) >> 16 + res[3] = v1b[5] + + //res += (v1 & (0xff << (1 * 8))) << 24 + res[4] = v1b[1] + + // res += (v0 & (0xff << (6 * 8))) >> 8 + res[5] = v0b[6] + + //res := (v0 & (0xff << (7 * 8))) + (v1 & (0xff << (2 * 8))) + res[7] = v0b[7] + + //res += (v1 & 0xff) << 48 + res[6] = v1b[0] + + v0 = binary.LittleEndian.Uint64(res[:]) + *d1 += v0 + } else { + // original. + res := v0 & (0xff << (2 * 8)) + res += (v1 & (0xff << (7 * 8))) >> 8 + res += ((v0 & (0xff << (5 * 8))) + (v1 & (0xff << (6 * 8)))) >> 16 + res += ((v0 & (0xff << (3 * 8))) + (v1 & (0xff << (4 * 8)))) >> 24 + res += (v0 & (0xff << (1 * 8))) << 32 + res += v0 << 56 + + *d0 += res + + res = (v0 & (0xff << (7 * 8))) + (v1 & (0xff << (2 * 8))) + res += (v0 & (0xff << (6 * 8))) >> 8 + res += (v1 & (0xff << (5 * 8))) >> 16 + res += ((v1 & (0xff << (3 * 8))) + (v0 & (0xff << (4 * 8)))) >> 24 + res += (v1 & 0xff) << 48 + res += (v1 & (0xff << (1 * 8))) << 24 + + *d1 += res + } } +*/ // reduce v = [v0, v1, v2, v3] mod the irreducible polynomial x^128 + x^2 + x func reduceMod(v0, v1, v2, v3 uint64) (r0, r1 uint64) { diff --git a/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.go b/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.go index 9a8a125..cf9ee1a 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.go +++ b/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.go @@ -1,15 +1,18 @@ -//+build !noasm - // Copyright (c) 2017 Minio Inc. All rights reserved. // Use of this source code is governed by a license that can be // found in the LICENSE file. +//go:build !noasm && !appengine +// +build !noasm,!appengine + package highwayhash var ( useSSE4 = false useAVX2 = false useNEON = false + useSVE = false + useSVE2 = false useVMX = true ) diff --git a/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.s b/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.s index b65b626..c70ec8d 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.s +++ b/vendor/github.com/minio/highwayhash/highwayhash_ppc64le.s @@ -1,5 +1,3 @@ -//+build !noasm !appengine - // // Minio Cloud Storage, (C) 2018 Minio, Inc. // @@ -16,6 +14,8 @@ // limitations under the License. // +//+build !noasm,!appengine + #include "textflag.h" // Definition of registers @@ -108,8 +108,8 @@ TEXT ·updatePpc64Le(SB), NOFRAME|NOSPLIT, $0-32 XXPERMDI MUL1_LO, MUL1_LO, $2, MUL1_LO XXPERMDI MUL1_HI, MUL1_HI, $2, MUL1_HI - // Load constants table pointer - MOVD $·constants(SB), CONSTANTS + // Load asmConstants table pointer + MOVD $·asmConstants(SB), CONSTANTS LXVD2X (CONSTANTS)(R0), ROTATE LXVD2X (CONSTANTS)(P1), MASK XXLNAND MASK, MASK, MASK @@ -174,9 +174,9 @@ complete: RET // Constants table -DATA ·constants+0x0(SB)/8, $0x0000000000000020 -DATA ·constants+0x8(SB)/8, $0x0000000000000020 -DATA ·constants+0x10(SB)/8, $0x070806090d0a040b // zipper merge constant -DATA ·constants+0x18(SB)/8, $0x000f010e05020c03 // zipper merge constant +DATA ·asmConstants+0x0(SB)/8, $0x0000000000000020 +DATA ·asmConstants+0x8(SB)/8, $0x0000000000000020 +DATA ·asmConstants+0x10(SB)/8, $0x070806090d0a040b // zipper merge constant +DATA ·asmConstants+0x18(SB)/8, $0x000f010e05020c03 // zipper merge constant -GLOBL ·constants(SB), 8, $32 +GLOBL ·asmConstants(SB), 8, $32 diff --git a/vendor/github.com/minio/highwayhash/highwayhash_ref.go b/vendor/github.com/minio/highwayhash/highwayhash_ref.go index fddac4b..42cbbb4 100644 --- a/vendor/github.com/minio/highwayhash/highwayhash_ref.go +++ b/vendor/github.com/minio/highwayhash/highwayhash_ref.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a license that can be // found in the LICENSE file. -// +build !amd64 -// +build !arm64 -// +build !ppc64le +//go:build noasm || (!amd64 && !arm64 && !ppc64le) +// +build noasm !amd64,!arm64,!ppc64le package highwayhash @@ -12,6 +11,8 @@ var ( useSSE4 = false useAVX2 = false useNEON = false + useSVE = false + useSVE2 = false useVMX = false ) diff --git a/vendor/github.com/mitchellh/go-homedir/go.mod b/vendor/github.com/mitchellh/go-homedir/go.mod deleted file mode 100644 index 7efa09a..0000000 --- a/vendor/github.com/mitchellh/go-homedir/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/mitchellh/go-homedir diff --git a/vendor/github.com/nats-io/jwt/go.mod b/vendor/github.com/nats-io/jwt/go.mod deleted file mode 100644 index eebea6c..0000000 --- a/vendor/github.com/nats-io/jwt/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/nats-io/jwt - -require github.com/nats-io/nkeys v0.1.4 - -go 1.13 diff --git a/vendor/github.com/nats-io/jwt/go.sum b/vendor/github.com/nats-io/jwt/go.sum deleted file mode 100644 index 5e6e47e..0000000 --- a/vendor/github.com/nats-io/jwt/go.sum +++ /dev/null @@ -1,9 +0,0 @@ -github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA= -github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/nats-io/jwt/v2/Makefile b/vendor/github.com/nats-io/jwt/v2/Makefile index 53585ce..108c1a4 100644 --- a/vendor/github.com/nats-io/jwt/v2/Makefile +++ b/vendor/github.com/nats-io/jwt/v2/Makefile @@ -15,4 +15,4 @@ test: go test -v -coverprofile=./coverage.out ./... cover: - go tool cover -html=coverage.out + go tool cover -html=coverage.out \ No newline at end of file diff --git a/vendor/github.com/nats-io/jwt/v2/account_claims.go b/vendor/github.com/nats-io/jwt/v2/account_claims.go index 4105dd7..9da374a 100644 --- a/vendor/github.com/nats-io/jwt/v2/account_claims.go +++ b/vendor/github.com/nats-io/jwt/v2/account_claims.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -17,6 +17,7 @@ package jwt import ( "errors" + "fmt" "sort" "time" @@ -24,19 +25,23 @@ import ( ) // NoLimit is used to indicate a limit field is unlimited in value. -const NoLimit = -1 +const ( + NoLimit = -1 + AnyAccount = "*" +) type AccountLimits struct { - Imports int64 `json:"imports,omitempty"` // Max number of imports - Exports int64 `json:"exports,omitempty"` // Max number of exports - WildcardExports bool `json:"wildcards,omitempty"` // Are wildcards allowed in exports - Conn int64 `json:"conn,omitempty"` // Max number of active connections - LeafNodeConn int64 `json:"leaf,omitempty"` // Max number of active leaf node connections + Imports int64 `json:"imports,omitempty"` // Max number of imports + Exports int64 `json:"exports,omitempty"` // Max number of exports + WildcardExports bool `json:"wildcards,omitempty"` // Are wildcards allowed in exports + DisallowBearer bool `json:"disallow_bearer,omitempty"` // User JWT can't be bearer token + Conn int64 `json:"conn,omitempty"` // Max number of active connections + LeafNodeConn int64 `json:"leaf,omitempty"` // Max number of active leaf node connections } // IsUnlimited returns true if all limits are unlimited func (a *AccountLimits) IsUnlimited() bool { - return *a == AccountLimits{NoLimit, NoLimit, true, NoLimit, NoLimit} + return *a == AccountLimits{NoLimit, NoLimit, true, false, NoLimit, NoLimit} } type NatsLimits struct { @@ -51,56 +56,247 @@ func (n *NatsLimits) IsUnlimited() bool { } type JetStreamLimits struct { - MemoryStorage int64 `json:"mem_storage,omitempty"` // Max number of bytes stored in memory across all streams. (0 means disabled) - DiskStorage int64 `json:"disk_storage,omitempty"` // Max number of bytes stored on disk across all streams. (0 means disabled) - Streams int64 `json:"streams,omitempty"` // Max number of streams - Consumer int64 `json:"consumer,omitempty"` // Max number of consumer + MemoryStorage int64 `json:"mem_storage,omitempty"` // Max number of bytes stored in memory across all streams. (0 means disabled) + DiskStorage int64 `json:"disk_storage,omitempty"` // Max number of bytes stored on disk across all streams. (0 means disabled) + Streams int64 `json:"streams,omitempty"` // Max number of streams + Consumer int64 `json:"consumer,omitempty"` // Max number of consumers + MaxAckPending int64 `json:"max_ack_pending,omitempty"` // Max ack pending of a Stream + MemoryMaxStreamBytes int64 `json:"mem_max_stream_bytes,omitempty"` // Max bytes a memory backed stream can have. (0 means disabled/unlimited) + DiskMaxStreamBytes int64 `json:"disk_max_stream_bytes,omitempty"` // Max bytes a disk backed stream can have. (0 means disabled/unlimited) + MaxBytesRequired bool `json:"max_bytes_required,omitempty"` // Max bytes required by all Streams } // IsUnlimited returns true if all limits are unlimited func (j *JetStreamLimits) IsUnlimited() bool { - return *j == JetStreamLimits{NoLimit, NoLimit, NoLimit, NoLimit} + lim := *j + // workaround in case NoLimit was used instead of 0 + if lim.MemoryMaxStreamBytes < 0 { + lim.MemoryMaxStreamBytes = 0 + } + if lim.DiskMaxStreamBytes < 0 { + lim.DiskMaxStreamBytes = 0 + } + if lim.MaxAckPending < 0 { + lim.MaxAckPending = 0 + } + return lim == JetStreamLimits{NoLimit, NoLimit, NoLimit, NoLimit, 0, 0, 0, false} } +type JetStreamTieredLimits map[string]JetStreamLimits + // OperatorLimits are used to limit access by an account type OperatorLimits struct { NatsLimits AccountLimits JetStreamLimits + JetStreamTieredLimits `json:"tiered_limits,omitempty"` +} + +// IsJSEnabled returns if this account claim has JS enabled either through a tier or the non tiered limits. +func (o *OperatorLimits) IsJSEnabled() bool { + if len(o.JetStreamTieredLimits) > 0 { + for _, l := range o.JetStreamTieredLimits { + if l.MemoryStorage != 0 || l.DiskStorage != 0 { + return true + } + } + return false + } + l := o.JetStreamLimits + return l.MemoryStorage != 0 || l.DiskStorage != 0 } -// IsEmpty returns true if all of the limits are 0/false. +// IsEmpty returns true if all limits are 0/false/empty. func (o *OperatorLimits) IsEmpty() bool { - return *o == OperatorLimits{} + return o.NatsLimits == NatsLimits{} && + o.AccountLimits == AccountLimits{} && + o.JetStreamLimits == JetStreamLimits{} && + len(o.JetStreamTieredLimits) == 0 } // IsUnlimited returns true if all limits are unlimited func (o *OperatorLimits) IsUnlimited() bool { - return o.AccountLimits.IsUnlimited() && o.NatsLimits.IsUnlimited() && o.JetStreamLimits.IsUnlimited() + return o.AccountLimits.IsUnlimited() && o.NatsLimits.IsUnlimited() && + o.JetStreamLimits.IsUnlimited() && len(o.JetStreamTieredLimits) == 0 } // Validate checks that the operator limits contain valid values -func (o *OperatorLimits) Validate(_ *ValidationResults) { +func (o *OperatorLimits) Validate(vr *ValidationResults) { // negative values mean unlimited, so all numbers are valid + if len(o.JetStreamTieredLimits) > 0 { + if (o.JetStreamLimits != JetStreamLimits{}) { + vr.AddError("JetStream Limits and tiered JetStream Limits are mutually exclusive") + } + if _, ok := o.JetStreamTieredLimits[""]; ok { + vr.AddError(`Tiered JetStream Limits can not contain a blank "" tier name`) + } + } +} + +// WeightedMapping for publishes +type WeightedMapping struct { + Subject Subject `json:"subject"` + Weight uint8 `json:"weight,omitempty"` + Cluster string `json:"cluster,omitempty"` +} + +func (m *WeightedMapping) GetWeight() uint8 { + if m.Weight == 0 { + return 100 + } + return m.Weight +} + +type Mapping map[Subject][]WeightedMapping + +func (m *Mapping) Validate(vr *ValidationResults) { + for ubFrom, wm := range (map[Subject][]WeightedMapping)(*m) { + ubFrom.Validate(vr) + perCluster := make(map[string]uint8) + total := uint8(0) + for _, e := range wm { + e.Subject.Validate(vr) + if e.Cluster != "" { + t := perCluster[e.Cluster] + t += e.Weight + perCluster[e.Cluster] = t + if t > 100 { + vr.AddError("Mapping %q in cluster %q exceeds 100%% among all of it's weighted to mappings", ubFrom, e.Cluster) + } + } else { + total += e.GetWeight() + } + } + if total > 100 { + vr.AddError("Mapping %q exceeds 100%% among all of it's weighted to mappings", ubFrom) + } + } +} + +func (a *Account) AddMapping(sub Subject, to ...WeightedMapping) { + a.Mappings[sub] = to +} + +// ExternalAuthorization enables external authorization for account users. +// AuthUsers are those users specified to bypass the authorization callout and should be used for the authorization service itself. +// AllowedAccounts specifies which accounts, if any, that the authorization service can bind an authorized user to. +// The authorization response, a user JWT, will still need to be signed by the correct account. +// If optional XKey is specified, that is the public xkey (x25519) and the server will encrypt the request such that only the +// holder of the private key can decrypt. The auth service can also optionally encrypt the response back to the server using it's +// public xkey which will be in the authorization request. +type ExternalAuthorization struct { + AuthUsers StringList `json:"auth_users,omitempty"` + AllowedAccounts StringList `json:"allowed_accounts,omitempty"` + XKey string `json:"xkey,omitempty"` +} + +func (ac *ExternalAuthorization) IsEnabled() bool { + return len(ac.AuthUsers) > 0 +} + +// HasExternalAuthorization helper function to determine if external authorization is enabled. +func (a *Account) HasExternalAuthorization() bool { + return a.Authorization.IsEnabled() +} + +// EnableExternalAuthorization helper function to setup external authorization. +func (a *Account) EnableExternalAuthorization(users ...string) { + a.Authorization.AuthUsers.Add(users...) +} + +func (ac *ExternalAuthorization) Validate(vr *ValidationResults) { + if len(ac.AllowedAccounts) > 0 && len(ac.AuthUsers) == 0 { + vr.AddError("External authorization cannot have accounts without users specified") + } + // Make sure users are all valid user nkeys. + // Make sure allowed accounts are all valid account nkeys. + for _, u := range ac.AuthUsers { + if !nkeys.IsValidPublicUserKey(u) { + vr.AddError("AuthUser %q is not a valid user public key", u) + } + } + for _, a := range ac.AllowedAccounts { + if a == AnyAccount && len(ac.AllowedAccounts) > 1 { + vr.AddError("AllowedAccounts can only be a list of accounts or %q", AnyAccount) + continue + } else if a == AnyAccount { + continue + } else if !nkeys.IsValidPublicAccountKey(a) { + vr.AddError("Account %q is not a valid account public key", a) + } + } + if ac.XKey != "" && !nkeys.IsValidPublicCurveKey(ac.XKey) { + vr.AddError("XKey %q is not a valid public xkey", ac.XKey) + } +} + +const ( + ClusterTrafficSystem = "system" + ClusterTrafficOwner = "owner" +) + +type ClusterTraffic string + +func (ct ClusterTraffic) Valid() error { + if ct == "" || ct == ClusterTrafficSystem || ct == ClusterTrafficOwner { + return nil + } + return fmt.Errorf("unknown cluster traffic option: %q", ct) } // Account holds account specific claims data type Account struct { - Imports Imports `json:"imports,omitempty"` - Exports Exports `json:"exports,omitempty"` - Limits OperatorLimits `json:"limits,omitempty"` - SigningKeys StringList `json:"signing_keys,omitempty"` - Revocations RevocationList `json:"revocations,omitempty"` - DefaultPermissions Permissions `json:"default_permissions,omitempty"` + Imports Imports `json:"imports,omitempty"` + Exports Exports `json:"exports,omitempty"` + Limits OperatorLimits `json:"limits,omitempty"` + SigningKeys SigningKeys `json:"signing_keys,omitempty"` + Revocations RevocationList `json:"revocations,omitempty"` + DefaultPermissions Permissions `json:"default_permissions,omitempty"` + Mappings Mapping `json:"mappings,omitempty"` + Authorization ExternalAuthorization `json:"authorization,omitempty"` + Trace *MsgTrace `json:"trace,omitempty"` + ClusterTraffic ClusterTraffic `json:"cluster_traffic,omitempty"` + Info GenericFields } +// MsgTrace holds distributed message tracing configuration +type MsgTrace struct { + // Destination is the subject the server will send message traces to + // if the inbound message contains the "traceparent" header and has + // its sampled field indicating that the trace should be triggered. + Destination Subject `json:"dest,omitempty"` + // Sampling is used to set the probability sampling, that is, the + // server will get a random number between 1 and 100 and trigger + // the trace if the number is lower than this Sampling value. + // The valid range is [1..100]. If the value is not set Validate() + // will set the value to 100. + Sampling int `json:"sampling,omitempty"` +} + // Validate checks if the account is valid, based on the wrapper func (a *Account) Validate(acct *AccountClaims, vr *ValidationResults) { a.Imports.Validate(acct.Subject, vr) a.Exports.Validate(vr) a.Limits.Validate(vr) a.DefaultPermissions.Validate(vr) + a.Mappings.Validate(vr) + a.Authorization.Validate(vr) + if a.Trace != nil { + tvr := CreateValidationResults() + a.Trace.Destination.Validate(tvr) + if !tvr.IsEmpty() { + vr.AddError(fmt.Sprintf("the account Trace.Destination %s", tvr.Issues[0].Description)) + } + if a.Trace.Destination.HasWildCards() { + vr.AddError("the account Trace.Destination subject %q is not a valid publish subject", a.Trace.Destination) + } + if a.Trace.Sampling < 0 || a.Trace.Sampling > 100 { + vr.AddError("the account Trace.Sampling value '%d' is not valid, should be in the range [1..100]", a.Trace.Sampling) + } else if a.Trace.Sampling == 0 { + a.Trace.Sampling = 100 + } + } if !a.Limits.IsEmpty() && a.Limits.Imports >= 0 && int64(len(a.Imports)) > a.Limits.Imports { vr.AddError("the account contains more imports than allowed by the operator") @@ -125,11 +321,11 @@ func (a *Account) Validate(acct *AccountClaims, vr *ValidationResults) { } } } + a.SigningKeys.Validate(vr) + a.Info.Validate(vr) - for _, k := range a.SigningKeys { - if !nkeys.IsValidPublicAccountKey(k) { - vr.AddError("%s is not an account public key", k) - } + if err := a.ClusterTraffic.Valid(); err != nil { + vr.AddError(err.Error()) } } @@ -145,25 +341,33 @@ func NewAccountClaims(subject string) *AccountClaims { return nil } c := &AccountClaims{} + c.SigningKeys = make(SigningKeys) // Set to unlimited to start. We do it this way so we get compiler // errors if we add to the OperatorLimits. c.Limits = OperatorLimits{ NatsLimits{NoLimit, NoLimit, NoLimit}, - AccountLimits{NoLimit, NoLimit, true, NoLimit, NoLimit}, - JetStreamLimits{NoLimit, NoLimit, NoLimit, NoLimit}} + AccountLimits{NoLimit, NoLimit, true, false, NoLimit, NoLimit}, + JetStreamLimits{0, 0, 0, 0, 0, 0, 0, false}, + JetStreamTieredLimits{}, + } c.Subject = subject + c.Mappings = Mapping{} return c } // Encode converts account claims into a JWT string func (a *AccountClaims) Encode(pair nkeys.KeyPair) (string, error) { + return a.EncodeWithSigner(pair, nil) +} + +func (a *AccountClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { if !nkeys.IsValidPublicAccountKey(a.Subject) { return "", errors.New("expected subject to be account public key") } sort.Sort(a.Exports) sort.Sort(a.Imports) a.Type = AccountClaim - return a.ClaimsData.encode(pair, a) + return a.ClaimsData.encode(pair, a, fn) } // DecodeAccountClaims decodes account claims from a JWT string @@ -217,15 +421,25 @@ func (a *AccountClaims) ExpectedPrefixes() []nkeys.PrefixByte { func (a *AccountClaims) Claims() *ClaimsData { return &a.ClaimsData } +func (a *AccountClaims) GetTags() TagList { + return a.Account.Tags +} // DidSign checks the claims against the account's public key and its signing keys -func (a *AccountClaims) DidSign(op Claims) bool { - if op != nil { - issuer := op.Claims().Issuer +func (a *AccountClaims) DidSign(c Claims) bool { + if c != nil { + issuer := c.Claims().Issuer if issuer == a.Subject { return true } - return a.SigningKeys.Contains(issuer) + uc, ok := c.(*UserClaims) + if ok && uc.IssuerAccount == a.Subject { + return a.SigningKeys.Contains(issuer) + } + at, ok := c.(*ActivationClaims) + if ok && at.IssuerAccount == a.Subject { + return a.SigningKeys.Contains(issuer) + } } return false } @@ -238,11 +452,11 @@ func (a *AccountClaims) Revoke(pubKey string) { // RevokeAt enters a revocation by public key and timestamp into this account // This will revoke all jwt issued for pubKey, prior to timestamp // If there is already a revocation for this public key that is newer, it is kept. +// The value is expected to be a public key or "*" (means all public keys) func (a *AccountClaims) RevokeAt(pubKey string, timestamp time.Time) { if a.Revocations == nil { a.Revocations = RevocationList{} } - a.Revocations.Revoke(pubKey, timestamp) } diff --git a/vendor/github.com/nats-io/jwt/v2/activation_claims.go b/vendor/github.com/nats-io/jwt/v2/activation_claims.go index 3ba8c4c..63fe788 100644 --- a/vendor/github.com/nats-io/jwt/v2/activation_claims.go +++ b/vendor/github.com/nats-io/jwt/v2/activation_claims.go @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -48,13 +48,7 @@ func (a *Activation) IsStream() bool { // Validate checks the exports and limits in an activation JWT func (a *Activation) Validate(vr *ValidationResults) { if !a.IsService() && !a.IsStream() { - vr.AddError("invalid export type: %q", a.ImportType) - } - - if a.IsService() { - if a.ImportSubject.HasWildCards() { - vr.AddError("services cannot have wildcard subject: %q", a.ImportSubject) - } + vr.AddError("invalid import type: %q", a.ImportType) } a.ImportSubject.Validate(vr) @@ -78,11 +72,15 @@ func NewActivationClaims(subject string) *ActivationClaims { // Encode turns an activation claim into a JWT strimg func (a *ActivationClaims) Encode(pair nkeys.KeyPair) (string, error) { + return a.EncodeWithSigner(pair, nil) +} + +func (a *ActivationClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { if !nkeys.IsValidPublicAccountKey(a.ClaimsData.Subject) { return "", errors.New("expected subject to be an account") } a.Type = ActivationClaim - return a.ClaimsData.encode(pair, a) + return a.ClaimsData.encode(pair, a, fn) } // DecodeActivationClaims tries to create an activation claim from a JWT string @@ -105,7 +103,14 @@ func (a *ActivationClaims) Payload() interface{} { // Validate checks the claims func (a *ActivationClaims) Validate(vr *ValidationResults) { - a.ClaimsData.Validate(vr) + a.validateWithTimeChecks(vr, true) +} + +// Validate checks the claims +func (a *ActivationClaims) validateWithTimeChecks(vr *ValidationResults, timeChecks bool) { + if timeChecks { + a.ClaimsData.Validate(vr) + } a.Activation.Validate(vr) if a.IssuerAccount != "" && !nkeys.IsValidPublicAccountKey(a.IssuerAccount) { vr.AddError("account_id is not an account public key") diff --git a/vendor/github.com/nats-io/jwt/v2/authorization_claims.go b/vendor/github.com/nats-io/jwt/v2/authorization_claims.go new file mode 100644 index 0000000..3448f11 --- /dev/null +++ b/vendor/github.com/nats-io/jwt/v2/authorization_claims.go @@ -0,0 +1,255 @@ +/* + * Copyright 2022-2024 The NATS Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jwt + +import ( + "errors" + + "github.com/nats-io/nkeys" +) + +// ServerID is basic static info for a NATS server. +type ServerID struct { + Name string `json:"name"` + Host string `json:"host"` + ID string `json:"id"` + Version string `json:"version,omitempty"` + Cluster string `json:"cluster,omitempty"` + Tags TagList `json:"tags,omitempty"` + XKey string `json:"xkey,omitempty"` +} + +// ClientInformation is information about a client that is trying to authorize. +type ClientInformation struct { + Host string `json:"host,omitempty"` + ID uint64 `json:"id,omitempty"` + User string `json:"user,omitempty"` + Name string `json:"name,omitempty"` + Tags TagList `json:"tags,omitempty"` + NameTag string `json:"name_tag,omitempty"` + Kind string `json:"kind,omitempty"` + Type string `json:"type,omitempty"` + MQTT string `json:"mqtt_id,omitempty"` + Nonce string `json:"nonce,omitempty"` +} + +// ConnectOptions represents options that were set in the CONNECT protocol from the client +// during authorization. +type ConnectOptions struct { + JWT string `json:"jwt,omitempty"` + Nkey string `json:"nkey,omitempty"` + SignedNonce string `json:"sig,omitempty"` + Token string `json:"auth_token,omitempty"` + Username string `json:"user,omitempty"` + Password string `json:"pass,omitempty"` + Name string `json:"name,omitempty"` + Lang string `json:"lang,omitempty"` + Version string `json:"version,omitempty"` + Protocol int `json:"protocol"` +} + +// ClientTLS is information about TLS state if present, including client certs. +// If the client certs were present and verified they will be under verified chains +// with the client peer cert being VerifiedChains[0]. These are complete and pem encoded. +// If they were not verified, they will be under certs. +type ClientTLS struct { + Version string `json:"version,omitempty"` + Cipher string `json:"cipher,omitempty"` + Certs StringList `json:"certs,omitempty"` + VerifiedChains []StringList `json:"verified_chains,omitempty"` +} + +// AuthorizationRequest represents all the information we know about the client that +// will be sent to an external authorization service. +type AuthorizationRequest struct { + Server ServerID `json:"server_id"` + UserNkey string `json:"user_nkey"` + ClientInformation ClientInformation `json:"client_info"` + ConnectOptions ConnectOptions `json:"connect_opts"` + TLS *ClientTLS `json:"client_tls,omitempty"` + RequestNonce string `json:"request_nonce,omitempty"` + GenericFields +} + +// AuthorizationRequestClaims defines an external auth request JWT. +// These wil be signed by a NATS server. +type AuthorizationRequestClaims struct { + ClaimsData + AuthorizationRequest `json:"nats"` +} + +// NewAuthorizationRequestClaims creates an auth request JWT with the specific subject/public key. +func NewAuthorizationRequestClaims(subject string) *AuthorizationRequestClaims { + if subject == "" { + return nil + } + var ac AuthorizationRequestClaims + ac.Subject = subject + return &ac +} + +// Validate checks the generic and specific parts of the auth request jwt. +func (ac *AuthorizationRequestClaims) Validate(vr *ValidationResults) { + if ac.UserNkey == "" { + vr.AddError("User nkey is required") + } else if !nkeys.IsValidPublicUserKey(ac.UserNkey) { + vr.AddError("User nkey %q is not a valid user public key", ac.UserNkey) + } + ac.ClaimsData.Validate(vr) +} + +// Encode tries to turn the auth request claims into a JWT string. +func (ac *AuthorizationRequestClaims) Encode(pair nkeys.KeyPair) (string, error) { + return ac.EncodeWithSigner(pair, nil) +} + +func (ac *AuthorizationRequestClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { + ac.Type = AuthorizationRequestClaim + return ac.ClaimsData.encode(pair, ac, fn) +} + +// DecodeAuthorizationRequestClaims tries to parse an auth request claims from a JWT string +func DecodeAuthorizationRequestClaims(token string) (*AuthorizationRequestClaims, error) { + claims, err := Decode(token) + if err != nil { + return nil, err + } + ac, ok := claims.(*AuthorizationRequestClaims) + if !ok { + return nil, errors.New("not an authorization request claim") + } + return ac, nil +} + +// ExpectedPrefixes defines the types that can encode an auth request jwt, servers. +func (ac *AuthorizationRequestClaims) ExpectedPrefixes() []nkeys.PrefixByte { + return []nkeys.PrefixByte{nkeys.PrefixByteServer} +} + +func (ac *AuthorizationRequestClaims) ClaimType() ClaimType { + return ac.Type +} + +// Claims returns the request claims data. +func (ac *AuthorizationRequestClaims) Claims() *ClaimsData { + return &ac.ClaimsData +} + +// Payload pulls the request specific payload out of the claims. +func (ac *AuthorizationRequestClaims) Payload() interface{} { + return &ac.AuthorizationRequest +} + +func (ac *AuthorizationRequestClaims) String() string { + return ac.ClaimsData.String(ac) +} + +func (ac *AuthorizationRequestClaims) updateVersion() { + ac.GenericFields.Version = libVersion +} + +type AuthorizationResponse struct { + Jwt string `json:"jwt,omitempty"` + Error string `json:"error,omitempty"` + // IssuerAccount stores the public key for the account the issuer represents. + // When set, the claim was issued by a signing key. + IssuerAccount string `json:"issuer_account,omitempty"` + GenericFields +} + +type AuthorizationResponseClaims struct { + ClaimsData + AuthorizationResponse `json:"nats"` +} + +func NewAuthorizationResponseClaims(subject string) *AuthorizationResponseClaims { + if subject == "" { + return nil + } + var ac AuthorizationResponseClaims + ac.Subject = subject + return &ac +} + +// DecodeAuthorizationResponseClaims tries to parse an auth request claims from a JWT string +func DecodeAuthorizationResponseClaims(token string) (*AuthorizationResponseClaims, error) { + claims, err := Decode(token) + if err != nil { + return nil, err + } + ac, ok := claims.(*AuthorizationResponseClaims) + if !ok { + return nil, errors.New("not an authorization request claim") + } + return ac, nil +} + +// ExpectedPrefixes defines the types that can encode an auth request jwt, servers. +func (ar *AuthorizationResponseClaims) ExpectedPrefixes() []nkeys.PrefixByte { + return []nkeys.PrefixByte{nkeys.PrefixByteAccount} +} + +func (ar *AuthorizationResponseClaims) ClaimType() ClaimType { + return ar.Type +} + +// Claims returns the request claims data. +func (ar *AuthorizationResponseClaims) Claims() *ClaimsData { + return &ar.ClaimsData +} + +// Payload pulls the request specific payload out of the claims. +func (ar *AuthorizationResponseClaims) Payload() interface{} { + return &ar.AuthorizationResponse +} + +func (ar *AuthorizationResponseClaims) String() string { + return ar.ClaimsData.String(ar) +} + +func (ar *AuthorizationResponseClaims) updateVersion() { + ar.GenericFields.Version = libVersion +} + +// Validate checks the generic and specific parts of the auth request jwt. +func (ar *AuthorizationResponseClaims) Validate(vr *ValidationResults) { + if !nkeys.IsValidPublicUserKey(ar.Subject) { + vr.AddError("Subject must be a user public key") + } + if !nkeys.IsValidPublicServerKey(ar.Audience) { + vr.AddError("Audience must be a server public key") + } + if ar.Error == "" && ar.Jwt == "" { + vr.AddError("Error or Jwt is required") + } + if ar.Error != "" && ar.Jwt != "" { + vr.AddError("Only Error or Jwt can be set") + } + if ar.IssuerAccount != "" && !nkeys.IsValidPublicAccountKey(ar.IssuerAccount) { + vr.AddError("issuer_account is not an account public key") + } + ar.ClaimsData.Validate(vr) +} + +// Encode tries to turn the auth request claims into a JWT string. +func (ar *AuthorizationResponseClaims) Encode(pair nkeys.KeyPair) (string, error) { + return ar.EncodeWithSigner(pair, nil) +} + +func (ar *AuthorizationResponseClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { + ar.Type = AuthorizationResponseClaim + return ar.ClaimsData.encode(pair, ar, fn) +} diff --git a/vendor/github.com/nats-io/jwt/v2/claims.go b/vendor/github.com/nats-io/jwt/v2/claims.go index b6d9111..9b816c3 100644 --- a/vendor/github.com/nats-io/jwt/v2/claims.go +++ b/vendor/github.com/nats-io/jwt/v2/claims.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -31,20 +31,53 @@ import ( type ClaimType string const ( - //OperatorClaim is the type of an operator JWT + // OperatorClaim is the type of an operator JWT OperatorClaim = "operator" // AccountClaim is the type of an Account JWT AccountClaim = "account" - //UserClaim is the type of an user JWT + // UserClaim is the type of an user JWT UserClaim = "user" - //ActivationClaim is the type of an activation JWT + // ActivationClaim is the type of an activation JWT ActivationClaim = "activation" + // AuthorizationRequestClaim is the type of an auth request claim JWT + AuthorizationRequestClaim = "authorization_request" + // AuthorizationResponseClaim is the response for an auth request + AuthorizationResponseClaim = "authorization_response" + // GenericClaim is a type that doesn't match Operator/Account/User/ActionClaim + GenericClaim = "generic" ) +func IsGenericClaimType(s string) bool { + switch s { + case OperatorClaim: + fallthrough + case AccountClaim: + fallthrough + case UserClaim: + fallthrough + case AuthorizationRequestClaim: + fallthrough + case AuthorizationResponseClaim: + fallthrough + case ActivationClaim: + return false + case GenericClaim: + return true + default: + return true + } +} + +// SignFn is used in an external sign environment. The function should be +// able to locate the private key for the specified pub key specified and sign the +// specified data returning the signature as generated. +type SignFn func(pub string, data []byte) ([]byte, error) + // Claims is a JWT claims type Claims interface { Claims() *ClaimsData Encode(kp nkeys.KeyPair) (string, error) + EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) ExpectedPrefixes() []nkeys.PrefixByte Payload() interface{} String() string @@ -94,7 +127,7 @@ func serialize(v interface{}) (string, error) { return encodeToString(j), nil } -func (c *ClaimsData) doEncode(header *Header, kp nkeys.KeyPair, claim Claims) (string, error) { +func (c *ClaimsData) doEncode(header *Header, kp nkeys.KeyPair, claim Claims, fn SignFn) (string, error) { if header == nil { return "", errors.New("header is required") } @@ -173,9 +206,21 @@ func (c *ClaimsData) doEncode(header *Header, kp nkeys.KeyPair, claim Claims) (s if header.Algorithm == AlgorithmNkeyOld { return "", errors.New(AlgorithmNkeyOld + " not supported to write jwtV2") } else if header.Algorithm == AlgorithmNkey { - sig, err := kp.Sign([]byte(toSign)) - if err != nil { - return "", err + var sig []byte + if fn != nil { + pk, err := kp.PublicKey() + if err != nil { + return "", err + } + sig, err = fn(pk, []byte(toSign)) + if err != nil { + return "", err + } + } else { + sig, err = kp.Sign([]byte(toSign)) + if err != nil { + return "", err + } } eSig = encodeToString(sig) } else { @@ -197,8 +242,8 @@ func (c *ClaimsData) hash() (string, error) { // Encode encodes a claim into a JWT token. The claim is signed with the // provided nkey's private key -func (c *ClaimsData) encode(kp nkeys.KeyPair, payload Claims) (string, error) { - return c.doEncode(&Header{TokenTypeJwt, AlgorithmNkey}, kp, payload) +func (c *ClaimsData) encode(kp nkeys.KeyPair, payload Claims, fn SignFn) (string, error) { + return c.doEncode(&Header{TokenTypeJwt, AlgorithmNkey}, kp, payload, fn) } // Returns a JSON representation of the claim diff --git a/vendor/github.com/nats-io/jwt/v2/creds_utils.go b/vendor/github.com/nats-io/jwt/v2/creds_utils.go index 93ba6d1..eade49d 100644 --- a/vendor/github.com/nats-io/jwt/v2/creds_utils.go +++ b/vendor/github.com/nats-io/jwt/v2/creds_utils.go @@ -21,6 +21,7 @@ import ( "fmt" "regexp" "strings" + "time" "github.com/nats-io/nkeys" ) @@ -51,13 +52,14 @@ func formatJwt(kind string, jwtString string) ([]byte, error) { // DecorateSeed takes a seed and returns a string that wraps // the seed in the form: -// ************************* IMPORTANT ************************* -// NKEY Seed printed below can be used sign and prove identity. -// NKEYs are sensitive and should be treated as secrets. // -// -----BEGIN USER NKEY SEED----- -// SUAIO3FHUX5PNV2LQIIP7TZ3N4L7TX3W53MQGEIVYFIGA635OZCKEYHFLM -// ------END USER NKEY SEED------ +// ************************* IMPORTANT ************************* +// NKEY Seed printed below can be used sign and prove identity. +// NKEYs are sensitive and should be treated as secrets. +// +// -----BEGIN USER NKEY SEED----- +// SUAIO3FHUX5PNV2LQIIP7TZ3N4L7TX3W53MQGEIVYFIGA635OZCKEYHFLM +// ------END USER NKEY SEED------ func DecorateSeed(seed []byte) ([]byte, error) { w := bytes.NewBuffer(nil) ts := bytes.TrimSpace(seed) @@ -97,7 +99,7 @@ NKEYs are sensitive and should be treated as secrets. return w.Bytes(), nil } -var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}\r?\n))`) +var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}(\r?\n|\z)))`) // An user config file looks like this: // -----BEGIN NATS USER JWT----- @@ -216,3 +218,49 @@ func ParseDecoratedUserNKey(contents []byte) (nkeys.KeyPair, error) { } return kp, nil } + +// IssueUserJWT takes an account scoped signing key, account id, and use public key (and optionally a user's name, an expiration duration and tags) and returns a valid signed JWT. +// The scopedSigningKey, is a mandatory account scoped signing nkey pair to sign the generated jwt (note that it _must_ be a signing key attached to the account (and a _scoped_ signing key), not the account's private (seed) key). +// The accountId, is a mandatory public account nkey. Will return error when not set or not account nkey. +// The publicUserKey, is a mandatory public user nkey. Will return error when not set or not user nkey. +// The name, is an optional human-readable name. When absent, default to publicUserKey. +// The expirationDuration, is an optional but recommended duration, when the generated jwt needs to expire. If not set, JWT will not expire. +// The tags, is an optional list of tags to be included in the JWT. +// +// Returns: +// string, resulting jwt. +// error, when issues arose. +func IssueUserJWT(scopedSigningKey nkeys.KeyPair, accountId string, publicUserKey string, name string, expirationDuration time.Duration, tags ...string) (string, error) { + + if !nkeys.IsValidPublicAccountKey(accountId) { + return "", errors.New("issueUserJWT requires an account key for the accountId parameter, but got " + nkeys.Prefix(accountId).String()) + } + + if !nkeys.IsValidPublicUserKey(publicUserKey) { + return "", errors.New("issueUserJWT requires an account key for the publicUserKey parameter, but got " + nkeys.Prefix(publicUserKey).String()) + } + + claim := NewUserClaims(publicUserKey) + claim.SetScoped(true) + + if expirationDuration != 0 { + claim.Expires = time.Now().Add(expirationDuration).UTC().Unix() + } + + claim.IssuerAccount = accountId + if name != "" { + claim.Name = name + } else { + claim.Name = publicUserKey + } + + claim.Subject = publicUserKey + claim.Tags = tags + + encoded, err := claim.Encode(scopedSigningKey) + if err != nil { + return "", errors.New("err encoding claim " + err.Error()) + } + + return encoded, nil +} diff --git a/vendor/github.com/nats-io/jwt/v2/decoder.go b/vendor/github.com/nats-io/jwt/v2/decoder.go index a887efd..1e043a3 100644 --- a/vendor/github.com/nats-io/jwt/v2/decoder.go +++ b/vendor/github.com/nats-io/jwt/v2/decoder.go @@ -1,5 +1,5 @@ /* - * Copyright 2020 The NATS Authors + * Copyright 2020-2022 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -110,6 +110,10 @@ func Decode(token string) (Claims, error) { if nkeys.IsValidPublicUserKey(issuer) { ok = true } + case nkeys.PrefixByteServer: + if nkeys.IsValidPublicServerKey(issuer) { + ok = true + } } } if !ok { @@ -140,6 +144,10 @@ func loadClaims(data []byte) (int, Claims, error) { claim, err = loadUser(data, id.Version()) case ActivationClaim: claim, err = loadActivation(data, id.Version()) + case AuthorizationRequestClaim: + claim, err = loadAuthorizationRequest(data, id.Version()) + case AuthorizationResponseClaim: + claim, err = loadAuthorizationResponse(data, id.Version()) case "cluster": return -1, nil, errors.New("ClusterClaims are not supported") case "server": diff --git a/vendor/github.com/nats-io/jwt/v2/decoder_account.go b/vendor/github.com/nats-io/jwt/v2/decoder_account.go index 2471b88..025aa0e 100644 --- a/vendor/github.com/nats-io/jwt/v2/decoder_account.go +++ b/vendor/github.com/nats-io/jwt/v2/decoder_account.go @@ -41,9 +41,13 @@ func loadAccount(data []byte, version int) (*AccountClaims, error) { return v1a.Migrate() case 2: var v2a AccountClaims + v2a.SigningKeys = make(SigningKeys) if err := json.Unmarshal(data, &v2a); err != nil { return nil, err } + if len(v2a.Limits.JetStreamTieredLimits) > 0 { + v2a.Limits.JetStreamLimits = JetStreamLimits{} + } return &v2a, nil default: return nil, fmt.Errorf("library supports version %d or less - received %d", libVersion, version) @@ -72,8 +76,11 @@ func (oa v1AccountClaims) migrateV1() (*AccountClaims, error) { a.Account.Exports = oa.v1NatsAccount.Exports a.Account.Limits.AccountLimits = oa.v1NatsAccount.Limits.AccountLimits a.Account.Limits.NatsLimits = oa.v1NatsAccount.Limits.NatsLimits - a.Account.Limits.JetStreamLimits = JetStreamLimits{0, 0, 0, 0} - a.Account.SigningKeys = oa.v1NatsAccount.SigningKeys + a.Account.Limits.JetStreamLimits = JetStreamLimits{} + a.Account.SigningKeys = make(SigningKeys) + for _, v := range oa.SigningKeys { + a.Account.SigningKeys.Add(v) + } a.Account.Revocations = oa.v1NatsAccount.Revocations a.Version = 1 return &a, nil diff --git a/vendor/github.com/nats-io/jwt/v2/decoder_authorization.go b/vendor/github.com/nats-io/jwt/v2/decoder_authorization.go new file mode 100644 index 0000000..aebd955 --- /dev/null +++ b/vendor/github.com/nats-io/jwt/v2/decoder_authorization.go @@ -0,0 +1,36 @@ +/* + * Copyright 2022 The NATS Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jwt + +import ( + "encoding/json" +) + +func loadAuthorizationRequest(data []byte, version int) (*AuthorizationRequestClaims, error) { + var ac AuthorizationRequestClaims + if err := json.Unmarshal(data, &ac); err != nil { + return nil, err + } + return &ac, nil +} + +func loadAuthorizationResponse(data []byte, version int) (*AuthorizationResponseClaims, error) { + var ac AuthorizationResponseClaims + if err := json.Unmarshal(data, &ac); err != nil { + return nil, err + } + return &ac, nil +} diff --git a/vendor/github.com/nats-io/jwt/v2/exports.go b/vendor/github.com/nats-io/jwt/v2/exports.go index c43b9a3..0f26e84 100644 --- a/vendor/github.com/nats-io/jwt/v2/exports.go +++ b/vendor/github.com/nats-io/jwt/v2/exports.go @@ -16,6 +16,7 @@ package jwt import ( + "encoding/json" "fmt" "strings" "time" @@ -41,28 +42,64 @@ const ( // Results is the subject where the latency metrics are published. // A metric will be defined by the nats-server's ServiceLatency. Time durations // are in nanoseconds. -// see https://github.com/nats-io/nats-server/blob/master/server/accounts.go#L524 +// see https://github.com/nats-io/nats-server/blob/main/server/accounts.go#L524 // e.g. -// { -// "app": "dlc22", -// "start": "2019-09-16T21:46:23.636869585-07:00", -// "svc": 219732, -// "nats": { -// "req": 320415, -// "resp": 228268, -// "sys": 0 -// }, -// "total": 768415 -// } // +// { +// "app": "dlc22", +// "start": "2019-09-16T21:46:23.636869585-07:00", +// "svc": 219732, +// "nats": { +// "req": 320415, +// "resp": 228268, +// "sys": 0 +// }, +// "total": 768415 +// } type ServiceLatency struct { - Sampling int `json:"sampling,omitempty"` - Results Subject `json:"results"` + Sampling SamplingRate `json:"sampling"` + Results Subject `json:"results"` +} + +type SamplingRate int + +const Headers = SamplingRate(0) + +// MarshalJSON marshals the field as "headers" or percentages +func (r *SamplingRate) MarshalJSON() ([]byte, error) { + sr := *r + if sr == 0 { + return []byte(`"headers"`), nil + } + if sr >= 1 && sr <= 100 { + return []byte(fmt.Sprintf("%d", sr)), nil + } + return nil, fmt.Errorf("unknown sampling rate") +} + +// UnmarshalJSON unmashals numbers as percentages or "headers" +func (t *SamplingRate) UnmarshalJSON(b []byte) error { + if len(b) == 0 { + return fmt.Errorf("empty sampling rate") + } + if strings.ToLower(string(b)) == `"headers"` { + *t = Headers + return nil + } + var j int + err := json.Unmarshal(b, &j) + if err != nil { + return err + } + *t = SamplingRate(j) + return nil } func (sl *ServiceLatency) Validate(vr *ValidationResults) { - if sl.Sampling < 1 || sl.Sampling > 100 { - vr.AddError("sampling percentage needs to be between 1-100") + if sl.Sampling != 0 { + if sl.Sampling < 1 || sl.Sampling > 100 { + vr.AddError("sampling percentage needs to be between 1-100") + } } sl.Results.Validate(vr) if sl.Results.HasWildCards() { @@ -81,6 +118,9 @@ type Export struct { ResponseThreshold time.Duration `json:"response_threshold,omitempty"` Latency *ServiceLatency `json:"service_latency,omitempty"` AccountTokenPosition uint `json:"account_token_position,omitempty"` + Advertise bool `json:"advertise,omitempty"` + AllowTrace bool `json:"allow_trace,omitempty"` + Info } // IsService returns true if an export is for a service @@ -121,8 +161,13 @@ func (e *Export) Validate(vr *ValidationResults) { if e.IsService() && !e.IsSingleResponse() && !e.IsChunkedResponse() && !e.IsStreamResponse() { vr.AddError("invalid response type for service: %q", e.ResponseType) } - if e.IsStream() && e.ResponseType != "" { - vr.AddError("invalid response type for stream: %q", e.ResponseType) + if e.IsStream() { + if e.ResponseType != "" { + vr.AddError("invalid response type for stream: %q", e.ResponseType) + } + if e.AllowTrace { + vr.AddError("AllowTrace only valid for service export") + } } if e.Latency != nil { if !e.IsService() { @@ -153,6 +198,7 @@ func (e *Export) Validate(vr *ValidationResults) { } } } + e.Info.Validate(vr) } // Revoke enters a revocation by publickey using time.Now(). @@ -227,7 +273,7 @@ func isContainedIn(kind ExportType, subjects []Subject, vr *ValidationResults) { } // Validate calls validate on all of the exports -func (e *Exports) Validate(vr *ValidationResults) error { +func (e *Exports) Validate(vr *ValidationResults) { var serviceSubjects []Subject var streamSubjects []Subject @@ -246,8 +292,6 @@ func (e *Exports) Validate(vr *ValidationResults) error { isContainedIn(Service, serviceSubjects, vr) isContainedIn(Stream, streamSubjects, vr) - - return nil } // HasExportContainingSubject checks if the export list has an export with the provided subject diff --git a/vendor/github.com/nats-io/jwt/v2/genericlaims.go b/vendor/github.com/nats-io/jwt/v2/genericlaims.go index 9a65728..e680866 100644 --- a/vendor/github.com/nats-io/jwt/v2/genericlaims.go +++ b/vendor/github.com/nats-io/jwt/v2/genericlaims.go @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -59,7 +59,10 @@ func DecodeGeneric(token string) (*GenericClaims, error) { return nil, err } - var gc GenericClaims + gc := struct { + GenericClaims + GenericFields + }{} if err := json.Unmarshal(data, &gc); err != nil { return nil, err } @@ -74,12 +77,22 @@ func DecodeGeneric(token string) (*GenericClaims, error) { if !gc.verify(chunks[1], sig) { return nil, errors.New("claim failed V1 signature verification") } + if tp := gc.GenericFields.Type; tp != "" { + // the conversion needs to be from a string because + // on custom types the type is not going to be one of + // the constants + gc.GenericClaims.Data["type"] = string(tp) + } + if tp := gc.GenericFields.Tags; len(tp) != 0 { + gc.GenericClaims.Data["tags"] = tp + } + } else { if !gc.verify(token[:len(chunks[0])+len(chunks[1])+1], sig) { return nil, errors.New("claim failed V2 signature verification") } } - return &gc, nil + return &gc.GenericClaims, nil } // Claims returns the standard part of the generic claim @@ -94,7 +107,11 @@ func (gc *GenericClaims) Payload() interface{} { // Encode takes a generic claims and creates a JWT string func (gc *GenericClaims) Encode(pair nkeys.KeyPair) (string, error) { - return gc.ClaimsData.encode(pair, gc) + return gc.ClaimsData.encode(pair, gc, nil) +} + +func (gc *GenericClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { + return gc.ClaimsData.encode(pair, gc, fn) } // Validate checks the generic part of the claims data @@ -122,11 +139,18 @@ func (gc *GenericClaims) ClaimType() ClaimType { } } } - ct, ctok := v.(string) - if ctok { + + switch ct := v.(type) { + case string: + if IsGenericClaimType(ct) { + return GenericClaim + } return ClaimType(ct) + case ClaimType: + return ct + default: + return "" } - return "" } func (gc *GenericClaims) updateVersion() { diff --git a/vendor/github.com/nats-io/jwt/v2/go.mod b/vendor/github.com/nats-io/jwt/v2/go.mod deleted file mode 100644 index 420392a..0000000 --- a/vendor/github.com/nats-io/jwt/v2/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module github.com/nats-io/jwt/v2 - -require ( - github.com/nats-io/jwt v0.3.2 - github.com/nats-io/nkeys v0.2.0 -) - -replace github.com/nats-io/jwt v0.3.2 => ../ - -go 1.14 diff --git a/vendor/github.com/nats-io/jwt/v2/go.sum b/vendor/github.com/nats-io/jwt/v2/go.sum deleted file mode 100644 index 05ef1fb..0000000 --- a/vendor/github.com/nats-io/jwt/v2/go.sum +++ /dev/null @@ -1,9 +0,0 @@ -github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/nats-io/jwt/v2/header.go b/vendor/github.com/nats-io/jwt/v2/header.go index 4fe7920..32f8a50 100644 --- a/vendor/github.com/nats-io/jwt/v2/header.go +++ b/vendor/github.com/nats-io/jwt/v2/header.go @@ -23,7 +23,7 @@ import ( const ( // Version is semantic version. - Version = "0.3.2" + Version = "2.4.0" // TokenTypeJwt is the JWT token type supported JWT tokens // encoded and decoded by this library diff --git a/vendor/github.com/nats-io/jwt/v2/imports.go b/vendor/github.com/nats-io/jwt/v2/imports.go index 04a9e36..c8524d0 100644 --- a/vendor/github.com/nats-io/jwt/v2/imports.go +++ b/vendor/github.com/nats-io/jwt/v2/imports.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 The NATS Authors + * Copyright 2018-2020 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -15,13 +15,6 @@ package jwt -import ( - "io/ioutil" - "net/http" - "net/url" - "time" -) - // Import describes a mapping from another account into this one type Import struct { Name string `json:"name,omitempty"` @@ -32,13 +25,22 @@ type Import struct { Subject Subject `json:"subject,omitempty"` Account string `json:"account,omitempty"` Token string `json:"token,omitempty"` + // Deprecated: use LocalSubject instead // To field in an import is always from the perspective of the subscriber // in the case of a stream it is the client of the stream (the importer), // from the perspective of a service, it is the subscription waiting for // requests (the exporter). If the field is empty, it will default to the // value in the Subject field. - To Subject `json:"to,omitempty"` - Type ExportType `json:"type,omitempty"` + To Subject `json:"to,omitempty"` + // Local subject used to subscribe (for streams) and publish (for services) to. + // This value only needs setting if you want to change the value of Subject. + // If the value of Subject ends in > then LocalSubject needs to end in > as well. + // LocalSubject can contain $ wildcard references where number references the nth wildcard in Subject. + // The sum of wildcard reference and * tokens needs to match the number of * token in Subject. + LocalSubject RenamingSubject `json:"local_subject,omitempty"` + Type ExportType `json:"type,omitempty"` + Share bool `json:"share,omitempty"` + AllowTrace bool `json:"allow_trace,omitempty"` } // IsService returns true if the import is of type service @@ -51,6 +53,11 @@ func (i *Import) IsStream() bool { return i.Type == Stream } +// Returns the value of To without triggering the deprecation warning for a read +func (i *Import) GetTo() string { + return string(i.To) +} + // Validate checks if an import is valid for the wrapping account func (i *Import) Validate(actPubKey string, vr *ValidationResults) { if i == nil { @@ -60,64 +67,58 @@ func (i *Import) Validate(actPubKey string, vr *ValidationResults) { if !i.IsService() && !i.IsStream() { vr.AddError("invalid import type: %q", i.Type) } + if i.IsService() && i.AllowTrace { + vr.AddError("AllowTrace only valid for stream import") + } if i.Account == "" { - vr.AddWarning("account to import from is not specified") + vr.AddError("account to import from is not specified") } - i.Subject.Validate(vr) - - if i.IsService() && i.Subject.HasWildCards() { - vr.AddError("services cannot have wildcard subject: %q", i.Subject) + if i.GetTo() != "" { + vr.AddWarning("the field to has been deprecated (use LocalSubject instead)") } - if i.IsStream() && i.To.HasWildCards() { - vr.AddError("streams cannot have wildcard to subject: %q", i.Subject) + + i.Subject.Validate(vr) + if i.LocalSubject != "" { + i.LocalSubject.Validate(i.Subject, vr) + if i.To != "" { + vr.AddError("Local Subject replaces To") + } } + if i.Share && !i.IsService() { + vr.AddError("sharing information (for latency tracking) is only valid for services: %q", i.Subject) + } var act *ActivationClaims if i.Token != "" { - // Check to see if its an embedded JWT or a URL. - if u, err := url.Parse(i.Token); err == nil && u.Scheme != "" { - c := &http.Client{Timeout: 5 * time.Second} - resp, err := c.Get(u.String()) - if err != nil { - vr.AddWarning("import %s contains an unreachable token URL %q", i.Subject, i.Token) - } - - if resp != nil { - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - vr.AddWarning("import %s contains an unreadable token URL %q", i.Subject, i.Token) - } else { - act, err = DecodeActivationClaims(string(body)) - if err != nil { - vr.AddWarning("import %s contains a URL %q with an invalid activation token", i.Subject, i.Token) - } - } - } - } else { - var err error - act, err = DecodeActivationClaims(i.Token) - if err != nil { - vr.AddWarning("import %q contains an invalid activation token", i.Subject) - } + var err error + act, err = DecodeActivationClaims(i.Token) + if err != nil { + vr.AddError("import %q contains an invalid activation token", i.Subject) } } if act != nil { - if act.Issuer != i.Account { - vr.AddWarning("activation token doesn't match account for import %q", i.Subject) + if !(act.Issuer == i.Account || act.IssuerAccount == i.Account) { + vr.AddError("activation token doesn't match account for import %q", i.Subject) } - if act.ClaimsData.Subject != actPubKey { - vr.AddWarning("activation token doesn't match account it is being included in, %q", i.Subject) + vr.AddError("activation token doesn't match account it is being included in, %q", i.Subject) + } + if act.ImportType != i.Type { + vr.AddError("mismatch between token import type %s and type of import %s", act.ImportType, i.Type) + } + act.validateWithTimeChecks(vr, false) + subj := i.Subject + if i.IsService() && i.To != "" { + subj = i.To + } + if !subj.IsContainedIn(act.ImportSubject) { + vr.AddError("activation token import subject %q doesn't match import %q", act.ImportSubject, i.Subject) } - } else { - vr.AddWarning("no activation provided for import %s", i.Subject) } - } // Imports is a list of import structs @@ -125,17 +126,29 @@ type Imports []*Import // Validate checks if an import is valid for the wrapping account func (i *Imports) Validate(acctPubKey string, vr *ValidationResults) { - toSet := make(map[Subject]bool, len(*i)) + toSet := make(map[Subject]struct{}, len(*i)) for _, v := range *i { if v == nil { vr.AddError("null import is not allowed") continue } if v.Type == Service { - if _, ok := toSet[v.To]; ok { - vr.AddError("Duplicate To subjects for %q", v.To) + sub := v.To + if sub == "" { + sub = v.LocalSubject.ToSubject() + } + if sub == "" { + sub = v.Subject + } + for k := range toSet { + if sub.IsContainedIn(k) || k.IsContainedIn(sub) { + vr.AddError("overlapping subject namespace for %q and %q", sub, k) + } + } + if _, ok := toSet[sub]; ok { + vr.AddError("overlapping subject namespace for %q", v.To) } - toSet[v.To] = true + toSet[sub] = struct{}{} } v.Validate(acctPubKey, vr) } diff --git a/vendor/github.com/nats-io/jwt/v2/operator_claims.go b/vendor/github.com/nats-io/jwt/v2/operator_claims.go index a41d9c0..b5c9c94 100644 --- a/vendor/github.com/nats-io/jwt/v2/operator_claims.go +++ b/vendor/github.com/nats-io/jwt/v2/operator_claims.go @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -43,6 +43,8 @@ type Operator struct { SystemAccount string `json:"system_account,omitempty"` // Min Server version AssertServerVersion string `json:"assert_server_version,omitempty"` + // Signing of subordinate objects will require signing keys + StrictSigningKeyUsage bool `json:"strict_signing_key_usage,omitempty"` GenericFields } @@ -134,8 +136,12 @@ func ValidateOperatorServiceURL(v string) error { return nil case "tls": return nil + case "ws": + return nil + case "wss": + return nil default: - return fmt.Errorf("operator service url %q - protocol not supported (only 'nats' or 'tls' only)", v) + return fmt.Errorf("operator service url %q - protocol not supported (only 'nats', 'tls', 'ws', 'wss' only)", v) } } @@ -164,6 +170,7 @@ func NewOperatorClaims(subject string) *OperatorClaims { } c := &OperatorClaims{} c.Subject = subject + c.Issuer = subject return c } @@ -174,13 +181,20 @@ func (oc *OperatorClaims) DidSign(op Claims) bool { } issuer := op.Claims().Issuer if issuer == oc.Subject { - return true + if !oc.StrictSigningKeyUsage { + return true + } + return op.Claims().Subject == oc.Subject } return oc.SigningKeys.Contains(issuer) } // Encode the claims into a JWT string func (oc *OperatorClaims) Encode(pair nkeys.KeyPair) (string, error) { + return oc.EncodeWithSigner(pair, nil) +} + +func (oc *OperatorClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { if !nkeys.IsValidPublicOperatorKey(oc.Subject) { return "", errors.New("expected subject to be an operator public key") } @@ -189,7 +203,7 @@ func (oc *OperatorClaims) Encode(pair nkeys.KeyPair) (string, error) { return "", err } oc.Type = OperatorClaim - return oc.ClaimsData.encode(pair, oc) + return oc.ClaimsData.encode(pair, oc, fn) } func (oc *OperatorClaims) ClaimType() ClaimType { @@ -237,3 +251,7 @@ func (oc *OperatorClaims) Claims() *ClaimsData { func (oc *OperatorClaims) updateVersion() { oc.GenericFields.Version = libVersion } + +func (oc *OperatorClaims) GetTags() TagList { + return oc.Operator.Tags +} diff --git a/vendor/github.com/nats-io/jwt/v2/revocation_list.go b/vendor/github.com/nats-io/jwt/v2/revocation_list.go index 9de30b1..c582896 100644 --- a/vendor/github.com/nats-io/jwt/v2/revocation_list.go +++ b/vendor/github.com/nats-io/jwt/v2/revocation_list.go @@ -19,20 +19,47 @@ import ( "time" ) +const All = "*" + // RevocationList is used to store a mapping of public keys to unix timestamps type RevocationList map[string]int64 +type RevocationEntry struct { + PublicKey string + TimeStamp int64 +} // Revoke enters a revocation by publickey and timestamp into this export // If there is already a revocation for this public key that is newer, it is kept. func (r RevocationList) Revoke(pubKey string, timestamp time.Time) { newTS := timestamp.Unix() + // cannot move a revocation into the future - only into the past if ts, ok := r[pubKey]; ok && ts > newTS { return } - r[pubKey] = newTS } +// MaybeCompact will compact the revocation list if jwt.All is found. Any +// revocation that is covered by a jwt.All revocation will be deleted, thus +// reducing the size of the JWT. Returns a slice of entries that were removed +// during the process. +func (r RevocationList) MaybeCompact() []RevocationEntry { + var deleted []RevocationEntry + ats, ok := r[All] + if ok { + for k, ts := range r { + if k != All && ats >= ts { + deleted = append(deleted, RevocationEntry{ + PublicKey: k, + TimeStamp: ts, + }) + delete(r, k) + } + } + } + return deleted +} + // ClearRevocation removes any revocation for the public key func (r RevocationList) ClearRevocation(pubKey string) { delete(r, pubKey) @@ -42,6 +69,16 @@ func (r RevocationList) ClearRevocation(pubKey string) { // the one passed in. Generally this method is called with an issue time but other time's can // be used for testing. func (r RevocationList) IsRevoked(pubKey string, timestamp time.Time) bool { + if r.allRevoked(timestamp) { + return true + } ts, ok := r[pubKey] return ok && ts >= timestamp.Unix() } + +// allRevoked returns true if All is set and the timestamp is later or same as the +// one passed. This is called by IsRevoked. +func (r RevocationList) allRevoked(timestamp time.Time) bool { + ts, ok := r[All] + return ok && ts >= timestamp.Unix() +} diff --git a/vendor/github.com/nats-io/jwt/v2/signingkeys.go b/vendor/github.com/nats-io/jwt/v2/signingkeys.go new file mode 100644 index 0000000..a997cbb --- /dev/null +++ b/vendor/github.com/nats-io/jwt/v2/signingkeys.go @@ -0,0 +1,213 @@ +/* + * Copyright 2020-2024 The NATS Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jwt + +import ( + "encoding/json" + "errors" + "fmt" + "sort" + + "github.com/nats-io/nkeys" +) + +type Scope interface { + SigningKey() string + ValidateScopedSigner(claim Claims) error + Validate(vr *ValidationResults) +} + +type ScopeType int + +const ( + UserScopeType ScopeType = iota + 1 +) + +func (t ScopeType) String() string { + switch t { + case UserScopeType: + return "user_scope" + } + return "unknown" +} + +func (t *ScopeType) MarshalJSON() ([]byte, error) { + switch *t { + case UserScopeType: + return []byte("\"user_scope\""), nil + } + return nil, fmt.Errorf("unknown scope type %q", t) +} + +func (t *ScopeType) UnmarshalJSON(b []byte) error { + var s string + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + switch s { + case "user_scope": + *t = UserScopeType + return nil + } + return fmt.Errorf("unknown scope type %q", t) +} + +type UserScope struct { + Kind ScopeType `json:"kind"` + Key string `json:"key"` + Role string `json:"role"` + Template UserPermissionLimits `json:"template"` + Description string `json:"description"` +} + +func NewUserScope() *UserScope { + var s UserScope + s.Kind = UserScopeType + s.Template.NatsLimits = NatsLimits{NoLimit, NoLimit, NoLimit} + return &s +} + +func (us UserScope) SigningKey() string { + return us.Key +} + +func (us UserScope) Validate(vr *ValidationResults) { + if !nkeys.IsValidPublicAccountKey(us.Key) { + vr.AddError("%s is not an account public key", us.Key) + } +} + +func (us UserScope) ValidateScopedSigner(c Claims) error { + uc, ok := c.(*UserClaims) + if !ok { + return fmt.Errorf("not an user claim - scoped signing key requires user claim") + } + if uc.Claims().Issuer != us.Key { + return errors.New("issuer not the scoped signer") + } + if !uc.HasEmptyPermissions() { + return errors.New("scoped users require no permissions or limits set") + } + return nil +} + +// SigningKeys is a map keyed by a public account key +type SigningKeys map[string]Scope + +func (sk SigningKeys) Validate(vr *ValidationResults) { + for k, v := range sk { + // regular signing keys won't have a scope + if v != nil { + v.Validate(vr) + } else { + if !nkeys.IsValidPublicAccountKey(k) { + vr.AddError("%q is not a valid account signing key", k) + } + } + } +} + +// MarshalJSON serializes the scoped signing keys as an array +func (sk *SigningKeys) MarshalJSON() ([]byte, error) { + if sk == nil { + return nil, nil + } + + keys := sk.Keys() + sort.Strings(keys) + + var a []interface{} + for _, k := range keys { + if (*sk)[k] != nil { + a = append(a, (*sk)[k]) + } else { + a = append(a, k) + } + } + return json.Marshal(a) +} + +func (sk *SigningKeys) UnmarshalJSON(data []byte) error { + if *sk == nil { + *sk = make(SigningKeys) + } + // read an array - we can have a string or an map + var a []interface{} + if err := json.Unmarshal(data, &a); err != nil { + return err + } + for _, i := range a { + switch v := i.(type) { + case string: + (*sk)[v] = nil + case map[string]interface{}: + d, err := json.Marshal(v) + if err != nil { + return err + } + switch v["kind"] { + case UserScopeType.String(): + us := NewUserScope() + if err := json.Unmarshal(d, &us); err != nil { + return err + } + (*sk)[us.Key] = us + default: + return fmt.Errorf("unknown signing key scope %q", v["type"]) + } + } + } + return nil +} + +func (sk SigningKeys) Keys() []string { + var keys []string + for k := range sk { + keys = append(keys, k) + } + return keys +} + +// GetScope returns nil if the key is not associated +func (sk SigningKeys) GetScope(k string) (Scope, bool) { + v, ok := sk[k] + if !ok { + return nil, false + } + return v, true +} + +func (sk SigningKeys) Contains(k string) bool { + _, ok := sk[k] + return ok +} + +func (sk SigningKeys) Add(keys ...string) { + for _, k := range keys { + sk[k] = nil + } +} + +func (sk SigningKeys) AddScopedSigner(s Scope) { + sk[s.SigningKey()] = s +} + +func (sk SigningKeys) Remove(keys ...string) { + for _, k := range keys { + delete(sk, k) + } +} diff --git a/vendor/github.com/nats-io/jwt/v2/types.go b/vendor/github.com/nats-io/jwt/v2/types.go index 34a3209..d5814db 100644 --- a/vendor/github.com/nats-io/jwt/v2/types.go +++ b/vendor/github.com/nats-io/jwt/v2/types.go @@ -19,10 +19,38 @@ import ( "encoding/json" "fmt" "net" + "net/url" + "reflect" + "strconv" "strings" "time" ) +const MaxInfoLength = 8 * 1024 + +type Info struct { + Description string `json:"description,omitempty"` + InfoURL string `json:"info_url,omitempty"` +} + +func (s Info) Validate(vr *ValidationResults) { + if len(s.Description) > MaxInfoLength { + vr.AddError("Description is too long") + } + if s.InfoURL != "" { + if len(s.InfoURL) > MaxInfoLength { + vr.AddError("Info URL is too long") + } + u, err := url.Parse(s.InfoURL) + if err == nil && (u.Hostname() == "" || u.Scheme == "") { + err = fmt.Errorf("no hostname or scheme") + } + if err != nil { + vr.AddError("error parsing info url: %v", err) + } + } +} + // ExportType defines the type of import/export. type ExportType int @@ -71,7 +99,74 @@ func (t *ExportType) UnmarshalJSON(b []byte) error { *t = Service return nil } - return fmt.Errorf("unknown export type") + return fmt.Errorf("unknown export type %q", j) +} + +type RenamingSubject Subject + +func (s RenamingSubject) Validate(from Subject, vr *ValidationResults) { + v := Subject(s) + v.Validate(vr) + if from == "" { + vr.AddError("subject cannot be empty") + } + if strings.Contains(string(s), " ") { + vr.AddError("subject %q cannot have spaces", v) + } + matchesSuffix := func(s Subject) bool { + return s == ">" || strings.HasSuffix(string(s), ".>") + } + if matchesSuffix(v) != matchesSuffix(from) { + vr.AddError("both, renaming subject and subject, need to end or not end in >") + } + fromCnt := from.countTokenWildcards() + refCnt := 0 + for _, tk := range strings.Split(string(v), ".") { + if tk == "*" { + refCnt++ + } + if len(tk) < 2 { + continue + } + if tk[0] == '$' { + if idx, err := strconv.Atoi(tk[1:]); err == nil { + if idx > fromCnt { + vr.AddError("Reference $%d in %q reference * in %q that do not exist", idx, s, from) + } else { + refCnt++ + } + } + } + } + if refCnt != fromCnt { + vr.AddError("subject does not contain enough * or reference wildcards $[0-9]") + } +} + +// Replaces reference tokens with * +func (s RenamingSubject) ToSubject() Subject { + if !strings.Contains(string(s), "$") { + return Subject(s) + } + bldr := strings.Builder{} + tokens := strings.Split(string(s), ".") + for i, tk := range tokens { + convert := false + if len(tk) > 1 && tk[0] == '$' { + if _, err := strconv.Atoi(tk[1:]); err == nil { + convert = true + } + } + if convert { + bldr.WriteString("*") + } else { + bldr.WriteString(tk) + } + if i != len(tokens)-1 { + bldr.WriteString(".") + } + } + return Subject(bldr.String()) } // Subject is a string that represents a NATS subject @@ -82,10 +177,32 @@ func (s Subject) Validate(vr *ValidationResults) { v := string(s) if v == "" { vr.AddError("subject cannot be empty") + // No other checks after that make sense + return } if strings.Contains(v, " ") { vr.AddError("subject %q cannot have spaces", v) } + if v[0] == '.' || v[len(v)-1] == '.' { + vr.AddError("subject %q cannot start or end with a `.`", v) + } + if strings.Contains(v, "..") { + vr.AddError("subject %q cannot contain consecutive `.`", v) + } +} + +func (s Subject) countTokenWildcards() int { + v := string(s) + if v == "*" { + return 1 + } + cnt := 0 + for _, t := range strings.Split(v, ".") { + if t == "*" { + cnt++ + } + } + return cnt } // HasWildCards is used to check if a subject contains a > or * @@ -163,6 +280,10 @@ type UserLimits struct { Locale string `json:"times_location,omitempty"` } +func (u *UserLimits) Empty() bool { + return reflect.DeepEqual(*u, UserLimits{}) +} + func (u *UserLimits) IsUnlimited() bool { return len(u.Src) == 0 && len(u.Times) == 0 } @@ -188,7 +309,7 @@ func (l *Limits) Validate(vr *ValidationResults) { } } - if l.Times != nil && len(l.Times) > 0 { + if len(l.Times) > 0 { for _, t := range l.Times { t.Validate(vr) } @@ -207,13 +328,33 @@ type Permission struct { Deny StringList `json:"deny,omitempty"` } +func (p *Permission) Empty() bool { + return len(p.Allow) == 0 && len(p.Deny) == 0 +} + +func checkPermission(vr *ValidationResults, subj string, permitQueue bool) { + tk := strings.Split(subj, " ") + switch len(tk) { + case 1: + Subject(tk[0]).Validate(vr) + case 2: + Subject(tk[0]).Validate(vr) + Subject(tk[1]).Validate(vr) + if !permitQueue { + vr.AddError(`Permission Subject "%s" is not allowed to contain queue`, subj) + } + default: + vr.AddError(`Permission Subject "%s" contains too many spaces`, subj) + } +} + // Validate the allow, deny elements of a permission -func (p *Permission) Validate(vr *ValidationResults) { +func (p *Permission) Validate(vr *ValidationResults, permitQueue bool) { for _, subj := range p.Allow { - Subject(subj).Validate(vr) + checkPermission(vr, subj, permitQueue) } for _, subj := range p.Deny { - Subject(subj).Validate(vr) + checkPermission(vr, subj, permitQueue) } } @@ -241,6 +382,8 @@ func (p *Permissions) Validate(vr *ValidationResults) { if p.Resp != nil { p.Resp.Validate(vr) } + p.Sub.Validate(vr, true) + p.Pub.Validate(vr, false) } // StringList is a wrapper for an array of strings diff --git a/vendor/github.com/nats-io/jwt/v2/user_claims.go b/vendor/github.com/nats-io/jwt/v2/user_claims.go index f36c74c..2cda51c 100644 --- a/vendor/github.com/nats-io/jwt/v2/user_claims.go +++ b/vendor/github.com/nats-io/jwt/v2/user_claims.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -17,23 +17,32 @@ package jwt import ( "errors" + "reflect" "github.com/nats-io/nkeys" ) const ( - ConnectionTypeStandard = "STANDARD" - ConnectionTypeWebsocket = "WEBSOCKET" - ConnectionTypeLeafnode = "LEAFNODE" - ConnectionTypeMqtt = "MQTT" + ConnectionTypeStandard = "STANDARD" + ConnectionTypeWebsocket = "WEBSOCKET" + ConnectionTypeLeafnode = "LEAFNODE" + ConnectionTypeLeafnodeWS = "LEAFNODE_WS" + ConnectionTypeMqtt = "MQTT" + ConnectionTypeMqttWS = "MQTT_WS" + ConnectionTypeInProcess = "IN_PROCESS" ) -// User defines the user specific data in a user JWT -type User struct { +type UserPermissionLimits struct { Permissions Limits BearerToken bool `json:"bearer_token,omitempty"` + ProxyRequired bool `json:"proxy_required,omitempty"` AllowedConnectionTypes StringList `json:"allowed_connection_types,omitempty"` +} + +// User defines the user specific data in a user JWT +type User struct { + UserPermissionLimits // IssuerAccount stores the public key for the account the issuer represents. // When set, the claim was issued by a signing key. IssuerAccount string `json:"issuer_account,omitempty"` @@ -67,13 +76,32 @@ func NewUserClaims(subject string) *UserClaims { return c } +func (u *UserClaims) SetScoped(t bool) { + if t { + u.UserPermissionLimits = UserPermissionLimits{} + } else { + u.Limits = Limits{ + UserLimits{CIDRList{}, nil, ""}, + NatsLimits{NoLimit, NoLimit, NoLimit}, + } + } +} + +func (u *UserClaims) HasEmptyPermissions() bool { + return reflect.DeepEqual(u.UserPermissionLimits, UserPermissionLimits{}) +} + // Encode tries to turn the user claims into a JWT string func (u *UserClaims) Encode(pair nkeys.KeyPair) (string, error) { + return u.EncodeWithSigner(pair, nil) +} + +func (u *UserClaims) EncodeWithSigner(pair nkeys.KeyPair, fn SignFn) (string, error) { if !nkeys.IsValidPublicUserKey(u.Subject) { return "", errors.New("expected subject to be user public key") } u.Type = UserClaim - return u.ClaimsData.encode(pair, u) + return u.ClaimsData.encode(pair, u, fn) } // DecodeUserClaims tries to parse a user claims from a JWT string @@ -129,3 +157,7 @@ func (u *UserClaims) updateVersion() { func (u *UserClaims) IsBearerToken() bool { return u.BearerToken } + +func (u *UserClaims) GetTags() TagList { + return u.User.Tags +} diff --git a/vendor/github.com/nats-io/jwt/v2/validation.go b/vendor/github.com/nats-io/jwt/v2/validation.go index afaed57..e76a03a 100644 --- a/vendor/github.com/nats-io/jwt/v2/validation.go +++ b/vendor/github.com/nats-io/jwt/v2/validation.go @@ -44,7 +44,7 @@ func CreateValidationResults() *ValidationResults { } } -//Add appends an issue to the list +// Add appends an issue to the list func (v *ValidationResults) Add(vi *ValidationIssue) { v.Issues = append(v.Issues, vi) } diff --git a/vendor/github.com/nats-io/nats-server/v2/conf/fuzz.go b/vendor/github.com/nats-io/nats-server/v2/conf/fuzz.go index 9dce7f7..e42a82e 100644 --- a/vendor/github.com/nats-io/nats-server/v2/conf/fuzz.go +++ b/vendor/github.com/nats-io/nats-server/v2/conf/fuzz.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2020-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build gofuzz +//go:build gofuzz package conf diff --git a/vendor/github.com/nats-io/nats-server/v2/conf/lex.go b/vendor/github.com/nats-io/nats-server/v2/conf/lex.go index 9358c9b..80a9a11 100644 --- a/vendor/github.com/nats-io/nats-server/v2/conf/lex.go +++ b/vendor/github.com/nats-io/nats-server/v2/conf/lex.go @@ -1,4 +1,4 @@ -// Copyright 2013-2018 The NATS Authors +// Copyright 2013-2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,7 +17,7 @@ // The format supported is less restrictive than today's formats. // Supports mixed Arrays [], nested Maps {}, multiple comment types (# and //) -// Also supports key value assigments using '=' or ':' or whiteSpace() +// Also supports key value assignments using '=' or ':' or whiteSpace() // e.g. foo = 2, foo : 2, foo 2 // maps can be assigned with no key separator as well // semicolons as value terminators in key/value assignments are optional @@ -78,6 +78,7 @@ const ( topOptTerm = '}' blockStart = '(' blockEnd = ')' + mapEndString = string(mapEnd) ) type stateFn func(lx *lexer) stateFn @@ -155,7 +156,6 @@ func (lx *lexer) pop() stateFn { func (lx *lexer) emit(typ itemType) { val := strings.Join(lx.stringParts, "") + lx.input[lx.start:lx.pos] - // Position of item in line where it started. pos := lx.pos - lx.ilstart - len(val) lx.items <- item{typ, val, lx.line, pos} @@ -235,7 +235,7 @@ func (lx *lexer) peek() rune { // errorf stops all lexing by emitting an error and returning `nil`. // Note that any value that is a character is escaped if it's a special // character (new lines, tabs, etc.). -func (lx *lexer) errorf(format string, values ...interface{}) stateFn { +func (lx *lexer) errorf(format string, values ...any) stateFn { for i, value := range values { if v, ok := value.(rune); ok { values[i] = escapeSpecial(v) @@ -262,7 +262,8 @@ func lexTop(lx *lexer) stateFn { switch r { case topOptStart: - return lexSkip(lx, lexTop) + lx.push(lexTop) + return lexSkip(lx, lexBlockStart) case commentHashStart: lx.push(lexTop) return lexCommentStart @@ -317,6 +318,105 @@ func lexTopValueEnd(lx *lexer) stateFn { "comment or EOF, but got '%v' instead.", r) } +func lexBlockStart(lx *lexer) stateFn { + r := lx.next() + if unicode.IsSpace(r) { + return lexSkip(lx, lexBlockStart) + } + + switch r { + case topOptStart: + lx.push(lexBlockEnd) + return lexSkip(lx, lexBlockStart) + case topOptTerm: + lx.ignore() + return lx.pop() + case commentHashStart: + lx.push(lexBlockStart) + return lexCommentStart + case commentSlashStart: + rn := lx.next() + if rn == commentSlashStart { + lx.push(lexBlockStart) + return lexCommentStart + } + lx.backup() + fallthrough + case eof: + if lx.pos > lx.start { + return lx.errorf("Unexpected EOF.") + } + lx.emit(itemEOF) + return nil + } + + // At this point, the only valid item can be a key, so we back up + // and let the key lexer do the rest. + lx.backup() + lx.push(lexBlockValueEnd) + return lexKeyStart +} + +// lexBlockValueEnd is entered whenever a block-level value has been consumed. +// It must see only whitespace, and will turn back to lexBlockStart upon a new line. +// If it sees EOF, it will quit the lexer successfully. +func lexBlockValueEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case r == commentHashStart: + // a comment will read to a new line for us. + lx.push(lexBlockValueEnd) + return lexCommentStart + case r == commentSlashStart: + rn := lx.next() + if rn == commentSlashStart { + lx.push(lexBlockValueEnd) + return lexCommentStart + } + lx.backup() + fallthrough + case isWhitespace(r): + return lexBlockValueEnd + case isNL(r) || r == optValTerm || r == topOptValTerm: + lx.ignore() + return lexBlockStart + case r == topOptTerm: + lx.backup() + return lexBlockEnd + } + return lx.errorf("Expected a block-level value to end with a new line, "+ + "comment or EOF, but got '%v' instead.", r) +} + +// lexBlockEnd is entered whenever a block-level value has been consumed. +// It must see only whitespace, and will turn back to lexTop upon a "}". +func lexBlockEnd(lx *lexer) stateFn { + r := lx.next() + switch { + case r == commentHashStart: + // a comment will read to a new line for us. + lx.push(lexBlockStart) + return lexCommentStart + case r == commentSlashStart: + rn := lx.next() + if rn == commentSlashStart { + lx.push(lexBlockStart) + return lexCommentStart + } + lx.backup() + fallthrough + case isNL(r) || isWhitespace(r): + return lexBlockEnd + case r == optValTerm || r == topOptValTerm: + lx.ignore() + return lexBlockStart + case r == topOptTerm: + lx.ignore() + return lx.pop() + } + return lx.errorf("Expected a block-level to end with a '}', but got '%v' instead.", r) +} + // lexKeyStart consumes a key name up until the first non-whitespace character. // lexKeyStart will ignore whitespace. It will also eat enclosing quotes. func lexKeyStart(lx *lexer) stateFn { @@ -413,6 +513,8 @@ func lexIncludeQuotedString(lx *lexer) stateFn { lx.next() lx.ignore() return lx.pop() + case r == eof: + return lx.errorf("Unexpected EOF in quoted include") } return lexIncludeQuotedString } @@ -429,6 +531,8 @@ func lexIncludeDubQuotedString(lx *lexer) stateFn { lx.next() lx.ignore() return lx.pop() + case r == eof: + return lx.errorf("Unexpected EOF in double quoted include") } return lexIncludeDubQuotedString } @@ -666,8 +770,9 @@ func lexMapKeyStart(lx *lexer) stateFn { // lexMapQuotedKey consumes the text of a key between quotes. func lexMapQuotedKey(lx *lexer) stateFn { - r := lx.peek() - if r == sqStringEnd { + if r := lx.peek(); r == eof { + return lx.errorf("Unexpected EOF processing quoted map key.") + } else if r == sqStringEnd { lx.emit(itemKey) lx.next() return lexSkip(lx, lexMapKeyEnd) @@ -676,10 +781,11 @@ func lexMapQuotedKey(lx *lexer) stateFn { return lexMapQuotedKey } -// lexMapQuotedKey consumes the text of a key between quotes. +// lexMapDubQuotedKey consumes the text of a key between quotes. func lexMapDubQuotedKey(lx *lexer) stateFn { - r := lx.peek() - if r == dqStringEnd { + if r := lx.peek(); r == eof { + return lx.errorf("Unexpected EOF processing double quoted map key.") + } else if r == dqStringEnd { lx.emit(itemKey) lx.next() return lexSkip(lx, lexMapKeyEnd) @@ -691,8 +797,9 @@ func lexMapDubQuotedKey(lx *lexer) stateFn { // lexMapKey consumes the text of a key. Assumes that the first character (which // is not whitespace) has already been consumed. func lexMapKey(lx *lexer) stateFn { - r := lx.peek() - if unicode.IsSpace(r) { + if r := lx.peek(); r == eof { + return lx.errorf("Unexpected EOF processing map key.") + } else if unicode.IsSpace(r) { // Spaces signal we could be looking at a keyword, e.g. include. // Keywords will eat the keyword and set the appropriate return stateFn. return lx.keyCheckKeyword(lexMapKeyEnd, lexMapValueEnd) @@ -783,6 +890,9 @@ func (lx *lexer) isBool() bool { // Check if the unquoted string is a variable reference, starting with $. func (lx *lexer) isVariable() bool { + if lx.start >= len(lx.input) { + return false + } if lx.input[lx.start] == '$' { lx.start += 1 return true @@ -984,6 +1094,7 @@ func lexNumberOrDateOrStringOrIP(lx *lexer) stateFn { case !(isNL(r) || r == eof || r == mapEnd || r == optValTerm || r == mapValTerm || isWhitespace(r) || unicode.IsDigit(r)): // Treat it as a string value once we get a rune that // is not a number. + lx.stringStateFn = lexString return lexString } lx.backup() @@ -999,8 +1110,13 @@ func lexConvenientNumber(lx *lexer) stateFn { return lexConvenientNumber } lx.backup() - lx.emit(itemInteger) - return lx.pop() + if isNL(r) || r == eof || r == mapEnd || r == optValTerm || r == mapValTerm || isWhitespace(r) || unicode.IsDigit(r) { + lx.emit(itemInteger) + return lx.pop() + } + // This is not a number, so treat it as a string. + lx.stringStateFn = lexString + return lexString } // lexDateAfterYear consumes a full Zulu Datetime in ISO8601 format. @@ -1045,7 +1161,7 @@ func lexNegNumberStart(lx *lexer) stateFn { return lexNegNumber } -// lexNumber consumes a negative integer or a float after seeing the first digit. +// lexNegNumber consumes a negative integer or a float after seeing the first digit. func lexNegNumber(lx *lexer) stateFn { r := lx.next() switch { diff --git a/vendor/github.com/nats-io/nats-server/v2/conf/parse.go b/vendor/github.com/nats-io/nats-server/v2/conf/parse.go index afb6f6e..b94c539 100644 --- a/vendor/github.com/nats-io/nats-server/v2/conf/parse.go +++ b/vendor/github.com/nats-io/nats-server/v2/conf/parse.go @@ -1,4 +1,4 @@ -// Copyright 2013-2018 The NATS Authors +// Copyright 2013-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18,7 +18,7 @@ package conf // The format supported is less restrictive than today's formats. // Supports mixed Arrays [], nested Maps {}, multiple comment types (# and //) -// Also supports key value assigments using '=' or ':' or whiteSpace() +// Also supports key value assignments using '=' or ':' or whiteSpace() // e.g. foo = 2, foo : 2, foo 2 // maps can be assigned with no key separator as well // semicolons as value terminators in key/value assignments are optional @@ -26,8 +26,9 @@ package conf // see parse_test.go for more examples. import ( + "crypto/sha256" + "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "strconv" @@ -36,15 +37,17 @@ import ( "unicode" ) +const _EMPTY_ = "" + type parser struct { - mapping map[string]interface{} + mapping map[string]any lx *lexer // The current scoped context, can be array or map - ctx interface{} + ctx any // stack of contexts, either map or array/slice stack - ctxs []interface{} + ctxs []any // Keys stack keys []string @@ -57,12 +60,15 @@ type parser struct { // pedantic reports error when configuration is not correct. pedantic bool + + // Tracks environment variable references, to avoid cycles + envVarReferences map[string]bool } -// Parse will return a map of keys to interface{}, although concrete types +// Parse will return a map of keys to any, although concrete types // underly them. The values supported are string, bool, int64, float64, DateTime. // Arrays and nested Maps are also supported. -func Parse(data string) (map[string]interface{}, error) { +func Parse(data string) (map[string]any, error) { p, err := parse(data, "", false) if err != nil { return nil, err @@ -70,9 +76,18 @@ func Parse(data string) (map[string]interface{}, error) { return p.mapping, nil } +// ParseWithChecks is equivalent to Parse but runs in pedantic mode. +func ParseWithChecks(data string) (map[string]any, error) { + p, err := parse(data, "", true) + if err != nil { + return nil, err + } + return p.mapping, nil +} + // ParseFile is a helper to open file, etc. and parse the contents. -func ParseFile(fp string) (map[string]interface{}, error) { - data, err := ioutil.ReadFile(fp) +func ParseFile(fp string) (map[string]any, error) { + data, err := os.ReadFile(fp) if err != nil { return nil, fmt.Errorf("error opening config file: %v", err) } @@ -85,8 +100,8 @@ func ParseFile(fp string) (map[string]interface{}, error) { } // ParseFileWithChecks is equivalent to ParseFile but runs in pedantic mode. -func ParseFileWithChecks(fp string) (map[string]interface{}, error) { - data, err := ioutil.ReadFile(fp) +func ParseFileWithChecks(fp string) (map[string]any, error) { + data, err := os.ReadFile(fp) if err != nil { return nil, err } @@ -99,14 +114,56 @@ func ParseFileWithChecks(fp string) (map[string]interface{}, error) { return p.mapping, nil } +// cleanupUsedEnvVars will recursively remove all already used +// environment variables which might be in the parsed tree. +func cleanupUsedEnvVars(m map[string]any) { + for k, v := range m { + t := v.(*token) + if t.usedVariable { + delete(m, k) + continue + } + // Cleanup any other env var that is still in the map. + if tm, ok := t.value.(map[string]any); ok { + cleanupUsedEnvVars(tm) + } + } +} + +// ParseFileWithChecksDigest returns the processed config and a digest +// that represents the configuration. +func ParseFileWithChecksDigest(fp string) (map[string]any, string, error) { + data, err := os.ReadFile(fp) + if err != nil { + return nil, _EMPTY_, err + } + p, err := parse(string(data), fp, true) + if err != nil { + return nil, _EMPTY_, err + } + // Filter out any environment variables before taking the digest. + cleanupUsedEnvVars(p.mapping) + digest := sha256.New() + e := json.NewEncoder(digest) + err = e.Encode(p.mapping) + if err != nil { + return nil, _EMPTY_, err + } + return p.mapping, fmt.Sprintf("sha256:%x", digest.Sum(nil)), nil +} + type token struct { item item - value interface{} + value any usedVariable bool sourceFile string } -func (t *token) Value() interface{} { +func (t *token) MarshalJSON() ([]byte, error) { + return json.Marshal(t.value) +} + +func (t *token) Value() any { return t.value } @@ -126,41 +183,68 @@ func (t *token) Position() int { return t.item.pos } -func parse(data, fp string, pedantic bool) (p *parser, err error) { - p = &parser{ - mapping: make(map[string]interface{}), - lx: lex(data), - ctxs: make([]interface{}, 0, 4), - keys: make([]string, 0, 4), - ikeys: make([]item, 0, 4), - fp: filepath.Dir(fp), - pedantic: pedantic, +func newParser(data, fp string, pedantic bool) *parser { + return &parser{ + mapping: make(map[string]any), + lx: lex(data), + ctxs: make([]any, 0, 4), + keys: make([]string, 0, 4), + ikeys: make([]item, 0, 4), + fp: filepath.Dir(fp), + pedantic: pedantic, + envVarReferences: make(map[string]bool), } +} + +func parse(data, fp string, pedantic bool) (*parser, error) { + p := newParser(data, fp, pedantic) + if err := p.parse(fp); err != nil { + return nil, err + } + return p, nil +} + +func parseEnv(data string, parent *parser) (*parser, error) { + p := newParser(data, "", false) + p.envVarReferences = parent.envVarReferences + if err := p.parse(""); err != nil { + return nil, err + } + return p, nil +} + +func (p *parser) parse(fp string) error { p.pushContext(p.mapping) + var prevItem item for { it := p.next() if it.typ == itemEOF { + // Here we allow the final character to be a bracket '}' + // in order to support JSON like configurations. + if prevItem.typ == itemKey && prevItem.val != mapEndString { + return fmt.Errorf("config is invalid (%s:%d:%d)", fp, it.line, it.pos) + } break } + prevItem = it if err := p.processItem(it, fp); err != nil { - return nil, err + return err } } - - return p, nil + return nil } func (p *parser) next() item { return p.lx.nextItem() } -func (p *parser) pushContext(ctx interface{}) { +func (p *parser) pushContext(ctx any) { p.ctxs = append(p.ctxs, ctx) p.ctx = ctx } -func (p *parser) popContext() interface{} { +func (p *parser) popContext() any { if len(p.ctxs) == 0 { panic("BUG in parser, context stack empty") } @@ -200,7 +284,7 @@ func (p *parser) popItemKey() item { } func (p *parser) processItem(it item, fp string) error { - setValue := func(it item, v interface{}) { + setValue := func(it item, v any) { if p.pedantic { p.setValue(&token{it, v, false, fp}) } else { @@ -221,7 +305,7 @@ func (p *parser) processItem(it item, fp string) error { p.pushItemKey(it) } case itemMapStart: - newCtx := make(map[string]interface{}) + newCtx := make(map[string]any) p.pushContext(newCtx) case itemMapEnd: setValue(it, p.popContext()) @@ -304,7 +388,7 @@ func (p *parser) processItem(it item, fp string) error { } setValue(it, dt) case itemArrayStart: - var array = make([]interface{}, 0) + var array = make([]any, 0) p.pushContext(array) case itemArrayEnd: array := p.ctx @@ -337,7 +421,7 @@ func (p *parser) processItem(it item, fp string) error { } case itemInclude: var ( - m map[string]interface{} + m map[string]any err error ) if p.pedantic { @@ -375,7 +459,7 @@ const bcryptPrefix = "2a$" // ignore array contexts and only process the map contexts.. // // Returns true for ok if it finds something, similar to map. -func (p *parser) lookupVariable(varReference string) (interface{}, bool, error) { +func (p *parser) lookupVariable(varReference string) (any, bool, error) { // Do special check to see if it is a raw bcrypt string. if strings.HasPrefix(varReference, bcryptPrefix) { return "$" + varReference, true, nil @@ -385,7 +469,7 @@ func (p *parser) lookupVariable(varReference string) (interface{}, bool, error) for i := len(p.ctxs) - 1; i >= 0; i-- { ctx := p.ctxs[i] // Process if it is a map context - if m, ok := ctx.(map[string]interface{}); ok { + if m, ok := ctx.(map[string]any); ok { if v, ok := m[varReference]; ok { return v, ok, nil } @@ -393,11 +477,18 @@ func (p *parser) lookupVariable(varReference string) (interface{}, bool, error) } // If we are here, we have exhausted our context maps and still not found anything. - // Parse from the environment. + // Detect reference cycles + if p.envVarReferences[varReference] { + return nil, false, fmt.Errorf("variable reference cycle for '%s'", varReference) + } + p.envVarReferences[varReference] = true + defer delete(p.envVarReferences, varReference) + + // Parse from the environment if vStr, ok := os.LookupEnv(varReference); ok { // Everything we get here will be a string value, so we need to process as a parser would. - if vmap, err := Parse(fmt.Sprintf("%s=%s", pkey, vStr)); err == nil { - v, ok := vmap[pkey] + if subp, err := parseEnv(fmt.Sprintf("%s=%s", pkey, vStr), p); err == nil { + v, ok := subp.mapping[pkey] return v, ok, nil } else { return nil, false, err @@ -406,17 +497,17 @@ func (p *parser) lookupVariable(varReference string) (interface{}, bool, error) return nil, false, nil } -func (p *parser) setValue(val interface{}) { +func (p *parser) setValue(val any) { // Test to see if we are on an array or a map // Array processing - if ctx, ok := p.ctx.([]interface{}); ok { + if ctx, ok := p.ctx.([]any); ok { p.ctx = append(ctx, val) p.ctxs[len(p.ctxs)-1] = p.ctx } // Map processing - if ctx, ok := p.ctx.(map[string]interface{}); ok { + if ctx, ok := p.ctx.(map[string]any); ok { key := p.popKey() if p.pedantic { diff --git a/vendor/github.com/nats-io/nats-server/v2/internal/fastrand/LICENSE b/vendor/github.com/nats-io/nats-server/v2/internal/fastrand/LICENSE new file mode 100644 index 0000000..c12aa07 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/internal/fastrand/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The LevelDB-Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/github.com/nats-io/nats-server/v2/internal/fastrand/fastrand.go b/vendor/github.com/nats-io/nats-server/v2/internal/fastrand/fastrand.go new file mode 100644 index 0000000..fbc5829 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/internal/fastrand/fastrand.go @@ -0,0 +1,23 @@ +// Copyright 2020-2023 The LevelDB-Go, Pebble and NATS 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 fastrand + +import _ "unsafe" // required by go:linkname + +// Uint32 returns a lock free uint32 value. +// +//go:linkname Uint32 runtime.fastrand +func Uint32() uint32 + +// Uint32n returns a lock free uint32 value in the interval [0, n). +// +//go:linkname Uint32n runtime.fastrandn +func Uint32n(n uint32) uint32 + +// Uint64 returns a lock free uint64 value. +func Uint64() uint64 { + v := uint64(Uint32()) + return v<<32 | uint64(Uint32()) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/logger/log.go b/vendor/github.com/nats-io/nats-server/v2/logger/log.go index 57cab62..83889fb 100644 --- a/vendor/github.com/nats-io/nats-server/v2/logger/log.go +++ b/vendor/github.com/nats-io/nats-server/v2/logger/log.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18,11 +18,16 @@ import ( "fmt" "log" "os" + "path/filepath" + "strings" "sync" "sync/atomic" "time" ) +// Default file permissions for log files. +const defaultLogPerms = os.FileMode(0640) + // Logger is the server logger type Logger struct { sync.Mutex @@ -38,13 +43,37 @@ type Logger struct { fl *fileLogger } -// NewStdLogger creates a logger with output directed to Stderr -func NewStdLogger(time, debug, trace, colors, pid bool) *Logger { +type LogOption interface { + isLoggerOption() +} + +// LogUTC controls whether timestamps in the log output should be UTC or local time. +type LogUTC bool + +func (l LogUTC) isLoggerOption() {} + +func logFlags(time bool, opts ...LogOption) int { flags := 0 if time { flags = log.LstdFlags | log.Lmicroseconds } + for _, opt := range opts { + switch v := opt.(type) { + case LogUTC: + if time && bool(v) { + flags |= log.LUTC + } + } + } + + return flags +} + +// NewStdLogger creates a logger with output directed to Stderr +func NewStdLogger(time, debug, trace, colors, pid bool, opts ...LogOption) *Logger { + flags := logFlags(time, opts...) + pre := "" if pid { pre = pidPrefix() @@ -66,11 +95,8 @@ func NewStdLogger(time, debug, trace, colors, pid bool) *Logger { } // NewFileLogger creates a logger with output directed to a file -func NewFileLogger(filename string, time, debug, trace, pid bool) *Logger { - flags := 0 - if time { - flags = log.LstdFlags | log.Lmicroseconds - } +func NewFileLogger(filename string, time, debug, trace, pid bool, opts ...LogOption) *Logger { + flags := logFlags(time, opts...) pre := "" if pid { @@ -107,18 +133,19 @@ type fileLogger struct { out int64 canRotate int32 sync.Mutex - l *Logger - f writerAndCloser - limit int64 - olimit int64 - pid string - time bool - closed bool + l *Logger + f writerAndCloser + limit int64 + olimit int64 + pid string + time bool + closed bool + maxNumFiles int } func newFileLogger(filename, pidPrefix string, time bool) (*fileLogger, error) { fileflags := os.O_WRONLY | os.O_APPEND | os.O_CREATE - f, err := os.OpenFile(filename, fileflags, 0660) + f, err := os.OpenFile(filename, fileflags, defaultLogPerms) if err != nil { return nil, err } @@ -148,7 +175,13 @@ func (l *fileLogger) setLimit(limit int64) { } } -func (l *fileLogger) logDirect(label, format string, v ...interface{}) int { +func (l *fileLogger) setMaxNumFiles(max int) { + l.Lock() + l.maxNumFiles = max + l.Unlock() +} + +func (l *fileLogger) logDirect(label, format string, v ...any) int { var entrya = [256]byte{} var entry = entrya[:0] if l.pid != "" { @@ -169,6 +202,41 @@ func (l *fileLogger) logDirect(label, format string, v ...interface{}) int { return len(entry) } +func (l *fileLogger) logPurge(fname string) { + var backups []string + lDir := filepath.Dir(fname) + lBase := filepath.Base(fname) + entries, err := os.ReadDir(lDir) + if err != nil { + l.logDirect(l.l.errorLabel, "Unable to read directory %q for log purge (%v), will attempt next rotation", lDir, err) + return + } + for _, entry := range entries { + if entry.IsDir() || entry.Name() == lBase || !strings.HasPrefix(entry.Name(), lBase) { + continue + } + if stamp, found := strings.CutPrefix(entry.Name(), fmt.Sprintf("%s%s", lBase, ".")); found { + _, err := time.Parse("2006:01:02:15:04:05.999999999", strings.Replace(stamp, ".", ":", 5)) + if err == nil { + backups = append(backups, entry.Name()) + } + } + } + currBackups := len(backups) + maxBackups := l.maxNumFiles - 1 + if currBackups > maxBackups { + // backups sorted oldest to latest based on timestamped lexical filename (ReadDir) + for i := 0; i < currBackups-maxBackups; i++ { + if err := os.Remove(filepath.Join(lDir, string(os.PathSeparator), backups[i])); err != nil { + l.logDirect(l.l.errorLabel, "Unable to remove backup log file %q (%v), will attempt next rotation", backups[i], err) + // Bail fast, we'll try again next rotation + return + } + l.logDirect(l.l.infoLabel, "Purged log file %q", backups[i]) + } + } +} + func (l *fileLogger) Write(b []byte) (int, error) { if atomic.LoadInt32(&l.canRotate) == 0 { n, err := l.f.Write(b) @@ -195,7 +263,7 @@ func (l *fileLogger) Write(b []byte) (int, error) { now.Second(), now.Nanosecond()) os.Rename(fname, bak) fileflags := os.O_WRONLY | os.O_APPEND | os.O_CREATE - f, err := os.OpenFile(fname, fileflags, 0660) + f, err := os.OpenFile(fname, fileflags, defaultLogPerms) if err != nil { l.Unlock() panic(fmt.Sprintf("Unable to re-open the logfile %q after rotation: %v", fname, err)) @@ -204,6 +272,9 @@ func (l *fileLogger) Write(b []byte) (int, error) { n := l.logDirect(l.l.infoLabel, "Rotated log, backup saved as %q", bak) l.out = int64(n) l.limit = l.olimit + if l.maxNumFiles > 0 { + l.logPurge(fname) + } } } l.Unlock() @@ -236,6 +307,19 @@ func (l *Logger) SetSizeLimit(limit int64) error { return nil } +// SetMaxNumFiles sets the number of archived log files that will be retained +func (l *Logger) SetMaxNumFiles(max int) error { + l.Lock() + if l.fl == nil { + l.Unlock() + return fmt.Errorf("can set log max number of files only for file logger") + } + fl := l.fl + l.Unlock() + fl.setMaxNumFiles(max) + return nil +} + // NewTestLogger creates a logger with output directed to Stderr with a prefix. // Useful for tracing in tests when multiple servers are in the same pid func NewTestLogger(prefix string, time bool) *Logger { @@ -287,34 +371,34 @@ func setColoredLabelFormats(l *Logger) { } // Noticef logs a notice statement -func (l *Logger) Noticef(format string, v ...interface{}) { +func (l *Logger) Noticef(format string, v ...any) { l.logger.Printf(l.infoLabel+format, v...) } // Warnf logs a notice statement -func (l *Logger) Warnf(format string, v ...interface{}) { +func (l *Logger) Warnf(format string, v ...any) { l.logger.Printf(l.warnLabel+format, v...) } // Errorf logs an error statement -func (l *Logger) Errorf(format string, v ...interface{}) { +func (l *Logger) Errorf(format string, v ...any) { l.logger.Printf(l.errorLabel+format, v...) } // Fatalf logs a fatal error -func (l *Logger) Fatalf(format string, v ...interface{}) { +func (l *Logger) Fatalf(format string, v ...any) { l.logger.Fatalf(l.fatalLabel+format, v...) } // Debugf logs a debug statement -func (l *Logger) Debugf(format string, v ...interface{}) { +func (l *Logger) Debugf(format string, v ...any) { if l.debug { l.logger.Printf(l.debugLabel+format, v...) } } // Tracef logs a trace statement -func (l *Logger) Tracef(format string, v ...interface{}) { +func (l *Logger) Tracef(format string, v ...any) { if l.trace { l.logger.Printf(l.traceLabel+format, v...) } diff --git a/vendor/github.com/nats-io/nats-server/v2/logger/syslog.go b/vendor/github.com/nats-io/nats-server/v2/logger/syslog.go index f211ccd..0eb134e 100644 --- a/vendor/github.com/nats-io/nats-server/v2/logger/syslog.go +++ b/vendor/github.com/nats-io/nats-server/v2/logger/syslog.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +//go:build !windows package logger @@ -98,34 +98,34 @@ func getNetworkAndAddr(fqn string) (network, addr string) { } // Noticef logs a notice statement -func (l *SysLogger) Noticef(format string, v ...interface{}) { +func (l *SysLogger) Noticef(format string, v ...any) { l.writer.Notice(fmt.Sprintf(format, v...)) } -// Warnf logs a notice statement -func (l *SysLogger) Warnf(format string, v ...interface{}) { - l.writer.Notice(fmt.Sprintf(format, v...)) +// Warnf logs a warning statement +func (l *SysLogger) Warnf(format string, v ...any) { + l.writer.Warning(fmt.Sprintf(format, v...)) } // Fatalf logs a fatal error -func (l *SysLogger) Fatalf(format string, v ...interface{}) { +func (l *SysLogger) Fatalf(format string, v ...any) { l.writer.Crit(fmt.Sprintf(format, v...)) } // Errorf logs an error statement -func (l *SysLogger) Errorf(format string, v ...interface{}) { +func (l *SysLogger) Errorf(format string, v ...any) { l.writer.Err(fmt.Sprintf(format, v...)) } // Debugf logs a debug statement -func (l *SysLogger) Debugf(format string, v ...interface{}) { +func (l *SysLogger) Debugf(format string, v ...any) { if l.debug { l.writer.Debug(fmt.Sprintf(format, v...)) } } // Tracef logs a trace statement -func (l *SysLogger) Tracef(format string, v ...interface{}) { +func (l *SysLogger) Tracef(format string, v ...any) { if l.trace { l.writer.Notice(fmt.Sprintf(format, v...)) } diff --git a/vendor/github.com/nats-io/nats-server/v2/logger/syslog_windows.go b/vendor/github.com/nats-io/nats-server/v2/logger/syslog_windows.go index 1a89e0a..176776b 100644 --- a/vendor/github.com/nats-io/nats-server/v2/logger/syslog_windows.go +++ b/vendor/github.com/nats-io/nats-server/v2/logger/syslog_windows.go @@ -1,4 +1,4 @@ -// Copyright 2012-2018 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -70,42 +70,42 @@ func NewRemoteSysLogger(fqn string, debug, trace bool) *SysLogger { } } -func formatMsg(tag, format string, v ...interface{}) string { +func formatMsg(tag, format string, v ...any) string { orig := fmt.Sprintf(format, v...) return fmt.Sprintf("pid[%d][%s]: %s", os.Getpid(), tag, orig) } // Noticef logs a notice statement -func (l *SysLogger) Noticef(format string, v ...interface{}) { +func (l *SysLogger) Noticef(format string, v ...any) { l.writer.Info(1, formatMsg("NOTICE", format, v...)) } -// Noticef logs a notice statement -func (l *SysLogger) Warnf(format string, v ...interface{}) { +// Warnf logs a warning statement +func (l *SysLogger) Warnf(format string, v ...any) { l.writer.Info(1, formatMsg("WARN", format, v...)) } // Fatalf logs a fatal error -func (l *SysLogger) Fatalf(format string, v ...interface{}) { +func (l *SysLogger) Fatalf(format string, v ...any) { msg := formatMsg("FATAL", format, v...) l.writer.Error(5, msg) panic(msg) } // Errorf logs an error statement -func (l *SysLogger) Errorf(format string, v ...interface{}) { +func (l *SysLogger) Errorf(format string, v ...any) { l.writer.Error(2, formatMsg("ERROR", format, v...)) } // Debugf logs a debug statement -func (l *SysLogger) Debugf(format string, v ...interface{}) { +func (l *SysLogger) Debugf(format string, v ...any) { if l.debug { l.writer.Info(3, formatMsg("DEBUG", format, v...)) } } // Tracef logs a trace statement -func (l *SysLogger) Tracef(format string, v ...interface{}) { +func (l *SysLogger) Tracef(format string, v ...any) { if l.trace { l.writer.Info(4, formatMsg("TRACE", format, v...)) } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/README-MQTT.md b/vendor/github.com/nats-io/nats-server/v2/server/README-MQTT.md new file mode 100644 index 0000000..6b420a8 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/README-MQTT.md @@ -0,0 +1,595 @@ +**MQTT Implementation Overview** + +Revision 1.1 + +Authors: Ivan Kozlovic, Lev Brouk + +NATS Server currently supports most of MQTT 3.1.1. This document describes how +it is implemented. + +It is strongly recommended to review the [MQTT v3.1.1 +specifications](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html) +and get a detailed understanding before proceeding with this document. + +# Contents + +1. [Concepts](#1-concepts) + - [Server, client](#server-client) + - [Connection, client ID, session](#connection-client-id-session) + - [Packets, messages, and subscriptions](#packets-messages-and-subscriptions) + - [Quality of Service (QoS), publish identifier (PI)](#quality-of-service-qos-publish-identifier-pi) + - [Retained message](#retained-message) + - [Will message](#will-message) +2. [Use of JetStream](#2-use-of-jetstream) + - [JetStream API](#jetstream-api) + - [Streams](#streams) + - [Consumers and Internal NATS Subscriptions](#consumers-and-internal-nats-subscriptions) +3. [Lifecycles](#3-lifecycles) + - [Connection, Session](#connection-session) + - [Subscription](#subscription) + - [Message](#message) + - [Retained messages](#retained-messages) +4. [Implementation Notes](#4-implementation-notes) + - [Hooking into NATS I/O](#hooking-into-nats-io) + - [Session Management](#session-management) + - [Processing QoS acks: PUBACK, PUBREC, PUBCOMP](#processing-qos-acks-puback-pubrec-pubcomp) + - [Subject Wildcards](#subject-wildcards) +5. [Known issues](#5-known-issues) + +# 1. Concepts + +## Server, client + +In the MQTT specification there are concepts of **Client** and **Server**, used +somewhat interchangeably with those of **Sender** and **Receiver**. A **Server** +acts as a **Receiver** when it gets `PUBLISH` messages from a **Sender** +**Client**, and acts as a **Sender** when it delivers them to subscribed +**Clients**. + +In the NATS server implementation there are also concepts (types) `server` and +`client`. `client` is an internal representation of a (connected) client and +runs its own read and write loops. Both of these have an `mqtt` field that if +set makes them behave as MQTT-compliant. + +The code and comments may sometimes be confusing as they refer to `server` and +`client` sometimes ambiguously between MQTT and NATS. + +## Connection, client ID, session + +When an MQTT client connects to a server, it must send a `CONNECT` packet to +create an **MQTT Connection**. The packet must include a **Client Identifier**. +The server will then create or load a previously saved **Session** for the (hash +of) the client ID. + +## Packets, messages, and subscriptions + +The low level unit of transmission in MQTT is a **Packet**. Examples of packets +are: `CONNECT`, `SUBSCRIBE`, `SUBACK`, `PUBLISH`, `PUBCOMP`, etc. + +An **MQTT Message** starts with a `PUBLISH` packet that a client sends to the +server. It is then matched against the current **MQTT Subscriptions** and is +delivered to them as appropriate. During the message delivery the server acts as +an MQTT client, and the receiver acts as an MQTT server. + +Internally we use **NATS Messages** and **NATS Subscriptions** to facilitate +message delivery. This may be somewhat confusing as the code refers to `msg` and +`sub`. What may be even more confusing is that some MQTT packets (specifically, +`PUBREL`) are represented as NATS messages, and that the original MQTT packet +"metadata" may be encoded as NATS message headers. + +## Quality of Service (QoS), publish identifier (PI) + +MQTT specifies 3 levels of quality of service (**QoS**): + +- `0` for at most once. A single delivery attempt. +- `1` for at least once. Will try to redeliver until acknowledged by the + receiver. +- `2` for exactly once. See the [SPEC REF] for the acknowledgement flow. + +QoS 1 and 2 messages need to be identified with publish identifiers (**PI**s). A +PI is a 16-bit integer that must uniquely identify a message for the duration of +the required exchange of acknowledgment packets. + +Note that the QoS applies separately to the transmission of a message from a +sender client to the server, and from the server to the receiving client. There +is no protocol-level acknowledgements between the receiver and the original +sender. The sender passes the ownership of messages to the server, and the +server then delivers them at maximum possible QoS to the receivers +(subscribers). The PIs for in-flight outgoing messages are issued and stored per +session. + +## Retained message + +A **Retained Message** is not part of any MQTT session and is not removed when the +session that produced it goes away. Instead, the server needs to persist a +_single_ retained message per topic. When a subscription is started, the server +needs to send the “matching” retained messages, that is, messages that would +have been delivered to the new subscription should that subscription had been +running prior to the publication of this message. + +Retained messages are removed when the server receives a retained message with +an empty body. Still, this retained message that serves as a “delete” of a +retained message will be processed as a normal published message. + +Retained messages can have QoS. + +## Will message + +The `CONNECT` packet can contain information about a **Will Message** that needs to +be sent to any client subscribing on the Will topic/subject in the event that +the client is disconnected implicitly, that is, not as a result as the client +sending the `DISCONNECT` packet. + +Will messages can have the retain flag and QoS. + +# 2. Use of JetStream + +The MQTT implementation relies heavily on JetStream. We use it to: + +- Persist (and restore) the [Session](#connection-client-id-session) state. +- Store and retrieve [Retained messages](#retained-message). +- Persist incoming [QoS 1 and + 2](#quality-of-service-qos-publish-identifier-pi) messages, and + re-deliver if needed. +- Store and de-duplicate incoming [QoS + 2](#quality-of-service-qos-publish-identifier-pi) messages. +- Persist and re-deliver outgoing [QoS + 2](#quality-of-service-qos-publish-identifier-pi) `PUBREL` packets. + +Here is the overview of how we set up and use JetStream **streams**, +**consumers**, and **internal NATS subscriptions**. + +## JetStream API + +All interactions with JetStream are performed via `mqttJSA` that sends NATS +requests to JetStream. Most are processed synchronously and await a response, +some (e.g. `jsa.sendAck()`) are sent asynchronously. JetStream API is usually +referred to as `jsa` in the code. No special locking is required to use `jsa`, +however the asynchronous use of JetStream may create race conditions with +delivery callbacks. + +## Streams + +We create the following streams unless they already exist. Failing to ensure the +streams would prevent the client from connecting. + +Each stream is created with a replica value that is determined by the size of +the cluster but limited to 3. It can also be overwritten by the stream_replicas +option in the MQTT configuration block. + +The streams are created the first time an Account Session Manager is initialized +and are used by all sessions in it. Note that to avoid race conditions, some +subscriptions are created first. The streams are never deleted. See +`mqttCreateAccountSessionManager()` for details. + +1. `$MQTT_sess` stores persisted **Session** records. It filters on + `"$MQTT.sess.>` subject and has a “limits” policy with `MaxMsgsPer` setting + of 1. +2. `$MQTT_msgs` is used for **QoS 1 and 2 message delivery**. + It filters on `$MQTT.msgs.>` subject and has an “interest” policy. +3. `$MQTT_rmsgs` stores **Retained Messages**. They are all + stored (and filtered) on a single subject `$MQTT.rmsg`. This stream has a + limits policy. +4. `$MQTT_qos2in` stores and deduplicates **Incoming QoS 2 Messages**. It + filters on `$MQTT.qos2.in.>` and has a "limits" policy with `MaxMsgsPer` of + 1. +5. `$MQTT_out` stores **Outgoing QoS 2** `PUBREL` packets. It filters on + `$MQTT.out.>` and has a "interest" retention policy. + +## Consumers and Internal NATS Subscriptions + +### Account Scope + +- A durable consumer for [Retained Messages](#retained-message) - + `$MQTT_rmsgs_` +- A subscription to handle all [jsa](#jetstream-api) replies for the account. +- A subscription to replies to "session persist" requests, so that we can detect + the use of a session with the same client ID anywhere in the cluster. +- 2 subscriptions to support [retained messages](#retained-message): + `$MQTT.sub.` for the messages themselves, and one to receive replies to + "delete retained message" JS API (on the JS reply subject var). + +### Session Scope + +When a new QoS 2 MQTT subscription is detected in a session, we ensure that +there is a durable consumer for [QoS +2](#quality-of-service-qos-publish-identifier-pi) `PUBREL`s out for delivery - +`$MQTT_PUBREL_` + +### Subscription Scope + +For all MQTT subscriptions, regardless of their QoS, we create internal NATS subscriptions to + +- `subject` (directly encoded from `topic`). This subscription is used to + deliver QoS 0 messages, and messages originating from NATS. +- if needed, `subject fwc` complements `subject` for topics like `topic.#` to + include `topic` itself, see [top-level wildcards](#subject-wildcards) + +For QoS 1 or 2 MQTT subscriptions we ensure: + +- A durable consumer for messages out for delivery - `_` +- An internal subscription to `$MQTT.sub.` to deliver the messages to the + receiving client. + +### (Old) Notes + +As indicated before, for a QoS1 or QoS2 subscription, the server will create a +JetStream consumer with the appropriate subject filter. If the subscription +already existed, then only the NATS subscription is created for the JetStream +consumer’s delivery subject. + +Note that JS consumers can be created with an “Replicas” override, which from +recent discussion is problematic with “Interest” policy streams, which +“$MQTT_msgs” is. + +We do handle situations where a subscription on the same subject filter is sent +with a different QoS as per MQTT specifications. If the existing was on QoS 1 or +2, and the “new” is for QoS 0, then we delete the existing JS consumer. + +Subscriptions that are QoS 0 have a NATS subscription with the callback function +being `mqttDeliverMsgCbQos0()`; while QoS 1 and 2 have a NATS subscription with +callback `mqttDeliverMsgCbQos12()`. Both those functions have comments that +describe the reason for their existence and what they are doing. For instance +the `mqttDeliverMsgCbQos0()` callback will reject any producing client that is +of type JETSTREAM, so that it handles only non JetStream (QoS 1 and 2) messages. + +Both these functions end-up calling mqttDeliver() which will first enqueue the +possible retained messages buffer before delivering any new message. The message +itself being delivered is serialized in MQTT format and enqueued to the client’s +outbound buffer and call to addToPCD is made so that it is flushed out of the +readloop. + +# 3. Lifecycles + +## Connection, Session + +An MQTT connection is created when a listening MQTT server receives a `CONNECT` +packet. See `mqttProcessConnect()`. A connection is associated with a session. +Steps: + +1. Ensure that we have an `AccountSessionManager` so we can have an + `mqttSession`. Lazily initialize JetStream streams, and internal consumers + and subscriptions. See `getOrCreateMQTTAccountSessionManager()`. +2. Find and disconnect any previous session/client for the same ID. See + `mqttProcessConnect()`. +3. Ensure we have an `mqttSession` - create a new or load a previously persisted + one. If the clean flag is set in `CONNECT`, clean the session. see + `mqttSession.clear()` +4. Initialize session's subscriptions, if any. +5. Always send back a `CONNACK` packet. If there were errors in previous steps, + include the error. + +An MQTT connection can be closed for a number of reasons, including receiving a +`DISCONNECT` from the client, explicit internal errors processing MQTT packets, +or the server receiving another `CONNECT` packet with the same client ID. See +`mqttHandleClosedClient()` and `mqttHandleWill()`. Steps: + +1. Send out the Will Message if applicable (if not caused by a `DISCONNECT` packet) +2. Delete the JetStream consumers for to QoS 1 and 2 packet delivery through + JS API calls (if "clean" session flag is set) +3. Delete the session record from the “$MQTT_sess” stream, based on recorded + stream sequence. (if "clean" session flag is set) +4. Close the client connection. + +On an explicit disconnect, that is, the client sends the DISCONNECT packet, the +server will NOT send the Will, as per specifications. + +For sessions that had the “clean” flag, the JS consumers corresponding to QoS 1 +subscriptions are deleted through JS API calls, the session record is then +deleted (based on recorded stream sequence) from the “$MQTT_sess” stream. + +Finally, the client connection is closed + +Sessions are persisted on disconnect, and on subscriptions changes. + +## Subscription + +Receiving an MQTT `SUBSCRIBE` packet creates new subscriptions, or updates +existing subscriptions in a session. Each `SUBSCRIBE` packet may contain several +specific subscriptions (`topic` + QoS in each). We always respond with a +`SUBACK`, which may indicate which subscriptions errored out. + +For each subscription in the packet, we: + +1. Ignore it if `topic` starts with `$MQTT.sub.`. +2. Set up QoS 0 message delivery - an internal NATS subscription on `topic`. +3. Replay any retained messages for `topic`, once as QoS 0. +4. If we already have a subscription on `topic`, update its QoS +5. If this is a QoS 2 subscription in the session, ensure we have the [PUBREL + consumer](#session-scope) for the session. +6. If this is a QoS 1 or 2 subscription, ensure we have the [Message + consumer](#subscription-scope) for this subscription (or delete one if it + exists and this is now a QoS 0 sub). +7. Add an extra subscription for the [top-level wildcard](#subject-wildcards) case. +8. Update the session, persist it if changed. + +When a session is restored (no clean flag), we go through the same steps to +re-subscribe to its stored subscription, except step #8 which would have been +redundant. + +When we get an `UNSUBSCRIBE` packet, it can contain multiple subscriptions to +unsubscribe. The parsing will generate a slice of mqttFilter objects that +contain the “filter” (the topic with possibly wildcard of the subscription) and +the QoS value. The server goes through the list and deletes the JS consumer (if +QoS 1 or 2) and unsubscribes the NATS subscription for the delivery subject (if +it was a QoS 1 or 2) or on the actual topic/subject. In case of the “#” +wildcard, the server will handle the “level up” subscriptions that NATS had to +create. + +Again, we update the session and persist it as needed in the `$MQTT_sess` +stream. + +## Message + +1. Detect an incoming PUBLISH packet, parse and check the message QoS. Fill out + the session's `mqttPublish` struct that contains information about the + published message. (see `mqttParse()`, `mqttParsePub()`) +2. Process the message according to its QoS (see `mqttProcessPub()`) + + - QoS 0: + - Initiate message delivery + - QoS 1: + - Initiate message delivery + - Send back a `PUBACK` + - QoS 2: + - Store the message in `$MQTT_qos2in` stream, using a PI-specific subject. + Since `MaxMsgsPer` is set to 1, we will ignore duplicates on the PI. + - Send back a `PUBREC` + - "Wait" for a `PUBREL`, then initiate message delivery + - Remove the previously stored QoS2 message + - Send back a `PUBCOMP` + +3. Initiate message delivery (see `mqttInitiateMsgDelivery()`) + + - Convert the MQTT `topic` into a NATS `subject` using + `mqttTopicToNATSPubSubject()` function. If there is a known subject + mapping, then we select the new subject using `selectMappedSubject()` + function and then convert back this subject into an MQTT topic using + `natsSubjectToMQTTTopic()` function. + - Re-serialize the `PUBLISH` packet received as a NATS message. Use NATS + headers for the metadata, and the deliverable MQTT `PUBLISH` packet as the + contents. + - Publish the messages as `subject` (and `subject fwc` if applicable, see + [subject wildcards](#subject-wildcards)). Use the "standard" NATS + `c.processInboundClientMsg()` to do that. `processInboundClientMsg()` will + distribute the message to any NATS subscriptions (including routes, + gateways, leafnodes) and the relevant MQTT subscriptions. + - Check for retained messages, process as needed. See + `c.processInboundClientMsg()` calling `c.mqttHandlePubRetain()` For MQTT + clients. + - If the message QoS is 1 or 2, store it in `$MQTT_msgs` stream as + `$MQTT.msgs.` for "at least once" delivery with retries. + +4. Let NATS and JetStream deliver to the internal subscriptions, and to the + receiving clients. See `mqttDeliverMsgCb...()` + + - The NATS message posted to `subject` (and `subject fwc`) will be delivered + to each relevant internal subscription by calling `mqttDeliverMsgCbQoS0()`. + The function has access to both the publishing and the receiving clients. + + - Ignore all irrelevant invocations. Specifically, do nothing if the + message needs to be delivered with a higher QoS - that will be handled by + the other, `...QoS12` callback. Note that if the original message was + publuished with a QoS 1 or 2, but the subscription has its maximum QoS + set to 0, the message will be delivered by this callback. + - Ignore "reserved" subscriptions, as per MQTT spec. + - Decode delivery `topic` from the NATS `subject`. + - Write (enqueue) outgoing `PUBLISH` packet. + - **DONE for QoS 0** + + - The NATS message posted to JetStream as `$MQTT.msgs.subject` will be + consumed by subscription-specific consumers. Note that MQTT subscriptions + with max QoS 0 do not have JetStream consumers. They are handled by the + QoS0 callback. + + The consumers will deliver it to the `$MQTT.sub.` + subject for their respective NATS subscriptions by calling + `mqttDeliverMsgCbQoS12()`. This callback too has access to both the + publishing and the receiving clients. + + - Ignore "reserved" subscriptions, as per MQTT spec. + - See if this is a re-delivery from JetStream by checking `sess.cpending` + for the JS reply subject. If so, use the existing PI and treat this as a + duplicate redelivery. + - Otherwise, assign the message a new PI (see `trackPublish()` and + `bumpPI()`) and store it in `sess.cpending` and `sess.pendingPublish`, + along with the JS reply subject that can be used to remove this pending + message from the consumer once it's delivered to the receipient. + - Decode delivery `topic` from the NATS `subject`. + - Write (enqueue) outgoing `PUBLISH` packet. + +5. QoS 1: "Wait" for a `PUBACK`. See `mqttProcessPubAck()`. + + - When received, remove the PI from the tracking maps, send an ACK to + consumer to remove the message. + - **DONE for QoS 1** + +6. QoS 2: "Wait" for a `PUBREC`. When received, we need to do all the same + things as in the QoS 1 `PUBACK` case, but we need to send out a `PUBREL`, and + continue using the same PI until the delivery flow is complete and we get + back a `PUBCOMP`. For that, we add the PI to `sess.pendingPubRel`, and to + `sess.cpending` with the PubRel consumer durable name. + + We also compose and store a headers-only NATS message signifying a `PUBREL` + out for delivery, and store it in the `$MQTT_qos2out` stream, as + `$MQTT.qos2.out.`. + +7. QoS 2: Deliver `PUBREL`. The PubRel session-specific consumer will publish to + internal subscription on `$MQTT.qos2.delivery`, calling + `mqttDeliverPubRelCb()`. We store the ACK reply subject in `cpending` to + remove the JS message on `PUBCOMP`, compose and send out a `PUBREL` packet. + +8. QoS 2: "Wait" for a `PUBCOMP`. See `mqttProcessPubComp()`. + - When received, remove the PI from the tracking maps, send an ACK to + consumer to remove the `PUBREL` message. + - **DONE for QoS 2** + +## Retained messages + +When we process an inbound `PUBLISH` and submit it to +`processInboundClientMsg()` function, for MQTT clients it will invoke +`mqttHandlePubRetain()` which checks if the published message is “retained” or +not. + +If it is, then we construct a record representing the retained message and store +it in the `$MQTT_rmsg` stream, under the single `$MQTT.rmsg` subject. The stored +record (in JSON) contains information about the subject, topic, MQTT flags, user +that produced this message and the message content itself. It is stored and the +stream sequence is remembered in the memory structure that contains retained +messages. + +Note that when creating an account session manager, the retained messages stream +is read from scratch to load all the messages through the use of a JS consumer. +The associated subscription will process the recovered retained messages or any +new that comes from the network. + +A retained message is added to a map and a subscription is created and inserted +into a sublist that will be used to perform a ReverseMatch() when a subscription +is started and we want to find all retained messages that the subscription would +have received if it had been running prior to the message being published. + +If a retained message on topic “foo” already exists, then the server has to +delete the old message at the stream sequence we saved when storing it. + +This could have been done with having retained messages stored under +`$MQTT.rmsg.` as opposed to all under a single subject, and make use of +the `MaxMsgsPer` field set to 1. The `MaxMsgsPer` option was introduced well into +the availability of MQTT and changes to the sessions was made in [PR +#2501](https://github.com/nats-io/nats-server/pull/2501), with a conversion of +existing streams such as `$MQTT*sess*` into a single stream with unique +subjects, but the changes were not made to the retained messages stream. + +There are also subscriptions for the handling of retained messages which are +messages that are asked by the publisher to be retained by the MQTT server to be +delivered to matching subscriptions when they start. There is a single message +per topic. Retained messages are deleted when the user sends a retained message +(there is a flag in the PUBLISH protocol) on a given topic with an empty body. +The difficulty with retained messages is to handle them in a cluster since all +servers need to be aware of their presence so that they can deliver them to +subscriptions that those servers may become the leader for. + +- `$MQTT_rmsgs` which has a “limits” policy and holds retained messages, all + under `$MQTT.rmsg` single subject. Not sure why I did not use MaxMsgsPer for + this stream and not filter `$MQTT.rmsg.>`. + +The first step when processing a new subscription is to gather the retained +messages that would be a match for this subscription. To do so, the server will +serialize into a buffer all messages for the account session manager’s sublist’s +ReverseMatch result. We use the returned subscriptions’ subject to find from a +map appropriate retained message (see `serializeRetainedMsgsForSub()` for +details). + +# 4. Implementation Notes + +## Hooking into NATS I/O + +### Starting the accept loop + +The MQTT accept loop is started when the server detects that an MQTT port has +been defined in the configuration file. It works similarly to all other accept +loops. Note that for MQTT over websocket, the websocket port has to be defined +and MQTT clients will connect to that port instead of the MQTT port and need to +provide `/mqtt` as part of the URL to redirect the creation of the client to an +MQTT client (with websocket support) instead of a regular NATS with websocket. +See the branching done in `startWebsocketServer()`. See `startMQTT()`. + +### Starting the read/write loops + +When a TCP connection is accepted, the internal go routine will invoke +`createMQTTClient()`. This function will set a `c.mqtt` object that will make it +become an MQTT client (through the `isMqtt()` helper function). The `readLoop()` +and `writeLoop()` are started similarly to other clients. However, the read loop +will branch out to `mqttParse()` instead when detecting that this is an MQTT +client. + +## Session Management + +### Account Session Manager + +`mqttAccountSessionManager` is an object that holds the state of all sessions in +an account. It also manages the lifecycle of JetStream streams and internal +subscriptions for processing JS API replies, session updates, etc. See +`mqttCreateAccountSessionManager()`. It is lazily initialized upon the first +MQTT `CONNECT` packet received. Account session manager is referred to as `asm` +in the code. + +Note that creating the account session manager (and attempting to create the +streams) is done only once per account on a given server, since once created the +account session manager for a given account would be found in the sessions map +of the mqttSessionManager object. + +### Find and disconnect previous session/client + +Once all that is done, we now go to the creation of the session object itself. +For that, we first need to make sure that it does not already exist, meaning +that it is registered on the server - or anywhere in the cluster. Note that MQTT +dictates that if a session with the same ID connects, the OLD session needs to +be closed, not the new one being created. NATS Server complies with this +requirement. + +Once a session is detected to already exists, the old one (as described above) +is closed and the new one accepted, however, the session ID is maintained in a +flappers map so that we detect situations where sessions with the same ID are +started multiple times causing the previous one to be closed. When that +detection occurs, the newly created session is put in “jail” for a second to +avoid a very rapid succession of connect/disconnect. This has already been seen +by users since there was some issue there where we would schedule the connection +closed instead of waiting in place which was causing a panic. + +We also protect from multiple clients on a given server trying to connect with +the same ID at the “same time” while the processing of a CONNECT of a session is +not yet finished. This is done with the use of a sessLocked map, keyed by the +session ID. + +### Create or restore the session + +If everything is good up to that point, the server will either create or restore +a session from the stream. This is done in the `createOrRestoreSession()` +function. The client/session ID is hashed and added to the session’s stream +subject along with the JS domain to prevent clients connecting from different +domains to “pollute” the session stream of a given domain. + +Since each session constitutes a subject and the stream has a maximum of 1 +message per subject, we attempt to load the last message on the formed subject. +If we don’t find it, then the session object is created “empty”, while if we +find a record, we create the session object based on the record persisted on the +stream. + +If the session was restored from the JS stream, we keep track of the stream +sequence where the record was located. When we save the session (even if it +already exists) we will use this sequence number to set the +`JSExpectedLastSubjSeq` header so that we handle possibly different servers in a +(super)cluster to detect the race of clients trying to use the same session ID, +since only one of the write should succeed. On success, the session’s new +sequence is remembered by the server that did the write. + +When created or restored, the CONNACK can now be sent back to the client, and if +there were any recovered subscriptions, they are now processed. + +## Processing QoS acks: PUBACK, PUBREC, PUBCOMP + +When the server delivers a message with QoS 1 or 2 (also a `PUBREL` for QoS 2) to a subscribed client, the client will send back an acknowledgement. See `mqttProcessPubAck()`, `mqttProcessPubRec()`, and `mqttProcessPubComp()` + +While the specific logic for each packet differs, these handlers all update the +session's PI mappings (`cpending`, `pendingPublish`, `pendingPubRel`), and if +needed send an ACK to JetStream to remove the message from its consumer and stop +the re-delivery attempts. + +## Subject Wildcards + +Note that MQTT subscriptions have wildcards too, the `“+”` wildcard is equivalent +to NATS’s `“*”` wildcard, however, MQTT’s wildcard `“#”` is similar to `“>”`, except +that it also includes the level above. That is, a subscription on `“foo/#”` would +receive messages on `“foo/bar/baz”`, but also on `“foo”`. + +So, for MQTT subscriptions enging with a `'#'` we are forced to create 2 +internal NATS subscriptions, one on `“foo”` and one on `“foo.>”`. + +# 5. Known issues +- "active" redelivery for QoS from JetStream (compliant, just a note) +- JetStream QoS redelivery happens out of (original) order +- finish delivery of in-flight messages after UNSUB +- finish delivery of in-flight messages after a reconnect +- consider replacing `$MQTT_msgs` with `$MQTT_out`. +- consider using unique `$MQTT.rmsg.>` and `MaxMsgsPer` for retained messages. +- add a cli command to list/clean old sessions diff --git a/vendor/github.com/nats-io/nats-server/v2/server/README.md b/vendor/github.com/nats-io/nats-server/v2/server/README.md new file mode 100644 index 0000000..38e8621 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/README.md @@ -0,0 +1,17 @@ +# Tests + +Tests that run on Travis have been split into jobs that run in their own VM in parallel. This reduces the overall running time but also is allowing recycling of a job when we get a flapper as opposed to have to recycle the whole test suite. + +## JetStream Tests + +For JetStream tests, we need to observe a naming convention so that no tests are omitted when running on Travis. + +The script `runTestsOnTravis.sh` will run a given job based on the definition found in "`.travis.yml`". + +As for the naming convention: + +- All JetStream test name should start with `TestJetStream` +- Cluster tests should go into `jetstream_cluster_test.go` and start with `TestJetStreamCluster` +- Super-cluster tests should go into `jetstream_super_cluster_test.go` and start with `TestJetStreamSuperCluster` + +Not following this convention means that some tests may not be executed on Travis. diff --git a/vendor/github.com/nats-io/nats-server/v2/server/accounts.go b/vendor/github.com/nats-io/nats-server/v2/server/accounts.go index e47ab83..e3ab9db 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/accounts.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/accounts.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The NATS Authors +// Copyright 2018-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,23 +15,26 @@ package server import ( "bytes" + "cmp" "encoding/hex" "errors" "fmt" - "io/ioutil" + "io" + "io/fs" "math" "math/rand" "net/http" "net/textproto" - "net/url" "reflect" - "sort" + "slices" "strconv" "strings" "sync" + "sync/atomic" "time" "github.com/nats-io/jwt/v2" + "github.com/nats-io/nats-server/v2/internal/fastrand" "github.com/nats-io/nkeys" "github.com/nats-io/nuid" ) @@ -40,9 +43,23 @@ import ( // account will be grouped in the default global account. const globalAccountName = DEFAULT_GLOBAL_ACCOUNT +const defaultMaxSubLimitReportThreshold = int64(2 * time.Second) + +var maxSubLimitReportThreshold = defaultMaxSubLimitReportThreshold + // Account are subject namespace definitions. By default no messages are shared between accounts. // You can share via Exports and Imports of Streams and Services. type Account struct { + // Total stats for the account. + stats struct { + sync.Mutex + stats // Totals + gw stats // Gateways + rt stats // Routes + ln stats // Leafnodes + } + + gwReplyMapping Name string Nkey string Issuer string @@ -52,6 +69,7 @@ type Account struct { sqmu sync.Mutex sl *Sublist ic *client + sq *sendq isid uint64 etmr *time.Timer ctmr *time.Timer @@ -64,32 +82,54 @@ type Account struct { rm map[string]int32 lqws map[string]int32 usersRevoked map[string]int64 - actsRevoked map[string]int64 mappings []*mapping + hasMapped atomic.Bool + lmu sync.RWMutex lleafs []*client + leafClusters map[string]uint64 imports importMap exports exportMap js *jsAccount - jsLimits *JetStreamAccountLimits + jsLimits map[string]JetStreamAccountLimits + nrgAccount string limits - expired bool + expired atomic.Bool incomplete bool - signingKeys []string + signingKeys map[string]jwt.Scope + extAuth *jwt.ExternalAuthorization srv *Server // server this account is registered with (possibly nil) lds string // loop detection subject for leaf nodes siReply []byte // service reply prefix, will form wildcard subscription. - prand *rand.Rand eventIds *nuid.NUID eventIdsMu sync.Mutex defaultPerms *Permissions + tags jwt.TagList + nameTag string + lastLimErr int64 + routePoolIdx int + // If the trace destination is specified and a message with a traceParentHdr + // is received, and has the least significant bit of the last token set to 1, + // then if traceDestSampling is > 0 and < 100, a random value will be selected + // and if it falls between 0 and that value, message tracing will be triggered. + traceDest string + traceDestSampling int + // Guarantee that only one goroutine can be running either checkJetStreamMigrate + // or clearObserverState at a given time for this account to prevent interleaving. + jscmMu sync.Mutex } +const ( + accDedicatedRoute = -1 + accTransitioningToDedicatedRoute = -2 +) + // Account based limits. type limits struct { - mpay int32 - msubs int32 - mconns int32 - mleafs int32 + mpay int32 + msubs int32 + mconns int32 + mleafs int32 + disallowBearer bool } // Used to track remote clients and leafnodes per remote server. @@ -103,13 +143,19 @@ type streamImport struct { acc *Account from string to string - tr *transform - rtr *transform + tr *subjectTransform + rtr *subjectTransform claim *jwt.Import usePub bool invalid bool + // This is `allow_trace` and when true and message tracing is happening, + // we will trace egresses past the account boundary, if `false`, we stop + // at the account boundary. + atrc bool } +const ClientInfoHdr = "Nats-Request-Info" + // Import service mapping struct type serviceImport struct { acc *Account @@ -118,8 +164,7 @@ type serviceImport struct { sid []byte from string to string - exsub string - tr *transform + tr *subjectTransform ts int64 rt ServiceRespType latency *serviceLatency @@ -131,7 +176,7 @@ type serviceImport struct { share bool tracking bool didDeliver bool - isSysAcc bool + atrc bool // allow trace (got from service export) trackingHdr http.Header // header from request } @@ -170,8 +215,10 @@ func (rt ServiceRespType) String() string { // exportAuth holds configured approvals or boolean indicating an // auth token is required for import. type exportAuth struct { - tokenReq bool - approved map[string]*Account + tokenReq bool + accountPos uint + approved map[string]*Account + actsRevoked map[string]int64 } // streamExport @@ -187,6 +234,11 @@ type serviceExport struct { latency *serviceLatency rtmr *time.Timer respThresh time.Duration + // This is `allow_trace` and when true and message tracing is happening, + // when processing a service import we will go through account boundary + // and trace egresses on that other account. If `false`, we stop at the + // account boundary. + atrc bool } // Used to track service latency. @@ -206,7 +258,7 @@ type exportMap struct { // For services we will also track the response mappings as well. type importMap struct { streams []*streamImport - services map[string]*serviceImport + services map[string][]*serviceImport rrMap map[string][]*serviceRespEntry } @@ -214,18 +266,40 @@ type importMap struct { func NewAccount(name string) *Account { a := &Account{ Name: name, - limits: limits{-1, -1, -1, -1}, + limits: limits{-1, -1, -1, -1, false}, eventIds: nuid.New(), } return a } +func (a *Account) String() string { + return a.Name +} + +func (a *Account) setTraceDest(dest string) { + a.mu.Lock() + a.traceDest = dest + a.mu.Unlock() +} + +func (a *Account) getTraceDestAndSampling() (string, int) { + a.mu.RLock() + dest := a.traceDest + sampling := a.traceDestSampling + a.mu.RUnlock() + return dest, sampling +} + // Used to create shallow copies of accounts for transfer // from opts to real accounts in server struct. -func (a *Account) shallowCopy() *Account { - na := NewAccount(a.Name) +// Account `na` write lock is expected to be held on entry +// while account `a` is the one from the Options struct +// being loaded/reloaded and do not need locking. +func (a *Account) shallowCopy(na *Account) { na.Nkey = a.Nkey na.Issuer = a.Issuer + na.traceDest, na.traceDestSampling = a.traceDest, a.traceDestSampling + na.nrgAccount = a.nrgAccount if a.imports.streams != nil { na.imports.streams = make([]*streamImport, 0, len(a.imports.streams)) @@ -235,10 +309,14 @@ func (a *Account) shallowCopy() *Account { } } if a.imports.services != nil { - na.imports.services = make(map[string]*serviceImport) + na.imports.services = make(map[string][]*serviceImport) for k, v := range a.imports.services { - si := *v - na.imports.services[k] = &si + sis := make([]*serviceImport, 0, len(v)) + for _, si := range v { + csi := *si + sis = append(sis, &csi) + } + na.imports.services[k] = sis } } if a.exports.streams != nil { @@ -263,10 +341,13 @@ func (a *Account) shallowCopy() *Account { } } } + na.mappings = a.mappings + na.hasMapped.Store(len(na.mappings) > 0) + // JetStream na.jsLimits = a.jsLimits - - return na + // Server config account limits. + na.limits = a.limits } // nextEventID uses its own lock for better concurrency. @@ -277,6 +358,42 @@ func (a *Account) nextEventID() string { return id } +// Returns a slice of clients stored in the account, or nil if none is present. +// Lock is held on entry. +func (a *Account) getClientsLocked() []*client { + if len(a.clients) == 0 { + return nil + } + clients := make([]*client, 0, len(a.clients)) + for c := range a.clients { + clients = append(clients, c) + } + return clients +} + +// Returns a slice of clients stored in the account, or nil if none is present. +func (a *Account) getClients() []*client { + a.mu.RLock() + clients := a.getClientsLocked() + a.mu.RUnlock() + return clients +} + +// Returns a slice of external (non-internal) clients stored in the account, or nil if none is present. +// Lock is held on entry. +func (a *Account) getExternalClientsLocked() []*client { + if len(a.clients) == 0 { + return nil + } + var clients []*client + for c := range a.clients { + if !isInternalClient(c.kind) { + clients = append(clients, c) + } + } + return clients +} + // Called to track a remote server and connections and leafnodes it // has for this account. func (a *Account) updateRemoteServer(m *AccountNumConns) []*client { @@ -297,13 +414,10 @@ func (a *Account) updateRemoteServer(m *AccountNumConns) []*client { // conservative and bit harsh here. Clients will reconnect if we over compensate. var clients []*client if mtce { - clients = make([]*client, 0, len(a.clients)) - for c := range a.clients { - clients = append(clients, c) - } - sort.Slice(clients, func(i, j int) bool { - return clients[i].start.After(clients[j].start) - }) + clients = a.getExternalClientsLocked() + + // Sort in reverse chronological. + slices.SortFunc(clients, func(i, j *client) int { return -i.start.Compare(j.start) }) over := (len(a.clients) - int(a.sysclients) + int(a.nrclients)) - int(a.mconns) if over < len(clients) { clients = clients[:over] @@ -313,12 +427,14 @@ func (a *Account) updateRemoteServer(m *AccountNumConns) []*client { mtlce := a.mleafs != jwt.NoLimit && (a.nleafs+a.nrleafs > a.mleafs) if mtlce { // Take ones from the end. + a.lmu.RLock() leafs := a.lleafs over := int(a.nleafs + a.nrleafs - a.mleafs) if over < len(leafs) { leafs = leafs[len(leafs)-over:] } clients = append(clients, leafs...) + a.lmu.RUnlock() } a.mu.Unlock() @@ -375,11 +491,34 @@ func (a *Account) GetName() string { return name } +// getNameTag will return the name tag or the account name if not set. +func (a *Account) getNameTag() string { + if a == nil { + return _EMPTY_ + } + a.mu.RLock() + defer a.mu.RUnlock() + return a.getNameTagLocked() +} + +// getNameTagLocked will return the name tag or the account name if not set. +// Lock should be held. +func (a *Account) getNameTagLocked() string { + if a == nil { + return _EMPTY_ + } + nameTag := a.nameTag + if nameTag == _EMPTY_ { + nameTag = a.Name + } + return nameTag +} + // NumConnections returns active number of clients for this account for // all known servers. func (a *Account) NumConnections() int { a.mu.RLock() - nc := len(a.clients) + int(a.nrclients) + nc := len(a.clients) - int(a.sysclients) + int(a.nrclients) a.mu.RUnlock() return nc } @@ -495,23 +634,42 @@ func (a *Account) RoutedSubs() int { func (a *Account) TotalSubs() int { a.mu.RLock() defer a.mu.RUnlock() + if a.sl == nil { + return 0 + } return int(a.sl.Count()) } +func (a *Account) shouldLogMaxSubErr() bool { + if a == nil { + return true + } + a.mu.RLock() + last := a.lastLimErr + a.mu.RUnlock() + if now := time.Now().UnixNano(); now-last >= maxSubLimitReportThreshold { + a.mu.Lock() + a.lastLimErr = now + a.mu.Unlock() + return true + } + return false +} + // MapDest is for mapping published subjects for clients. type MapDest struct { - Subject string `json:"subject"` - Weight uint8 `json:"weight"` - OptCluster string `json:"cluster,omitempty"` + Subject string `json:"subject"` + Weight uint8 `json:"weight"` + Cluster string `json:"cluster,omitempty"` } func NewMapDest(subject string, weight uint8) *MapDest { - return &MapDest{subject, weight, ""} + return &MapDest{subject, weight, _EMPTY_} } // destination is for internal representation for a weighted mapped destination. type destination struct { - tr *transform + tr *subjectTransform weight uint8 } @@ -529,17 +687,11 @@ func (a *Account) AddMapping(src, dest string) error { return a.AddWeightedMappings(src, NewMapDest(dest, 100)) } -// AddWeightedMapping will add in a weighted mappings for the destinations. -// TODO(dlc) - Allow cluster filtering +// AddWeightedMappings will add in a weighted mappings for the destinations. func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error { a.mu.Lock() defer a.mu.Unlock() - // We use this for selecting between multiple weighted destinations. - if a.prand == nil { - a.prand = rand.New(rand.NewSource(time.Now().UnixNano())) - } - if !IsValidSubject(src) { return ErrBadSubject } @@ -547,7 +699,7 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error { m := &mapping{src: src, wc: subjectHasWildcard(src), dests: make([]*destination, 0, len(dests)+1)} seen := make(map[string]struct{}) - var tw uint8 + var tw = make(map[string]uint8) for _, d := range dests { if _, ok := seen[d.Subject]; ok { return fmt.Errorf("duplicate entry for %q", d.Subject) @@ -556,27 +708,28 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error { if d.Weight > 100 { return fmt.Errorf("individual weights need to be <= 100") } - tw += d.Weight - if tw > 100 { + tw[d.Cluster] += d.Weight + if tw[d.Cluster] > 100 { return fmt.Errorf("total weight needs to be <= 100") } - if !IsValidSubject(d.Subject) { - return ErrBadSubject + err := ValidateMapping(src, d.Subject) + if err != nil { + return err } - tr, err := newTransform(src, d.Subject) + tr, err := NewSubjectTransform(src, d.Subject) if err != nil { return err } - if d.OptCluster == "" { + if d.Cluster == _EMPTY_ { m.dests = append(m.dests, &destination{tr, d.Weight}) } else { // We have a cluster scoped filter. if m.cdests == nil { m.cdests = make(map[string][]*destination) } - ad := m.cdests[d.OptCluster] + ad := m.cdests[d.Cluster] ad = append(ad, &destination{tr, d.Weight}) - m.cdests[d.OptCluster] = ad + m.cdests[d.Cluster] = ad } } @@ -594,7 +747,7 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error { // We need to make the appropriate markers for the wildcards etc. dest = transformTokenize(dest) } - tr, err := newTransform(src, dest) + tr, err := NewSubjectTransform(src, dest) if err != nil { return nil, err } @@ -604,7 +757,7 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error { } dests = append(dests, &destination{tr, aw}) } - sort.Slice(dests, func(i, j int) bool { return dests[i].weight < dests[j].weight }) + slices.SortFunc(dests, func(i, j *destination) int { return cmp.Compare(i.weight, j.weight) }) var lw uint8 for _, d := range dests { @@ -628,48 +781,29 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error { } // Replace an old one if it exists. - for i, m := range a.mappings { - if m.src == src { + for i, em := range a.mappings { + if em.src == src { a.mappings[i] = m return nil } } // If we did not replace add to the end. a.mappings = append(a.mappings, m) + a.hasMapped.Store(len(a.mappings) > 0) - return nil -} - -// Helper function to tokenize subjects with partial wildcards into formal transform destinations. -// e.g. foo.*.* -> foo.$1.$2 -func transformTokenize(subject string) string { - // We need to make the appropriate markers for the wildcards etc. - i := 1 - var nda []string - for _, token := range strings.Split(subject, tsep) { - if token == "*" { - nda = append(nda, fmt.Sprintf("$%d", i)) - i++ - } else { - nda = append(nda, token) - } - } - return strings.Join(nda, tsep) -} - -func transformUntokenize(subject string) (string, []string) { - var phs []string - var nda []string - - for _, token := range strings.Split(subject, tsep) { - if len(token) > 1 && token[0] == '$' && token[1] >= '1' && token[1] <= '9' { - phs = append(phs, token) - nda = append(nda, "*") - } else { - nda = append(nda, token) + // If we have connected leafnodes make sure to update. + if a.nleafs > 0 { + // Need to release because lock ordering is client -> account + a.mu.Unlock() + // Now grab the leaf list lock. We can hold client lock under this one. + a.lmu.RLock() + for _, lc := range a.lleafs { + lc.forceAddToSmap(src) } + a.lmu.RUnlock() + a.mu.Lock() } - return strings.Join(nda, tsep), phs + return nil } // RemoveMapping will remove an existing mapping. @@ -682,6 +816,19 @@ func (a *Account) RemoveMapping(src string) bool { a.mappings[i] = a.mappings[len(a.mappings)-1] a.mappings[len(a.mappings)-1] = nil // gc a.mappings = a.mappings[:len(a.mappings)-1] + a.hasMapped.Store(len(a.mappings) > 0) + // If we have connected leafnodes make sure to update. + if a.nleafs > 0 { + // Need to release because lock ordering is client -> account + a.mu.Unlock() + // Now grab the leaf list lock. We can hold client lock under this one. + a.lmu.RLock() + for _, lc := range a.lleafs { + lc.forceRemoveFromSmap(src) + } + a.lmu.RUnlock() + a.mu.Lock() + } return true } } @@ -693,21 +840,17 @@ func (a *Account) hasMappings() bool { if a == nil { return false } - a.mu.RLock() - n := len(a.mappings) - a.mu.RUnlock() - return n > 0 + return a.hasMapped.Load() } // This performs the logic to map to a new dest subject based on mappings. // Should only be called from processInboundClientMsg or service import processing. func (a *Account) selectMappedSubject(dest string) (string, bool) { - a.mu.RLock() - if len(a.mappings) == 0 { - a.mu.RUnlock() + if !a.hasMappings() { return dest, false } + a.mu.RLock() // In case we have to tokenize for subset matching. tsa := [32]string{} tts := tsa[:0] @@ -760,7 +903,7 @@ func (a *Account) selectMappedSubject(dest string) (string, bool) { if len(dests) == 1 && dests[0].weight == 100 { d = dests[0] } else { - w := uint8(a.prand.Int31n(100)) + w := uint8(fastrand.Uint32n(100)) for _, rm := range dests { if w < rm.weight { d = rm @@ -770,10 +913,10 @@ func (a *Account) selectMappedSubject(dest string) (string, bool) { } if d != nil { - if len(d.tr.dtpi) == 0 { + if len(d.tr.dtokmftokindexesargs) == 0 { ndest = d.tr.dest - } else if nsubj, err := d.tr.transform(tts); err == nil { - ndest = nsubj + } else { + ndest = d.tr.TransformTokenizedSubject(tts) } } @@ -782,8 +925,7 @@ func (a *Account) selectMappedSubject(dest string) (string, bool) { } // SubscriptionInterest returns true if this account has a matching subscription -// for the given `subject`. Works only for literal subjects. -// TODO: Add support for wildcards +// for the given `subject`. func (a *Account) SubscriptionInterest(subject string) bool { return a.Interest(subject) > 0 } @@ -793,8 +935,8 @@ func (a *Account) Interest(subject string) int { var nms int a.mu.RLock() if a.sl != nil { - res := a.sl.Match(subject) - nms = len(res.psubs) + len(res.qsubs) + np, nq := a.sl.NumInterest(subject) + nms = np + nq } a.mu.RUnlock() return nms @@ -805,32 +947,79 @@ func (a *Account) Interest(subject string) int { func (a *Account) addClient(c *client) int { a.mu.Lock() n := len(a.clients) - if a.clients != nil { - a.clients[c] = struct{}{} + + // Could come here earlier than the account is registered with the server. + // Make sure we can still track clients. + if a.clients == nil { + a.clients = make(map[*client]struct{}) } - added := n != len(a.clients) - if added { - if c.kind == SYSTEM { - a.sysclients++ - } else if c.kind == LEAF { - a.nleafs++ - a.lleafs = append(a.lleafs, c) - } + a.clients[c] = struct{}{} + + // If we did not add it, we are done + if n == len(a.clients) { + a.mu.Unlock() + return n + } + if c.kind != CLIENT && c.kind != LEAF { + a.sysclients++ + } else if c.kind == LEAF { + a.nleafs++ } a.mu.Unlock() - if c != nil && c.srv != nil && added { + // If we added a new leaf use the list lock and add it to the list. + if c.kind == LEAF { + a.lmu.Lock() + a.lleafs = append(a.lleafs, c) + a.lmu.Unlock() + } + + if c != nil && c.srv != nil { c.srv.accConnsUpdate(a) } return n } +// For registering clusters for remote leafnodes. +// We only register as the hub. +func (a *Account) registerLeafNodeCluster(cluster string) { + a.mu.Lock() + defer a.mu.Unlock() + if a.leafClusters == nil { + a.leafClusters = make(map[string]uint64) + } + a.leafClusters[cluster]++ +} + +// Check to see if we already have this cluster registered. +func (a *Account) hasLeafNodeCluster(cluster string) bool { + a.mu.RLock() + defer a.mu.RUnlock() + return a.leafClusters[cluster] > 0 +} + +// Check to see if this cluster is isolated, meaning the only one. +// Read Lock should be held. +func (a *Account) isLeafNodeClusterIsolated(cluster string) bool { + if cluster == _EMPTY_ { + return false + } + if len(a.leafClusters) > 1 { + return false + } + return a.leafClusters[cluster] == uint64(a.nleafs) +} + // Helper function to remove leaf nodes. If number of leafnodes gets large // this may need to be optimized out of linear search but believe number // of active leafnodes per account scope to be small and therefore cache friendly. -// Lock should be held on account. +// Lock should not be held on general account lock. func (a *Account) removeLeafNode(c *client) { + // Make sure we hold the list lock as well. + a.lmu.Lock() + defer a.lmu.Unlock() + ll := len(a.lleafs) for i, l := range a.lleafs { if l == c { @@ -850,53 +1039,87 @@ func (a *Account) removeClient(c *client) int { a.mu.Lock() n := len(a.clients) delete(a.clients, c) - removed := n != len(a.clients) - if removed { - if c.kind == SYSTEM { - a.sysclients-- - } else if c.kind == LEAF { - a.nleafs-- - a.removeLeafNode(c) + // If we did not actually remove it, we are done. + if n == len(a.clients) { + a.mu.Unlock() + return n + } + if c.kind != CLIENT && c.kind != LEAF { + a.sysclients-- + } else if c.kind == LEAF { + a.nleafs-- + // Need to do cluster accounting here. + // Do cluster accounting if we are a hub. + if c.isHubLeafNode() { + cluster := c.remoteCluster() + if count := a.leafClusters[cluster]; count > 1 { + a.leafClusters[cluster]-- + } else if count == 1 { + delete(a.leafClusters, cluster) + } } } a.mu.Unlock() - if c != nil && c.srv != nil && removed { - c.srv.mu.Lock() - doRemove := a != c.srv.gacc - c.srv.mu.Unlock() - if doRemove { - c.srv.accConnsUpdate(a) - } + if c.kind == LEAF { + a.removeLeafNode(c) + } + + if c != nil && c.srv != nil { + c.srv.accConnsUpdate(a) } + return n } -func (a *Account) randomClient() *client { - if a.ic != nil { - return a.ic +func setExportAuth(ea *exportAuth, subject string, accounts []*Account, accountPos uint) error { + if accountPos > 0 { + token := strings.Split(subject, tsep) + if len(token) < int(accountPos) || token[accountPos-1] != "*" { + return ErrInvalidSubject + } + } + ea.accountPos = accountPos + // empty means auth required but will be import token. + if accounts == nil { + return nil + } + if len(accounts) == 0 { + ea.tokenReq = true + return nil + } + if ea.approved == nil { + ea.approved = make(map[string]*Account, len(accounts)) } - var c *client - for c = range a.clients { - break + for _, acc := range accounts { + ea.approved[acc.Name] = acc } - return c + return nil } // AddServiceExport will configure the account with the defined export. func (a *Account) AddServiceExport(subject string, accounts []*Account) error { - return a.AddServiceExportWithResponse(subject, Singleton, accounts) + return a.addServiceExportWithResponseAndAccountPos(subject, Singleton, accounts, 0) +} + +// AddServiceExport will configure the account with the defined export. +func (a *Account) addServiceExportWithAccountPos(subject string, accounts []*Account, accountPos uint) error { + return a.addServiceExportWithResponseAndAccountPos(subject, Singleton, accounts, accountPos) } // AddServiceExportWithResponse will configure the account with the defined export and response type. func (a *Account) AddServiceExportWithResponse(subject string, respType ServiceRespType, accounts []*Account) error { + return a.addServiceExportWithResponseAndAccountPos(subject, respType, accounts, 0) +} + +// AddServiceExportWithresponse will configure the account with the defined export and response type. +func (a *Account) addServiceExportWithResponseAndAccountPos( + subject string, respType ServiceRespType, accounts []*Account, accountPos uint) error { if a == nil { return ErrMissingAccount } a.mu.Lock() - defer a.mu.Unlock() - if a.exports.services == nil { a.exports.services = make(map[string]*serviceExport) } @@ -911,25 +1134,26 @@ func (a *Account) AddServiceExportWithResponse(subject string, respType ServiceR se.respType = respType } - if accounts != nil { - // empty means auth required but will be import token. - if len(accounts) == 0 { - se.tokenReq = true - } else { - if se.approved == nil { - se.approved = make(map[string]*Account, len(accounts)) - } - for _, acc := range accounts { - se.approved[acc.Name] = acc - } + if accounts != nil || accountPos > 0 { + if err := setExportAuth(&se.exportAuth, subject, accounts, accountPos); err != nil { + a.mu.Unlock() + return err } } lrt := a.lowestServiceExportResponseTime() se.acc = a se.respThresh = DEFAULT_SERVICE_EXPORT_RESPONSE_THRESHOLD a.exports.services[subject] = se - if nlrt := a.lowestServiceExportResponseTime(); nlrt != lrt { - a.updateAllClientsServiceExportResponseTime(nlrt) + + var clients []*client + nlrt := a.lowestServiceExportResponseTime() + if nlrt != lrt && len(a.clients) > 0 { + clients = a.getClientsLocked() + } + // Need to release because lock ordering is client -> Account + a.mu.Unlock() + if len(clients) > 0 { + updateAllClientsServiceExportResponseTime(clients, nlrt) } return nil } @@ -993,12 +1217,14 @@ func (a *Account) TrackServiceExportWithSampling(service, results string, sampli } // Now track down the imports and add in latency as needed to enable. - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) acc.mu.Lock() - for _, im := range acc.imports.services { - if im != nil && im.acc.Name == a.Name && subjectIsSubsetMatch(im.to, service) { - im.latency = ea.latency + for _, ims := range acc.imports.services { + for _, im := range ims { + if im != nil && im.acc.Name == a.Name && subjectIsSubsetMatch(im.to, service) { + im.latency = ea.latency + } } } acc.mu.Unlock() @@ -1015,7 +1241,7 @@ func (a *Account) UnTrackServiceExport(service string) { } a.mu.Lock() - if a == nil || a.exports.services == nil { + if a.exports.services == nil { a.mu.Unlock() return } @@ -1034,13 +1260,15 @@ func (a *Account) UnTrackServiceExport(service string) { } // Now track down the imports and clean them up. - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) acc.mu.Lock() - for _, im := range acc.imports.services { - if im != nil && im.acc.Name == a.Name { - if subjectIsSubsetMatch(im.to, service) { - im.latency, im.m1 = nil, nil + for _, ims := range acc.imports.services { + for _, im := range ims { + if im != nil && im.acc.Name == a.Name { + if subjectIsSubsetMatch(im.to, service) { + im.latency, im.m1 = nil, nil + } } } } @@ -1097,11 +1325,10 @@ func (a *Account) IsExportServiceTracking(service string) bool { // designate to share the additional information in the service import. type ServiceLatency struct { TypedEvent - Status int `json:"status"` Error string `json:"description,omitempty"` - Requestor LatencyClient `json:"requestor,omitempty"` - Responder LatencyClient `json:"responder,omitempty"` + Requestor *ClientInfo `json:"requestor,omitempty"` + Responder *ClientInfo `json:"responder,omitempty"` RequestHeader http.Header `json:"header,omitempty"` // only contains header(s) triggering the measurement RequestStart time.Time `json:"start"` ServiceLatency time.Duration `json:"service"` @@ -1112,26 +1339,9 @@ type ServiceLatency struct { // ServiceLatencyType is the NATS Event Type for ServiceLatency const ServiceLatencyType = "io.nats.server.metric.v1.service_latency" -// LatencyClient is the JSON message structure assigned to requestors and responders. -// Note that for a requestor, the only information shared by default is the RTT used -// to calculate the total latency. The requestor's account can designate to share -// the additional information in the service import. -type LatencyClient struct { - Account string `json:"acc"` - RTT time.Duration `json:"rtt"` - Start time.Time `json:"start,omitempty"` - User string `json:"user,omitempty"` - Name string `json:"name,omitempty"` - Lang string `json:"lang,omitempty"` - Version string `json:"ver,omitempty"` - IP string `json:"ip,omitempty"` - CID uint64 `json:"cid,omitempty"` - Server string `json:"server,omitempty"` -} - // NATSTotalTime is a helper function that totals the NATS latencies. -func (nl *ServiceLatency) NATSTotalTime() time.Duration { - return nl.Requestor.RTT + nl.Responder.RTT + nl.SystemLatency +func (m1 *ServiceLatency) NATSTotalTime() time.Duration { + return m1.Requestor.RTT + m1.Responder.RTT + m1.SystemLatency } // Merge function to merge m1 and m2 (requestor and responder) measurements @@ -1142,7 +1352,11 @@ func (nl *ServiceLatency) NATSTotalTime() time.Duration { // m1 TotalLatency is correct, so use that. // Will use those to back into NATS latency. func (m1 *ServiceLatency) merge(m2 *ServiceLatency) { - m1.SystemLatency = m1.ServiceLatency - (m2.ServiceLatency + m2.Responder.RTT) + rtt := time.Duration(0) + if m2.Responder != nil { + rtt = m2.Responder.RTT + } + m1.SystemLatency = m1.ServiceLatency - (m2.ServiceLatency + rtt) m1.ServiceLatency = m2.ServiceLatency m1.Responder = m2.Responder sanitizeLatencyMetric(m1) @@ -1203,9 +1417,7 @@ func (a *Account) sendReplyInterestLostTrackLatency(si *serviceImport) { Error: "Request Timeout", } a.mu.RLock() - rc := si.rc - share := si.share - ts := si.ts + rc, share, ts := si.rc, si.share, si.ts sl.RequestHeader = si.trackingHdr a.mu.RUnlock() if rc != nil { @@ -1218,15 +1430,17 @@ func (a *Account) sendReplyInterestLostTrackLatency(si *serviceImport) { func (a *Account) sendBackendErrorTrackingLatency(si *serviceImport, reason rsiReason) { sl := &ServiceLatency{} a.mu.RLock() - rc := si.rc - share := si.share - ts := si.ts + rc, share, ts := si.rc, si.share, si.ts sl.RequestHeader = si.trackingHdr a.mu.RUnlock() if rc != nil { sl.Requestor = rc.getClientInfo(share) } - sl.RequestStart = time.Unix(0, ts-int64(sl.Requestor.RTT)).UTC() + var reqRTT time.Duration + if sl.Requestor != nil { + reqRTT = sl.Requestor.RTT + } + sl.RequestStart = time.Unix(0, ts-int64(reqRTT)).UTC() if reason == rsiNoDelivery { sl.Status = 503 sl.Error = "Service Unavailable" @@ -1237,12 +1451,15 @@ func (a *Account) sendBackendErrorTrackingLatency(si *serviceImport, reason rsiR a.sendLatencyResult(si, sl) } -// sendTrackingMessage will send out the appropriate tracking information for the +// sendTrackingLatency will send out the appropriate tracking information for the // service request/response latency. This is called when the requestor's server has // received the response. // TODO(dlc) - holding locks for RTTs may be too much long term. Should revisit. func (a *Account) sendTrackingLatency(si *serviceImport, responder *client) bool { - if si.rc == nil { + a.mu.RLock() + rc := si.rc + a.mu.RUnlock() + if rc == nil { return true } @@ -1255,10 +1472,17 @@ func (a *Account) sendTrackingLatency(si *serviceImport, responder *client) bool Requestor: requestor.getClientInfo(si.share), Responder: responder.getClientInfo(true), } - sl.RequestStart = time.Unix(0, si.ts-int64(sl.Requestor.RTT)).UTC() - sl.ServiceLatency = serviceRTT - sl.Responder.RTT - sl.TotalLatency = sl.Requestor.RTT + serviceRTT - if sl.Responder.RTT > 0 { + var respRTT, reqRTT time.Duration + if sl.Responder != nil { + respRTT = sl.Responder.RTT + } + if sl.Requestor != nil { + reqRTT = sl.Requestor.RTT + } + sl.RequestStart = time.Unix(0, si.ts-int64(reqRTT)).UTC() + sl.ServiceLatency = serviceRTT - respRTT + sl.TotalLatency = reqRTT + serviceRTT + if respRTT > 0 { sl.SystemLatency = time.Since(ts) sl.TotalLatency += sl.SystemLatency } @@ -1300,9 +1524,8 @@ func (a *Account) sendTrackingLatency(si *serviceImport, responder *client) bool // This will check to make sure our response lower threshold is set // properly in any clients doing rrTracking. -// Lock should be held. -func (a *Account) updateAllClientsServiceExportResponseTime(lrt time.Duration) { - for c := range a.clients { +func updateAllClientsServiceExportResponseTime(clients []*client, lrt time.Duration) { + for _, c := range clients { c.mu.Lock() if c.rrTracking != nil && lrt != c.rrTracking.lrt { c.rrTracking.lrt = lrt @@ -1318,7 +1541,7 @@ func (a *Account) updateAllClientsServiceExportResponseTime(lrt time.Duration) { // Read lock should be held. func (a *Account) lowestServiceExportResponseTime() time.Duration { // Lowest we will allow is 5 minutes. Its an upper bound for this function. - lrt := time.Duration(5 * time.Minute) + lrt := 5 * time.Minute for _, se := range a.exports.services { if se.respThresh < lrt { lrt = se.respThresh @@ -1329,11 +1552,17 @@ func (a *Account) lowestServiceExportResponseTime() time.Duration { // AddServiceImportWithClaim will add in the service import via the jwt claim. func (a *Account) AddServiceImportWithClaim(destination *Account, from, to string, imClaim *jwt.Import) error { + return a.addServiceImportWithClaim(destination, from, to, imClaim, false) +} + +// addServiceImportWithClaim will add in the service import via the jwt claim. +// It will also skip the authorization check in cases where internal is true +func (a *Account) addServiceImportWithClaim(destination *Account, from, to string, imClaim *jwt.Import, internal bool) error { if destination == nil { return ErrMissingAccount } // Empty means use from. - if to == "" { + if to == _EMPTY_ { to = from } if !IsValidSubject(from) || !IsValidSubject(to) { @@ -1341,16 +1570,23 @@ func (a *Account) AddServiceImportWithClaim(destination *Account, from, to strin } // First check to see if the account has authorized us to route to the "to" subject. - if !destination.checkServiceImportAuthorized(a, to, imClaim) { + if !internal && !destination.checkServiceImportAuthorized(a, to, imClaim) { return ErrServiceImportAuthorization } // Check if this introduces a cycle before proceeding. - if err := a.serviceImportFormsCycle(destination, from); err != nil { + // From will be the mapped subject. + // If the 'to' has a wildcard make sure we pre-transform the 'from' before we check for cycles, e.g. '$1' + fromT := from + if subjectHasWildcard(to) { + fromT, _ = transformUntokenize(from) + } + if err := a.serviceImportFormsCycle(destination, fromT); err != nil { return err } _, err := a.addServiceImport(destination, from, to, imClaim) + return err } @@ -1365,21 +1601,23 @@ func (a *Account) checkServiceImportsForCycles(from string, visited map[string]b return ErrCycleSearchDepth } a.mu.RLock() - for _, si := range a.imports.services { - if SubjectsCollide(from, si.to) { - a.mu.RUnlock() - if visited[si.acc.Name] { - return ErrImportFormsCycle - } - // Push ourselves and check si.acc - visited[a.Name] = true - if subjectIsSubsetMatch(si.from, from) { - from = si.from - } - if err := si.acc.checkServiceImportsForCycles(from, visited); err != nil { - return err + for _, sis := range a.imports.services { + for _, si := range sis { + if SubjectsCollide(from, si.to) { + a.mu.RUnlock() + if visited[si.acc.Name] { + return ErrImportFormsCycle + } + // Push ourselves and check si.acc + visited[a.Name] = true + if subjectIsSubsetMatch(si.from, from) { + from = si.from + } + if err := si.acc.checkServiceImportsForCycles(from, visited); err != nil { + return err + } + a.mu.RLock() } - a.mu.RLock() } } a.mu.RUnlock() @@ -1390,6 +1628,16 @@ func (a *Account) streamImportFormsCycle(dest *Account, to string) error { return dest.checkStreamImportsForCycles(to, map[string]bool{a.Name: true}) } +// Lock should be held. +func (a *Account) hasServiceExportMatching(to string) bool { + for subj := range a.exports.services { + if subjectIsSubsetMatch(to, subj) { + return true + } + } + return false +} + // Lock should be held. func (a *Account) hasStreamExportMatching(to string) bool { for subj := range a.exports.streams { @@ -1436,15 +1684,25 @@ func (a *Account) checkStreamImportsForCycles(to string, visited map[string]bool // SetServiceImportSharing will allow sharing of information about requests with the export account. // Used for service latency tracking at the moment. func (a *Account) SetServiceImportSharing(destination *Account, to string, allow bool) error { + return a.setServiceImportSharing(destination, to, true, allow) +} + +// setServiceImportSharing will allow sharing of information about requests with the export account. +func (a *Account) setServiceImportSharing(destination *Account, to string, check, allow bool) error { a.mu.Lock() defer a.mu.Unlock() - if a.isClaimAccount() { + if check && a.isClaimAccount() { return fmt.Errorf("claim based accounts can not be updated directly") } - for _, si := range a.imports.services { - if si.acc == destination && si.to == to { - si.share = allow - return nil + // We can't use getServiceImportForAccountLocked() here since we are looking + // for the service import with the si.to == to, which may not be the key + // for the service import in the map. + for _, sis := range a.imports.services { + for _, si := range sis { + if si.acc.Name == destination.Name && si.to == to { + si.share = allow + return nil + } } } return fmt.Errorf("service import not found") @@ -1468,17 +1726,17 @@ func (a *Account) NumPendingReverseResponses() int { // NumPendingAllResponses return the number of all responses outstanding for service exports. func (a *Account) NumPendingAllResponses() int { - return a.NumPendingResponses("") + return a.NumPendingResponses(_EMPTY_) } -// NumResponsesPending returns the number of responses outstanding for service exports +// NumPendingResponses returns the number of responses outstanding for service exports // on this account. An empty filter string returns all responses regardless of which export. // If you specify the filter we will only return ones that are for that export. // NOTE this is only for what this server is tracking. func (a *Account) NumPendingResponses(filter string) int { a.mu.RLock() defer a.mu.RUnlock() - if filter == "" { + if filter == _EMPTY_ { return len(a.exports.responses) } se := a.getServiceExport(filter) @@ -1517,33 +1775,77 @@ func (a *Account) removeRespServiceImport(si *serviceImport, reason rsiReason) { } a.mu.Lock() + c := a.ic delete(a.exports.responses, si.from) - dest := si.acc - to := si.to - tracking := si.tracking - rc := si.rc + dest, to, tracking, rc, didDeliver := si.acc, si.to, si.tracking, si.rc, si.didDeliver a.mu.Unlock() - if tracking && rc != nil { + // If we have a sid make sure to unsub. + if len(si.sid) > 0 && c != nil { + c.processUnsub(si.sid) + } + + if tracking && rc != nil && !didDeliver { a.sendBackendErrorTrackingLatency(si, reason) } dest.checkForReverseEntry(to, si, false) } +func (a *Account) getServiceImportForAccountLocked(dstAccName, subject string) *serviceImport { + sis, ok := a.imports.services[subject] + if !ok { + return nil + } + if len(sis) == 1 && sis[0].acc.Name == dstAccName { + return sis[0] + } + for _, si := range sis { + if si.acc.Name == dstAccName { + return si + } + } + return nil +} + // removeServiceImport will remove the route by subject. -func (a *Account) removeServiceImport(subject string) { +func (a *Account) removeServiceImport(dstAccName, subject string) { a.mu.Lock() - si, ok := a.imports.services[subject] - delete(a.imports.services, subject) - + sis, ok := a.imports.services[subject] + if !ok { + a.mu.Unlock() + return + } + var si *serviceImport + if len(sis) == 1 { + si = sis[0] + if si.acc.Name != dstAccName { + si = nil + } else { + delete(a.imports.services, subject) + } + } else { + for i, esi := range sis { + if esi.acc.Name == dstAccName { + si = esi + last := len(sis) - 1 + if i != last { + sis[i] = sis[last] + } + sis = sis[:last] + a.imports.services[subject] = sis + break + } + } + } + if si == nil { + a.mu.Unlock() + return + } var sid []byte c := a.ic - - if ok && si != nil { - if a.ic != nil && si.sid != nil { - sid = si.sid - } + if c != nil && si.sid != nil { + sid = si.sid } a.mu.Unlock() @@ -1567,37 +1869,51 @@ func (a *Account) addReverseRespMapEntry(acc *Account, reply, from string) { // checkForReverseEntries is for when we are trying to match reverse entries to a wildcard. // This will be called from checkForReverseEntry when the reply arg is a wildcard subject. // This will usually be called in a go routine since we need to walk all the entries. -func (a *Account) checkForReverseEntries(reply string, checkInterest bool) { - a.mu.RLock() - if len(a.imports.rrMap) == 0 { - a.mu.RUnlock() +func (a *Account) checkForReverseEntries(reply string, checkInterest, recursed bool) { + if subjectIsLiteral(reply) { + a._checkForReverseEntry(reply, nil, checkInterest, recursed) return } - if subjectIsLiteral(reply) { + a.mu.RLock() + if len(a.imports.rrMap) == 0 { a.mu.RUnlock() - a.checkForReverseEntry(reply, nil, checkInterest) return } - var _rs [32]string + var _rs [64]string rs := _rs[:0] + if n := len(a.imports.rrMap); n > cap(rs) { + rs = make([]string, 0, n) + } for k := range a.imports.rrMap { - if subjectIsSubsetMatch(k, reply) { - rs = append(rs, k) - } + rs = append(rs, k) } a.mu.RUnlock() - for _, reply := range rs { - a.checkForReverseEntry(reply, nil, checkInterest) + tsa := [32]string{} + tts := tokenizeSubjectIntoSlice(tsa[:0], reply) + + rsa := [32]string{} + for _, r := range rs { + rts := tokenizeSubjectIntoSlice(rsa[:0], r) + // isSubsetMatchTokenized is heavy so make sure we do this without the lock. + if isSubsetMatchTokenized(rts, tts) { + a._checkForReverseEntry(r, nil, checkInterest, recursed) + } } } // This checks for any response map entries. If you specify an si we will only match and // clean up for that one, otherwise we remove them all. func (a *Account) checkForReverseEntry(reply string, si *serviceImport, checkInterest bool) { + a._checkForReverseEntry(reply, si, checkInterest, false) +} + +// Callers should use checkForReverseEntry instead. This function exists to help prevent +// infinite recursion. +func (a *Account) _checkForReverseEntry(reply string, si *serviceImport, checkInterest, recursed bool) { a.mu.RLock() if len(a.imports.rrMap) == 0 { a.mu.RUnlock() @@ -1605,13 +1921,28 @@ func (a *Account) checkForReverseEntry(reply string, si *serviceImport, checkInt } if subjectHasWildcard(reply) { - a.mu.RUnlock() - go a.checkForReverseEntries(reply, checkInterest) + if recursed { + // If we have reached this condition then it is because the reverse entries also + // contain wildcards (that shouldn't happen but a client *could* provide an inbox + // prefix that is illegal because it ends in a wildcard character), at which point + // we will end up with infinite recursion between this func and checkForReverseEntries. + // To avoid a stack overflow panic, we'll give up instead. + a.mu.RUnlock() + return + } + + doInline := len(a.imports.rrMap) <= 64 + a.mu.RUnlock() + + if doInline { + a.checkForReverseEntries(reply, checkInterest, true) + } else { + go a.checkForReverseEntries(reply, checkInterest, true) + } return } - sres := a.imports.rrMap[reply] - if sres == nil { + if sres := a.imports.rrMap[reply]; sres == nil { a.mu.RUnlock() return } @@ -1623,7 +1954,7 @@ func (a *Account) checkForReverseEntry(reply string, si *serviceImport, checkInt // Note that if we are here reply has to be a literal subject. if checkInterest { // If interest still exists we can not clean these up yet. - if rr := a.sl.Match(reply); len(rr.psubs)+len(rr.qsubs) > 0 { + if a.sl.HasInterest(reply) { a.mu.RUnlock() return } @@ -1632,9 +1963,11 @@ func (a *Account) checkForReverseEntry(reply string, si *serviceImport, checkInt // Delete the appropriate entries here based on optional si. a.mu.Lock() + // We need a new lookup here because we have released the lock. + sres := a.imports.rrMap[reply] if si == nil { delete(a.imports.rrMap, reply) - } else { + } else if sres != nil { // Find the one we are looking for.. for i, sre := range sres { if sre.msub == si.from { @@ -1653,17 +1986,24 @@ func (a *Account) checkForReverseEntry(reply string, si *serviceImport, checkInt // If we are here we no longer have interest and we have // response entries that we should clean up. if si == nil { + // sres is now known to have been removed from a.imports.rrMap, so we + // can safely (data race wise) iterate through. for _, sre := range sres { acc := sre.acc var trackingCleanup bool var rsi *serviceImport acc.mu.Lock() + c := acc.ic if rsi = acc.exports.responses[sre.msub]; rsi != nil && !rsi.didDeliver { delete(acc.exports.responses, rsi.from) trackingCleanup = rsi.tracking && rsi.rc != nil } acc.mu.Unlock() - + // If we are doing explicit subs for all responses (e.g. bound to leafnode) + // we will have a non-empty sid here. + if rsi != nil && len(rsi.sid) > 0 && c != nil { + c.processUnsub(rsi.sid) + } if trackingCleanup { acc.sendReplyInterestLostTrackLatency(rsi) } @@ -1671,78 +2011,101 @@ func (a *Account) checkForReverseEntry(reply string, si *serviceImport, checkInt } } +// Checks to see if a potential service import subject is already overshadowed. +func (a *Account) serviceImportShadowed(from string) bool { + a.mu.RLock() + defer a.mu.RUnlock() + if a.imports.services[from] != nil { + return true + } + // We did not find a direct match, so check individually. + for subj := range a.imports.services { + if subjectIsSubsetMatch(from, subj) { + return true + } + } + return false +} + // Internal check to see if a service import exists. -func (a *Account) serviceImportExists(dest *Account, from string) bool { +func (a *Account) serviceImportExists(dstAccName, from string) bool { a.mu.RLock() - dup := a.imports.services[from] + dup := a.getServiceImportForAccountLocked(dstAccName, from) a.mu.RUnlock() return dup != nil } // Add a service import. -// This does no checks and should only be called by the msg processing code. Use -// AddServiceImport from above if responding to user input or config changes, etc. +// This does no checks and should only be called by the msg processing code. +// Use AddServiceImport from above if responding to user input or config changes, etc. func (a *Account) addServiceImport(dest *Account, from, to string, claim *jwt.Import) (*serviceImport, error) { rt := Singleton var lat *serviceLatency + if dest == nil { + return nil, ErrMissingAccount + } + + var atrc bool dest.mu.RLock() se := dest.getServiceExport(to) if se != nil { rt = se.respType lat = se.latency + atrc = se.atrc } - s := dest.srv + destAccName := dest.Name dest.mu.RUnlock() - // Track if this maps us to the system account. - var isSysAcc bool - if s != nil { - s.mu.Lock() - if s.sys != nil && dest == s.sys.account { - isSysAcc = true - } - s.mu.Unlock() - } - a.mu.Lock() if a.imports.services == nil { - a.imports.services = make(map[string]*serviceImport) - } else if dup := a.imports.services[from]; dup != nil { + a.imports.services = make(map[string][]*serviceImport) + } else if dup := a.getServiceImportForAccountLocked(destAccName, from); dup != nil { a.mu.Unlock() return nil, fmt.Errorf("duplicate service import subject %q, previously used in import for account %q, subject %q", from, dup.acc.Name, dup.to) } - if to == "" { + if to == _EMPTY_ { to = from } // Check to see if we have a wildcard var ( usePub bool - tr *transform + tr *subjectTransform err error ) + if subjectHasWildcard(to) { // If to and from match, then we use the published subject. if to == from { usePub = true } else { - from, _ = transformUntokenize(from) - // Create a transform - if tr, err = newTransform(from, transformTokenize(to)); err != nil { + to, _ = transformUntokenize(to) + // Create a transform. Do so in reverse such that $ symbols only exist in to + if tr, err = NewSubjectTransformStrict(to, transformTokenize(from)); err != nil { a.mu.Unlock() - return nil, fmt.Errorf("failed to create mapping transform for service import subject %q to %q: %v", + return nil, fmt.Errorf("failed to create mapping transform for service import subject from %q to %q: %v", from, to, err) + } else { + // un-tokenize and reverse transform so we get the transform needed + from, _ = transformUntokenize(from) + tr = tr.reverse() } } } - si := &serviceImport{dest, claim, se, nil, from, to, "", tr, 0, rt, lat, nil, nil, usePub, false, false, false, false, false, isSysAcc, nil} - a.imports.services[from] = si + var share bool + if claim != nil { + share = claim.Share + } + si := &serviceImport{dest, claim, se, nil, from, to, tr, 0, rt, lat, nil, nil, usePub, false, false, share, false, false, atrc, nil} + sis := a.imports.services[from] + sis = append(sis, si) + a.imports.services[from] = sis a.mu.Unlock() if err := a.addServiceImportSub(si); err != nil { - a.removeServiceImport(si.from) + a.removeServiceImport(destAccName, si.from) return nil, err } return si, nil @@ -1760,10 +2123,25 @@ func (a *Account) internalClient() *client { // Internal account scoped subscriptions. func (a *Account) subscribeInternal(subject string, cb msgHandler) (*subscription, error) { + return a.subscribeInternalEx(subject, cb, false) +} + +// Unsubscribe from an internal account subscription. +func (a *Account) unsubscribeInternal(sub *subscription) { + if ic := a.internalClient(); ic != nil { + ic.processUnsub(sub.sid) + } +} + +// Creates internal subscription for service import responses. +func (a *Account) subscribeServiceImportResponse(subject string) (*subscription, error) { + return a.subscribeInternalEx(subject, a.processServiceImportResponse, true) +} + +func (a *Account) subscribeInternalEx(subject string, cb msgHandler, ri bool) (*subscription, error) { a.mu.Lock() - c := a.internalClient() a.isid++ - sid := strconv.FormatUint(a.isid, 10) + c, sid := a.internalClient(), strconv.FormatUint(a.isid, 10) a.mu.Unlock() // This will happen in parsing when the account has not been properly setup. @@ -1771,7 +2149,7 @@ func (a *Account) subscribeInternal(subject string, cb msgHandler) (*subscriptio return nil, fmt.Errorf("no internal account client") } - return c.processSub([]byte(subject), nil, []byte(sid), cb, false) + return c.processSubEx([]byte(subject), nil, []byte(sid), cb, false, false, ri) } // This will add an account subscription that matches the "from" from a service import entry. @@ -1793,21 +2171,31 @@ func (a *Account) addServiceImportSub(si *serviceImport) error { subject := si.from a.mu.Unlock() - cb := func(sub *subscription, c *client, subject, reply string, msg []byte) { - c.processServiceImport(si, a, msg) + cb := func(sub *subscription, c *client, acc *Account, subject, reply string, msg []byte) { + c.pa.delivered = c.processServiceImport(si, acc, msg) } - _, err := c.processSub([]byte(subject), nil, []byte(sid), cb, true) - return err + sub, err := c.processSubEx([]byte(subject), nil, []byte(sid), cb, true, true, false) + if err != nil { + return err + } + // Leafnodes introduce a new way to introduce messages into the system. Therefore forward import subscription + // This is similar to what initLeafNodeSmapAndSendSubs does + // TODO we need to consider performing this update as we get client subscriptions. + // This behavior would result in subscription propagation only where actually used. + a.updateLeafNodes(sub, 1) + return nil } // Remove all the subscriptions associated with service imports. func (a *Account) removeAllServiceImportSubs() { a.mu.RLock() var sids [][]byte - for _, si := range a.imports.services { - if si.sid != nil { - sids = append(sids, si.sid) - si.sid = nil + for _, sis := range a.imports.services { + for _, si := range sis { + if si.sid != nil { + sids = append(sids, si.sid) + si.sid = nil + } } } c := a.ic @@ -1825,7 +2213,14 @@ func (a *Account) removeAllServiceImportSubs() { // Add in subscriptions for all registered service imports. func (a *Account) addAllServiceImportSubs() { - for _, si := range a.imports.services { + var sis [32]*serviceImport + serviceImports := sis[:0] + a.mu.RLock() + for _, sis := range a.imports.services { + serviceImports = append(serviceImports, sis...) + } + a.mu.RUnlock() + for _, si := range serviceImports { a.addServiceImportSub(si) } } @@ -1931,9 +2326,15 @@ func shouldSample(l *serviceLatency, c *client) (bool, http.Header) { } return true, http.Header{trcB3: b3} // sampling allowed or left to recipient of header } else if tId := h[trcCtx]; len(tId) != 0 { + var sample bool // sample 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01 tk := strings.Split(tId[0], "-") - if len(tk) == 4 && len([]byte(tk[3])) == 2 && tk[3] == "01" { + if len(tk) == 4 && len([]byte(tk[3])) == 2 { + if hexVal, err := strconv.ParseInt(tk[3], 16, 8); err == nil { + sample = hexVal&0x1 == 0x1 + } + } + if sample { return true, newTraceCtxHeader(h, tId) } else { return false, nil @@ -1945,7 +2346,6 @@ func shouldSample(l *serviceLatency, c *client) (bool, http.Header) { // Used to mimic client like replies. const ( replyPrefix = "_R_." - trackSuffix = ".T" replyPrefixLen = len(replyPrefix) baseServerLen = 10 replyLen = 6 @@ -1955,9 +2355,9 @@ const ( ) // This is where all service export responses are handled. -func (a *Account) processServiceImportResponse(sub *subscription, c *client, subject, reply string, msg []byte) { +func (a *Account) processServiceImportResponse(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { a.mu.RLock() - if a.expired || len(a.exports.responses) == 0 { + if a.expired.Load() || len(a.exports.responses) == 0 { a.mu.RUnlock() return } @@ -1973,32 +2373,18 @@ func (a *Account) processServiceImportResponse(sub *subscription, c *client, sub c.processServiceImport(si, a, msg) } -// Will create a wildcard subscription to handle interest graph propagation for all -// service replies. -// Lock should not be held. -func (a *Account) createRespWildcard() []byte { - a.mu.Lock() - if a.prand == nil { - a.prand = rand.New(rand.NewSource(time.Now().UnixNano())) - } +// Will create the response prefix for fast generation of responses. +// A wildcard subscription may be used handle interest graph propagation +// for all service replies, unless we are bound to a leafnode. +// Lock should be held. +func (a *Account) createRespWildcard() { var b = [baseServerLen]byte{'_', 'R', '_', '.'} - rn := a.prand.Int63() + rn := fastrand.Uint64() for i, l := replyPrefixLen, rn; i < len(b); i++ { b[i] = digits[l%base] l /= base } a.siReply = append(b[:], '.') - pre := a.siReply - wcsub := append(a.siReply, '>') - c := a.internalClient() - a.isid++ - sid := strconv.FormatUint(a.isid, 10) - a.mu.Unlock() - - // Create subscription and internal callback for all the wildcard response subjects. - c.processSub(wcsub, nil, []byte(sid), a.processServiceImportResponse, false) - - return pre } // Test whether this is a tracked reply. @@ -2010,17 +2396,26 @@ func isTrackedReply(reply []byte) bool { // Generate a new service reply from the wildcard prefix. // FIXME(dlc) - probably do not have to use rand here. about 25ns per. func (a *Account) newServiceReply(tracking bool) []byte { - a.mu.RLock() - replyPre := a.siReply + a.mu.Lock() s := a.srv - a.mu.RUnlock() + rn := fastrand.Uint64() + + // Check if we need to create the reply here. + var createdSiReply bool + if a.siReply == nil { + a.createRespWildcard() + createdSiReply = true + } + replyPre := a.siReply + a.mu.Unlock() - if replyPre == nil { - replyPre = a.createRespWildcard() + // If we created the siReply and we are not bound to a leafnode + // we need to do the wildcard subscription. + if createdSiReply { + a.subscribeServiceImportResponse(string(append(replyPre, '>'))) } var b [replyLen]byte - rn := a.prand.Int63() for i, l := 0, rn; i < len(b); i++ { b[i] = digits[l%base] l /= base @@ -2037,6 +2432,7 @@ func (a *Account) newServiceReply(tracking bool) []byte { reply = append(reply, s.sys.shash...) reply = append(reply, '.', 'T') } + return reply } @@ -2045,7 +2441,7 @@ func (si *serviceImport) isRespServiceImport() bool { return si != nil && si.response } -// Sets the response theshold timer for a service export. +// Sets the response threshold timer for a service export. // Account lock should be held func (se *serviceExport) setResponseThresholdTimer() { if se.rtmr != nil { @@ -2069,9 +2465,7 @@ func (se *serviceExport) clearResponseThresholdTimer() bool { func (se *serviceExport) checkExpiredResponses() { acc := se.acc if acc == nil { - acc.mu.Lock() se.clearResponseThresholdTimer() - acc.mu.Unlock() return } @@ -2127,22 +2521,43 @@ func (a *Account) ServiceExportResponseThreshold(export string) (time.Duration, // from a service export responder. func (a *Account) SetServiceExportResponseThreshold(export string, maxTime time.Duration) error { a.mu.Lock() - defer a.mu.Unlock() if a.isClaimAccount() { + a.mu.Unlock() return fmt.Errorf("claim based accounts can not be updated directly") } lrt := a.lowestServiceExportResponseTime() se := a.getServiceExport(export) if se == nil { + a.mu.Unlock() return fmt.Errorf("no export defined for %q", export) } se.respThresh = maxTime - if nlrt := a.lowestServiceExportResponseTime(); nlrt != lrt { - a.updateAllClientsServiceExportResponseTime(nlrt) + + var clients []*client + nlrt := a.lowestServiceExportResponseTime() + if nlrt != lrt && len(a.clients) > 0 { + clients = a.getClientsLocked() + } + // Need to release because lock ordering is client -> Account + a.mu.Unlock() + if len(clients) > 0 { + updateAllClientsServiceExportResponseTime(clients, nlrt) } return nil } +func (a *Account) SetServiceExportAllowTrace(export string, allowTrace bool) error { + a.mu.Lock() + se := a.getServiceExport(export) + if se == nil { + a.mu.Unlock() + return fmt.Errorf("no export defined for %q", export) + } + se.atrc = allowTrace + a.mu.Unlock() + return nil +} + // This is for internal service import responses. func (a *Account) addRespServiceImport(dest *Account, to string, osi *serviceImport, tracking bool, header http.Header) *serviceImport { nrr := string(osi.acc.newServiceReply(tracking)) @@ -2152,7 +2567,7 @@ func (a *Account) addRespServiceImport(dest *Account, to string, osi *serviceImp // dest is the requestor's account. a is the service responder with the export. // Marked as internal here, that is how we distinguish. - si := &serviceImport{dest, nil, osi.se, nil, nrr, to, osi.to, nil, 0, rt, nil, nil, nil, false, true, false, osi.share, false, false, false, nil} + si := &serviceImport{dest, nil, osi.se, nil, nrr, to, nil, 0, rt, nil, nil, nil, false, true, false, osi.share, false, false, false, nil} if a.exports.responses == nil { a.exports.responses = make(map[string]*serviceImport) @@ -2161,7 +2576,9 @@ func (a *Account) addRespServiceImport(dest *Account, to string, osi *serviceImp // Always grab time and make sure response threshold timer is running. si.ts = time.Now().UnixNano() - osi.se.setResponseThresholdTimer() + if osi.se != nil { + osi.se.setResponseThresholdTimer() + } if rt == Singleton && tracking { si.latency = osi.latency @@ -2170,10 +2587,6 @@ func (a *Account) addRespServiceImport(dest *Account, to string, osi *serviceImp } a.mu.Unlock() - // We do not do individual subscriptions here like we do on configured imports. - // We have an internal callback for all responses inbound to this account and - // will process appropriately there. This does not pollute the sublist and the caches. - // We do add in the reverse map such that we can detect loss of interest and do proper // cleanup of this si as interest goes away. dest.addReverseRespMapEntry(a, to, nrr) @@ -2183,6 +2596,10 @@ func (a *Account) addRespServiceImport(dest *Account, to string, osi *serviceImp // AddStreamImportWithClaim will add in the stream import from a specific account with optional token. func (a *Account) AddStreamImportWithClaim(account *Account, from, prefix string, imClaim *jwt.Import) error { + return a.addStreamImportWithClaim(account, from, prefix, false, imClaim) +} + +func (a *Account) addStreamImportWithClaim(account *Account, from, prefix string, allowTrace bool, imClaim *jwt.Import) error { if account == nil { return ErrMissingAccount } @@ -2194,7 +2611,7 @@ func (a *Account) AddStreamImportWithClaim(account *Account, from, prefix string // Check prefix if it exists and make sure its a literal. // Append token separator if not already present. - if prefix != "" { + if prefix != _EMPTY_ { // Make sure there are no wildcards here, this prefix needs to be a literal // since it will be prepended to a publish subject. if !subjectIsLiteral(prefix) { @@ -2205,7 +2622,7 @@ func (a *Account) AddStreamImportWithClaim(account *Account, from, prefix string } } - return a.AddMappedStreamImportWithClaim(account, from, prefix+from, imClaim) + return a.addMappedStreamImportWithClaim(account, from, prefix+from, allowTrace, imClaim) } // AddMappedStreamImport helper for AddMappedStreamImportWithClaim @@ -2215,6 +2632,10 @@ func (a *Account) AddMappedStreamImport(account *Account, from, to string) error // AddMappedStreamImportWithClaim will add in the stream import from a specific account with optional token. func (a *Account) AddMappedStreamImportWithClaim(account *Account, from, to string, imClaim *jwt.Import) error { + return a.addMappedStreamImportWithClaim(account, from, to, false, imClaim) +} + +func (a *Account) addMappedStreamImportWithClaim(account *Account, from, to string, allowTrace bool, imClaim *jwt.Import) error { if account == nil { return ErrMissingAccount } @@ -2224,7 +2645,7 @@ func (a *Account) AddMappedStreamImportWithClaim(account *Account, from, to stri return ErrStreamImportAuthorization } - if to == "" { + if to == _EMPTY_ { to = from } @@ -2233,9 +2654,13 @@ func (a *Account) AddMappedStreamImportWithClaim(account *Account, from, to stri return err } + if err := a.streamImportFormsCycle(account, from); err != nil { + return err + } + var ( usePub bool - tr *transform + tr *subjectTransform err error ) if subjectHasWildcard(from) { @@ -2243,10 +2668,11 @@ func (a *Account) AddMappedStreamImportWithClaim(account *Account, from, to stri usePub = true } else { // Create a transform - if tr, err = newTransform(from, transformTokenize(to)); err != nil { - return fmt.Errorf("failed to create mapping transform for stream import subject %q to %q: %v", + if tr, err = NewSubjectTransformStrict(from, transformTokenize(to)); err != nil { + return fmt.Errorf("failed to create mapping transform for stream import subject from %q to %q: %v", from, to, err) } + to, _ = transformUntokenize(to) } } @@ -2255,7 +2681,10 @@ func (a *Account) AddMappedStreamImportWithClaim(account *Account, from, to stri a.mu.Unlock() return ErrStreamImportDuplicate } - a.imports.streams = append(a.imports.streams, &streamImport{account, from, to, tr, nil, imClaim, usePub, false}) + if imClaim != nil { + allowTrace = imClaim.AllowTrace + } + a.imports.streams = append(a.imports.streams, &streamImport{account, from, to, tr, nil, imClaim, usePub, false, allowTrace}) a.mu.Unlock() return nil } @@ -2273,15 +2702,23 @@ func (a *Account) isStreamImportDuplicate(acc *Account, from string) bool { // AddStreamImport will add in the stream import from a specific account. func (a *Account) AddStreamImport(account *Account, from, prefix string) error { - return a.AddStreamImportWithClaim(account, from, prefix, nil) + return a.addStreamImportWithClaim(account, from, prefix, false, nil) } // IsPublicExport is a placeholder to denote a public export. var IsPublicExport = []*Account(nil) // AddStreamExport will add an export to the account. If accounts is nil -// it will signify a public export, meaning anyone can impoort. +// it will signify a public export, meaning anyone can import. func (a *Account) AddStreamExport(subject string, accounts []*Account) error { + return a.addStreamExportWithAccountPos(subject, accounts, 0) +} + +// AddStreamExport will add an export to the account. If accounts is nil +// it will signify a public export, meaning anyone can import. +// if accountPos is > 0, all imports will be granted where the following holds: +// strings.Split(subject, tsep)[accountPos] == account id will be granted. +func (a *Account) addStreamExportWithAccountPos(subject string, accounts []*Account, accountPos uint) error { if a == nil { return ErrMissingAccount } @@ -2293,20 +2730,12 @@ func (a *Account) AddStreamExport(subject string, accounts []*Account) error { a.exports.streams = make(map[string]*streamExport) } ea := a.exports.streams[subject] - if accounts != nil { + if accounts != nil || accountPos > 0 { if ea == nil { ea = &streamExport{} } - // empty means auth required but will be import token. - if len(accounts) == 0 { - ea.tokenReq = true - } else { - if ea.approved == nil { - ea.approved = make(map[string]*Account, len(accounts)) - } - for _, acc := range accounts { - ea.approved[acc.Name] = acc - } + if err := setExportAuth(&ea.exportAuth, subject, accounts, accountPos); err != nil { + return err } } a.exports.streams[subject] = ea @@ -2329,14 +2758,21 @@ func (a *Account) checkStreamImportAuthorizedNoLock(account *Account, subject st return a.checkStreamExportApproved(account, subject, imClaim) } -func (a *Account) checkAuth(ea *exportAuth, account *Account, imClaim *jwt.Import) bool { +func (a *Account) checkAuth(ea *exportAuth, account *Account, imClaim *jwt.Import, tokens []string) bool { // if ea is nil or ea.approved is nil, that denotes a public export - if ea == nil || (ea.approved == nil && !ea.tokenReq) { + if ea == nil || (len(ea.approved) == 0 && !ea.tokenReq && ea.accountPos == 0) { return true } + // Check if the export is protected and enforces presence of importing account identity + if ea.accountPos > 0 { + return ea.accountPos <= uint(len(tokens)) && tokens[ea.accountPos-1] == account.Name + } // Check if token required if ea.tokenReq { - return a.checkActivation(account, imClaim, true) + return a.checkActivation(account, imClaim, ea, true) + } + if ea.approved == nil { + return false } // If we have a matching account we are authorized _, ok := ea.approved[account.Name] @@ -2347,11 +2783,13 @@ func (a *Account) checkStreamExportApproved(account *Account, subject string, im // Check direct match of subject first ea, ok := a.exports.streams[subject] if ok { + // if ea is nil or eq.approved is nil, that denotes a public export if ea == nil { return true } - return a.checkAuth(&ea.exportAuth, account, imClaim) + return a.checkAuth(&ea.exportAuth, account, imClaim, nil) } + // ok if we are here we did not match directly so we need to test each one. // The import subject arg has to take precedence, meaning the export // has to be a true subset of the import claim. We already checked for @@ -2362,7 +2800,7 @@ func (a *Account) checkStreamExportApproved(account *Account, subject string, im if ea == nil { return true } - return a.checkAuth(&ea.exportAuth, account, imClaim) + return a.checkAuth(&ea.exportAuth, account, imClaim, tokens) } } return false @@ -2373,16 +2811,10 @@ func (a *Account) checkServiceExportApproved(account *Account, subject string, i se, ok := a.exports.services[subject] if ok { // if se is nil or eq.approved is nil, that denotes a public export - if se == nil || (se.approved == nil && !se.tokenReq) { + if se == nil { return true } - // Check if token required - if se.tokenReq { - return a.checkActivation(account, imClaim, true) - } - // If we have a matching account we are authorized - _, ok := se.approved[account.Name] - return ok + return a.checkAuth(&se.exportAuth, account, imClaim, nil) } // ok if we are here we did not match directly so we need to test each one. // The import subject arg has to take precedence, meaning the export @@ -2391,15 +2823,10 @@ func (a *Account) checkServiceExportApproved(account *Account, subject string, i tokens := strings.Split(subject, tsep) for subj, se := range a.exports.services { if isSubsetMatch(tokens, subj) { - if se == nil || (se.approved == nil && !se.tokenReq) { + if se == nil { return true } - // Check if token required - if se.tokenReq { - return a.checkActivation(account, imClaim, true) - } - _, ok := se.approved[account.Name] - return ok + return a.checkAuth(&se.exportAuth, account, imClaim, tokens) } } return false @@ -2429,26 +2856,10 @@ func (a *Account) getWildcardServiceExport(from string) *serviceExport { return nil } -// Will fetch the activation token for an import. -func fetchActivation(url string) string { - // FIXME(dlc) - Make configurable. - c := &http.Client{Timeout: 2 * time.Second} - resp, err := c.Get(url) - if err != nil || resp == nil { - return "" - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "" - } - return string(body) -} - // These are import stream specific versions for when an activation expires. func (a *Account) streamActivationExpired(exportAcc *Account, subject string) { a.mu.RLock() - if a.expired || a.imports.streams == nil { + if a.expired.Load() || a.imports.streams == nil { a.mu.RUnlock() return } @@ -2465,17 +2876,14 @@ func (a *Account) streamActivationExpired(exportAcc *Account, subject string) { } a.mu.RUnlock() - if si.acc.checkActivation(a, si.claim, false) { + if si.acc.checkActivation(a, si.claim, nil, false) { // The token has been updated most likely and we are good to go. return } a.mu.Lock() si.invalid = true - clients := make([]*client, 0, len(a.clients)) - for c := range a.clients { - clients = append(clients, c) - } + clients := a.getClientsLocked() awcsti := map[string]struct{}{a.Name: {}} a.mu.Unlock() for _, c := range clients { @@ -2484,20 +2892,20 @@ func (a *Account) streamActivationExpired(exportAcc *Account, subject string) { } // These are import service specific versions for when an activation expires. -func (a *Account) serviceActivationExpired(subject string) { +func (a *Account) serviceActivationExpired(dstAcc *Account, subject string) { a.mu.RLock() - if a.expired || a.imports.services == nil { + if a.expired.Load() || a.imports.services == nil { a.mu.RUnlock() return } - si := a.imports.services[subject] + si := a.getServiceImportForAccountLocked(dstAcc.Name, subject) if si == nil || si.invalid { a.mu.RUnlock() return } a.mu.RUnlock() - if si.acc.checkActivation(a, si.claim, false) { + if si.acc.checkActivation(a, si.claim, nil, false) { // The token has been updated most likely and we are good to go. return } @@ -2514,34 +2922,33 @@ func (a *Account) activationExpired(exportAcc *Account, subject string, kind jwt case jwt.Stream: a.streamActivationExpired(exportAcc, subject) case jwt.Service: - a.serviceActivationExpired(subject) + a.serviceActivationExpired(exportAcc, subject) } } func isRevoked(revocations map[string]int64, subject string, issuedAt int64) bool { - if revocations == nil { + if len(revocations) == 0 { return false } if t, ok := revocations[subject]; !ok || t < issuedAt { - return false + if t, ok := revocations[jwt.All]; !ok || t < issuedAt { + return false + } } return true } // checkActivation will check the activation token for validity. -func (a *Account) checkActivation(importAcc *Account, claim *jwt.Import, expTimer bool) bool { - if claim == nil || claim.Token == "" { +// ea may only be nil in cases where revocation may not be checked, say triggered by expiration timer. +func (a *Account) checkActivation(importAcc *Account, claim *jwt.Import, ea *exportAuth, expTimer bool) bool { + if claim == nil || claim.Token == _EMPTY_ { return false } // Create a quick clone so we can inline Token JWT. clone := *claim - // We grab the token from a URL by hand here since we need expiration etc. - if url, err := url.Parse(clone.Token); err == nil && url.Scheme != "" { - clone.Token = fetchActivation(url.String()) - } vr := jwt.CreateValidationResults() - clone.Validate(a.Name, vr) + clone.Validate(importAcc.Name, vr) if vr.IsBlocking(true) { return false } @@ -2569,15 +2976,18 @@ func (a *Account) checkActivation(importAcc *Account, claim *jwt.Import, expTime }) } } + if ea == nil { + return true + } // Check for token revocation.. - return !isRevoked(a.actsRevoked, act.Subject, act.IssuedAt) + return !isRevoked(ea.actsRevoked, act.Subject, act.IssuedAt) } // Returns true if the activation claim is trusted. That is the issuer matches // the account or is an entry in the signing keys. func (a *Account) isIssuerClaimTrusted(claims *jwt.ActivationClaims) bool { // if no issuer account, issuer is the account - if claims.IssuerAccount == "" { + if claims.IssuerAccount == _EMPTY_ { return true } // If the IssuerAccount is not us, then this is considered an error. @@ -2588,16 +2998,20 @@ func (a *Account) isIssuerClaimTrusted(claims *jwt.ActivationClaims) bool { } return false } - return a.hasIssuerNoLock(claims.Issuer) + _, ok := a.hasIssuerNoLock(claims.Issuer) + return ok } // Returns true if `a` and `b` stream imports are the same. Note that the // check is done with the account's name, not the pointer. This is used // during config reload where we are comparing current and new config // in which pointers are different. -// No lock is acquired in this function, so it is assumed that the -// import maps are not changed while this executes. +// Acquires `a` read lock, but `b` is assumed to not be accessed +// by anyone but the caller (`b` is not registered anywhere). func (a *Account) checkStreamImportsEqual(b *Account) bool { + a.mu.RLock() + defer a.mu.RUnlock() + if len(a.imports.streams) != len(b.imports.streams) { return false } @@ -2607,14 +3021,21 @@ func (a *Account) checkStreamImportsEqual(b *Account) bool { bm[bim.acc.Name+bim.from+bim.to] = bim } for _, aim := range a.imports.streams { - if _, ok := bm[aim.acc.Name+aim.from+aim.to]; !ok { + if bim, ok := bm[aim.acc.Name+aim.from+aim.to]; !ok { + return false + } else if aim.atrc != bim.atrc { return false } } return true } +// Returns true if `a` and `b` stream exports are the same. +// Acquires `a` read lock, but `b` is assumed to not be accessed +// by anyone but the caller (`b` is not registered anywhere). func (a *Account) checkStreamExportsEqual(b *Account) bool { + a.mu.RLock() + defer a.mu.RUnlock() if len(a.exports.streams) != len(b.exports.streams) { return false } @@ -2623,14 +3044,29 @@ func (a *Account) checkStreamExportsEqual(b *Account) bool { if !ok { return false } - if !reflect.DeepEqual(aea, bea) { + if !isStreamExportEqual(aea, bea) { return false } } return true } +func isStreamExportEqual(a, b *streamExport) bool { + if a == nil && b == nil { + return true + } + if (a == nil && b != nil) || (a != nil && b == nil) { + return false + } + return isExportAuthEqual(&a.exportAuth, &b.exportAuth) +} + +// Returns true if `a` and `b` service exports are the same. +// Acquires `a` read lock, but `b` is assumed to not be accessed +// by anyone but the caller (`b` is not registered anywhere). func (a *Account) checkServiceExportsEqual(b *Account) bool { + a.mu.RLock() + defer a.mu.RUnlock() if len(a.exports.services) != len(b.exports.services) { return false } @@ -2639,7 +3075,69 @@ func (a *Account) checkServiceExportsEqual(b *Account) bool { if !ok { return false } - if !reflect.DeepEqual(aea, bea) { + if !isServiceExportEqual(aea, bea) { + return false + } + } + return true +} + +func isServiceExportEqual(a, b *serviceExport) bool { + if a == nil && b == nil { + return true + } + if (a == nil && b != nil) || (a != nil && b == nil) { + return false + } + if !isExportAuthEqual(&a.exportAuth, &b.exportAuth) { + return false + } + if a.acc.Name != b.acc.Name { + return false + } + if a.respType != b.respType { + return false + } + if a.latency != nil || b.latency != nil { + if (a.latency != nil && b.latency == nil) || (a.latency == nil && b.latency != nil) { + return false + } + if a.latency.sampling != b.latency.sampling { + return false + } + if a.latency.subject != b.latency.subject { + return false + } + } + if a.atrc != b.atrc { + return false + } + return true +} + +// Returns true if `a` and `b` exportAuth structures are equal. +// Both `a` and `b` are guaranteed to be non-nil. +// Locking is handled by the caller. +func isExportAuthEqual(a, b *exportAuth) bool { + if a.tokenReq != b.tokenReq { + return false + } + if a.accountPos != b.accountPos { + return false + } + if len(a.approved) != len(b.approved) { + return false + } + for ak, av := range a.approved { + if bv, ok := b.approved[ak]; !ok || av.Name != bv.Name { + return false + } + } + if len(a.actsRevoked) != len(b.actsRevoked) { + return false + } + for ak, av := range a.actsRevoked { + if bv, ok := b.actsRevoked[ak]; !ok || av != bv { return false } } @@ -2665,29 +3163,20 @@ func (a *Account) checkServiceImportAuthorizedNoLock(account *Account, subject s // IsExpired returns expiration status. func (a *Account) IsExpired() bool { - a.mu.RLock() - exp := a.expired - a.mu.RUnlock() - return exp + return a.expired.Load() } // Called when an account has expired. func (a *Account) expiredTimeout() { // Mark expired first. - a.mu.Lock() - a.expired = true - a.mu.Unlock() + a.expired.Store(true) // Collect the clients and expire them. - cs := make([]*client, 0, len(a.clients)) - a.mu.RLock() - for c := range a.clients { - cs = append(cs, c) - } - a.mu.RUnlock() - + cs := a.getClients() for _, c := range cs { - c.accountAuthExpired() + if !isInternalClient(c.kind) { + c.accountAuthExpired() + } } } @@ -2713,6 +3202,13 @@ func (a *Account) checkUserRevoked(nkey string, issuedAt int64) bool { return isRevoked(a.usersRevoked, nkey, issuedAt) } +// failBearer will return if bearer token are allowed (false) or disallowed (true) +func (a *Account) failBearer() bool { + a.mu.RLock() + defer a.mu.RUnlock() + return a.disallowBearer +} + // Check expiration and set the proper state as needed. func (a *Account) checkExpiration(claims *jwt.ClaimsData) { a.mu.Lock() @@ -2720,40 +3216,33 @@ func (a *Account) checkExpiration(claims *jwt.ClaimsData) { a.clearExpirationTimer() if claims.Expires == 0 { - a.expired = false + a.expired.Store(false) return } tn := time.Now().Unix() if claims.Expires <= tn { - a.expired = true + a.expired.Store(true) return } expiresAt := time.Duration(claims.Expires - tn) a.setExpirationTimer(expiresAt * time.Second) - a.expired = false + a.expired.Store(false) } // hasIssuer returns true if the issuer matches the account +// If the issuer is a scoped signing key, the scope will be returned as well // issuer or it is a signing key for the account. -func (a *Account) hasIssuer(issuer string) bool { +func (a *Account) hasIssuer(issuer string) (jwt.Scope, bool) { a.mu.RLock() - hi := a.hasIssuerNoLock(issuer) + scope, ok := a.hasIssuerNoLock(issuer) a.mu.RUnlock() - return hi + return scope, ok } // hasIssuerNoLock is the unlocked version of hasIssuer -func (a *Account) hasIssuerNoLock(issuer string) bool { - // same issuer -- keep this for safety on the calling code - if a.Name == issuer { - return true - } - for i := 0; i < len(a.signingKeys); i++ { - if a.signingKeys[i] == issuer { - return true - } - } - return false +func (a *Account) hasIssuerNoLock(issuer string) (jwt.Scope, bool) { + scope, ok := a.signingKeys[issuer] + return scope, ok } // Returns the loop detection subject used for leafnodes @@ -2783,25 +3272,101 @@ func (s *Server) SetAccountResolver(ar AccountResolver) { // AccountResolver returns the registered account resolver. func (s *Server) AccountResolver() AccountResolver { - s.mu.Lock() + s.mu.RLock() ar := s.accResolver - s.mu.Unlock() + s.mu.RUnlock() return ar } // isClaimAccount returns if this account is backed by a JWT claim. // Lock should be held. func (a *Account) isClaimAccount() bool { - return a.claimJWT != "" + return a.claimJWT != _EMPTY_ } -// updateAccountClaims will update an existing account with new claims. +// UpdateAccountClaims will update an existing account with new claims. // This will replace any exports or imports previously defined. // Lock MUST NOT be held upon entry. func (s *Server) UpdateAccountClaims(a *Account, ac *jwt.AccountClaims) { s.updateAccountClaimsWithRefresh(a, ac, true) } +func (a *Account) traceLabel() string { + if a == nil { + return _EMPTY_ + } + if a.nameTag != _EMPTY_ { + return fmt.Sprintf("%s/%s", a.Name, a.nameTag) + } + return a.Name +} + +// Check if an account has external auth set. +// Operator/Account Resolver only. +func (a *Account) hasExternalAuth() bool { + if a == nil { + return false + } + a.mu.RLock() + defer a.mu.RUnlock() + return a.extAuth != nil +} + +// Deterimine if this is an external auth user. +func (a *Account) isExternalAuthUser(userID string) bool { + if a == nil { + return false + } + a.mu.RLock() + defer a.mu.RUnlock() + if a.extAuth != nil { + for _, u := range a.extAuth.AuthUsers { + if userID == u { + return true + } + } + } + return false +} + +// Return the external authorization xkey if external authorization is enabled and the xkey is set. +// Operator/Account Resolver only. +func (a *Account) externalAuthXKey() string { + if a == nil { + return _EMPTY_ + } + a.mu.RLock() + defer a.mu.RUnlock() + if a.extAuth != nil && a.extAuth.XKey != _EMPTY_ { + return a.extAuth.XKey + } + return _EMPTY_ +} + +// Check if an account switch for external authorization is allowed. +func (a *Account) isAllowedAcount(acc string) bool { + if a == nil { + return false + } + a.mu.RLock() + defer a.mu.RUnlock() + if a.extAuth != nil { + // if we have a single allowed account, and we have a wildcard + // we accept it + if len(a.extAuth.AllowedAccounts) == 1 && + a.extAuth.AllowedAccounts[0] == jwt.AnyAccount { + return true + } + // otherwise must match exactly + for _, a := range a.extAuth.AllowedAccounts { + if a == acc { + return true + } + } + } + return false +} + // updateAccountClaimsWithRefresh will update an existing account with new claims. // If refreshImportingAccounts is true it will also update incomplete dependent accounts // This will replace any exports or imports previously defined. @@ -2810,13 +3375,41 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim if a == nil { return } - s.Debugf("Updating account claims: %s", a.Name) + s.Debugf("Updating account claims: %s/%s", a.Name, ac.Name) a.checkExpiration(ac.Claims()) a.mu.Lock() // Clone to update, only select certain fields. old := &Account{Name: a.Name, exports: a.exports, limits: a.limits, signingKeys: a.signingKeys} + // overwrite claim meta data + a.nameTag = ac.Name + a.tags = ac.Tags + + // Grab trace label under lock. + tl := a.traceLabel() + + var td string + var tds int + if ac.Trace != nil { + // Update trace destination and sampling + td, tds = string(ac.Trace.Destination), ac.Trace.Sampling + if !IsValidPublishSubject(td) { + td, tds = _EMPTY_, 0 + } else if tds <= 0 || tds > 100 { + tds = 100 + } + } + a.traceDest, a.traceDestSampling = td, tds + + // Check for external authorization. + if ac.HasExternalAuthorization() { + a.extAuth = &jwt.ExternalAuthorization{} + a.extAuth.AuthUsers.Add(ac.Authorization.AuthUsers...) + a.extAuth.AllowedAccounts.Add(ac.Authorization.AllowedAccounts...) + a.extAuth.XKey = ac.Authorization.XKey + } + // Reset exports and imports here. // Exports is creating a whole new map. @@ -2828,65 +3421,88 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim a.imports.streams = nil } if a.imports.services != nil { - old.imports.services = make(map[string]*serviceImport, len(a.imports.services)) - } - for k, v := range a.imports.services { - old.imports.services[k] = v - delete(a.imports.services, k) + old.imports.services = make(map[string][]*serviceImport, len(a.imports.services)) + for k, v := range a.imports.services { + sis := append([]*serviceImport(nil), v...) + old.imports.services[k] = sis + delete(a.imports.services, k) + } } - // Reset any notion of export revocations. - a.actsRevoked = nil + alteredScope := map[string]struct{}{} // update account signing keys a.signingKeys = nil + _, strict := s.strictSigningKeyUsage[a.Issuer] + if len(ac.SigningKeys) > 0 || !strict { + a.signingKeys = make(map[string]jwt.Scope) + } signersChanged := false - if len(ac.SigningKeys) > 0 { - // insure copy the new keys and sort - a.signingKeys = append(a.signingKeys, ac.SigningKeys...) - sort.Strings(a.signingKeys) + for k, scope := range ac.SigningKeys { + a.signingKeys[k] = scope + } + if !strict { + a.signingKeys[a.Name] = nil } if len(a.signingKeys) != len(old.signingKeys) { signersChanged = true - } else { - for i := 0; i < len(old.signingKeys); i++ { - if a.signingKeys[i] != old.signingKeys[i] { - signersChanged = true - break - } + } + for k, scope := range a.signingKeys { + if oldScope, ok := old.signingKeys[k]; !ok { + signersChanged = true + } else if !reflect.DeepEqual(scope, oldScope) { + signersChanged = true + alteredScope[k] = struct{}{} } } - a.mu.Unlock() - - gatherClients := func() []*client { - a.mu.RLock() - clients := make([]*client, 0, len(a.clients)) - for c := range a.clients { - clients = append(clients, c) + // collect mappings that need to be removed + removeList := []string{} + for _, m := range a.mappings { + if _, ok := ac.Mappings[jwt.Subject(m.src)]; !ok { + removeList = append(removeList, m.src) } - a.mu.RUnlock() - return clients } + a.mu.Unlock() - jsEnabled := s.JetStreamEnabled() - if jsEnabled && a == s.SystemAccount() { - for _, export := range allJsExports { - s.Debugf("Adding jetstream service export %q for %s", export, a.Name) - if err := a.AddServiceExport(export, nil); err != nil { - s.Errorf("Error setting up jetstream service exports: %v", err) + for sub, wm := range ac.Mappings { + mappings := make([]*MapDest, len(wm)) + for i, m := range wm { + mappings[i] = &MapDest{ + Subject: string(m.Subject), + Weight: m.GetWeight(), + Cluster: m.Cluster, } } + // This will overwrite existing entries + a.AddWeightedMappings(string(sub), mappings...) + } + // remove mappings + for _, rmMapping := range removeList { + a.RemoveMapping(rmMapping) } + // Re-register system exports/imports. + if a == s.SystemAccount() { + s.addSystemAccountExports(a) + } else { + s.registerSystemImports(a) + } + + jsEnabled := s.JetStreamEnabled() + + streamTokenExpirationChanged := false + serviceTokenExpirationChanged := false + for _, e := range ac.Exports { switch e.Type { case jwt.Stream: - s.Debugf("Adding stream export %q for %s", e.Subject, a.Name) - if err := a.AddStreamExport(string(e.Subject), authAccounts(e.TokenReq)); err != nil { - s.Debugf("Error adding stream export to account [%s]: %v", a.Name, err.Error()) + s.Debugf("Adding stream export %q for %s", e.Subject, tl) + if err := a.addStreamExportWithAccountPos( + string(e.Subject), authAccounts(e.TokenReq), e.AccountTokenPosition); err != nil { + s.Debugf("Error adding stream export to account [%s]: %v", tl, err.Error()) } case jwt.Service: - s.Debugf("Adding service export %q for %s", e.Subject, a.Name) + s.Debugf("Adding service export %q for %s", e.Subject, tl) rt := Singleton switch e.ResponseType { case jwt.ResponseTypeStream: @@ -2894,54 +3510,107 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim case jwt.ResponseTypeChunked: rt = Chunked } - if err := a.AddServiceExportWithResponse(string(e.Subject), rt, authAccounts(e.TokenReq)); err != nil { - s.Debugf("Error adding service export to account [%s]: %v", a.Name, err) + if err := a.addServiceExportWithResponseAndAccountPos( + string(e.Subject), rt, authAccounts(e.TokenReq), e.AccountTokenPosition); err != nil { + s.Debugf("Error adding service export to account [%s]: %v", tl, err) + continue } + sub := string(e.Subject) if e.Latency != nil { - if err := a.TrackServiceExportWithSampling(string(e.Subject), string(e.Latency.Results), e.Latency.Sampling); err != nil { - s.Debugf("Error adding latency tracking for service export to account [%s]: %v", a.Name, err) + if err := a.TrackServiceExportWithSampling(sub, string(e.Latency.Results), int(e.Latency.Sampling)); err != nil { + hdrNote := _EMPTY_ + if e.Latency.Sampling == jwt.Headers { + hdrNote = " (using headers)" + } + s.Debugf("Error adding latency tracking%s for service export to account [%s]: %v", hdrNote, tl, err) } } + if e.ResponseThreshold != 0 { + // Response threshold was set in options. + if err := a.SetServiceExportResponseThreshold(sub, e.ResponseThreshold); err != nil { + s.Debugf("Error adding service export response threshold for [%s]: %v", tl, err) + } + } + if err := a.SetServiceExportAllowTrace(sub, e.AllowTrace); err != nil { + s.Debugf("Error adding allow_trace for %q: %v", sub, err) + } } - // We will track these at the account level. Should not have any collisions. - if e.Revocations != nil { - a.mu.Lock() - if a.actsRevoked == nil { - a.actsRevoked = make(map[string]int64) + + var revocationChanged *bool + var ea *exportAuth + + a.mu.Lock() + switch e.Type { + case jwt.Stream: + revocationChanged = &streamTokenExpirationChanged + if se, ok := a.exports.streams[string(e.Subject)]; ok && se != nil { + ea = &se.exportAuth } - for k, t := range e.Revocations { - a.actsRevoked[k] = t + case jwt.Service: + revocationChanged = &serviceTokenExpirationChanged + if se, ok := a.exports.services[string(e.Subject)]; ok && se != nil { + ea = &se.exportAuth + } + } + if ea != nil { + oldRevocations := ea.actsRevoked + if len(e.Revocations) == 0 { + // remove all, no need to evaluate existing imports + ea.actsRevoked = nil + } else if len(oldRevocations) == 0 { + // add all, existing imports need to be re evaluated + ea.actsRevoked = e.Revocations + *revocationChanged = true + } else { + ea.actsRevoked = e.Revocations + // diff, existing imports need to be conditionally re evaluated, depending on: + // if a key was added, or it's timestamp increased + for k, t := range e.Revocations { + if tOld, ok := oldRevocations[k]; !ok || tOld < t { + *revocationChanged = true + } + } } - a.mu.Unlock() } + a.mu.Unlock() } var incompleteImports []*jwt.Import for _, i := range ac.Imports { - // check tmpAccounts with priority - var acc *Account - var err error - if v, ok := s.tmpAccounts.Load(i.Account); ok { - acc = v.(*Account) - } else { - acc, err = s.lookupAccount(i.Account) - } + acc, err := s.lookupAccount(i.Account) if acc == nil || err != nil { s.Errorf("Can't locate account [%s] for import of [%v] %s (err=%v)", i.Account, i.Subject, i.Type, err) incompleteImports = append(incompleteImports, i) continue } + // Capture trace labels. + acc.mu.RLock() + atl := acc.traceLabel() + acc.mu.RUnlock() + // Grab from and to + from, to := string(i.Subject), i.GetTo() switch i.Type { case jwt.Stream: - s.Debugf("Adding stream import %s:%q for %s:%q", acc.Name, i.Subject, a.Name, i.To) - if err := a.AddStreamImportWithClaim(acc, string(i.Subject), string(i.To), i); err != nil { - s.Debugf("Error adding stream import to account [%s]: %v", a.Name, err.Error()) + if i.LocalSubject != _EMPTY_ { + // set local subject implies to is empty + to = string(i.LocalSubject) + s.Debugf("Adding stream import %s:%q for %s:%q", atl, from, tl, to) + err = a.AddMappedStreamImportWithClaim(acc, from, to, i) + } else { + s.Debugf("Adding stream import %s:%q for %s:%q", atl, from, tl, to) + err = a.AddStreamImportWithClaim(acc, from, to, i) + } + if err != nil { + s.Debugf("Error adding stream import to account [%s]: %v", tl, err.Error()) incompleteImports = append(incompleteImports, i) } case jwt.Service: - // FIXME(dlc) - need to add in respThresh here eventually. - s.Debugf("Adding service import %s:%q for %s:%q", acc.Name, i.Subject, a.Name, i.To) - if err := a.AddServiceImportWithClaim(acc, string(i.Subject), string(i.To), i); err != nil { - s.Debugf("Error adding service import to account [%s]: %v", a.Name, err.Error()) + if i.LocalSubject != _EMPTY_ { + from = string(i.LocalSubject) + to = string(i.Subject) + } + s.Debugf("Adding service import %s:%q for %s:%q", atl, from, tl, to) + if err := a.AddServiceImportWithClaim(acc, from, to, i); err != nil { + s.Debugf("Error adding service import to account [%s]: %v", tl, err.Error()) incompleteImports = append(incompleteImports, i) } } @@ -2949,24 +3618,25 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim // Now let's apply any needed changes from import/export changes. if !a.checkStreamImportsEqual(old) { awcsti := map[string]struct{}{a.Name: {}} - for _, c := range gatherClients() { + for _, c := range a.getClients() { c.processSubsOnConfigReload(awcsti) } } // Now check if stream exports have changed. - if !a.checkStreamExportsEqual(old) || signersChanged { + if !a.checkStreamExportsEqual(old) || signersChanged || streamTokenExpirationChanged { clients := map[*client]struct{}{} // We need to check all accounts that have an import claim from this account. awcsti := map[string]struct{}{} - s.accounts.Range(func(k, v interface{}) bool { + + // We must only allow one goroutine to go through here, otherwise we could deadlock + // due to locking two accounts in succession. + s.mu.Lock() + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) // Move to the next if this account is actually account "a". if acc.Name == a.Name { return true } - // TODO: checkStreamImportAuthorized() stack should not be trying - // to lock "acc". If we find that to be needed, we will need to - // rework this to ensure we don't lock acc. acc.mu.Lock() for _, im := range acc.imports.streams { if im != nil && im.acc.Name == a.Name { @@ -2981,31 +3651,41 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim acc.mu.Unlock() return true }) + s.mu.Unlock() // Now walk clients. for c := range clients { c.processSubsOnConfigReload(awcsti) } } // Now check if service exports have changed. - if !a.checkServiceExportsEqual(old) || signersChanged { - s.accounts.Range(func(k, v interface{}) bool { + if !a.checkServiceExportsEqual(old) || signersChanged || serviceTokenExpirationChanged { + // We must only allow one goroutine to go through here, otherwise we could deadlock + // due to locking two accounts in succession. + s.mu.Lock() + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) // Move to the next if this account is actually account "a". if acc.Name == a.Name { return true } - // TODO: checkServiceImportAuthorized() stack should not be trying - // to lock "acc". If we find that to be needed, we will need to - // rework this to ensure we don't lock acc. acc.mu.Lock() - for _, si := range acc.imports.services { - if si != nil && si.acc.Name == a.Name { - // Check for if we are still authorized for an import. - si.invalid = !a.checkServiceImportAuthorized(acc, si.to, si.claim) - if si.latency != nil && !si.response { - // Make sure we should still be tracking latency. - if se := a.getServiceExport(si.to); se != nil { - si.latency = se.latency + for _, sis := range acc.imports.services { + for _, si := range sis { + if si != nil && si.acc.Name == a.Name { + // Check for if we are still authorized for an import. + si.invalid = !a.checkServiceImportAuthorized(acc, si.to, si.claim) + // Make sure we should still be tracking latency and if we + // are allowed to trace. + if !si.response { + a.mu.RLock() + if se := a.getServiceExport(si.to); se != nil { + if si.latency != nil { + si.latency = se.latency + } + // Update allow trace. + si.atrc = se.atrc + } + a.mu.RUnlock() } } } @@ -3013,15 +3693,20 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim acc.mu.Unlock() return true }) + s.mu.Unlock() } // Now make sure we shutdown the old service import subscriptions. var sids [][]byte a.mu.RLock() c := a.ic - for _, si := range old.imports.services { - if c != nil && si.sid != nil { - sids = append(sids, si.sid) + if c != nil { + for _, sis := range old.imports.services { + for _, si := range sis { + if si.sid != nil { + sids = append(sids, si.sid) + } + } } } a.mu.RUnlock() @@ -3035,6 +3720,7 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim a.mpay = int32(ac.Limits.Payload) a.mconns = int32(ac.Limits.Conn) a.mleafs = int32(ac.Limits.LeafNodeConn) + a.disallowBearer = ac.Limits.DisallowBearer // Check for any revocations if len(ac.Revocations) > 0 { // We will always replace whatever we had with most current, so no @@ -3054,74 +3740,181 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim if a.srv == nil { a.srv = s } - if jsEnabled { + + if ac.Limits.IsJSEnabled() { + toUnlimited := func(value int64) int64 { + if value > 0 { + return value + } + return -1 + } if ac.Limits.JetStreamLimits.DiskStorage != 0 || ac.Limits.JetStreamLimits.MemoryStorage != 0 { // JetStreamAccountLimits and jwt.JetStreamLimits use same value for unlimited - a.jsLimits = &JetStreamAccountLimits{ - MaxMemory: ac.Limits.JetStreamLimits.MemoryStorage, - MaxStore: ac.Limits.JetStreamLimits.DiskStorage, - MaxStreams: int(ac.Limits.JetStreamLimits.Streams), - MaxConsumers: int(ac.Limits.JetStreamLimits.Consumer), + a.jsLimits = map[string]JetStreamAccountLimits{ + _EMPTY_: { + MaxMemory: ac.Limits.JetStreamLimits.MemoryStorage, + MaxStore: ac.Limits.JetStreamLimits.DiskStorage, + MaxStreams: int(ac.Limits.JetStreamLimits.Streams), + MaxConsumers: int(ac.Limits.JetStreamLimits.Consumer), + MemoryMaxStreamBytes: toUnlimited(ac.Limits.JetStreamLimits.MemoryMaxStreamBytes), + StoreMaxStreamBytes: toUnlimited(ac.Limits.JetStreamLimits.DiskMaxStreamBytes), + MaxBytesRequired: ac.Limits.JetStreamLimits.MaxBytesRequired, + MaxAckPending: int(toUnlimited(ac.Limits.JetStreamLimits.MaxAckPending)), + }, + } + } else { + a.jsLimits = map[string]JetStreamAccountLimits{} + for t, l := range ac.Limits.JetStreamTieredLimits { + a.jsLimits[t] = JetStreamAccountLimits{ + MaxMemory: l.MemoryStorage, + MaxStore: l.DiskStorage, + MaxStreams: int(l.Streams), + MaxConsumers: int(l.Consumer), + MemoryMaxStreamBytes: toUnlimited(l.MemoryMaxStreamBytes), + StoreMaxStreamBytes: toUnlimited(l.DiskMaxStreamBytes), + MaxBytesRequired: l.MaxBytesRequired, + MaxAckPending: int(toUnlimited(l.MaxAckPending)), + } } - } else if a.jsLimits != nil { - // covers failed update followed by disable - a.jsLimits = nil } + } else if a.jsLimits != nil { + // covers failed update followed by disable + a.jsLimits = nil } + a.updated = time.Now() + clients := a.getClientsLocked() + ajs := a.js a.mu.Unlock() - clients := gatherClients() - // Sort if we are over the limit. + // Sort in chronological order so that most recent connections over the limit are pruned. if a.MaxTotalConnectionsReached() { - sort.Slice(clients, func(i, j int) bool { - return clients[i].start.After(clients[j].start) - }) + slices.SortFunc(clients, func(i, j *client) int { return i.start.Compare(j.start) }) } + // If JetStream is enabled for this server we will call into configJetStream for the account + // regardless of enabled or disabled. It handles both cases. if jsEnabled { - if err := s.configJetStream(a); err != nil { - s.Errorf("Error configuring jetstream for account [%s]: %v", a.Name, err.Error()) + if err := s.configJetStream(a, nil); err != nil { + s.Errorf("Error configuring jetstream for account [%s]: %v", tl, err.Error()) a.mu.Lock() // Absent reload of js server cfg, this is going to be broken until js is disabled a.incomplete = true a.mu.Unlock() + } else { + a.mu.Lock() + // Refresh reference, we've just enabled JetStream, so it would have been nil before. + ajs = a.js + a.mu.Unlock() } + } else if a.jsLimits != nil { + // We do not have JS enabled for this server, but the account has it enabled so setup + // our imports properly. This allows this server to proxy JS traffic correctly. + s.checkJetStreamExports() + a.enableAllJetStreamServiceImportsAndMappings() } - for i, c := range clients { + if ajs != nil { + // Check whether the account NRG status changed. If it has then we need to notify the + // Raft groups running on the system so that they can move their subs if needed. + a.mu.Lock() + previous := a.nrgAccount + switch ac.ClusterTraffic { + case "system", _EMPTY_: + a.nrgAccount = _EMPTY_ + case "owner": + a.nrgAccount = a.Name + default: + s.Errorf("Account claim for %q has invalid value %q for cluster traffic account", a.Name, ac.ClusterTraffic) + } + changed := a.nrgAccount != previous + a.mu.Unlock() + if changed { + s.updateNRGAccountStatus() + } + } + + // client list is in chronological order (older cids at the beginning of the list). + count := 0 + for _, c := range clients { a.mu.RLock() - exceeded := a.mconns != jwt.NoLimit && i >= int(a.mconns) + exceeded := a.mconns != jwt.NoLimit && count >= int(a.mconns) a.mu.RUnlock() - if exceeded { - c.maxAccountConnExceeded() - continue + // Only kick non-internal clients. + if !isInternalClient(c.kind) { + if exceeded { + c.maxAccountConnExceeded() + continue + } + count++ } c.mu.Lock() c.applyAccountLimits() + // if we have an nkey user we are a callout user - save + // the issuedAt, and nkey user id to honor revocations + var nkeyUserID string + var issuedAt int64 + if c.user != nil { + issuedAt = c.user.Issued + nkeyUserID = c.user.Nkey + } theJWT := c.opts.JWT c.mu.Unlock() // Check for being revoked here. We use ac one to avoid the account lock. - if ac.Revocations != nil && theJWT != "" { + if (ac.Revocations != nil || ac.Limits.DisallowBearer) && theJWT != _EMPTY_ { if juc, err := jwt.DecodeUserClaims(theJWT); err != nil { c.Debugf("User JWT not valid: %v", err) c.authViolation() continue + } else if juc.BearerToken && ac.Limits.DisallowBearer { + c.Debugf("Bearer User JWT not allowed") + c.authViolation() + continue } else if ok := ac.IsClaimRevoked(juc); ok { c.sendErrAndDebug("User Authentication Revoked") c.closeConnection(Revocation) continue } } + + // if we extracted nkeyUserID and issuedAt we are a callout type + // calloutIAT should only be set if we are in callout scenario as + // the user JWT is _NOT_ associated with the client for callouts, + // so we rely on the calloutIAT to know when the JWT was issued + // revocations simply state that JWT issued before or by that date + // are not valid + if ac.Revocations != nil && nkeyUserID != _EMPTY_ && issuedAt > 0 { + seconds, ok := ac.Revocations[jwt.All] + if ok && seconds >= issuedAt { + c.sendErrAndDebug("User Authentication Revoked") + c.closeConnection(Revocation) + continue + } + seconds, ok = ac.Revocations[nkeyUserID] + if ok && seconds >= issuedAt { + c.sendErrAndDebug("User Authentication Revoked") + c.closeConnection(Revocation) + continue + } + } } // Check if the signing keys changed, might have to evict if signersChanged { for _, c := range clients { c.mu.Lock() + if c.user == nil { + c.mu.Unlock() + continue + } sk := c.user.SigningKey c.mu.Unlock() - if sk != "" && !a.hasIssuer(sk) { + if sk == _EMPTY_ { + continue + } + if _, ok := alteredScope[sk]; ok { + c.closeConnection(AuthenticationViolation) + } else if _, ok := a.hasIssuer(sk); !ok { c.closeConnection(AuthenticationViolation) } } @@ -3129,11 +3922,12 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim if _, ok := s.incompleteAccExporterMap.Load(old.Name); ok && refreshImportingAccounts { s.incompleteAccExporterMap.Delete(old.Name) - s.accounts.Range(func(key, value interface{}) bool { + s.accounts.Range(func(key, value any) bool { acc := value.(*Account) acc.mu.RLock() incomplete := acc.incomplete name := acc.Name + label := acc.traceLabel() // Must use jwt in account or risk failing on fetch // This jwt may not be the same that caused exportingAcc to be in incompleteAccExporterMap claimJWT := acc.claimJWT @@ -3149,7 +3943,7 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim // Since this account just got updated, the import itself may be in error. So trace that. if _, ok := s.incompleteAccExporterMap.Load(old.Name); ok { s.incompleteAccExporterMap.Delete(old.Name) - s.Errorf("Account %s has issues importing account %s", name, old.Name) + s.Errorf("Account %s has issues importing account %s", label, old.Name) } } } @@ -3170,8 +3964,13 @@ func (s *Server) buildInternalAccount(ac *jwt.AccountClaims) *Account { // We don't want to register an account that is in the process of // being built, however, to solve circular import dependencies, we // need to store it here. - s.tmpAccounts.Store(ac.Subject, acc) + if v, loaded := s.tmpAccounts.LoadOrStore(ac.Subject, acc); loaded { + return v.(*Account) + } + + // Update based on claims. s.UpdateAccountClaims(acc, ac) + return acc } @@ -3183,9 +3982,7 @@ func buildPermissionsFromJwt(uc *jwt.Permissions) *Permissions { } var p *Permissions if len(uc.Pub.Allow) > 0 || len(uc.Pub.Deny) > 0 { - if p == nil { - p = &Permissions{} - } + p = &Permissions{} p.Publish = &SubjectPermission{} p.Publish.Allow = uc.Pub.Allow p.Publish.Deny = uc.Pub.Deny @@ -3213,8 +4010,8 @@ func buildPermissionsFromJwt(uc *jwt.Permissions) *Permissions { // Helper to build internal NKeyUser. func buildInternalNkeyUser(uc *jwt.UserClaims, acts map[string]struct{}, acc *Account) *NkeyUser { - nu := &NkeyUser{Nkey: uc.Subject, Account: acc, AllowedConnectionTypes: acts} - if uc.IssuerAccount != "" { + nu := &NkeyUser{Nkey: uc.Subject, Account: acc, AllowedConnectionTypes: acts, Issued: uc.IssuedAt} + if uc.IssuerAccount != _EMPTY_ { nu.SigningKey = uc.Issuer } @@ -3227,13 +4024,11 @@ func buildInternalNkeyUser(uc *jwt.UserClaims, acts map[string]struct{}, acc *Ac return nu } -const fetchTimeout = 2 * time.Second - func fetchAccount(res AccountResolver, name string) (string, error) { if !nkeys.IsValidPublicAccountKey(name) { - return "", fmt.Errorf("will only fetch valid account keys") + return _EMPTY_, fmt.Errorf("will only fetch valid account keys") } - return res.Fetch(name) + return res.Fetch(copyString(name)) } // AccountResolver interface. This is to fetch Account JWTs by public nkeys @@ -3270,7 +4065,7 @@ func (*resolverDefaultsOpsImpl) Close() { } func (*resolverDefaultsOpsImpl) Store(_, _ string) error { - return fmt.Errorf("Store operation not supported for URL Resolver") + return fmt.Errorf("store operation not supported for URL Resolver") } // MemAccResolver is a memory only resolver. @@ -3294,7 +4089,7 @@ func (m *MemAccResolver) Store(name, jwt string) error { return nil } -func (ur *MemAccResolver) IsReadOnly() bool { +func (m *MemAccResolver) IsReadOnly() bool { return false } @@ -3318,7 +4113,7 @@ func NewURLAccResolver(url string) (*URLAccResolver, error) { } ur := &URLAccResolver{ url: url, - c: &http.Client{Timeout: fetchTimeout, Transport: tr}, + c: &http.Client{Timeout: DEFAULT_ACCOUNT_FETCH_TIMEOUT, Transport: tr}, } return ur, nil } @@ -3329,14 +4124,15 @@ func (ur *URLAccResolver) Fetch(name string) (string, error) { url := ur.url + name resp, err := ur.c.Get(url) if err != nil { - return _EMPTY_, fmt.Errorf("could not fetch <%q>: %v", url, err) + return _EMPTY_, fmt.Errorf("could not fetch <%q>: %v", redactURLString(url), err) } else if resp == nil { - return _EMPTY_, fmt.Errorf("could not fetch <%q>: no response", url) - } else if resp.StatusCode != http.StatusOK { - return _EMPTY_, fmt.Errorf("could not fetch <%q>: %v", url, resp.Status) + return _EMPTY_, fmt.Errorf("could not fetch <%q>: no response", redactURLString(url)) } defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + if resp.StatusCode != http.StatusOK { + return _EMPTY_, fmt.Errorf("could not fetch <%q>: %v", redactURLString(url), resp.Status) + } + body, err := io.ReadAll(resp.Body) if err != nil { return _EMPTY_, err } @@ -3348,6 +4144,7 @@ type DirAccResolver struct { *DirJWTStore *Server syncInterval time.Duration + fetchTimeout time.Duration } func (dr *DirAccResolver) IsTrackingUpdate() bool { @@ -3358,43 +4155,66 @@ func (dr *DirAccResolver) Reload() error { return dr.DirJWTStore.Reload() } +// ServerAPIClaimUpdateResponse is the response to $SYS.REQ.ACCOUNT..CLAIMS.UPDATE and $SYS.REQ.CLAIMS.UPDATE +type ServerAPIClaimUpdateResponse struct { + Server *ServerInfo `json:"server"` + Data *ClaimUpdateStatus `json:"data,omitempty"` + Error *ClaimUpdateError `json:"error,omitempty"` +} + +type ClaimUpdateError struct { + Account string `json:"account,omitempty"` + Code int `json:"code"` + Description string `json:"description,omitempty"` +} + +type ClaimUpdateStatus struct { + Account string `json:"account,omitempty"` + Code int `json:"code,omitempty"` + Message string `json:"message,omitempty"` +} + func respondToUpdate(s *Server, respSubj string, acc string, message string, err error) { if err == nil { - if acc == "" { + if acc == _EMPTY_ { s.Debugf("%s", message) } else { s.Debugf("%s - %s", message, acc) } } else { - if acc == "" { + if acc == _EMPTY_ { s.Errorf("%s - %s", message, err) } else { s.Errorf("%s - %s - %s", message, acc, err) } } - if respSubj == "" { + if respSubj == _EMPTY_ { return } - server := &ServerInfo{} - response := map[string]interface{}{"server": server} - m := map[string]interface{}{} - if acc != "" { - m["account"] = acc + + response := ServerAPIClaimUpdateResponse{ + Server: &ServerInfo{}, } + if err == nil { - m["code"] = http.StatusOK - m["message"] = message - response["data"] = m + response.Data = &ClaimUpdateStatus{ + Account: acc, + Code: http.StatusOK, + Message: message, + } } else { - m["code"] = http.StatusInternalServerError - m["description"] = fmt.Sprintf("%s - %v", message, err) - response["error"] = m + response.Error = &ClaimUpdateError{ + Account: acc, + Code: http.StatusInternalServerError, + Description: fmt.Sprintf("%s - %v", message, err), + } } - s.sendInternalMsgLocked(respSubj, _EMPTY_, server, response) + + s.sendInternalMsgLocked(respSubj, _EMPTY_, response.Server, response) } func handleListRequest(store *DirJWTStore, s *Server, reply string) { - if reply == "" { + if reply == _EMPTY_ { return } accIds := make([]string, 0, 1024) @@ -3408,19 +4228,18 @@ func handleListRequest(store *DirJWTStore, s *Server, reply string) { } else { s.Debugf("list request responded with %d account ids", len(accIds)) server := &ServerInfo{} - response := map[string]interface{}{"server": server, "data": accIds} + response := map[string]any{"server": server, "data": accIds} s.sendInternalMsgLocked(reply, _EMPTY_, server, response) } } func handleDeleteRequest(store *DirJWTStore, s *Server, msg []byte, reply string) { - var accIds []interface{} + var accIds []any var subj, sysAccName string if sysAcc := s.SystemAccount(); sysAcc != nil { sysAccName = sysAcc.GetName() } - // TODO Can allow keys (issuer) to delete accounts they issued and operator key to delete all accounts. - // For now only operator is allowed to delete + // Only operator and operator signing key are allowed to delete gk, err := jwt.DecodeGeneric(string(msg)) if err == nil { subj = gk.Subject @@ -3428,18 +4247,16 @@ func handleDeleteRequest(store *DirJWTStore, s *Server, msg []byte, reply string err = fmt.Errorf("delete must be enabled in server config") } else if subj != gk.Issuer { err = fmt.Errorf("not self signed") - } else if !s.isTrustedIssuer(gk.Issuer) { + } else if _, ok := store.operator[gk.Issuer]; !ok { err = fmt.Errorf("not trusted") - } else if store.operator != gk.Issuer { - err = fmt.Errorf("needs to be the operator operator") } else if list, ok := gk.Data["accounts"]; !ok { err = fmt.Errorf("malformed request") - } else if accIds, ok = list.([]interface{}); !ok { + } else if accIds, ok = list.([]any); !ok { err = fmt.Errorf("malformed request") } else { for _, entry := range accIds { if acc, ok := entry.(string); !ok || - acc == "" || !nkeys.IsValidPublicAccountKey(acc) { + acc == _EMPTY_ || !nkeys.IsValidPublicAccountKey(acc) { err = fmt.Errorf("malformed request") break } else if acc == sysAccName { @@ -3450,7 +4267,7 @@ func handleDeleteRequest(store *DirJWTStore, s *Server, msg []byte, reply string } } if err != nil { - respondToUpdate(s, reply, "", fmt.Sprintf("delete accounts request by %s failed", subj), err) + respondToUpdate(s, reply, _EMPTY_, fmt.Sprintf("delete accounts request by %s failed", subj), err) return } errs := []string{} @@ -3463,60 +4280,133 @@ func handleDeleteRequest(store *DirJWTStore, s *Server, msg []byte, reply string } } if len(errs) == 0 { - respondToUpdate(s, reply, "", fmt.Sprintf("deleted %d accounts", passCnt), nil) + respondToUpdate(s, reply, _EMPTY_, fmt.Sprintf("deleted %d accounts", passCnt), nil) } else { - respondToUpdate(s, reply, "", fmt.Sprintf("deleted %d accounts, failed for %d", passCnt, len(errs)), - errors.New(strings.Join(errs, "<\n"))) + respondToUpdate(s, reply, _EMPTY_, fmt.Sprintf("deleted %d accounts, failed for %d", passCnt, len(errs)), + errors.New(strings.Join(errs, "\n"))) } } -func getOperator(s *Server) (string, error) { +func getOperatorKeys(s *Server) (string, map[string]struct{}, bool, error) { var op string + var strict bool + keys := make(map[string]struct{}) if opts := s.getOpts(); opts != nil && len(opts.TrustedOperators) > 0 { op = opts.TrustedOperators[0].Subject + strict = opts.TrustedOperators[0].StrictSigningKeyUsage + if !strict { + keys[opts.TrustedOperators[0].Subject] = struct{}{} + } + for _, key := range opts.TrustedOperators[0].SigningKeys { + keys[key] = struct{}{} + } + } + if len(keys) == 0 { + return _EMPTY_, nil, false, fmt.Errorf("no operator key found") } - if op == "" { - return "", fmt.Errorf("no operator found") + return op, keys, strict, nil +} + +func claimValidate(claim *jwt.AccountClaims) error { + vr := &jwt.ValidationResults{} + claim.Validate(vr) + if vr.IsBlocking(false) { + return fmt.Errorf("validation errors: %v", vr.Errors()) } - return op, nil + return nil +} + +func removeCb(s *Server, pubKey string) { + v, ok := s.accounts.Load(pubKey) + if !ok { + return + } + a := v.(*Account) + s.Debugf("Disable account %s due to remove", pubKey) + a.mu.Lock() + // lock out new clients + a.msubs = 0 + a.mpay = 0 + a.mconns = 0 + a.mleafs = 0 + a.updated = time.Now() + jsa := a.js + a.mu.Unlock() + // set the account to be expired and disconnect clients + a.expiredTimeout() + // For JS, we need also to disable it. + if js := s.getJetStream(); js != nil && jsa != nil { + js.disableJetStream(jsa) + // Remove JetStream state in memory, this will be reset + // on the changed callback from the account in case it is + // enabled again. + a.js = nil + } + // We also need to remove all ServerImport subscriptions + a.removeAllServiceImportSubs() + a.mu.Lock() + a.clearExpirationTimer() + a.mu.Unlock() } func (dr *DirAccResolver) Start(s *Server) error { - op, err := getOperator(s) + op, opKeys, strict, err := getOperatorKeys(s) if err != nil { return err } dr.Lock() defer dr.Unlock() dr.Server = s - dr.operator = op + dr.operator = opKeys dr.DirJWTStore.changed = func(pubKey string) { - if v, ok := s.accounts.Load(pubKey); !ok { - } else if jwt, err := dr.LoadAcc(pubKey); err != nil { - s.Errorf("update got error on load: %v", err) - } else if err := s.updateAccountWithClaimJWT(v.(*Account), jwt); err != nil { - s.Errorf("update resulted in error %v", err) + if v, ok := s.accounts.Load(pubKey); ok { + if theJwt, err := dr.LoadAcc(pubKey); err != nil { + s.Errorf("DirResolver - Update got error on load: %v", err) + } else { + acc := v.(*Account) + if err = s.updateAccountWithClaimJWT(acc, theJwt); err != nil { + s.Errorf("DirResolver - Update for account %q resulted in error %v", pubKey, err) + } else { + if _, jsa, err := acc.checkForJetStream(); err != nil { + if !IsNatsErr(err, JSNotEnabledForAccountErr) { + s.Warnf("DirResolver - Error checking for JetStream support for account %q: %v", pubKey, err) + } + } else if jsa == nil { + if err = s.configJetStream(acc, nil); err != nil { + s.Errorf("DirResolver - Error configuring JetStream for account %q: %v", pubKey, err) + } + } + } + } } } + dr.DirJWTStore.deleted = func(pubKey string) { + removeCb(s, pubKey) + } packRespIb := s.newRespInbox() for _, reqSub := range []string{accUpdateEventSubjOld, accUpdateEventSubjNew} { // subscribe to account jwt update requests - if _, err := s.sysSubscribe(fmt.Sprintf(reqSub, "*"), func(_ *subscription, _ *client, subj, resp string, msg []byte) { - pubKey := "" + if _, err := s.sysSubscribe(fmt.Sprintf(reqSub, "*"), func(_ *subscription, _ *client, _ *Account, subj, resp string, msg []byte) { + var pubKey string tk := strings.Split(subj, tsep) if len(tk) == accUpdateTokensNew { pubKey = tk[accReqAccIndex] } else if len(tk) == accUpdateTokensOld { pubKey = tk[accUpdateAccIdxOld] } else { - s.Debugf("jwt update skipped due to bad subject %q", subj) + s.Debugf("DirResolver - jwt update skipped due to bad subject %q", subj) return } if claim, err := jwt.DecodeAccountClaims(string(msg)); err != nil { - respondToUpdate(s, resp, pubKey, "jwt update resulted in error", err) + respondToUpdate(s, resp, "n/a", "jwt update resulted in error", err) + } else if err := claimValidate(claim); err != nil { + respondToUpdate(s, resp, claim.Subject, "jwt validation failed", err) } else if claim.Subject != pubKey { err := errors.New("subject does not match jwt content") respondToUpdate(s, resp, pubKey, "jwt update resulted in error", err) + } else if claim.Issuer == op && strict { + err := errors.New("operator requires issuer to be a signing key") + respondToUpdate(s, resp, pubKey, "jwt update resulted in error", err) } else if err := dr.save(pubKey, string(msg)); err != nil { respondToUpdate(s, resp, pubKey, "jwt update resulted in error", err) } else { @@ -3526,9 +4416,17 @@ func (dr *DirAccResolver) Start(s *Server) error { return fmt.Errorf("error setting up update handling: %v", err) } } - if _, err := s.sysSubscribe(accClaimsReqSubj, func(_ *subscription, _ *client, subj, resp string, msg []byte) { + if _, err := s.sysSubscribe(accClaimsReqSubj, func(_ *subscription, c *client, _ *Account, _, resp string, msg []byte) { + // As this is a raw message, we need to extract payload and only decode claims from it, + // in case request is sent with headers. + _, msg = c.msgParts(msg) if claim, err := jwt.DecodeAccountClaims(string(msg)); err != nil { respondToUpdate(s, resp, "n/a", "jwt update resulted in error", err) + } else if claim.Issuer == op && strict { + err := errors.New("operator requires issuer to be a signing key") + respondToUpdate(s, resp, claim.Subject, "jwt update resulted in error", err) + } else if err := claimValidate(claim); err != nil { + respondToUpdate(s, resp, claim.Subject, "jwt validation failed", err) } else if err := dr.save(claim.Subject, string(msg)); err != nil { respondToUpdate(s, resp, claim.Subject, "jwt update resulted in error", err) } else { @@ -3538,65 +4436,72 @@ func (dr *DirAccResolver) Start(s *Server) error { return fmt.Errorf("error setting up update handling: %v", err) } // respond to lookups with our version - if _, err := s.sysSubscribe(fmt.Sprintf(accLookupReqSubj, "*"), func(_ *subscription, _ *client, subj, reply string, msg []byte) { - if reply == "" { + if _, err := s.sysSubscribe(fmt.Sprintf(accLookupReqSubj, "*"), func(_ *subscription, _ *client, _ *Account, subj, reply string, msg []byte) { + if reply == _EMPTY_ { return } tk := strings.Split(subj, tsep) if len(tk) != accLookupReqTokens { return } - if theJWT, err := dr.DirJWTStore.LoadAcc(tk[accReqAccIndex]); err != nil { - s.Errorf("Merging resulted in error: %v", err) + accName := tk[accReqAccIndex] + if theJWT, err := dr.DirJWTStore.LoadAcc(accName); err != nil { + if errors.Is(err, fs.ErrNotExist) { + s.Debugf("DirResolver - Could not find account %q", accName) + // Reply with empty response to signal absence of JWT to others. + s.sendInternalMsgLocked(reply, _EMPTY_, nil, nil) + } else { + s.Errorf("DirResolver - Error looking up account %q: %v", accName, err) + } } else { - s.sendInternalMsgLocked(reply, "", nil, []byte(theJWT)) + s.sendInternalMsgLocked(reply, _EMPTY_, nil, []byte(theJWT)) } }); err != nil { return fmt.Errorf("error setting up lookup request handling: %v", err) } // respond to pack requests with one or more pack messages - // an empty message signifies the end of the response responder - if _, err := s.sysSubscribeQ(accPackReqSubj, "responder", func(_ *subscription, _ *client, _, reply string, theirHash []byte) { - if reply == "" { + // an empty message signifies the end of the response responder. + if _, err := s.sysSubscribeQ(accPackReqSubj, "responder", func(_ *subscription, _ *client, _ *Account, _, reply string, theirHash []byte) { + if reply == _EMPTY_ { return } ourHash := dr.DirJWTStore.Hash() if bytes.Equal(theirHash, ourHash[:]) { - s.sendInternalMsgLocked(reply, "", nil, []byte{}) - s.Debugf("pack request matches hash %x", ourHash[:]) + s.sendInternalMsgLocked(reply, _EMPTY_, nil, []byte{}) + s.Debugf("DirResolver - Pack request matches hash %x", ourHash[:]) } else if err := dr.DirJWTStore.PackWalk(1, func(partialPackMsg string) { - s.sendInternalMsgLocked(reply, "", nil, []byte(partialPackMsg)) + s.sendInternalMsgLocked(reply, _EMPTY_, nil, []byte(partialPackMsg)) }); err != nil { // let them timeout - s.Errorf("pack request error: %v", err) + s.Errorf("DirResolver - Pack request error: %v", err) } else { - s.Debugf("pack request hash %x - finished responding with hash %x", theirHash, ourHash) - s.sendInternalMsgLocked(reply, "", nil, []byte{}) + s.Debugf("DirResolver - Pack request hash %x - finished responding with hash %x", theirHash, ourHash) + s.sendInternalMsgLocked(reply, _EMPTY_, nil, []byte{}) } }); err != nil { return fmt.Errorf("error setting up pack request handling: %v", err) } // respond to list requests with one message containing all account ids - if _, err := s.sysSubscribe(accListReqSubj, func(_ *subscription, _ *client, _, reply string, _ []byte) { + if _, err := s.sysSubscribe(accListReqSubj, func(_ *subscription, _ *client, _ *Account, _, reply string, _ []byte) { handleListRequest(dr.DirJWTStore, s, reply) }); err != nil { return fmt.Errorf("error setting up list request handling: %v", err) } - if _, err := s.sysSubscribe(accDeleteReqSubj, func(_ *subscription, _ *client, _, reply string, msg []byte) { + if _, err := s.sysSubscribe(accDeleteReqSubj, func(_ *subscription, _ *client, _ *Account, _, reply string, msg []byte) { handleDeleteRequest(dr.DirJWTStore, s, msg, reply) }); err != nil { return fmt.Errorf("error setting up delete request handling: %v", err) } // embed pack responses into store - if _, err := s.sysSubscribe(packRespIb, func(_ *subscription, _ *client, _, _ string, msg []byte) { + if _, err := s.sysSubscribe(packRespIb, func(_ *subscription, _ *client, _ *Account, _, _ string, msg []byte) { hash := dr.DirJWTStore.Hash() if len(msg) == 0 { // end of response stream - s.Debugf("Merging Finished and resulting in: %x", dr.DirJWTStore.Hash()) + s.Debugf("DirResolver - Merging finished and resulting in: %x", dr.DirJWTStore.Hash()) return } else if err := dr.DirJWTStore.Merge(string(msg)); err != nil { - s.Errorf("Merging resulted in error: %v", err) + s.Errorf("DirResolver - Merging resulted in error: %v", err) } else { - s.Debugf("Merging succeeded and changed %x to %x", hash, dr.DirJWTStore.Hash()) + s.Debugf("DirResolver - Merging succeeded and changed %x to %x", hash, dr.DirJWTStore.Hash()) } }); err != nil { return fmt.Errorf("error setting up pack response handling: %v", err) @@ -3614,7 +4519,7 @@ func (dr *DirAccResolver) Start(s *Server) error { case <-ticker.C: } ourHash := dr.DirJWTStore.Hash() - s.Debugf("Checking store state: %x", ourHash) + s.Debugf("DirResolver - Checking store state: %x", ourHash) s.sendInternalMsgLocked(accPackReqSubj, packRespIb, nil, ourHash[:]) } }) @@ -3623,16 +4528,17 @@ func (dr *DirAccResolver) Start(s *Server) error { } func (dr *DirAccResolver) Fetch(name string) (string, error) { - if theJWT, err := dr.LoadAcc(name); theJWT != "" { + if theJWT, err := dr.LoadAcc(name); theJWT != _EMPTY_ { return theJWT, nil } else { dr.Lock() srv := dr.Server + to := dr.fetchTimeout dr.Unlock() if srv == nil { - return "", err + return _EMPTY_, err } - return srv.fetch(dr, name) // lookup from other server + return srv.fetch(dr, name, to) // lookup from other server } } @@ -3640,22 +4546,45 @@ func (dr *DirAccResolver) Store(name, jwt string) error { return dr.saveIfNewer(name, jwt) } -func NewDirAccResolver(path string, limit int64, syncInterval time.Duration, delete bool) (*DirAccResolver, error) { +type DirResOption func(s *DirAccResolver) error + +// limits the amount of time spent waiting for an account fetch to complete +func FetchTimeout(to time.Duration) DirResOption { + return func(r *DirAccResolver) error { + if to <= time.Duration(0) { + return fmt.Errorf("Fetch timeout %v is too smal", to) + } + r.fetchTimeout = to + return nil + } +} + +func (dr *DirAccResolver) apply(opts ...DirResOption) error { + for _, o := range opts { + if err := o(dr); err != nil { + return err + } + } + return nil +} + +func NewDirAccResolver(path string, limit int64, syncInterval time.Duration, delete deleteType, opts ...DirResOption) (*DirAccResolver, error) { if limit == 0 { limit = math.MaxInt64 } if syncInterval <= 0 { syncInterval = time.Minute } - deleteType := NoDelete - if delete { - deleteType = RenameDeleted - } - store, err := NewExpiringDirJWTStore(path, false, true, deleteType, 0, limit, false, 0, nil) + store, err := NewExpiringDirJWTStore(path, false, true, delete, 0, limit, false, 0, nil) if err != nil { return nil, err } - return &DirAccResolver{store, nil, syncInterval}, nil + + res := &DirAccResolver{store, nil, syncInterval, DEFAULT_ACCOUNT_FETCH_TIMEOUT} + if err := res.apply(opts...); err != nil { + return nil, err + } + return res, nil } // Caching resolver using nats for lookups and making use of a directory for storage @@ -3664,31 +4593,46 @@ type CacheDirAccResolver struct { ttl time.Duration } -func (s *Server) fetch(res AccountResolver, name string) (string, error) { +func (s *Server) fetch(res AccountResolver, name string, timeout time.Duration) (string, error) { if s == nil { - return "", ErrNoAccountResolver + return _EMPTY_, ErrNoAccountResolver } respC := make(chan []byte, 1) accountLookupRequest := fmt.Sprintf(accLookupReqSubj, name) s.mu.Lock() if s.sys == nil || s.sys.replies == nil { s.mu.Unlock() - return "", fmt.Errorf("eventing shut down") + return _EMPTY_, fmt.Errorf("eventing shut down") } + // Resolver will wait for detected active servers to reply + // before serving an error in case there weren't any found. + expectedServers := len(s.sys.servers) replySubj := s.newRespInbox() replies := s.sys.replies + // Store our handler. - replies[replySubj] = func(sub *subscription, _ *client, subject, _ string, msg []byte) { - clone := make([]byte, len(msg)) - copy(clone, msg) + replies[replySubj] = func(sub *subscription, _ *client, _ *Account, subject, _ string, msg []byte) { + var clone []byte + isEmpty := len(msg) == 0 + if !isEmpty { + clone = make([]byte, len(msg)) + copy(clone, msg) + } s.mu.Lock() + defer s.mu.Unlock() + expectedServers-- + // Skip empty responses until getting all the available servers. + if isEmpty && expectedServers > 0 { + return + } + // Use the first valid response if there is still interest or + // one of the empty responses to signal that it was not found. if _, ok := replies[replySubj]; ok { select { - case respC <- clone: // only use first response and only if there is still interest + case respC <- clone: default: } } - s.mu.Unlock() } s.sendInternalMsg(accountLookupRequest, replySubj, nil, []byte{}) quit := s.quitCh @@ -3698,10 +4642,12 @@ func (s *Server) fetch(res AccountResolver, name string) (string, error) { select { case <-quit: err = errors.New("fetching jwt failed due to shutdown") - case <-time.After(fetchTimeout): + case <-time.After(timeout): err = errors.New("fetching jwt timed out") case m := <-respC: - if err = res.Store(name, string(m)); err == nil { + if len(m) == 0 { + err = errors.New("account jwt not found") + } else if err = res.Store(name, string(m)); err == nil { theJWT = string(m) } } @@ -3712,7 +4658,7 @@ func (s *Server) fetch(res AccountResolver, name string) (string, error) { return theJWT, err } -func NewCacheDirAccResolver(path string, limit int64, ttl time.Duration, _ ...dirJWTStoreOption) (*CacheDirAccResolver, error) { +func NewCacheDirAccResolver(path string, limit int64, ttl time.Duration, opts ...DirResOption) (*CacheDirAccResolver, error) { if limit <= 0 { limit = 1_000 } @@ -3720,37 +4666,44 @@ func NewCacheDirAccResolver(path string, limit int64, ttl time.Duration, _ ...di if err != nil { return nil, err } - return &CacheDirAccResolver{DirAccResolver{store, nil, 0}, ttl}, nil + res := &CacheDirAccResolver{DirAccResolver{store, nil, 0, DEFAULT_ACCOUNT_FETCH_TIMEOUT}, ttl} + if err := res.apply(opts...); err != nil { + return nil, err + } + return res, nil } func (dr *CacheDirAccResolver) Start(s *Server) error { - op, err := getOperator(s) + op, opKeys, strict, err := getOperatorKeys(s) if err != nil { return err } dr.Lock() defer dr.Unlock() dr.Server = s - dr.operator = op + dr.operator = opKeys dr.DirJWTStore.changed = func(pubKey string) { if v, ok := s.accounts.Load(pubKey); !ok { - } else if jwt, err := dr.LoadAcc(pubKey); err != nil { - s.Errorf("update got error on load: %v", err) - } else if err := s.updateAccountWithClaimJWT(v.(*Account), jwt); err != nil { - s.Errorf("update resulted in error %v", err) + } else if theJwt, err := dr.LoadAcc(pubKey); err != nil { + s.Errorf("DirResolver - Update got error on load: %v", err) + } else if err := s.updateAccountWithClaimJWT(v.(*Account), theJwt); err != nil { + s.Errorf("DirResolver - Update resulted in error %v", err) } } + dr.DirJWTStore.deleted = func(pubKey string) { + removeCb(s, pubKey) + } for _, reqSub := range []string{accUpdateEventSubjOld, accUpdateEventSubjNew} { // subscribe to account jwt update requests - if _, err := s.sysSubscribe(fmt.Sprintf(reqSub, "*"), func(_ *subscription, _ *client, subj, resp string, msg []byte) { - pubKey := "" + if _, err := s.sysSubscribe(fmt.Sprintf(reqSub, "*"), func(_ *subscription, _ *client, _ *Account, subj, resp string, msg []byte) { + var pubKey string tk := strings.Split(subj, tsep) if len(tk) == accUpdateTokensNew { pubKey = tk[accReqAccIndex] } else if len(tk) == accUpdateTokensOld { pubKey = tk[accUpdateAccIdxOld] } else { - s.Debugf("jwt update cache skipped due to bad subject %q", subj) + s.Debugf("DirResolver - jwt update cache skipped due to bad subject %q", subj) return } if claim, err := jwt.DecodeAccountClaims(string(msg)); err != nil { @@ -3758,8 +4711,13 @@ func (dr *CacheDirAccResolver) Start(s *Server) error { } else if claim.Subject != pubKey { err := errors.New("subject does not match jwt content") respondToUpdate(s, resp, pubKey, "jwt update cache resulted in error", err) + } else if claim.Issuer == op && strict { + err := errors.New("operator requires issuer to be a signing key") + respondToUpdate(s, resp, pubKey, "jwt update cache resulted in error", err) } else if _, ok := s.accounts.Load(pubKey); !ok { respondToUpdate(s, resp, pubKey, "jwt update cache skipped", nil) + } else if err := claimValidate(claim); err != nil { + respondToUpdate(s, resp, claim.Subject, "jwt update cache validation failed", err) } else if err := dr.save(pubKey, string(msg)); err != nil { respondToUpdate(s, resp, pubKey, "jwt update cache resulted in error", err) } else { @@ -3769,11 +4727,19 @@ func (dr *CacheDirAccResolver) Start(s *Server) error { return fmt.Errorf("error setting up update handling: %v", err) } } - if _, err := s.sysSubscribe(accClaimsReqSubj, func(_ *subscription, _ *client, subj, resp string, msg []byte) { + if _, err := s.sysSubscribe(accClaimsReqSubj, func(_ *subscription, c *client, _ *Account, _, resp string, msg []byte) { + // As this is a raw message, we need to extract payload and only decode claims from it, + // in case request is sent with headers. + _, msg = c.msgParts(msg) if claim, err := jwt.DecodeAccountClaims(string(msg)); err != nil { respondToUpdate(s, resp, "n/a", "jwt update cache resulted in error", err) + } else if claim.Issuer == op && strict { + err := errors.New("operator requires issuer to be a signing key") + respondToUpdate(s, resp, claim.Subject, "jwt update cache resulted in error", err) } else if _, ok := s.accounts.Load(claim.Subject); !ok { respondToUpdate(s, resp, claim.Subject, "jwt update cache skipped", nil) + } else if err := claimValidate(claim); err != nil { + respondToUpdate(s, resp, claim.Subject, "jwt update cache validation failed", err) } else if err := dr.save(claim.Subject, string(msg)); err != nil { respondToUpdate(s, resp, claim.Subject, "jwt update cache resulted in error", err) } else { @@ -3783,12 +4749,12 @@ func (dr *CacheDirAccResolver) Start(s *Server) error { return fmt.Errorf("error setting up update handling: %v", err) } // respond to list requests with one message containing all account ids - if _, err := s.sysSubscribe(accListReqSubj, func(_ *subscription, _ *client, _, reply string, _ []byte) { + if _, err := s.sysSubscribe(accListReqSubj, func(_ *subscription, _ *client, _ *Account, _, reply string, _ []byte) { handleListRequest(dr.DirJWTStore, s, reply) }); err != nil { return fmt.Errorf("error setting up list request handling: %v", err) } - if _, err := s.sysSubscribe(accDeleteReqSubj, func(_ *subscription, _ *client, _, reply string, msg []byte) { + if _, err := s.sysSubscribe(accDeleteReqSubj, func(_ *subscription, _ *client, _ *Account, _, reply string, msg []byte) { handleDeleteRequest(dr.DirJWTStore, s, msg, reply) }); err != nil { return fmt.Errorf("error setting up list request handling: %v", err) @@ -3800,181 +4766,3 @@ func (dr *CacheDirAccResolver) Start(s *Server) error { func (dr *CacheDirAccResolver) Reload() error { return dr.DirAccResolver.Reload() } - -// Transforms for arbitrarily mapping subjects from one to another for maps, tees and filters. -// These can also be used for proper mapping on wildcard exports/imports. -// These will be grouped and caching and locking are assumed to be in the upper layers. -type transform struct { - src, dest string - dtoks []string - stoks []string - dtpi []int8 -} - -// Helper to pull raw place holder index. Returns -1 if not a place holder. -func placeHolderIndex(token string) int { - if len(token) > 1 && token[0] == '$' { - var tp int - if n, err := fmt.Sscanf(token, "$%d", &tp); err == nil && n == 1 { - return tp - } - } - return -1 -} - -// newTransform will create a new transform checking the src and dest subjects for accuracy. -func newTransform(src, dest string) (*transform, error) { - // Both entries need to be valid subjects. - sv, stokens, npwcs, hasFwc := subjectInfo(src) - dv, dtokens, dnpwcs, dHasFwc := subjectInfo(dest) - - // Make sure both are valid, match fwc if present and there are no pwcs in the dest subject. - if !sv || !dv || dnpwcs > 0 || hasFwc != dHasFwc { - return nil, ErrBadSubject - } - - var dtpi []int8 - - // If the src has partial wildcards then the dest needs to have the token place markers. - if npwcs > 0 || hasFwc { - // We need to count to make sure that the dest has token holders for the pwcs. - sti := make(map[int]int) - for i, token := range stokens { - if len(token) == 1 && token[0] == pwc { - sti[len(sti)+1] = i - } - } - - nphs := 0 - for _, token := range dtokens { - tp := placeHolderIndex(token) - if tp >= 0 { - if tp > npwcs { - return nil, ErrBadSubject - } - nphs++ - // Now build up our runtime mapping from dest to source tokens. - dtpi = append(dtpi, int8(sti[tp])) - } else { - dtpi = append(dtpi, -1) - } - } - - if nphs != npwcs { - return nil, ErrBadSubject - } - } - - return &transform{src: src, dest: dest, dtoks: dtokens, stoks: stokens, dtpi: dtpi}, nil -} - -// match will take a literal published subject that is associated with a client and will match and transform -// the subject if possible. -// TODO(dlc) - We could add in client here to allow for things like foo -> foo.$ACCOUNT -func (tr *transform) match(subject string) (string, error) { - // Tokenize the subject. This should always be a literal subject. - tsa := [32]string{} - tts := tsa[:0] - start := 0 - for i := 0; i < len(subject); i++ { - if subject[i] == btsep { - tts = append(tts, subject[start:i]) - start = i + 1 - } - } - tts = append(tts, subject[start:]) - if !isValidLiteralSubject(tts) { - return "", ErrBadSubject - } - - if isSubsetMatch(tts, tr.src) { - return tr.transform(tts) - } - return "", ErrNoTransforms -} - -// Do not need to match, just transform. -func (tr *transform) transformSubject(subject string) (string, error) { - // Tokenize the subject. - tsa := [32]string{} - tts := tsa[:0] - start := 0 - for i := 0; i < len(subject); i++ { - if subject[i] == btsep { - tts = append(tts, subject[start:i]) - start = i + 1 - } - } - tts = append(tts, subject[start:]) - return tr.transform(tts) -} - -// Do a transform on the subject to the dest subject. -func (tr *transform) transform(tokens []string) (string, error) { - if len(tr.dtpi) == 0 { - return tr.dest, nil - } - - var b strings.Builder - var token string - - // We need to walk destination tokens and create the mapped subject pulling tokens from src. - // This is slow and that is ok, transforms should have caching layer in front for mapping transforms - // and export/import semantics with streams and services. - li := len(tr.dtpi) - 1 - for i, index := range tr.dtpi { - // <0 means use destination token. - if index < 0 { - token = tr.dtoks[i] - // Break if fwc - if len(token) == 1 && token[0] == fwc { - break - } - } else { - // >= 0 means use source map index to figure out which source token to pull. - token = tokens[index] - } - b.WriteString(token) - if i < li { - b.WriteByte(btsep) - } - } - - // We may have more source tokens available. This happens with ">". - if tr.dtoks[len(tr.dtoks)-1] == ">" { - for sli, i := len(tokens)-1, len(tr.stoks)-1; i < len(tokens); i++ { - b.WriteString(tokens[i]) - if i < sli { - b.WriteByte(btsep) - } - } - } - return b.String(), nil -} - -// Reverse a transform. -func (tr *transform) reverse() *transform { - if len(tr.dtpi) == 0 { - rtr, _ := newTransform(tr.dest, tr.src) - return rtr - } - // If we are here we need to dynamically get the correct reverse - // of this transform. - nsrc, phs := transformUntokenize(tr.dest) - var nda []string - for _, token := range tr.stoks { - if token == "*" { - if len(phs) == 0 { - // TODO(dlc) - Should not happen - return nil - } - nda = append(nda, phs[0]) - phs = phs[1:] - } else { - nda = append(nda, token) - } - } - ndest := strings.Join(nda, tsep) - rtr, _ := newTransform(nsrc, ndest) - return rtr -} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ats/ats.go b/vendor/github.com/nats-io/nats-server/v2/server/ats/ats.go new file mode 100644 index 0000000..50045bf --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/ats/ats.go @@ -0,0 +1,86 @@ +// Copyright 2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ats controls the go routines for the access time service. +// This allows more efficient unixnano operations for cache access times. +// We will have one per binary (usually per server). +package ats + +import ( + "sync/atomic" + "time" +) + +// Update every 100ms for gathering access time in unix nano. +const TickInterval = 100 * time.Millisecond + +var ( + // Our unix nano time. + utime atomic.Int64 + // How may registered users do we have, controls lifetime of Go routine. + refs atomic.Int64 + // To signal the shutdown of the Go routine. + done chan struct{} +) + +func init() { + // Initialize our done chan. + done = make(chan struct{}, 1) +} + +// Register usage. This will happen on filestore creation. +func Register() { + if v := refs.Add(1); v == 1 { + // This is the first to register (could also go up and down), + // so spin up Go routine and grab initial time. + utime.Store(time.Now().UnixNano()) + + go func() { + ticker := time.NewTicker(TickInterval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + utime.Store(time.Now().UnixNano()) + case <-done: + return + } + } + }() + } +} + +// Unregister usage. We will shutdown the go routine if no more registered users. +func Unregister() { + if v := refs.Add(-1); v == 0 { + done <- struct{}{} + } else if v < 0 { + refs.Store(0) + panic("unbalanced unregister for access time state") + } +} + +// Will load the access time from an atomic. +// If no one has registered this will return 0 or stale data. +// It is the responsibility of the user to properly register and unregister. +func AccessTime() int64 { + // Return last updated time. + v := utime.Load() + if v == 0 { + // Always register a time, the worst case is a stale time. + // On startup, we can register in parallel and could previously panic. + v = time.Now().UnixNano() + utime.Store(v) + } + return v +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/auth.go b/vendor/github.com/nats-io/nats-server/v2/server/auth.go index 0e04304..ce917a0 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/auth.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/auth.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,15 +14,19 @@ package server import ( + "crypto/sha256" + "crypto/subtle" "crypto/tls" "crypto/x509/pkix" "encoding/asn1" "encoding/base64" + "encoding/hex" "fmt" "net" "net/url" "regexp" "strings" + "sync/atomic" "time" "github.com/nats-io/jwt/v2" @@ -39,19 +43,24 @@ type Authentication interface { // ClientAuthentication is an interface for client authentication type ClientAuthentication interface { - // Get options associated with a client - GetOpts() *clientOpts - // If TLS is enabled, TLS ConnectionState, nil otherwise + // GetOpts gets options associated with a client + GetOpts() *ClientOpts + // GetTLSConnectionState if TLS is enabled, TLS ConnectionState, nil otherwise GetTLSConnectionState() *tls.ConnectionState - // Optionally map a user after auth. + // RegisterUser optionally map a user after auth. RegisterUser(*User) // RemoteAddress expose the connection information of the client RemoteAddress() net.Addr + // GetNonce is the nonce presented to the user in the INFO line + GetNonce() []byte + // Kind indicates what type of connection this is matching defined constants like CLIENT, ROUTER, GATEWAY, LEAF etc + Kind() int } // NkeyUser is for multiple nkey based users type NkeyUser struct { Nkey string `json:"user"` + Issued int64 `json:"issued,omitempty"` // this is a copy of the issued at (iat) field in the jwt Permissions *Permissions `json:"permissions,omitempty"` Account *Account `json:"account,omitempty"` SigningKey string `json:"signing_key,omitempty"` @@ -64,6 +73,7 @@ type User struct { Password string `json:"password"` Permissions *Permissions `json:"permissions,omitempty"` Account *Account `json:"account,omitempty"` + ConnectionDeadline time.Time `json:"connection_deadline,omitempty"` AllowedConnectionTypes map[string]struct{} `json:"connection_types,omitempty"` } @@ -75,7 +85,16 @@ func (u *User) clone() *User { } clone := &User{} *clone = *u + // Account is not cloned because it is always by reference to an existing struct. clone.Permissions = u.Permissions.clone() + + if u.AllowedConnectionTypes != nil { + clone.AllowedConnectionTypes = make(map[string]struct{}) + for k, v := range u.AllowedConnectionTypes { + clone.AllowedConnectionTypes[k] = v + } + } + return clone } @@ -87,7 +106,16 @@ func (n *NkeyUser) clone() *NkeyUser { } clone := &NkeyUser{} *clone = *n + // Account is not cloned because it is always by reference to an existing struct. clone.Permissions = n.Permissions.clone() + + if n.AllowedConnectionTypes != nil { + clone.AllowedConnectionTypes = make(map[string]struct{}) + for k, v := range n.AllowedConnectionTypes { + clone.AllowedConnectionTypes[k] = v + } + } + return clone } @@ -164,16 +192,20 @@ func (p *Permissions) clone() *Permissions { // Lock is assumed held. func (s *Server) checkAuthforWarnings() { warn := false - if s.opts.Password != "" && !isBcrypt(s.opts.Password) { + opts := s.getOpts() + if opts.Password != _EMPTY_ && !isBcrypt(opts.Password) { warn = true } for _, u := range s.users { // Skip warn if using TLS certs based auth // unless a password has been left in the config. - if u.Password == "" && s.opts.TLSMap { + if u.Password == _EMPTY_ && opts.TLSMap { + continue + } + // Check if this is our internal sys client created on the fly. + if s.sysAccOnlyNoAuthUser != _EMPTY_ && u.Username == s.sysAccOnlyNoAuthUser { continue } - if !isBcrypt(u.Password) { warn = true break @@ -238,12 +270,12 @@ func (s *Server) configureAuthorization() { // This just checks and sets up the user map if we have multiple users. if opts.CustomClientAuthentication != nil { s.info.AuthRequired = true - } else if len(s.trustedKeys) > 0 { + } else if s.trustedKeys != nil { s.info.AuthRequired = true } else if opts.Nkeys != nil || opts.Users != nil { s.nkeys, s.users = s.buildNkeysAndUsersFromOptions(opts.Nkeys, opts.Users) s.info.AuthRequired = true - } else if opts.Username != "" || opts.Authorization != "" { + } else if opts.Username != _EMPTY_ || opts.Authorization != _EMPTY_ { s.info.AuthRequired = true } else { s.users = nil @@ -255,6 +287,30 @@ func (s *Server) configureAuthorization() { s.wsConfigAuth(&opts.Websocket) // And for mqtt config s.mqttConfigAuth(&opts.MQTT) + + // Check for server configured auth callouts. + if opts.AuthCallout != nil { + s.mu.Unlock() + // Give operator log entries if not valid account and auth_users. + _, err := s.lookupAccount(opts.AuthCallout.Account) + s.mu.Lock() + if err != nil { + s.Errorf("Authorization callout account %q not valid", opts.AuthCallout.Account) + } + for _, u := range opts.AuthCallout.AuthUsers { + // Check for user in users and nkeys since this is server config. + var found bool + if len(s.users) > 0 { + _, found = s.users[u] + } + if !found && len(s.nkeys) > 0 { + _, found = s.nkeys[u] + } + if !found { + s.Errorf("Authorization callout user %q not valid: %v", u, err) + } + } + } } // Takes the given slices of NkeyUser and User options and build @@ -326,14 +382,207 @@ func (s *Server) isClientAuthorized(c *client) bool { // Check custom auth first, then jwts, then nkeys, then // multiple users with TLS map if enabled, then token, // then single user/pass. - if opts.CustomClientAuthentication != nil { - return opts.CustomClientAuthentication.Check(c) + if opts.CustomClientAuthentication != nil && !opts.CustomClientAuthentication.Check(c) { + return false + } + + if opts.CustomClientAuthentication == nil && !s.processClientOrLeafAuthentication(c, opts) { + return false + } + + if c.kind == CLIENT || c.kind == LEAF { + // Generate an event if we have a system account. + s.accountConnectEvent(c) } - return s.processClientOrLeafAuthentication(c, opts) + return true } -func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) bool { +// returns false if the client needs to be disconnected +func (c *client) matchesPinnedCert(tlsPinnedCerts PinnedCertSet) bool { + if tlsPinnedCerts == nil { + return true + } + tlsState := c.GetTLSConnectionState() + if tlsState == nil || len(tlsState.PeerCertificates) == 0 || tlsState.PeerCertificates[0] == nil { + c.Debugf("Failed pinned cert test as client did not provide a certificate") + return false + } + sha := sha256.Sum256(tlsState.PeerCertificates[0].RawSubjectPublicKeyInfo) + keyId := hex.EncodeToString(sha[:]) + if _, ok := tlsPinnedCerts[keyId]; !ok { + c.Debugf("Failed pinned cert test for key id: %s", keyId) + return false + } + return true +} + +var ( + mustacheRE = regexp.MustCompile(`{{2}([^}]+)}{2}`) +) + +func processUserPermissionsTemplate(lim jwt.UserPermissionLimits, ujwt *jwt.UserClaims, acc *Account) (jwt.UserPermissionLimits, error) { + nArrayCartesianProduct := func(a ...[]string) [][]string { + c := 1 + for _, a := range a { + c *= len(a) + } + if c == 0 { + return nil + } + p := make([][]string, c) + b := make([]string, c*len(a)) + n := make([]int, len(a)) + s := 0 + for i := range p { + e := s + len(a) + pi := b[s:e] + p[i] = pi + s = e + for j, n := range n { + pi[j] = a[j][n] + } + for j := len(n) - 1; j >= 0; j-- { + n[j]++ + if n[j] < len(a[j]) { + break + } + n[j] = 0 + } + } + return p + } + isTag := func(op string) []string { + if strings.EqualFold("tag(", op[:4]) && strings.HasSuffix(op, ")") { + v := strings.TrimPrefix(op, "tag(") + v = strings.TrimSuffix(v, ")") + return []string{"tag", v} + } else if strings.EqualFold("account-tag(", op[:12]) && strings.HasSuffix(op, ")") { + v := strings.TrimPrefix(op, "account-tag(") + v = strings.TrimSuffix(v, ")") + return []string{"account-tag", v} + } + return nil + } + applyTemplate := func(list jwt.StringList, failOnBadSubject bool) (jwt.StringList, error) { + found := false + FOR_FIND: + for i := 0; i < len(list); i++ { + // check if templates are present + if mustacheRE.MatchString(list[i]) { + found = true + break FOR_FIND + } + } + if !found { + return list, nil + } + // process the templates + emittedList := make([]string, 0, len(list)) + for i := 0; i < len(list); i++ { + // find all the templates {{}} in this acl + tokens := mustacheRE.FindAllString(list[i], -1) + srcs := make([]string, len(tokens)) + values := make([][]string, len(tokens)) + hasTags := false + for tokenNum, tk := range tokens { + srcs[tokenNum] = tk + op := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(tk, "{{"), "}}")) + if strings.EqualFold("name()", op) { + values[tokenNum] = []string{ujwt.Name} + } else if strings.EqualFold("subject()", op) { + values[tokenNum] = []string{ujwt.Subject} + } else if strings.EqualFold("account-name()", op) { + acc.mu.RLock() + values[tokenNum] = []string{acc.nameTag} + acc.mu.RUnlock() + } else if strings.EqualFold("account-subject()", op) { + // this always has an issuer account since this is a scoped signer + values[tokenNum] = []string{ujwt.IssuerAccount} + } else if isTag(op) != nil { + hasTags = true + match := isTag(op) + var tags jwt.TagList + if match[0] == "account-tag" { + acc.mu.RLock() + tags = acc.tags + acc.mu.RUnlock() + } else { + tags = ujwt.Tags + } + tagPrefix := fmt.Sprintf("%s:", strings.ToLower(match[1])) + var valueList []string + for _, tag := range tags { + if strings.HasPrefix(tag, tagPrefix) { + tagValue := strings.TrimPrefix(tag, tagPrefix) + valueList = append(valueList, tagValue) + } + } + if len(valueList) != 0 { + values[tokenNum] = valueList + } else if failOnBadSubject { + return nil, fmt.Errorf("generated invalid subject %q: %q is not defined", list[i], match[1]) + } else { + // generate an invalid subject? + values[tokenNum] = []string{" "} + } + } else if failOnBadSubject { + return nil, fmt.Errorf("template operation in %q: %q is not defined", list[i], op) + } + } + if !hasTags { + subj := list[i] + for idx, m := range srcs { + subj = strings.Replace(subj, m, values[idx][0], -1) + } + if IsValidSubject(subj) { + emittedList = append(emittedList, subj) + } else if failOnBadSubject { + return nil, fmt.Errorf("generated invalid subject") + } + } else { + a := nArrayCartesianProduct(values...) + for _, aa := range a { + subj := list[i] + for j := 0; j < len(srcs); j++ { + subj = strings.Replace(subj, srcs[j], aa[j], -1) + } + if IsValidSubject(subj) { + emittedList = append(emittedList, subj) + } else if failOnBadSubject { + return nil, fmt.Errorf("generated invalid subject") + } + } + } + } + return emittedList, nil + } + + subAllowWasNotEmpty := len(lim.Permissions.Sub.Allow) > 0 + pubAllowWasNotEmpty := len(lim.Permissions.Pub.Allow) > 0 + + var err error + if lim.Permissions.Sub.Allow, err = applyTemplate(lim.Permissions.Sub.Allow, false); err != nil { + return jwt.UserPermissionLimits{}, err + } else if lim.Permissions.Sub.Deny, err = applyTemplate(lim.Permissions.Sub.Deny, true); err != nil { + return jwt.UserPermissionLimits{}, err + } else if lim.Permissions.Pub.Allow, err = applyTemplate(lim.Permissions.Pub.Allow, false); err != nil { + return jwt.UserPermissionLimits{}, err + } else if lim.Permissions.Pub.Deny, err = applyTemplate(lim.Permissions.Pub.Deny, true); err != nil { + return jwt.UserPermissionLimits{}, err + } + + // if pub/sub allow were not empty, but are empty post template processing, add in a "deny >" to compensate + if subAllowWasNotEmpty && len(lim.Permissions.Sub.Allow) == 0 { + lim.Permissions.Sub.Deny.Add(">") + } + if pubAllowWasNotEmpty && len(lim.Permissions.Pub.Allow) == 0 { + lim.Permissions.Pub.Deny.Add(">") + } + return lim, nil +} + +func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) (authorized bool) { var ( nkey *NkeyUser juc *jwt.UserClaims @@ -343,6 +592,96 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo err error ao bool // auth override ) + + // Check if we have auth callouts enabled at the server level or in the bound account. + defer func() { + // Default reason + reason := AuthenticationViolation.String() + // No-op + if juc == nil && opts.AuthCallout == nil { + if !authorized { + s.sendAccountAuthErrorEvent(c, c.acc, reason) + } + return + } + // We have a juc, check if externally managed, i.e. should be delegated + // to the auth callout service. + if juc != nil && !acc.hasExternalAuth() { + if !authorized { + s.sendAccountAuthErrorEvent(c, c.acc, reason) + } + return + } + // Check config-mode. The global account is a condition since users that + // are not found in the config are implicitly bound to the global account. + // This means those users should be implicitly delegated to auth callout + // if configured. Exclude LEAF connections from this check. + if c.kind != LEAF && juc == nil && opts.AuthCallout != nil && c.acc.Name != globalAccountName { + // If no allowed accounts are defined, then all accounts are in scope. + // Otherwise see if the account is in the list. + delegated := len(opts.AuthCallout.AllowedAccounts) == 0 + if !delegated { + for _, n := range opts.AuthCallout.AllowedAccounts { + if n == c.acc.Name { + delegated = true + break + } + } + } + + // Not delegated, so return with previous authorized result. + if !delegated { + if !authorized { + s.sendAccountAuthErrorEvent(c, c.acc, reason) + } + return + } + } + + // We have auth callout set here. + var skip bool + // Check if we are on the list of auth_users. + userID := c.getRawAuthUser() + if juc != nil { + skip = acc.isExternalAuthUser(userID) + } else { + for _, u := range opts.AuthCallout.AuthUsers { + if userID == u { + skip = true + break + } + } + } + + // If we are here we have an auth callout defined and we have failed auth so far + // so we will callout to our auth backend for processing. + if !skip { + authorized, reason = s.processClientOrLeafCallout(c, opts) + } + // Check if we are authorized and in the auth callout account, and if so add in deny publish permissions for the auth subject. + if authorized { + var authAccountName string + if juc == nil && opts.AuthCallout != nil { + authAccountName = opts.AuthCallout.Account + } else if juc != nil { + authAccountName = acc.Name + } + c.mu.Lock() + if c.acc != nil && c.acc.Name == authAccountName { + c.mergeDenyPermissions(pub, []string{AuthCalloutSubject}) + } + c.mu.Unlock() + } else { + // If we are here we failed external authorization. + // Send an account scoped event. Server config mode acc will be nil, + // so lookup the auth callout assigned account, that is where this will be sent. + if acc == nil { + acc, _ = s.lookupAccount(opts.AuthCallout.Account) + } + s.sendAccountAuthErrorEvent(c, acc, reason) + } + }() + s.mu.Lock() authRequired := s.info.AuthRequired if !authRequired { @@ -361,10 +700,11 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo return true } var ( - username string - password string - token string - noAuthUser string + username string + password string + token string + noAuthUser string + pinnedAcounts map[string]struct{} ) tlsMap := opts.TLSMap if c.kind == CLIENT { @@ -399,8 +739,14 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo } else { tlsMap = opts.LeafNode.TLSMap } + if !ao { noAuthUser = opts.NoAuthUser + // If a leaf connects using websocket, and websocket{} block has a no_auth_user + // use that one instead. + if c.kind == LEAF && c.isWebsocket() && opts.Websocket.NoAuthUser != _EMPTY_ { + noAuthUser = opts.Websocket.NoAuthUser + } username = opts.Username password = opts.Password token = opts.Authorization @@ -408,7 +754,10 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo // Check if we have trustedKeys defined in the server. If so we require a user jwt. if s.trustedKeys != nil { - if c.opts.JWT == "" { + if c.opts.JWT == _EMPTY_ && opts.DefaultSentinel != _EMPTY_ { + c.opts.JWT = opts.DefaultSentinel + } + if c.opts.JWT == _EMPTY_ { s.mu.Unlock() c.Debugf("Authentication requires a user JWT") return false @@ -427,34 +776,46 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo c.Debugf("User JWT no longer valid: %+v", vr) return false } + pinnedAcounts = opts.resolverPinnedAccounts } // Check if we have nkeys or users for client. hasNkeys := len(s.nkeys) > 0 hasUsers := len(s.users) > 0 - if hasNkeys && c.opts.Nkey != "" { - nkey, ok = s.nkeys[c.opts.Nkey] - if !ok || !c.connectionTypeAllowed(nkey.AllowedConnectionTypes) { - s.mu.Unlock() - return false + if hasNkeys { + if (c.kind == CLIENT || c.kind == LEAF) && noAuthUser != _EMPTY_ && + c.opts.Username == _EMPTY_ && c.opts.Password == _EMPTY_ && c.opts.Token == _EMPTY_ && c.opts.Nkey == _EMPTY_ { + if _, exists := s.nkeys[noAuthUser]; exists { + c.mu.Lock() + c.opts.Nkey = noAuthUser + c.mu.Unlock() + } } - } else if hasUsers { + if c.opts.Nkey != _EMPTY_ { + nkey, ok = s.nkeys[c.opts.Nkey] + if !ok || !c.connectionTypeAllowed(nkey.AllowedConnectionTypes) { + s.mu.Unlock() + return false + } + } + } + if hasUsers && nkey == nil { // Check if we are tls verify and are mapping users from the client_certificate. if tlsMap { authorized := checkClientTLSCertSubject(c, func(u string, certDN *ldap.DN, _ bool) (string, bool) { // First do literal lookup using the resulting string representation // of RDNSequence as implemented by the pkix package from Go. - if u != "" { + if u != _EMPTY_ { usr, ok := s.users[u] if !ok || !c.connectionTypeAllowed(usr.AllowedConnectionTypes) { - return "", ok + return _EMPTY_, false } user = usr - return usr.Username, ok + return usr.Username, true } if certDN == nil { - return "", false + return _EMPTY_, false } // Look through the accounts for a DN that is equal to the one @@ -487,26 +848,29 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo return usr.Username, true } } - return "", false + return _EMPTY_, false }) if !authorized { s.mu.Unlock() return false } - if c.opts.Username != "" { + if c.opts.Username != _EMPTY_ { s.Warnf("User %q found in connect proto, but user required from cert", c.opts.Username) } // Already checked that the client didn't send a user in connect // but we set it here to be able to identify it in the logs. c.opts.Username = user.Username } else { - if c.kind == CLIENT && c.opts.Username == "" && noAuthUser != "" { + if (c.kind == CLIENT || c.kind == LEAF) && noAuthUser != _EMPTY_ && + c.opts.Username == _EMPTY_ && c.opts.Password == _EMPTY_ && c.opts.Token == _EMPTY_ { if u, exists := s.users[noAuthUser]; exists { + c.mu.Lock() c.opts.Username = u.Username c.opts.Password = u.Password + c.mu.Unlock() } } - if c.opts.Username != "" { + if c.opts.Username != _EMPTY_ { user, ok = s.users[c.opts.Username] if !ok || !c.connectionTypeAllowed(user.AllowedConnectionTypes) { s.mu.Unlock() @@ -520,6 +884,54 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo // If we have a jwt and a userClaim, make sure we have the Account, etc associated. // We need to look up the account. This will use an account resolver if one is present. if juc != nil { + issuer := juc.Issuer + if juc.IssuerAccount != _EMPTY_ { + issuer = juc.IssuerAccount + } + if pinnedAcounts != nil { + if _, ok := pinnedAcounts[issuer]; !ok { + c.Debugf("Account %s not listed as operator pinned account", issuer) + atomic.AddUint64(&s.pinnedAccFail, 1) + return false + } + } + if acc, err = s.LookupAccount(issuer); acc == nil { + c.Debugf("Account JWT lookup error: %v", err) + return false + } + acc.mu.RLock() + aissuer := acc.Issuer + acc.mu.RUnlock() + if !s.isTrustedIssuer(aissuer) { + c.Debugf("Account JWT not signed by trusted operator") + return false + } + if scope, ok := acc.hasIssuer(juc.Issuer); !ok { + c.Debugf("User JWT issuer is not known") + return false + } else if scope != nil { + if err := scope.ValidateScopedSigner(juc); err != nil { + c.Debugf("User JWT is not valid: %v", err) + return false + } else if uSc, ok := scope.(*jwt.UserScope); !ok { + c.Debugf("User JWT is not valid") + return false + } else if juc.UserPermissionLimits, err = processUserPermissionsTemplate(uSc.Template, juc, acc); err != nil { + c.Debugf("User JWT generated invalid permissions") + return false + } + } + if acc.IsExpired() { + c.Debugf("Account JWT has expired") + return false + } + if juc.BearerToken && acc.failBearer() { + c.Debugf("Account does not allow bearer tokens") + return false + } + // We check the allowed connection types, but only after processing + // of scoped signer (so that it updates `juc` with what is defined + // in the account. allowedConnTypes, err := convertAllowedConnectionTypes(juc.AllowedConnectionTypes) if err != nil { // We got an error, which means some connection types were unknown. As long as @@ -542,38 +954,16 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo if len(allowedConnTypes) == 0 { return false } - err = nil } if !c.connectionTypeAllowed(allowedConnTypes) { c.Debugf("Connection type not allowed") return false } - issuer := juc.Issuer - if juc.IssuerAccount != "" { - issuer = juc.IssuerAccount - } - if acc, err = s.LookupAccount(issuer); acc == nil { - c.Debugf("Account JWT lookup error: %v", err) - return false - } - if !s.isTrustedIssuer(acc.Issuer) { - c.Debugf("Account JWT not signed by trusted operator") - return false - } - // this only executes IF there's an issuer on the Juc - otherwise the account is already vetted - if juc.IssuerAccount != "" && !acc.hasIssuer(juc.Issuer) { - c.Debugf("User JWT issuer is not known") - return false - } - if acc.IsExpired() { - c.Debugf("Account JWT has expired") - return false - } // skip validation of nonce when presented with a bearer token // FIXME: if BearerToken is only for WSS, need check for server with that port enabled if !juc.BearerToken { // Verify the signature against the nonce. - if c.opts.Sig == "" { + if c.opts.Sig == _EMPTY_ { c.Debugf("Signature missing") return false } @@ -614,39 +1004,71 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo if err := c.RegisterNkeyUser(nkey); err != nil { return false } + + // Warn about JetStream restrictions + if c.perms != nil { + deniedPub := []string{} + deniedSub := []string{} + for _, sub := range denyAllJs { + if c.perms.pub.deny != nil { + if c.perms.pub.deny.HasInterest(sub) { + deniedPub = append(deniedPub, sub) + } + } + if c.perms.sub.deny != nil { + if c.perms.sub.deny.HasInterest(sub) { + deniedSub = append(deniedSub, sub) + } + } + } + if len(deniedPub) > 0 || len(deniedSub) > 0 { + c.Noticef("Connected %s has JetStream denied on pub: %v sub: %v", c.kindString(), deniedPub, deniedSub) + } + } + // Hold onto the user's public key. + c.mu.Lock() c.pubKey = juc.Subject - - // Generate an event if we have a system account. - s.accountConnectEvent(c) + c.tags = juc.Tags + c.nameTag = juc.Name + c.mu.Unlock() // Check if we need to set an auth timer if the user jwt expires. c.setExpiration(juc.Claims(), validFor) + + acc.mu.RLock() + c.Debugf("Authenticated JWT: %s %q (claim-name: %q, claim-tags: %q) "+ + "signed with %q by Account %q (claim-name: %q, claim-tags: %q) signed with %q has mappings %t accused %p", + c.kindString(), juc.Subject, juc.Name, juc.Tags, juc.Issuer, issuer, acc.nameTag, acc.tags, acc.Issuer, acc.hasMappings(), acc) + acc.mu.RUnlock() return true } if nkey != nil { - if c.opts.Sig == "" { - c.Debugf("Signature missing") - return false - } - sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig) - if err != nil { - // Allow fallback to normal base64. - sig, err = base64.StdEncoding.DecodeString(c.opts.Sig) + // If we did not match noAuthUser check signature which is required. + if nkey.Nkey != noAuthUser { + if c.opts.Sig == _EMPTY_ { + c.Debugf("Signature missing") + return false + } + sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig) if err != nil { - c.Debugf("Signature not valid base64") + // Allow fallback to normal base64. + sig, err = base64.StdEncoding.DecodeString(c.opts.Sig) + if err != nil { + c.Debugf("Signature not valid base64") + return false + } + } + pub, err := nkeys.FromPublicKey(c.opts.Nkey) + if err != nil { + c.Debugf("User nkey not valid: %v", err) + return false + } + if err := pub.Verify(c.nonce, sig); err != nil { + c.Debugf("Signature not verified") return false } - } - pub, err := nkeys.FromPublicKey(c.opts.Nkey) - if err != nil { - c.Debugf("User nkey not valid: %v", err) - return false - } - if err := pub.Verify(c.nonce, sig); err != nil { - c.Debugf("Signature not verified") - return false } if err := c.RegisterNkeyUser(nkey); err != nil { return false @@ -659,16 +1081,14 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) boo // for pub/sub authorizations. if ok { c.RegisterUser(user) - // Generate an event if we have a system account and this is not the $G account. - s.accountConnectEvent(c) } return ok } if c.kind == CLIENT { - if token != "" { + if token != _EMPTY_ { return comparePasswords(token, c.opts.Token) - } else if username != "" { + } else if username != _EMPTY_ { if username != c.opts.Username { return false } @@ -764,7 +1184,7 @@ func checkClientTLSCertSubject(c *client, fn tlsMapAuthFn) bool { // https://github.com/golang/go/issues/12342 dn, err := ldap.FromRawCertSubject(cert.RawSubject) if err == nil { - if match, ok := fn("", dn, false); ok { + if match, ok := fn(_EMPTY_, dn, false); ok { c.Debugf("Using DistinguishedNameMatch for auth [%q]", match) return true } @@ -815,7 +1235,7 @@ URLS: } hostLabels := strings.Split(strings.ToLower(url.Hostname()), ".") // Following https://tools.ietf.org/html/rfc6125#section-6.4.3, should not => will not, may => will not - // The wilcard * never matches multiple label and only matches the left most label. + // The wildcard * never matches multiple label and only matches the left most label. if len(hostLabels) != len(dnsAltNameLabels) { continue URLS } @@ -841,28 +1261,28 @@ func (s *Server) isRouterAuthorized(c *client) bool { // Check custom auth first, then TLS map if enabled // then single user/pass. - if s.opts.CustomRouterAuthentication != nil { - return s.opts.CustomRouterAuthentication.Check(c) + if opts.CustomRouterAuthentication != nil { + return opts.CustomRouterAuthentication.Check(c) } - if opts.Cluster.TLSMap || opts.Cluster.TLSCheckKnwonURLs { + if opts.Cluster.TLSMap || opts.Cluster.TLSCheckKnownURLs { return checkClientTLSCertSubject(c, func(user string, _ *ldap.DN, isDNSAltName bool) (string, bool) { - if user == "" { - return "", false + if user == _EMPTY_ { + return _EMPTY_, false } - if opts.Cluster.TLSCheckKnwonURLs && isDNSAltName { + if opts.Cluster.TLSCheckKnownURLs && isDNSAltName { if dnsAltNameMatches(dnsAltNameLabels(user), opts.Routes) { - return "", true + return _EMPTY_, true } } if opts.Cluster.TLSMap && opts.Cluster.Username == user { - return "", true + return _EMPTY_, true } - return "", false + return _EMPTY_, false }) } - if opts.Cluster.Username == "" { + if opts.Cluster.Username == _EMPTY_ { return true } @@ -883,25 +1303,25 @@ func (s *Server) isGatewayAuthorized(c *client) bool { // Check whether TLS map is enabled, otherwise use single user/pass. if opts.Gateway.TLSMap || opts.Gateway.TLSCheckKnownURLs { return checkClientTLSCertSubject(c, func(user string, _ *ldap.DN, isDNSAltName bool) (string, bool) { - if user == "" { - return "", false + if user == _EMPTY_ { + return _EMPTY_, false } if opts.Gateway.TLSCheckKnownURLs && isDNSAltName { labels := dnsAltNameLabels(user) for _, gw := range opts.Gateway.Gateways { if gw != nil && dnsAltNameMatches(labels, gw.URLs) { - return "", true + return _EMPTY_, true } } } if opts.Gateway.TLSMap && opts.Gateway.Username == user { - return "", true + return _EMPTY_, true } - return "", false + return _EMPTY_, false }) } - if opts.Gateway.Username == "" { + if opts.Gateway.Username == _EMPTY_ { return true } @@ -943,10 +1363,37 @@ func (s *Server) isLeafNodeAuthorized(c *client) bool { } // If leafnodes config has an authorization{} stanza, this takes precedence. - // The user in CONNECT mutch match. We will bind to the account associated + // The user in CONNECT must match. We will bind to the account associated // with that user (from the leafnode's authorization{} config). if opts.LeafNode.Username != _EMPTY_ { return isAuthorized(opts.LeafNode.Username, opts.LeafNode.Password, opts.LeafNode.Account) + } else if opts.LeafNode.Nkey != _EMPTY_ { + if c.opts.Nkey != opts.LeafNode.Nkey { + return false + } + if c.opts.Sig == _EMPTY_ { + c.Debugf("Signature missing") + return false + } + sig, err := base64.RawURLEncoding.DecodeString(c.opts.Sig) + if err != nil { + // Allow fallback to normal base64. + sig, err = base64.StdEncoding.DecodeString(c.opts.Sig) + if err != nil { + c.Debugf("Signature not valid base64") + return false + } + } + pub, err := nkeys.FromPublicKey(c.opts.Nkey) + if err != nil { + c.Debugf("User nkey not valid: %v", err) + return false + } + if err := pub.Verify(c.nonce, sig); err != nil { + c.Debugf("Signature not verified") + return false + } + return s.registerLeafWithAccount(c, opts.LeafNode.Account) } else if len(opts.LeafNode.Users) > 0 { if opts.LeafNode.TLSMap { var user *User @@ -958,18 +1405,23 @@ func (s *Server) isLeafNodeAuthorized(c *client) bool { return u, true } } - return "", false + return _EMPTY_, false }) if !found { return false } - if c.opts.Username != "" { + if c.opts.Username != _EMPTY_ { s.Warnf("User %q found in connect proto, but user required from cert", c.opts.Username) } c.opts.Username = user.Username + // EMPTY will result in $G + accName := _EMPTY_ + if user.Account != nil { + accName = user.Account.GetName() + } // This will authorize since are using an existing user, // but it will also register with proper account. - return isAuthorized(user.Username, user.Password, user.Account.GetName()) + return isAuthorized(user.Username, user.Password, accName) } // This is expected to be a very small array. @@ -990,11 +1442,11 @@ func (s *Server) isLeafNodeAuthorized(c *client) bool { // Still, if the CONNECT has some user info, we will bind to the // user's account or to the specified default account (if provided) // or to the global account. - return s.processClientOrLeafAuthentication(c, opts) + return s.isClientAuthorized(c) } // Support for bcrypt stored passwords and tokens. -var validBcryptPrefix = regexp.MustCompile(`^\$2[a,b,x,y]{1}\$\d{2}\$.*`) +var validBcryptPrefix = regexp.MustCompile(`^\$2[abxy]\$\d{2}\$.*`) // isBcrypt checks whether the given password or token is bcrypted. func isBcrypt(password string) bool { @@ -1011,13 +1463,22 @@ func comparePasswords(serverPassword, clientPassword string) bool { if err := bcrypt.CompareHashAndPassword([]byte(serverPassword), []byte(clientPassword)); err != nil { return false } - } else if serverPassword != clientPassword { - return false + } else { + // stringToBytes should be constant-time near enough compared to + // turning a string into []byte normally. + spass := stringToBytes(serverPassword) + cpass := stringToBytes(clientPassword) + if subtle.ConstantTimeCompare(spass, cpass) == 0 { + return false + } } return true } func validateAuth(o *Options) error { + if err := validatePinnedCerts(o.TLSPinnedCerts); err != nil { + return err + } for _, u := range o.Users { if err := validateAllowedConnectionTypes(u.AllowedConnectionTypes); err != nil { return err @@ -1035,7 +1496,10 @@ func validateAllowedConnectionTypes(m map[string]struct{}) error { for ct := range m { ctuc := strings.ToUpper(ct) switch ctuc { - case jwt.ConnectionTypeStandard, jwt.ConnectionTypeWebsocket, jwt.ConnectionTypeLeafnode, jwt.ConnectionTypeMqtt: + case jwt.ConnectionTypeStandard, jwt.ConnectionTypeWebsocket, + jwt.ConnectionTypeLeafnode, jwt.ConnectionTypeLeafnodeWS, + jwt.ConnectionTypeMqtt, jwt.ConnectionTypeMqttWS, + jwt.ConnectionTypeInProcess: default: return fmt.Errorf("unknown connection type %q", ct) } @@ -1048,21 +1512,27 @@ func validateAllowedConnectionTypes(m map[string]struct{}) error { } func validateNoAuthUser(o *Options, noAuthUser string) error { - if noAuthUser == "" { + if noAuthUser == _EMPTY_ { return nil } if len(o.TrustedOperators) > 0 { return fmt.Errorf("no_auth_user not compatible with Trusted Operator") } - if o.Users == nil { - return fmt.Errorf(`no_auth_user: "%s" present, but users are not defined`, noAuthUser) + + if o.Nkeys == nil && o.Users == nil { + return fmt.Errorf(`no_auth_user: "%s" present, but users/nkeys are not defined`, noAuthUser) } for _, u := range o.Users { if u.Username == noAuthUser { return nil } } + for _, u := range o.Nkeys { + if u.Nkey == noAuthUser { + return nil + } + } return fmt.Errorf( - `no_auth_user: "%s" not present as user in authorization block or account configuration`, + `no_auth_user: "%s" not present as user or nkey in authorization block or account configuration`, noAuthUser) } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/auth_callout.go b/vendor/github.com/nats-io/nats-server/v2/server/auth_callout.go new file mode 100644 index 0000000..038d53b --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/auth_callout.go @@ -0,0 +1,480 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "crypto/tls" + "encoding/pem" + "errors" + "fmt" + "time" + "unicode" + + "github.com/nats-io/jwt/v2" + "github.com/nats-io/nkeys" +) + +const ( + AuthCalloutSubject = "$SYS.REQ.USER.AUTH" + AuthRequestSubject = "nats-authorization-request" + AuthRequestXKeyHeader = "Nats-Server-Xkey" +) + +// Process a callout on this client's behalf. +func (s *Server) processClientOrLeafCallout(c *client, opts *Options) (authorized bool, errStr string) { + isOperatorMode := len(opts.TrustedKeys) > 0 + + // this is the account the user connected in, or the one running the callout + var acc *Account + if !isOperatorMode && opts.AuthCallout != nil && opts.AuthCallout.Account != _EMPTY_ { + aname := opts.AuthCallout.Account + var err error + acc, err = s.LookupAccount(aname) + if err != nil { + errStr = fmt.Sprintf("No valid account %q for auth callout request: %v", aname, err) + s.Warnf(errStr) + return false, errStr + } + } else { + acc = c.acc + } + + // Check if we have been requested to encrypt. + var xkp nkeys.KeyPair + var xkey string + var pubAccXKey string + if !isOperatorMode && opts.AuthCallout != nil && opts.AuthCallout.XKey != _EMPTY_ { + pubAccXKey = opts.AuthCallout.XKey + } else if isOperatorMode { + pubAccXKey = acc.externalAuthXKey() + } + // If set grab server's xkey keypair and public key. + if pubAccXKey != _EMPTY_ { + // These are only set on creation, so lock not needed. + xkp, xkey = s.xkp, s.info.XKey + } + + // FIXME: so things like the server ID that get assigned, are used as a sort of nonce - but + // reality is that the keypair here, is generated, so the response generated a JWT has to be + // this user - no replay possible + // Create a keypair for the user. We will expect this public user to be in the signed response. + // This prevents replay attacks. + ukp, _ := nkeys.CreateUser() + pub, _ := ukp.PublicKey() + + reply := s.newRespInbox() + respCh := make(chan string, 1) + + decodeResponse := func(rc *client, rmsg []byte, acc *Account) (*jwt.UserClaims, error) { + account := acc.Name + _, msg := rc.msgParts(rmsg) + + // This signals not authorized. + // Since this is an account subscription will always have "\r\n". + if len(msg) <= LEN_CR_LF { + return nil, fmt.Errorf("auth callout violation: %q on account %q", "no reason supplied", account) + } + // Strip trailing CRLF. + msg = msg[:len(msg)-LEN_CR_LF] + encrypted := false + // If we sent an encrypted request the response could be encrypted as well. + // we are expecting the input to be `eyJ` if it is a JWT + if xkp != nil && len(msg) > 0 && !bytes.HasPrefix(msg, []byte(jwtPrefix)) { + var err error + msg, err = xkp.Open(msg, pubAccXKey) + if err != nil { + return nil, fmt.Errorf("error decrypting auth callout response on account %q: %v", account, err) + } + encrypted = true + } + + cr, err := jwt.DecodeAuthorizationResponseClaims(string(msg)) + if err != nil { + return nil, err + } + vr := jwt.CreateValidationResults() + cr.Validate(vr) + if len(vr.Issues) > 0 { + return nil, fmt.Errorf("authorization response had validation errors: %v", vr.Issues[0]) + } + + // the subject is the user id + if cr.Subject != pub { + return nil, errors.New("auth callout violation: auth callout response is not for expected user") + } + + // check the audience to be the server ID + if cr.Audience != s.info.ID { + return nil, errors.New("auth callout violation: auth callout response is not for server") + } + + // check if had an error message from the auth account + if cr.Error != _EMPTY_ { + return nil, fmt.Errorf("auth callout service returned an error: %v", cr.Error) + } + + // if response is encrypted none of this is needed + if isOperatorMode && !encrypted { + pkStr := cr.Issuer + if cr.IssuerAccount != _EMPTY_ { + pkStr = cr.IssuerAccount + } + if pkStr != account { + if _, ok := acc.signingKeys[pkStr]; !ok { + return nil, errors.New("auth callout signing key is unknown") + } + } + } + + return jwt.DecodeUserClaims(cr.Jwt) + } + + // getIssuerAccount returns the issuer (as per JWT) - it also asserts that + // only in operator mode we expect to receive `issuer_account`. + getIssuerAccount := func(arc *jwt.UserClaims, account string) (string, error) { + // Make sure correct issuer. + var issuer string + if opts.AuthCallout != nil { + issuer = opts.AuthCallout.Issuer + } else { + // Operator mode is who we send the request on unless switching accounts. + issuer = acc.Name + } + + // the jwt issuer can be a signing key + jwtIssuer := arc.Issuer + if arc.IssuerAccount != _EMPTY_ { + if !isOperatorMode { + // this should be invalid - effectively it would allow the auth callout + // to issue on another account which may be allowed given the configuration + // where the auth callout account can handle multiple different ones.. + return _EMPTY_, fmt.Errorf("error non operator mode account %q: attempted to use issuer_account", account) + } + jwtIssuer = arc.IssuerAccount + } + + if jwtIssuer != issuer { + if !isOperatorMode { + return _EMPTY_, fmt.Errorf("wrong issuer for auth callout response on account %q, expected %q got %q", account, issuer, jwtIssuer) + } else if !acc.isAllowedAcount(jwtIssuer) { + return _EMPTY_, fmt.Errorf("account %q not permitted as valid account option for auth callout for account %q", + arc.Issuer, account) + } + } + return jwtIssuer, nil + } + + getExpirationAndAllowedConnections := func(arc *jwt.UserClaims, account string) (time.Duration, map[string]struct{}, error) { + allowNow, expiration := validateTimes(arc) + if !allowNow { + c.Errorf("Outside connect times") + return 0, nil, fmt.Errorf("authorized user on account %q outside of valid connect times", account) + } + + allowedConnTypes, err := convertAllowedConnectionTypes(arc.User.AllowedConnectionTypes) + if err != nil { + c.Debugf("%v", err) + if len(allowedConnTypes) == 0 { + return 0, nil, fmt.Errorf("authorized user on account %q using invalid connection type", account) + } + } + return expiration, allowedConnTypes, nil + } + + assignAccountAndPermissions := func(arc *jwt.UserClaims, account string) (*Account, error) { + // Apply to this client. + var err error + issuerAccount, err := getIssuerAccount(arc, account) + if err != nil { + return nil, err + } + + // if we are not in operator mode, they can specify placement as a tag + var placement string + if !isOperatorMode { + // only allow placement if we are not in operator mode + placement = arc.Audience + } else { + placement = issuerAccount + } + + targetAcc, err := s.LookupAccount(placement) + if err != nil { + return nil, fmt.Errorf("no valid account %q for auth callout response on account %q: %v", placement, account, err) + } + if isOperatorMode { + // this will validate the signing key that emitted the user, and if it is a signing + // key it assigns the permissions from the target account + if scope, ok := targetAcc.hasIssuer(arc.Issuer); !ok { + return nil, fmt.Errorf("user JWT issuer %q is not known", arc.Issuer) + } else if scope != nil { + // this possibly has to be different because it could just be a plain issued by a non-scoped signing key + if err := scope.ValidateScopedSigner(arc); err != nil { + return nil, fmt.Errorf("user JWT is not valid: %v", err) + } else if uSc, ok := scope.(*jwt.UserScope); !ok { + return nil, fmt.Errorf("user JWT is not a valid scoped user") + } else if arc.User.UserPermissionLimits, err = processUserPermissionsTemplate(uSc.Template, arc, targetAcc); err != nil { + return nil, fmt.Errorf("user JWT generated invalid permissions: %v", err) + } + } + } + return targetAcc, nil + } + + processReply := func(_ *subscription, rc *client, racc *Account, subject, reply string, rmsg []byte) { + titleCase := func(m string) string { + r := []rune(m) + return string(append([]rune{unicode.ToUpper(r[0])}, r[1:]...)) + } + + arc, err := decodeResponse(rc, rmsg, racc) + if err != nil { + c.authViolation() + respCh <- titleCase(err.Error()) + return + } + vr := jwt.CreateValidationResults() + arc.Validate(vr) + if len(vr.Issues) > 0 { + c.authViolation() + respCh <- fmt.Sprintf("Error validating user JWT: %v", vr.Issues[0]) + return + } + + // Make sure that the user is what we requested. + if arc.Subject != pub { + c.authViolation() + respCh <- fmt.Sprintf("Expected authorized user of %q but got %q on account %q", pub, arc.Subject, racc.Name) + return + } + + expiration, allowedConnTypes, err := getExpirationAndAllowedConnections(arc, racc.Name) + if err != nil { + c.authViolation() + respCh <- titleCase(err.Error()) + return + } + + targetAcc, err := assignAccountAndPermissions(arc, racc.Name) + if err != nil { + c.authViolation() + respCh <- titleCase(err.Error()) + return + } + + // the JWT is cleared, because if in operator mode it may hold the JWT + // for the bearer token that connected to the callout if in operator mode + // the permissions are already set on the client, this prevents a decode + // on c.RegisterNKeyUser which would have wrong values + c.mu.Lock() + c.opts.JWT = _EMPTY_ + c.mu.Unlock() + + // Build internal user and bind to the targeted account. + nkuser := buildInternalNkeyUser(arc, allowedConnTypes, targetAcc) + if err := c.RegisterNkeyUser(nkuser); err != nil { + c.authViolation() + respCh <- fmt.Sprintf("Could not register auth callout user: %v", err) + return + } + + // See if the response wants to override the username. + if arc.Name != _EMPTY_ { + c.mu.Lock() + c.opts.Username = arc.Name + // Clear any others. + c.opts.Nkey = _EMPTY_ + c.pubKey = _EMPTY_ + c.opts.Token = _EMPTY_ + c.mu.Unlock() + } + + // Check if we need to set an auth timer if the user jwt expires. + c.setExpiration(arc.Claims(), expiration) + + respCh <- _EMPTY_ + } + + // create a subscription to receive a response from the authcallout + sub, err := acc.subscribeInternal(reply, processReply) + if err != nil { + errStr = fmt.Sprintf("Error setting up reply subscription for auth request: %v", err) + s.Warnf(errStr) + return false, errStr + } + defer acc.unsubscribeInternal(sub) + + // Build our request claims - jwt subject should be nkey + jwtSub := acc.Name + if opts.AuthCallout != nil { + jwtSub = opts.AuthCallout.Issuer + } + + // The public key of the server, if set is available on Varz.Key + // This means that when a service connects, it can now peer + // authenticate if it wants to - but that also means that it needs to be + // listening to cluster changes + claim := jwt.NewAuthorizationRequestClaims(jwtSub) + claim.Audience = AuthRequestSubject + // Set expected public user nkey. + claim.UserNkey = pub + + s.mu.RLock() + claim.Server = jwt.ServerID{ + Name: s.info.Name, + Host: s.info.Host, + ID: s.info.ID, + Version: s.info.Version, + Cluster: s.info.Cluster, + } + s.mu.RUnlock() + + // Tags + claim.Server.Tags = s.getOpts().Tags + + // Check if we have been requested to encrypt. + // FIXME: possibly this public key also needs to be on the + // Varz, because then it can be peer verified? + if xkp != nil { + claim.Server.XKey = xkey + } + + authTimeout := secondsToDuration(s.getOpts().AuthTimeout) + claim.Expires = time.Now().Add(time.Duration(authTimeout)).UTC().Unix() + + // Grab client info for the request. + c.mu.Lock() + c.fillClientInfo(&claim.ClientInformation) + c.fillConnectOpts(&claim.ConnectOptions) + // If we have a sig in the client opts, fill in nonce. + if claim.ConnectOptions.SignedNonce != _EMPTY_ { + claim.ClientInformation.Nonce = string(c.nonce) + } + + // TLS + if c.flags.isSet(handshakeComplete) && c.nc != nil { + var ct jwt.ClientTLS + conn := c.nc.(*tls.Conn) + cs := conn.ConnectionState() + ct.Version = tlsVersion(cs.Version) + ct.Cipher = tlsCipher(cs.CipherSuite) + // Check verified chains. + for _, vs := range cs.VerifiedChains { + var certs []string + for _, c := range vs { + blk := &pem.Block{ + Type: "CERTIFICATE", + Bytes: c.Raw, + } + certs = append(certs, string(pem.EncodeToMemory(blk))) + } + ct.VerifiedChains = append(ct.VerifiedChains, certs) + } + // If we do not have verified chains put in peer certs. + if len(ct.VerifiedChains) == 0 { + for _, c := range cs.PeerCertificates { + blk := &pem.Block{ + Type: "CERTIFICATE", + Bytes: c.Raw, + } + ct.Certs = append(ct.Certs, string(pem.EncodeToMemory(blk))) + } + } + claim.TLS = &ct + } + c.mu.Unlock() + + b, err := claim.Encode(s.kp) + if err != nil { + errStr = fmt.Sprintf("Error encoding auth request claim on account %q: %v", acc.Name, err) + s.Warnf(errStr) + return false, errStr + } + req := []byte(b) + var hdr []byte + + // Check if we have been asked to encrypt. + if xkp != nil { + req, err = xkp.Seal([]byte(req), pubAccXKey) + if err != nil { + errStr = fmt.Sprintf("Error encrypting auth request claim on account %q: %v", acc.Name, err) + s.Warnf(errStr) + return false, errStr + } + hdr = genHeader(hdr, AuthRequestXKeyHeader, xkey) + } + + // Send out our request. + if err := s.sendInternalAccountMsgWithReply(acc, AuthCalloutSubject, reply, hdr, req, false); err != nil { + errStr = fmt.Sprintf("Error sending authorization request: %v", err) + s.Debugf(errStr) + return false, errStr + } + select { + case errStr = <-respCh: + if authorized = errStr == _EMPTY_; !authorized { + s.Warnf(errStr) + } + case <-time.After(authTimeout): + s.Debugf(fmt.Sprintf("Authorization callout response not received in time on account %q", acc.Name)) + } + + return authorized, errStr +} + +// Fill in client information for the request. +// Lock should be held. +func (c *client) fillClientInfo(ci *jwt.ClientInformation) { + if c == nil || (c.kind != CLIENT && c.kind != LEAF && c.kind != JETSTREAM && c.kind != ACCOUNT) { + return + } + + // Do it this way to fail to compile if fields are added to jwt.ClientInformation. + *ci = jwt.ClientInformation{ + Host: c.host, + ID: c.cid, + User: c.getRawAuthUser(), + Name: c.opts.Name, + Tags: c.tags, + NameTag: c.nameTag, + Kind: c.kindString(), + Type: c.clientTypeString(), + MQTT: c.getMQTTClientID(), + } +} + +// Fill in client options. +// Lock should be held. +func (c *client) fillConnectOpts(opts *jwt.ConnectOptions) { + if c == nil || (c.kind != CLIENT && c.kind != LEAF && c.kind != JETSTREAM && c.kind != ACCOUNT) { + return + } + + o := c.opts + + // Do it this way to fail to compile if fields are added to jwt.ClientInformation. + *opts = jwt.ConnectOptions{ + JWT: o.JWT, + Nkey: o.Nkey, + SignedNonce: o.Sig, + Token: o.Token, + Username: o.Username, + Password: o.Password, + Name: o.Name, + Lang: o.Lang, + Version: o.Version, + Protocol: o.Protocol, + } +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/avl/seqset.go b/vendor/github.com/nats-io/nats-server/v2/server/avl/seqset.go new file mode 100644 index 0000000..de281d0 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/avl/seqset.go @@ -0,0 +1,678 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package avl + +import ( + "cmp" + "encoding/binary" + "errors" + "math/bits" + "slices" +) + +// SequenceSet is a memory and encoding optimized set for storing unsigned ints. +// +// SequenceSet is ~80-100 times more efficient memory wise than a map[uint64]struct{}. +// SequenceSet is ~1.75 times slower at inserts than the same map. +// SequenceSet is not thread safe. +// +// We use an AVL tree with nodes that hold bitmasks for set membership. +// +// Encoding will convert to a space optimized encoding using bitmasks. +type SequenceSet struct { + root *node // root node + size int // number of items + nodes int // number of nodes + // Having this here vs on the stack in Insert/Delete + // makes a difference in memory usage. + changed bool +} + +// Insert will insert the sequence into the set. +// The tree will be balanced inline. +func (ss *SequenceSet) Insert(seq uint64) { + if ss.root = ss.root.insert(seq, &ss.changed, &ss.nodes); ss.changed { + ss.changed = false + ss.size++ + } +} + +// Exists will return true iff the sequence is a member of this set. +func (ss *SequenceSet) Exists(seq uint64) bool { + for n := ss.root; n != nil; { + if seq < n.base { + n = n.l + continue + } else if seq >= n.base+numEntries { + n = n.r + continue + } + return n.exists(seq) + } + return false +} + +// SetInitialMin should be used to set the initial minimum sequence when known. +// This will more effectively utilize space versus self selecting. +// The set should be empty. +func (ss *SequenceSet) SetInitialMin(min uint64) error { + if !ss.IsEmpty() { + return ErrSetNotEmpty + } + ss.root, ss.nodes = &node{base: min, h: 1}, 1 + return nil +} + +// Delete will remove the sequence from the set. +// Will optionally remove nodes and rebalance. +// Returns where the sequence was set. +func (ss *SequenceSet) Delete(seq uint64) bool { + if ss == nil || ss.root == nil { + return false + } + ss.root = ss.root.delete(seq, &ss.changed, &ss.nodes) + if ss.changed { + ss.changed = false + ss.size-- + if ss.size == 0 { + ss.Empty() + } + return true + } + return false +} + +// Size returns the number of items in the set. +func (ss *SequenceSet) Size() int { + return ss.size +} + +// Nodes returns the number of nodes in the tree. +func (ss *SequenceSet) Nodes() int { + return ss.nodes +} + +// Empty will clear all items from a set. +func (ss *SequenceSet) Empty() { + ss.root = nil + ss.size = 0 + ss.nodes = 0 +} + +// IsEmpty is a fast check of the set being empty. +func (ss *SequenceSet) IsEmpty() bool { + if ss == nil || ss.root == nil { + return true + } + return false +} + +// Range will invoke the given function for each item in the set. +// They will range over the set in ascending order. +// If the callback returns false we terminate the iteration. +func (ss *SequenceSet) Range(f func(uint64) bool) { + ss.root.iter(f) +} + +// Heights returns the left and right heights of the tree. +func (ss *SequenceSet) Heights() (l, r int) { + if ss.root == nil { + return 0, 0 + } + if ss.root.l != nil { + l = ss.root.l.h + } + if ss.root.r != nil { + r = ss.root.r.h + } + return l, r +} + +// Returns min, max and number of set items. +func (ss *SequenceSet) State() (min, max, num uint64) { + if ss == nil || ss.root == nil { + return 0, 0, 0 + } + min, max = ss.MinMax() + return min, max, uint64(ss.Size()) +} + +// MinMax will return the minunum and maximum values in the set. +func (ss *SequenceSet) MinMax() (min, max uint64) { + if ss.root == nil { + return 0, 0 + } + for l := ss.root; l != nil; l = l.l { + if l.l == nil { + min = l.min() + } + } + for r := ss.root; r != nil; r = r.r { + if r.r == nil { + max = r.max() + } + } + return min, max +} + +func clone(src *node, target **node) { + if src == nil { + return + } + n := &node{base: src.base, bits: src.bits, h: src.h} + *target = n + clone(src.l, &n.l) + clone(src.r, &n.r) +} + +// Clone will return a clone of the given SequenceSet. +func (ss *SequenceSet) Clone() *SequenceSet { + if ss == nil { + return nil + } + css := &SequenceSet{nodes: ss.nodes, size: ss.size} + clone(ss.root, &css.root) + + return css +} + +// Union will union this SequenceSet with ssa. +func (ss *SequenceSet) Union(ssa ...*SequenceSet) { + for _, sa := range ssa { + sa.root.nodeIter(func(n *node) { + for nb, b := range n.bits { + for pos := uint64(0); b != 0; pos++ { + if b&1 == 1 { + seq := n.base + (uint64(nb) * uint64(bitsPerBucket)) + pos + ss.Insert(seq) + } + b >>= 1 + } + } + }) + } +} + +// Union will return a union of all sets. +func Union(ssa ...*SequenceSet) *SequenceSet { + if len(ssa) == 0 { + return nil + } + // Sort so we can clone largest. + slices.SortFunc(ssa, func(i, j *SequenceSet) int { return -cmp.Compare(i.Size(), j.Size()) }) // reverse order + ss := ssa[0].Clone() + + // Insert the rest through range call. + for i := 1; i < len(ssa); i++ { + ssa[i].Range(func(n uint64) bool { + ss.Insert(n) + return true + }) + } + return ss +} + +const ( + // Magic is used to identify the encode binary state.. + magic = uint8(22) + // Version + version = uint8(2) + // hdrLen + hdrLen = 2 + // minimum length of an encoded SequenceSet. + minLen = 2 + 8 // magic + version + num nodes + num entries. +) + +// EncodeLen returns the bytes needed for encoding. +func (ss SequenceSet) EncodeLen() int { + return minLen + (ss.Nodes() * ((numBuckets+1)*8 + 2)) +} + +func (ss SequenceSet) Encode(buf []byte) ([]byte, error) { + nn, encLen := ss.Nodes(), ss.EncodeLen() + + if cap(buf) < encLen { + buf = make([]byte, encLen) + } else { + buf = buf[:encLen] + } + + // TODO(dlc) - Go 1.19 introduced Append to not have to keep track. + // Once 1.20 is out we could change this over. + // Also binary.Write() is way slower, do not use. + + var le = binary.LittleEndian + buf[0], buf[1] = magic, version + i := hdrLen + le.PutUint32(buf[i:], uint32(nn)) + le.PutUint32(buf[i+4:], uint32(ss.size)) + i += 8 + ss.root.nodeIter(func(n *node) { + le.PutUint64(buf[i:], n.base) + i += 8 + for _, b := range n.bits { + le.PutUint64(buf[i:], b) + i += 8 + } + le.PutUint16(buf[i:], uint16(n.h)) + i += 2 + }) + return buf[:i], nil +} + +// ErrBadEncoding is returned when we can not decode properly. +var ( + ErrBadEncoding = errors.New("ss: bad encoding") + ErrBadVersion = errors.New("ss: bad version") + ErrSetNotEmpty = errors.New("ss: set not empty") +) + +// Decode returns the sequence set and number of bytes read from the buffer on success. +func Decode(buf []byte) (*SequenceSet, int, error) { + if len(buf) < minLen || buf[0] != magic { + return nil, -1, ErrBadEncoding + } + + switch v := buf[1]; v { + case 1: + return decodev1(buf) + case 2: + return decodev2(buf) + default: + return nil, -1, ErrBadVersion + } +} + +// Helper to decode v2. +func decodev2(buf []byte) (*SequenceSet, int, error) { + var le = binary.LittleEndian + index := 2 + nn := int(le.Uint32(buf[index:])) + sz := int(le.Uint32(buf[index+4:])) + index += 8 + + expectedLen := minLen + (nn * ((numBuckets+1)*8 + 2)) + if len(buf) < expectedLen { + return nil, -1, ErrBadEncoding + } + + ss, nodes := SequenceSet{size: sz}, make([]node, nn) + + for i := 0; i < nn; i++ { + n := &nodes[i] + n.base = le.Uint64(buf[index:]) + index += 8 + for bi := range n.bits { + n.bits[bi] = le.Uint64(buf[index:]) + index += 8 + } + n.h = int(le.Uint16(buf[index:])) + index += 2 + ss.insertNode(n) + } + + return &ss, index, nil +} + +// Helper to decode v1 into v2 which has fixed buckets of 32 vs 64 originally. +func decodev1(buf []byte) (*SequenceSet, int, error) { + var le = binary.LittleEndian + index := 2 + nn := int(le.Uint32(buf[index:])) + sz := int(le.Uint32(buf[index+4:])) + index += 8 + + const v1NumBuckets = 64 + + expectedLen := minLen + (nn * ((v1NumBuckets+1)*8 + 2)) + if len(buf) < expectedLen { + return nil, -1, ErrBadEncoding + } + + var ss SequenceSet + for i := 0; i < nn; i++ { + base := le.Uint64(buf[index:]) + index += 8 + for nb := uint64(0); nb < v1NumBuckets; nb++ { + n := le.Uint64(buf[index:]) + // Walk all set bits and insert sequences manually for this decode from v1. + for pos := uint64(0); n != 0; pos++ { + if n&1 == 1 { + seq := base + (nb * uint64(bitsPerBucket)) + pos + ss.Insert(seq) + } + n >>= 1 + } + index += 8 + } + // Skip over encoded height. + index += 2 + } + + // Sanity check. + if ss.Size() != sz { + return nil, -1, ErrBadEncoding + } + + return &ss, index, nil + +} + +// insertNode places a decoded node into the tree. +// These should be done in tree order as defined by Encode() +// This allows us to not have to calculate height or do rebalancing. +// So much better performance this way. +func (ss *SequenceSet) insertNode(n *node) { + ss.nodes++ + + if ss.root == nil { + ss.root = n + return + } + // Walk our way to the insertion point. + for p := ss.root; p != nil; { + if n.base < p.base { + if p.l == nil { + p.l = n + return + } + p = p.l + } else { + if p.r == nil { + p.r = n + return + } + p = p.r + } + } +} + +const ( + bitsPerBucket = 64 // bits in uint64 + numBuckets = 32 + numEntries = numBuckets * bitsPerBucket +) + +type node struct { + //v dvalue + base uint64 + bits [numBuckets]uint64 + l *node + r *node + h int +} + +// Set the proper bit. +// seq should have already been qualified and inserted should be non nil. +func (n *node) set(seq uint64, inserted *bool) { + seq -= n.base + i := seq / bitsPerBucket + mask := uint64(1) << (seq % bitsPerBucket) + if (n.bits[i] & mask) == 0 { + n.bits[i] |= mask + *inserted = true + } +} + +func (n *node) insert(seq uint64, inserted *bool, nodes *int) *node { + if n == nil { + base := (seq / numEntries) * numEntries + n := &node{base: base, h: 1} + n.set(seq, inserted) + *nodes++ + return n + } + + if seq < n.base { + n.l = n.l.insert(seq, inserted, nodes) + } else if seq >= n.base+numEntries { + n.r = n.r.insert(seq, inserted, nodes) + } else { + n.set(seq, inserted) + } + + n.h = maxH(n) + 1 + + // Don't make a function, impacts performance. + if bf := balanceF(n); bf > 1 { + // Left unbalanced. + if balanceF(n.l) < 0 { + n.l = n.l.rotateL() + } + return n.rotateR() + } else if bf < -1 { + // Right unbalanced. + if balanceF(n.r) > 0 { + n.r = n.r.rotateR() + } + return n.rotateL() + } + return n +} + +func (n *node) rotateL() *node { + r := n.r + if r != nil { + n.r = r.l + r.l = n + n.h = maxH(n) + 1 + r.h = maxH(r) + 1 + } else { + n.r = nil + n.h = maxH(n) + 1 + } + return r +} + +func (n *node) rotateR() *node { + l := n.l + if l != nil { + n.l = l.r + l.r = n + n.h = maxH(n) + 1 + l.h = maxH(l) + 1 + } else { + n.l = nil + n.h = maxH(n) + 1 + } + return l +} + +func balanceF(n *node) int { + if n == nil { + return 0 + } + var lh, rh int + if n.l != nil { + lh = n.l.h + } + if n.r != nil { + rh = n.r.h + } + return lh - rh +} + +func maxH(n *node) int { + if n == nil { + return 0 + } + var lh, rh int + if n.l != nil { + lh = n.l.h + } + if n.r != nil { + rh = n.r.h + } + if lh > rh { + return lh + } + return rh +} + +// Clear the proper bit. +// seq should have already been qualified and deleted should be non nil. +// Will return true if this node is now empty. +func (n *node) clear(seq uint64, deleted *bool) bool { + seq -= n.base + i := seq / bitsPerBucket + mask := uint64(1) << (seq % bitsPerBucket) + if (n.bits[i] & mask) != 0 { + n.bits[i] &^= mask + *deleted = true + } + for _, b := range n.bits { + if b != 0 { + return false + } + } + return true +} + +func (n *node) delete(seq uint64, deleted *bool, nodes *int) *node { + if n == nil { + return nil + } + + if seq < n.base { + n.l = n.l.delete(seq, deleted, nodes) + } else if seq >= n.base+numEntries { + n.r = n.r.delete(seq, deleted, nodes) + } else if empty := n.clear(seq, deleted); empty { + *nodes-- + if n.l == nil { + n = n.r + } else if n.r == nil { + n = n.l + } else { + // We have both children. + n.r = n.r.insertNodePrev(n.l) + n = n.r + } + } + + if n != nil { + n.h = maxH(n) + 1 + } + + // Check balance. + if bf := balanceF(n); bf > 1 { + // Left unbalanced. + if balanceF(n.l) < 0 { + n.l = n.l.rotateL() + } + return n.rotateR() + } else if bf < -1 { + // right unbalanced. + if balanceF(n.r) > 0 { + n.r = n.r.rotateR() + } + return n.rotateL() + } + + return n +} + +// Will insert nn into the node assuming it is less than all other nodes in n. +// Will re-calculate height and balance. +func (n *node) insertNodePrev(nn *node) *node { + if n.l == nil { + n.l = nn + } else { + n.l = n.l.insertNodePrev(nn) + } + n.h = maxH(n) + 1 + + // Check balance. + if bf := balanceF(n); bf > 1 { + // Left unbalanced. + if balanceF(n.l) < 0 { + n.l = n.l.rotateL() + } + return n.rotateR() + } else if bf < -1 { + // right unbalanced. + if balanceF(n.r) > 0 { + n.r = n.r.rotateR() + } + return n.rotateL() + } + return n +} + +func (n *node) exists(seq uint64) bool { + seq -= n.base + i := seq / bitsPerBucket + mask := uint64(1) << (seq % bitsPerBucket) + return n.bits[i]&mask != 0 +} + +// Return minimum sequence in the set. +// This node can not be empty. +func (n *node) min() uint64 { + for i, b := range n.bits { + if b != 0 { + return n.base + + uint64(i*bitsPerBucket) + + uint64(bits.TrailingZeros64(b)) + } + } + return 0 +} + +// Return maximum sequence in the set. +// This node can not be empty. +func (n *node) max() uint64 { + for i := numBuckets - 1; i >= 0; i-- { + if b := n.bits[i]; b != 0 { + return n.base + + uint64(i*bitsPerBucket) + + uint64(bitsPerBucket-bits.LeadingZeros64(b>>1)) + } + } + return 0 +} + +// This is done in tree order. +func (n *node) nodeIter(f func(n *node)) { + if n == nil { + return + } + f(n) + n.l.nodeIter(f) + n.r.nodeIter(f) +} + +// iter will iterate through the set's items in this node. +// If the supplied function returns false we terminate the iteration. +func (n *node) iter(f func(uint64) bool) bool { + if n == nil { + return true + } + + if ok := n.l.iter(f); !ok { + return false + } + for num := n.base; num < n.base+numEntries; num++ { + if n.exists(num) { + if ok := f(num); !ok { + return false + } + } + } + if ok := n.r.iter(f); !ok { + return false + } + + return true +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certidp/certidp.go b/vendor/github.com/nats-io/nats-server/v2/server/certidp/certidp.go new file mode 100644 index 0000000..a266185 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certidp/certidp.go @@ -0,0 +1,312 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package certidp + +import ( + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "fmt" + "net/url" + "strings" + "time" + + "golang.org/x/crypto/ocsp" +) + +const ( + DefaultAllowedClockSkew = 30 * time.Second + DefaultOCSPResponderTimeout = 2 * time.Second + DefaultTTLUnsetNextUpdate = 1 * time.Hour +) + +type StatusAssertion int + +var ( + StatusAssertionStrToVal = map[string]StatusAssertion{ + "good": ocsp.Good, + "revoked": ocsp.Revoked, + "unknown": ocsp.Unknown, + } + StatusAssertionValToStr = map[StatusAssertion]string{ + ocsp.Good: "good", + ocsp.Revoked: "revoked", + ocsp.Unknown: "unknown", + } + StatusAssertionIntToVal = map[int]StatusAssertion{ + 0: ocsp.Good, + 1: ocsp.Revoked, + 2: ocsp.Unknown, + } +) + +// GetStatusAssertionStr returns the corresponding string representation of the StatusAssertion. +func GetStatusAssertionStr(sa int) string { + // If the provided status assertion value is not found in the map (StatusAssertionIntToVal), + // the function defaults to "unknown" to avoid defaulting to "good," which is the default iota value + // for the ocsp.StatusAssertion enumeration (https://pkg.go.dev/golang.org/x/crypto/ocsp#pkg-constants). + // This ensures that we don't unintentionally default to "good" when there's no map entry. + v, ok := StatusAssertionIntToVal[sa] + if !ok { + // set unknown as fallback + v = ocsp.Unknown + } + + return StatusAssertionValToStr[v] +} + +func (sa StatusAssertion) MarshalJSON() ([]byte, error) { + // This ensures that we don't unintentionally default to "good" when there's no map entry. + // (see more details in the GetStatusAssertionStr() comment) + str, ok := StatusAssertionValToStr[sa] + if !ok { + // set unknown as fallback + str = StatusAssertionValToStr[ocsp.Unknown] + } + return json.Marshal(str) +} + +func (sa *StatusAssertion) UnmarshalJSON(in []byte) error { + // This ensures that we don't unintentionally default to "good" when there's no map entry. + // (see more details in the GetStatusAssertionStr() comment) + v, ok := StatusAssertionStrToVal[strings.ReplaceAll(string(in), "\"", "")] + if !ok { + // set unknown as fallback + v = StatusAssertionStrToVal["unknown"] + } + *sa = v + return nil +} + +type ChainLink struct { + Leaf *x509.Certificate + Issuer *x509.Certificate + OCSPWebEndpoints *[]*url.URL +} + +// OCSPPeerConfig holds the parsed OCSP peer configuration section of TLS configuration +type OCSPPeerConfig struct { + Verify bool + Timeout float64 + ClockSkew float64 + WarnOnly bool + UnknownIsGood bool + AllowWhenCAUnreachable bool + TTLUnsetNextUpdate float64 +} + +func NewOCSPPeerConfig() *OCSPPeerConfig { + return &OCSPPeerConfig{ + Verify: false, + Timeout: DefaultOCSPResponderTimeout.Seconds(), + ClockSkew: DefaultAllowedClockSkew.Seconds(), + WarnOnly: false, + UnknownIsGood: false, + AllowWhenCAUnreachable: false, + TTLUnsetNextUpdate: DefaultTTLUnsetNextUpdate.Seconds(), + } +} + +// Log is a neutral method of passing server loggers to plugins +type Log struct { + Debugf func(format string, v ...any) + Noticef func(format string, v ...any) + Warnf func(format string, v ...any) + Errorf func(format string, v ...any) + Tracef func(format string, v ...any) +} + +type CertInfo struct { + Subject string `json:"subject,omitempty"` + Issuer string `json:"issuer,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + Raw []byte `json:"raw,omitempty"` +} + +var OCSPPeerUsage = ` +For client, leaf spoke (remotes), and leaf hub connections, you may enable OCSP peer validation: + + tls { + ... + # mTLS must be enabled (with exception of Leaf remotes) + verify: true + ... + # short form enables peer verify and takes option defaults + ocsp_peer: true + + # long form includes settable options + ocsp_peer { + # Enable OCSP peer validation (default false) + verify: true + + # OCSP responder timeout in seconds (may be fractional, default 2 seconds) + ca_timeout: 2 + + # Allowed skew between server and OCSP responder time in seconds (may be fractional, default 30 seconds) + allowed_clockskew: 30 + + # Warn-only and never reject connections (default false) + warn_only: false + + # Treat response Unknown status as valid certificate (default false) + unknown_is_good: false + + # Warn-only if no CA response can be obtained and no cached revocation exists (default false) + allow_when_ca_unreachable: false + + # If response NextUpdate unset by CA, set a default cache TTL in seconds from ThisUpdate (default 1 hour) + cache_ttl_when_next_update_unset: 3600 + } + ... + } + +Note: OCSP validation for route and gateway connections is enabled using the 'ocsp' configuration option. +` + +// GenerateFingerprint returns a base64-encoded SHA256 hash of the raw certificate +func GenerateFingerprint(cert *x509.Certificate) string { + data := sha256.Sum256(cert.Raw) + return base64.StdEncoding.EncodeToString(data[:]) +} + +func getWebEndpoints(uris []string) []*url.URL { + var urls []*url.URL + for _, uri := range uris { + endpoint, err := url.ParseRequestURI(uri) + if err != nil { + // skip invalid URLs + continue + } + if endpoint.Scheme != "http" && endpoint.Scheme != "https" { + // skip non-web URLs + continue + } + urls = append(urls, endpoint) + } + return urls +} + +// GetSubjectDNForm returns RDN sequence concatenation of the certificate's subject to be +// used in logs, events, etc. Should never be used for reliable cache matching or other crypto purposes. +func GetSubjectDNForm(cert *x509.Certificate) string { + if cert == nil { + return "" + } + return strings.TrimSuffix(fmt.Sprintf("%s+", cert.Subject.ToRDNSequence()), "+") +} + +// GetIssuerDNForm returns RDN sequence concatenation of the certificate's issuer to be +// used in logs, events, etc. Should never be used for reliable cache matching or other crypto purposes. +func GetIssuerDNForm(cert *x509.Certificate) string { + if cert == nil { + return "" + } + return strings.TrimSuffix(fmt.Sprintf("%s+", cert.Issuer.ToRDNSequence()), "+") +} + +// CertOCSPEligible checks if the certificate's issuer has populated AIA with OCSP responder endpoint(s) +// and is thus eligible for OCSP validation +func CertOCSPEligible(link *ChainLink) bool { + if link == nil || link.Leaf.Raw == nil || len(link.Leaf.Raw) == 0 { + return false + } + if len(link.Leaf.OCSPServer) == 0 { + return false + } + urls := getWebEndpoints(link.Leaf.OCSPServer) + if len(urls) == 0 { + return false + } + link.OCSPWebEndpoints = &urls + return true +} + +// GetLeafIssuerCert returns the issuer certificate of the leaf (positional) certificate in the chain +func GetLeafIssuerCert(chain []*x509.Certificate, leafPos int) *x509.Certificate { + if len(chain) == 0 || leafPos < 0 { + return nil + } + // self-signed certificate or too-big leafPos + if leafPos >= len(chain)-1 { + return nil + } + // returns pointer to issuer cert or nil + return (chain)[leafPos+1] +} + +// OCSPResponseCurrent checks if the OCSP response is current (i.e. not expired and not future effective) +func OCSPResponseCurrent(ocspr *ocsp.Response, opts *OCSPPeerConfig, log *Log) bool { + skew := time.Duration(opts.ClockSkew * float64(time.Second)) + if skew < 0*time.Second { + skew = DefaultAllowedClockSkew + } + now := time.Now().UTC() + // Typical effectivity check based on CA response ThisUpdate and NextUpdate semantics + if !ocspr.NextUpdate.IsZero() && ocspr.NextUpdate.Before(now.Add(-1*skew)) { + t := ocspr.NextUpdate.Format(time.RFC3339Nano) + nt := now.Format(time.RFC3339Nano) + log.Debugf(DbgResponseExpired, t, nt, skew) + return false + } + // CA responder can assert NextUpdate unset, in which case use config option to set a default cache TTL + if ocspr.NextUpdate.IsZero() { + ttl := time.Duration(opts.TTLUnsetNextUpdate * float64(time.Second)) + if ttl < 0*time.Second { + ttl = DefaultTTLUnsetNextUpdate + } + expiryTime := ocspr.ThisUpdate.Add(ttl) + if expiryTime.Before(now.Add(-1 * skew)) { + t := expiryTime.Format(time.RFC3339Nano) + nt := now.Format(time.RFC3339Nano) + log.Debugf(DbgResponseTTLExpired, t, nt, skew) + return false + } + } + if ocspr.ThisUpdate.After(now.Add(skew)) { + t := ocspr.ThisUpdate.Format(time.RFC3339Nano) + nt := now.Format(time.RFC3339Nano) + log.Debugf(DbgResponseFutureDated, t, nt, skew) + return false + } + return true +} + +// ValidDelegationCheck checks if the CA OCSP Response was signed by a valid CA Issuer delegate as per (RFC 6960, section 4.2.2.2) +// If a valid delegate or direct-signed by CA Issuer, true returned. +func ValidDelegationCheck(iss *x509.Certificate, ocspr *ocsp.Response) bool { + // This call assumes prior successful parse and signature validation of the OCSP response + // The Go OCSP library (as of x/crypto/ocsp v0.9) will detect and perform a 1-level delegate signature check but does not + // implement the additional criteria for delegation specified in RFC 6960, section 4.2.2.2. + if iss == nil || ocspr == nil { + return false + } + // not a delegation, no-op + if ocspr.Certificate == nil { + return true + } + // delegate is self-same with CA Issuer, not a delegation although response issued in that form + if ocspr.Certificate.Equal(iss) { + return true + } + // we need to verify CA Issuer stamped id-kp-OCSPSigning on delegate + delegatedSigner := false + for _, keyUseExt := range ocspr.Certificate.ExtKeyUsage { + if keyUseExt == x509.ExtKeyUsageOCSPSigning { + delegatedSigner = true + break + } + } + return delegatedSigner +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certidp/messages.go b/vendor/github.com/nats-io/nats-server/v2/server/certidp/messages.go new file mode 100644 index 0000000..52a799a --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certidp/messages.go @@ -0,0 +1,106 @@ +// Copyright 2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package certidp + +var ( + // Returned errors + ErrIllegalPeerOptsConfig = "expected map to define OCSP peer options, got [%T]" + ErrIllegalCacheOptsConfig = "expected map to define OCSP peer cache options, got [%T]" + ErrParsingPeerOptFieldGeneric = "error parsing tls peer config, unknown field [%q]" + ErrParsingPeerOptFieldTypeConversion = "error parsing tls peer config, conversion error: %s" + ErrParsingCacheOptFieldTypeConversion = "error parsing OCSP peer cache config, conversion error: %s" + ErrUnableToPlugTLSEmptyConfig = "unable to plug TLS verify connection, config is nil" + ErrMTLSRequired = "OCSP peer verification for client connections requires TLS verify (mTLS) to be enabled" + ErrUnableToPlugTLSClient = "unable to register client OCSP verification" + ErrUnableToPlugTLSServer = "unable to register server OCSP verification" + ErrCannotWriteCompressed = "error writing to compression writer: %w" + ErrCannotReadCompressed = "error reading compression reader: %w" + ErrTruncatedWrite = "short write on body (%d != %d)" + ErrCannotCloseWriter = "error closing compression writer: %w" + ErrParsingCacheOptFieldGeneric = "error parsing OCSP peer cache config, unknown field [%q]" + ErrUnknownCacheType = "error parsing OCSP peer cache config, unknown type [%s]" + ErrInvalidChainlink = "invalid chain link" + ErrBadResponderHTTPStatus = "bad OCSP responder http status: [%d]" + ErrNoAvailOCSPServers = "no available OCSP servers" + ErrFailedWithAllRequests = "exhausted OCSP responders: %w" + + // Direct logged errors + ErrLoadCacheFail = "Unable to load OCSP peer cache: %s" + ErrSaveCacheFail = "Unable to save OCSP peer cache: %s" + ErrBadCacheTypeConfig = "Unimplemented OCSP peer cache type [%v]" + ErrResponseCompressFail = "Unable to compress OCSP response for key [%s]: %s" + ErrResponseDecompressFail = "Unable to decompress OCSP response for key [%s]: %s" + ErrPeerEmptyNoEvent = "Peer certificate is nil, cannot send OCSP peer reject event" + ErrPeerEmptyAutoReject = "Peer certificate is nil, rejecting OCSP peer" + + // Debug information + DbgPlugTLSForKind = "Plugging TLS OCSP peer for [%s]" + DbgNumServerChains = "Peer OCSP enabled: %d TLS server chain(s) will be evaluated" + DbgNumClientChains = "Peer OCSP enabled: %d TLS client chain(s) will be evaluated" + DbgLinksInChain = "Chain [%d]: %d total link(s)" + DbgSelfSignedValid = "Chain [%d] is self-signed, thus peer is valid" + DbgValidNonOCSPChain = "Chain [%d] has no OCSP eligible links, thus peer is valid" + DbgChainIsOCSPEligible = "Chain [%d] has %d OCSP eligible link(s)" + DbgChainIsOCSPValid = "Chain [%d] is OCSP valid for all eligible links, thus peer is valid" + DbgNoOCSPValidChains = "No OCSP valid chains, thus peer is invalid" + DbgCheckingCacheForCert = "Checking OCSP peer cache for [%s], key [%s]" + DbgCurrentResponseCached = "Cached OCSP response is current, status [%s]" + DbgExpiredResponseCached = "Cached OCSP response is expired, status [%s]" + DbgOCSPValidPeerLink = "OCSP verify pass for [%s]" + DbgCachingResponse = "Caching OCSP response for [%s], key [%s]" + DbgAchievedCompression = "OCSP response compression ratio: [%f]" + DbgCacheHit = "OCSP peer cache hit for key [%s]" + DbgCacheMiss = "OCSP peer cache miss for key [%s]" + DbgPreservedRevocation = "Revoked OCSP response for key [%s] preserved by cache policy" + DbgDeletingCacheResponse = "Deleting OCSP peer cached response for key [%s]" + DbgStartingCache = "Starting OCSP peer cache" + DbgStoppingCache = "Stopping OCSP peer cache" + DbgLoadingCache = "Loading OCSP peer cache [%s]" + DbgNoCacheFound = "No OCSP peer cache found, starting with empty cache" + DbgSavingCache = "Saving OCSP peer cache [%s]" + DbgCacheSaved = "Saved OCSP peer cache successfully (%d bytes)" + DbgMakingCARequest = "Trying OCSP responder url [%s]" + DbgResponseExpired = "OCSP response NextUpdate [%s] is before now [%s] with clockskew [%s]" + DbgResponseTTLExpired = "OCSP response cache expiry [%s] is before now [%s] with clockskew [%s]" + DbgResponseFutureDated = "OCSP response ThisUpdate [%s] is before now [%s] with clockskew [%s]" + DbgCacheSaveTimerExpired = "OCSP peer cache save timer expired" + DbgCacheDirtySave = "OCSP peer cache is dirty, saving" + + // Returned to peer as TLS reject reason + MsgTLSClientRejectConnection = "client not OCSP valid" + MsgTLSServerRejectConnection = "server not OCSP valid" + + // Expected runtime errors (direct logged) + ErrCAResponderCalloutFail = "Attempt to obtain OCSP response from CA responder for [%s] failed: %s" + ErrNewCAResponseNotCurrent = "New OCSP CA response obtained for [%s] but not current" + ErrCAResponseParseFailed = "Could not parse OCSP CA response for [%s]: %s" + ErrOCSPInvalidPeerLink = "OCSP verify fail for [%s] with CA status [%s]" + + // Policy override warnings (direct logged) + MsgAllowWhenCAUnreachableOccurred = "Failed to obtain OCSP CA response for [%s] but AllowWhenCAUnreachable set; no cached revocation so allowing" + MsgAllowWhenCAUnreachableOccurredCachedRevoke = "Failed to obtain OCSP CA response for [%s] but AllowWhenCAUnreachable set; cached revocation exists so rejecting" + MsgAllowWarnOnlyOccurred = "OCSP verify fail for [%s] but WarnOnly is true so allowing" + + // Info (direct logged) + MsgCacheOnline = "OCSP peer cache online, type [%s]" + MsgCacheOffline = "OCSP peer cache offline, type [%s]" + + // OCSP cert invalid reasons (debug and event reasons) + MsgFailedOCSPResponseFetch = "Failed OCSP response fetch" + MsgOCSPResponseNotEffective = "OCSP response not in effectivity window" + MsgFailedOCSPResponseParse = "Failed OCSP response parse" + MsgOCSPResponseInvalidStatus = "Invalid OCSP response status: %s" + MsgOCSPResponseDelegationInvalid = "Invalid OCSP response delegation: %s" + MsgCachedOCSPResponseInvalid = "Invalid cached OCSP response for [%s] with fingerprint [%s]" +) diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certidp/ocsp_responder.go b/vendor/github.com/nats-io/nats-server/v2/server/certidp/ocsp_responder.go new file mode 100644 index 0000000..e560d6e --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certidp/ocsp_responder.go @@ -0,0 +1,92 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package certidp + +import ( + "encoding/base64" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "time" + + "golang.org/x/crypto/ocsp" +) + +func FetchOCSPResponse(link *ChainLink, opts *OCSPPeerConfig, log *Log) ([]byte, error) { + if link == nil || link.Leaf == nil || link.Issuer == nil || opts == nil || log == nil { + return nil, errors.New(ErrInvalidChainlink) + } + + timeout := time.Duration(opts.Timeout * float64(time.Second)) + if timeout <= 0*time.Second { + timeout = DefaultOCSPResponderTimeout + } + + getRequestBytes := func(u string, hc *http.Client) ([]byte, error) { + resp, err := hc.Get(u) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf(ErrBadResponderHTTPStatus, resp.StatusCode) + } + return io.ReadAll(resp.Body) + } + + // Request documentation: + // https://tools.ietf.org/html/rfc6960#appendix-A.1 + + reqDER, err := ocsp.CreateRequest(link.Leaf, link.Issuer, nil) + if err != nil { + return nil, err + } + + reqEnc := encodeOCSPRequest(reqDER) + + responders := *link.OCSPWebEndpoints + + if len(responders) == 0 { + return nil, errors.New(ErrNoAvailOCSPServers) + } + + var raw []byte + hc := &http.Client{ + Timeout: timeout, + } + for _, u := range responders { + responderURL := u.String() + log.Debugf(DbgMakingCARequest, responderURL) + responderURL = strings.TrimSuffix(responderURL, "/") + raw, err = getRequestBytes(fmt.Sprintf("%s/%s", responderURL, reqEnc), hc) + if err == nil { + break + } + } + if err != nil { + return nil, fmt.Errorf(ErrFailedWithAllRequests, err) + } + + return raw, nil +} + +// encodeOCSPRequest encodes the OCSP request in base64 and URL-encodes it. +// This is needed to fulfill the OCSP responder's requirements for the request format. (X.690) +func encodeOCSPRequest(reqDER []byte) string { + reqEnc := base64.StdEncoding.EncodeToString(reqDER) + return url.QueryEscape(reqEnc) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore.go b/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore.go new file mode 100644 index 0000000..3c8114f --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore.go @@ -0,0 +1,104 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package certstore + +import ( + "crypto" + "crypto/x509" + "io" + "runtime" + "strings" +) + +type StoreType int + +const MATCHBYEMPTY = 0 +const STOREEMPTY = 0 + +const ( + windowsCurrentUser StoreType = iota + 1 + windowsLocalMachine +) + +var StoreMap = map[string]StoreType{ + "windowscurrentuser": windowsCurrentUser, + "windowslocalmachine": windowsLocalMachine, +} + +var StoreOSMap = map[StoreType]string{ + windowsCurrentUser: "windows", + windowsLocalMachine: "windows", +} + +type MatchByType int + +const ( + matchByIssuer MatchByType = iota + 1 + matchBySubject + matchByThumbprint +) + +var MatchByMap = map[string]MatchByType{ + "issuer": matchByIssuer, + "subject": matchBySubject, + "thumbprint": matchByThumbprint, +} + +var Usage = ` +In place of cert_file and key_file you may use the windows certificate store: + + tls { + cert_store: "WindowsCurrentUser" + cert_match_by: "Subject" + cert_match: "MyServer123" + } +` + +func ParseCertStore(certStore string) (StoreType, error) { + certStoreType, exists := StoreMap[strings.ToLower(certStore)] + if !exists { + return 0, ErrBadCertStore + } + validOS, exists := StoreOSMap[certStoreType] + if !exists || validOS != runtime.GOOS { + return 0, ErrOSNotCompatCertStore + } + return certStoreType, nil +} + +func ParseCertMatchBy(certMatchBy string) (MatchByType, error) { + certMatchByType, exists := MatchByMap[strings.ToLower(certMatchBy)] + if !exists { + return 0, ErrBadMatchByType + } + return certMatchByType, nil +} + +func GetLeafIssuer(leaf *x509.Certificate, vOpts x509.VerifyOptions) (issuer *x509.Certificate) { + chains, err := leaf.Verify(vOpts) + if err != nil || len(chains) == 0 { + issuer = nil + } else { + issuer = chains[0][1] + } + return +} + +// credential provides access to a public key and is a crypto.Signer. +type credential interface { + // Public returns the public key corresponding to the leaf certificate. + Public() crypto.PublicKey + // Sign signs digest with the private key. + Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore_other.go b/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore_other.go new file mode 100644 index 0000000..185efc6 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore_other.go @@ -0,0 +1,45 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !windows + +package certstore + +import ( + "crypto" + "crypto/tls" + "io" +) + +var _ = MATCHBYEMPTY + +// otherKey implements crypto.Signer and crypto.Decrypter to satisfy linter on platforms that don't implement certstore +type otherKey struct{} + +func TLSConfig(_ StoreType, _ MatchByType, _ string, _ []string, _ bool, _ *tls.Config) error { + return ErrOSNotCompatCertStore +} + +// Public always returns nil public key since this is a stub on non-supported platform +func (k otherKey) Public() crypto.PublicKey { + return nil +} + +// Sign always returns a nil signature since this is a stub on non-supported platform +func (k otherKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { + _, _, _ = rand, digest, opts + return nil, nil +} + +// Verify interface conformance. +var _ credential = &otherKey{} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore_windows.go new file mode 100644 index 0000000..96eaea8 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certstore/certstore_windows.go @@ -0,0 +1,965 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Adapted, updated, and enhanced from CertToStore, https://github.com/google/certtostore/releases/tag/v1.0.2 +// Apache License, Version 2.0, Copyright 2017 Google Inc. + +package certstore + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "encoding/binary" + "fmt" + "io" + "math/big" + "reflect" + "sync" + "syscall" + "unicode/utf16" + "unsafe" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" + "golang.org/x/sys/windows" +) + +const ( + // wincrypt.h constants + winAcquireCached = windows.CRYPT_ACQUIRE_CACHE_FLAG + winAcquireSilent = windows.CRYPT_ACQUIRE_SILENT_FLAG + winAcquireOnlyNCryptKey = windows.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG + winEncodingX509ASN = windows.X509_ASN_ENCODING + winEncodingPKCS7 = windows.PKCS_7_ASN_ENCODING + winCertStoreProvSystem = windows.CERT_STORE_PROV_SYSTEM + winCertStoreCurrentUser = windows.CERT_SYSTEM_STORE_CURRENT_USER + winCertStoreLocalMachine = windows.CERT_SYSTEM_STORE_LOCAL_MACHINE + winCertStoreReadOnly = windows.CERT_STORE_READONLY_FLAG + winInfoIssuerFlag = windows.CERT_INFO_ISSUER_FLAG + winInfoSubjectFlag = windows.CERT_INFO_SUBJECT_FLAG + winCompareNameStrW = windows.CERT_COMPARE_NAME_STR_W + winCompareShift = windows.CERT_COMPARE_SHIFT + + // Reference https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore + winFindIssuerStr = windows.CERT_FIND_ISSUER_STR_W + winFindSubjectStr = windows.CERT_FIND_SUBJECT_STR_W + winFindHashStr = windows.CERT_FIND_HASH_STR + + winNcryptKeySpec = windows.CERT_NCRYPT_KEY_SPEC + + winBCryptPadPKCS1 uintptr = 0x2 + winBCryptPadPSS uintptr = 0x8 // Modern TLS 1.2+ + winBCryptPadPSSSalt uint32 = 32 // default 20, 32 optimal for typical SHA256 hash + + winRSA1Magic = 0x31415352 // "RSA1" BCRYPT_RSAPUBLIC_MAGIC + + winECS1Magic = 0x31534345 // "ECS1" BCRYPT_ECDSA_PUBLIC_P256_MAGIC + winECS3Magic = 0x33534345 // "ECS3" BCRYPT_ECDSA_PUBLIC_P384_MAGIC + winECS5Magic = 0x35534345 // "ECS5" BCRYPT_ECDSA_PUBLIC_P521_MAGIC + + winECK1Magic = 0x314B4345 // "ECK1" BCRYPT_ECDH_PUBLIC_P256_MAGIC + winECK3Magic = 0x334B4345 // "ECK3" BCRYPT_ECDH_PUBLIC_P384_MAGIC + winECK5Magic = 0x354B4345 // "ECK5" BCRYPT_ECDH_PUBLIC_P521_MAGIC + + winCryptENotFound = windows.CRYPT_E_NOT_FOUND + + providerMSSoftware = "Microsoft Software Key Storage Provider" +) + +var ( + winBCryptRSAPublicBlob = winWide("RSAPUBLICBLOB") + winBCryptECCPublicBlob = winWide("ECCPUBLICBLOB") + + winNCryptAlgorithmGroupProperty = winWide("Algorithm Group") // NCRYPT_ALGORITHM_GROUP_PROPERTY + winNCryptUniqueNameProperty = winWide("Unique Name") // NCRYPT_UNIQUE_NAME_PROPERTY + winNCryptECCCurveNameProperty = winWide("ECCCurveName") // NCRYPT_ECC_CURVE_NAME_PROPERTY + + winCurveIDs = map[uint32]elliptic.Curve{ + winECS1Magic: elliptic.P256(), // BCRYPT_ECDSA_PUBLIC_P256_MAGIC + winECS3Magic: elliptic.P384(), // BCRYPT_ECDSA_PUBLIC_P384_MAGIC + winECS5Magic: elliptic.P521(), // BCRYPT_ECDSA_PUBLIC_P521_MAGIC + winECK1Magic: elliptic.P256(), // BCRYPT_ECDH_PUBLIC_P256_MAGIC + winECK3Magic: elliptic.P384(), // BCRYPT_ECDH_PUBLIC_P384_MAGIC + winECK5Magic: elliptic.P521(), // BCRYPT_ECDH_PUBLIC_P521_MAGIC + } + + winCurveNames = map[string]elliptic.Curve{ + "nistP256": elliptic.P256(), // BCRYPT_ECC_CURVE_NISTP256 + "nistP384": elliptic.P384(), // BCRYPT_ECC_CURVE_NISTP384 + "nistP521": elliptic.P521(), // BCRYPT_ECC_CURVE_NISTP521 + } + + winAlgIDs = map[crypto.Hash]*uint16{ + crypto.SHA1: winWide("SHA1"), // BCRYPT_SHA1_ALGORITHM + crypto.SHA256: winWide("SHA256"), // BCRYPT_SHA256_ALGORITHM + crypto.SHA384: winWide("SHA384"), // BCRYPT_SHA384_ALGORITHM + crypto.SHA512: winWide("SHA512"), // BCRYPT_SHA512_ALGORITHM + } + + // MY is well-known system store on Windows that holds personal certificates. Read + // More about the CA locations here: + // https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/certificate-of-clientcertificate-element?redirectedfrom=MSDN + // https://superuser.com/questions/217719/what-are-the-windows-system-certificate-stores + // https://docs.microsoft.com/en-us/windows/win32/seccrypto/certificate-stores + // https://learn.microsoft.com/en-us/windows/win32/seccrypto/system-store-locations + // https://stackoverflow.com/questions/63286085/which-x509-storename-refers-to-the-certificates-stored-beneath-trusted-root-cert#:~:text=4-,StoreName.,is%20%22Intermediate%20Certification%20Authorities%22. + winMyStore = winWide("MY") + winIntermediateCAStore = winWide("CA") + winRootStore = winWide("Root") + winAuthRootStore = winWide("AuthRoot") + + // These DLLs must be available on all Windows hosts + winCrypt32 = windows.NewLazySystemDLL("crypt32.dll") + winNCrypt = windows.NewLazySystemDLL("ncrypt.dll") + + winCertFindCertificateInStore = winCrypt32.NewProc("CertFindCertificateInStore") + winCertVerifyTimeValidity = winCrypt32.NewProc("CertVerifyTimeValidity") + winCryptAcquireCertificatePrivateKey = winCrypt32.NewProc("CryptAcquireCertificatePrivateKey") + winNCryptExportKey = winNCrypt.NewProc("NCryptExportKey") + winNCryptOpenStorageProvider = winNCrypt.NewProc("NCryptOpenStorageProvider") + winNCryptGetProperty = winNCrypt.NewProc("NCryptGetProperty") + winNCryptSignHash = winNCrypt.NewProc("NCryptSignHash") + + winFnGetProperty = winGetProperty +) + +func init() { + for _, d := range []*windows.LazyDLL{ + winCrypt32, winNCrypt, + } { + if err := d.Load(); err != nil { + panic(err) + } + } + for _, p := range []*windows.LazyProc{ + winCertFindCertificateInStore, winCryptAcquireCertificatePrivateKey, + winNCryptExportKey, winNCryptOpenStorageProvider, + winNCryptGetProperty, winNCryptSignHash, + } { + if err := p.Find(); err != nil { + panic(err) + } + } +} + +type winPKCS1PaddingInfo struct { + pszAlgID *uint16 +} + +type winPSSPaddingInfo struct { + pszAlgID *uint16 + cbSalt uint32 +} + +// createCACertsPool generates a CertPool from the Windows certificate store, +// adding all matching certificates from the caCertsMatch array to the pool. +// All matching certificates (vs first) are added to the pool based on a user +// request. If no certificates are found an error is returned. +func createCACertsPool(cs *winCertStore, storeType uint32, caCertsMatch []string, skipInvalid bool) (*x509.CertPool, error) { + var errs []error + caPool := x509.NewCertPool() + for _, s := range caCertsMatch { + lfs, err := cs.caCertsBySubjectMatch(s, storeType, skipInvalid) + if err != nil { + errs = append(errs, err) + } else { + for _, lf := range lfs { + caPool.AddCert(lf) + } + } + } + // If every lookup failed return the errors. + if len(errs) == len(caCertsMatch) { + return nil, fmt.Errorf("unable to match any CA certificate: %v", errs) + } + return caPool, nil +} + +// TLSConfig fulfills the same function as reading cert and key pair from +// pem files but sources the Windows certificate store instead. The +// certMatchBy and certMatch fields search the "MY" certificate location +// for the first certificate that matches the certMatch field. The +// caCertsMatch field is used to search the Trusted Root, Third Party Root, +// and Intermediate Certificate Authority locations for certificates with +// Subjects matching the provided strings. If a match is found, the +// certificate is added to the pool that is used to verify the certificate +// chain. +func TLSConfig(certStore StoreType, certMatchBy MatchByType, certMatch string, caCertsMatch []string, skipInvalid bool, config *tls.Config) error { + var ( + leaf *x509.Certificate + leafCtx *windows.CertContext + pk *winKey + vOpts = x509.VerifyOptions{} + chains [][]*x509.Certificate + chain []*x509.Certificate + rawChain [][]byte + ) + + // By StoreType, open a store + if certStore == windowsCurrentUser || certStore == windowsLocalMachine { + var scope uint32 + cs, err := winOpenCertStore(providerMSSoftware) + if err != nil || cs == nil { + return err + } + if certStore == windowsCurrentUser { + scope = winCertStoreCurrentUser + } + if certStore == windowsLocalMachine { + scope = winCertStoreLocalMachine + } + + // certByIssuer or certBySubject + if certMatchBy == matchBySubject || certMatchBy == MATCHBYEMPTY { + leaf, leafCtx, err = cs.certBySubject(certMatch, scope, skipInvalid) + } else if certMatchBy == matchByIssuer { + leaf, leafCtx, err = cs.certByIssuer(certMatch, scope, skipInvalid) + } else if certMatchBy == matchByThumbprint { + leaf, leafCtx, err = cs.certByThumbprint(certMatch, scope, skipInvalid) + } else { + return ErrBadMatchByType + } + if err != nil { + // pass through error from cert search + return err + } + if leaf == nil || leafCtx == nil { + return ErrFailedCertSearch + } + pk, err = cs.certKey(leafCtx) + if err != nil { + return err + } + if pk == nil { + return ErrNoPrivateKeyStoreRef + } + // Look for CA Certificates + if len(caCertsMatch) != 0 { + caPool, err := createCACertsPool(cs, scope, caCertsMatch, skipInvalid) + if err != nil { + return err + } + config.ClientCAs = caPool + } + } else { + return ErrBadCertStore + } + + // Get intermediates in the cert store for the found leaf IFF there is a full chain of trust in the store + // otherwise just use leaf as the final chain. + // + // Using std lib Verify as a reliable way to get valid chains out of the win store for the leaf; however, + // using empty options since server TLS stanza could be TLS role as server identity or client identity. + chains, err := leaf.Verify(vOpts) + if err != nil || len(chains) == 0 { + chains = append(chains, []*x509.Certificate{leaf}) + } + + // We have at least one verified chain so pop the first chain and remove the self-signed CA cert (if present) + // from the end of the chain + chain = chains[0] + if len(chain) > 1 { + chain = chain[:len(chain)-1] + } + + // For tls.Certificate.Certificate need a [][]byte from []*x509.Certificate + // Approximate capacity for efficiency + rawChain = make([][]byte, 0, len(chain)) + for _, link := range chain { + rawChain = append(rawChain, link.Raw) + } + + tlsCert := tls.Certificate{ + Certificate: rawChain, + PrivateKey: pk, + Leaf: leaf, + } + config.Certificates = []tls.Certificate{tlsCert} + + // note: pk is a windows pointer (not freed by Go) but needs to live the life of the server for Signing. + // The cert context (leafCtx) windows pointer must not be freed underneath the pk so also life of the server. + return nil +} + +// winWide returns a pointer to uint16 representing the equivalent +// to a Windows LPCWSTR. +func winWide(s string) *uint16 { + w := utf16.Encode([]rune(s)) + w = append(w, 0) + return &w[0] +} + +// winOpenProvider gets a provider handle for subsequent calls +func winOpenProvider(provider string) (uintptr, error) { + var hProv uintptr + pname := winWide(provider) + // Open the provider, the last parameter is not used + r, _, err := winNCryptOpenStorageProvider.Call(uintptr(unsafe.Pointer(&hProv)), uintptr(unsafe.Pointer(pname)), 0) + if r == 0 { + return hProv, nil + } + return hProv, fmt.Errorf("NCryptOpenStorageProvider returned %X: %v", r, err) +} + +// winFindCert wraps the CertFindCertificateInStore library call. Note that any cert context passed +// into prev will be freed. If no certificate was found, nil will be returned. +func winFindCert(store windows.Handle, enc, findFlags, findType uint32, para *uint16, prev *windows.CertContext) (*windows.CertContext, error) { + h, _, err := winCertFindCertificateInStore.Call( + uintptr(store), + uintptr(enc), + uintptr(findFlags), + uintptr(findType), + uintptr(unsafe.Pointer(para)), + uintptr(unsafe.Pointer(prev)), + ) + if h == 0 { + // Actual error, or simply not found? + if errno, ok := err.(syscall.Errno); ok && errno == syscall.Errno(winCryptENotFound) { + return nil, ErrFailedCertSearch + } + return nil, ErrFailedCertSearch + } + // nolint:govet + return (*windows.CertContext)(unsafe.Pointer(h)), nil +} + +// winVerifyCertValid wraps the CertVerifyTimeValidity and simply returns true if the certificate is valid +func winVerifyCertValid(timeToVerify *windows.Filetime, certInfo *windows.CertInfo) bool { + // this function does not document returning errors / setting lasterror + r, _, _ := winCertVerifyTimeValidity.Call( + uintptr(unsafe.Pointer(timeToVerify)), + uintptr(unsafe.Pointer(certInfo)), + ) + return r == 0 +} + +// winCertStore is a store implementation for the Windows Certificate Store +type winCertStore struct { + Prov uintptr + ProvName string + stores map[string]*winStoreHandle + mu sync.Mutex +} + +// winOpenCertStore creates a winCertStore +func winOpenCertStore(provider string) (*winCertStore, error) { + cngProv, err := winOpenProvider(provider) + if err != nil { + // pass through error from winOpenProvider + return nil, err + } + + wcs := &winCertStore{ + Prov: cngProv, + ProvName: provider, + stores: make(map[string]*winStoreHandle), + } + + return wcs, nil +} + +// winCertContextToX509 creates an x509.Certificate from a Windows cert context. +func winCertContextToX509(ctx *windows.CertContext) (*x509.Certificate, error) { + var der []byte + slice := (*reflect.SliceHeader)(unsafe.Pointer(&der)) + slice.Data = uintptr(unsafe.Pointer(ctx.EncodedCert)) + slice.Len = int(ctx.Length) + slice.Cap = int(ctx.Length) + return x509.ParseCertificate(der) +} + +// certByIssuer matches and returns the first certificate found by passed issuer. +// CertContext pointer returned allows subsequent key operations like Sign. Caller specifies +// current user's personal certs or local machine's personal certs using storeType. +// See CERT_FIND_ISSUER_STR description at https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore +func (w *winCertStore) certByIssuer(issuer string, storeType uint32, skipInvalid bool) (*x509.Certificate, *windows.CertContext, error) { + return w.certSearch(winFindIssuerStr, issuer, winMyStore, storeType, skipInvalid) +} + +// certBySubject matches and returns the first certificate found by passed subject field. +// CertContext pointer returned allows subsequent key operations like Sign. Caller specifies +// current user's personal certs or local machine's personal certs using storeType. +// See CERT_FIND_SUBJECT_STR description at https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore +func (w *winCertStore) certBySubject(subject string, storeType uint32, skipInvalid bool) (*x509.Certificate, *windows.CertContext, error) { + return w.certSearch(winFindSubjectStr, subject, winMyStore, storeType, skipInvalid) +} + +// certByThumbprint matches and returns the first certificate found by passed SHA1 thumbprint. +// CertContext pointer returned allows subsequent key operations like Sign. Caller specifies +// current user's personal certs or local machine's personal certs using storeType. +// See CERT_FIND_SUBJECT_STR description at https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore +func (w *winCertStore) certByThumbprint(hash string, storeType uint32, skipInvalid bool) (*x509.Certificate, *windows.CertContext, error) { + return w.certSearch(winFindHashStr, hash, winMyStore, storeType, skipInvalid) +} + +// caCertsBySubjectMatch matches and returns all matching certificates of the subject field. +// +// The following locations are searched: +// 1) Root (Trusted Root Certification Authorities) +// 2) AuthRoot (Third-Party Root Certification Authorities) +// 3) CA (Intermediate Certification Authorities) +// +// Caller specifies current user's personal certs or local machine's personal certs using storeType. +// See CERT_FIND_SUBJECT_STR description at https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certfindcertificateinstore +func (w *winCertStore) caCertsBySubjectMatch(subject string, storeType uint32, skipInvalid bool) ([]*x509.Certificate, error) { + var ( + leaf *x509.Certificate + searchLocations = [3]*uint16{winRootStore, winAuthRootStore, winIntermediateCAStore} + rv []*x509.Certificate + ) + // surprisingly, an empty string returns a result. We'll treat this as an error. + if subject == "" { + return nil, ErrBadCaCertMatchField + } + for _, sr := range searchLocations { + var err error + if leaf, _, err = w.certSearch(winFindSubjectStr, subject, sr, storeType, skipInvalid); err == nil { + rv = append(rv, leaf) + } else { + // Ignore the failed search from a single location. Errors we catch include + // ErrFailedX509Extract (resulting from a malformed certificate) and errors + // around invalid attributes, unsupported algorithms, etc. These are corner + // cases as certificates with these errors shouldn't have been allowed + // to be added to the store in the first place. + if err != ErrFailedCertSearch { + return nil, err + } + } + } + // Not found anywhere + if len(rv) == 0 { + return nil, ErrFailedCertSearch + } + return rv, nil +} + +// certSearch is a helper function to lookup certificates based on search type and match value. +// store is used to specify which store to perform the lookup in (system or user). +func (w *winCertStore) certSearch(searchType uint32, matchValue string, searchRoot *uint16, store uint32, skipInvalid bool) (*x509.Certificate, *windows.CertContext, error) { + // store handle to "MY" store + h, err := w.storeHandle(store, searchRoot) + if err != nil { + return nil, nil, err + } + + var prev *windows.CertContext + var cert *x509.Certificate + + i, err := windows.UTF16PtrFromString(matchValue) + if err != nil { + return nil, nil, ErrFailedCertSearch + } + + // pass 0 as the third parameter because it is not used + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa376064(v=vs.85).aspx + + for { + nc, err := winFindCert(h, winEncodingX509ASN|winEncodingPKCS7, 0, searchType, i, prev) + if err != nil { + return nil, nil, err + } + if nc != nil { + // certificate found + prev = nc + + var now *windows.Filetime + if skipInvalid && !winVerifyCertValid(now, nc.CertInfo) { + continue + } + + // Extract the DER-encoded certificate from the cert context + xc, err := winCertContextToX509(nc) + if err == nil { + cert = xc + break + } else { + return nil, nil, ErrFailedX509Extract + } + } else { + return nil, nil, ErrFailedCertSearch + } + } + + if cert == nil { + return nil, nil, ErrFailedX509Extract + } + + return cert, prev, nil +} + +type winStoreHandle struct { + handle *windows.Handle +} + +func winNewStoreHandle(provider uint32, store *uint16) (*winStoreHandle, error) { + var s winStoreHandle + if s.handle != nil { + return &s, nil + } + st, err := windows.CertOpenStore( + winCertStoreProvSystem, + 0, + 0, + provider|winCertStoreReadOnly, + uintptr(unsafe.Pointer(store))) + if err != nil { + return nil, ErrBadCryptoStoreProvider + } + s.handle = &st + return &s, nil +} + +// winKey implements crypto.Signer and crypto.Decrypter for key based operations. +type winKey struct { + handle uintptr + pub crypto.PublicKey + Container string + AlgorithmGroup string +} + +// Public exports a public key to implement crypto.Signer +func (k winKey) Public() crypto.PublicKey { + return k.pub +} + +// Sign returns the signature of a hash to implement crypto.Signer +func (k winKey) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + switch k.AlgorithmGroup { + case "ECDSA", "ECDH": + return winSignECDSA(k.handle, digest) + case "RSA": + hf := opts.HashFunc() + algID, ok := winAlgIDs[hf] + if !ok { + return nil, ErrBadRSAHashAlgorithm + } + switch opts.(type) { + case *rsa.PSSOptions: + return winSignRSAPSSPadding(k.handle, digest, algID) + default: + return winSignRSAPKCS1Padding(k.handle, digest, algID) + } + default: + return nil, ErrBadSigningAlgorithm + } +} + +func winSignECDSA(kh uintptr, digest []byte) ([]byte, error) { + var size uint32 + // Obtain the size of the signature + r, _, _ := winNCryptSignHash.Call( + kh, + 0, + uintptr(unsafe.Pointer(&digest[0])), + uintptr(len(digest)), + 0, + 0, + uintptr(unsafe.Pointer(&size)), + 0) + if r != 0 { + return nil, ErrStoreECDSASigningError + } + + // Obtain the signature data + buf := make([]byte, size) + r, _, _ = winNCryptSignHash.Call( + kh, + 0, + uintptr(unsafe.Pointer(&digest[0])), + uintptr(len(digest)), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(size), + uintptr(unsafe.Pointer(&size)), + 0) + if r != 0 { + return nil, ErrStoreECDSASigningError + } + if len(buf) != int(size) { + return nil, ErrStoreECDSASigningError + } + + return winPackECDSASigValue(bytes.NewReader(buf[:size]), int(size/2)) +} + +func winPackECDSASigValue(r io.Reader, digestLength int) ([]byte, error) { + sigR := make([]byte, digestLength) + if _, err := io.ReadFull(r, sigR); err != nil { + return nil, ErrStoreECDSASigningError + } + + sigS := make([]byte, digestLength) + if _, err := io.ReadFull(r, sigS); err != nil { + return nil, ErrStoreECDSASigningError + } + + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(new(big.Int).SetBytes(sigR)) + b.AddASN1BigInt(new(big.Int).SetBytes(sigS)) + }) + return b.Bytes() +} + +func winSignRSAPKCS1Padding(kh uintptr, digest []byte, algID *uint16) ([]byte, error) { + // PKCS#1 v1.5 padding for some TLS 1.2 + padInfo := winPKCS1PaddingInfo{pszAlgID: algID} + var size uint32 + // Obtain the size of the signature + r, _, _ := winNCryptSignHash.Call( + kh, + uintptr(unsafe.Pointer(&padInfo)), + uintptr(unsafe.Pointer(&digest[0])), + uintptr(len(digest)), + 0, + 0, + uintptr(unsafe.Pointer(&size)), + winBCryptPadPKCS1) + if r != 0 { + return nil, ErrStoreRSASigningError + } + + // Obtain the signature data + sig := make([]byte, size) + r, _, _ = winNCryptSignHash.Call( + kh, + uintptr(unsafe.Pointer(&padInfo)), + uintptr(unsafe.Pointer(&digest[0])), + uintptr(len(digest)), + uintptr(unsafe.Pointer(&sig[0])), + uintptr(size), + uintptr(unsafe.Pointer(&size)), + winBCryptPadPKCS1) + if r != 0 { + return nil, ErrStoreRSASigningError + } + + return sig[:size], nil +} + +func winSignRSAPSSPadding(kh uintptr, digest []byte, algID *uint16) ([]byte, error) { + // PSS padding for TLS 1.3 and some TLS 1.2 + padInfo := winPSSPaddingInfo{pszAlgID: algID, cbSalt: winBCryptPadPSSSalt} + + var size uint32 + // Obtain the size of the signature + r, _, _ := winNCryptSignHash.Call( + kh, + uintptr(unsafe.Pointer(&padInfo)), + uintptr(unsafe.Pointer(&digest[0])), + uintptr(len(digest)), + 0, + 0, + uintptr(unsafe.Pointer(&size)), + winBCryptPadPSS) + if r != 0 { + return nil, ErrStoreRSASigningError + } + + // Obtain the signature data + sig := make([]byte, size) + r, _, _ = winNCryptSignHash.Call( + kh, + uintptr(unsafe.Pointer(&padInfo)), + uintptr(unsafe.Pointer(&digest[0])), + uintptr(len(digest)), + uintptr(unsafe.Pointer(&sig[0])), + uintptr(size), + uintptr(unsafe.Pointer(&size)), + winBCryptPadPSS) + if r != 0 { + return nil, ErrStoreRSASigningError + } + + return sig[:size], nil +} + +// certKey wraps CryptAcquireCertificatePrivateKey. It obtains the CNG private +// key of a known certificate and returns a pointer to a winKey which implements +// both crypto.Signer. When a nil cert context is passed +// a nil key is intentionally returned, to model the expected behavior of a +// non-existent cert having no private key. +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecertificateprivatekey +func (w *winCertStore) certKey(cert *windows.CertContext) (*winKey, error) { + // Return early if a nil cert was passed. + if cert == nil { + return nil, nil + } + var ( + kh uintptr + spec uint32 + mustFree int + ) + r, _, _ := winCryptAcquireCertificatePrivateKey.Call( + uintptr(unsafe.Pointer(cert)), + winAcquireCached|winAcquireSilent|winAcquireOnlyNCryptKey, + 0, // Reserved, must be null. + uintptr(unsafe.Pointer(&kh)), + uintptr(unsafe.Pointer(&spec)), + uintptr(unsafe.Pointer(&mustFree)), + ) + // If the function succeeds, the return value is nonzero (TRUE). + if r == 0 { + return nil, ErrNoPrivateKeyStoreRef + } + if mustFree != 0 { + return nil, ErrNoPrivateKeyStoreRef + } + if spec != winNcryptKeySpec { + return nil, ErrNoPrivateKeyStoreRef + } + + return winKeyMetadata(kh) +} + +func winKeyMetadata(kh uintptr) (*winKey, error) { + // uc is used to populate the unique container name attribute of the private key + uc, err := winGetPropertyStr(kh, winNCryptUniqueNameProperty) + if err != nil { + // unable to determine key unique name + return nil, ErrExtractingPrivateKeyMetadata + } + + alg, err := winGetPropertyStr(kh, winNCryptAlgorithmGroupProperty) + if err != nil { + // unable to determine key algorithm + return nil, ErrExtractingPrivateKeyMetadata + } + + var pub crypto.PublicKey + + switch alg { + case "ECDSA", "ECDH": + buf, err := winExport(kh, winBCryptECCPublicBlob) + if err != nil { + // failed to export ECC public key + return nil, ErrExtractingECCPublicKey + } + pub, err = unmarshalECC(buf, kh) + if err != nil { + return nil, ErrExtractingECCPublicKey + } + case "RSA": + buf, err := winExport(kh, winBCryptRSAPublicBlob) + if err != nil { + return nil, ErrExtractingRSAPublicKey + } + pub, err = winUnmarshalRSA(buf) + if err != nil { + return nil, ErrExtractingRSAPublicKey + } + default: + return nil, ErrBadPublicKeyAlgorithm + } + + return &winKey{handle: kh, pub: pub, Container: uc, AlgorithmGroup: alg}, nil +} + +func winGetProperty(kh uintptr, property *uint16) ([]byte, error) { + var strSize uint32 + r, _, _ := winNCryptGetProperty.Call( + kh, + uintptr(unsafe.Pointer(property)), + 0, + 0, + uintptr(unsafe.Pointer(&strSize)), + 0, + 0) + if r != 0 { + return nil, ErrExtractPropertyFromKey + } + + buf := make([]byte, strSize) + r, _, _ = winNCryptGetProperty.Call( + kh, + uintptr(unsafe.Pointer(property)), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(strSize), + uintptr(unsafe.Pointer(&strSize)), + 0, + 0) + if r != 0 { + return nil, ErrExtractPropertyFromKey + } + + return buf, nil +} + +func winGetPropertyStr(kh uintptr, property *uint16) (string, error) { + buf, err := winFnGetProperty(kh, property) + if err != nil { + return "", ErrExtractPropertyFromKey + } + uc := bytes.ReplaceAll(buf, []byte{0x00}, []byte("")) + return string(uc), nil +} + +func winExport(kh uintptr, blobType *uint16) ([]byte, error) { + var size uint32 + // When obtaining the size of a public key, most parameters are not required + r, _, _ := winNCryptExportKey.Call( + kh, + 0, + uintptr(unsafe.Pointer(blobType)), + 0, + 0, + 0, + uintptr(unsafe.Pointer(&size)), + 0) + if r != 0 { + return nil, ErrExtractingPublicKey + } + + // Place the exported key in buf now that we know the size required + buf := make([]byte, size) + r, _, _ = winNCryptExportKey.Call( + kh, + 0, + uintptr(unsafe.Pointer(blobType)), + 0, + uintptr(unsafe.Pointer(&buf[0])), + uintptr(size), + uintptr(unsafe.Pointer(&size)), + 0) + if r != 0 { + return nil, ErrExtractingPublicKey + } + return buf, nil +} + +func unmarshalECC(buf []byte, kh uintptr) (*ecdsa.PublicKey, error) { + // BCRYPT_ECCKEY_BLOB from bcrypt.h + header := struct { + Magic uint32 + Key uint32 + }{} + + r := bytes.NewReader(buf) + if err := binary.Read(r, binary.LittleEndian, &header); err != nil { + return nil, ErrExtractingECCPublicKey + } + + curve, ok := winCurveIDs[header.Magic] + if !ok { + // Fix for b/185945636, where despite specifying the curve, nCrypt returns + // an incorrect response with BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC. + var err error + curve, err = winCurveName(kh) + if err != nil { + // unsupported header magic or cannot match the curve by name + return nil, err + } + } + + keyX := make([]byte, header.Key) + if n, err := r.Read(keyX); n != int(header.Key) || err != nil { + // failed to read key X + return nil, ErrExtractingECCPublicKey + } + + keyY := make([]byte, header.Key) + if n, err := r.Read(keyY); n != int(header.Key) || err != nil { + // failed to read key Y + return nil, ErrExtractingECCPublicKey + } + + pub := &ecdsa.PublicKey{ + Curve: curve, + X: new(big.Int).SetBytes(keyX), + Y: new(big.Int).SetBytes(keyY), + } + return pub, nil +} + +// winCurveName reads the curve name property and returns the corresponding curve. +func winCurveName(kh uintptr) (elliptic.Curve, error) { + cn, err := winGetPropertyStr(kh, winNCryptECCCurveNameProperty) + if err != nil { + // unable to determine the curve property name + return nil, ErrExtractPropertyFromKey + } + curve, ok := winCurveNames[cn] + if !ok { + // unknown curve name + return nil, ErrBadECCCurveName + } + return curve, nil +} + +func winUnmarshalRSA(buf []byte) (*rsa.PublicKey, error) { + // BCRYPT_RSA_BLOB from bcrypt.h + header := struct { + Magic uint32 + BitLength uint32 + PublicExpSize uint32 + ModulusSize uint32 + UnusedPrime1 uint32 + UnusedPrime2 uint32 + }{} + + r := bytes.NewReader(buf) + if err := binary.Read(r, binary.LittleEndian, &header); err != nil { + return nil, ErrExtractingRSAPublicKey + } + + if header.Magic != winRSA1Magic { + // invalid header magic + return nil, ErrExtractingRSAPublicKey + } + + if header.PublicExpSize > 8 { + // unsupported public exponent size + return nil, ErrExtractingRSAPublicKey + } + + exp := make([]byte, 8) + if n, err := r.Read(exp[8-header.PublicExpSize:]); n != int(header.PublicExpSize) || err != nil { + // failed to read public exponent + return nil, ErrExtractingRSAPublicKey + } + + mod := make([]byte, header.ModulusSize) + if n, err := r.Read(mod); n != int(header.ModulusSize) || err != nil { + // failed to read modulus + return nil, ErrExtractingRSAPublicKey + } + + pub := &rsa.PublicKey{ + N: new(big.Int).SetBytes(mod), + E: int(binary.BigEndian.Uint64(exp)), + } + return pub, nil +} + +// storeHandle returns a handle to a given cert store, opening the handle as needed. +func (w *winCertStore) storeHandle(provider uint32, store *uint16) (windows.Handle, error) { + w.mu.Lock() + defer w.mu.Unlock() + + key := fmt.Sprintf("%d%s", provider, windows.UTF16PtrToString(store)) + var err error + if w.stores[key] == nil { + w.stores[key], err = winNewStoreHandle(provider, store) + if err != nil { + return 0, ErrBadCryptoStoreProvider + } + } + return *w.stores[key].handle, nil +} + +// Verify interface conformance. +var _ credential = &winKey{} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/certstore/errors.go b/vendor/github.com/nats-io/nats-server/v2/server/certstore/errors.go new file mode 100644 index 0000000..be545cf --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/certstore/errors.go @@ -0,0 +1,79 @@ +package certstore + +import ( + "errors" +) + +var ( + // ErrBadCryptoStoreProvider represents inablity to establish link with a certificate store + ErrBadCryptoStoreProvider = errors.New("unable to open certificate store or store not available") + + // ErrBadRSAHashAlgorithm represents a bad or unsupported RSA hash algorithm + ErrBadRSAHashAlgorithm = errors.New("unsupported RSA hash algorithm") + + // ErrBadSigningAlgorithm represents a bad or unsupported signing algorithm + ErrBadSigningAlgorithm = errors.New("unsupported signing algorithm") + + // ErrStoreRSASigningError represents an error returned from store during RSA signature + ErrStoreRSASigningError = errors.New("unable to obtain RSA signature from store") + + // ErrStoreECDSASigningError represents an error returned from store during ECDSA signature + ErrStoreECDSASigningError = errors.New("unable to obtain ECDSA signature from store") + + // ErrNoPrivateKeyStoreRef represents an error getting a handle to a private key in store + ErrNoPrivateKeyStoreRef = errors.New("unable to obtain private key handle from store") + + // ErrExtractingPrivateKeyMetadata represents a family of errors extracting metadata about the private key in store + ErrExtractingPrivateKeyMetadata = errors.New("unable to extract private key metadata") + + // ErrExtractingECCPublicKey represents an error exporting ECC-type public key from store + ErrExtractingECCPublicKey = errors.New("unable to extract ECC public key from store") + + // ErrExtractingRSAPublicKey represents an error exporting RSA-type public key from store + ErrExtractingRSAPublicKey = errors.New("unable to extract RSA public key from store") + + // ErrExtractingPublicKey represents a general error exporting public key from store + ErrExtractingPublicKey = errors.New("unable to extract public key from store") + + // ErrBadPublicKeyAlgorithm represents a bad or unsupported public key algorithm + ErrBadPublicKeyAlgorithm = errors.New("unsupported public key algorithm") + + // ErrExtractPropertyFromKey represents a general failure to extract a metadata property field + ErrExtractPropertyFromKey = errors.New("unable to extract property from key") + + // ErrBadECCCurveName represents an ECC signature curve name that is bad or unsupported + ErrBadECCCurveName = errors.New("unsupported ECC curve name") + + // ErrFailedCertSearch represents not able to find certificate in store + ErrFailedCertSearch = errors.New("unable to find certificate in store") + + // ErrFailedX509Extract represents not being able to extract x509 certificate from found cert in store + ErrFailedX509Extract = errors.New("unable to extract x509 from certificate") + + // ErrBadMatchByType represents unknown CERT_MATCH_BY passed + ErrBadMatchByType = errors.New("cert match by type not implemented") + + // ErrBadCertStore represents unknown CERT_STORE passed + ErrBadCertStore = errors.New("cert store type not implemented") + + // ErrConflictCertFileAndStore represents ambiguous configuration of both file and store + ErrConflictCertFileAndStore = errors.New("'cert_file' and 'cert_store' may not both be configured") + + // ErrBadCertStoreField represents malformed cert_store option + ErrBadCertStoreField = errors.New("expected 'cert_store' to be a valid non-empty string") + + // ErrBadCertMatchByField represents malformed cert_match_by option + ErrBadCertMatchByField = errors.New("expected 'cert_match_by' to be a valid non-empty string") + + // ErrBadCertMatchField represents malformed cert_match option + ErrBadCertMatchField = errors.New("expected 'cert_match' to be a valid non-empty string") + + // ErrBadCaCertMatchField represents malformed cert_match option + ErrBadCaCertMatchField = errors.New("expected 'ca_certs_match' to be a valid non-empty string array") + + // ErrBadCertMatchSkipInvalidField represents malformed cert_match_skip_invalid option + ErrBadCertMatchSkipInvalidField = errors.New("expected 'cert_match_skip_invalid' to be a boolean") + + // ErrOSNotCompatCertStore represents cert_store passed that exists but is not valid on current OS + ErrOSNotCompatCertStore = errors.New("cert_store not compatible with current operating system") +) diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ciphersuites.go b/vendor/github.com/nats-io/nats-server/v2/server/ciphersuites.go index 55dbc8b..1c5ec3a 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/ciphersuites.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/ciphersuites.go @@ -1,4 +1,4 @@ -// Copyright 2016-2018 The NATS Authors +// Copyright 2016-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,6 +14,7 @@ package server import ( + "crypto/fips140" "crypto/tls" ) @@ -94,6 +95,16 @@ var curvePreferenceMap = map[string]tls.CurveID{ // reorder to default to the highest level of security. See: // https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go func defaultCurvePreferences() []tls.CurveID { + if fips140.Enabled() { + // X25519 is not FIPS-approved by itself, but it is when + // combined with MLKEM768. + return []tls.CurveID{ + tls.X25519MLKEM768, // post-quantum + tls.CurveP256, + tls.CurveP384, + tls.CurveP521, + } + } return []tls.CurveID{ tls.X25519, // faster than P256, arguably more secure tls.CurveP256, diff --git a/vendor/github.com/nats-io/nats-server/v2/server/client.go b/vendor/github.com/nats-io/nats-server/v2/server/client.go index 806978c..4f733b7 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/client.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/client.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,13 +15,19 @@ package server import ( "bytes" + "crypto/sha256" "crypto/tls" + "crypto/x509" + "encoding/hex" "encoding/json" + "errors" "fmt" "io" + "math" "math/rand" "net" "net/http" + "net/url" "regexp" "runtime" "strconv" @@ -30,7 +36,9 @@ import ( "sync/atomic" "time" + "github.com/klauspost/compress/s2" "github.com/nats-io/jwt/v2" + "github.com/nats-io/nats-server/v2/internal/fastrand" ) // Type of client connection. @@ -51,6 +59,11 @@ const ( ACCOUNT ) +// Internal clients. kind should be SYSTEM, JETSTREAM or ACCOUNT +func isInternalClient(kind int) bool { + return kind == SYSTEM || kind == JETSTREAM || kind == ACCOUNT +} + // Extended type of a CLIENT connection. This is returned by c.clientType() // and indicate what type of client connection we are dealing with. // If invoked on a non CLIENT connection, NON_CLIENT type is returned. @@ -81,9 +94,11 @@ const ( okProto = "+OK" + _CRLF_ ) -func init() { - rand.Seed(time.Now().UnixNano()) -} +// TLS Hanshake client types +const ( + tlsHandshakeLeaf = "leafnode" + tlsHandshakeMQTT = "mqtt" +) const ( // Scratch buffer size for the processMsg() calls. @@ -106,8 +121,9 @@ const ( maxNoRTTPingBeforeFirstPong = 2 * time.Second // For stalling fast producers - stallClientMinDuration = 100 * time.Millisecond - stallClientMaxDuration = time.Second + stallClientMinDuration = 2 * time.Millisecond + stallClientMaxDuration = 5 * time.Millisecond + stallTotalAllowed = 10 * time.Millisecond ) var readLoopReportThreshold = readLoopReport @@ -115,19 +131,29 @@ var readLoopReportThreshold = readLoopReport // Represent client booleans with a bitmask type clientFlag uint16 +const ( + hdrLine = "NATS/1.0\r\n" + emptyHdrLine = "NATS/1.0\r\n\r\n" +) + // Some client state represented as flags const ( - connectReceived clientFlag = 1 << iota // The CONNECT proto has been received - infoReceived // The INFO protocol has been received - firstPongSent // The first PONG has been sent - handshakeComplete // For TLS clients, indicate that the handshake is complete - flushOutbound // Marks client as having a flushOutbound call in progress. - noReconnect // Indicate that on close, this connection should not attempt a reconnect - closeConnection // Marks that closeConnection has already been called. - connMarkedClosed // Marks that markConnAsClosed has already been called. - writeLoopStarted // Marks that the writeLoop has been started. - skipFlushOnClose // Marks that flushOutbound() should not be called on connection close. - expectConnect // Marks if this connection is expected to send a CONNECT + connectReceived clientFlag = 1 << iota // The CONNECT proto has been received + infoReceived // The INFO protocol has been received + firstPongSent // The first PONG has been sent + handshakeComplete // For TLS clients, indicate that the handshake is complete + flushOutbound // Marks client as having a flushOutbound call in progress. + noReconnect // Indicate that on close, this connection should not attempt a reconnect + closeConnection // Marks that closeConnection has already been called. + connMarkedClosed // Marks that markConnAsClosed has already been called. + writeLoopStarted // Marks that the writeLoop has been started. + skipFlushOnClose // Marks that flushOutbound() should not be called on connection close. + expectConnect // Marks if this connection is expected to send a CONNECT + connectProcessFinished // Marks if this connection has finished the connect process. + compressionNegotiated // Marks if this connection has negotiated compression level with remote. + didTLSFirst // Marks if this connection requested and was accepted doing the TLS handshake first (prior to INFO). + isSlowConsumer // Marks connection as a slow consumer. + firstPong // Marks if this is the first PONG received ) // set the flag (would be equivalent to set the boolean to true) @@ -193,6 +219,10 @@ const ( ClusterNameConflict DuplicateRemoteLeafnodeConnection DuplicateClientID + DuplicateServerName + MinimumVersionRequired + ClusterNamesIdentical + Kicked ) // Some flags passed to processMsgResults @@ -204,21 +234,37 @@ const ( pmrMsgImportedFromService ) +type WriteTimeoutPolicy uint8 + +const ( + WriteTimeoutPolicyDefault = iota + WriteTimeoutPolicyClose + WriteTimeoutPolicyRetry +) + +// String returns a human-friendly value. Only used in varz. +func (p WriteTimeoutPolicy) String() string { + switch p { + case WriteTimeoutPolicyClose: + return "close" + case WriteTimeoutPolicyRetry: + return "retry" + default: + return _EMPTY_ + } +} + type client struct { // Here first because of use of atomics, and memory alignment. stats - // Indicate if we should check gwrm or not. Since checking gwrm is done - // when processing inbound messages and requires the lock we want to - // check only when needed. This is set/get using atomic, so needs to - // be memory aligned. - cgwrt int32 + gwReplyMapping kind int srv *Server acc *Account perms *permissions in readCache parseState - opts clientOpts + opts ClientOpts rrTracking *rrTracking mpay int32 msubs int32 @@ -240,10 +286,16 @@ type client struct { darray []string pcd map[*client]struct{} atmr *time.Timer + expires time.Time ping pinfo msgb [msgScratchSize]byte last time.Time - headers bool + lastIn time.Time + + repliesSincePrune uint16 + lastReplyPrune time.Time + + headers bool rtt time.Duration rttStart time.Time @@ -254,15 +306,19 @@ type client struct { ws *websocket mqtt *mqtt - // To keep track of gateway replies mapping - gwrm map[string]*gwReplyMap - flags clientFlag // Compact booleans into a single field. Size will be increased when needed. rref byte trace bool echo bool + noIcb bool + iproc bool // In-Process connection, set at creation and immutable. + + tags jwt.TagList + nameTag string + + tlsTo *time.Timer } type rrTracking struct { @@ -273,26 +329,85 @@ type rrTracking struct { // Struct for PING initiation from the server. type pinfo struct { - tmr *time.Timer - last time.Time - out int + tmr *time.Timer + out int } // outbound holds pending data for a socket. type outbound struct { - p []byte // Primary write buffer - s []byte // Secondary for use post flush - nb net.Buffers // net.Buffers for writev IO - sz int32 // limit size per []byte, uses variable BufSize constants, start, min, max. - sws int32 // Number of short writes, used for dynamic resizing. - pb int64 // Total pending/queued bytes. - pm int32 // Total pending/queued messages. - fsp int32 // Flush signals that are pending per producer from readLoop's pcd. - sch chan struct{} // To signal writeLoop that there is data to flush. - wdl time.Duration // Snapshot of write deadline. - mp int64 // Snapshot of max pending for client. - lft time.Duration // Last flush time for Write. - stc chan struct{} // Stall chan we create to slow down producers on overrun, e.g. fan-in. + nb net.Buffers // Pending buffers for send, each has fixed capacity as per nbPool below. + wnb net.Buffers // Working copy of "nb", reused on each flushOutbound call, partial writes may leave entries here for next iteration. + pb int64 // Total pending/queued bytes. + fsp int32 // Flush signals that are pending per producer from readLoop's pcd. + wtp WriteTimeoutPolicy // What do we do on a write timeout? + sg *sync.Cond // To signal writeLoop that there is data to flush. + wdl time.Duration // Snapshot of write deadline. + mp int64 // Snapshot of max pending for client. + lft time.Duration // Last flush time for Write. + stc chan struct{} // Stall chan we create to slow down producers on overrun, e.g. fan-in. + cw *s2.Writer +} + +const nbMaxVectorSize = 1024 // == IOV_MAX on Linux/Darwin and most other Unices (except Solaris/AIX) + +const nbPoolSizeSmall = 512 // Underlying array size of small buffer +const nbPoolSizeMedium = 4096 // Underlying array size of medium buffer +const nbPoolSizeLarge = 65536 // Underlying array size of large buffer + +var nbPoolSmall = &sync.Pool{ + New: func() any { + b := [nbPoolSizeSmall]byte{} + return &b + }, +} + +var nbPoolMedium = &sync.Pool{ + New: func() any { + b := [nbPoolSizeMedium]byte{} + return &b + }, +} + +var nbPoolLarge = &sync.Pool{ + New: func() any { + b := [nbPoolSizeLarge]byte{} + return &b + }, +} + +// nbPoolGet returns a frame that is a best-effort match for the given size. +// Once a pooled frame is no longer needed, it should be recycled by passing +// it to nbPoolPut. +func nbPoolGet(sz int) []byte { + switch { + case sz <= nbPoolSizeSmall: + return nbPoolSmall.Get().(*[nbPoolSizeSmall]byte)[:0] + case sz <= nbPoolSizeMedium: + return nbPoolMedium.Get().(*[nbPoolSizeMedium]byte)[:0] + default: + return nbPoolLarge.Get().(*[nbPoolSizeLarge]byte)[:0] + } +} + +// nbPoolPut recycles a frame that was retrieved from nbPoolGet. It is not +// safe to return multiple slices referring to chunks of the same underlying +// array as this may create overlaps when the buffers are returned to their +// original size, resulting in race conditions. +func nbPoolPut(b []byte) { + switch cap(b) { + case nbPoolSizeSmall: + b := (*[nbPoolSizeSmall]byte)(b[0:nbPoolSizeSmall]) + nbPoolSmall.Put(b) + case nbPoolSizeMedium: + b := (*[nbPoolSizeMedium]byte)(b[0:nbPoolSizeMedium]) + nbPoolMedium.Put(b) + case nbPoolSizeLarge: + b := (*[nbPoolSizeLarge]byte)(b[0:nbPoolSizeLarge]) + nbPoolLarge.Put(b) + default: + // Ignore frames that are the wrong size, this might happen + // with WebSocket/MQTT messages as they are framed + } } type perm struct { @@ -301,10 +416,13 @@ type perm struct { } type permissions struct { + // Have these 2 first for memory alignment due to the use of atomic. + pcsz int32 + prun int32 sub perm pub perm resp *ResponsePermission - pcache map[string]bool + pcache sync.Map } // This is used to dynamically track responses and reply subjects @@ -338,15 +456,19 @@ const ( pruneSize = 32 routeTargetInit = 8 replyPermLimit = 4096 + replyPruneTime = time.Second ) // Represent read cache booleans with a bitmask type readCacheFlag uint16 const ( - hasMappings readCacheFlag = 1 << iota // For account subject mappings. + hasMappings readCacheFlag = 1 << iota // For account subject mappings. + switchToCompression readCacheFlag = 1 << 1 ) +const sysGroup = "_sys_" + // Used in readloop to cache hot subject lookups and group statistics. type readCache struct { // These are for clients who are bound to a single account. @@ -360,8 +482,6 @@ type readCache struct { // to make sure to only send one message and properly scope to queues as needed. rts []routeTarget - prand *rand.Rand - // These are all temporary totals for an invocation of a read in readloop. msgs int32 bytes int32 @@ -370,8 +490,14 @@ type readCache struct { rsz int32 // Read buffer size srs int32 // Short reads, used for dynamic buffer resizing. - // These are for readcache flags to avoind locks. + // These are for readcache flags to avoid locks. flags readCacheFlag + + // Capture the time we started processing our readLoop. + start time.Time + + // Total time stalled so far for readLoop processing. + tst time.Duration } // set the flag (would be equivalent to set the boolean to true) @@ -390,8 +516,8 @@ func (rcf readCacheFlag) isSet(c readCacheFlag) bool { } const ( - defaultMaxPerAccountCacheSize = 4096 - defaultPrunePerAccountCacheSize = 256 + defaultMaxPerAccountCacheSize = 8192 + defaultPrunePerAccountCacheSize = 1024 defaultClosedSubsCheckInterval = 5 * time.Minute ) @@ -414,7 +540,15 @@ func (c *client) String() (id string) { return loaded.(string) } - return "" + return _EMPTY_ +} + +// GetNonce returns the nonce that was presented to the user on connection +func (c *client) GetNonce() []byte { + c.mu.Lock() + defer c.mu.Unlock() + + return c.nonce } // GetName returns the application supplied name for the connection. @@ -426,13 +560,18 @@ func (c *client) GetName() string { } // GetOpts returns the client options provided by the application. -func (c *client) GetOpts() *clientOpts { +func (c *client) GetOpts() *ClientOpts { return &c.opts } // GetTLSConnectionState returns the TLS ConnectionState if TLS is enabled, nil // otherwise. Implements the ClientAuth interface. func (c *client) GetTLSConnectionState() *tls.ConnectionState { + c.mu.Lock() + defer c.mu.Unlock() + if c.nc == nil { + return nil + } tc, ok := c.nc.(*tls.Conn) if !ok { return nil @@ -461,13 +600,29 @@ func (c *client) clientType() int { } } +var clientTypeStringMap = map[int]string{ + NON_CLIENT: _EMPTY_, + NATS: "nats", + WS: "websocket", + MQTT: "mqtt", +} + +func (c *client) clientTypeString() string { + if typeStringVal, ok := clientTypeStringMap[c.clientType()]; ok { + return typeStringVal + } + return _EMPTY_ +} + // This is the main subscription struct that indicates // interest in published messages. // FIXME(dlc) - This is getting bloated for normal subs, need // to optionally have an opts section for non-normal stuff. type subscription struct { client *client - im *streamImport // This is for import stream support. + im *streamImport // This is for import stream support. + rsi bool + si bool shadow []*subscription // This is to track shadowed accounts. icb msgHandler subject []byte @@ -493,7 +648,7 @@ func (s *subscription) isClosed() bool { return atomic.LoadInt32(&s.closed) == 1 } -type clientOpts struct { +type ClientOpts struct { Echo bool `json:"echo"` Verbose bool `json:"verbose"` Pedantic bool `json:"pedantic"` @@ -516,10 +671,13 @@ type clientOpts struct { // Routes and Leafnodes only Import *SubjectPermission `json:"import,omitempty"` Export *SubjectPermission `json:"export,omitempty"` + + // Leafnodes + RemoteAccount string `json:"remote_account,omitempty"` } -var defaultOpts = clientOpts{Verbose: true, Pedantic: true, Echo: true} -var internalOpts = clientOpts{Verbose: false, Pedantic: false, Echo: false} +var defaultOpts = ClientOpts{Verbose: true, Pedantic: true, Echo: true} +var internalOpts = ClientOpts{Verbose: false, Pedantic: false, Echo: false} func (c *client) setTraceLevel() { if c.kind == SYSTEM && !(atomic.LoadInt32(&c.srv.logging.traceSysAcc) != 0) { @@ -535,12 +693,44 @@ func (c *client) initClient() { c.cid = atomic.AddUint64(&s.gcid, 1) // Outbound data structure setup - c.out.sz = startBufSize - c.out.sch = make(chan struct{}, 1) + c.out.sg = sync.NewCond(&(c.mu)) opts := s.getOpts() // Snapshots to avoid mutex access in fast paths. c.out.wdl = opts.WriteDeadline + switch { + case c.kind == ROUTER && opts.Cluster.WriteDeadline > 0: + c.out.wdl = opts.Cluster.WriteDeadline + case c.kind == GATEWAY && opts.Gateway.WriteDeadline > 0: + c.out.wdl = opts.Gateway.WriteDeadline + case c.kind == LEAF && opts.LeafNode.WriteDeadline > 0: + c.out.wdl = opts.LeafNode.WriteDeadline + } + switch c.kind { + case ROUTER: + if c.out.wtp = opts.Cluster.WriteTimeout; c.out.wtp == WriteTimeoutPolicyDefault { + c.out.wtp = WriteTimeoutPolicyRetry + } + case LEAF: + if c.out.wtp = opts.LeafNode.WriteTimeout; c.out.wtp == WriteTimeoutPolicyDefault { + c.out.wtp = WriteTimeoutPolicyRetry + } + case GATEWAY: + if c.out.wtp = opts.Gateway.WriteTimeout; c.out.wtp == WriteTimeoutPolicyDefault { + c.out.wtp = WriteTimeoutPolicyRetry + } + default: + if c.out.wtp = opts.WriteTimeout; c.out.wtp == WriteTimeoutPolicyDefault { + c.out.wtp = WriteTimeoutPolicyClose + } + } c.out.mp = opts.MaxPending + // Snapshot max control line since currently can not be changed on reload and we + // were checking it on each call to parse. If this changes and we allow MaxControlLine + // to be reloaded without restart, this code will need to change. + c.mcl = int32(opts.MaxControlLine) + if c.mcl == 0 { + c.mcl = MAX_CONTROL_LINE_SIZE + } c.subs = make(map[string]*subscription) c.echo = true @@ -563,8 +753,17 @@ func (c *client) initClient() { if addr := c.nc.RemoteAddr(); addr != nil { if conn = addr.String(); conn != _EMPTY_ { host, port, _ := net.SplitHostPort(conn) - iPort, _ := strconv.Atoi(port) + iPort, _ := strconv.ParseUint(port, 10, 16) c.host, c.port = host, uint16(iPort) + if c.isWebsocket() && c.ws.clientIP != _EMPTY_ { + cip := c.ws.clientIP + // Surround IPv6 addresses with square brackets, as + // net.JoinHostPort would do... + if strings.Contains(cip, ":") { + cip = "[" + cip + "]" + } + conn = fmt.Sprintf("%s/%s", cip, conn) + } // Now that we have extracted host and port, escape // the string because it is going to be used in Sprintf conn = strings.ReplaceAll(conn, "%", "%%") @@ -580,14 +779,22 @@ func (c *client) initClient() { case WS: c.ncs.Store(fmt.Sprintf("%s - wid:%d", conn, c.cid)) case MQTT: - c.ncs.Store(fmt.Sprintf("%s - mid:%d", conn, c.cid)) + var ws string + if c.isWebsocket() { + ws = "_ws" + } + c.ncs.Store(fmt.Sprintf("%s - mid%s:%d", conn, ws, c.cid)) } case ROUTER: c.ncs.Store(fmt.Sprintf("%s - rid:%d", conn, c.cid)) case GATEWAY: c.ncs.Store(fmt.Sprintf("%s - gid:%d", conn, c.cid)) case LEAF: - c.ncs.Store(fmt.Sprintf("%s - lid:%d", conn, c.cid)) + var ws string + if c.isWebsocket() { + ws = "_ws" + } + c.ncs.Store(fmt.Sprintf("%s - lid%s:%d", conn, ws, c.cid)) case SYSTEM: c.ncs.Store("SYSTEM") case JETSTREAM: @@ -616,14 +823,29 @@ func (c *client) reportErrRegisterAccount(acc *Account, err error) { c.maxAccountConnExceeded() return } - c.Errorf("Problem registering with account [%s]", acc.Name) + c.Errorf("Problem registering with account %q: %s", acc.Name, err) c.sendErr("Failed Account Registration") } +// Kind returns the client kind and will be one of the defined constants like CLIENT, ROUTER, GATEWAY, LEAF +func (c *client) Kind() int { + c.mu.Lock() + kind := c.kind + c.mu.Unlock() + + return kind +} + // registerWithAccount will register the given user with a specific // account. This will change the subject namespace. func (c *client) registerWithAccount(acc *Account) error { - if acc == nil || acc.sl == nil { + if acc == nil { + return ErrBadAccount + } + acc.mu.RLock() + bad := acc.sl == nil + acc.mu.RUnlock() + if bad { return ErrBadAccount } // If we were previously registered, usually to $G, do accounting here to remove. @@ -643,8 +865,14 @@ func (c *client) registerWithAccount(acc *Account) error { // Check if we have a max connections violation if kind == CLIENT && acc.MaxTotalConnectionsReached() { return ErrTooManyAccountConnections - } else if kind == LEAF && acc.MaxTotalLeafNodesReached() { - return ErrTooManyAccountConnections + } else if kind == LEAF { + // Check if we are already connected to this cluster. + if rc := c.remoteCluster(); rc != _EMPTY_ && acc.hasLeafNodeCluster(rc) { + return ErrLeafNodeLoop + } + if acc.MaxTotalLeafNodesReached() { + return ErrTooManyAccountConnections + } } // Add in new one. @@ -661,15 +889,16 @@ func (c *client) subsAtLimit() bool { } func minLimit(value *int32, limit int32) bool { - if *value != jwt.NoLimit { + v := atomic.LoadInt32(value) + if v != jwt.NoLimit { if limit != jwt.NoLimit { - if limit < *value { - *value = limit + if limit < v { + atomic.StoreInt32(value, limit) return true } } } else if limit != jwt.NoLimit { - *value = limit + atomic.StoreInt32(value, limit) return true } return false @@ -682,16 +911,29 @@ func (c *client) applyAccountLimits() { if c.acc == nil || (c.kind != CLIENT && c.kind != LEAF) { return } - c.mpay = jwt.NoLimit + atomic.StoreInt32(&c.mpay, jwt.NoLimit) c.msubs = jwt.NoLimit - if c.opts.JWT != "" { // user jwt implies account + if c.opts.JWT != _EMPTY_ { // user jwt implies account if uc, _ := jwt.DecodeUserClaims(c.opts.JWT); uc != nil { - c.mpay = int32(uc.Limits.Payload) + atomic.StoreInt32(&c.mpay, int32(uc.Limits.Payload)) c.msubs = int32(uc.Limits.Subs) + if uc.IssuerAccount != _EMPTY_ && uc.IssuerAccount != uc.Issuer { + if scope, ok := c.acc.signingKeys[uc.Issuer]; ok { + if userScope, ok := scope.(*jwt.UserScope); ok { + // if signing key disappeared or changed and we don't get here, the client will be disconnected + c.mpay = int32(userScope.Template.Limits.Payload) + c.msubs = int32(userScope.Template.Limits.Subs) + } + } + } } } + + c.acc.mu.RLock() minLimit(&c.mpay, c.acc.mpay) minLimit(&c.msubs, c.acc.msubs) + c.acc.mu.RUnlock() + s := c.srv opts := s.getOpts() mPay := opts.MaxPayload @@ -742,10 +984,22 @@ func (c *client) RegisterUser(user *User) { } else { c.setPermissions(user.Permissions) } + + // allows custom authenticators to set a username to be reported in + // server events and more + if user.Username != _EMPTY_ { + c.opts.Username = user.Username + } + + // if a deadline time stamp is set we start a timer to disconnect the user at that time + if !user.ConnectionDeadline.IsZero() { + c.setExpirationTimerUnlocked(time.Until(user.ConnectionDeadline)) + } + c.mu.Unlock() } -// RegisterNkey allows auth to call back into a new nkey +// RegisterNkeyUser allows auth to call back into a new nkey // client with the authenticated user. This is used to map // any permissions into the client and setup accounts. func (c *client) RegisterNkeyUser(user *NkeyUser) error { @@ -790,7 +1044,6 @@ func (c *client) setPermissions(perms *Permissions) { return } c.perms = &permissions{} - c.perms.pcache = make(map[string]bool) // Loop over publish permissions if perms.Publish != nil { @@ -858,6 +1111,120 @@ func (c *client) setPermissions(perms *Permissions) { } } +// Build public permissions from internal ones. +// Used for user info requests. +func (c *client) publicPermissions() *Permissions { + c.mu.Lock() + defer c.mu.Unlock() + + if c.perms == nil { + return nil + } + perms := &Permissions{ + Publish: &SubjectPermission{}, + Subscribe: &SubjectPermission{}, + } + + _subs := [32]*subscription{} + + // Publish + if c.perms.pub.allow != nil { + subs := _subs[:0] + c.perms.pub.allow.All(&subs) + for _, sub := range subs { + perms.Publish.Allow = append(perms.Publish.Allow, string(sub.subject)) + } + } + if c.perms.pub.deny != nil { + subs := _subs[:0] + c.perms.pub.deny.All(&subs) + for _, sub := range subs { + perms.Publish.Deny = append(perms.Publish.Deny, string(sub.subject)) + } + } + // Subsribe + if c.perms.sub.allow != nil { + subs := _subs[:0] + c.perms.sub.allow.All(&subs) + for _, sub := range subs { + perms.Subscribe.Allow = append(perms.Subscribe.Allow, string(sub.subject)) + } + } + if c.perms.sub.deny != nil { + subs := _subs[:0] + c.perms.sub.deny.All(&subs) + for _, sub := range subs { + perms.Subscribe.Deny = append(perms.Subscribe.Deny, string(sub.subject)) + } + } + // Responses. + if c.perms.resp != nil { + rp := *c.perms.resp + perms.Response = &rp + } + + return perms +} + +type denyType int + +const ( + pub = denyType(iota + 1) + sub + both +) + +// Merge client.perms structure with additional pub deny permissions +// Lock is held on entry. +func (c *client) mergeDenyPermissions(what denyType, denyPubs []string) { + if len(denyPubs) == 0 { + return + } + if c.perms == nil { + c.perms = &permissions{} + } + var perms []*perm + switch what { + case pub: + perms = []*perm{&c.perms.pub} + case sub: + perms = []*perm{&c.perms.sub} + case both: + perms = []*perm{&c.perms.pub, &c.perms.sub} + } + for _, p := range perms { + if p.deny == nil { + p.deny = NewSublistWithCache() + } + FOR_DENY: + for _, subj := range denyPubs { + r := p.deny.Match(subj) + for _, v := range r.qsubs { + for _, s := range v { + if string(s.subject) == subj { + continue FOR_DENY + } + } + } + for _, s := range r.psubs { + if string(s.subject) == subj { + continue FOR_DENY + } + } + sub := &subscription{subject: []byte(subj)} + p.deny.Insert(sub) + } + } +} + +// Merge client.perms structure with additional pub deny permissions +// Client lock must not be held on entry +func (c *client) mergeDenyPermissionsLocked(what denyType, denyPubs []string) { + c.mu.Lock() + c.mergeDenyPermissions(what, denyPubs) + c.mu.Unlock() +} + // Check to see if we have an expiration for the user JWT via base claims. // FIXME(dlc) - Clear on connect with new JWT. func (c *client) setExpiration(claims *jwt.ClaimsData, validFor time.Duration) { @@ -899,41 +1266,26 @@ func (c *client) writeLoop() { return } c.flags.set(writeLoopStarted) - ch := c.out.sch c.mu.Unlock() // Used to check that we did flush from last wake up. waitOk := true - - // Used to limit the wait for a signal - const maxWait = time.Second - t := time.NewTimer(maxWait) - - var close bool + var closed bool // Main loop. Will wait to be signaled and then will use // buffered outbound structure for efficient writev to the underlying socket. for { c.mu.Lock() - if close = c.isClosed(); !close { + if closed = c.isClosed(); !closed { owtf := c.out.fsp > 0 && c.out.pb < maxBufSize && c.out.fsp < maxFlushPending if waitOk && (c.out.pb == 0 || owtf) { - c.mu.Unlock() - - // Reset our timer - t.Reset(maxWait) - - // Wait on pending data. - select { - case <-ch: - case <-t.C: - } - - c.mu.Lock() - close = c.isClosed() + c.out.sg.Wait() + // Check that connection has not been closed while lock was released + // in the conditional wait. + closed = c.isClosed() } } - if close { + if closed { c.flushAndClose(false) c.mu.Unlock() @@ -955,9 +1307,7 @@ func (c *client) writeLoop() { // flushClients will make sure to flush any clients we may have // sent to during processing. We pass in a budget as a time.Duration -// for how much time to spend in place flushing for this client. This -// will normally be called in the readLoop of the client who sent the -// message that now is being delivered. +// for how much time to spend in place flushing for this client. func (c *client) flushClients(budget time.Duration) time.Time { last := time.Now() @@ -1008,26 +1358,22 @@ func (c *client) readLoop(pre []byte) { c.mqtt.r = &mqttReader{reader: nc} } c.in.rsz = startBufSize - // Snapshot max control line since currently can not be changed on reload and we - // were checking it on each call to parse. If this changes and we allow MaxControlLine - // to be reloaded without restart, this code will need to change. - c.mcl = MAX_CONTROL_LINE_SIZE - if s != nil { - if opts := s.getOpts(); opts != nil { - c.mcl = int32(opts.MaxControlLine) - } - } // Check the per-account-cache for closed subscriptions cpacc := c.kind == ROUTER || c.kind == GATEWAY // Last per-account-cache check for closed subscriptions lpacc := time.Now() acc := c.acc + var masking bool + if ws { + masking = c.ws.maskread + } + checkCompress := c.kind == ROUTER || c.kind == LEAF c.mu.Unlock() defer func() { if c.isMqtt() { - s.mqttHandleWill(c) + s.mqttHandleClosedClient(c) } // These are used only in the readloop, so we can set them to nil // on exit of the readLoop. @@ -1046,40 +1392,49 @@ func (c *client) readLoop(pre []byte) { var wsr *wsReadInfo if ws { - wsr = &wsReadInfo{} + wsr = &wsReadInfo{mask: masking} wsr.init() } - // If we have a pre buffer parse that first. - if len(pre) > 0 { - c.parse(pre) - } + var decompress bool + var reader io.Reader + reader = nc for { - n, err := nc.Read(b) - // If we have any data we will try to parse and exit at the end. - if n == 0 && err != nil { - c.closeConnection(closedStateForErr(err)) - return + var n int + var err error + + // If we have a pre buffer parse that first. + if len(pre) > 0 { + b = pre + n = len(pre) + pre = nil + } else { + n, err = reader.Read(b) + // If we have any data we will try to parse and exit at the end. + if n == 0 && err != nil { + c.closeConnection(closedStateForErr(err)) + return + } } if ws { - bufs, err = c.wsRead(wsr, nc, b[:n]) + bufs, err = c.wsRead(wsr, reader, b[:n]) if bufs == nil && err != nil { if err != io.EOF { c.Errorf("read error: %v", err) } c.closeConnection(closedStateForErr(err)) + return } else if bufs == nil { continue } } else { bufs[0] = b[:n] } - start := time.Now() // Check if the account has mappings and if so set the local readcache flag. // We check here to make sure any changes such as config reload are reflected here. - if c.kind == CLIENT { + if c.kind == CLIENT || c.kind == LEAF { if acc.hasMappings() { c.in.flags.set(hasMappings) } else { @@ -1087,6 +1442,8 @@ func (c *client) readLoop(pre []byte) { } } + c.in.start = time.Now() + // Clear inbound stats cache c.in.msgs = 0 c.in.bytes = 0 @@ -1096,7 +1453,16 @@ func (c *client) readLoop(pre []byte) { // to process messages, etc. for i := 0; i < len(bufs); i++ { if err := c.parse(bufs[i]); err != nil { - if dur := time.Since(start); dur >= readLoopReportThreshold { + if err == ErrMinimumVersionRequired { + // Special case here, currently only for leaf node connections. + // When process the CONNECT protocol, if the minimum version + // required was not met, an error was printed and sent back to + // the remote, and connection was closed after a certain delay + // (to avoid "rapid" reconnection from the remote). + // We don't need to do any of the things below, simply return. + return + } + if dur := time.Since(c.in.start); dur >= readLoopReportThreshold { c.Warnf("Readloop processing time: %v", dur) } // Need to call flushClients because some of the clients have been @@ -1110,35 +1476,57 @@ func (c *client) readLoop(pre []byte) { } return } + // Clear total stalled time here. + if c.in.tst >= stallClientMaxDuration { + c.rateLimitFormatWarnf("Producer was stalled for a total of %v", c.in.tst.Round(time.Millisecond)) + } + c.in.tst = 0 + } + + // If we are a ROUTER/LEAF and have processed an INFO, it is possible that + // we are asked to switch to compression now. + if checkCompress && c.in.flags.isSet(switchToCompression) { + c.in.flags.clear(switchToCompression) + // For now we support only s2 compression... + reader = s2.NewReader(nc) + decompress = true } // Updates stats for client and server that were collected // from parsing through the buffer. if c.in.msgs > 0 { - atomic.AddInt64(&c.inMsgs, int64(c.in.msgs)) - atomic.AddInt64(&c.inBytes, int64(c.in.bytes)) - atomic.AddInt64(&s.inMsgs, int64(c.in.msgs)) - atomic.AddInt64(&s.inBytes, int64(c.in.bytes)) - } + inMsgs := int64(c.in.msgs) + inBytes := int64(c.in.bytes) + + atomic.AddInt64(&c.inMsgs, inMsgs) + atomic.AddInt64(&c.inBytes, inBytes) + + if acc != nil { + acc.stats.Lock() + acc.stats.inMsgs += inMsgs + acc.stats.inBytes += inBytes + if c.kind == LEAF { + acc.stats.ln.inMsgs += int64(inMsgs) + acc.stats.ln.inBytes += int64(inBytes) + } + acc.stats.Unlock() + } - // Budget to spend in place flushing outbound data. - // Client will be checked on several fronts to see - // if applicable. Routes and Gateways will never - // spend time flushing outbound in place. - var budget time.Duration - if c.kind == CLIENT { - budget = time.Millisecond + atomic.AddInt64(&s.inMsgs, inMsgs) + atomic.AddInt64(&s.inBytes, inBytes) } - // Flush, or signal to writeLoop to flush to socket. - last := c.flushClients(budget) + // Signal to writeLoop to flush to socket. + last := c.flushClients(0) // Update activity, check read buffer size. c.mu.Lock() // Activity based on interest changes or data/msgs. + // Also update last receive activity for ping sender if c.in.msgs > 0 || c.in.subs > 0 { c.last = last + c.lastIn = last } if n >= cap(b) { @@ -1159,9 +1547,24 @@ func (c *client) readLoop(pre []byte) { } // re-snapshot the account since it can change during reload, etc. acc = c.acc + // Refresh nc because in some cases, we have upgraded c.nc to TLS. + if nc != c.nc { + nc = c.nc + if decompress && nc != nil { + // For now we support only s2 compression... + reader.(*s2.Reader).Reset(nc) + } else if !decompress { + reader = nc + } + } c.mu.Unlock() - if dur := time.Since(start); dur >= readLoopReportThreshold { + // Connection was closed + if nc == nil { + return + } + + if dur := time.Since(c.in.start); dur >= readLoopReportThreshold { c.Warnf("Readloop processing time: %v", dur) } @@ -1172,7 +1575,7 @@ func (c *client) readLoop(pre []byte) { return } - if cpacc && (start.Sub(lpacc)) >= closedSubsCheckInterval { + if cpacc && (c.in.start.Sub(lpacc)) >= closedSubsCheckInterval { c.pruneClosedSubFromPerAccountCache() lpacc = time.Now() } @@ -1187,32 +1590,15 @@ func closedStateForErr(err error) ClosedState { return ReadError } -// collapsePtoNB will place primary onto nb buffer as needed in prep for WriteTo. -// This will return a copy on purpose. +// collapsePtoNB will either returned framed WebSocket buffers or it will +// return a reference to c.out.nb. func (c *client) collapsePtoNB() (net.Buffers, int64) { if c.isWebsocket() { return c.wsCollapsePtoNB() } - if c.out.p != nil { - p := c.out.p - c.out.p = nil - return append(c.out.nb, p), c.out.pb - } return c.out.nb, c.out.pb } -// This will handle the fixup needed on a partial write. -// Assume pending has been already calculated correctly. -func (c *client) handlePartialWrite(pnb net.Buffers) { - if c.isWebsocket() { - c.ws.frames = append(pnb, c.ws.frames...) - return - } - nb, _ := c.collapsePtoNB() - // The partial needs to be first, so append nb to pnb - c.out.nb = append(pnb, nb...) -} - // flushOutbound will flush outbound buffer to a client. // Will return true if data was attempted to be written. // Lock must be held @@ -1227,57 +1613,171 @@ func (c *client) flushOutbound() bool { return false } c.flags.set(flushOutbound) - defer c.flags.clear(flushOutbound) + defer func() { + // Check flushAndClose() for explanation on why we do this. + if c.isClosed() { + for i := range c.out.wnb { + nbPoolPut(c.out.wnb[i]) + } + c.out.wnb = nil + } + c.flags.clear(flushOutbound) + }() // Check for nothing to do. if c.nc == nil || c.srv == nil || c.out.pb == 0 { return true // true because no need to queue a signal. } - // Place primary on nb, assign primary to secondary, nil out nb and secondary. - nb, attempted := c.collapsePtoNB() - c.out.p, c.out.nb, c.out.s = c.out.s, nil, nil - if nb == nil { - return true - } - - // For selecting primary replacement. - cnb := nb - var lfs int - if len(cnb) > 0 { - lfs = len(cnb[0]) - } + // In the case of a normal socket connection, "collapsed" is just a ref + // to "nb". In the case of WebSockets, additional framing is added to + // anything that is waiting in "nb". Also keep a note of how many bytes + // were queued before we release the mutex. + collapsed, attempted := c.collapsePtoNB() + + // Frustratingly, (net.Buffers).WriteTo() modifies the receiver so we + // can't work on "nb" directly — while the mutex is unlocked during IO, + // something else might call queueOutbound and modify it. So instead we + // need a working copy — we'll operate on "wnb" instead. Note that in + // the case of a partial write, "wnb" may have remaining data from the + // previous write, and in the case of WebSockets, that data may already + // be framed, so we are careful not to re-frame "wnb" here. Instead we + // will just frame up "nb" and append it onto whatever is left on "wnb". + // "nb" will be set to nil so that we can manipulate "collapsed" outside + // of the client's lock, which is interesting in case of compression. + c.out.nb = nil // In case it goes away after releasing the lock. nc := c.nc - apm := c.out.pm // Capture this (we change the value in some tests) wdl := c.out.wdl + + // Check for compression + cw := c.out.cw + if cw != nil { + // We will have to adjust once we have compressed, so remove for now. + c.out.pb -= attempted + if c.isWebsocket() { + c.ws.fs -= attempted + } + } + // Do NOT hold lock during actual IO. c.mu.Unlock() + // Compress outside of the lock + if cw != nil { + var err error + bb := bytes.Buffer{} + + cw.Reset(&bb) + for _, buf := range collapsed { + if _, err = cw.Write(buf); err != nil { + break + } + } + if err == nil { + err = cw.Close() + } + if err != nil { + c.Errorf("Error compressing data: %v", err) + // We need to grab the lock now before marking as closed and exiting + c.mu.Lock() + c.markConnAsClosed(WriteError) + return false + } + collapsed = append(net.Buffers(nil), bb.Bytes()) + attempted = int64(len(collapsed[0])) + } + + // This is safe to do outside of the lock since "collapsed" is no longer + // referenced in c.out.nb (which can be modified in queueOutboud() while + // the lock is released). + c.out.wnb = append(c.out.wnb, collapsed...) + var _orig [nbMaxVectorSize][]byte + orig := append(_orig[:0], c.out.wnb...) + + // Since WriteTo is lopping things off the beginning, we need to remember + // the start position of the underlying array so that we can get back to it. + // Otherwise we'll always "slide forward" and that will result in reallocs. + startOfWnb := c.out.wnb[0:] + // flush here start := time.Now() - // FIXME(dlc) - writev will do multiple IOs past 1024 on - // most platforms, need to account for that with deadline? - nc.SetWriteDeadline(start.Add(wdl)) - - // Actual write to the socket. - n, err := nb.WriteTo(nc) - nc.SetWriteDeadline(time.Time{}) + var n int64 // Total bytes written + var wn int64 // Bytes written per loop + var err error // Error from last write, if any + for len(c.out.wnb) > 0 { + // Limit the number of vectors to no more than nbMaxVectorSize, + // which if 1024, will mean a maximum of 64MB in one go. + wnb := c.out.wnb + if len(wnb) > nbMaxVectorSize { + wnb = wnb[:nbMaxVectorSize] + } + consumed := len(wnb) + + // Actual write to the socket. The deadline applies to each batch + // rather than the total write, such that the configured deadline + // can be tuned to a known maximum quantity (64MB). + nc.SetWriteDeadline(time.Now().Add(wdl)) + wn, err = wnb.WriteTo(nc) + nc.SetWriteDeadline(time.Time{}) + + // Update accounting, move wnb slice onwards if needed, or stop + // if a write error was reported that wasn't a short write. + n += wn + c.out.wnb = c.out.wnb[consumed-len(wnb):] + if err != nil && err != io.ErrShortWrite { + break + } + } lft := time.Since(start) // Re-acquire client lock. c.mu.Lock() + // Adjust if we were compressing. + if cw != nil { + c.out.pb += attempted + if c.isWebsocket() { + c.ws.fs += attempted + } + } + + // At this point, "wnb" has been mutated by WriteTo and any consumed + // buffers have been lopped off the beginning, so in order to return + // them to the pool, we need to look at the difference between "orig" + // and "wnb". + for i := 0; i < len(orig)-len(c.out.wnb); i++ { + nbPoolPut(orig[i]) + } + + // At this point it's possible that "nb" has been modified by another + // call to queueOutbound while the lock was released, so we'll leave + // those for the next iteration. Meanwhile it's possible that we only + // managed a partial write of "wnb", so we'll shift anything that + // remains up to the beginning of the array to prevent reallocating. + // Anything left in "wnb" has already been framed for WebSocket conns + // so leave them alone for the next call to flushOutbound. + c.out.wnb = append(startOfWnb[:0], c.out.wnb...) + + // If we've written everything but the underlying array of our working + // buffer has grown excessively then free it — the GC will tidy it up + // and we can allocate a new one next time. + if len(c.out.wnb) == 0 && cap(c.out.wnb) > nbPoolSizeLarge*8 { + c.out.wnb = nil + } + // Ignore ErrShortWrite errors, they will be handled as partials. + var gotWriteTimeout bool if err != nil && err != io.ErrShortWrite { // Handle timeout error (slow consumer) differently if ne, ok := err.(net.Error); ok && ne.Timeout() { - if closed := c.handleWriteTimeout(n, attempted, len(cnb)); closed { + gotWriteTimeout = true + if closed := c.handleWriteTimeout(n, attempted, len(orig)); closed { return true } } else { @@ -1301,44 +1801,6 @@ func (c *client) flushOutbound() bool { if c.isWebsocket() { c.ws.fs -= n } - c.out.pm -= apm // FIXME(dlc) - this will not be totally accurate on partials. - - // Check for partial writes - // TODO(dlc) - zero write with no error will cause lost message and the writeloop to spin. - if n != attempted && n > 0 { - c.handlePartialWrite(nb) - } else if int32(n) >= c.out.sz { - c.out.sws = 0 - } - - // Adjust based on what we wrote plus any pending. - pt := n + c.out.pb - - // Adjust sz as needed downward, keeping power of 2. - // We do this at a slower rate. - if pt < int64(c.out.sz) && c.out.sz > minBufSize { - c.out.sws++ - if c.out.sws > shortsToShrink { - c.out.sz >>= 1 - } - } - // Adjust sz as needed upward, keeping power of 2. - if pt > int64(c.out.sz) && c.out.sz < maxBufSize { - c.out.sz <<= 1 - } - - // Check to see if we can reuse buffers. - if lfs != 0 && n >= int64(lfs) { - oldp := cnb[0][:0] - if cap(oldp) >= int(c.out.sz) { - // Replace primary or secondary if they are nil, reusing same buffer. - if c.out.p == nil { - c.out.p = oldp - } else if c.out.s == nil || cap(c.out.s) < int(c.out.sz) { - c.out.s = oldp - } - } - } // Check that if there is still data to send and writeLoop is in wait, // then we need to signal. @@ -1348,10 +1810,15 @@ func (c *client) flushOutbound() bool { // Check if we have a stalled gate and if so and we are recovering release // any stalled producers. Only kind==CLIENT will stall. - if c.out.stc != nil && (n == attempted || c.out.pb < c.out.mp/2) { + if c.out.stc != nil && (n == attempted || c.out.pb < c.out.mp/4*3) { close(c.out.stc) c.out.stc = nil } + // Check if the connection is recovering from being a slow consumer. + if !gotWriteTimeout && c.flags.isSet(isSlowConsumer) { + c.Noticef("Slow Consumer Recovered: Flush took %.3fs with %d chunks of %d total bytes.", time.Since(start).Seconds(), len(orig), attempted) + c.flags.clear(isSlowConsumer) + } return true } @@ -1377,16 +1844,41 @@ func (c *client) handleWriteTimeout(written, attempted int64, numChunks int) boo c.markConnAsClosed(SlowConsumerWriteDeadline) return true } + alreadySC := c.flags.isSet(isSlowConsumer) + scState := "Detected" + if alreadySC { + scState = "State" + } - // Slow consumer here.. + // Aggregate slow consumers. atomic.AddInt64(&c.srv.slowConsumers, 1) - c.Noticef("Slow Consumer Detected: WriteDeadline of %v exceeded with %d chunks of %d total bytes.", - c.out.wdl, numChunks, attempted) + switch c.kind { + case CLIENT: + c.srv.scStats.clients.Add(1) + case ROUTER: + // Only count each Slow Consumer event once. + if !alreadySC { + c.srv.scStats.routes.Add(1) + } + case GATEWAY: + c.srv.scStats.gateways.Add(1) + case LEAF: + c.srv.scStats.leafs.Add(1) + } + if c.acc != nil { + c.acc.stats.Lock() + c.acc.stats.slowConsumers++ + c.acc.stats.Unlock() + } + c.Noticef("Slow Consumer %s: WriteDeadline of %v exceeded with %d chunks of %d total bytes.", + scState, c.out.wdl, numChunks, attempted) // We always close CLIENT connections, or when nothing was written at all... - if c.kind == CLIENT || written == 0 { + if c.out.wtp == WriteTimeoutPolicyClose || written == 0 { c.markConnAsClosed(SlowConsumerWriteDeadline) return true + } else { + c.flags.setIfNotSet(isSlowConsumer) } return false } @@ -1420,13 +1912,19 @@ func (c *client) markConnAsClosed(reason ClosedState) { if !skipFlush && c.isWebsocket() && !c.ws.closeSent { c.wsEnqueueCloseMessage(reason) } - // Be consistent with the creation: for routes and gateways, + // Be consistent with the creation: for routes, gateways and leaf, // we use Noticef on create, so use that too for delete. if c.srv != nil { - if c.kind == ROUTER || c.kind == GATEWAY { - c.Noticef("%s connection closed: %s", c.typeString(), reason) - } else { // Client, System, Jetstream, Account and Leafnode connections. - c.Debugf("%s connection closed: %s", c.typeString(), reason) + if c.kind == LEAF { + if c.acc != nil { + c.Noticef("%s connection closed: %s - Account: %s", c.kindString(), reason, c.acc.traceLabel()) + } else { + c.Noticef("%s connection closed: %s", c.kindString(), reason) + } + } else if c.kind == ROUTER || c.kind == GATEWAY { + c.Noticef("%s connection closed: %s", c.kindString(), reason) + } else { // Client, System, Jetstream, and Account connections. + c.Debugf("%s connection closed: %s", c.kindString(), reason) } } @@ -1435,7 +1933,9 @@ func (c *client) markConnAsClosed(reason ClosedState) { if nc := c.nc; nc != nil && c.srv != nil { // TODO: May want to send events to single go routine instead // of creating a new go routine for each save. - go c.srv.saveClosedClient(c, nc, reason) + // Pass the c.subs as a reference. It may be set to nil in + // closeConnection. + go c.srv.saveClosedClient(c, nc, c.subs, reason) } } // If writeLoop exists, let it do the final flush, close and teardown. @@ -1456,23 +1956,39 @@ func (c *client) markConnAsClosed(reason ClosedState) { // flushSignal will use server to queue the flush IO operation to a pool of flushers. // Lock must be held. -func (c *client) flushSignal() bool { - select { - case c.out.sch <- struct{}{}: - return true - default: +func (c *client) flushSignal() { + // Check that sg is not nil, which will happen if the connection is closed. + if c.out.sg != nil { + c.out.sg.Signal() } - return false } // Traces a message. // Will NOT check if tracing is enabled, does NOT need the client lock. func (c *client) traceMsg(msg []byte) { - maxTrace := c.srv.getOpts().MaxTracedMsgLen - if maxTrace > 0 && (len(msg)-LEN_CR_LF) > maxTrace { - c.Tracef("<<- MSG_PAYLOAD: [\"%s...\"]", msg[:maxTrace]) + opts := c.srv.getOpts() + maxTrace := opts.MaxTracedMsgLen + headersOnly := opts.TraceHeaders + suffix := LEN_CR_LF + + // If TraceHeaders is enabled, extract only the header portion of the msg. + // If a header is present, it ends with an additional trailing CRLF. + if headersOnly { + msg, _ = c.msgParts(msg) + suffix += LEN_CR_LF + } + + // Do not emit a log line for zero-length payloads. + l := len(msg) - suffix + if l <= 0 { + return + } + + if maxTrace > 0 && l > maxTrace { + tm := fmt.Sprintf("%q", msg[:maxTrace]) + c.Tracef("<<- MSG_PAYLOAD: [\"%s...\"]", tm[1:len(tm)-1]) } else { - c.Tracef("<<- MSG_PAYLOAD: [%q]", msg[:len(msg)-LEN_CR_LF]) + c.Tracef("<<- MSG_PAYLOAD: [%q]", msg[:l]) } } @@ -1489,12 +2005,12 @@ func (c *client) traceOutOp(op string, arg []byte) { } func (c *client) traceOp(format, op string, arg []byte) { - opa := []interface{}{} - if op != "" { + opa := []any{} + if op != _EMPTY_ { opa = append(opa, op) } if arg != nil { - opa = append(opa, string(arg)) + opa = append(opa, bytesToString(arg)) } c.Tracef(format, opa) } @@ -1511,7 +2027,7 @@ func (c *client) processInfo(arg []byte) error { case GATEWAY: c.processGatewayInfo(&info) case LEAF: - return c.processLeafnodeInfo(&info) + c.processLeafnodeInfo(&info) } return nil } @@ -1539,20 +2055,26 @@ func (c *client) processErr(errStr string) { // Password pattern matcher. var passPat = regexp.MustCompile(`"?\s*pass\S*?"?\s*[:=]\s*"?(([^",\r\n}])*)`) +var tokenPat = regexp.MustCompile(`"?\s*auth_token\S*?"?\s*[:=]\s*"?(([^",\r\n}])*)`) -// removePassFromTrace removes any notion of passwords from trace +// removeSecretsFromTrace removes any notion of passwords/tokens from trace // messages for logging. -func removePassFromTrace(arg []byte) []byte { - if !bytes.Contains(arg, []byte(`pass`)) { - return arg +func removeSecretsFromTrace(arg []byte) []byte { + buf := redact("pass", passPat, arg) + return redact("auth_token", tokenPat, buf) +} + +func redact(name string, pat *regexp.Regexp, proto []byte) []byte { + if !bytes.Contains(proto, []byte(name)) { + return proto } // Take a copy of the connect proto just for the trace message. var _arg [4096]byte - buf := append(_arg[:0], arg...) + buf := append(_arg[:0], proto...) - m := passPat.FindAllSubmatchIndex(buf, -1) + m := pat.FindAllSubmatchIndex(buf, -1) if len(m) == 0 { - return arg + return proto } redactedPass := []byte("[REDACTED]") @@ -1563,7 +2085,7 @@ func removePassFromTrace(arg []byte) []byte { start := i[2] end := i[3] - // Replace password substring. + // Replace value substring. buf = append(buf[:start], append(redactedPass, buf[end:]...)...) break } @@ -1597,13 +2119,13 @@ func (c *client) processConnect(arg []byte) error { c.mu.Unlock() return nil } - c.last = time.Now() + c.last = time.Now().UTC() // Estimate RTT to start. if c.kind == CLIENT { c.rtt = computeRTT(c.start) if c.srv != nil { c.clearPingTimer() - c.srv.setFirstPingTimer(c) + c.setFirstPingTimer() } } kind := c.kind @@ -1631,17 +2153,17 @@ func (c *client) processConnect(arg []byte) error { if c.kind == CLIENT { var ncs string - if c.opts.Version != "" { + if c.opts.Version != _EMPTY_ { ncs = fmt.Sprintf("v%s", c.opts.Version) } - if c.opts.Lang != "" { + if c.opts.Lang != _EMPTY_ { if c.opts.Version == _EMPTY_ { ncs = c.opts.Lang } else { ncs = fmt.Sprintf("%s:%s", ncs, c.opts.Lang) } } - if c.opts.Name != "" { + if c.opts.Name != _EMPTY_ { if c.opts.Version == _EMPTY_ && c.opts.Lang == _EMPTY_ { ncs = c.opts.Name } else { @@ -1649,17 +2171,33 @@ func (c *client) processConnect(arg []byte) error { } } if ncs != _EMPTY_ { - c.ncs.Store(fmt.Sprintf("%s - %q", c.String(), ncs)) + c.ncs.CompareAndSwap(nil, fmt.Sprintf("%s - %q", c, ncs)) + } + } + + // if websocket client, maybe some options through cookies + if ws := c.ws; ws != nil { + // if JWT not in the CONNECT, use the cookie JWT (possibly empty). + if c.opts.JWT == _EMPTY_ { + c.opts.JWT = ws.cookieJwt + } + // if user not in the CONNECT, use the cookie user (possibly empty) + if c.opts.Username == _EMPTY_ { + c.opts.Username = ws.cookieUsername + } + // if pass not in the CONNECT, use the cookie password (possibly empty). + if c.opts.Password == _EMPTY_ { + c.opts.Password = ws.cookiePassword + } + // if token not in the CONNECT, use the cookie token (possibly empty). + if c.opts.Token == _EMPTY_ { + c.opts.Token = ws.cookieToken } } - // If websocket client and JWT not in the CONNECT, use the cookie JWT (possibly empty). - if ws := c.ws; ws != nil && c.opts.JWT == "" { - c.opts.JWT = ws.cookieJwt - } // when not in operator mode, discard the jwt if srv != nil && srv.trustedKeys == nil { - c.opts.JWT = "" + c.opts.JWT = _EMPTY_ } ujwt := c.opts.JWT @@ -1682,7 +2220,7 @@ func (c *client) processConnect(arg []byte) error { // Check for Auth if ok := srv.checkAuthentication(c); !ok { // We may fail here because we reached max limits on an account. - if ujwt != "" { + if ujwt != _EMPTY_ { c.mu.Lock() acc := c.acc c.mu.Unlock() @@ -1697,35 +2235,16 @@ func (c *client) processConnect(arg []byte) error { return ErrAuthentication } - // Check for Account designation, this section should be only used when there is not a jwt. - if account != "" { - var acc *Account - var wasNew bool - var err error - if !srv.NewAccountsAllowed() { - acc, err = srv.LookupAccount(account) - if err != nil { - c.Errorf(err.Error()) - c.sendErr(ErrMissingAccount.Error()) - return err - } else if accountNew && acc != nil { - c.sendErrAndErr(ErrAccountExists.Error()) - return ErrAccountExists - } - } else { - // We can create this one on the fly. - acc, wasNew = srv.LookupOrRegisterAccount(account) - if accountNew && !wasNew { - c.sendErrAndErr(ErrAccountExists.Error()) - return ErrAccountExists - } - } - // If we are here we can register ourselves with the new account. - if err := c.registerWithAccount(acc); err != nil { - c.reportErrRegisterAccount(acc, err) - return ErrBadAccount - } - } else if c.acc == nil { + // Check for Account designation, we used to have this as an optional feature for dynamic + // sandbox environments. Now its considered an error. + if accountNew || account != _EMPTY_ { + c.authViolation() + return ErrAuthentication + } + + // If no account designation. + // Do this only for CLIENT and LEAF connections. + if c.acc == nil && (c.kind == CLIENT || c.kind == LEAF) { // By default register with the global account. c.registerWithAccount(srv.globalAccount()) } @@ -1794,14 +2313,14 @@ func (c *client) authViolation() { var s *Server var hasTrustedNkeys, hasNkeys, hasUsers bool if s = c.srv; s != nil { - s.mu.Lock() - hasTrustedNkeys = len(s.trustedKeys) > 0 + s.mu.RLock() + hasTrustedNkeys = s.trustedKeys != nil hasNkeys = s.nkeys != nil hasUsers = s.users != nil - s.mu.Unlock() + s.mu.RUnlock() defer s.sendAuthErrorEvent(c) - } + if hasTrustedNkeys { c.Errorf("%v", ErrAuthentication) } else if hasNkeys { @@ -1813,9 +2332,15 @@ func (c *client) authViolation() { ErrAuthentication.Error(), c.opts.Username) } else { - c.Errorf(ErrAuthentication.Error()) + if c.srv != nil { + c.Errorf(ErrAuthentication.Error()) + } + } + if c.isMqtt() { + c.mqttEnqueueConnAck(mqttConnAckRCNotAuthorized, false) + } else { + c.sendErr("Authorization Violation") } - c.sendErr("Authorization Violation") c.closeConnection(AuthenticationViolation) } @@ -1830,7 +2355,10 @@ func (c *client) maxConnExceeded() { } func (c *client) maxSubsExceeded() { - c.sendErrAndErr(ErrTooManySubs.Error()) + if c.acc.shouldLogMaxSubErr() { + c.Errorf(ErrTooManySubs.Error()) + } + c.sendErr(ErrTooManySubs.Error()) } func (c *client) maxPayloadViolation(sz int, max int32) { @@ -1840,96 +2368,72 @@ func (c *client) maxPayloadViolation(sz int, max int32) { } // queueOutbound queues data for a clientconnection. -// Returns if the data is referenced or not. If referenced, the caller -// should not reuse the `data` array. // Lock should be held. -func (c *client) queueOutbound(data []byte) bool { +func (c *client) queueOutbound(data []byte) { // Do not keep going if closed if c.isClosed() { - return false + return } - // Assume data will not be referenced - referenced := false // Add to pending bytes total. c.out.pb += int64(len(data)) + // Take a copy of the slice ref so that we can chop bits off the beginning + // without affecting the original "data" slice. + toBuffer := data + + // All of the queued []byte have a fixed capacity, so if there's a []byte + // at the tail of the buffer list that isn't full yet, we should top that + // up first. This helps to ensure we aren't pulling more []bytes from the + // pool than we need to. + if len(c.out.nb) > 0 { + last := &c.out.nb[len(c.out.nb)-1] + if free := cap(*last) - len(*last); free > 0 { + if l := len(toBuffer); l < free { + free = l + } + *last = append(*last, toBuffer[:free]...) + toBuffer = toBuffer[free:] + } + } + + // Now we can push the rest of the data into new []bytes from the pool + // in fixed size chunks. This ensures we don't go over the capacity of any + // of the buffers and end up reallocating. + for len(toBuffer) > 0 { + new := nbPoolGet(len(toBuffer)) + n := copy(new[:cap(new)], toBuffer) + c.out.nb = append(c.out.nb, new[:n]) + toBuffer = toBuffer[n:] + } + // Check for slow consumer via pending bytes limit. // ok to return here, client is going away. if c.kind == CLIENT && c.out.pb > c.out.mp { // Perf wise, it looks like it is faster to optimistically add than // checking current pb+len(data) and then add to pb. c.out.pb -= int64(len(data)) + + // Increment the total and client's slow consumer counters. atomic.AddInt64(&c.srv.slowConsumers, 1) + c.srv.scStats.clients.Add(1) + if c.acc != nil { + c.acc.stats.Lock() + c.acc.stats.slowConsumers++ + c.acc.stats.Unlock() + } c.Noticef("Slow Consumer Detected: MaxPending of %d Exceeded", c.out.mp) c.markConnAsClosed(SlowConsumerPendingBytes) - return referenced - } - - if c.out.p == nil && len(data) < maxBufSize { - if c.out.sz == 0 { - c.out.sz = startBufSize - } - if c.out.s != nil && cap(c.out.s) >= int(c.out.sz) { - c.out.p = c.out.s - c.out.s = nil - } else { - // FIXME(dlc) - make power of 2 if less than maxBufSize? - c.out.p = make([]byte, 0, c.out.sz) - } - } - // Determine if we copy or reference - available := cap(c.out.p) - len(c.out.p) - if len(data) > available { - // We can't fit everything into existing primary, but message will - // fit in next one we allocate or utilize from the secondary. - // So copy what we can. - if available > 0 && len(data) < int(c.out.sz) { - c.out.p = append(c.out.p, data[:available]...) - data = data[available:] - } - // Put the primary on the nb if it has a payload - if len(c.out.p) > 0 { - c.out.nb = append(c.out.nb, c.out.p) - c.out.p = nil - } - // Check for a big message, and if found place directly on nb - // FIXME(dlc) - do we need signaling of ownership here if we want len(data) < maxBufSize - if len(data) > maxBufSize { - c.out.nb = append(c.out.nb, data) - referenced = true - } else { - // We will copy to primary. - if c.out.p == nil { - // Grow here - if (c.out.sz << 1) <= maxBufSize { - c.out.sz <<= 1 - } - if len(data) > int(c.out.sz) { - c.out.p = make([]byte, 0, len(data)) - } else { - if c.out.s != nil && cap(c.out.s) >= int(c.out.sz) { // TODO(dlc) - Size mismatch? - c.out.p = c.out.s - c.out.s = nil - } else { - c.out.p = make([]byte, 0, c.out.sz) - } - } - } - c.out.p = append(c.out.p, data...) - } - } else { - c.out.p = append(c.out.p, data...) + return } // Check here if we should create a stall channel if we are falling behind. // We do this here since if we wait for consumer's writeLoop it could be // too late with large number of fan in producers. - if c.out.pb > c.out.mp/2 && c.out.stc == nil { + // If the outbound connection is > 75% of maximum pending allowed, create a stall gate. + if c.out.pb > c.out.mp/4*3 && c.out.stc == nil { c.out.stc = make(chan struct{}) } - - return referenced } // Assume the lock is held upon entry. @@ -1995,7 +2499,7 @@ func (c *client) sendRTTPingLocked() bool { // Assume the lock is held upon entry. func (c *client) sendPing() { - c.rttStart = time.Now() + c.rttStart = time.Now().UTC() c.ping.out++ if c.trace { c.traceOutOp("PING", nil) @@ -2012,12 +2516,15 @@ func (c *client) generateClientInfoJSON(info Info) []byte { info.MaxPayload = c.mpay if c.isWebsocket() { info.ClientConnectURLs = info.WSConnectURLs + // Otherwise lame duck info can panic + if c.srv != nil { + ws := &c.srv.websocket + info.TLSAvailable, info.TLSRequired = ws.tls, ws.tls + info.Host, info.Port = ws.host, ws.port + } } info.WSConnectURLs = nil - // Generate the info json - b, _ := json.Marshal(info) - pcs := [][]byte{[]byte("INFO"), b, []byte(CR_LF)} - return bytes.Join(pcs, []byte(" ")) + return generateInfoJSON(&info) } func (c *client) sendErr(err string) { @@ -2052,7 +2559,7 @@ func (c *client) processPing() { // Record this to suppress us sending one if this // is within a given time interval for activity. - c.ping.last = time.Now() + c.lastIn = time.Now() // If not a CLIENT, we are done. Also the CONNECT should // have been received, but make sure it is so before proceeding @@ -2105,14 +2612,66 @@ func (c *client) processPong() { c.rtt = computeRTT(c.rttStart) srv := c.srv reorderGWs := c.kind == GATEWAY && c.gw.outbound + firstPong := c.flags.setIfNotSet(firstPong) + var ri *routeInfo + // When receiving the first PONG, for a route with pooling, we may be + // instructed to start a new route. + if firstPong && c.kind == ROUTER && c.route != nil { + ri = c.route.startNewRoute + c.route.startNewRoute = nil + } + // If compression is currently active for a route/leaf connection, if the + // compression configuration is s2_auto, check if we should change + // the compression level. + if c.kind == ROUTER && needsCompression(c.route.compression) { + c.updateS2AutoCompressionLevel(&srv.getOpts().Cluster.Compression, &c.route.compression) + } else if c.kind == LEAF && needsCompression(c.leaf.compression) { + var co *CompressionOpts + if r := c.leaf.remote; r != nil { + co = &r.Compression + } else { + co = &srv.getOpts().LeafNode.Compression + } + c.updateS2AutoCompressionLevel(co, &c.leaf.compression) + } c.mu.Unlock() if reorderGWs { srv.gateway.orderOutboundConnections() } + if ri != nil { + srv.startGoRoutine(func() { + srv.connectToRoute(ri.url, ri.rtype, true, ri.gossipMode, _EMPTY_) + }) + } +} + +// Select the s2 compression level based on the client's current RTT and the configured +// RTT thresholds slice. If current level is different than selected one, save the +// new compression level string and create a new s2 writer. +// Lock held on entry. +func (c *client) updateS2AutoCompressionLevel(co *CompressionOpts, compression *string) { + if co.Mode != CompressionS2Auto { + return + } + if cm := selectS2AutoModeBasedOnRTT(c.rtt, co.RTTThresholds); cm != *compression { + *compression = cm + c.out.cw = s2.NewWriter(nil, s2WriterOptions(cm)...) + } +} + +// Will return the parts from the raw wire msg. +// We return the `hdr` as a slice that is capped to the length of the headers +// so that if the caller later tries to append to the returned header slice it +// does not affect the message content. +func (c *client) msgParts(data []byte) (hdr []byte, msg []byte) { + if c != nil && c.pa.hdr > 0 { + return data[:c.pa.hdr:c.pa.hdr], data[c.pa.hdr:] + } + return nil, data } // Header pubs take form HPUB [reply] \r\n -func (c *client) processHeaderPub(arg []byte) error { +func (c *client) processHeaderPub(arg, remaining []byte) error { if !c.headers { return ErrMsgHeadersNotSupported } @@ -2155,25 +2714,35 @@ func (c *client) processHeaderPub(arg []byte) error { c.pa.hdb = args[2] c.pa.szb = args[3] default: - return fmt.Errorf("processHeaderPub Parse Error: '%s'", arg) + return fmt.Errorf("processHeaderPub Parse Error: %q", arg) } if c.pa.hdr < 0 { - return fmt.Errorf("processHeaderPub Bad or Missing Header Size: '%s'", arg) + return fmt.Errorf("processHeaderPub Bad or Missing Header Size: %q", arg) } // If number overruns an int64, parseSize() will have returned a negative value if c.pa.size < 0 { - return fmt.Errorf("processHeaderPub Bad or Missing Total Size: '%s'", arg) + return fmt.Errorf("processHeaderPub Bad or Missing Total Size: %q", arg) } if c.pa.hdr > c.pa.size { - return fmt.Errorf("processHeaderPub Header Size larger then TotalSize: '%s'", arg) + return fmt.Errorf("processHeaderPub Header Size larger then TotalSize: %q", arg) } maxPayload := atomic.LoadInt32(&c.mpay) // Use int64() to avoid int32 overrun... if maxPayload != jwt.NoLimit && int64(c.pa.size) > int64(maxPayload) { + // If we are given the remaining read buffer (since we do blind reads + // we may have the beginning of the message header/payload), we will + // look for the tracing header and if found, we will generate a + // trace event with the max payload ingress error. + // Do this only for CLIENT connections. + if c.kind == CLIENT && len(remaining) > 0 { + if td := getHeader(MsgTraceDest, remaining); len(td) > 0 { + c.initAndSendIngressErrEvent(remaining, string(td), ErrMaxPayload) + } + } c.maxPayloadViolation(c.pa.size, maxPayload) return ErrMaxPayload } - if c.opts.Pedantic && !IsValidLiteralSubject(string(c.pa.subject)) { + if c.opts.Pedantic && !IsValidLiteralSubject(bytesToString(c.pa.subject)) { c.sendErr("Invalid Publish Subject") } return nil @@ -2214,11 +2783,11 @@ func (c *client) processPub(arg []byte) error { c.pa.size = parseSize(args[2]) c.pa.szb = args[2] default: - return fmt.Errorf("processPub Parse Error: '%s'", arg) + return fmt.Errorf("processPub Parse Error: %q", arg) } // If number overruns an int64, parseSize() will have returned a negative value if c.pa.size < 0 { - return fmt.Errorf("processPub Bad or Missing Size: '%s'", arg) + return fmt.Errorf("processPub Bad or Missing Size: %q", arg) } maxPayload := atomic.LoadInt32(&c.mpay) // Use int64() to avoid int32 overrun... @@ -2226,7 +2795,7 @@ func (c *client) processPub(arg []byte) error { c.maxPayloadViolation(c.pa.size, maxPayload) return ErrMaxPayload } - if c.opts.Pedantic && !IsValidLiteralSubject(string(c.pa.subject)) { + if c.opts.Pedantic && !IsValidLiteralSubject(bytesToString(c.pa.subject)) { c.sendErr("Invalid Publish Subject") } return nil @@ -2276,7 +2845,7 @@ func (c *client) parseSub(argo []byte, noForward bool) error { queue = args[1] sid = args[2] default: - return fmt.Errorf("processSub Parse Error: '%s'", arg) + return fmt.Errorf("processSub Parse Error: %q", arg) } // If there was an error, it has been sent to the client. We don't return an // error here to not close the connection as a parsing error. @@ -2285,8 +2854,12 @@ func (c *client) parseSub(argo []byte, noForward bool) error { } func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForward bool) (*subscription, error) { + return c.processSubEx(subject, queue, bsid, cb, noForward, false, false) +} + +func (c *client) processSubEx(subject, queue, bsid []byte, cb msgHandler, noForward, si, rsi bool) (*subscription, error) { // Create the subscription - sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb} + sub := &subscription{client: c, subject: subject, queue: queue, sid: bsid, icb: cb, si: si, rsi: rsi} c.mu.Lock() @@ -2298,10 +2871,11 @@ func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForwar acc := c.acc srv := c.srv - sid := string(sub.sid) + sid := bytesToString(sub.sid) // This check does not apply to SYSTEM or JETSTREAM or ACCOUNT clients (because they don't have a `nc`...) - if c.isClosed() && (kind != SYSTEM && kind != JETSTREAM && kind != ACCOUNT) { + // When a connection is closed though, we set c.subs to nil. So check for the map to not be nil. + if (c.isClosed() && !isInternalClient(kind)) || (c.subs == nil) { c.mu.Unlock() return nil, ErrConnectionClosed } @@ -2316,7 +2890,7 @@ func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForwar // allow = ["foo", "foo v1"] -> can subscribe to 'foo' but can only queue subscribe to 'foo v1' // if sub.queue != nil { - if !c.canQueueSubscribe(string(sub.subject), string(sub.queue)) { + if !c.canSubscribe(string(sub.subject), string(sub.queue)) || string(sub.queue) == sysGroup { c.mu.Unlock() c.subPermissionViolation(sub) return nil, ErrSubscribePermissionViolation @@ -2326,6 +2900,14 @@ func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForwar c.subPermissionViolation(sub) return nil, ErrSubscribePermissionViolation } + + if opts := srv.getOpts(); opts != nil && opts.MaxSubTokens > 0 { + if len(bytes.Split(sub.subject, []byte(tsep))) > int(opts.MaxSubTokens) { + c.mu.Unlock() + c.maxTokensViolation(sub) + return nil, ErrTooManySubTokens + } + } } // Check if we have a maximum on the number of subscriptions. @@ -2387,66 +2969,109 @@ func (c *client) processSub(subject, queue, bsid []byte, cb msgHandler, noForwar } } // Now check on leafnode updates. - srv.updateLeafNodes(acc, sub, 1) + acc.updateLeafNodes(sub, 1) return sub, nil } // Used to pass stream import matches to addShadowSub type ime struct { - im *streamImport - dyn bool + im *streamImport + overlapSubj string + dyn bool } -// If the client's account has stream imports and there are matches for -// this subscription's subject, then add shadow subscriptions in the -// other accounts that export this subject. +// If the client's account has stream imports and there are matches for this +// subscription's subject, then add shadow subscriptions in the other accounts +// that export this subject. func (c *client) addShadowSubscriptions(acc *Account, sub *subscription) error { if acc == nil { return ErrMissingAccount } var ( - _ims [16]ime - ims = _ims[:0] - tokens []string - tsa [32]string - hasWC bool + _ims [16]ime + ims = _ims[:0] + imTsa [32]string + tokens []string + tsa [32]string + hasWC bool + tokensModified bool ) acc.mu.RLock() - // Loop over the import subjects. We have 3 scenarios. If we have an + // If this is from a service import, ignore. + if sub.si { + acc.mu.RUnlock() + return nil + } + subj := bytesToString(sub.subject) + if len(acc.imports.streams) > 0 { + tokens = tokenizeSubjectIntoSlice(tsa[:0], subj) + for _, tk := range tokens { + if tk == pwcs { + hasWC = true + break + } + } + if !hasWC && tokens[len(tokens)-1] == fwcs { + hasWC = true + } + } + // Loop over the import subjects. We have 4 scenarios. If we have an // exact match or a superset match we should use the from field from - // the import. If we are a subset, we have to dynamically calculate - // the subject. + // the import. If we are a subset or overlap, we have to dynamically calculate + // the subject. On overlap, ime requires the overlap subject. for _, im := range acc.imports.streams { if im.invalid { continue } - subj := string(sub.subject) if subj == im.to { - ims = append(ims, ime{im, false}) + ims = append(ims, ime{im, _EMPTY_, false}) continue } - if tokens == nil { - tokens = tsa[:0] - start := 0 - for i := 0; i < len(subj); i++ { - // This is not perfect, but the test below will - // be more exact, this is just to trigger the - // additional test. - if subj[i] == pwc || subj[i] == fwc { - hasWC = true - } else if subj[i] == btsep { - tokens = append(tokens, subj[start:i]) - start = i + 1 + if tokensModified { + // re-tokenize subj to overwrite modifications from a previous iteration + tokens = tokenizeSubjectIntoSlice(tsa[:0], subj) + tokensModified = false + } + imTokens := tokenizeSubjectIntoSlice(imTsa[:0], im.to) + + if isSubsetMatchTokenized(tokens, imTokens) { + ims = append(ims, ime{im, _EMPTY_, true}) + } else if hasWC { + if isSubsetMatchTokenized(imTokens, tokens) { + ims = append(ims, ime{im, _EMPTY_, false}) + } else { + imTokensLen := len(imTokens) + for i, t := range tokens { + if i >= imTokensLen { + break + } + if t == pwcs && imTokens[i] != fwcs { + tokens[i] = imTokens[i] + tokensModified = true + } + } + tokensLen := len(tokens) + lastIdx := tokensLen - 1 + if tokens[lastIdx] == fwcs { + if imTokensLen >= tokensLen { + // rewrite ">" in tokens to be more specific + tokens[lastIdx] = imTokens[lastIdx] + tokensModified = true + if imTokensLen > tokensLen { + // copy even more specific parts from import + tokens = append(tokens, imTokens[tokensLen:]...) + } + } + } + if isSubsetMatchTokenized(tokens, imTokens) { + // As isSubsetMatchTokenized was already called with tokens and imTokens, + // we wouldn't be here if it where not for tokens being modified. + // Hence, Join to re compute the subject string + ims = append(ims, ime{im, strings.Join(tokens, tsep), true}) } } - tokens = append(tokens, subj[start:]) - } - if isSubsetMatch(tokens, im.to) { - ims = append(ims, ime{im, true}) - } else if hasWC && subjectIsSubsetMatch(im.to, subj) { - ims = append(ims, ime{im, false}) } } acc.mu.RUnlock() @@ -2479,62 +3104,102 @@ func (c *client) addShadowSubscriptions(acc *Account, sub *subscription) error { // Add in the shadow subscription. func (c *client) addShadowSub(sub *subscription, ime *ime) (*subscription, error) { - im := ime.im + c.mu.Lock() nsub := *sub // copy + c.mu.Unlock() + + im := ime.im nsub.im = im - // Check if we need to change shadow subscription's subject. - if !im.usePub { - if ime.dyn { - if im.rtr == nil { - im.rtr = im.tr.reverse() - } - subj, err := im.rtr.transformSubject(string(nsub.subject)) - if err != nil { - return nil, err - } - nsub.subject = []byte(subj) + if !im.usePub && ime.dyn && im.tr != nil { + if im.rtr == nil { + im.rtr = im.tr.reverse() + } + s := bytesToString(nsub.subject) + if ime.overlapSubj != _EMPTY_ { + s = ime.overlapSubj + } + subj := im.rtr.TransformSubject(s) + + nsub.subject = []byte(subj) + } else if !im.usePub || (im.usePub && ime.overlapSubj != _EMPTY_) || !ime.dyn { + if ime.overlapSubj != _EMPTY_ { + nsub.subject = []byte(ime.overlapSubj) } else { nsub.subject = []byte(im.from) } } + // Else use original subject + c.Debugf("Creating import subscription on %q from account %q", nsub.subject, im.acc.Name) if err := im.acc.sl.Insert(&nsub); err != nil { errs := fmt.Sprintf("Could not add shadow import subscription for account %q", im.acc.Name) c.Debugf(errs) - return nil, fmt.Errorf(errs) + return nil, errors.New(errs) } - // Update our route map here. - c.srv.updateRouteSubscriptionMap(im.acc, &nsub, 1) - if c.srv.gateway.enabled { - c.srv.gatewayUpdateSubInterest(im.acc.Name, &nsub, 1) + // Update our route map here. But only if we are not a leaf node or a hub leafnode. + if c.kind != LEAF || c.isHubLeafNode() { + c.srv.updateRemoteSubscription(im.acc, &nsub, 1) + } else if c.kind == LEAF { + // Update all leafnodes that connect to this server. Note that we could have + // used the updateLeafNodes() function since when it does invoke updateSmap() + // this function already takes care of not sending to a spoke leafnode since + // the `nsub` here is already from a spoke leafnode, but to be explicit, we + // use this version that updates only leafnodes that connect to this server. + im.acc.updateLeafNodesEx(&nsub, 1, true) } - c.srv.updateLeafNodes(im.acc, &nsub, 1) return &nsub, nil } // canSubscribe determines if the client is authorized to subscribe to the // given subject. Assumes caller is holding lock. -func (c *client) canSubscribe(subject string) bool { +func (c *client) canSubscribe(subject string, optQueue ...string) bool { if c.perms == nil { return true } - allowed := true + allowed, checkAllow := true, true + + // Optional queue group. + var queue string + if len(optQueue) > 0 { + queue = optQueue[0] + } + // For CLIENT connections that are MQTT, or other types of connections, we will + // implicitly allow anything that starts with the "$MQTT." prefix. However, + // we don't just return here, we skip the check for "allow" but will check "deny". + if (c.isMqtt() || (c.kind != CLIENT)) && strings.HasPrefix(subject, mqttPrefix) { + checkAllow = false + } // Check allow list. If no allow list that means all are allowed. Deny can overrule. - if c.perms.sub.allow != nil { + if checkAllow && c.perms.sub.allow != nil { r := c.perms.sub.allow.Match(subject) - allowed = len(r.psubs) != 0 + allowed = len(r.psubs) > 0 + if queue != _EMPTY_ && len(r.qsubs) > 0 { + // If the queue appears in the allow list, then DO allow. + allowed = queueMatches(queue, r.qsubs) + } + // Leafnodes operate slightly differently in that they allow broader scoped subjects. + // They will prune based on publish perms before sending to a leafnode client. + if !allowed && c.kind == LEAF && subjectHasWildcard(subject) { + r := c.perms.sub.allow.ReverseMatch(subject) + allowed = len(r.psubs) != 0 + } } // If we have a deny list and we think we are allowed, check that as well. if allowed && c.perms.sub.deny != nil { r := c.perms.sub.deny.Match(subject) allowed = len(r.psubs) == 0 + if queue != _EMPTY_ && len(r.qsubs) > 0 { + // If the queue appears in the deny list, then DO NOT allow. + allowed = !queueMatches(queue, r.qsubs) + } + // We use the actual subscription to signal us to spin up the deny mperms // and cache. We check if the subject is a wildcard that contains any of // the deny clauses. @@ -2542,8 +3207,7 @@ func (c *client) canSubscribe(subject string) bool { if allowed && c.mperms == nil && subjectHasWildcard(subject) { // Whip through the deny array and check if this wildcard subject is within scope. for _, sub := range c.darray { - tokens := strings.Split(sub, tsep) - if isSubsetMatch(tokens, sub) { + if subjectIsSubsetMatch(sub, subject) { c.loadMsgDenyFilter() break } @@ -2559,7 +3223,7 @@ func queueMatches(queue string, qsubs [][]*subscription) bool { } for _, qsub := range qsubs { qs := qsub[0] - qname := string(qs.queue) + qname := bytesToString(qs.queue) // NOTE: '*' and '>' tokens can also be valid // queue names so we first check against the @@ -2571,49 +3235,15 @@ func queueMatches(queue string, qsubs [][]*subscription) bool { return false } -func (c *client) canQueueSubscribe(subject, queue string) bool { - if c.perms == nil { - return true - } - - allowed := true - - if c.perms.sub.allow != nil { - r := c.perms.sub.allow.Match(subject) - - // If perms DO NOT have queue name, then psubs will be greater than - // zero. If perms DO have queue name, then qsubs will be greater than - // zero. - allowed = len(r.psubs) > 0 - if len(r.qsubs) > 0 { - // If the queue appears in the allow list, then DO allow. - allowed = queueMatches(queue, r.qsubs) - } - } - - if allowed && c.perms.sub.deny != nil { - r := c.perms.sub.deny.Match(subject) - - // If perms DO NOT have queue name, then psubs will be greater than - // zero. If perms DO have queue name, then qsubs will be greater than - // zero. - allowed = len(r.psubs) == 0 - if len(r.qsubs) > 0 { - // If the queue appears in the deny list, then DO NOT allow. - allowed = !queueMatches(queue, r.qsubs) - } - } - - return allowed -} - // Low level unsubscribe for a given client. func (c *client) unsubscribe(acc *Account, sub *subscription, force, remove bool) { + if s := c.srv; s != nil && s.isShuttingDown() { + return + } + c.mu.Lock() if !force && sub.max > 0 && sub.nm < sub.max { - c.Debugf( - "Deferring actual UNSUB(%s): %d max, %d received", - string(sub.subject), sub.max, sub.nm) + c.Debugf("Deferring actual UNSUB(%s): %d max, %d received", sub.subject, sub.max, sub.nm) c.mu.Unlock() return } @@ -2622,14 +3252,10 @@ func (c *client) unsubscribe(acc *Account, sub *subscription, force, remove bool c.traceOp("<-> %s", "DELSUB", sub.sid) } - if c.kind != CLIENT && c.kind != SYSTEM { - c.removeReplySubTimeout(sub) - } - // Remove accounting if requested. This will be false when we close a connection // with open subscriptions. if remove { - delete(c.subs, string(sub.sid)) + delete(c.subs, bytesToString(sub.sid)) if acc != nil { acc.sl.Remove(sub) } @@ -2637,14 +3263,12 @@ func (c *client) unsubscribe(acc *Account, sub *subscription, force, remove bool // Check to see if we have shadow subscriptions. var updateRoute bool - var updateGWs bool + var isSpokeLeaf bool shadowSubs := sub.shadow sub.shadow = nil if len(shadowSubs) > 0 { - updateRoute = (c.kind == CLIENT || c.kind == SYSTEM || c.kind == LEAF) && c.srv != nil - if updateRoute { - updateGWs = c.srv.gateway.enabled - } + isSpokeLeaf = c.isSpokeLeafNode() + updateRoute = !isSpokeLeaf && (c.kind == CLIENT || c.kind == SYSTEM || c.kind == LEAF || c.kind == JETSTREAM) && c.srv != nil } sub.close() c.mu.Unlock() @@ -2653,20 +3277,17 @@ func (c *client) unsubscribe(acc *Account, sub *subscription, force, remove bool for _, nsub := range shadowSubs { if err := nsub.im.acc.sl.Remove(nsub); err != nil { c.Debugf("Could not remove shadow import subscription for account %q", nsub.im.acc.Name) - } else { - if updateRoute { - c.srv.updateRouteSubscriptionMap(nsub.im.acc, nsub, -1) - } - if updateGWs { - c.srv.gatewayUpdateSubInterest(nsub.im.acc.Name, nsub, -1) - } } - // Now check on leafnode updates. - c.srv.updateLeafNodes(nsub.im.acc, nsub, -1) + if updateRoute { + c.srv.updateRemoteSubscription(nsub.im.acc, nsub, -1) + } else if isSpokeLeaf { + nsub.im.acc.updateLeafNodesEx(nsub, -1, true) + } } // Now check to see if this was part of a respMap entry for service imports. - if acc != nil { + // We can skip subscriptions on reserved replies. + if acc != nil && !isReservedReply(sub.subject) { acc.checkForReverseEntry(string(sub.subject), nil, true) } } @@ -2674,16 +3295,16 @@ func (c *client) unsubscribe(acc *Account, sub *subscription, force, remove bool func (c *client) processUnsub(arg []byte) error { args := splitArg(arg) var sid []byte - max := -1 + max := int64(-1) switch len(args) { case 1: sid = args[0] case 2: sid = args[0] - max = parseSize(args[1]) + max = int64(parseSize(args[1])) default: - return fmt.Errorf("processUnsub Parse Error: '%s'", arg) + return fmt.Errorf("processUnsub Parse Error: %q", arg) } var sub *subscription @@ -2702,8 +3323,8 @@ func (c *client) processUnsub(arg []byte) error { updateGWs := false if sub, ok = c.subs[string(sid)]; ok { acc = c.acc - if max > 0 { - sub.max = int64(max) + if max > 0 && max > sub.nm { + sub.max = max } else { // Clear it here to override sub.max = 0 @@ -2719,14 +3340,14 @@ func (c *client) processUnsub(arg []byte) error { if unsub { c.unsubscribe(acc, sub, false, true) - if acc != nil && kind == CLIENT || kind == SYSTEM || kind == ACCOUNT { + if acc != nil && (kind == CLIENT || kind == SYSTEM || kind == ACCOUNT || kind == JETSTREAM) { srv.updateRouteSubscriptionMap(acc, sub, -1) if updateGWs { srv.gatewayUpdateSubInterest(acc.Name, sub, -1) } } // Now check on leafnode updates. - srv.updateLeafNodes(acc, sub, -1) + acc.updateLeafNodes(sub, -1) } return nil @@ -2739,7 +3360,7 @@ func (c *client) processUnsub(arg []byte) error { func (c *client) checkDenySub(subject string) bool { if denied, ok := c.mperms.dcache[subject]; ok { return denied - } else if r := c.mperms.deny.Match(subject); len(r.psubs) != 0 { + } else if np, _ := c.mperms.deny.NumInterest(subject); np != 0 { c.mperms.dcache[subject] = true return true } else { @@ -2754,36 +3375,43 @@ func (c *client) checkDenySub(subject string) bool { // Create a message header for routes or leafnodes. Header and origin cluster aware. func (c *client) msgHeaderForRouteOrLeaf(subj, reply []byte, rt *routeTarget, acc *Account) []byte { hasHeader := c.pa.hdr > 0 - canReceiveHeader := rt.sub.client.headers + subclient := rt.sub.client + canReceiveHeader := subclient.headers mh := c.msgb[:msgHeadProtoLen] - kind := rt.sub.client.kind + kind := subclient.kind var lnoc bool if kind == ROUTER { // If we are coming from a leaf with an origin cluster we need to handle differently // if we can. We will send a route based LMSG which has origin cluster and headers // by default. - if c.kind == LEAF && c.remoteCluster() != _EMPTY_ && rt.sub.client.route.lnoc { + if c.kind == LEAF && c.remoteCluster() != _EMPTY_ { + subclient.mu.Lock() + lnoc = subclient.route.lnoc + subclient.mu.Unlock() + } + if lnoc { mh[0] = 'L' mh = append(mh, c.remoteCluster()...) mh = append(mh, ' ') - lnoc = true } else { // Router (and Gateway) nodes are RMSG. Set here since leafnodes may rewrite. mh[0] = 'R' } - mh = append(mh, acc.Name...) - mh = append(mh, ' ') + if len(subclient.route.accName) == 0 { + mh = append(mh, acc.Name...) + mh = append(mh, ' ') + } } else { // Leaf nodes are LMSG mh[0] = 'L' // Remap subject if its a shadow subscription, treat like a normal client. if rt.sub.im != nil { if rt.sub.im.tr != nil { - to, _ := rt.sub.im.tr.transformSubject(string(subj)) + to := rt.sub.im.tr.TransformSubject(bytesToString(subj)) subj = []byte(to) - } else { + } else if !rt.sub.im.usePub { subj = []byte(rt.sub.im.to) } } @@ -2792,7 +3420,7 @@ func (c *client) msgHeaderForRouteOrLeaf(subj, reply []byte, rt *routeTarget, ac mh = append(mh, ' ') if len(rt.qs) > 0 { - if reply != nil { + if len(reply) > 0 { mh = append(mh, "+ "...) // Signal that there is a reply. mh = append(mh, reply...) mh = append(mh, ' ') @@ -2800,7 +3428,7 @@ func (c *client) msgHeaderForRouteOrLeaf(subj, reply []byte, rt *routeTarget, ac mh = append(mh, "| "...) // Only queues } mh = append(mh, rt.qs...) - } else if reply != nil { + } else if len(reply) > 0 { mh = append(mh, reply...) mh = append(mh, ' ') } @@ -2874,28 +3502,37 @@ func (c *client) msgHeader(subj, reply []byte, sub *subscription) []byte { } func (c *client) stalledWait(producer *client) { + // Check to see if we have exceeded our total wait time per readLoop invocation. + if producer.in.tst > stallTotalAllowed { + return + } + + // Grab stall channel which the slow consumer will close when caught up. stall := c.out.stc - ttl := stallDuration(c.out.pb, c.out.mp) + + // Calculate stall time. + ttl := stallClientMinDuration + if c.out.pb >= c.out.mp { + ttl = stallClientMaxDuration + } + c.mu.Unlock() defer c.mu.Lock() + // Now check if we are close to total allowed. + if producer.in.tst+ttl > stallTotalAllowed { + ttl = stallTotalAllowed - producer.in.tst + } + delay := time.NewTimer(ttl) + defer delay.Stop() + + start := time.Now() select { case <-stall: - case <-time.After(ttl): + case <-delay.C: producer.Debugf("Timed out of fast producer stall (%v)", ttl) } -} - -func stallDuration(pb, mp int64) time.Duration { - ttl := stallClientMinDuration - if pb >= mp { - ttl = stallClientMaxDuration - } else if hmp := mp / 2; pb > hmp { - bsz := hmp / 10 - additional := int64(ttl) * ((pb - hmp) / bsz) - ttl += time.Duration(additional) - } - return ttl + producer.in.tst += time.Since(start) } // Used to treat maps as efficient set @@ -2903,45 +3540,100 @@ var needFlush = struct{}{} // deliverMsg will deliver a message to a matching subscription and its underlying client. // We process all connection/client types. mh is the part that will be protocol/client specific. -func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, gwrply bool) bool { - if sub.client == nil { - return false - } - client := sub.client - client.mu.Lock() +func (c *client) deliverMsg(prodIsMQTT bool, sub *subscription, acc *Account, subject, reply, mh, msg []byte, gwrply bool) bool { + // Check if message tracing is enabled. + mt, traceOnly := c.isMsgTraceEnabled() - // Check echo - if c == client && !client.echo { - client.mu.Unlock() + client := sub.client + // Check sub client and check echo. Only do this if not a service import. + if client == nil || (c == client && !client.echo && !sub.si) { + if client != nil && mt != nil { + client.mu.Lock() + mt.addEgressEvent(client, sub, errMsgTraceNoEcho) + client.mu.Unlock() + } return false } + client.mu.Lock() + // Check if we have a subscribe deny clause. This will trigger us to check the subject // for a match against the denied subjects. if client.mperms != nil && client.checkDenySub(string(subject)) { + mt.addEgressEvent(client, sub, errMsgTraceSubDeny) client.mu.Unlock() return false } - // This is set under the client lock using atomic because it can be - // checked with atomic without the client lock. Here, we don't need - // the atomic operation since we are under the lock. - if sub.closed == 1 { + // New race detector forces this now. + if sub.isClosed() { + mt.addEgressEvent(client, sub, errMsgTraceSubClosed) client.mu.Unlock() return false } // Check if we are a leafnode and have perms to check. if client.kind == LEAF && client.perms != nil { - if !client.pubAllowed(string(subject)) { + var subjectToCheck []byte + if subject[0] == '_' && bytes.HasPrefix(subject, []byte(gwReplyPrefix)) { + subjectToCheck = subject[gwSubjectOffset:] + } else if subject[0] == '$' && bytes.HasPrefix(subject, []byte(oldGWReplyPrefix)) { + subjectToCheck = subject[oldGWReplyStart:] + } else { + subjectToCheck = subject + } + if !client.pubAllowedFullCheck(string(subjectToCheck), true, true) { + mt.addEgressEvent(client, sub, errMsgTracePubViolation) client.mu.Unlock() + client.Debugf("Not permitted to deliver to %q", subjectToCheck) return false } } + var mtErr string + if mt != nil { + // For non internal subscription, and if the remote does not support + // the tracing feature... + if sub.icb == nil && !client.msgTraceSupport() { + if traceOnly { + // We are not sending the message at all because the user + // expects a trace-only and the remote does not support + // tracing, which means that it would process/deliver this + // message, which may break applications. + // Add the Egress with the no-support error message. + mt.addEgressEvent(client, sub, errMsgTraceOnlyNoSupport) + client.mu.Unlock() + return false + } + // If we are doing delivery, we will still forward the message, + // but we add an error to the Egress event to hint that one should + // not expect a tracing event from that remote. + mtErr = errMsgTraceNoSupport + } + // For ROUTER, GATEWAY and LEAF, even if we intend to do tracing only, + // we will still deliver the message. The remote side will + // generate an event based on what happened on that server. + if traceOnly && (client.kind == ROUTER || client.kind == GATEWAY || client.kind == LEAF) { + traceOnly = false + } + // If we skip delivery and this is not for a service import, we are done. + if traceOnly && (sub.icb == nil || c.noIcb) { + mt.addEgressEvent(client, sub, _EMPTY_) + client.mu.Unlock() + // Although the message is not actually delivered, for the + // purpose of "didDeliver", we need to return "true" here. + return true + } + } + srv := client.srv - sub.nm++ + // We don't want to bump the number of delivered messages to the subscription + // if we are doing trace-only (since really we are not sending it to the sub). + if !traceOnly { + sub.nm++ + } + // Check if we should auto-unsubscribe. if sub.max > 0 { if client.kind == ROUTER && sub.nm >= sub.max { @@ -2955,25 +3647,20 @@ func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, g // still process the message in hand, otherwise // unsubscribe and drop message on the floor. if sub.nm == sub.max { - client.Debugf("Auto-unsubscribe limit of %d reached for sid '%s'", sub.max, string(sub.sid)) + client.Debugf("Auto-unsubscribe limit of %d reached for sid '%s'", sub.max, sub.sid) // Due to defer, reverse the code order so that execution // is consistent with other cases where we unsubscribe. if shouldForward { - if srv.gateway.enabled { - defer srv.gatewayUpdateSubInterest(client.acc.Name, sub, -1) - } - defer srv.updateRouteSubscriptionMap(client.acc, sub, -1) + defer srv.updateRemoteSubscription(client.acc, sub, -1) } defer client.unsubscribe(client.acc, sub, true, true) } else if sub.nm > sub.max { client.Debugf("Auto-unsubscribe limit [%d] exceeded", sub.max) + mt.addEgressEvent(client, sub, errMsgTraceAutoSubExceeded) client.mu.Unlock() client.unsubscribe(client.acc, sub, true, true) if shouldForward { - srv.updateRouteSubscriptionMap(client.acc, sub, -1) - if srv.gateway.enabled { - srv.gatewayUpdateSubInterest(client.acc.Name, sub, -1) - } + srv.updateRemoteSubscription(client.acc, sub, -1) } return false } @@ -2992,53 +3679,76 @@ func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, g // The msg includes the CR_LF, so pull back out for accounting. msgSize := int64(len(msg)) - prodIsMQTT := c.isMqtt() // MQTT producers send messages without CR_LF, so don't remove it for them. if !prodIsMQTT { msgSize -= int64(LEN_CR_LF) } - // No atomic needed since accessed under client lock. - // Monitor is reading those also under client's lock. - client.outMsgs++ - client.outBytes += msgSize + // We do not update the outbound stats if we are doing trace only since + // this message will not be sent out. + // Also do not update on internal callbacks. + if !traceOnly && sub.icb == nil { + // No atomic needed since accessed under client lock. + // Monitor is reading those also under client's lock. + client.outMsgs++ + client.outBytes += msgSize + } // Check for internal subscriptions. - if sub.icb != nil { + if sub.icb != nil && !c.noIcb { if gwrply { - // Note that we keep track of the GW routed reply in the destination - // connection (`client`). The routed reply subject is in `c.pa.reply`, - // should that change, we would have to pass the GW routed reply as - // a parameter of deliverMsg(). - srv.trackGWReply(client, c.pa.reply) + // We will store in the account, not the client since it will likely + // be a different client that will send the reply. + srv.trackGWReply(nil, client.acc, reply, c.pa.reply) } client.mu.Unlock() + + // For service imports, track if we delivered. + didDeliver := true + // Internal account clients are for service imports and need the '\r\n'. + start := time.Now() if client.kind == ACCOUNT { - sub.icb(sub, c, string(subject), string(reply), msg) + sub.icb(sub, c, acc, string(subject), string(reply), msg) + // If we are a service import check to make sure we delivered the message somewhere. + if sub.si { + didDeliver = c.pa.delivered + } } else { - sub.icb(sub, c, string(subject), string(reply), msg[:msgSize]) + sub.icb(sub, c, acc, string(subject), string(reply), msg[:msgSize]) + } + if dur := time.Since(start); dur >= readLoopReportThreshold { + srv.Warnf("Internal subscription on %q took too long: %v", subject, dur) } - return true - } - // We don't count internal deliveries so we update server statistics here. - atomic.AddInt64(&srv.outMsgs, 1) - atomic.AddInt64(&srv.outBytes, msgSize) + return didDeliver + } // If we are a client and we detect that the consumer we are // sending to is in a stalled state, go ahead and wait here // with a limit. if c.kind == CLIENT && client.out.stc != nil { + if srv.getOpts().NoFastProducerStall { + mt.addEgressEvent(client, sub, errMsgTraceFastProdNoStall) + client.mu.Unlock() + return false + } client.stalledWait(c) } // Check for closed connection if client.isClosed() { + mt.addEgressEvent(client, sub, errMsgTraceClientClosed) client.mu.Unlock() return false } + // We have passed cases where we could possibly fail to deliver. + // Do not call for service-import. + if mt != nil && sub.icb == nil { + mt.addEgressEvent(client, sub, mtErr) + } + // Do a fast check here to see if we should be tracking this from a latency // perspective. This will be for a request being received for an exported service. // This needs to be from a non-client (otherwise tracking happens at requestor). @@ -3053,7 +3763,7 @@ func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, g // connection (`client`). The routed reply subject is in `c.pa.reply`, // should that change, we would have to pass the GW routed reply as // a parameter of deliverMsg(). - srv.trackGWReply(client, c.pa.reply) + srv.trackGWReply(client, nil, reply, c.pa.reply) } // If we do not have a registered RTT queue that up now. @@ -3076,13 +3786,13 @@ func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, g client.queueOutbound([]byte(CR_LF)) } - client.out.pm++ - // If we are tracking dynamic publish permissions that track reply subjects, // do that accounting here. We only look at client.replies which will be non-nil. - if client.replies != nil && len(reply) > 0 { + // Only reply subject permissions if the client is not already allowed to publish to the reply subject. + if client.replies != nil && len(reply) > 0 && !client.pubAllowedFullCheck(string(reply), true, true) { client.replies[string(reply)] = &resp{time.Now(), 0} - if len(client.replies) > replyPermLimit { + client.repliesSincePrune++ + if client.repliesSincePrune > replyPermLimit || time.Since(client.lastReplyPrune) > replyPruneTime { client.pruneReplyPerms() } } @@ -3092,7 +3802,7 @@ func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, g // to intervene before this producer goes back to top of readloop. We are in the producer's // readloop go routine at this point. // FIXME(dlc) - We may call this alot, maybe suppress after first call? - if client.out.pm > 1 && client.out.pb > maxBufSize*2 { + if len(client.out.nb) != 0 { client.flushSignal() } @@ -3101,7 +3811,7 @@ func (c *client) deliverMsg(sub *subscription, subject, reply, mh, msg []byte, g c.addToPCD(client) if client.trace { - client.traceOutOp(string(mh[:len(mh)-LEN_CR_LF]), nil) + client.traceOutOp(bytesToString(mh[:len(mh)-LEN_CR_LF]), nil) } client.mu.Unlock() @@ -3206,6 +3916,9 @@ func (c *client) pruneReplyPerms() { delete(c.replies, k) } } + + c.repliesSincePrune = 0 + c.lastReplyPrune = now } // pruneDenyCache will prune the deny cache via randomly @@ -3225,11 +3938,32 @@ func (c *client) pruneDenyCache() { // prunePubPermsCache will prune the cache via randomly // deleting items. Doing so pruneSize items at a time. func (c *client) prunePubPermsCache() { - r := 0 - for subject := range c.perms.pcache { - delete(c.perms.pcache, subject) - if r++; r > pruneSize { - break + // With parallel additions to the cache, it is possible that this function + // would not be able to reduce the cache to its max size in one go. We + // will try a few times but will release/reacquire the "lock" at each + // attempt to give a chance to another go routine to take over and not + // have this go routine do too many attempts. + for i := 0; i < 5; i++ { + // There is a case where we can invoke this from multiple go routines, + // (in deliverMsg() if sub.client is a LEAF), so we make sure to prune + // from only one go routine at a time. + if !atomic.CompareAndSwapInt32(&c.perms.prun, 0, 1) { + return + } + const maxPruneAtOnce = 1000 + r := 0 + c.perms.pcache.Range(func(k, _ any) bool { + c.perms.pcache.Delete(k) + if r++; (r > pruneSize && atomic.LoadInt32(&c.perms.pcsz) < int32(maxPermCacheSize)) || + (r > maxPruneAtOnce) { + return false + } + return true + }) + n := atomic.AddInt32(&c.perms.pcsz, -int32(r)) + atomic.StoreInt32(&c.perms.prun, 0) + if n <= int32(maxPermCacheSize) { + return } } } @@ -3237,39 +3971,45 @@ func (c *client) prunePubPermsCache() { // pubAllowed checks on publish permissioning. // Lock should not be held. func (c *client) pubAllowed(subject string) bool { - return c.pubAllowedFullCheck(subject, true) + return c.pubAllowedFullCheck(subject, true, false) } // pubAllowedFullCheck checks on all publish permissioning depending // on the flag for dynamic reply permissions. -func (c *client) pubAllowedFullCheck(subject string, fullCheck bool) bool { +func (c *client) pubAllowedFullCheck(subject string, fullCheck, hasLock bool) bool { if c.perms == nil || (c.perms.pub.allow == nil && c.perms.pub.deny == nil) { return true } // Check if published subject is allowed if we have permissions in place. - allowed, ok := c.perms.pcache[subject] + v, ok := c.perms.pcache.Load(subject) if ok { - return allowed + return v.(bool) + } + allowed, checkAllow := true, true + // For CLIENT connections that are MQTT, or other types of connections, we will + // implicitly allow anything that starts with the "$MQTT." prefix. However, + // we don't just return here, we skip the check for "allow" but will check "deny". + if (c.isMqtt() || c.kind != CLIENT) && strings.HasPrefix(subject, mqttPrefix) { + checkAllow = false } // Cache miss, check allow then deny as needed. - if c.perms.pub.allow != nil { - r := c.perms.pub.allow.Match(subject) - allowed = len(r.psubs) != 0 - } else { - // No entries means all are allowed. Deny will overrule as needed. - allowed = true + if checkAllow && c.perms.pub.allow != nil { + np, _ := c.perms.pub.allow.NumInterest(subject) + allowed = np != 0 } // If we have a deny list and are currently allowed, check that as well. if allowed && c.perms.pub.deny != nil { - r := c.perms.pub.deny.Match(subject) - allowed = len(r.psubs) == 0 + np, _ := c.perms.pub.deny.NumInterest(subject) + allowed = np == 0 } - // If we are currently not allowed but we are tracking reply subjects + // If we are tracking reply subjects // dynamically, check to see if we are allowed here but avoid pcache. // We need to acquire the lock though. if !allowed && fullCheck && c.perms.resp != nil { - c.mu.Lock() + if !hasLock { + c.mu.Lock() + } if resp := c.replies[subject]; resp != nil { resp.n++ // Check if we have sent too many responses. @@ -3281,12 +4021,13 @@ func (c *client) pubAllowedFullCheck(subject string, fullCheck bool) bool { allowed = true } } - c.mu.Unlock() + if !hasLock { + c.mu.Unlock() + } } else { // Update our cache here. - c.perms.pcache[string(subject)] = allowed - // Prune if needed. - if len(c.perms.pcache) > maxPermCacheSize { + c.perms.pcache.Store(subject, allowed) + if n := atomic.AddInt32(&c.perms.pcsz, 1); n > maxPermCacheSize { c.prunePubPermsCache() } } @@ -3297,7 +4038,7 @@ func (c *client) pubAllowedFullCheck(subject string, fullCheck bool) bool { func isServiceReply(reply []byte) bool { // This function is inlined and checking this way is actually faster // than byte-by-byte comparison. - return len(reply) > 3 && string(reply[:4]) == replyPrefix + return len(reply) > 3 && bytesToString(reply[:4]) == replyPrefix } // Test whether a reply subject is a service import or a gateway routed reply. @@ -3305,8 +4046,11 @@ func isReservedReply(reply []byte) bool { if isServiceReply(reply) { return true } + rLen := len(reply) // Faster to check with string([:]) than byte-by-byte - if len(reply) > gwReplyPrefixLen && string(reply[:gwReplyPrefixLen]) == gwReplyPrefix { + if rLen > jsAckPreLen && bytesToString(reply[:jsAckPreLen]) == jsAckPre { + return true + } else if rLen > gwReplyPrefixLen && bytesToString(reply[:gwReplyPrefixLen]) == gwReplyPrefix { return true } return false @@ -3326,17 +4070,24 @@ func (c *client) processInboundMsg(msg []byte) { } } -// selectMappedSubject will chose the mapped subject based on the client's inbound subject. +// selectMappedSubject will choose the mapped subject based on the client's inbound subject. func (c *client) selectMappedSubject() bool { - nsubj, changed := c.acc.selectMappedSubject(string(c.pa.subject)) + nsubj, changed := c.acc.selectMappedSubject(bytesToString(c.pa.subject)) if changed { + c.pa.mapped = c.pa.subject c.pa.subject = []byte(nsubj) } return changed } +// clientNRGPrefix is used in processInboundClientMsg to detect if publishes +// are being made from normal clients to NRG subjects. +var clientNRGPrefix = []byte("$NRG.") + // processInboundClientMsg is called to process an inbound msg from a client. -func (c *client) processInboundClientMsg(msg []byte) bool { +// Return if the message was delivered, and if the message was not delivered +// due to a permission issue. +func (c *client) processInboundClientMsg(msg []byte) (bool, bool) { // Update statistics // The msg includes the CR_LF, so pull back out for accounting. c.in.msgs++ @@ -3345,24 +4096,37 @@ func (c *client) processInboundClientMsg(msg []byte) bool { // Check that client (could be here with SYSTEM) is not publishing on reserved "$GNR" prefix. if c.kind == CLIENT && hasGWRoutedReplyPrefix(c.pa.subject) { c.pubPermissionViolation(c.pa.subject) - return false + return false, true } // Mostly under testing scenarios. + c.mu.Lock() if c.srv == nil || c.acc == nil { - return false + c.mu.Unlock() + return false, false } + acc := c.acc + genidAddr := &acc.sl.genid // Check pub permissions - if c.perms != nil && (c.perms.pub.allow != nil || c.perms.pub.deny != nil) && !c.pubAllowed(string(c.pa.subject)) { + if c.perms != nil && (c.perms.pub.allow != nil || c.perms.pub.deny != nil) && !c.pubAllowedFullCheck(string(c.pa.subject), true, true) { + c.mu.Unlock() c.pubPermissionViolation(c.pa.subject) - return false + return false, true + } + c.mu.Unlock() + + // Check if the client is trying to publish to reserved NRG subjects. + // Doesn't apply to NRGs themselves as they use SYSTEM-kind clients instead. + if c.kind == CLIENT && bytes.HasPrefix(c.pa.subject, clientNRGPrefix) && acc != c.srv.SystemAccount() { + c.pubPermissionViolation(c.pa.subject) + return false, true } // Now check for reserved replies. These are used for service imports. - if len(c.pa.reply) > 0 && isReservedReply(c.pa.reply) { + if c.kind == CLIENT && len(c.pa.reply) > 0 && isReservedReply(c.pa.reply) { c.replySubjectViolation(c.pa.reply) - return false + return false, true } if c.opts.Verbose { @@ -3374,18 +4138,28 @@ func (c *client) processInboundClientMsg(msg []byte) bool { c.mqttHandlePubRetain() } - // Check if this client's gateway replies map is not empty - if atomic.LoadInt32(&c.cgwrt) > 0 && c.handleGWReplyMap(msg) { - return true - } - + // Doing this inline as opposed to create a function (which otherwise has a measured + // performance impact reported in our bench) + var isGWRouted bool + if c.kind != CLIENT { + if atomic.LoadInt32(&acc.gwReplyMapping.check) > 0 { + acc.mu.RLock() + c.pa.subject, isGWRouted = acc.gwReplyMapping.get(c.pa.subject) + acc.mu.RUnlock() + } + } else if atomic.LoadInt32(&c.gwReplyMapping.check) > 0 { + c.mu.Lock() + c.pa.subject, isGWRouted = c.gwReplyMapping.get(c.pa.subject) + c.mu.Unlock() + } + // If we have an exported service and we are doing remote tracking, check this subject // to see if we need to report the latency. if c.rrTracking != nil { c.mu.Lock() rl := c.rrTracking.rmap[string(c.pa.subject)] if rl != nil { - delete(c.rrTracking.rmap, string(c.pa.subject)) + delete(c.rrTracking.rmap, bytesToString(c.pa.subject)) } c.mu.Unlock() @@ -3402,12 +4176,19 @@ func (c *client) processInboundClientMsg(msg []byte) bool { } } + // If the subject was converted to the gateway routed subject, then handle it now + // and be done with the rest of this function. + if isGWRouted { + c.handleGWReplyMap(msg) + return true, false + } + // Match the subscriptions. We will use our own L1 map if // it's still valid, avoiding contention on the shared sublist. var r *SublistResult var ok bool - genid := atomic.LoadUint64(&c.acc.sl.genid) + genid := atomic.LoadUint64(genidAddr) if genid == c.in.genid && c.in.results != nil { r, ok = c.in.results[string(c.pa.subject)] } else { @@ -3418,17 +4199,21 @@ func (c *client) processInboundClientMsg(msg []byte) bool { // Go back to the sublist data structure. if !ok { - r = c.acc.sl.Match(string(c.pa.subject)) - c.in.results[string(c.pa.subject)] = r - // Prune the results cache. Keeps us from unbounded growth. Random delete. - if len(c.in.results) > maxResultCacheSize { - n := 0 - for subject := range c.in.results { - delete(c.in.results, subject) - if n++; n > pruneSize { - break + // Match may use the subject here to populate a cache, so can not use bytesToString here. + r = acc.sl.Match(string(c.pa.subject)) + if len(r.psubs)+len(r.qsubs) > 0 { + // Prune the results cache. Keeps us from unbounded growth. Random delete. + if len(c.in.results) >= maxResultCacheSize { + n := 0 + for subject := range c.in.results { + delete(c.in.results, subject) + if n++; n > pruneSize { + break + } } } + // Then add the new cache entry. + c.in.results[string(c.pa.subject)] = r } } @@ -3449,13 +4234,17 @@ func (c *client) processInboundClientMsg(msg []byte) bool { atomic.LoadInt64(&c.srv.gateway.totalQSubs) > 0 { flag |= pmrCollectQueueNames } - - didDeliver, qnames = c.processMsgResults(c.acc, r, msg, c.pa.deliver, c.pa.subject, c.pa.reply, flag) + didDeliver, qnames = c.processMsgResults(acc, r, msg, c.pa.deliver, c.pa.subject, c.pa.reply, flag) } // Now deal with gateways if c.srv.gateway.enabled { - didDeliver = c.sendMsgToGateways(c.acc, msg, c.pa.subject, c.pa.reply, qnames) || didDeliver + reply := c.pa.reply + if len(c.pa.deliver) > 0 && c.kind == JETSTREAM && len(c.pa.reply) > 0 { + reply = append(reply, '@') + reply = append(reply, c.pa.deliver...) + } + didDeliver = c.sendMsgToGateways(acc, msg, c.pa.subject, reply, qnames, false) || didDeliver } // Check to see if we did not deliver to anyone and the client has a reply subject set @@ -3472,7 +4261,7 @@ func (c *client) processInboundClientMsg(msg []byte) bool { c.mu.Unlock() } - return didDeliver + return didDeliver, false } // Return the subscription for this reply subject. Only look at normal subs for this client. @@ -3486,53 +4275,24 @@ func (c *client) subForReply(reply []byte) *subscription { return nil } -// This is invoked knowing that this client has some GW replies -// in its map. It will check if one is find for the c.pa.subject -// and if so will process it directly (send to GWs and LEAFs) and -// return true to notify the caller that the message was handled. -// If there is no mapping for the subject, false is returned. +// This is invoked knowing that c.pa.subject has been set to the gateway routed subject. +// This function will send the message to possibly LEAFs and directly back to the origin +// gateway. func (c *client) handleGWReplyMap(msg []byte) bool { - c.mu.Lock() - rm, ok := c.gwrm[string(c.pa.subject)] - if !ok { - c.mu.Unlock() - return false - } - // Set subject to the mapped reply subject - c.pa.subject = []byte(rm.ms) - - var rl *remoteLatency - - if c.rrTracking != nil { - rl = c.rrTracking.rmap[string(c.pa.subject)] - if rl != nil { - delete(c.rrTracking.rmap, string(c.pa.subject)) - } - } - c.mu.Unlock() - - if rl != nil { - sl := &rl.M2 - // Fill this in and send it off to the other side. - sl.Status = 200 - sl.Responder = c.getClientInfo(true) - sl.ServiceLatency = time.Since(sl.RequestStart) - sl.Responder.RTT - sl.TotalLatency = sl.ServiceLatency + sl.Responder.RTT - sanitizeLatencyMetric(sl) - lsub := remoteLatencySubjectForResponse(c.pa.subject) - c.srv.sendInternalAccountMsg(nil, lsub, rl) // Send to SYS account - } - // Check for leaf nodes if c.srv.gwLeafSubs.Count() > 0 { - if r := c.srv.gwLeafSubs.Match(string(c.pa.subject)); len(r.psubs) > 0 { - c.processMsgResults(c.acc, r, msg, nil, c.pa.subject, c.pa.reply, pmrNoFlag) + if r := c.srv.gwLeafSubs.MatchBytes(c.pa.subject); len(r.psubs) > 0 { + c.processMsgResults(c.acc, r, msg, c.pa.deliver, c.pa.subject, c.pa.reply, pmrNoFlag) } } if c.srv.gateway.enabled { - c.sendMsgToGateways(c.acc, msg, c.pa.subject, c.pa.reply, nil) + reply := c.pa.reply + if len(c.pa.deliver) > 0 && c.kind == JETSTREAM && len(c.pa.reply) > 0 { + reply = append(reply, '@') + reply = append(reply, c.pa.deliver...) + } + c.sendMsgToGateways(c.acc, msg, c.pa.subject, reply, nil, false) } - return true } @@ -3551,70 +4311,406 @@ func (c *client) setupResponseServiceImport(acc *Account, si *serviceImport, tra return rsi } +// Will remove a header if present. +func removeHeaderIfPresent(hdr []byte, key string) []byte { + start := getHeaderKeyIndex(key, hdr) + // key can't be first and we want to check that it is preceded by a '\n' + if start < 1 || hdr[start-1] != '\n' { + return hdr + } + index := start + len(key) + if index >= len(hdr) || hdr[index] != ':' { + return hdr + } + end := bytes.Index(hdr[start:], []byte(_CRLF_)) + if end < 0 { + return hdr + } + hdr = append(hdr[:start], hdr[start+end+len(_CRLF_):]...) + if len(hdr) <= len(emptyHdrLine) { + return nil + } + return hdr +} + +func removeHeaderIfPrefixPresent(hdr []byte, prefix string) []byte { + var index int + for { + if index >= len(hdr) { + return hdr + } + + start := bytes.Index(hdr[index:], []byte(prefix)) + if start < 0 { + return hdr + } + index += start + if index < 1 || hdr[index-1] != '\n' { + return hdr + } + + end := bytes.Index(hdr[index+len(prefix):], []byte(_CRLF_)) + if end < 0 { + return hdr + } + + hdr = append(hdr[:index], hdr[index+end+len(prefix)+len(_CRLF_):]...) + if len(hdr) <= len(emptyHdrLine) { + return nil + } + } +} + +// Generate a new header based on optional original header and key value. +// More used in JetStream layers. +func genHeader(hdr []byte, key, value string) []byte { + var bb bytes.Buffer + if len(hdr) > LEN_CR_LF { + bb.Write(hdr[:len(hdr)-LEN_CR_LF]) + } else { + bb.WriteString(hdrLine) + } + http.Header{key: []string{value}}.Write(&bb) + bb.WriteString(CR_LF) + return bb.Bytes() +} + +// This will set a header for the message. +// Lock does not need to be held but this should only be called +// from the inbound go routine. We will update the pubArgs. +// This will replace any previously set header and not add to it per normal spec. +func (c *client) setHeader(key, value string, msg []byte) []byte { + var bb bytes.Buffer + var omi int + // Write original header if present. + if c.pa.hdr > LEN_CR_LF { + omi = c.pa.hdr + hdr := removeHeaderIfPresent(msg[:c.pa.hdr-LEN_CR_LF], key) + if len(hdr) == 0 { + bb.WriteString(hdrLine) + } else { + bb.Write(hdr) + } + } else { + bb.WriteString(hdrLine) + } + http.Header{key: []string{value}}.Write(&bb) + bb.WriteString(CR_LF) + nhdr := bb.Len() + // Put the original message back. + // FIXME(dlc) - This is inefficient. + bb.Write(msg[omi:]) + nsize := bb.Len() - LEN_CR_LF + // MQTT producers don't have CRLF, so add it back. + if c.isMqtt() { + nsize += LEN_CR_LF + } + // Update pubArgs + // If others will use this later we need to save and restore original. + c.pa.hdr = nhdr + c.pa.size = nsize + c.pa.hdb = []byte(strconv.Itoa(nhdr)) + c.pa.szb = []byte(strconv.Itoa(nsize)) + return bb.Bytes() +} + +// Will return a copy of the value for the header denoted by key or nil if it does not exist. +// If you know that it is safe to refer to the underlying hdr slice for the period that the +// return value is used, then sliceHeader() will be faster. +func getHeader(key string, hdr []byte) []byte { + v := sliceHeader(key, hdr) + if v == nil { + return nil + } + return append(make([]byte, 0, len(v)), v...) +} + +// Will return the sliced value for the header denoted by key or nil if it does not exists. +// This function ignores errors and tries to achieve speed and no additional allocations. +func sliceHeader(key string, hdr []byte) []byte { + if len(hdr) == 0 { + return nil + } + index := getHeaderKeyIndex(key, hdr) + if index == -1 { + return nil + } + // Skip over the key and the : separator. + index += len(key) + 1 + hdrLen := len(hdr) + // Skip over whitespace before the value. + for index < hdrLen && hdr[index] == ' ' { + index++ + } + // Collect together the rest of the value until we hit a CRLF. + start := index + for index < hdrLen { + if hdr[index] == '\r' && index < hdrLen-1 && hdr[index+1] == '\n' { + break + } + index++ + } + return hdr[start:index:index] +} + +// getHeaderKeyIndex returns an index into the header slice for the given key. +// Returns -1 if not found. +func getHeaderKeyIndex(key string, hdr []byte) int { + if len(hdr) == 0 { + return -1 + } + bkey := stringToBytes(key) + keyLen, hdrLen := len(key), len(hdr) + var offset int + for { + index := bytes.Index(hdr[offset:], bkey) + // Check that we have enough characters, this will handle the -1 case of the key not + // being found and will also handle not having enough characters for trailing CRLF. + if index < 2 { + return -1 + } + index += offset + // There should be a terminating CRLF. + if index >= hdrLen-1 || hdr[index-1] != '\n' || hdr[index-2] != '\r' { + offset = index + keyLen + continue + } + // The key should be immediately followed by a : separator. + if index+keyLen >= hdrLen { + return -1 + } + if hdr[index+keyLen] != ':' { + offset = index + keyLen + continue + } + return index + } +} + +// setHeader will replace the value of the first existing key `key` +// with the given value `val`, or add this new key at the end of +// the headers. +// +// Note: If the key does not exist, or if it exists but the new value +// would make the resulting byte slice larger than the original one, +// a new byte slice is returned and the original is left untouched. +// This is to prevent situations where caller may have a `hdr` and +// `msg` that are the parts of an underlying buffer. Extending the +// `hdr` would otherwise overwrite the `msg` part. +// +// If the new value is smaller, then the original `hdr` byte slice +// is modified. +func setHeader(key, val string, hdr []byte) []byte { + start := getHeaderKeyIndex(key, hdr) + if start >= 0 { + valStart := start + len(key) + 1 + // Preserve single whitespace if used. + hdrLen := len(hdr) + if valStart < hdrLen && hdr[valStart] == ' ' { + valStart++ + } + valEnd := bytes.Index(hdr[valStart:], []byte("\r")) + if valEnd < 0 { + return hdr // malformed headers + } + valEnd += valStart + // Length of the existing value (before the `\r`) + oldValLen := valEnd - valStart + // This is how many extra bytes we need for the new value. + // If <= 0, it means that we need less and so will reuse the `hdr` buffer. + if extra := len(val) - oldValLen; extra > 0 { + // Check that we don't overflow an "int". + if rem := math.MaxInt - hdrLen; rem < extra { + // We don't grow, and return the existing header. + return hdr + } + // The new size is the old size plus the extra bytes. + newHdrSize := hdrLen + extra + newHdr := make([]byte, newHdrSize) + // Copy the parts from `hdr` and `val` into the new buffer. + n := copy(newHdr, hdr[:valStart]) + n += copy(newHdr[n:], val) + copy(newHdr[n:], hdr[valEnd:]) + return newHdr + } + // We can write in place since it fits in the existing `hdr` buffer. + n := copy(hdr[valStart:], val) + n += copy(hdr[valStart+n:], hdr[valEnd:]) + hdr = hdr[:valStart+n] + return hdr + } + if len(hdr) > 0 && bytes.HasSuffix(hdr, []byte("\r\n")) { + hdr = hdr[:len(hdr)-2] + val += "\r\n" + } + // Create the new buffer based on length of existing one and + // length of the new ": \r\n". Protect against "int" overflow. + newSize := uint64(len(hdr)) + uint64(len(key)) + 1 + 1 + uint64(len(val)) + 2 + if newSize > uint64(math.MaxInt) { + // We don't grow, and return the existing header. + return hdr + } + newHdr := make([]byte, 0, int(newSize)) + newHdr = append(newHdr, hdr...) + return fmt.Appendf(newHdr, "%s: %s\r\n", key, val) +} + +// For bytes.HasPrefix below. +var ( + jsRequestNextPreB = []byte(jsRequestNextPre) + jsDirectGetPreB = []byte(jsDirectGetPre) +) + // processServiceImport is an internal callback when a subscription matches an imported service // from another account. This includes response mappings as well. -func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byte) { - if c.kind == GATEWAY && !si.isRespServiceImport() { - return +func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byte) bool { + // If we are a GW and this is not a direct serviceImport ignore. + isResponse := si.isRespServiceImport() + if (c.kind == GATEWAY || c.kind == ROUTER) && !isResponse { + return false + } + // Detect cycles and ignore (return) when we detect one. + if len(c.pa.psi) > 0 { + for i := len(c.pa.psi) - 1; i >= 0; i-- { + if psi := c.pa.psi[i]; psi.se == si.se { + return false + } + } } acc.mu.RLock() + var checkJS bool shouldReturn := si.invalid || acc.sl == nil + if !shouldReturn && !isResponse && si.to == jsAllAPI { + if bytes.HasPrefix(c.pa.subject, jsDirectGetPreB) || bytes.HasPrefix(c.pa.subject, jsRequestNextPreB) { + checkJS = true + } + } + siAcc := si.acc + allowTrace := si.atrc acc.mu.RUnlock() - if shouldReturn { - return + // We have a special case where JetStream pulls in all service imports through one export. + // However the GetNext for consumers and DirectGet for streams are a no-op and causes buildups of service imports, + // response service imports and rrMap entries which all will need to simply expire. + // TODO(dlc) - Come up with something better. + if shouldReturn || (checkJS && si.se != nil && si.se.acc == c.srv.SystemAccount()) { + return false } + mt, traceOnly := c.isMsgTraceEnabled() + var nrr []byte var rsi *serviceImport // Check if there is a reply present and set up a response. - // TODO(dlc) - restrict to configured service imports and not responses? tracking, headers := shouldSample(si.latency, c) if len(c.pa.reply) > 0 { - if rsi = c.setupResponseServiceImport(acc, si, tracking, headers); rsi != nil { - nrr = []byte(rsi.from) + // Special case for now, need to formalize. + // TODO(dlc) - Formalize as a service import option for reply rewrite. + // For now we can't do $JS.ACK since that breaks pull consumers across accounts. + if !bytes.HasPrefix(c.pa.reply, []byte(jsAckPre)) { + if rsi = c.setupResponseServiceImport(acc, si, tracking, headers); rsi != nil { + nrr = []byte(rsi.from) + } + } else { + // This only happens when we do a pull subscriber that trampolines through another account. + // Normally this code is not called. + nrr = c.pa.reply } - } else { + } else if !isResponse && si.latency != nil && tracking { // Check to see if this was a bad request with no reply and we were supposed to be tracking. - if !si.response && si.latency != nil && tracking { - si.acc.sendBadRequestTrackingLatency(si, c, headers) - } + siAcc.sendBadRequestTrackingLatency(si, c, headers) } // Send tracking info here if we are tracking this response. // This is always a response. var didSendTL bool - if si.tracking { + if si.tracking && !si.didDeliver { // Stamp that we attempted delivery. si.didDeliver = true didSendTL = acc.sendTrackingLatency(si, c) } - // Pick correct to subject. If we matched on a wildcard use the literal publish subject. - to := si.to + // Pick correct "to" subject. If we matched on a wildcard use the literal publish subject. + to, subject := si.to, string(c.pa.subject) + if si.tr != nil { // FIXME(dlc) - This could be slow, may want to look at adding cache to bare transforms? - to, _ = si.tr.transformSubject(string(c.pa.subject)) + to = si.tr.TransformSubject(subject) } else if si.usePub { - to = string(c.pa.subject) + to = subject } + // Copy our pubArg since this gets modified as we process the service import itself. + pacopy := c.pa + // Now check to see if this account has mappings that could affect the service import. // Can't use non-locked trick like in processInboundClientMsg, so just call into selectMappedSubject // so we only lock once. - to, _ = si.acc.selectMappedSubject(to) + nsubj, changed := siAcc.selectMappedSubject(to) + if changed { + c.pa.mapped = []byte(to) + to = nsubj + } + + // Set previous service import to detect chaining. + lpsi := len(c.pa.psi) + hadPrevSi, share := lpsi > 0, si.share + if hadPrevSi { + share = c.pa.psi[lpsi-1].share + } + c.pa.psi = append(c.pa.psi, si) + + // Place our client info for the request in the original message. + // This will survive going across routes, etc. + if !isResponse { + isSysImport := siAcc == c.srv.SystemAccount() + var ci *ClientInfo + if hadPrevSi && c.pa.hdr >= 0 { + var cis ClientInfo + if err := json.Unmarshal(sliceHeader(ClientInfoHdr, msg[:c.pa.hdr]), &cis); err == nil { + ci = &cis + ci.Service = acc.Name + // Check if we are moving into a share details account from a non-shared + // and add in server and cluster details. + if !share && (si.share || isSysImport) { + c.addServerAndClusterInfo(ci) + } + } + } else if c.kind != LEAF || c.pa.hdr < 0 || len(sliceHeader(ClientInfoHdr, msg[:c.pa.hdr])) == 0 { + ci = c.getClientInfo(share) + // If we did not share but the imports destination is the system account add in the server and cluster info. + if !share && isSysImport { + c.addServerAndClusterInfo(ci) + } + } else if c.kind == LEAF && (si.share || isSysImport) { + // We have a leaf header here for ci, augment as above. + ci = c.getClientInfo(si.share) + if !si.share && isSysImport { + c.addServerAndClusterInfo(ci) + } + } + // Set clientInfo if present. + if ci != nil { + if b, _ := json.Marshal(ci); b != nil { + msg = c.setHeader(ClientInfoHdr, bytesToString(b), msg) + } + } + } - oreply, oacc := c.pa.reply, c.acc + // Set our optional subject(to) and reply. + if !isResponse && to != subject { + c.pa.subject = []byte(to) + } c.pa.reply = nrr - if !si.isSysAcc { - c.mu.Lock() - c.acc = si.acc - c.mu.Unlock() + + if changed && c.isMqtt() && c.pa.hdr > 0 { + c.srv.mqttStoreQoSMsgForAccountOnNewSubject(c.pa.hdr, msg, siAcc.GetName(), to) } + // FIXME(dlc) - Do L1 cache trick like normal client? - rr := si.acc.sl.Match(to) + rr := siAcc.sl.Match(to) // If we are a route or gateway or leafnode and this message is flipped to a queue subscriber we // need to handle that since the processMsgResults will want a queue filter. @@ -3632,33 +4728,62 @@ func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byt var lrts [routeTargetInit]routeTarget c.in.rts = lrts[:0] + var skipProcessing bool + // If message tracing enabled, add the service import trace. + if mt != nil { + mt.addServiceImportEvent(siAcc.GetName(), string(pacopy.subject), to) + // If we are not allowing tracing and doing trace only, we stop at this level. + if !allowTrace { + if traceOnly { + skipProcessing = true + } else { + // We are going to do normal processing, and possibly chainning + // with other server imports, but the rest won't be traced. + // We do so by setting the c.pa.trace to nil (it will be restored + // with c.pa = pacopy). + c.pa.trace = nil + // We also need to disable the message trace headers so that + // if the message is routed, it does not initialize tracing in the + // remote. + positions := disableTraceHeaders(c, msg) + defer enableTraceHeaders(msg, positions) + } + } + } + var didDeliver bool - // If this is not a gateway connection but gateway is enabled, - // try to send this converted message to all gateways. - if c.srv.gateway.enabled { - flags |= pmrCollectQueueNames - var queues [][]byte - didDeliver, queues = c.processMsgResults(si.acc, rr, msg, nil, []byte(to), nrr, flags) - didDeliver = c.sendMsgToGateways(si.acc, msg, []byte(to), nrr, queues) || didDeliver - } else { - didDeliver, _ = c.processMsgResults(si.acc, rr, msg, nil, []byte(to), nrr, flags) + if !skipProcessing { + // If this is not a gateway connection but gateway is enabled, + // try to send this converted message to all gateways. + if c.srv.gateway.enabled { + flags |= pmrCollectQueueNames + var queues [][]byte + didDeliver, queues = c.processMsgResults(siAcc, rr, msg, c.pa.deliver, []byte(to), nrr, flags) + didDeliver = c.sendMsgToGateways(siAcc, msg, []byte(to), nrr, queues, false) || didDeliver + } else { + didDeliver, _ = c.processMsgResults(siAcc, rr, msg, c.pa.deliver, []byte(to), nrr, flags) + } } - // Put what was there back now. + // Restore to original values. c.in.rts = orts - c.pa.reply = oreply + c.pa = pacopy - if !si.isSysAcc { - c.mu.Lock() - c.acc = oacc - c.mu.Unlock() + // Before we undo didDeliver based on tracing and last mile, mark in the c.pa which informs us of no responders status. + // If we override due to tracing and traceOnly we do not want to send back a no responders. + c.pa.delivered = didDeliver + + // If this was a message trace but we skip last-mile delivery, we need to + // do the remove, so: + if mt != nil && traceOnly && didDeliver { + didDeliver = false } // Determine if we should remove this service import. This is for response service imports. // We will remove if we did not deliver, or if we are a response service import and we are // a singleton, or we have an EOF message. - shouldRemove := !didDeliver || (si.response && (si.rt == Singleton || len(msg) == LEN_CR_LF)) + shouldRemove := !didDeliver || (isResponse && (si.rt == Singleton || len(msg) == LEN_CR_LF)) // If we are tracking and we did not actually send the latency info we need to suppress the removal. if si.tracking && !didSendTL { shouldRemove = false @@ -3676,14 +4801,16 @@ func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byt if !didDeliver { reason = rsiNoDelivery } - if si.isRespServiceImport() { + if isResponse { acc.removeRespServiceImport(si, reason) } else { // This is a main import and since we could not even deliver to the exporting account // go ahead and remove the respServiceImport we created above. - si.acc.removeRespServiceImport(rsi, reason) + siAcc.removeRespServiceImport(rsi, reason) } } + + return didDeliver } func (c *client) addSubToRouteTargets(sub *subscription) { @@ -3752,11 +4879,23 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, // Check for JetStream encoded reply subjects. // For now these will only be on $JS.ACK prefixed reply subjects. - if len(creply) > 0 && - c.kind != CLIENT && c.kind != SYSTEM && c.kind != JETSTREAM && c.kind != ACCOUNT && - bytes.HasPrefix(creply, []byte(jsAckPre)) { + var remapped bool + if len(creply) > 0 && c.kind != CLIENT && !isInternalClient(c.kind) && bytes.HasPrefix(creply, []byte(jsAckPre)) { // We need to rewrite the subject and the reply. - if li := bytes.LastIndex(creply, []byte("@")); li != 0 && li < len(creply)-1 { + // But, we must be careful that the stream name, consumer name, and subject can contain '@' characters. + // JS ACK contains at least 8 dots, find the first @ after this prefix. + // - $JS.ACK....... + counter := 0 + li := bytes.IndexFunc(creply, func(rn rune) bool { + if rn == '.' { + counter++ + } else if rn == '@' { + return counter >= 8 + } + return false + }) + if li != -1 && li < len(creply)-1 { + remapped = true subj, creply = creply[li+1:], creply[:li] } } @@ -3766,7 +4905,60 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, // delivery subject for clients var dsubj []byte // Used as scratch if mapping - var _dsubj [64]byte + var _dsubj [128]byte + + // For stats, we will keep track of the number of messages that have been + // delivered and then multiply by the size of that message and update + // server and account stats in a "single" operation (instead of per-sub). + // However, we account for situations where the message is possibly changed + // by having an extra size + var dlvMsgs int64 + var dlvExtraSize int64 + var dlvRouteMsgs int64 + var dlvLeafMsgs int64 + + // We need to know if this is a MQTT producer because they send messages + // without CR_LF (we otherwise remove the size of CR_LF from message size). + prodIsMQTT := c.isMqtt() + + updateStats := func() { + if dlvMsgs == 0 { + return + } + + totalBytes := dlvMsgs*int64(len(msg)) + dlvExtraSize + routeBytes := dlvRouteMsgs*int64(len(msg)) + dlvExtraSize + leafBytes := dlvLeafMsgs*int64(len(msg)) + dlvExtraSize + + // For non MQTT producers, remove the CR_LF * number of messages + if !prodIsMQTT { + totalBytes -= dlvMsgs * int64(LEN_CR_LF) + routeBytes -= dlvRouteMsgs * int64(LEN_CR_LF) + leafBytes -= dlvLeafMsgs * int64(LEN_CR_LF) + } + + if acc != nil { + acc.stats.Lock() + acc.stats.outMsgs += dlvMsgs + acc.stats.outBytes += totalBytes + if dlvRouteMsgs > 0 { + acc.stats.rt.outMsgs += dlvRouteMsgs + acc.stats.rt.outBytes += routeBytes + } + if dlvLeafMsgs > 0 { + acc.stats.ln.outMsgs += dlvLeafMsgs + acc.stats.ln.outBytes += leafBytes + } + acc.stats.Unlock() + } + + if srv := c.srv; srv != nil { + atomic.AddInt64(&srv.outMsgs, dlvMsgs) + atomic.AddInt64(&srv.outBytes, totalBytes) + } + } + + mt, traceOnly := c.isMsgTraceEnabled() // Loop over all normal subscriptions that match. for _, sub := range r.psubs { @@ -3785,8 +4977,9 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, // We handle similarly to routes and use the same data structures. // Leaf node delivery audience is different however. // Also leaf nodes are always no echo, so we make sure we are not - // going to send back to ourselves here. - if c != sub.client && (c.kind != ROUTER || sub.client.isHubLeafNode()) { + // going to send back to ourselves here. For messages from routes we want + // to suppress in general unless we know from the hub or its a service reply. + if c != sub.client && (c.kind != ROUTER || sub.client.isHubLeafNode() || isServiceReply(c.pa.subject)) { c.addSubToRouteTargets(sub) } continue @@ -3795,6 +4988,11 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, // Assume delivery subject is the normal subject to this point. dsubj = subj + // We may need to disable tracing, by setting c.pa.trace to `nil` + // before the call to deliverMsg, if so, this will indicate that + // we need to put it back. + var restorePaTrace bool + // Check for stream import mapped subs (shadow subs). These apply to local subs only. if sub.im != nil { // If this message was a service import do not re-export to an exported stream. @@ -3802,13 +5000,37 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, continue } if sub.im.tr != nil { - to, _ := sub.im.tr.transformSubject(string(dsubj)) + to := sub.im.tr.TransformSubject(bytesToString(subject)) dsubj = append(_dsubj[:0], to...) } else if sub.im.usePub { dsubj = append(_dsubj[:0], subj...) } else { dsubj = append(_dsubj[:0], sub.im.to...) } + + if mt != nil { + mt.addStreamExportEvent(sub.client, dsubj) + // If allow_trace is false... + if !sub.im.atrc { + // If we are doing only message tracing, we can move to the + // next sub. + if traceOnly { + // Although the message was not delivered, for the purpose + // of didDeliver, we need to set to true (to avoid possible + // no responders). + didDeliver = true + continue + } + // If we are delivering the message, we need to disable tracing + // before calling deliverMsg(). + c.pa.trace, restorePaTrace = nil, true + } + } + + // Make sure deliver is set if inbound from a route. + if remapped && (c.kind == GATEWAY || c.kind == ROUTER || c.kind == LEAF) { + deliver = subj + } // If we are mapping for a deliver subject we will reverse roles. // The original subj we set from above is correct for the msg header, // but we need to transform the deliver subject to properly route. @@ -3817,14 +5039,23 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, } } - // Remap to original if internal. - if sub.icb != nil { - subj = subject + // Remap to the original subject if internal. + if sub.icb != nil && sub.rsi { + dsubj = subject } // Normal delivery mh := c.msgHeader(dsubj, creply, sub) - didDeliver = c.deliverMsg(sub, subj, creply, mh, msg, rplyHasGWPrefix) || didDeliver + if c.deliverMsg(prodIsMQTT, sub, acc, dsubj, creply, mh, msg, rplyHasGWPrefix) { + // We don't count internal deliveries, so do only when sub.icb is nil. + if sub.icb == nil { + dlvMsgs++ + } + didDeliver = true + } + if restorePaTrace { + c.pa.trace = mt + } } // Set these up to optionally filter based on the queue lists. @@ -3835,20 +5066,29 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, // Declared here because of goto. var queues [][]byte + var leafOrigin string + switch c.kind { + case ROUTER: + if len(c.pa.origin) > 0 { + // Picture a message sent from a leafnode to a server that then routes + // this message: CluserA -leaf-> HUB1 -route-> HUB2 + // Here we are in HUB2, so c.kind is a ROUTER, but the message will + // contain a c.pa.origin set to "ClusterA" to indicate that this message + // originated from that leafnode cluster. + leafOrigin = bytesToString(c.pa.origin) + } + case LEAF: + leafOrigin = c.remoteCluster() + } + // For all routes/leaf/gateway connections, we may still want to send messages to // leaf nodes or routes even if there are no queue filters since we collect // them above and do not process inline like normal clients. // However, do select queue subs if asked to ignore empty queue filter. - if (c.kind == LEAF || c.kind == ROUTER || c.kind == GATEWAY) && qf == nil && flags&pmrIgnoreEmptyQueueFilter == 0 { + if (c.kind == LEAF || c.kind == ROUTER || c.kind == GATEWAY) && len(qf) == 0 && flags&pmrIgnoreEmptyQueueFilter == 0 { goto sendToRoutesOrLeafs } - // Check to see if we have our own rand yet. Global rand - // has contention with lots of clients, etc. - if c.in.prand == nil { - c.in.prand = rand.New(rand.NewSource(time.Now().UnixNano())) - } - // Process queue subs for i := 0; i < len(r.qsubs); i++ { qsubs := r.qsubs[i] @@ -3879,9 +5119,24 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, ql := _ql[:0] for i := 0; i < len(qsubs); i++ { sub = qsubs[i] - if sub.client.kind == LEAF || sub.client.kind == ROUTER { - if rsub == nil { + if dst := sub.client.kind; dst == LEAF || dst == ROUTER { + // If the destination is a LEAF, we first need to make sure + // that we would not pick one that was the origin of this + // message. + if dst == LEAF && leafOrigin != _EMPTY_ && leafOrigin == sub.client.remoteCluster() { + continue + } + // If we have assigned a ROUTER rsub already, replace if + // the destination is a LEAF since we want to favor that. + if rsub == nil || (rsub.client.kind == ROUTER && dst == LEAF) { rsub = sub + } else if dst == LEAF { + // We already have a LEAF and this is another one. + // Flip a coin to see if we swap it or not. + // See https://github.com/nats-io/nats-server/issues/6040 + if fastrand.Uint32()%2 == 1 { + rsub = sub + } } } else { ql = append(ql, sub) @@ -3893,10 +5148,12 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, sindex := 0 lqs := len(qsubs) if lqs > 1 { - sindex = c.in.prand.Int() % lqs + sindex = int(fastrand.Uint32() % uint32(lqs)) } // Find a subscription that is able to deliver this message starting at a random index. + // Note that if the message came from a ROUTER, we will only have CLIENT or LEAF + // queue subs here, otherwise we can have all types. for i := 0; i < lqs; i++ { if sindex+i < lqs { sub = qsubs[sindex+i] @@ -3907,27 +5164,59 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, continue } + // If we are a spoke leaf node make sure to not forward across routes. + // This mimics same behavior for normal subs above. + if c.kind == LEAF && c.isSpokeLeafNode() && sub.client.kind == ROUTER { + continue + } + // We have taken care of preferring local subs for a message from a route above. // Here we just care about a client or leaf and skipping a leaf and preferring locals. if dst := sub.client.kind; dst == ROUTER || dst == LEAF { if (src == LEAF || src == CLIENT) && dst == LEAF { + // If we come from a LEAF and are about to pick a LEAF connection, + // make sure this is not the same leaf cluster. + if src == LEAF && leafOrigin != _EMPTY_ && leafOrigin == sub.client.remoteCluster() { + continue + } + // Remember that leaf in case we don't find any other candidate. + // We already start randomly in lqs slice, so we don't need + // to do a random swap if we already have an rsub like we do + // when src == ROUTER above. if rsub == nil { rsub = sub } continue } else { - c.addSubToRouteTargets(sub) - // Clear rsub since we added a sub. - rsub = nil - if flags&pmrCollectQueueNames != 0 { - queues = append(queues, sub.queue) + // We want to favor qsubs in our own cluster. If the routed + // qsub has an origin, it means that is on behalf of a leaf. + // We need to treat it differently. + if len(sub.origin) > 0 { + // If we already have an rsub, nothing to do. Also, do + // not pick a routed qsub for a LEAF origin cluster + // that is the same than where the message comes from. + if rsub == nil && (leafOrigin == _EMPTY_ || leafOrigin != bytesToString(sub.origin)) { + rsub = sub + } + continue } + // This is a qsub that is local on the remote server (or + // we are connected to an older server and we don't know). + // Pick this one and be done. + rsub = sub + break } - break } // Assume delivery subject is normal subject to this point. dsubj = subj + + // We may need to disable tracing, by setting c.pa.trace to `nil` + // before the call to deliverMsg, if so, this will indicate that + // we need to put it back. + var restorePaTrace bool + var skipDelivery bool + // Check for stream import mapped subs. These apply to local subs only. if sub.im != nil { // If this message was a service import do not re-export to an exported stream. @@ -3935,23 +5224,62 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, continue } if sub.im.tr != nil { - to, _ := sub.im.tr.transformSubject(string(subj)) + to := sub.im.tr.TransformSubject(bytesToString(subject)) dsubj = append(_dsubj[:0], to...) } else if sub.im.usePub { dsubj = append(_dsubj[:0], subj...) } else { dsubj = append(_dsubj[:0], sub.im.to...) } + + if mt != nil { + mt.addStreamExportEvent(sub.client, dsubj) + // If allow_trace is false... + if !sub.im.atrc { + // If we are doing only message tracing, we are done + // with this queue group. + if traceOnly { + skipDelivery = true + } else { + // If we are delivering, we need to disable tracing + // before the call to deliverMsg() + c.pa.trace, restorePaTrace = nil, true + } + } + } + + // Make sure deliver is set if inbound from a route. + if remapped && (c.kind == GATEWAY || c.kind == ROUTER || c.kind == LEAF) { + deliver = subj + } + // If we are mapping for a deliver subject we will reverse roles. + // The original subj we set from above is correct for the msg header, + // but we need to transform the deliver subject to properly route. + if len(deliver) > 0 { + dsubj, subj = subj, dsubj + } } - var rreply = reply - if rplyHasGWPrefix && sub.client.kind == CLIENT { - rreply = creply + var delivered bool + if !skipDelivery { + mh := c.msgHeader(dsubj, creply, sub) + delivered = c.deliverMsg(prodIsMQTT, sub, acc, subject, creply, mh, msg, rplyHasGWPrefix) + if restorePaTrace { + c.pa.trace = mt + } } - // "rreply" will be stripped of the $GNR prefix (if present) - // for client connections only. - mh := c.msgHeader(dsubj, rreply, sub) - if c.deliverMsg(sub, subject, rreply, mh, msg, rplyHasGWPrefix) { + if skipDelivery || delivered { + // Update only if not skipped. + if !skipDelivery && sub.icb == nil { + dlvMsgs++ + switch sub.client.kind { + case ROUTER: + dlvRouteMsgs++ + case LEAF: + dlvLeafMsgs++ + } + } + // Do the rest even when message delivery was skipped. didDeliver = true // Clear rsub rsub = nil @@ -3963,8 +5291,8 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, } if rsub != nil { - // If we are here we tried to deliver to a local qsub - // but failed. So we will send it to a remote or leaf node. + // We are here if we have selected a leaf or route as the destination, + // or if we tried to deliver to a local qsub but failed. c.addSubToRouteTargets(rsub) if flags&pmrCollectQueueNames != 0 { queues = append(queues, rsub.queue) @@ -3976,49 +5304,125 @@ sendToRoutesOrLeafs: // If no messages for routes or leafnodes return here. if len(c.in.rts) == 0 { + updateStats() return didDeliver, queues } // If we do have a deliver subject we need to do something with it. // Again this is when JetStream (but possibly others) wants the system // to rewrite the delivered subject. The way we will do that is place it - // at the end of the reply subject if it exists. - if len(deliver) > 0 && len(reply) > 0 { + // at the end of the reply subject if it exists. But only if this wasn't + // already performed, otherwise we'd end up with a duplicate '@' suffix + // resulting in a protocol error. + if len(deliver) > 0 && len(reply) > 0 && !remapped { reply = append(reply, '@') reply = append(reply, deliver...) } + // Copy off original pa in case it changes. + pa := c.pa + + if mt != nil { + // We are going to replace "pa" with our copy of c.pa, but to restore + // to the original copy of c.pa, we need to save it again. + cpa := pa + msg = mt.setOriginAccountHeaderIfNeeded(c, acc, msg) + defer func() { c.pa = cpa }() + // Update pa with our current c.pa state. + pa = c.pa + } + // We address by index to avoid struct copy. // We have inline structs for memory layout and cache coherency. for i := range c.in.rts { rt := &c.in.rts[i] + dc := rt.sub.client + dmsg, hset := msg, false + // Check if we have an origin cluster set from a leafnode message. // If so make sure we do not send it back to the same cluster for a different // leafnode. Cluster wide no echo. - if rt.sub.client.kind == LEAF { - // Check two scenarios. One is inbound from a route (c.pa.origin) - if c.kind == ROUTER && len(c.pa.origin) > 0 { - if string(c.pa.origin) == rt.sub.client.remoteCluster() { - continue - } + if dc.kind == LEAF { + // Check two scenarios. One is inbound from a route (c.pa.origin), + // and the other is leaf to leaf. In both case, leafOrigin is the one + // to use for the comparison. + if leafOrigin != _EMPTY_ && leafOrigin == dc.remoteCluster() { + continue } - // The other is leaf to leaf. - if c.kind == LEAF { - src, dest := c.remoteCluster(), rt.sub.client.remoteCluster() - if src != _EMPTY_ && src == dest { - continue - } + + // We need to check if this is a request that has a stamped client information header. + // This will contain an account but will represent the account from the leafnode. If + // they are not named the same this would cause an account lookup failure trying to + // process the request for something like JetStream or other system services that rely + // on the client info header. We can just check for reply and the presence of a header + // to avoid slow downs for all traffic. + if len(c.pa.reply) > 0 && c.pa.hdr >= 0 { + dmsg, hset = c.checkLeafClientInfoHeader(msg) } } + if mt != nil { + dmsg = mt.setHopHeader(c, dmsg) + hset = true + } + mh := c.msgHeaderForRouteOrLeaf(subject, reply, rt, acc) - didDeliver = c.deliverMsg(rt.sub, subject, reply, mh, msg, false) || didDeliver + if c.deliverMsg(prodIsMQTT, rt.sub, acc, subject, reply, mh, dmsg, false) { + if rt.sub.icb == nil { + dlvMsgs++ + switch dc.kind { + case ROUTER: + dlvRouteMsgs++ + case LEAF: + dlvLeafMsgs++ + } + dlvExtraSize += int64(len(dmsg) - len(msg)) + } + didDeliver = true + } + + // If we set the header reset the origin pub args. + if hset { + c.pa = pa + } } + updateStats() return didDeliver, queues } +// Check and swap accounts on a client info header destined across a leafnode. +func (c *client) checkLeafClientInfoHeader(msg []byte) (dmsg []byte, setHdr bool) { + if c.pa.hdr < 0 || len(msg) < c.pa.hdr { + return msg, false + } + cir := sliceHeader(ClientInfoHdr, msg[:c.pa.hdr]) + if len(cir) == 0 { + return msg, false + } + + dmsg = msg + + var ci ClientInfo + if err := json.Unmarshal(cir, &ci); err == nil { + if v, _ := c.srv.leafRemoteAccounts.Load(ci.Account); v != nil { + remoteAcc := v.(string) + if ci.Account != remoteAcc { + ci.Account = remoteAcc + if b, _ := json.Marshal(ci); b != nil { + dmsg, setHdr = c.setHeader(ClientInfoHdr, bytesToString(b), msg), true + } + } + } + } + return dmsg, setHdr +} + func (c *client) pubPermissionViolation(subject []byte) { - c.sendErr(fmt.Sprintf("Permissions Violation for Publish to %q", subject)) + errTxt := fmt.Sprintf("Permissions Violation for Publish to %q", subject) + if mt, _ := c.isMsgTraceEnabled(); mt != nil { + mt.setIngressError(errTxt) + } + c.sendErr(errTxt) c.Errorf("Publish Violation - %s, Subject %q", c.getAuthUser(), subject) } @@ -4038,10 +5442,22 @@ func (c *client) subPermissionViolation(sub *subscription) { } func (c *client) replySubjectViolation(reply []byte) { - c.sendErr(fmt.Sprintf("Permissions Violation for Publish with Reply of %q", reply)) + errTxt := fmt.Sprintf("Permissions Violation for Publish with Reply of %q", reply) + if mt, _ := c.isMsgTraceEnabled(); mt != nil { + mt.setIngressError(errTxt) + } + c.sendErr(errTxt) c.Errorf("Publish Violation - %s, Reply %q", c.getAuthUser(), reply) } +func (c *client) maxTokensViolation(sub *subscription) { + errTxt := fmt.Sprintf("Permissions Violation for Subscription to %q, too many tokens", sub.subject) + logTxt := fmt.Sprintf("Subscription Violation Too Many Tokens - %s, Subject %q, SID %s", + c.getAuthUser(), sub.subject, sub.sid) + c.sendErr(errTxt) + c.Errorf(logTxt) +} + func (c *client) processPingTimer() { c.mu.Lock() c.ping.tmr = nil @@ -4051,34 +5467,42 @@ func (c *client) processPingTimer() { return } - c.Debugf("%s Ping Timer", c.typeString()) + c.Debugf("%s Ping Timer", c.kindString()) var sendPing bool - // If we have had activity within the PingInterval then - // there is no need to send a ping. This can be client data - // or if we received a ping from the other side. - pingInterval := c.srv.getOpts().PingInterval - if c.kind == GATEWAY { - pingInterval = adjustPingIntervalForGateway(pingInterval) - sendPing = true + opts := c.srv.getOpts() + pingInterval := opts.PingInterval + if c.kind == ROUTER && opts.Cluster.PingInterval > 0 { + pingInterval = opts.Cluster.PingInterval } + if c.isWebsocket() && opts.Websocket.PingInterval > 0 { + pingInterval = opts.Websocket.PingInterval + } + pingInterval = adjustPingInterval(c.kind, pingInterval) now := time.Now() needRTT := c.rtt == 0 || now.Sub(c.rttStart) > DEFAULT_RTT_MEASUREMENT_INTERVAL - // Do not delay PINGs for GATEWAY connections. - if c.kind != GATEWAY { - if delta := now.Sub(c.last); delta < pingInterval && !needRTT { - c.Debugf("Delaying PING due to client activity %v ago", delta.Round(time.Second)) - } else if delta := now.Sub(c.ping.last); delta < pingInterval && !needRTT { - c.Debugf("Delaying PING due to remote ping %v ago", delta.Round(time.Second)) + // Do not delay PINGs for ROUTER, GATEWAY or spoke LEAF connections. + if c.kind == ROUTER || c.kind == GATEWAY || c.isSpokeLeafNode() { + sendPing = true + } else { + // If we received client data or a ping from the other side within the PingInterval, + // then there is no need to send a ping. + if delta := now.Sub(c.lastIn); delta < pingInterval && !needRTT { + c.Debugf("Delaying PING due to remote client data or ping %v ago", delta.Round(time.Second)) } else { sendPing = true } } + if sendPing { // Check for violation - if c.ping.out+1 > c.srv.getOpts().MaxPingsOut { + maxPingsOut := opts.MaxPingsOut + if c.kind == ROUTER && opts.Cluster.MaxPingsOut > 0 { + maxPingsOut = opts.Cluster.MaxPingsOut + } + if c.ping.out+1 > maxPingsOut { c.Debugf("Stale Client Connection - Closing") c.enqueueProto([]byte(fmt.Sprintf(errProto, "Stale Connection"))) c.mu.Unlock() @@ -4094,24 +5518,53 @@ func (c *client) processPingTimer() { c.mu.Unlock() } -// Returns the smallest value between the given `d` and `gatewayMaxPingInterval` durations. -// Invoked for connections known to be of GATEWAY type. -func adjustPingIntervalForGateway(d time.Duration) time.Duration { - if d > gatewayMaxPingInterval { - return gatewayMaxPingInterval +// Returns the smallest value between the given `d` and some max value +// based on the connection kind. +func adjustPingInterval(kind int, d time.Duration) time.Duration { + switch kind { + case ROUTER: + if d > routeMaxPingInterval { + return routeMaxPingInterval + } + case GATEWAY: + if d > gatewayMaxPingInterval { + return gatewayMaxPingInterval + } } return d } +// This is used when a connection cannot yet start to send PINGs because +// the remote would not be able to handle them (case of compression, +// or outbound gateway, etc...), but we still want to close the connection +// if the timer has not been reset by the time we reach the time equivalent +// to have sent the max number of pings. +// +// Lock should be held +func (c *client) watchForStaleConnection(pingInterval time.Duration, pingMax int) { + c.ping.tmr = time.AfterFunc(pingInterval*time.Duration(pingMax+1), func() { + c.mu.Lock() + c.Debugf("Stale Client Connection - Closing") + c.enqueueProto([]byte(fmt.Sprintf(errProto, "Stale Connection"))) + c.mu.Unlock() + c.closeConnection(StaleConnection) + }) +} + // Lock should be held func (c *client) setPingTimer() { if c.srv == nil { return } - d := c.srv.getOpts().PingInterval - if c.kind == GATEWAY { - d = adjustPingIntervalForGateway(d) + opts := c.srv.getOpts() + d := opts.PingInterval + if c.kind == ROUTER && opts.Cluster.PingInterval > 0 { + d = opts.Cluster.PingInterval } + if c.isWebsocket() && opts.Websocket.PingInterval > 0 { + d = opts.Websocket.PingInterval + } + d = adjustPingInterval(c.kind, d) c.ping.tmr = time.AfterFunc(d, c.processPingTimer) } @@ -4124,6 +5577,14 @@ func (c *client) clearPingTimer() { c.ping.tmr = nil } +func (c *client) clearTlsToTimer() { + if c.tlsTo == nil { + return + } + c.tlsTo.Stop() + c.tlsTo = nil +} + // Lock should be held func (c *client) setAuthTimer(d time.Duration) { c.atmr = time.AfterFunc(d, c.authTimeout) @@ -4150,10 +5611,29 @@ func (c *client) awaitingAuth() bool { // We will lock on entry. func (c *client) setExpirationTimer(d time.Duration) { c.mu.Lock() - c.atmr = time.AfterFunc(d, c.authExpired) + c.setExpirationTimerUnlocked(d) c.mu.Unlock() } +// This will set the atmr for the JWT expiration time. client lock should be held before call +func (c *client) setExpirationTimerUnlocked(d time.Duration) { + c.atmr = time.AfterFunc(d, c.authExpired) + // This is an JWT expiration. + if c.flags.isSet(connectReceived) { + c.expires = time.Now().Add(d).Truncate(time.Second) + } +} + +// Return when this client expires via a claim, or 0 if not set. +func (c *client) claimExpiration() time.Duration { + c.mu.Lock() + defer c.mu.Unlock() + if c.expires.IsZero() { + return 0 + } + return time.Until(c.expires).Truncate(time.Second) +} + // Possibly flush the connection and then close the low level connection. // The boolean `minimalFlush` indicates if the flush operation should have a // minimal write deadline. @@ -4170,31 +5650,51 @@ func (c *client) flushAndClose(minimalFlush bool) { } c.flushOutbound() } - c.out.p, c.out.s = nil, nil + for i := range c.out.nb { + nbPoolPut(c.out.nb[i]) + } + c.out.nb = nil + // We can't touch c.out.wnb when a flushOutbound is in progress since it + // is accessed outside the lock there. If in progress, the cleanup will be + // done in flushOutbound when detecting that connection is closed. + if !c.flags.isSet(flushOutbound) { + for i := range c.out.wnb { + nbPoolPut(c.out.wnb[i]) + } + c.out.wnb = nil + } + // This seem to be important (from experimentation) for the GC to release + // the connection. + c.out.sg = nil - // Close the low level connection. WriteDeadline need to be set - // in case this is a TLS connection. + // Close the low level connection. if c.nc != nil { - c.nc.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) - c.nc.Close() + // Starting with Go 1.16, the low level close will set its own deadline + // of 5 seconds, so setting our own deadline does not work. Instead, + // we will close the TLS connection in separate go routine. + nc := c.nc c.nc = nil + if _, ok := nc.(*tls.Conn); ok { + go func() { nc.Close() }() + } else { + nc.Close() + } } } -func (c *client) typeString() string { - switch c.kind { - case CLIENT: - return "Client" - case ROUTER: - return "Router" - case GATEWAY: - return "Gateway" - case LEAF: - return "Leafnode" - case JETSTREAM: - return "JetStream" - case ACCOUNT: - return "Account" +var kindStringMap = map[int]string{ + CLIENT: "Client", + ROUTER: "Router", + GATEWAY: "Gateway", + LEAF: "Leafnode", + JETSTREAM: "JetStream", + ACCOUNT: "Account", + SYSTEM: "System", +} + +func (c *client) kindString() string { + if kindStringVal, ok := kindStringMap[c.kind]; ok { + return kindStringVal } return "Unknown Type" } @@ -4204,12 +5704,19 @@ func (c *client) typeString() string { // an older one. func (c *client) swapAccountAfterReload() { c.mu.Lock() - defer c.mu.Unlock() - if c.srv == nil { + srv := c.srv + an := c.acc.GetName() + c.mu.Unlock() + if srv == nil { return } - acc, _ := c.srv.LookupAccount(c.acc.Name) - c.acc = acc + if acc, _ := srv.LookupAccount(an); acc != nil { + c.mu.Lock() + if c.acc != acc { + c.acc = acc + } + c.mu.Unlock() + } } // processSubsOnConfigReload removes any subscriptions the client has that are no @@ -4246,7 +5753,7 @@ func (c *client) processSubsOnConfigReload(awcsti map[string]struct{}) { // Just checking to rebuild mperms under the lock, will collect removed though here. // Only collect under subs array of canSubscribe and checkAcc true. canSub := c.canSubscribe(string(sub.subject)) - canQSub := sub.queue != nil && c.canQueueSubscribe(string(sub.subject), string(sub.queue)) + canQSub := sub.queue != nil && c.canSubscribe(string(sub.subject), string(sub.queue)) if !canSub && !canQSub { removed = append(removed, sub) @@ -4296,6 +5803,7 @@ func (c *client) closeConnection(reason ClosedState) { c.flags.set(closeConnection) c.clearAuthTimer() c.clearPingTimer() + c.clearTlsToTimer() c.markConnAsClosed(reason) // Unblock anyone who is potentially stalled waiting on us. @@ -4304,13 +5812,30 @@ func (c *client) closeConnection(reason ClosedState) { c.out.stc = nil } + // If we have remote latency tracking running shut that down. + if c.rrTracking != nil { + c.rrTracking.ptmr.Stop() + c.rrTracking = nil + } + + // If we are shutting down, no need to do all the accounting on subs, etc. + // During LDM we'll still do the accounting, otherwise account limits could close others after this reconnects. + if reason == ServerShutdown && c.srv.isShuttingDown() { + s := c.srv + c.mu.Unlock() + if s != nil { + // Unregister + s.removeClient(c) + } + return + } + var ( - connectURLs []string - wsConnectURLs []string - kind = c.kind - srv = c.srv - noReconnect = c.flags.isSet(noReconnect) - acc = c.acc + kind = c.kind + srv = c.srv + noReconnect = c.flags.isSet(noReconnect) + acc = c.acc + spoke bool ) // Snapshot for use if we are a client connection. @@ -4320,23 +5845,16 @@ func (c *client) closeConnection(reason ClosedState) { if kind == CLIENT || kind == LEAF || kind == JETSTREAM { var _subs [32]*subscription subs = _subs[:0] + // Do not set c.subs to nil or delete the sub from c.subs here because + // it will be needed in saveClosedClient (which has been started as a + // go routine in markConnAsClosed). Cleanup will be done there. for _, sub := range c.subs { // Auto-unsubscribe subscriptions must be unsubscribed forcibly. sub.max = 0 sub.close() subs = append(subs, sub) } - } - - if c.route != nil { - connectURLs = c.route.connectURLs - wsConnectURLs = c.route.wsConnURLs - } - - // If we have remote latency tracking running shut that down. - if c.rrTracking != nil { - c.rrTracking.ptmr.Stop() - c.rrTracking = nil + spoke = c.isSpokeLeafNode() } c.mu.Unlock() @@ -4345,56 +5863,72 @@ func (c *client) closeConnection(reason ClosedState) { if acc != nil && (kind == CLIENT || kind == LEAF || kind == JETSTREAM) { acc.sl.RemoveBatch(subs) } else if kind == ROUTER { - go c.removeRemoteSubs() + c.removeRemoteSubs() } if srv != nil { - // If this is a route that disconnected, possibly send an INFO with - // the updated list of connect URLs to clients that know how to - // handle async INFOs. - if (len(connectURLs) > 0 || len(wsConnectURLs) > 0) && !srv.getOpts().Cluster.NoAdvertise { - srv.removeConnectURLsAndSendINFOToClients(connectURLs, wsConnectURLs) - } - // Unregister srv.removeClient(c) - // Update remote subscriptions. - if acc != nil && (kind == CLIENT || kind == LEAF) { - qsubs := map[string]*qsub{} - for _, sub := range subs { - // Call unsubscribe here to cleanup shadow subscriptions and such. - c.unsubscribe(acc, sub, true, false) - // Update route as normal for a normal subscriber. - if sub.queue == nil { - srv.updateRouteSubscriptionMap(acc, sub, -1) - srv.updateLeafNodes(acc, sub, -1) - } else { - // We handle queue subscribers special in case we - // have a bunch we can just send one update to the - // connected routes. - key := string(sub.subject) + " " + string(sub.queue) - if esub, ok := qsubs[key]; ok { - esub.n++ + if acc != nil { + // Update remote subscriptions. + if kind == CLIENT || kind == LEAF || kind == JETSTREAM { + qsubs := map[string]*qsub{} + for _, sub := range subs { + // Call unsubscribe here to cleanup shadow subscriptions and such. + c.unsubscribe(acc, sub, true, false) + // Update route as normal for a normal subscriber. + if sub.queue == nil { + if !spoke { + srv.updateRouteSubscriptionMap(acc, sub, -1) + if srv.gateway.enabled { + srv.gatewayUpdateSubInterest(acc.Name, sub, -1) + } + } + acc.updateLeafNodes(sub, -1) } else { - qsubs[key] = &qsub{sub, 1} + // We handle queue subscribers special in case we + // have a bunch we can just send one update to the + // connected routes. + num := int32(1) + if kind == LEAF { + num = sub.qw + } + key := keyFromSub(sub) + if esub, ok := qsubs[key]; ok { + esub.n += num + } else { + qsubs[key] = &qsub{sub, num} + } } } - if srv.gateway.enabled { - srv.gatewayUpdateSubInterest(acc.Name, sub, -1) + // Process any qsubs here. + for _, esub := range qsubs { + if !spoke { + srv.updateRouteSubscriptionMap(acc, esub.sub, -(esub.n)) + if srv.gateway.enabled { + srv.gatewayUpdateSubInterest(acc.Name, esub.sub, -(esub.n)) + } + } + acc.updateLeafNodes(esub.sub, -(esub.n)) } } - // Process any qsubs here. - for _, esub := range qsubs { - srv.updateRouteSubscriptionMap(acc, esub.sub, -(esub.n)) - srv.updateLeafNodes(acc, esub.sub, -(esub.n)) - } - if prev := acc.removeClient(c); prev == 1 && srv != nil { + // Always remove from the account, otherwise we can leak clients. + // Note that SYSTEM and ACCOUNT types from above cleanup their own subs. + if prev := acc.removeClient(c); prev == 1 { srv.decActiveAccounts() } } } + // Now that we are done with subscriptions, clear the field so that the + // connection can be released and gc'ed. + if kind == CLIENT || kind == LEAF { + c.mu.Lock() + c.subs = nil + c.mu.Unlock() + } + // Don't reconnect connections that have been marked with // the no reconnect flag. if noReconnect { @@ -4412,6 +5946,7 @@ func (c *client) reconnect() { gwName string gwIsOutbound bool gwCfg *gatewayCfg + leafCfg *leafNodeCfg ) c.mu.Lock() @@ -4422,47 +5957,65 @@ func (c *client) reconnect() { return } if c.route != nil { - retryImplicit = c.route.retry + // A route is marked as solicited if it was given an URL to connect to, + // which would be the case even with implicit (due to gossip), so mark this + // as a retry for a route that is solicited and not explicit. + retryImplicit = c.route.retry || (c.route.didSolicit && c.route.routeType == Implicit) } kind := c.kind - if kind == GATEWAY { + switch kind { + case GATEWAY: gwName = c.gw.name gwIsOutbound = c.gw.outbound gwCfg = c.gw.cfg + case LEAF: + if c.isSolicitedLeafNode() { + leafCfg = c.leaf.remote + } } srv := c.srv c.mu.Unlock() // Check for a solicited route. If it was, start up a reconnect unless // we are already connected to the other end. - if c.isSolicitedRoute() || retryImplicit { + if didSolicit := c.isSolicitedRoute(); didSolicit || retryImplicit { + srv.mu.Lock() + defer srv.mu.Unlock() + // Capture these under lock c.mu.Lock() rid := c.route.remoteID rtype := c.route.routeType rurl := c.route.url + accName := string(c.route.accName) + checkRID := accName == _EMPTY_ && srv.getOpts().Cluster.PoolSize < 1 && rid != _EMPTY_ c.mu.Unlock() - srv.mu.Lock() - defer srv.mu.Unlock() - // It is possible that the server is being shutdown. // If so, don't try to reconnect - if !srv.running { + if !srv.isRunning() { return } - if rid != "" && srv.remotes[rid] != nil { - srv.Debugf("Not attempting reconnect for solicited route, already connected to \"%s\"", rid) + if checkRID && srv.routes[rid] != nil { + // This is the case of "no pool". Make sure that the registered one + // is upgraded to solicited if the connection trying to reconnect + // was a solicited one. + if didSolicit { + if remote := srv.routes[rid][0]; remote != nil { + upgradeRouteToSolicited(remote, rurl, rtype) + } + } + srv.Debugf("Not attempting reconnect for solicited route, already connected to %q", rid) return } else if rid == srv.info.ID { - srv.Debugf("Detected route to self, ignoring %q", rurl) + srv.Debugf("Detected route to self, ignoring %q", rurl.Redacted()) return } else if rtype != Implicit || retryImplicit { - srv.Debugf("Attempting reconnect for solicited route \"%s\"", rurl) + srv.Debugf("Attempting reconnect for solicited route %q", rurl.Redacted()) // Keep track of this go-routine so we can wait for it on // server shutdown. - srv.startGoRoutine(func() { srv.reConnectToRoute(rurl, rtype) }) + srv.startGoRoutine(func() { srv.reConnectToRoute(rurl, rtype, accName) }) } } else if srv != nil && kind == GATEWAY && gwIsOutbound { if gwCfg != nil { @@ -4474,9 +6027,9 @@ func (c *client) reconnect() { } else { srv.Debugf("Gateway %q not in configuration, not attempting reconnect", gwName) } - } else if c.isSolicitedLeafNode() { + } else if leafCfg != nil { // Check if this is a solicited leaf node. Start up a reconnect. - srv.startGoRoutine(func() { srv.reConnectToRemoteLeafNode(c.leaf.remote) }) + srv.startGoRoutine(func() { srv.reConnectToRemoteLeafNode(leafCfg) }) } } @@ -4512,9 +6065,14 @@ func (c *client) getAccAndResultFromCache() (*Account, *SublistResult) { // Check our cache. if pac, ok = c.in.pacache[string(c.pa.pacache)]; ok { // Check the genid to see if it's still valid. - if genid := atomic.LoadUint64(&pac.acc.sl.genid); genid != pac.genid { + // Since v2.10.0, the config reload of accounts has been fixed + // and an account's sublist pointer should not change, so no need to + // lock to access it. + sl := pac.acc.sl + + if genid := atomic.LoadUint64(&sl.genid); genid != pac.genid { ok = false - delete(c.in.pacache, string(c.pa.pacache)) + c.in.pacache = make(map[string]*perAccountCache) } else { acc = pac.acc r = pac.results @@ -4522,21 +6080,28 @@ func (c *client) getAccAndResultFromCache() (*Account, *SublistResult) { } if !ok { - // Match correct account and sublist. - if acc, _ = c.srv.LookupAccount(string(c.pa.account)); acc == nil { - return nil, nil + if c.kind == ROUTER && len(c.route.accName) > 0 { + if acc = c.acc; acc == nil { + return nil, nil + } + } else { + // Match correct account and sublist. + if acc, _ = c.srv.LookupAccount(bytesToString(c.pa.account)); acc == nil { + return nil, nil + } } + sl := acc.sl // Match against the account sublist. - r = acc.sl.Match(string(c.pa.subject)) - - // Store in our cache - c.in.pacache[string(c.pa.pacache)] = &perAccountCache{acc, r, atomic.LoadUint64(&acc.sl.genid)} + r = sl.MatchBytes(c.pa.subject) // Check if we need to prune. - if len(c.in.pacache) > maxPerAccountCacheSize { + if len(c.in.pacache) >= maxPerAccountCacheSize { c.prunePerAccountCache() } + + // Store in our cache,make sure to do so after we prune. + c.in.pacache[string(c.pa.pacache)] = &perAccountCache{acc, r, atomic.LoadUint64(&sl.genid)} } return acc, r } @@ -4585,48 +6150,219 @@ func (c *client) pruneClosedSubFromPerAccountCache() { } } +// Returns our service account for this request. +func (ci *ClientInfo) serviceAccount() string { + if ci == nil { + return _EMPTY_ + } + if ci.Service != _EMPTY_ { + return ci.Service + } + return ci.Account +} + +// Add in our server and cluster information to this client info. +func (c *client) addServerAndClusterInfo(ci *ClientInfo) { + if ci == nil { + return + } + // Server + if c.kind != LEAF { + ci.Server = c.srv.Name() + } else if c.kind == LEAF { + ci.Server = c.leaf.remoteServer + } + // Cluster + ci.Cluster = c.srv.cachedClusterName() + // If we have gateways fill in cluster alternates. + // These will be in RTT asc order. + if c.srv.gateway.enabled { + var gws []*client + c.srv.getOutboundGatewayConnections(&gws) + for _, c := range gws { + c.mu.Lock() + cn := c.gw.name + c.mu.Unlock() + ci.Alternates = append(ci.Alternates, cn) + } + } +} + // Grabs the information for this client. -func (c *client) getClientInfo(detailed bool) LatencyClient { - var lc LatencyClient - if c == nil || c.kind != CLIENT { - return lc +func (c *client) getClientInfo(detailed bool) *ClientInfo { + if c == nil || (c.kind != CLIENT && c.kind != LEAF && c.kind != JETSTREAM && c.kind != ACCOUNT) { + return nil + } + + // Result + var ci ClientInfo + + if detailed { + c.addServerAndClusterInfo(&ci) } - // Server name. Defaults to server ID if not set explicitly. - sn := c.srv.Name() c.mu.Lock() - // Defaults for all are RTT and Account. - lc.Account = accForClient(c) - lc.RTT = c.rtt - // Detailed is opt in. + // RTT and Account are always added. + ci.Account = accForClient(c) + ci.RTT = c.rtt + // Detailed signals additional opt in. if detailed { - lc.Start = c.start.UTC() - lc.IP = c.host - lc.CID = c.cid - lc.Name = c.opts.Name - lc.User = c.getRawAuthUser() - lc.Lang = c.opts.Lang - lc.Version = c.opts.Version - lc.Server = sn + ci.Start = &c.start + ci.Host = c.host + ci.ID = c.cid + ci.Name = c.opts.Name + ci.User = c.getRawAuthUser() + ci.Lang = c.opts.Lang + ci.Version = c.opts.Version + ci.Jwt = c.opts.JWT + ci.IssuerKey = issuerForClient(c) + ci.NameTag = c.nameTag + ci.Tags = c.tags + ci.Kind = c.kindString() + ci.ClientType = c.clientTypeString() + } + c.mu.Unlock() + return &ci +} + +func (c *client) doTLSServerHandshake(typ string, tlsConfig *tls.Config, timeout float64, pCerts PinnedCertSet) error { + _, err := c.doTLSHandshake(typ, false, nil, tlsConfig, _EMPTY_, timeout, pCerts) + return err +} + +func (c *client) doTLSClientHandshake(typ string, url *url.URL, tlsConfig *tls.Config, tlsName string, timeout float64, pCerts PinnedCertSet) (bool, error) { + return c.doTLSHandshake(typ, true, url, tlsConfig, tlsName, timeout, pCerts) +} + +// Performs either server or client side (if solicit is true) TLS Handshake. +// On error, the TLS handshake error has been logged and the connection +// has been closed. +// +// Lock is held on entry. +func (c *client) doTLSHandshake(typ string, solicit bool, url *url.URL, tlsConfig *tls.Config, tlsName string, timeout float64, pCerts PinnedCertSet) (bool, error) { + var host string + var resetTLSName bool + var err error + + // Capture kind for some debug/error statements. + kind := c.kind + + // If we solicited, we will act like the client, otherwise the server. + if solicit { + c.Debugf("Starting TLS %s client handshake", typ) + if tlsConfig.ServerName == _EMPTY_ { + // If the given url is a hostname, use this hostname for the + // ServerName. If it is an IP, use the cfg's tlsName. If none + // is available, resort to current IP. + host = url.Hostname() + if tlsName != _EMPTY_ && net.ParseIP(host) != nil { + host = tlsName + } + tlsConfig.ServerName = host + } + c.nc = tls.Client(c.nc, tlsConfig) + } else { + if kind == CLIENT { + c.Debugf("Starting TLS client connection handshake") + } else { + c.Debugf("Starting TLS %s server handshake", typ) + } + c.nc = tls.Server(c.nc, tlsConfig) } + + conn := c.nc.(*tls.Conn) + + // Setup the timeout + ttl := secondsToDuration(timeout) + c.tlsTo = time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) + conn.SetReadDeadline(time.Now().Add(ttl)) + c.mu.Unlock() - return lc + if err = conn.Handshake(); err != nil { + if solicit { + // Based on type of error, possibly clear the saved tlsName + // See: https://github.com/nats-io/nats-server/issues/1256 + // NOTE: As of Go 1.20, the HostnameError is wrapped so cannot + // type assert to check directly. + var hostnameErr x509.HostnameError + if errors.As(err, &hostnameErr) { + if host == tlsName { + resetTLSName = true + } + } + } + } else if !c.matchesPinnedCert(pCerts) { + err = ErrCertNotPinned + } + + if err != nil { + var detail string + var subjs []string + if ve, ok := err.(*tls.CertificateVerificationError); ok { + for _, cert := range ve.UnverifiedCertificates { + fp := sha256.Sum256(cert.Raw) + fph := hex.EncodeToString(fp[:]) + subjs = append(subjs, fmt.Sprintf("%s SHA-256: %s", cert.Subject.String(), fph)) + } + } + if len(subjs) > 0 { + detail = fmt.Sprintf(" (%s)", strings.Join(subjs, "; ")) + } + if kind == CLIENT { + c.Errorf("TLS handshake error: %v%s", err, detail) + } else { + c.Errorf("TLS %s handshake error: %v%s", typ, err, detail) + } + c.closeConnection(TLSHandshakeError) + + // Grab the lock before returning since the caller was holding the lock on entry + c.mu.Lock() + // Returning any error is fine. Since the connection is closed ErrConnectionClosed + // is appropriate. + return resetTLSName, ErrConnectionClosed + } + + // Reset the read deadline + conn.SetReadDeadline(time.Time{}) + + // Re-Grab lock + c.mu.Lock() + + // To be consistent with client, set this flag to indicate that handshake is done + c.flags.set(handshakeComplete) + + // The connection still may have been closed on success handshake due + // to a race with tls timeout. If that the case, return error indicating + // that the connection is closed. + if c.isClosed() { + err = ErrConnectionClosed + } + + return false, err } -// getRAwAuthUser returns the raw auth user for the client. +// getRawAuthUserLock returns the raw auth user for the client. +// Will acquire the client lock. +func (c *client) getRawAuthUserLock() string { + c.mu.Lock() + defer c.mu.Unlock() + return c.getRawAuthUser() +} + +// getRawAuthUser returns the raw auth user for the client. // Lock should be held. func (c *client) getRawAuthUser() string { switch { - case c.opts.Nkey != "": + case c.opts.Nkey != _EMPTY_: return c.opts.Nkey - case c.opts.Username != "": + case c.opts.Username != _EMPTY_: return c.opts.Username - case c.opts.JWT != "": + case c.opts.JWT != _EMPTY_: return c.pubKey - case c.opts.Token != "": - return c.opts.Token + case c.opts.Token != _EMPTY_: + return "[REDACTED]" default: - return "" + return _EMPTY_ } } @@ -4634,12 +6370,14 @@ func (c *client) getRawAuthUser() string { // Lock should be held. func (c *client) getAuthUser() string { switch { - case c.opts.Nkey != "": + case c.opts.Nkey != _EMPTY_: return fmt.Sprintf("Nkey %q", c.opts.Nkey) - case c.opts.Username != "": + case c.opts.Username != _EMPTY_: return fmt.Sprintf("User %q", c.opts.Username) - case c.opts.JWT != "": + case c.opts.JWT != _EMPTY_: return fmt.Sprintf("JWT User %q", c.pubKey) + case c.opts.Token != _EMPTY_: + return fmt.Sprintf("Token %q", "[REDACTED]") default: return `User "N/A"` } @@ -4659,7 +6397,10 @@ func convertAllowedConnectionTypes(cts []string) (map[string]struct{}, error) { for _, i := range cts { i = strings.ToUpper(i) switch i { - case jwt.ConnectionTypeStandard, jwt.ConnectionTypeWebsocket, jwt.ConnectionTypeLeafnode, jwt.ConnectionTypeMqtt: + case jwt.ConnectionTypeStandard, jwt.ConnectionTypeWebsocket, + jwt.ConnectionTypeLeafnode, jwt.ConnectionTypeLeafnodeWS, + jwt.ConnectionTypeMqtt, jwt.ConnectionTypeMqttWS, + jwt.ConnectionTypeInProcess: m[i] = struct{}{} default: unknown = append(unknown, i) @@ -4686,14 +6427,26 @@ func (c *client) connectionTypeAllowed(acts map[string]struct{}) bool { case CLIENT: switch c.clientType() { case NATS: - want = jwt.ConnectionTypeStandard + if c.iproc { + want = jwt.ConnectionTypeInProcess + } else { + want = jwt.ConnectionTypeStandard + } case WS: want = jwt.ConnectionTypeWebsocket case MQTT: - want = jwt.ConnectionTypeMqtt + if c.isWebsocket() { + want = jwt.ConnectionTypeMqttWS + } else { + want = jwt.ConnectionTypeMqtt + } } case LEAF: - want = jwt.ConnectionTypeLeafnode + if c.isWebsocket() { + want = jwt.ConnectionTypeLeafnodeWS + } else { + want = jwt.ConnectionTypeLeafnode + } } _, ok := acts[want] return ok @@ -4710,27 +6463,84 @@ func (c *client) Error(err error) { c.srv.Errors(c, err) } -func (c *client) Errorf(format string, v ...interface{}) { +func (c *client) Errorf(format string, v ...any) { format = fmt.Sprintf("%s - %s", c, format) c.srv.Errorf(format, v...) } -func (c *client) Debugf(format string, v ...interface{}) { +func (c *client) Debugf(format string, v ...any) { format = fmt.Sprintf("%s - %s", c, format) c.srv.Debugf(format, v...) } -func (c *client) Noticef(format string, v ...interface{}) { +func (c *client) Noticef(format string, v ...any) { format = fmt.Sprintf("%s - %s", c, format) c.srv.Noticef(format, v...) } -func (c *client) Tracef(format string, v ...interface{}) { +func (c *client) Tracef(format string, v ...any) { format = fmt.Sprintf("%s - %s", c, format) c.srv.Tracef(format, v...) } -func (c *client) Warnf(format string, v ...interface{}) { +func (c *client) Warnf(format string, v ...any) { format = fmt.Sprintf("%s - %s", c, format) c.srv.Warnf(format, v...) } + +func (c *client) rateLimitFormatWarnf(format string, v ...any) { + if _, loaded := c.srv.rateLimitLogging.LoadOrStore(format, time.Now()); loaded { + return + } + statement := fmt.Sprintf(format, v...) + c.Warnf("%s", statement) +} + +func (c *client) RateLimitWarnf(format string, v ...any) { + // Do the check before adding the client info to the format... + statement := fmt.Sprintf(format, v...) + if _, loaded := c.srv.rateLimitLogging.LoadOrStore(statement, time.Now()); loaded { + return + } + c.Warnf("%s", statement) +} + +// Set the very first PING to a lower interval to capture the initial RTT. +// After that the PING interval will be set to the user defined value. +// Client lock should be held. +func (c *client) setFirstPingTimer() { + s := c.srv + if s == nil { + return + } + opts := s.getOpts() + d := opts.PingInterval + + if c.kind == ROUTER && opts.Cluster.PingInterval > 0 { + d = opts.Cluster.PingInterval + } + if c.isWebsocket() && opts.Websocket.PingInterval > 0 { + d = opts.Websocket.PingInterval + } + if !opts.DisableShortFirstPing { + if c.kind != CLIENT { + if d > firstPingInterval { + d = firstPingInterval + } + d = adjustPingInterval(c.kind, d) + } else if d > firstClientPingInterval { + d = firstClientPingInterval + } + } + // We randomize the first one by an offset up to 20%, e.g. 2m ~= max 24s. + addDelay := rand.Int63n(int64(d / 5)) + d += time.Duration(addDelay) + // In the case of ROUTER/LEAF and when compression is configured, it is possible + // that this timer was already set, but just to detect a stale connection + // since we have to delay the first PING after compression negotiation + // occurred. + if c.ping.tmr != nil { + c.ping.tmr.Stop() + } + c.ping.tmr = time.AfterFunc(d, c.processPingTimer) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/const.go b/vendor/github.com/nats-io/nats-server/v2/server/const.go index bcb1f43..e2b6249 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/const.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/const.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,6 +14,8 @@ package server import ( + "regexp" + "runtime/debug" "time" ) @@ -29,18 +31,42 @@ const ( // private for now commandLDMode = Command("ldm") + commandTerm = Command("term") ) var ( - // gitCommit injected at build - gitCommit string + // gitCommit and serverVersion injected at build. + gitCommit, serverVersion string // trustedKeys is a whitespace separated array of trusted operator's public nkeys. trustedKeys string + // SemVer regexp to validate the VERSION. + semVerRe = regexp.MustCompile(`^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) ) +// formatRevision formats a VCS revision string for display. +func formatRevision(revision string) string { + if len(revision) >= 7 { + return revision[:7] + } + return revision +} + +func init() { + // Use build info if present, it would be if building using 'go build .' + // or when using a release. + if info, ok := debug.ReadBuildInfo(); ok { + for _, setting := range info.Settings { + switch setting.Key { + case "vcs.revision": + gitCommit = formatRevision(setting.Value) + } + } + } +} + const ( // VERSION is the current version for the server. - VERSION = "2.2.0-beta.35" + VERSION = "2.11.12" // PROTO is the currently supported protocol. // 0 was the original @@ -67,6 +93,11 @@ const ( // something different if > 1MB payloads are needed. MAX_PAYLOAD_SIZE = (1024 * 1024) + // MAX_PAYLOAD_MAX_SIZE is the size at which the server will warn about + // max_payload being too high. In the future, the server may enforce/reject + // max_payload above this value. + MAX_PAYLOAD_MAX_SIZE = (8 * 1024 * 1024) + // MAX_PENDING_SIZE is the maximum outbound pending bytes per client. MAX_PENDING_SIZE = (64 * 1024 * 1024) @@ -76,10 +107,16 @@ const ( // TLS_TIMEOUT is the TLS wait time. TLS_TIMEOUT = 2 * time.Second + // DEFAULT_TLS_HANDSHAKE_FIRST_FALLBACK_DELAY is the default amount of + // time for the server to wait for the TLS handshake with a client to + // be initiated before falling back to sending the INFO protocol first. + // See TLSHandshakeFirst and TLSHandshakeFirstFallback options. + DEFAULT_TLS_HANDSHAKE_FIRST_FALLBACK_DELAY = 50 * time.Millisecond + // AUTH_TIMEOUT is the authorization wait time. AUTH_TIMEOUT = 2 * time.Second - // DEFAULT_PING_INTERVAL is how often pings are sent to clients and routes. + // DEFAULT_PING_INTERVAL is how often pings are sent to clients, etc... DEFAULT_PING_INTERVAL = 2 * time.Minute // DEFAULT_PING_MAX_OUT is maximum allowed pings outstanding before disconnect. @@ -115,6 +152,9 @@ const ( // DEFAULT_ROUTE_DIAL Route dial timeout. DEFAULT_ROUTE_DIAL = 1 * time.Second + // DEFAULT_ROUTE_POOL_SIZE Route default pool size + DEFAULT_ROUTE_POOL_SIZE = 3 + // DEFAULT_LEAF_NODE_RECONNECT LeafNode reconnect interval. DEFAULT_LEAF_NODE_RECONNECT = time.Second @@ -124,6 +164,9 @@ const ( // PROTO_SNIPPET_SIZE is the default size of proto to print on parse errors. PROTO_SNIPPET_SIZE = 32 + // MAX_CONTROL_LINE_SNIPPET_SIZE is the default size of proto to print on max control line errors. + MAX_CONTROL_LINE_SNIPPET_SIZE = 128 + // MAX_MSG_ARGS Maximum possible number of arguments from MSG proto. MAX_MSG_ARGS = 4 @@ -139,6 +182,9 @@ const ( // MAX_HPUB_ARGS Maximum possible number of arguments from HPUB proto. MAX_HPUB_ARGS = 4 + // MAX_RSUB_ARGS Maximum possible number of arguments from a RS+/LS+ proto. + MAX_RSUB_ARGS = 6 + // DEFAULT_MAX_CLOSED_CLIENTS is the maximum number of closed connections we hold onto. DEFAULT_MAX_CLOSED_CLIENTS = 10000 @@ -196,4 +242,7 @@ const ( // DEFAULT GLOBAL_ACCOUNT DEFAULT_GLOBAL_ACCOUNT = "$G" + + // DEFAULT_FETCH_TIMEOUT is the default time that the system will wait for an account fetch to return. + DEFAULT_ACCOUNT_FETCH_TIMEOUT = 1900 * time.Millisecond ) diff --git a/vendor/github.com/nats-io/nats-server/v2/server/consumer.go b/vendor/github.com/nats-io/nats-server/v2/server/consumer.go index 897bddd..fd275e1 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/consumer.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/consumer.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,61 +15,268 @@ package server import ( "bytes" - "crypto/rand" - "crypto/sha256" + "encoding/binary" "encoding/json" "errors" "fmt" - mrand "math/rand" + "math/rand" + "os" + "path/filepath" "reflect" - "sort" + "regexp" + "slices" "strconv" "strings" "sync" + "sync/atomic" "time" + "github.com/nats-io/nats-server/v2/server/avl" + "github.com/nats-io/nats-server/v2/server/gsl" "github.com/nats-io/nuid" "golang.org/x/time/rate" ) +// Headers sent with Request Timeout +const ( + JSPullRequestPendingMsgs = "Nats-Pending-Messages" + JSPullRequestPendingBytes = "Nats-Pending-Bytes" + JSPullRequestWrongPinID = "NATS/1.0 423 Nats-Wrong-Pin-Id\r\n\r\n" + JSPullRequestNatsPinId = "Nats-Pin-Id" +) + +var ( + validGroupName = regexp.MustCompile(`^[a-zA-Z0-9/_=-]{1,16}$`) +) + +// Headers sent when batch size was completed, but there were remaining bytes. +const JsPullRequestRemainingBytesT = "NATS/1.0 409 Batch Completed\r\n%s: %d\r\n%s: %d\r\n\r\n" + type ConsumerInfo struct { - Stream string `json:"stream_name"` - Name string `json:"name"` - Created time.Time `json:"created"` - Config ConsumerConfig `json:"config"` - Delivered SequencePair `json:"delivered"` - AckFloor SequencePair `json:"ack_floor"` - NumAckPending int `json:"num_ack_pending"` - NumRedelivered int `json:"num_redelivered"` - NumWaiting int `json:"num_waiting"` - NumPending uint64 `json:"num_pending"` + Stream string `json:"stream_name"` + Name string `json:"name"` + Created time.Time `json:"created"` + Config *ConsumerConfig `json:"config,omitempty"` + Delivered SequenceInfo `json:"delivered"` + AckFloor SequenceInfo `json:"ack_floor"` + NumAckPending int `json:"num_ack_pending"` + NumRedelivered int `json:"num_redelivered"` + NumWaiting int `json:"num_waiting"` + NumPending uint64 `json:"num_pending"` + Cluster *ClusterInfo `json:"cluster,omitempty"` + PushBound bool `json:"push_bound,omitempty"` + Paused bool `json:"paused,omitempty"` + PauseRemaining time.Duration `json:"pause_remaining,omitempty"` + // TimeStamp indicates when the info was gathered + TimeStamp time.Time `json:"ts"` + PriorityGroups []PriorityGroupState `json:"priority_groups,omitempty"` +} + +// consumerInfoClusterResponse is a response used in a cluster to communicate the consumer info +// back to the meta leader as part of a consumer list request. +type consumerInfoClusterResponse struct { + ConsumerInfo + OfflineReason string `json:"offline_reason,omitempty"` // Reporting when a consumer is offline. +} + +type PriorityGroupState struct { + Group string `json:"group"` + PinnedClientID string `json:"pinned_client_id,omitempty"` + PinnedTS time.Time `json:"pinned_ts,omitempty"` } type ConsumerConfig struct { - Durable string `json:"durable_name,omitempty"` - DeliverSubject string `json:"deliver_subject,omitempty"` - DeliverPolicy DeliverPolicy `json:"deliver_policy"` - OptStartSeq uint64 `json:"opt_start_seq,omitempty"` - OptStartTime *time.Time `json:"opt_start_time,omitempty"` - AckPolicy AckPolicy `json:"ack_policy"` - AckWait time.Duration `json:"ack_wait,omitempty"` - MaxDeliver int `json:"max_deliver,omitempty"` - FilterSubject string `json:"filter_subject,omitempty"` - ReplayPolicy ReplayPolicy `json:"replay_policy"` - RateLimit uint64 `json:"rate_limit_bps,omitempty"` // Bits per sec - SampleFrequency string `json:"sample_freq,omitempty"` - MaxWaiting int `json:"max_waiting,omitempty"` - MaxAckPending int `json:"max_ack_pending,omitempty"` - - // These are non public configuration options. - // If you add new options, check fileConsumerInfoJSON in order for them to - // be properly persisted/recovered, if needed. - allowNoInterest bool + Durable string `json:"durable_name,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + DeliverPolicy DeliverPolicy `json:"deliver_policy"` + OptStartSeq uint64 `json:"opt_start_seq,omitempty"` + OptStartTime *time.Time `json:"opt_start_time,omitempty"` + AckPolicy AckPolicy `json:"ack_policy"` + AckWait time.Duration `json:"ack_wait,omitempty"` + MaxDeliver int `json:"max_deliver,omitempty"` + BackOff []time.Duration `json:"backoff,omitempty"` + FilterSubject string `json:"filter_subject,omitempty"` + FilterSubjects []string `json:"filter_subjects,omitempty"` + ReplayPolicy ReplayPolicy `json:"replay_policy"` + RateLimit uint64 `json:"rate_limit_bps,omitempty"` // Bits per sec + SampleFrequency string `json:"sample_freq,omitempty"` + MaxWaiting int `json:"max_waiting,omitempty"` + MaxAckPending int `json:"max_ack_pending,omitempty"` + FlowControl bool `json:"flow_control,omitempty"` + HeadersOnly bool `json:"headers_only,omitempty"` + + // Pull based options. + MaxRequestBatch int `json:"max_batch,omitempty"` + MaxRequestExpires time.Duration `json:"max_expires,omitempty"` + MaxRequestMaxBytes int `json:"max_bytes,omitempty"` + + // Push based consumers. + DeliverSubject string `json:"deliver_subject,omitempty"` + DeliverGroup string `json:"deliver_group,omitempty"` + Heartbeat time.Duration `json:"idle_heartbeat,omitempty"` + + // Ephemeral inactivity threshold. + InactiveThreshold time.Duration `json:"inactive_threshold,omitempty"` + + // Generally inherited by parent stream and other markers, now can be configured directly. + Replicas int `json:"num_replicas"` + // Force memory storage. + MemoryStorage bool `json:"mem_storage,omitempty"` + + // Don't add to general clients. + Direct bool `json:"direct,omitempty"` + + // Metadata is additional metadata for the Consumer. + Metadata map[string]string `json:"metadata,omitempty"` + + // PauseUntil is for suspending the consumer until the deadline. + PauseUntil *time.Time `json:"pause_until,omitempty"` + + // Priority groups + PriorityGroups []string `json:"priority_groups,omitempty"` + PriorityPolicy PriorityPolicy `json:"priority_policy,omitempty"` + PinnedTTL time.Duration `json:"priority_timeout,omitempty"` +} + +// SequenceInfo has both the consumer and the stream sequence and last activity. +type SequenceInfo struct { + Consumer uint64 `json:"consumer_seq"` + Stream uint64 `json:"stream_seq"` + Last *time.Time `json:"last_active,omitempty"` } type CreateConsumerRequest struct { - Stream string `json:"stream_name"` - Config ConsumerConfig `json:"config"` + Stream string `json:"stream_name"` + Config ConsumerConfig `json:"config"` + Action ConsumerAction `json:"action"` + Pedantic bool `json:"pedantic,omitempty"` +} + +type ConsumerAction int + +const ( + ActionCreateOrUpdate ConsumerAction = iota + ActionUpdate + ActionCreate +) + +const ( + actionUpdateJSONString = `"update"` + actionCreateJSONString = `"create"` + actionCreateOrUpdateJSONString = `""` +) + +var ( + actionUpdateJSONBytes = []byte(actionUpdateJSONString) + actionCreateJSONBytes = []byte(actionCreateJSONString) + actionCreateOrUpdateJSONBytes = []byte(actionCreateOrUpdateJSONString) +) + +func (a ConsumerAction) String() string { + switch a { + case ActionCreateOrUpdate: + return actionCreateOrUpdateJSONString + case ActionCreate: + return actionCreateJSONString + case ActionUpdate: + return actionUpdateJSONString + } + return actionCreateOrUpdateJSONString +} + +func (a ConsumerAction) MarshalJSON() ([]byte, error) { + switch a { + case ActionCreate: + return actionCreateJSONBytes, nil + case ActionUpdate: + return actionUpdateJSONBytes, nil + case ActionCreateOrUpdate: + return actionCreateOrUpdateJSONBytes, nil + default: + return nil, fmt.Errorf("can not marshal %v", a) + } +} + +func (a *ConsumerAction) UnmarshalJSON(data []byte) error { + switch string(data) { + case actionCreateJSONString: + *a = ActionCreate + case actionUpdateJSONString: + *a = ActionUpdate + case actionCreateOrUpdateJSONString: + *a = ActionCreateOrUpdate + default: + return fmt.Errorf("unknown consumer action: %v", string(data)) + } + return nil +} + +// ConsumerNakOptions is for optional NAK values, e.g. delay. +type ConsumerNakOptions struct { + Delay time.Duration `json:"delay"` +} + +// PriorityPolicy determines policy for selecting messages based on priority. +type PriorityPolicy int + +const ( + // No priority policy. + PriorityNone PriorityPolicy = iota + // Clients will get the messages only if certain criteria are specified. + PriorityOverflow + // Single client takes over handling of the messages, while others are on standby. + PriorityPinnedClient +) + +const ( + PriorityNoneJSONString = `"none"` + PriorityOverflowJSONString = `"overflow"` + PriorityPinnedClientJSONString = `"pinned_client"` +) + +var ( + PriorityNoneJSONBytes = []byte(PriorityNoneJSONString) + PriorityOverflowJSONBytes = []byte(PriorityOverflowJSONString) + PriorityPinnedClientJSONBytes = []byte(PriorityPinnedClientJSONString) +) + +func (pp PriorityPolicy) String() string { + switch pp { + case PriorityOverflow: + return PriorityOverflowJSONString + case PriorityPinnedClient: + return PriorityPinnedClientJSONString + default: + return PriorityNoneJSONString + } +} + +func (pp PriorityPolicy) MarshalJSON() ([]byte, error) { + switch pp { + case PriorityOverflow: + return PriorityOverflowJSONBytes, nil + case PriorityPinnedClient: + return PriorityPinnedClientJSONBytes, nil + case PriorityNone: + return PriorityNoneJSONBytes, nil + default: + return nil, fmt.Errorf("unknown priority policy: %v", pp) + } +} + +func (pp *PriorityPolicy) UnmarshalJSON(data []byte) error { + switch string(data) { + case PriorityOverflowJSONString: + *pp = PriorityOverflow + case PriorityPinnedClientJSONString: + *pp = PriorityPinnedClient + case PriorityNoneJSONString: + *pp = PriorityNone + default: + return fmt.Errorf("unknown priority policy: %v", string(data)) + } + return nil } // DeliverPolicy determines how the consumer should select the first message to deliver. @@ -84,8 +291,10 @@ const ( DeliverNew // DeliverByStartSequence will look for a defined starting sequence to start. DeliverByStartSequence - // DeliverByStartTime will select the first messsage with a timestamp >= to StartTime + // DeliverByStartTime will select the first messsage with a timestamp >= to StartTime. DeliverByStartTime + // DeliverLastPerSubject will start the consumer with the last message for all subjects received. + DeliverLastPerSubject ) func (dp DeliverPolicy) String() string { @@ -100,6 +309,8 @@ func (dp DeliverPolicy) String() string { return "by_start_sequence" case DeliverByStartTime: return "by_start_time" + case DeliverLastPerSubject: + return "last_per_subject" default: return "undefined" } @@ -141,9 +352,9 @@ const ( func (r ReplayPolicy) String() string { switch r { case ReplayInstant: - return "instant" + return replayInstantPolicyJSONString default: - return "original" + return replayOriginalPolicyJSONString } } @@ -166,418 +377,1286 @@ var ( AckTerm = []byte("+TERM") ) +const ( + // reasons to supply when terminating messages using limits + ackTermLimitsReason = "Message deleted by stream limits" + ackTermUnackedLimitsReason = "Unacknowledged message was deleted" +) + +// Calculate accurate replicas for the consumer config with the parent stream config. +func (consCfg ConsumerConfig) replicas(strCfg *StreamConfig) int { + if consCfg.Replicas == 0 || consCfg.Replicas > strCfg.Replicas { + if !isDurableConsumer(&consCfg) && strCfg.Retention == LimitsPolicy && consCfg.Replicas == 0 { + // Matches old-school ephemerals only, where the replica count is 0. + return 1 + } + return strCfg.Replicas + } + return consCfg.Replicas +} + // Consumer is a jetstream consumer. -type Consumer struct { - mu sync.Mutex - mset *Stream +type consumer struct { + // Atomic used to notify that we want to process an ack. + // This will be checked in checkPending to abort processing + // and let ack be processed in priority. + awl int64 + leader atomic.Bool + mu sync.RWMutex + js *jetStream + mset *stream acc *Account + srv *Server + client *client + sysc *client + sid int name string stream string - sseq uint64 - dseq uint64 - adflr uint64 - asflr uint64 - sgap uint64 + sseq uint64 // next stream sequence + subjf subjectFilters // subject filters and their sequences + filters *gsl.SimpleSublist // When we have multiple filters we will use LoadNextMsgMulti and pass this in. + dseq uint64 // delivered consumer sequence + adflr uint64 // ack delivery floor + asflr uint64 // ack store floor + chkflr uint64 // our check floor, interest streams only. + npc int64 // Num Pending Count + npf uint64 // Num Pending Floor Sequence dsubj string + qgroup string + lss *lastSeqSkipList rlimit *rate.Limiter reqSub *subscription ackSub *subscription ackReplyT string + ackSubj string nextMsgSubj string + nextMsgReqs *ipQueue[*nextMsgReq] maxp int - sendq chan *jsPubMsg + pblimit int + maxpb int + pbytes int + fcsz int + fcid string + fcSub *subscription + outq *jsOutQ pending map[uint64]*Pending ptmr *time.Timer + ptmrEnd time.Time rdq []uint64 + rdqi avl.SequenceSet rdc map[uint64]uint64 + replies map[uint64]string + pendingDeliveries map[uint64]*jsPubMsg // Messages that can be delivered after achieving quorum. + waitingDeliveries map[string]*waitingDelivery // (Optional) request timeout messages that need to wait for replicated deliveries first. maxdc uint64 waiting *waitQueue - config ConsumerConfig + cfg ConsumerConfig + ici *ConsumerInfo store ConsumerStore active bool replay bool - filterWC bool dtmr *time.Timer + uptmr *time.Timer // Unpause timer + gwdtmr *time.Timer dthresh time.Duration - mch chan struct{} - qch chan struct{} - inch chan bool + mch chan struct{} // Message channel + qch chan struct{} // Quit channel + mqch chan struct{} // The monitor's quit channel. + inch chan bool // Interest change channel sfreq int32 ackEventT string + nakEventT string deliveryExcEventT string created time.Time + ldt time.Time + lat time.Time + lwqic time.Time closed bool + + // Clustered. + ca *consumerAssignment + node RaftNode + infoSub *subscription + lqsent time.Time + prm map[string]struct{} + prOk bool + uch chan struct{} + retention RetentionPolicy + + monitorWg sync.WaitGroup + inMonitor bool + + // R>1 proposals + pch chan struct{} + phead *proposal + ptail *proposal + + // Ack queue + ackMsgs *ipQueue[*jsAckMsg] + + // for stream signaling when multiple filters are set. + sigSubs []string + + // Priority groups + // Details described in ADR-42. + + // currentPinId is the current nuid for the pinned consumer. + // If the Consumer is running in `PriorityPinnedClient` mode, server will + // pick up a new nuid and assign it to first pending pull request. + currentPinId string + /// pinnedTtl is the remaining time before the current PinId expires. + pinnedTtl *time.Timer + pinnedTS time.Time + + // If standalone/single-server, the offline reason needs to be stored directly in the consumer. + // Otherwise, if clustered it will be part of the consumer assignment. + offlineReason string +} + +// A single subject filter. +type subjectFilter struct { + subject string + tokenizedSubject []string + hasWildcard bool +} + +type subjectFilters []*subjectFilter + +// subjects is a helper function used for updating consumers. +// It is not used and should not be used in hotpath. +func (s subjectFilters) subjects() []string { + subjects := make([]string, 0, len(s)) + for _, filter := range s { + subjects = append(subjects, filter.subject) + } + return subjects +} + +type proposal struct { + data []byte + next *proposal } const ( - // JsAckWaitDefault is the default AckWait, only applicable on explicit ack policy observables. + // JsAckWaitDefault is the default AckWait, only applicable on explicit ack policy consumers. JsAckWaitDefault = 30 * time.Second // JsDeleteWaitTimeDefault is the default amount of time we will wait for non-durable - // observables to be in an inactive state before deleting them. + // consumers to be in an inactive state before deleting them. JsDeleteWaitTimeDefault = 5 * time.Second + // JsFlowControlMaxPending specifies default pending bytes during flow control that can be outstanding. + JsFlowControlMaxPending = 32 * 1024 * 1024 + // JsDefaultMaxAckPending is set for consumers with explicit ack that do not set the max ack pending. + JsDefaultMaxAckPending = 1000 + // JsDefaultPinnedTTL is the default grace period for the pinned consumer to send a new request before a new pin + // is picked by a server. + JsDefaultPinnedTTL = 2 * time.Minute ) -func (mset *Stream) AddConsumer(config *ConsumerConfig) (*Consumer, error) { - if config == nil { - return nil, fmt.Errorf("consumer config required") +// Helper function to set consumer config defaults from above. +func setConsumerConfigDefaults(config *ConsumerConfig, streamCfg *StreamConfig, lim *JSLimitOpts, accLim *JetStreamAccountLimits, pedantic bool) *ApiError { + // Set to default if not specified. + if config.DeliverSubject == _EMPTY_ && config.MaxWaiting == 0 { + config.MaxWaiting = JSWaitQueueDefaultMax + } + // Setup proper default for ack wait if we are in explicit ack mode. + if config.AckWait == 0 && (config.AckPolicy == AckExplicit || config.AckPolicy == AckAll) { + config.AckWait = JsAckWaitDefault + } + // Setup default of -1, meaning no limit for MaxDeliver. + if config.MaxDeliver == 0 { + config.MaxDeliver = -1 + } + // If BackOff was specified that will override the AckWait and the MaxDeliver. + if len(config.BackOff) > 0 { + if pedantic && config.AckWait != config.BackOff[0] { + return NewJSPedanticError(errors.New("first backoff value has to equal batch AckWait")) + } + config.AckWait = config.BackOff[0] + } + if config.MaxAckPending == 0 { + if pedantic && streamCfg.ConsumerLimits.MaxAckPending > 0 { + return NewJSPedanticError(errors.New("max_ack_pending must be set if it's configured in stream limits")) + } + config.MaxAckPending = streamCfg.ConsumerLimits.MaxAckPending + } + if config.InactiveThreshold == 0 { + if pedantic && streamCfg.ConsumerLimits.InactiveThreshold > 0 { + return NewJSPedanticError(errors.New("inactive_threshold must be set if it's configured in stream limits")) + } + config.InactiveThreshold = streamCfg.ConsumerLimits.InactiveThreshold + } + // Set proper default for max ack pending if we are ack explicit and none has been set. + if (config.AckPolicy == AckExplicit || config.AckPolicy == AckAll) && config.MaxAckPending == 0 { + accPending := JsDefaultMaxAckPending + if lim.MaxAckPending > 0 && lim.MaxAckPending < accPending { + accPending = lim.MaxAckPending + } + if accLim.MaxAckPending > 0 && accLim.MaxAckPending < accPending { + accPending = accLim.MaxAckPending + } + config.MaxAckPending = accPending + } + // if applicable set max request batch size + if config.DeliverSubject == _EMPTY_ && config.MaxRequestBatch == 0 && lim.MaxRequestBatch > 0 { + if pedantic { + return NewJSPedanticError(errors.New("max_request_batch must be set if it's JetStream limits are set")) + } + config.MaxRequestBatch = lim.MaxRequestBatch + } + + // set the default value only if pinned policy is used. + if config.PriorityPolicy == PriorityPinnedClient && config.PinnedTTL == 0 { + config.PinnedTTL = JsDefaultPinnedTTL + } + return nil +} + +// Check the consumer config. If we are recovering don't check filter subjects. +func checkConsumerCfg( + config *ConsumerConfig, + srvLim *JSLimitOpts, + cfg *StreamConfig, + _ *Account, + accLim *JetStreamAccountLimits, + isRecovering bool, +) *ApiError { + + // Check if replicas is defined but exceeds parent stream. + if config.Replicas > 0 && config.Replicas > cfg.Replicas { + return NewJSConsumerReplicasExceedsStreamError() + } + // Check that it is not negative + if config.Replicas < 0 { + return NewJSReplicasCountCannotBeNegativeError() + } + // If the stream is interest or workqueue retention make sure the replicas + // match that of the stream. This is REQUIRED for now. + if cfg.Retention == InterestPolicy || cfg.Retention == WorkQueuePolicy { + // Only error here if not recovering. + // We handle recovering in a different spot to allow consumer to come up + // if previous version allowed it to be created. We do not want it to not come up. + if !isRecovering && config.Replicas != 0 && config.Replicas != cfg.Replicas { + return NewJSConsumerReplicasShouldMatchStreamError() + } + } + + // Check if we have a BackOff defined that MaxDeliver is within range etc. + if lbo := len(config.BackOff); lbo > 0 && config.MaxDeliver != -1 && lbo > config.MaxDeliver { + return NewJSConsumerMaxDeliverBackoffError() + } + + if len(config.Description) > JSMaxDescriptionLen { + return NewJSConsumerDescriptionTooLongError(JSMaxDescriptionLen) } - var err error // For now expect a literal subject if its not empty. Empty means work queue mode (pull mode). if config.DeliverSubject != _EMPTY_ { if !subjectIsLiteral(config.DeliverSubject) { - return nil, fmt.Errorf("consumer deliver subject has wildcards") + return NewJSConsumerDeliverToWildcardsError() + } + if !IsValidSubject(config.DeliverSubject) { + return NewJSConsumerInvalidDeliverSubjectError() } - if mset.deliveryFormsCycle(config.DeliverSubject) { - return nil, fmt.Errorf("consumer deliver subject forms a cycle") + if deliveryFormsCycle(cfg, config.DeliverSubject) { + return NewJSConsumerDeliverCycleError() } if config.MaxWaiting != 0 { - return nil, fmt.Errorf("consumer in push mode can not set max waiting") + return NewJSConsumerPushMaxWaitingError() } if config.MaxAckPending > 0 && config.AckPolicy == AckNone { - return nil, fmt.Errorf("consumer requires ack policy for max ack pending") + return NewJSConsumerMaxPendingAckPolicyRequiredError() } - } else { - // Pull mode / work queue mode require explicit ack. - if config.AckPolicy != AckExplicit { - return nil, fmt.Errorf("consumer in pull mode requires explicit ack policy") + if config.Heartbeat > 0 && config.Heartbeat < 100*time.Millisecond { + return NewJSConsumerSmallHeartbeatError() } - // They are also required to be durable since otherwise we will not know when to - // clean them up. - if config.Durable == _EMPTY_ { - return nil, fmt.Errorf("consumer in pull mode requires a durable name") + } else { + // Pull mode with work queue retention from the stream requires an explicit ack. + if config.AckPolicy == AckNone && cfg.Retention == WorkQueuePolicy { + return NewJSConsumerPullRequiresAckError() } if config.RateLimit > 0 { - return nil, fmt.Errorf("consumer in pull mode can not have rate limit set") + return NewJSConsumerPullWithRateLimitError() } if config.MaxWaiting < 0 { - return nil, fmt.Errorf("consumer max waiting needs to be positive") + return NewJSConsumerMaxWaitingNegativeError() + } + if config.Heartbeat > 0 { + return NewJSConsumerHBRequiresPushError() + } + if config.FlowControl { + return NewJSConsumerFCRequiresPushError() + } + if config.MaxRequestBatch < 0 { + return NewJSConsumerMaxRequestBatchNegativeError() } - // Set to default if not specified. - if config.MaxWaiting == 0 { - config.MaxWaiting = JSWaitQueueDefaultMax + if config.MaxRequestExpires != 0 && config.MaxRequestExpires < time.Millisecond { + return NewJSConsumerMaxRequestExpiresToSmallError() } + if srvLim.MaxRequestBatch > 0 && config.MaxRequestBatch > srvLim.MaxRequestBatch { + return NewJSConsumerMaxRequestBatchExceededError(srvLim.MaxRequestBatch) + } + } + if srvLim.MaxAckPending > 0 && config.MaxAckPending > srvLim.MaxAckPending { + return NewJSConsumerMaxPendingAckExcessError(srvLim.MaxAckPending) + } + if accLim.MaxAckPending > 0 && config.MaxAckPending > accLim.MaxAckPending { + return NewJSConsumerMaxPendingAckExcessError(accLim.MaxAckPending) + } + if cfg.ConsumerLimits.MaxAckPending > 0 && config.MaxAckPending > cfg.ConsumerLimits.MaxAckPending { + return NewJSConsumerMaxPendingAckExcessError(cfg.ConsumerLimits.MaxAckPending) + } + if cfg.ConsumerLimits.InactiveThreshold > 0 && config.InactiveThreshold > cfg.ConsumerLimits.InactiveThreshold { + return NewJSConsumerInactiveThresholdExcessError(cfg.ConsumerLimits.InactiveThreshold) } - // Setup proper default for ack wait if we are in explicit ack mode. - if config.AckWait == 0 && (config.AckPolicy == AckExplicit || config.AckPolicy == AckAll) { - config.AckWait = JsAckWaitDefault + // Direct need to be non-mapped ephemerals. + if config.Direct { + if config.DeliverSubject == _EMPTY_ { + return NewJSConsumerDirectRequiresPushError() + } + if isDurableConsumer(config) { + return NewJSConsumerDirectRequiresEphemeralError() + } } - // Setup default of -1, meaning no limit for MaxDeliver. - if config.MaxDeliver == 0 { - config.MaxDeliver = -1 + + // Do not allow specifying both FilterSubject and FilterSubjects, + // as that's probably unintentional without any difference from passing + // all filters in FilterSubjects. + if config.FilterSubject != _EMPTY_ && len(config.FilterSubjects) > 0 { + return NewJSConsumerDuplicateFilterSubjectsError() } - // Make sure any partition subject is also a literal. - if config.FilterSubject != "" { - var checkSubject bool + if config.FilterSubject != _EMPTY_ && !IsValidSubject(config.FilterSubject) { + return NewJSStreamInvalidConfigError(ErrBadSubject) + } - mset.mu.RLock() - // If the stream was created with no subject, then skip the checks - if !mset.config.allowNoSubject { - // If this is a direct match for the streams only subject clear the filter. - if len(mset.config.Subjects) == 1 && mset.config.Subjects[0] == config.FilterSubject { - config.FilterSubject = _EMPTY_ - } else { - checkSubject = true - } + // We treat FilterSubjects: []string{""} as a misconfig, so we validate against it. + for _, filter := range config.FilterSubjects { + if filter == _EMPTY_ { + return NewJSConsumerEmptyFilterError() } - mset.mu.RUnlock() + } + subjectFilters := gatherSubjectFilters(config.FilterSubject, config.FilterSubjects) - // Make sure this is a valid partition of the interest subjects. - if checkSubject && !mset.validSubject(config.FilterSubject) { - return nil, fmt.Errorf("consumer filter subject is not a valid subset of the interest subjects") + // Check subject filters do not overlap. + for outer, subject := range subjectFilters { + if !IsValidSubject(subject) { + return NewJSStreamInvalidConfigError(ErrBadSubject) } + for inner, ssubject := range subjectFilters { + if inner != outer && SubjectsCollide(subject, ssubject) { + return NewJSConsumerOverlappingSubjectFiltersError() + } + } + } + + // Helper function to formulate similar errors. + badStart := func(dp, start string) error { + return fmt.Errorf("consumer delivery policy is deliver %s, but optional start %s is also set", dp, start) + } + notSet := func(dp, notSet string) error { + return fmt.Errorf("consumer delivery policy is deliver %s, but optional %s is not set", dp, notSet) } // Check on start position conflicts. switch config.DeliverPolicy { case DeliverAll: if config.OptStartSeq > 0 { - return nil, fmt.Errorf("consumer delivery policy is deliver all, but optional start sequence is also set") + return NewJSConsumerInvalidPolicyError(badStart("all", "sequence")) } if config.OptStartTime != nil { - return nil, fmt.Errorf("consumer delivery policy is deliver all, but optional start time is also set") + return NewJSConsumerInvalidPolicyError(badStart("all", "time")) } case DeliverLast: if config.OptStartSeq > 0 { - return nil, fmt.Errorf("consumer delivery policy is deliver last, but optional start sequence is also set") + return NewJSConsumerInvalidPolicyError(badStart("last", "sequence")) + } + if config.OptStartTime != nil { + return NewJSConsumerInvalidPolicyError(badStart("last", "time")) + } + case DeliverLastPerSubject: + if config.OptStartSeq > 0 { + return NewJSConsumerInvalidPolicyError(badStart("last per subject", "sequence")) } if config.OptStartTime != nil { - return nil, fmt.Errorf("consumer delivery policy is deliver last, but optional start time is also set") + return NewJSConsumerInvalidPolicyError(badStart("last per subject", "time")) + } + if config.FilterSubject == _EMPTY_ && len(config.FilterSubjects) == 0 { + return NewJSConsumerInvalidPolicyError(notSet("last per subject", "filter subject")) } case DeliverNew: if config.OptStartSeq > 0 { - return nil, fmt.Errorf("consumer delivery policy is deliver new, but optional start sequence is also set") + return NewJSConsumerInvalidPolicyError(badStart("new", "sequence")) } if config.OptStartTime != nil { - return nil, fmt.Errorf("consumer delivery policy is deliver new, but optional start time is also set") + return NewJSConsumerInvalidPolicyError(badStart("new", "time")) } case DeliverByStartSequence: if config.OptStartSeq == 0 { - return nil, fmt.Errorf("consumer delivery policy is deliver by start sequence, but optional start sequence is not set") + return NewJSConsumerInvalidPolicyError(notSet("by start sequence", "start sequence")) } if config.OptStartTime != nil { - return nil, fmt.Errorf("consumer delivery policy is deliver by start sequence, but optional start time is also set") + return NewJSConsumerInvalidPolicyError(badStart("by start sequence", "time")) } case DeliverByStartTime: if config.OptStartTime == nil { - return nil, fmt.Errorf("consumer delivery policy is deliver by start time, but optional start time is not set") + return NewJSConsumerInvalidPolicyError(notSet("by start time", "start time")) } if config.OptStartSeq != 0 { - return nil, fmt.Errorf("consumer delivery policy is deliver by start time, but optional start sequence is also set") + return NewJSConsumerInvalidPolicyError(badStart("by start time", "start sequence")) } } - sampleFreq := 0 - if config.SampleFrequency != "" { + if config.SampleFrequency != _EMPTY_ { s := strings.TrimSuffix(config.SampleFrequency, "%") - sampleFreq, err = strconv.Atoi(s) - if err != nil { - return nil, fmt.Errorf("failed to parse consumer sampling configuration: %v", err) + if sampleFreq, err := strconv.Atoi(s); err != nil || sampleFreq < 0 { + return NewJSConsumerInvalidSamplingError(err) + } + } + + // We reject if flow control is set without heartbeats. + if config.FlowControl && config.Heartbeat == 0 { + return NewJSConsumerWithFlowControlNeedsHeartbeatsError() + } + + if config.Durable != _EMPTY_ && config.Name != _EMPTY_ { + if config.Name != config.Durable { + return NewJSConsumerCreateDurableAndNameMismatchError() + } + } + + var metadataLen int + for k, v := range config.Metadata { + metadataLen += len(k) + len(v) + } + if metadataLen > JSMaxMetadataLen { + return NewJSConsumerMetadataLengthError(fmt.Sprintf("%dKB", JSMaxMetadataLen/1024)) + } + + if config.PriorityPolicy != PriorityNone { + if config.DeliverSubject != "" { + return NewJSConsumerPushWithPriorityGroupError() + } + if len(config.PriorityGroups) == 0 { + return NewJSConsumerPriorityPolicyWithoutGroupError() } + + for _, group := range config.PriorityGroups { + if group == _EMPTY_ { + return NewJSConsumerEmptyGroupNameError() + } + if !validGroupName.MatchString(group) { + return NewJSConsumerInvalidGroupNameError() + } + } + } + + // For now don't allow preferred server in placement. + if cfg.Placement != nil && cfg.Placement.Preferred != _EMPTY_ { + return NewJSStreamInvalidConfigError(fmt.Errorf("preferred server not permitted in placement")) + } + + return nil +} + +func (mset *stream) addConsumerWithAction(config *ConsumerConfig, action ConsumerAction, pedantic bool) (*consumer, error) { + return mset.addConsumerWithAssignment(config, _EMPTY_, nil, false, action, pedantic) +} + +func (mset *stream) addConsumer(config *ConsumerConfig) (*consumer, error) { + return mset.addConsumerWithAction(config, ActionCreateOrUpdate, false) +} + +func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname string, ca *consumerAssignment, isRecovering bool, action ConsumerAction, pedantic bool) (*consumer, error) { + // Check if this stream has closed. + if mset.closed.Load() { + return nil, NewJSStreamInvalidError() + } + + mset.mu.RLock() + s, jsa, cfg, acc := mset.srv, mset.jsa, mset.cfg, mset.acc + mset.mu.RUnlock() + + // If we do not have the consumer currently assigned to us in cluster mode we will proceed but warn. + // This can happen on startup with restored state where on meta replay we still do not have + // the assignment. Running in single server mode this always returns true. + if oname != _EMPTY_ && !jsa.consumerAssigned(mset.name(), oname) { + s.Debugf("Consumer %q > %q does not seem to be assigned to this server", mset.name(), oname) + } + + if config == nil { + return nil, NewJSConsumerConfigRequiredError() + } + + selectedLimits, _, _, _ := acc.selectLimits(config.replicas(&cfg)) + if selectedLimits == nil { + return nil, NewJSNoLimitsError() + } + + srvLim := &s.getOpts().JetStreamLimits + // Make sure we have sane defaults. Do so with the JS lock, otherwise a + // badly timed meta snapshot can result in a race condition. + mset.js.mu.Lock() + err := setConsumerConfigDefaults(config, &cfg, srvLim, selectedLimits, pedantic) + mset.js.mu.Unlock() + if err != nil { + return nil, err + } + + if err := checkConsumerCfg(config, srvLim, &cfg, acc, selectedLimits, isRecovering); err != nil { + return nil, err + } + sampleFreq := 0 + if config.SampleFrequency != _EMPTY_ { + // Can't fail as checkConsumerCfg checks correct format + sampleFreq, _ = strconv.Atoi(strings.TrimSuffix(config.SampleFrequency, "%")) } // Grab the client, account and server reference. c := mset.client if c == nil { - return nil, fmt.Errorf("stream not valid") + return nil, NewJSStreamInvalidError() } + var accName string c.mu.Lock() s, a := c.srv, c.acc + if a != nil { + accName = a.Name + } c.mu.Unlock() // Hold mset lock here. mset.mu.Lock() + if mset.client == nil || mset.store == nil || mset.consumers == nil { + mset.mu.Unlock() + return nil, NewJSStreamInvalidError() + } - // If this one is durable and already exists, we let that be ok as long as the configs match. + // If this one is durable and already exists, we let that be ok as long as only updating what should be allowed. + var cName string if isDurableConsumer(config) { - if eo, ok := mset.consumers[config.Durable]; ok { + cName = config.Durable + } else if config.Name != _EMPTY_ { + cName = config.Name + } + if cName != _EMPTY_ { + if eo, ok := mset.consumers[cName]; ok { + if action == ActionCreate { + ocfg := eo.config() + copyConsumerMetadata(config, &ocfg) + if !reflect.DeepEqual(config, &ocfg) { + mset.mu.Unlock() + return nil, NewJSConsumerAlreadyExistsError() + } + } + // Check for overlapping subjects if we are a workqueue + if cfg.Retention == WorkQueuePolicy { + subjects := gatherSubjectFilters(config.FilterSubject, config.FilterSubjects) + if !mset.partitionUnique(cName, subjects) { + mset.mu.Unlock() + return nil, NewJSConsumerWQConsumerNotUniqueError() + } + } mset.mu.Unlock() - ocfg := eo.Config() - if reflect.DeepEqual(&ocfg, config) { + err := eo.updateConfig(config) + if err == nil { return eo, nil - } else { - // If we are a push mode and not active and the only difference - // is deliver subject then update and return. - if configsEqualSansDelivery(ocfg, *config) && (config.allowNoInterest || eo.hasNoLocalInterest()) { - eo.updateDeliverSubject(config.DeliverSubject) - return eo, nil - } else { - return nil, fmt.Errorf("consumer already exists") - } } + return nil, NewJSConsumerCreateError(err, Unless(err)) } } + if action == ActionUpdate { + mset.mu.Unlock() + return nil, NewJSConsumerDoesNotExistError() + } // Check for any limits, if the config for the consumer sets a limit we check against that // but if not we use the value from account limits, if account limits is more restrictive // than stream config we prefer the account limits to handle cases where account limits are // updated during the lifecycle of the stream - maxc := mset.config.MaxConsumers - if mset.config.MaxConsumers <= 0 || mset.jsa.limits.MaxConsumers < mset.config.MaxConsumers { - maxc = mset.jsa.limits.MaxConsumers + maxc := cfg.MaxConsumers + if maxc <= 0 || (selectedLimits.MaxConsumers > 0 && selectedLimits.MaxConsumers < maxc) { + maxc = selectedLimits.MaxConsumers } - - if maxc > 0 && len(mset.consumers) >= maxc { + if maxc > 0 && mset.numPublicConsumers() >= maxc { mset.mu.Unlock() - return nil, fmt.Errorf("maximum consumers limit reached") + return nil, NewJSMaximumConsumersLimitError() } - // Check on stream type conflicts. - switch mset.config.Retention { - case WorkQueuePolicy: + // Check on stream type conflicts with WorkQueues. + if cfg.Retention == WorkQueuePolicy && !config.Direct { // Force explicit acks here. if config.AckPolicy != AckExplicit { mset.mu.Unlock() - return nil, fmt.Errorf("workqueue stream requires explicit ack") + return nil, NewJSConsumerWQRequiresExplicitAckError() } if len(mset.consumers) > 0 { - if config.FilterSubject == _EMPTY_ { + subjects := gatherSubjectFilters(config.FilterSubject, config.FilterSubjects) + if len(subjects) == 0 { mset.mu.Unlock() - return nil, fmt.Errorf("multiple non-filtered observables not allowed on workqueue stream") - } else if !mset.partitionUnique(config.FilterSubject) { - // We have a partition but it is not unique amongst the others. - mset.mu.Unlock() - return nil, fmt.Errorf("filtered consumer not unique on workqueue stream") + return nil, NewJSConsumerWQMultipleUnfilteredError() + } else if !mset.partitionUnique(cName, subjects) { + // Prior to v2.9.7, on a stream with WorkQueue policy, the servers + // were not catching the error of having multiple consumers with + // overlapping filter subjects depending on the scope, for instance + // creating "foo.*.bar" and then "foo.>" was not detected, while + // "foo.>" and then "foo.*.bar" would have been. Failing here + // in recovery mode would leave the rejected consumer in a bad state, + // so we will simply warn here, asking the user to remove this + // consumer administratively. Otherwise, if this is the creation + // of a new consumer, we will return the error. + if isRecovering { + s.Warnf("Consumer %q > %q has a filter subject that overlaps "+ + "with other consumers, which is not allowed for a stream "+ + "with WorkQueue policy, it should be administratively deleted", + cfg.Name, cName) + } else { + // We have a partition but it is not unique amongst the others. + mset.mu.Unlock() + return nil, NewJSConsumerWQConsumerNotUniqueError() + } } } if config.DeliverPolicy != DeliverAll { mset.mu.Unlock() - return nil, fmt.Errorf("consumer must be deliver all on workqueue stream") + return nil, NewJSConsumerWQConsumerNotDeliverAllError() } } // Set name, which will be durable name if set, otherwise we create one at random. - o := &Consumer{ - mset: mset, - acc: a, - config: *config, - dsubj: config.DeliverSubject, - active: true, - qch: make(chan struct{}), - mch: make(chan struct{}, 1), - sfreq: int32(sampleFreq), - maxdc: uint64(config.MaxDeliver), - maxp: config.MaxAckPending, - created: time.Now().UTC(), - } + o := &consumer{ + mset: mset, + js: s.getJetStream(), + acc: a, + srv: s, + client: s.createInternalJetStreamClient(), + sysc: s.createInternalJetStreamClient(), + cfg: *config, + dsubj: config.DeliverSubject, + outq: mset.outq, + active: true, + qch: make(chan struct{}), + mqch: make(chan struct{}), + uch: make(chan struct{}, 1), + mch: make(chan struct{}, 1), + sfreq: int32(sampleFreq), + maxdc: uint64(max(config.MaxDeliver, 0)), // MaxDeliver is negative (-1) when infinite. + maxp: config.MaxAckPending, + retention: cfg.Retention, + created: time.Now().UTC(), + } + + // Bind internal client to the user account. + o.client.registerWithAccount(a) + // Bind to the system account. + o.sysc.registerWithAccount(s.SystemAccount()) + if isDurableConsumer(config) { if len(config.Durable) > JSMaxNameLen { mset.mu.Unlock() - return nil, fmt.Errorf("consumer name is too long, maximum allowed is %d", JSMaxNameLen) + o.deleteWithoutAdvisory() + return nil, NewJSConsumerNameTooLongError(JSMaxNameLen) } o.name = config.Durable - if o.isPullMode() { - o.waiting = newWaitQueue(config.MaxWaiting) - } + } else if oname != _EMPTY_ { + o.name = oname } else { - for { - o.name = createConsumerName() - if _, ok := mset.consumers[o.name]; !ok { - break - } - } - } - - // Check if we have a rate limit set. - if config.RateLimit != 0 { - // TODO(dlc) - Make sane values or error if not sane? - // We are configured in bits per sec so adjust to bytes. - rl := rate.Limit(config.RateLimit / 8) - // Burst should be set to maximum msg size for this account, etc. - var burst int - if mset.config.MaxMsgSize > 0 { - burst = int(mset.config.MaxMsgSize) - } else if mset.jsa.account.limits.mpay > 0 { - burst = int(mset.jsa.account.limits.mpay) + if config.Name != _EMPTY_ { + o.name = config.Name } else { - s := mset.jsa.account.srv - burst = int(s.getOpts().MaxPayload) + // Legacy ephemeral auto-generated. + for { + o.name = createConsumerName() + if _, ok := mset.consumers[o.name]; !ok { + break + } + } + config.Name = o.name } - o.rlimit = rate.NewLimiter(rl, burst) } + // Create ackMsgs queue now that we have a consumer name + o.ackMsgs = newIPQueue[*jsAckMsg](s, fmt.Sprintf("[ACC:%s] consumer '%s' on stream '%s' ackMsgs", accName, o.name, cfg.Name)) - // Check if we have filtered subject that is a wildcard. - if config.FilterSubject != _EMPTY_ && !subjectIsLiteral(config.FilterSubject) { - o.filterWC = true + // Create our request waiting queue. + if o.isPullMode() { + o.waiting = newWaitQueue(config.MaxWaiting) + // Create our internal queue for next msg requests. + o.nextMsgReqs = newIPQueue[*nextMsgReq](s, fmt.Sprintf("[ACC:%s] consumer '%s' on stream '%s' pull requests", accName, o.name, cfg.Name)) } // already under lock, mset.Name() would deadlock - o.stream = mset.config.Name + o.stream = cfg.Name o.ackEventT = JSMetricConsumerAckPre + "." + o.stream + "." + o.name + o.nakEventT = JSAdvisoryConsumerMsgNakPre + "." + o.stream + "." + o.name o.deliveryExcEventT = JSAdvisoryConsumerMaxDeliveryExceedPre + "." + o.stream + "." + o.name - store, err := mset.store.ConsumerStore(o.name, config) - if err != nil { + if !isValidName(o.name) { mset.mu.Unlock() - return nil, fmt.Errorf("error creating store for observable: %v", err) + o.deleteWithoutAdvisory() + return nil, NewJSConsumerBadDurableNameError() } - o.store = store - if !isValidName(o.name) { - mset.mu.Unlock() - return nil, fmt.Errorf("durable name can not contain '.', '*', '>'") + // Setup our storage if not a direct consumer. + if !config.Direct { + store, err := mset.store.ConsumerStore(o.name, config) + if err != nil { + mset.mu.Unlock() + o.deleteWithoutAdvisory() + return nil, NewJSConsumerStoreFailedError(err) + } + o.store = store } - // Select starting sequence number - o.selectStartingSeqNo() + for _, filter := range gatherSubjectFilters(o.cfg.FilterSubject, o.cfg.FilterSubjects) { + sub := &subjectFilter{ + subject: filter, + hasWildcard: subjectHasWildcard(filter), + tokenizedSubject: tokenizeSubjectIntoSlice(nil, filter), + } + o.subjf = append(o.subjf, sub) + } + + // If we have multiple filter subjects, create a sublist which we will use + // in calling store.LoadNextMsgMulti. + if len(o.cfg.FilterSubjects) > 0 { + o.filters = gsl.NewSublist[struct{}]() + for _, filter := range o.cfg.FilterSubjects { + o.filters.Insert(filter, struct{}{}) + } + } else { + // Make sure this is nil otherwise. + o.filters = nil + } + + if o.store != nil && o.store.HasState() { + // Restore our saved state. + o.mu.Lock() + o.readStoredState() + o.mu.Unlock() + } else { + // Select starting sequence number + o.selectStartingSeqNo() + } // Now register with mset and create the ack subscription. // Check if we already have this one registered. if eo, ok := mset.consumers[o.name]; ok { mset.mu.Unlock() if !o.isDurable() || !o.isPushMode() { - return nil, fmt.Errorf("consumer already exists") + o.name = _EMPTY_ // Prevent removal since same name. + o.deleteWithoutAdvisory() + return nil, NewJSConsumerNameExistError() } // If we are here we have already registered this durable. If it is still active that is an error. - if eo.Active() { - return nil, fmt.Errorf("consumer already exists and is still active") + if eo.isActive() { + o.name = _EMPTY_ // Prevent removal since same name. + o.deleteWithoutAdvisory() + return nil, NewJSConsumerExistingActiveError() } // Since we are here this means we have a potentially new durable so we should update here. // Check that configs are the same. - if !configsEqualSansDelivery(o.config, eo.config) { - return nil, fmt.Errorf("consumer replacement durable config not the same") + if !configsEqualSansDelivery(o.cfg, eo.cfg) { + o.name = _EMPTY_ // Prevent removal since same name. + o.deleteWithoutAdvisory() + return nil, NewJSConsumerReplacementWithDifferentNameError() } // Once we are here we have a replacement push-based durable. - eo.updateDeliverSubject(o.config.DeliverSubject) + eo.updateDeliverSubject(o.cfg.DeliverSubject) return eo, nil } - // Set up the ack subscription for this observable. Will use wildcard for all acks. + + // Set up the ack subscription for this consumer. Will use wildcard for all acks. // We will remember the template to generate replies with sequence numbers and use // that to scanf them back in. - mn := mset.config.Name - pre := fmt.Sprintf(jsAckT, mn, o.name) + // Escape '%' in consumer and stream names, as `pre` is used as a template later + // in consumer.ackReply(), resulting in erroneous formatting of the ack subject. + mn := strings.ReplaceAll(cfg.Name, "%", "%%") + pre := fmt.Sprintf(jsAckT, mn, strings.ReplaceAll(o.name, "%", "%%")) o.ackReplyT = fmt.Sprintf("%s.%%d.%%d.%%d.%%d.%%d", pre) - ackSubj := fmt.Sprintf("%s.*.*.*.*.*", pre) - if sub, err := mset.subscribeInternal(ackSubj, o.processAck); err != nil { - mset.mu.Unlock() - return nil, err - } else { - o.ackSub = sub + o.ackSubj = fmt.Sprintf("%s.*.*.*.*.*", pre) + o.nextMsgSubj = fmt.Sprintf(JSApiRequestNextT, mn, o.name) + + // Check/update the inactive threshold + o.updateInactiveThreshold(&o.cfg) + + if o.isPushMode() { + // Check if we are running only 1 replica and that the delivery subject has interest. + // Check in place here for interest. Will setup properly in setLeader. + if config.replicas(&cfg) == 1 { + interest := o.acc.sl.HasInterest(o.cfg.DeliverSubject) + if !o.hasDeliveryInterest(interest) { + // Let the interest come to us eventually, but setup delete timer. + o.updateDeliveryInterest(false) + } + } } - // Setup the internal sub for next message requests. - if !o.isPushMode() { - o.nextMsgSubj = fmt.Sprintf(JSApiRequestNextT, mn, o.name) - if sub, err := mset.subscribeInternal(o.nextMsgSubj, o.processNextMsgReq); err != nil { - mset.mu.Unlock() - o.deleteWithoutAdvisory() - return nil, err + // Set our ca. + if ca != nil { + o.setConsumerAssignment(ca) + } + + // Check if we have a rate limit set. + if config.RateLimit != 0 { + o.setRateLimit(config.RateLimit) + } + + mset.setConsumer(o) + mset.mu.Unlock() + + if config.Direct || (!s.JetStreamIsClustered() && s.standAloneMode()) { + o.setLeader(true) + } + + // This is always true in single server mode. + if o.IsLeader() { + // Send advisory. + var suppress bool + if !s.standAloneMode() && ca == nil { + suppress = true + } else if ca != nil { + suppress = ca.responded + } + if !suppress { + o.sendCreateAdvisory() + } + } + + return o, nil +} + +// Updates the consumer `dthresh` delete timer duration and set +// cfg.InactiveThreshold to JsDeleteWaitTimeDefault for ephemerals +// if not explicitly already specified by the user. +// Lock should be held. +func (o *consumer) updateInactiveThreshold(cfg *ConsumerConfig) { + // Ephemerals will always have inactive thresholds. + if !o.isDurable() && cfg.InactiveThreshold <= 0 { + // Add in 1 sec of jitter above and beyond the default of 5s. + o.dthresh = JsDeleteWaitTimeDefault + 100*time.Millisecond + time.Duration(rand.Int63n(900))*time.Millisecond + // Only stamp config with default sans jitter. + cfg.InactiveThreshold = JsDeleteWaitTimeDefault + } else if cfg.InactiveThreshold > 0 { + // Add in up to 1 sec of jitter if pull mode. + if o.isPullMode() { + o.dthresh = cfg.InactiveThreshold + 100*time.Millisecond + time.Duration(rand.Int63n(900))*time.Millisecond } else { - o.reqSub = sub + o.dthresh = cfg.InactiveThreshold } + } else if cfg.InactiveThreshold <= 0 { + // We accept InactiveThreshold be set to 0 (for durables) + o.dthresh = 0 } - o.setInitialPending() +} - mset.addConsumer(o) - mset.mu.Unlock() +// Updates the paused state. If we are the leader and the pause deadline +// hasn't passed yet then we will start a timer to kick the consumer once +// that deadline is reached. Lock should be held. +func (o *consumer) updatePauseState(cfg *ConsumerConfig) { + if o.uptmr != nil { + stopAndClearTimer(&o.uptmr) + } + if !o.isLeader() { + // Only the leader will run the timer as only the leader will run + // loopAndGatherMsgs. + return + } + if cfg.PauseUntil == nil || cfg.PauseUntil.IsZero() || cfg.PauseUntil.Before(time.Now()) { + // Either the PauseUntil is unset (is effectively zero) or the + // deadline has already passed, in which case there is nothing + // to do. + return + } + o.uptmr = time.AfterFunc(time.Until(*cfg.PauseUntil), func() { + o.mu.Lock() + defer o.mu.Unlock() - // If push mode, register for notifications on interest. - if o.isPushMode() { - o.dthresh = JsDeleteWaitTimeDefault - o.inch = make(chan bool, 8) - a.sl.RegisterNotification(config.DeliverSubject, o.inch) - o.active = o.hasDeliveryInterest(<-o.inch) - // Check if we are not durable that the delivery subject has interest. - if !o.isDurable() && !o.active { - o.deleteWithoutAdvisory() - return nil, fmt.Errorf("consumer requires interest for delivery subject when ephemeral") + stopAndClearTimer(&o.uptmr) + o.sendPauseAdvisoryLocked(&o.cfg) + o.signalNewMessages() + }) +} + +func (o *consumer) consumerAssignment() *consumerAssignment { + o.mu.RLock() + defer o.mu.RUnlock() + return o.ca +} + +func (o *consumer) setConsumerAssignment(ca *consumerAssignment) { + o.mu.Lock() + defer o.mu.Unlock() + + o.ca = ca + if ca == nil { + return + } + // Set our node. + o.node = ca.Group.node + + // Trigger update chan. + select { + case o.uch <- struct{}{}: + default: + } +} + +func (o *consumer) monitorQuitC() <-chan struct{} { + if o == nil { + return nil + } + o.mu.RLock() + defer o.mu.RUnlock() + return o.mqch +} + +// signalMonitorQuit signals to exit the monitor loop. If there's no Raft node, +// this will be the only way to stop the monitor goroutine. +func (o *consumer) signalMonitorQuit() { + o.mu.Lock() + defer o.mu.Unlock() + if o.mqch != nil { + close(o.mqch) + o.mqch = nil + } +} + +func (o *consumer) updateC() <-chan struct{} { + o.mu.RLock() + defer o.mu.RUnlock() + return o.uch +} + +// checkQueueInterest will check on our interest's queue group status. +// Lock should be held. +func (o *consumer) checkQueueInterest() { + if !o.active || o.cfg.DeliverSubject == _EMPTY_ { + return + } + subj := o.dsubj + if subj == _EMPTY_ { + subj = o.cfg.DeliverSubject + } + + if rr := o.acc.sl.Match(subj); len(rr.qsubs) > 0 { + // Just grab first + if qsubs := rr.qsubs[0]; len(qsubs) > 0 { + if sub := rr.qsubs[0][0]; len(sub.queue) > 0 { + o.qgroup = string(sub.queue) + } } } +} - // If we are not in ReplayInstant mode mark us as in replay state until resolved. - if config.ReplayPolicy != ReplayInstant { - o.replay = true +// clears our node if we have one. When we scale down to 1. +func (o *consumer) clearNode() { + o.mu.Lock() + defer o.mu.Unlock() + if o.node != nil { + o.node.Delete() + o.node = nil } +} - // Create internal sendq - o.sendq = make(chan *jsPubMsg, msetSendQSize) +// IsLeader will return if we are the current leader. +func (o *consumer) IsLeader() bool { + return o.isLeader() +} - // Now start up Go routine to deliver msgs. - go o.loopAndGatherMsgs(s, a) - // Startup our deliver loop. - go o.loopAndDeliverMsgs() +// Lock should be held. +func (o *consumer) isLeader() bool { + return o.leader.Load() +} - o.sendCreateAdvisory() +func (o *consumer) setLeader(isLeader bool) { + o.mu.RLock() + mset, closed := o.mset, o.closed + movingToClustered := o.node != nil && o.pch == nil + movingToNonClustered := o.node == nil && o.pch != nil + wasLeader := o.leader.Swap(isLeader) + o.mu.RUnlock() + + // If we are here we have a change in leader status. + if isLeader { + if closed || mset == nil { + return + } - return o, nil + if wasLeader { + // If we detect we are scaling up, make sure to create clustered routines and channels. + if movingToClustered { + o.mu.Lock() + // We are moving from R1 to clustered. + o.pch = make(chan struct{}, 1) + go o.loopAndForwardProposals(o.qch) + if o.phead != nil { + select { + case o.pch <- struct{}{}: + default: + } + } + o.mu.Unlock() + } else if movingToNonClustered { + // We are moving from clustered to non-clustered now. + // Set pch to nil so if we scale back up we will recreate the loopAndForward from above. + o.mu.Lock() + pch := o.pch + o.pch = nil + select { + case pch <- struct{}{}: + default: + } + o.mu.Unlock() + } + return + } + + mset.mu.RLock() + s, jsa, stream := mset.srv, mset.jsa, mset.getCfgName() + mset.mu.RUnlock() + + o.mu.Lock() + o.rdq = nil + o.rdqi.Empty() + + // Restore our saved state. + // During non-leader status we just update our underlying store when not clustered. + // If clustered we need to propose our initial (possibly skipped ahead) o.sseq to the group. + if o.node == nil || o.dseq > 1 || (o.store != nil && o.store.HasState()) { + o.readStoredState() + } else if o.node != nil && o.sseq >= 1 { + o.updateSkipped(o.sseq) + } + + // Setup initial num pending. + o.streamNumPending() + + // Cleanup lss when we take over in clustered mode. + if o.hasSkipListPending() && o.sseq >= o.lss.resume { + o.lss = nil + } + + // Do info sub. + if o.infoSub == nil && jsa != nil { + isubj := fmt.Sprintf(clusterConsumerInfoT, jsa.acc(), stream, o.name) + // Note below the way we subscribe here is so that we can send requests to ourselves. + o.infoSub, _ = s.systemSubscribe(isubj, _EMPTY_, false, o.sysc, o.handleClusterConsumerInfoRequest) + } + + var err error + if o.cfg.AckPolicy != AckNone { + if o.ackSub, err = o.subscribeInternal(o.ackSubj, o.pushAck); err != nil { + o.mu.Unlock() + return + } + } + + // Setup the internal sub for next message requests regardless. + // Will error if wrong mode to provide feedback to users. + if o.reqSub, err = o.subscribeInternal(o.nextMsgSubj, o.processNextMsgReq); err != nil { + o.mu.Unlock() + return + } + + // Check on flow control settings. + if o.cfg.FlowControl { + o.setMaxPendingBytes(JsFlowControlMaxPending) + fcsubj := fmt.Sprintf(jsFlowControl, stream, o.name) + if o.fcSub, err = o.subscribeInternal(fcsubj, o.processFlowControl); err != nil { + o.mu.Unlock() + return + } + } + + // If push mode, register for notifications on interest. + if o.isPushMode() { + o.inch = make(chan bool, 8) + o.acc.sl.registerNotification(o.cfg.DeliverSubject, o.cfg.DeliverGroup, o.inch) + if o.active = <-o.inch; o.active { + o.checkQueueInterest() + } + + // Check gateways in case they are enabled. + if s.gateway.enabled { + if !o.active { + o.active = s.hasGatewayInterest(o.acc.Name, o.cfg.DeliverSubject) + } + stopAndClearTimer(&o.gwdtmr) + o.gwdtmr = time.AfterFunc(time.Second, func() { o.watchGWinterest() }) + } + } + + if o.dthresh > 0 && (o.isPullMode() || !o.active) { + // Pull consumer. We run the dtmr all the time for this one. + stopAndClearTimer(&o.dtmr) + o.dtmr = time.AfterFunc(o.dthresh, o.deleteNotActive) + } + + // Update the consumer pause tracking. + o.updatePauseState(&o.cfg) + + // If we are not in ReplayInstant mode mark us as in replay state until resolved. + if o.cfg.ReplayPolicy != ReplayInstant { + o.replay = true + } + + // Recreate quit channel. + o.qch = make(chan struct{}) + qch := o.qch + node := o.node + if node != nil && o.pch == nil { + o.pch = make(chan struct{}, 1) + } + pullMode := o.isPullMode() + o.mu.Unlock() + + // Check if there are any pending we might need to clean up etc. + o.checkPending() + + // Snapshot initial info. + o.infoWithSnap(true) + + // These are the labels we will use to annotate our goroutines. + labels := pprofLabels{ + "type": "consumer", + "account": mset.accName(), + "stream": mset.name(), + "consumer": o.name, + } + + // Now start up Go routine to deliver msgs. + go func() { + setGoRoutineLabels(labels) + o.loopAndGatherMsgs(qch) + }() + + // Now start up Go routine to process acks. + go func() { + setGoRoutineLabels(labels) + o.processInboundAcks(qch) + }() + + if pullMode { + // Now start up Go routine to process inbound next message requests. + go func() { + setGoRoutineLabels(labels) + o.processInboundNextMsgReqs(qch) + }() + } + + // If we are R>1 spin up our proposal loop. + if node != nil { + // Determine if we can send pending requests info to the group. + // They must be on server versions >= 2.7.1 + o.checkAndSetPendingRequestsOk() + o.checkPendingRequests() + go func() { + setGoRoutineLabels(labels) + o.loopAndForwardProposals(qch) + }() + } + + } else { + // Shutdown the go routines and the subscriptions. + o.mu.Lock() + if o.qch != nil { + close(o.qch) + o.qch = nil + } + // Stop any inactivity timers. Should only be running on leaders. + stopAndClearTimer(&o.dtmr) + // Stop any unpause timers. Should only be running on leaders. + stopAndClearTimer(&o.uptmr) + // Make sure to clear out any re-deliver queues + o.stopAndClearPtmr() + o.rdq = nil + o.rdqi.Empty() + o.pending = nil + o.resetPendingDeliveries() + // ok if they are nil, we protect inside unsubscribe() + o.unsubscribe(o.ackSub) + o.unsubscribe(o.reqSub) + o.unsubscribe(o.fcSub) + o.ackSub, o.reqSub, o.fcSub = nil, nil, nil + if o.infoSub != nil { + o.srv.sysUnsubscribe(o.infoSub) + o.infoSub = nil + } + // Reset waiting if we are in pull mode. + if o.isPullMode() { + o.waiting = newWaitQueue(o.cfg.MaxWaiting) + o.nextMsgReqs.drain() + } else if o.srv.gateway.enabled { + stopAndClearTimer(&o.gwdtmr) + } + // If we were the leader make sure to drain queued up acks. + if wasLeader { + o.ackMsgs.drain() + // Reset amount of acks that need to be processed. + atomic.StoreInt64(&o.awl, 0) + // Also remove any pending replies since we should not be the one to respond at this point. + o.replies = nil + } + o.mu.Unlock() + } +} + +// This is coming on the wire so do not block here. +func (o *consumer) handleClusterConsumerInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + go o.infoWithSnapAndReply(false, reply) +} + +// Lock should be held. +func (o *consumer) subscribeInternal(subject string, cb msgHandler) (*subscription, error) { + c := o.client + if c == nil { + return nil, fmt.Errorf("invalid consumer") + } + if !c.srv.EventsEnabled() { + return nil, ErrNoSysAccount + } + if cb == nil { + return nil, fmt.Errorf("undefined message handler") + } + + o.sid++ + + // Now create the subscription + return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(o.sid)), cb, false) +} + +// Unsubscribe from our subscription. +// Lock should be held. +func (o *consumer) unsubscribe(sub *subscription) { + if sub == nil || o.client == nil { + return + } + o.client.processUnsub(sub.sid) } -// We need to make sure we protect access to the sendq. +// We need to make sure we protect access to the outq. // Do all advisory sends here. -// Lock should be held on entry but will be released. -func (o *Consumer) sendAdvisory(subj string, msg []byte) { - sendq := o.sendq - o.mu.Unlock() - if sendq != nil { - sendq <- &jsPubMsg{subj, subj, _EMPTY_, nil, msg, nil, 0} +func (o *consumer) sendAdvisory(subject string, e any) { + if o.acc == nil { + return } - o.mu.Lock() + + // If there is no one listening for this advisory then save ourselves the effort + // and don't bother encoding the JSON or sending it. + if sl := o.acc.sl; (sl != nil && !sl.HasInterest(subject)) && !o.srv.hasGatewayInterest(o.acc.Name, subject) { + return + } + + j, err := json.Marshal(e) + if err != nil { + return + } + + o.outq.sendMsg(subject, j) } -func (o *Consumer) sendDeleteAdvisoryLocked() { +func (o *consumer) sendDeleteAdvisoryLocked() { e := JSConsumerActionAdvisory{ TypedEvent: TypedEvent{ Type: JSConsumerActionAdvisoryType, @@ -587,18 +1666,53 @@ func (o *Consumer) sendDeleteAdvisoryLocked() { Stream: o.stream, Consumer: o.name, Action: DeleteEvent, + Domain: o.srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(e, "", " ") - if err != nil { - return + subj := JSAdvisoryConsumerDeletedPre + "." + o.stream + "." + o.name + o.sendAdvisory(subj, e) +} + +func (o *consumer) sendPinnedAdvisoryLocked(group string) { + e := JSConsumerGroupPinnedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSConsumerGroupPinnedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Account: o.acc.Name, + Stream: o.stream, + Consumer: o.name, + Domain: o.srv.getOpts().JetStreamDomain, + PinnedClientId: o.currentPinId, + Group: group, } - subj := JSAdvisoryConsumerDeletedPre + "." + o.stream + "." + o.name - o.sendAdvisory(subj, j) + subj := JSAdvisoryConsumerPinnedPre + "." + o.stream + "." + o.name + o.sendAdvisory(subj, e) + +} +func (o *consumer) sendUnpinnedAdvisoryLocked(group string, reason string) { + e := JSConsumerGroupUnpinnedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSConsumerGroupUnpinnedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Account: o.acc.Name, + Stream: o.stream, + Consumer: o.name, + Domain: o.srv.getOpts().JetStreamDomain, + Group: group, + Reason: reason, + } + + subj := JSAdvisoryConsumerUnpinnedPre + "." + o.stream + "." + o.name + o.sendAdvisory(subj, e) + } -func (o *Consumer) sendCreateAdvisory() { +func (o *consumer) sendCreateAdvisory() { o.mu.Lock() defer o.mu.Unlock() @@ -611,19 +1725,36 @@ func (o *Consumer) sendCreateAdvisory() { Stream: o.stream, Consumer: o.name, Action: CreateEvent, + Domain: o.srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(e, "", " ") - if err != nil { - return + subj := JSAdvisoryConsumerCreatedPre + "." + o.stream + "." + o.name + o.sendAdvisory(subj, e) +} + +func (o *consumer) sendPauseAdvisoryLocked(cfg *ConsumerConfig) { + e := JSConsumerPauseAdvisory{ + TypedEvent: TypedEvent{ + Type: JSConsumerPauseAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Stream: o.stream, + Consumer: o.name, + Domain: o.srv.getOpts().JetStreamDomain, } - subj := JSAdvisoryConsumerCreatedPre + "." + o.stream + "." + o.name - o.sendAdvisory(subj, j) + if cfg.PauseUntil != nil { + e.PauseUntil = *cfg.PauseUntil + e.Paused = time.Now().Before(e.PauseUntil) + } + + subj := JSAdvisoryConsumerPausePre + "." + o.stream + "." + o.name + o.sendAdvisory(subj, e) } // Created returns created time. -func (o *Consumer) Created() time.Time { +func (o *consumer) createdTime() time.Time { o.mu.Lock() created := o.created o.mu.Unlock() @@ -631,7 +1762,7 @@ func (o *Consumer) Created() time.Time { } // Internal to allow creation time to be restored. -func (o *Consumer) setCreated(created time.Time) { +func (o *consumer) setCreatedTime(created time.Time) { o.mu.Lock() o.created = created o.mu.Unlock() @@ -640,39 +1771,46 @@ func (o *Consumer) setCreated(created time.Time) { // This will check for extended interest in a subject. If we have local interest we just return // that, but in the absence of local interest and presence of gateways or service imports we need // to check those as well. -func (o *Consumer) hasDeliveryInterest(localInterest bool) bool { - o.mu.Lock() +func (o *consumer) hasDeliveryInterest(localInterest bool) bool { + o.mu.RLock() mset := o.mset if mset == nil { - o.mu.Unlock() + o.mu.RUnlock() return false } acc := o.acc - deliver := o.config.DeliverSubject - o.mu.Unlock() + deliver := o.cfg.DeliverSubject + o.mu.RUnlock() if localInterest { return true } // If we are here check gateways. - if acc.srv != nil && acc.srv.gateway.enabled { - gw := acc.srv.gateway - gw.RLock() - for _, gwc := range gw.outo { - psi, qr := gwc.gatewayInterest(acc.Name, deliver) - if psi || qr != nil { - gw.RUnlock() - return true - } + if s := acc.srv; s != nil && s.hasGatewayInterest(acc.Name, deliver) { + return true + } + return false +} + +func (s *Server) hasGatewayInterest(account, subject string) bool { + gw := s.gateway + if !gw.enabled { + return false + } + gw.RLock() + defer gw.RUnlock() + for _, gwc := range gw.outo { + psi, qr := gwc.gatewayInterest(account, stringToBytes(subject)) + if psi || qr != nil { + return true } - gw.RUnlock() } return false } // This processes an update to the local interest for a deliver subject. -func (o *Consumer) updateDeliveryInterest(localInterest bool) { +func (o *consumer) updateDeliveryInterest(localInterest bool) bool { interest := o.hasDeliveryInterest(localInterest) o.mu.Lock() @@ -680,65 +1818,560 @@ func (o *Consumer) updateDeliveryInterest(localInterest bool) { mset := o.mset if mset == nil || o.isPullMode() { - return + return false } if interest && !o.active { o.signalNewMessages() } - o.active = interest + // Update active status, if not active clear any queue group we captured. + if o.active = interest; !o.active { + o.qgroup = _EMPTY_ + } else { + o.checkQueueInterest() + } + + // If the delete timer has already been set do not clear here and return. + // Note that durable can now have an inactive threshold, so don't check + // for durable status, instead check for dthresh > 0. + if o.dtmr != nil && o.dthresh > 0 && !interest { + return true + } // Stop and clear the delete timer always. stopAndClearTimer(&o.dtmr) - // If we do not have interest anymore and we are not durable start + // If we do not have interest anymore and have a delete threshold set, then set // a timer to delete us. We wait for a bit in case of server reconnect. - if !o.isDurable() && !interest { - o.dtmr = time.AfterFunc(o.dthresh, func() { o.Delete() }) + if !interest && o.dthresh > 0 { + o.dtmr = time.AfterFunc(o.dthresh, o.deleteNotActive) + return true } + return false } -// Config returns the consumer's configuration. -func (o *Consumer) Config() ConsumerConfig { - o.mu.Lock() - defer o.mu.Unlock() - return o.config -} +const ( + defaultConsumerNotActiveStartInterval = 30 * time.Second + defaultConsumerNotActiveMaxInterval = 5 * time.Minute +) -// Force expiration of all pending. -// Lock should be held. -func (o *Consumer) forceExpirePending() { - now := time.Now().UnixNano() - var expired []uint64 - for seq := range o.pending { - if !o.onRedeliverQueue(seq) { - expired = append(expired, seq) - } - } - if len(expired) > 0 { - sort.Slice(expired, func(i, j int) bool { return expired[i] < expired[j] }) - o.rdq = append(o.rdq, expired...) - // Now we should update the timestamp here since we are redelivering. - // We will use an incrementing time to preserve order for any other redelivery. - off := now - o.pending[expired[0]].Timestamp - for _, seq := range expired { - if p, ok := o.pending[seq]; ok && p != nil { - p.Timestamp += off - } - } - o.ptmr.Reset(o.ackWait(0)) - } - o.signalNewMessages() -} +var ( + consumerNotActiveStartInterval = defaultConsumerNotActiveStartInterval + consumerNotActiveMaxInterval = defaultConsumerNotActiveMaxInterval +) + +// deleteNotActive must only be called from time.AfterFunc or in its own +// goroutine, as it can block on clean-up. +func (o *consumer) deleteNotActive() { + // Take a copy of these when the goroutine starts, mostly it avoids a + // race condition with tests that modify these consts, such as + // TestJetStreamClusterGhostEphemeralsAfterRestart. + cnaMax := consumerNotActiveMaxInterval + cnaStart := consumerNotActiveStartInterval + + o.mu.Lock() + if o.mset == nil { + o.mu.Unlock() + return + } + // Push mode just look at active. + if o.isPushMode() { + // If we are active simply return. + if o.active { + o.mu.Unlock() + return + } + } else { + // Pull mode. + elapsed := time.Since(o.waiting.last) + if elapsed < o.dthresh { + // These need to keep firing so reset but use delta. + if o.dtmr != nil { + o.dtmr.Reset(o.dthresh - elapsed) + } else { + o.dtmr = time.AfterFunc(o.dthresh-elapsed, o.deleteNotActive) + } + o.mu.Unlock() + return + } + // Check if we still have valid requests waiting. + if o.checkWaitingForInterest() { + if o.dtmr != nil { + o.dtmr.Reset(o.dthresh) + } else { + o.dtmr = time.AfterFunc(o.dthresh, o.deleteNotActive) + } + o.mu.Unlock() + return + } + + // We now know we have no waiting requests, and our last request was long ago. + // However, based on AckWait the consumer could still be actively processing, + // even if we haven't been informed if there were no acks in the meantime. + // We must wait for the message that expires last and start counting down the + // inactive threshold from there. + now := time.Now().UnixNano() + l := len(o.cfg.BackOff) + var delay time.Duration + var ackWait time.Duration + for _, p := range o.pending { + if l == 0 { + ackWait = o.ackWait(0) + } else { + bi := int(o.rdc[p.Sequence]) + if bi < 0 { + bi = 0 + } else if bi >= l { + bi = l - 1 + } + ackWait = o.ackWait(o.cfg.BackOff[bi]) + } + if ts := p.Timestamp + ackWait.Nanoseconds() + o.dthresh.Nanoseconds(); ts > now { + delay = max(delay, time.Duration(ts-now)) + } + } + // We'll wait for the latest time we expect an ack, plus the inactive threshold. + // Acknowledging a message will reset this back down to just the inactive threshold. + if delay > 0 { + if o.dtmr != nil { + o.dtmr.Reset(delay) + } else { + o.dtmr = time.AfterFunc(delay, o.deleteNotActive) + } + o.mu.Unlock() + return + } + } + + s, js := o.mset.srv, o.srv.js.Load() + acc, stream, name, isDirect := o.acc.Name, o.stream, o.name, o.cfg.Direct + var qch, cqch chan struct{} + if o.srv != nil { + qch = o.srv.quitCh + } + o.mu.Unlock() + if js != nil { + cqch = js.clusterQuitC() + } + + // Useful for pprof. + setGoRoutineLabels(pprofLabels{ + "account": acc, + "stream": stream, + "consumer": name, + }) + + // We will delete locally regardless. + defer o.delete() + + // If we are clustered, check if we still have this consumer assigned. + // If we do forward a proposal to delete ourselves to the metacontroller leader. + if !isDirect && s.JetStreamIsClustered() { + js.mu.RLock() + var ( + cca consumerAssignment + meta RaftNode + removeEntry []byte + ) + ca, cc := js.consumerAssignment(acc, stream, name), js.cluster + if ca != nil && cc != nil { + meta = cc.meta + cca = *ca + cca.Reply = _EMPTY_ + removeEntry = encodeDeleteConsumerAssignment(&cca) + meta.ForwardProposal(removeEntry) + } + js.mu.RUnlock() + + if ca != nil && cc != nil { + // Check to make sure we went away. + // Don't think this needs to be a monitored go routine. + jitter := time.Duration(rand.Int63n(int64(cnaStart))) + interval := cnaStart + jitter + ticker := time.NewTicker(interval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + case <-qch: + return + case <-cqch: + return + } + js.mu.RLock() + if js.shuttingDown { + js.mu.RUnlock() + return + } + nca := js.consumerAssignment(acc, stream, name) + js.mu.RUnlock() + // Make sure this is the same consumer assignment, and not a new consumer with the same name. + if nca != nil && reflect.DeepEqual(nca, ca) { + s.Warnf("Consumer assignment for '%s > %s > %s' not cleaned up, retrying", acc, stream, name) + meta.ForwardProposal(removeEntry) + if interval < cnaMax { + interval *= 2 + ticker.Reset(interval) + } + continue + } + // We saw that consumer has been removed, all done. + return + } + } + } +} + +func (o *consumer) watchGWinterest() { + pa := o.isActive() + // If there is no local interest... + if o.hasNoLocalInterest() { + o.updateDeliveryInterest(false) + if !pa && o.isActive() { + o.signalNewMessages() + } + } + + // We want this to always be running so we can also pick up on interest returning. + o.mu.Lock() + if o.gwdtmr != nil { + o.gwdtmr.Reset(time.Second) + } else { + stopAndClearTimer(&o.gwdtmr) + o.gwdtmr = time.AfterFunc(time.Second, func() { o.watchGWinterest() }) + } + o.mu.Unlock() +} + +// Config returns the consumer's configuration. +func (o *consumer) config() ConsumerConfig { + o.mu.Lock() + defer o.mu.Unlock() + return o.cfg +} + +// Check if we have hit max deliveries. If so do notification and cleanup. +// Return whether or not the max was hit. +// Lock should be held. +func (o *consumer) hasMaxDeliveries(seq uint64) bool { + if o.maxdc == 0 { + return false + } + if dc := o.deliveryCount(seq); dc >= o.maxdc { + // We have hit our max deliveries for this sequence. + // Only send the advisory once. + if dc == o.maxdc { + o.notifyDeliveryExceeded(seq, dc) + } + // Determine if we signal to start flow of messages again. + if o.maxp > 0 && len(o.pending) >= o.maxp { + o.signalNewMessages() + } + // Make sure to remove from pending. + if p, ok := o.pending[seq]; ok && p != nil { + delete(o.pending, seq) + o.updateDelivered(p.Sequence, seq, dc, p.Timestamp) + } + // Ensure redelivered state is set, if not already. + if o.rdc == nil { + o.rdc = make(map[uint64]uint64) + } + o.rdc[seq] = dc + return true + } + return false +} + +// Force expiration of all pending. +// Lock should be held. +func (o *consumer) forceExpirePending() { + var expired []uint64 + for seq := range o.pending { + if !o.onRedeliverQueue(seq) && !o.hasMaxDeliveries(seq) { + expired = append(expired, seq) + } + } + if len(expired) > 0 { + slices.Sort(expired) + o.addToRedeliverQueue(expired...) + // Now we should update the timestamp here since we are redelivering. + // We will use an incrementing time to preserve order for any other redelivery. + off := time.Now().UnixNano() - o.pending[expired[0]].Timestamp + for _, seq := range expired { + if p, ok := o.pending[seq]; ok && p != nil { + p.Timestamp += off + } + } + o.resetPtmr(o.ackWait(0)) + } + o.signalNewMessages() +} + +// Acquire proper locks and update rate limit. +// Will use what is in config. +func (o *consumer) setRateLimitNeedsLocks() { + o.mu.RLock() + mset := o.mset + o.mu.RUnlock() + + if mset == nil { + return + } + + mset.mu.RLock() + o.mu.Lock() + o.setRateLimit(o.cfg.RateLimit) + o.mu.Unlock() + mset.mu.RUnlock() +} + +// Set the rate limiter +// Both mset and consumer lock should be held. +func (o *consumer) setRateLimit(bps uint64) { + if bps == 0 { + o.rlimit = nil + return + } + + // TODO(dlc) - Make sane values or error if not sane? + // We are configured in bits per sec so adjust to bytes. + rl := rate.Limit(bps / 8) + mset := o.mset + + // Burst should be set to maximum msg size for this account, etc. + var burst int + // We don't need to get cfgMu's rlock here since this function + // is already invoked under mset.mu.RLock(), which superseeds cfgMu. + if mset.cfg.MaxMsgSize > 0 { + burst = int(mset.cfg.MaxMsgSize) + } else if mset.jsa.account.limits.mpay > 0 { + burst = int(mset.jsa.account.limits.mpay) + } else { + s := mset.jsa.account.srv + burst = int(s.getOpts().MaxPayload) + } + + o.rlimit = rate.NewLimiter(rl, burst) +} + +// Check if new consumer config allowed vs old. +func (acc *Account) checkNewConsumerConfig(cfg, ncfg *ConsumerConfig) error { + if reflect.DeepEqual(cfg, ncfg) { + return nil + } + // Something different, so check since we only allow certain things to be updated. + if cfg.DeliverPolicy != ncfg.DeliverPolicy { + return errors.New("deliver policy can not be updated") + } + if cfg.OptStartSeq != ncfg.OptStartSeq { + return errors.New("start sequence can not be updated") + } + if cfg.OptStartTime != nil && ncfg.OptStartTime != nil { + // Both have start times set, compare them directly: + if !cfg.OptStartTime.Equal(*ncfg.OptStartTime) { + return errors.New("start time can not be updated") + } + } else if cfg.OptStartTime != nil || ncfg.OptStartTime != nil { + // At least one start time is set and the other is not + return errors.New("start time can not be updated") + } + if cfg.AckPolicy != ncfg.AckPolicy { + return errors.New("ack policy can not be updated") + } + if cfg.ReplayPolicy != ncfg.ReplayPolicy { + return errors.New("replay policy can not be updated") + } + if cfg.Heartbeat != ncfg.Heartbeat { + return errors.New("heart beats can not be updated") + } + if cfg.FlowControl != ncfg.FlowControl { + return errors.New("flow control can not be updated") + } + + // Deliver Subject is conditional on if its bound. + if cfg.DeliverSubject != ncfg.DeliverSubject { + if cfg.DeliverSubject == _EMPTY_ { + return errors.New("can not update pull consumer to push based") + } + if ncfg.DeliverSubject == _EMPTY_ { + return errors.New("can not update push consumer to pull based") + } + if acc.sl.HasInterest(cfg.DeliverSubject) { + return NewJSConsumerNameExistError() + } + } + + if cfg.MaxWaiting != ncfg.MaxWaiting { + return errors.New("max waiting can not be updated") + } + + // Check if BackOff is defined, MaxDeliver is within range. + if lbo := len(ncfg.BackOff); lbo > 0 && ncfg.MaxDeliver != -1 && lbo > ncfg.MaxDeliver { + return NewJSConsumerMaxDeliverBackoffError() + } + + return nil +} + +// Update the config based on the new config, or error if update not allowed. +func (o *consumer) updateConfig(cfg *ConsumerConfig) error { + o.mu.Lock() + defer o.mu.Unlock() + + if o.closed || o.mset == nil { + return NewJSConsumerDoesNotExistError() + } + + if err := o.acc.checkNewConsumerConfig(&o.cfg, cfg); err != nil { + return err + } + + // Make sure we always store PauseUntil in UTC. + if cfg.PauseUntil != nil { + utc := (*cfg.PauseUntil).UTC() + cfg.PauseUntil = &utc + } + + if o.store != nil { + // Update local state always. + if err := o.store.UpdateConfig(cfg); err != nil { + return err + } + } + + // DeliverSubject + if cfg.DeliverSubject != o.cfg.DeliverSubject { + o.updateDeliverSubjectLocked(cfg.DeliverSubject) + } + + // MaxAckPending + if cfg.MaxAckPending != o.cfg.MaxAckPending { + o.maxp = cfg.MaxAckPending + o.signalNewMessages() + // If MaxAckPending is lowered, we could have allocated a pending deliveries map of larger size. + // Reset it here, so we can shrink the map. + if cfg.MaxAckPending < o.cfg.MaxAckPending { + o.resetPendingDeliveries() + } + } + // AckWait + if cfg.AckWait != o.cfg.AckWait { + if o.ptmr != nil { + o.resetPtmr(100 * time.Millisecond) + } + } + // Rate Limit + if cfg.RateLimit != o.cfg.RateLimit { + // We need both locks here so do in Go routine. + go o.setRateLimitNeedsLocks() + } + if cfg.SampleFrequency != o.cfg.SampleFrequency { + s := strings.TrimSuffix(cfg.SampleFrequency, "%") + if sampleFreq, err := strconv.ParseInt(s, 10, 32); err == nil { + o.sfreq = int32(sampleFreq) + } + } + // Set MaxDeliver if changed + if cfg.MaxDeliver != o.cfg.MaxDeliver { + // MaxDeliver is negative (-1) when infinite. + o.maxdc = uint64(max(cfg.MaxDeliver, 0)) + } + // Set InactiveThreshold if changed. + if val := cfg.InactiveThreshold; val != o.cfg.InactiveThreshold { + o.updateInactiveThreshold(cfg) + stopAndClearTimer(&o.dtmr) + // Restart timer only if we are the leader. + if o.isLeader() && o.dthresh > 0 { + o.dtmr = time.AfterFunc(o.dthresh, o.deleteNotActive) + } + } + // Check whether the pause has changed + { + var old, new time.Time + if o.cfg.PauseUntil != nil { + old = *o.cfg.PauseUntil + } + if cfg.PauseUntil != nil { + new = *cfg.PauseUntil + } + if !old.Equal(new) { + o.updatePauseState(cfg) + if o.isLeader() { + o.sendPauseAdvisoryLocked(cfg) + } + } + } + + // Check for Subject Filters update. + newSubjects := gatherSubjectFilters(cfg.FilterSubject, cfg.FilterSubjects) + updatedFilters := !subjectSliceEqual(newSubjects, o.subjf.subjects()) + if updatedFilters { + newSubjf := make(subjectFilters, 0, len(newSubjects)) + for _, newFilter := range newSubjects { + fs := &subjectFilter{ + subject: newFilter, + hasWildcard: subjectHasWildcard(newFilter), + tokenizedSubject: tokenizeSubjectIntoSlice(nil, newFilter), + } + newSubjf = append(newSubjf, fs) + } + // Make sure we have correct signaling setup. + // Consumer lock can not be held. + mset := o.mset + o.mu.Unlock() + mset.swapSigSubs(o, newSubjf.subjects()) + o.mu.Lock() + + // When we're done with signaling, we can replace the subjects. + // If filters were removed, set `o.subjf` to nil. + if len(newSubjf) == 0 { + o.subjf = nil + o.filters = nil + } else { + o.subjf = newSubjf + if len(o.subjf) == 1 { + o.filters = nil + } else { + o.filters = gsl.NewSublist[struct{}]() + for _, filter := range o.subjf { + o.filters.Insert(filter.subject, struct{}{}) + } + } + } + } + + // Record new config for others that do not need special handling. + // Allowed but considered no-op, [Description, SampleFrequency, MaxWaiting, HeadersOnly] + o.cfg = *cfg + + if updatedFilters { + // Cleanup messages that lost interest. + if o.retention == InterestPolicy { + o.mu.Unlock() + o.cleanupNoInterestMessages(o.mset, false) + o.mu.Lock() + } + + // Re-calculate num pending on update. + o.streamNumPending() + } + + return nil +} // This is a config change for the delivery subject for a // push based consumer. -func (o *Consumer) updateDeliverSubject(newDeliver string) { +func (o *consumer) updateDeliverSubject(newDeliver string) { // Update the config and the dsubj o.mu.Lock() defer o.mu.Unlock() + o.updateDeliverSubjectLocked(newDeliver) +} - if o.closed || o.isPullMode() || o.config.DeliverSubject == newDeliver { +// This is a config change for the delivery subject for a +// push based consumer. +func (o *consumer) updateDeliverSubjectLocked(newDeliver string) { + if o.closed || o.isPullMode() || o.cfg.DeliverSubject == newDeliver { return } @@ -747,45 +2380,102 @@ func (o *Consumer) updateDeliverSubject(newDeliver string) { o.forceExpirePending() } - o.acc.sl.ClearNotification(o.dsubj, o.inch) - o.dsubj, o.config.DeliverSubject = newDeliver, newDeliver + o.acc.sl.clearNotification(o.dsubj, o.cfg.DeliverGroup, o.inch) + o.dsubj, o.cfg.DeliverSubject = newDeliver, newDeliver // When we register new one it will deliver to update state loop. - o.acc.sl.RegisterNotification(newDeliver, o.inch) + o.acc.sl.registerNotification(newDeliver, o.cfg.DeliverGroup, o.inch) } // Check that configs are equal but allow delivery subjects to be different. func configsEqualSansDelivery(a, b ConsumerConfig) bool { // These were copied in so can set Delivery here. a.DeliverSubject, b.DeliverSubject = _EMPTY_, _EMPTY_ - return a == b + return reflect.DeepEqual(a, b) } // Helper to send a reply to an ack. -func (o *Consumer) sendAckReply(subj string) { - o.mu.Lock() - defer o.mu.Unlock() - o.sendAdvisory(subj, nil) +func (o *consumer) sendAckReply(subj string) { + o.mu.RLock() + defer o.mu.RUnlock() + o.outq.sendMsg(subj, nil) +} + +type jsAckMsg struct { + subject string + reply string + hdr int + msg []byte +} + +var jsAckMsgPool sync.Pool + +func newJSAckMsg(subj, reply string, hdr int, msg []byte) *jsAckMsg { + var m *jsAckMsg + am := jsAckMsgPool.Get() + if am != nil { + m = am.(*jsAckMsg) + } else { + m = &jsAckMsg{} + } + // When getting something from a pool it is critical that all fields are + // initialized. Doing this way guarantees that if someone adds a field to + // the structure, the compiler will fail the build if this line is not updated. + (*m) = jsAckMsg{subj, reply, hdr, msg} + return m +} + +func (am *jsAckMsg) returnToPool() { + if am == nil { + return + } + am.subject, am.reply, am.hdr, am.msg = _EMPTY_, _EMPTY_, -1, nil + jsAckMsgPool.Put(am) } -// Process a message for the ack reply subject delivered with a message. -func (o *Consumer) processAck(_ *subscription, _ *client, subject, reply string, msg []byte) { +// Push the ack message to the consumer's ackMsgs queue +func (o *consumer) pushAck(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + atomic.AddInt64(&o.awl, 1) + o.ackMsgs.push(newJSAckMsg(subject, reply, c.pa.hdr, copyBytes(rmsg))) +} + +// Processes a message for the ack reply subject delivered with a message. +func (o *consumer) processAck(subject, reply string, hdr int, rmsg []byte) { + defer atomic.AddInt64(&o.awl, -1) + + var msg []byte + if hdr > 0 { + msg = rmsg[hdr:] + } else { + msg = rmsg + } + sseq, dseq, dc := ackReplyInfo(subject) skipAckReply := sseq == 0 switch { case len(msg) == 0, bytes.Equal(msg, AckAck), bytes.Equal(msg, AckOK): - o.ackMsg(sseq, dseq, dc) + if !o.processAckMsg(sseq, dseq, dc, reply, true) { + // We handle replies for acks in updateAcks + skipAckReply = true + } case bytes.HasPrefix(msg, AckNext): - o.ackMsg(sseq, dseq, dc) - o.processNextMsgReq(nil, nil, subject, reply, msg[len(AckNext):]) + o.processAckMsg(sseq, dseq, dc, _EMPTY_, true) + o.processNextMsgRequest(reply, msg[len(AckNext):]) skipAckReply = true - case bytes.Equal(msg, AckNak): - o.processNak(sseq, dseq) + case bytes.HasPrefix(msg, AckNak): + o.processNak(sseq, dseq, dc, msg) case bytes.Equal(msg, AckProgress): o.progressUpdate(sseq) - case bytes.Equal(msg, AckTerm): - o.processTerm(sseq, dseq, dc) + case bytes.HasPrefix(msg, AckTerm): + var reason string + if buf := msg[len(AckTerm):]; len(buf) > 0 { + reason = string(bytes.TrimSpace(buf)) + } + if !o.processTerm(sseq, dseq, dc, reason, reply) { + // We handle replies for acks in updateAcks + skipAckReply = true + } } // Ack the ack if requested. @@ -795,20 +2485,285 @@ func (o *Consumer) processAck(_ *subscription, _ *client, subject, reply string, } // Used to process a working update to delay redelivery. -func (o *Consumer) progressUpdate(seq uint64) { +func (o *consumer) progressUpdate(seq uint64) { o.mu.Lock() - if len(o.pending) > 0 { - if p, ok := o.pending[seq]; ok { - p.Timestamp = time.Now().UnixNano() - // Update store system. - o.store.UpdateDelivered(p.Sequence, seq, 1, p.Timestamp) + defer o.mu.Unlock() + + if p, ok := o.pending[seq]; ok { + p.Timestamp = time.Now().UnixNano() + // Update store system. + o.updateDelivered(p.Sequence, seq, 1, p.Timestamp) + } +} + +// Lock should be held. +func (o *consumer) updateSkipped(seq uint64) { + // Clustered mode and R>1 only. + if o.node == nil || !o.isLeader() { + return + } + var b [1 + 8]byte + b[0] = byte(updateSkipOp) + var le = binary.LittleEndian + le.PutUint64(b[1:], seq) + o.propose(b[:]) +} + +func (o *consumer) loopAndForwardProposals(qch chan struct{}) { + // On exit make sure we nil out pch. + defer func() { + o.mu.Lock() + o.pch = nil + o.mu.Unlock() + }() + + o.mu.RLock() + node, pch := o.node, o.pch + o.mu.RUnlock() + + if node == nil || pch == nil { + return + } + + forwardProposals := func() error { + o.mu.Lock() + if o.node == nil || !o.node.Leader() { + o.mu.Unlock() + return errors.New("no longer leader") + } + proposal := o.phead + o.phead, o.ptail = nil, nil + o.mu.Unlock() + // 256k max for now per batch. + const maxBatch = 256 * 1024 + var entries []*Entry + for sz := 0; proposal != nil; proposal = proposal.next { + entries = append(entries, newEntry(EntryNormal, proposal.data)) + sz += len(proposal.data) + if sz > maxBatch { + node.ProposeMulti(entries) + // We need to re-create `entries` because there is a reference + // to it in the node's pae map. + sz, entries = 0, nil + } } + if len(entries) > 0 { + node.ProposeMulti(entries) + } + return nil } + + // In case we have anything pending on entry. + forwardProposals() + + for { + select { + case <-qch: + forwardProposals() + return + case <-pch: + if err := forwardProposals(); err != nil { + return + } + } + } +} + +// Lock should be held. +func (o *consumer) propose(entry []byte) { + p := &proposal{data: entry} + if o.phead == nil { + o.phead = p + } else { + o.ptail.next = p + } + o.ptail = p + + // Kick our looper routine. + select { + case o.pch <- struct{}{}: + default: + } +} + +// Lock should be held. +func (o *consumer) updateDelivered(dseq, sseq, dc uint64, ts int64) { + // Clustered mode and R>1. + if o.node != nil { + // Inline for now, use variable compression. + var b [4*binary.MaxVarintLen64 + 1]byte + b[0] = byte(updateDeliveredOp) + n := 1 + n += binary.PutUvarint(b[n:], dseq) + n += binary.PutUvarint(b[n:], sseq) + n += binary.PutUvarint(b[n:], dc) + n += binary.PutVarint(b[n:], ts) + o.propose(b[:n]) + } else if o.store != nil { + o.store.UpdateDelivered(dseq, sseq, dc, ts) + } + // Update activity. + o.ldt = time.Now() +} + +// Used to remember a pending ack reply in a replicated consumer. +// Lock should be held. +func (o *consumer) addAckReply(sseq uint64, reply string) { + if o.replies == nil { + o.replies = make(map[uint64]string) + } + o.replies[sseq] = reply +} + +// Used to remember messages that need to be sent for a replicated consumer, after delivered quorum. +// Lock should be held. +func (o *consumer) addReplicatedQueuedMsg(pmsg *jsPubMsg) { + // Is not explicitly limited in size, but will at most hold maximum ack pending. + if o.pendingDeliveries == nil { + o.pendingDeliveries = make(map[uint64]*jsPubMsg) + } + o.pendingDeliveries[pmsg.seq] = pmsg + + // Is not explicitly limited in size, but will at most hold maximum waiting requests. + if o.waitingDeliveries == nil { + o.waitingDeliveries = make(map[string]*waitingDelivery) + } + if wd, ok := o.waitingDeliveries[pmsg.dsubj]; ok { + wd.seq = pmsg.seq + } else { + wd := wdPool.Get().(*waitingDelivery) + wd.seq = pmsg.seq + o.waitingDeliveries[pmsg.dsubj] = wd + } +} + +// Lock should be held. +func (o *consumer) updateAcks(dseq, sseq uint64, reply string) { + if o.node != nil { + // Inline for now, use variable compression. + var b [2*binary.MaxVarintLen64 + 1]byte + b[0] = byte(updateAcksOp) + n := 1 + n += binary.PutUvarint(b[n:], dseq) + n += binary.PutUvarint(b[n:], sseq) + o.propose(b[:n]) + if reply != _EMPTY_ { + o.addAckReply(sseq, reply) + } + } else if o.store != nil { + o.store.UpdateAcks(dseq, sseq) + if reply != _EMPTY_ { + // Already locked so send direct. + o.outq.sendMsg(reply, nil) + } + } + // Update activity. + o.lat = time.Now() +} + +// Communicate to the cluster an addition of a pending request. +// Lock should be held. +func (o *consumer) addClusterPendingRequest(reply string) { + if o.node == nil || !o.pendingRequestsOk() { + return + } + b := make([]byte, len(reply)+1) + b[0] = byte(addPendingRequest) + copy(b[1:], reply) + o.propose(b) +} + +// Communicate to the cluster a removal of a pending request. +// Lock should be held. +func (o *consumer) removeClusterPendingRequest(reply string) { + if o.node == nil || !o.pendingRequestsOk() { + return + } + b := make([]byte, len(reply)+1) + b[0] = byte(removePendingRequest) + copy(b[1:], reply) + o.propose(b) +} + +// Set whether or not we can send pending requests to followers. +func (o *consumer) setPendingRequestsOk(ok bool) { + o.mu.Lock() + o.prOk = ok o.mu.Unlock() } +// Lock should be held. +func (o *consumer) pendingRequestsOk() bool { + return o.prOk +} + +// Set whether or not we can send info about pending pull requests to our group. +// Will require all peers have a minimum version. +func (o *consumer) checkAndSetPendingRequestsOk() { + o.mu.RLock() + s, isValid := o.srv, o.mset != nil + o.mu.RUnlock() + if !isValid { + return + } + + if ca := o.consumerAssignment(); ca != nil && len(ca.Group.Peers) > 1 { + for _, pn := range ca.Group.Peers { + if si, ok := s.nodeToInfo.Load(pn); ok { + if !versionAtLeast(si.(nodeInfo).version, 2, 7, 1) { + // We expect all of our peers to eventually be up to date. + // So check again in awhile. + time.AfterFunc(eventsHBInterval, func() { o.checkAndSetPendingRequestsOk() }) + o.setPendingRequestsOk(false) + return + } + } + } + } + o.setPendingRequestsOk(true) +} + +// On leadership change make sure we alert the pending requests that they are no longer valid. +func (o *consumer) checkPendingRequests() { + o.mu.Lock() + defer o.mu.Unlock() + if o.mset == nil || o.outq == nil { + return + } + hdr := []byte("NATS/1.0 409 Leadership Change\r\n\r\n") + for reply := range o.prm { + o.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + } + o.prm = nil +} + +// This will release any pending pull requests if applicable. +// Should be called only by the leader being deleted or stopped. +// Lock should be held. +func (o *consumer) releaseAnyPendingRequests(isAssigned bool) { + if o.mset == nil || o.outq == nil || o.waiting.len() == 0 { + return + } + var hdr []byte + if !isAssigned { + hdr = []byte("NATS/1.0 409 Consumer Deleted\r\n\r\n") + } + + wq := o.waiting + for wr := wq.head; wr != nil; { + if hdr != nil { + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + } + next := wr.next + wr.recycle() + wr = next + } + // Nil out old queue. + o.waiting = nil +} + // Process a NAK. -func (o *Consumer) processNak(sseq, dseq uint64) { +func (o *consumer) processNak(sseq, dseq, dc uint64, nak []byte) { o.mu.Lock() defer o.mu.Unlock() @@ -817,23 +2772,80 @@ func (o *Consumer) processNak(sseq, dseq uint64) { return } // If we are explicit ack make sure this is still on our pending list. - if len(o.pending) > 0 { - if _, ok := o.pending[sseq]; !ok { - return + if _, ok := o.pending[sseq]; !ok { + return + } + + // Deliver an advisory + e := JSConsumerDeliveryNakAdvisory{ + TypedEvent: TypedEvent{ + Type: JSConsumerDeliveryNakAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Stream: o.stream, + Consumer: o.name, + ConsumerSeq: dseq, + StreamSeq: sseq, + Deliveries: dc, + Domain: o.srv.getOpts().JetStreamDomain, + } + + o.sendAdvisory(o.nakEventT, e) + + // Check to see if we have delays attached. + if len(nak) > len(AckNak) { + arg := bytes.TrimSpace(nak[len(AckNak):]) + if len(arg) > 0 { + var d time.Duration + var err error + if arg[0] == '{' { + var nd ConsumerNakOptions + if err = json.Unmarshal(arg, &nd); err == nil { + d = nd.Delay + } + } else { + d, err = time.ParseDuration(string(arg)) + } + if err != nil { + // Treat this as normal NAK. + o.srv.Warnf("JetStream consumer '%s > %s > %s' bad NAK delay value: %q", o.acc.Name, o.stream, o.name, arg) + } else { + // We have a parsed duration that the user wants us to wait before retrying. + // Make sure we are not on the rdq. + o.removeFromRedeliverQueue(sseq) + if p, ok := o.pending[sseq]; ok { + // now - ackWait is expired now, so offset from there. + p.Timestamp = time.Now().Add(-o.cfg.AckWait).Add(d).UnixNano() + // Update store system which will update followers as well. + o.updateDelivered(p.Sequence, sseq, dc, p.Timestamp) + if o.ptmr != nil { + // Want checkPending to run and figure out the next timer ttl. + // TODO(dlc) - We could optimize this maybe a bit more and track when we expect the timer to fire. + o.resetPtmr(10 * time.Millisecond) + } + } + // Nothing else for use to do now so return. + return + } } } + // If already queued up also ignore. if !o.onRedeliverQueue(sseq) { - o.rdq = append(o.rdq, sseq) + o.addToRedeliverQueue(sseq) } o.signalNewMessages() } // Process a TERM -func (o *Consumer) processTerm(sseq, dseq, dc uint64) { +// Returns `true` if the ack was processed in place and the sender can now respond +// to the client, or `false` if there was an error or the ack is replicated (in which +// case the reply will be sent later). +func (o *consumer) processTerm(sseq, dseq, dc uint64, reason, reply string) bool { // Treat like an ack to suppress redelivery. - o.processAckMsg(sseq, dseq, dc, false) + ackedInPlace := o.processAckMsg(sseq, dseq, dc, reply, false) o.mu.Lock() defer o.mu.Unlock() @@ -850,15 +2862,13 @@ func (o *Consumer) processTerm(sseq, dseq, dc uint64) { ConsumerSeq: dseq, StreamSeq: sseq, Deliveries: dc, - } - - j, err := json.MarshalIndent(e, "", " ") - if err != nil { - return + Reason: reason, + Domain: o.srv.getOpts().JetStreamDomain, } subj := JSAdvisoryConsumerMsgTerminatedPre + "." + o.stream + "." + o.name - o.sendAdvisory(subj, j) + o.sendAdvisory(subj, e) + return ackedInPlace } // Introduce a small delay in when timer fires to check pending. @@ -866,157 +2876,268 @@ func (o *Consumer) processTerm(sseq, dseq, dc uint64) { const ackWaitDelay = time.Millisecond // ackWait returns how long to wait to fire the pending timer. -func (o *Consumer) ackWait(next time.Duration) time.Duration { +func (o *consumer) ackWait(next time.Duration) time.Duration { if next > 0 { return next + ackWaitDelay } - return o.config.AckWait + ackWaitDelay + return o.cfg.AckWait + ackWaitDelay +} + +// Due to bug in calculation of sequences on restoring redelivered let's do quick sanity check. +// Lock should be held. +func (o *consumer) checkRedelivered() { + var shouldUpdateState bool + for sseq := range o.rdc { + if sseq <= o.asflr { + delete(o.rdc, sseq) + o.removeFromRedeliverQueue(sseq) + shouldUpdateState = true + } + } + if shouldUpdateState { + if err := o.writeStoreStateUnlocked(); err != nil && o.srv != nil && o.mset != nil && !o.closed { + s, acc, mset, name := o.srv, o.acc, o.mset, o.name + s.Warnf("Consumer '%s > %s > %s' error on write store state from check redelivered: %v", acc, mset.getCfgName(), name, err) + } + } } // This will restore the state from disk. -func (o *Consumer) readStoredState() error { +// Lock should be held. +func (o *consumer) readStoredState() error { if o.store == nil { return nil } state, err := o.store.State() - if err == nil && state != nil { - // FIXME(dlc) - re-apply state. - o.dseq = state.Delivered.Consumer + 1 - o.sseq = state.Delivered.Stream + 1 - o.adflr = state.AckFloor.Consumer - o.asflr = state.AckFloor.Stream - o.pending = state.Pending - o.rdc = state.Redelivered + if err == nil { + o.applyState(state) + if len(o.rdc) > 0 { + o.checkRedelivered() + } } + return err +} + +// Apply the consumer stored state. +// Lock should be held. +func (o *consumer) applyState(state *ConsumerState) { + if state == nil { + return + } + + o.sseq = state.Delivered.Stream + 1 + o.dseq = state.Delivered.Consumer + 1 + o.adflr = state.AckFloor.Consumer + o.asflr = state.AckFloor.Stream + o.pending = state.Pending + o.rdc = state.Redelivered // Setup tracking timer if we have restored pending. - if len(o.pending) > 0 && o.ptmr == nil { - o.mu.Lock() - o.ptmr = time.AfterFunc(o.ackWait(0), o.checkPending) - o.mu.Unlock() + if o.isLeader() && len(o.pending) > 0 { + // This is on startup or leader change. We want to check pending + // sooner in case there are inconsistencies etc. Pick between 500ms - 1.5s + delay := 500*time.Millisecond + time.Duration(rand.Int63n(1000))*time.Millisecond + + // If normal is lower than this just use that. + if o.cfg.AckWait < delay { + delay = o.ackWait(0) + } + o.resetPtmr(delay) + } +} + +// Sets our store state from another source. Used in clustered mode on snapshot restore. +// Lock should be held. +func (o *consumer) setStoreState(state *ConsumerState) error { + if state == nil || o.store == nil { + return nil + } + err := o.store.Update(state) + if err == nil { + o.applyState(state) } return err } // Update our state to the store. -func (o *Consumer) writeState() { +func (o *consumer) writeStoreState() error { o.mu.Lock() - if o.store != nil { - state := ConsumerState{ - Delivered: SequencePair{ - Consumer: o.dseq - 1, - Stream: o.sseq - 1, - }, - AckFloor: SequencePair{ - Consumer: o.adflr, - Stream: o.asflr, - }, - Pending: o.pending, - Redelivered: o.rdc, - } - // FIXME(dlc) - Hold onto any errors. - o.store.Update(&state) + defer o.mu.Unlock() + return o.writeStoreStateUnlocked() +} + +// Update our state to the store. +// Lock should be held. +func (o *consumer) writeStoreStateUnlocked() error { + if o.store == nil { + return nil + } + state := ConsumerState{ + Delivered: SequencePair{ + Consumer: o.dseq - 1, + Stream: o.sseq - 1, + }, + AckFloor: SequencePair{ + Consumer: o.adflr, + Stream: o.asflr, + }, + Pending: o.pending, + Redelivered: o.rdc, } + return o.store.Update(&state) +} + +// Returns an initial info. Only applicable for non-clustered consumers. +// We will clear after we return it, so one shot. +func (o *consumer) initialInfo() *ConsumerInfo { + o.mu.Lock() + ici := o.ici + o.ici = nil // gc friendly o.mu.Unlock() + if ici == nil { + ici = o.info() + } + return ici } -// loopAndDeliverMsgs() will loop and deliver messages and watch for interest changes. -func (o *Consumer) loopAndDeliverMsgs() { +// Clears our initial info. +// Used when we have a leader change in cluster mode but do not send a response. +func (o *consumer) clearInitialInfo() { o.mu.Lock() - qch, inch, sendq := o.qch, o.inch, o.sendq - s, acc := o.acc.srv, o.acc + o.ici = nil // gc friendly o.mu.Unlock() +} - // Create our client used to send messages. - c := s.createInternalJetStreamClient() - // Bind to the account. - c.registerWithAccount(acc) - // Clean up on exit. - defer c.closeConnection(ClientClosed) - - // Warn when internal send queue is backed up past 75% - warnThresh := cap(sendq) * 3 / 4 - warnFreq := time.Second - last := time.Now().Add(-warnFreq) +// Info returns our current consumer state. +func (o *consumer) info() *ConsumerInfo { + return o.infoWithSnap(false) +} - for { - if len(sendq) > warnThresh && time.Since(last) >= warnFreq { - s.Warnf("Jetstream internal consumer send queue > 75%% for account: %q consumer: %q", acc.Name, o.Name()) - last = time.Now() - } +func (o *consumer) infoWithSnap(snap bool) *ConsumerInfo { + return o.infoWithSnapAndReply(snap, _EMPTY_) +} - select { - case <-qch: - return - case interest := <-inch: - // inch can be nil on pull-based, but then this will - // just block and not fire. - o.updateDeliveryInterest(interest) - case pm := <-sendq: - if pm == nil { - return - } - c.pa.subject = []byte(pm.subj) - c.pa.deliver = []byte(pm.dsubj) - c.pa.size = len(pm.msg) + len(pm.hdr) - c.pa.szb = []byte(strconv.Itoa(c.pa.size)) - c.pa.reply = []byte(pm.reply) - - var msg []byte - if len(pm.hdr) > 0 { - c.pa.hdr = len(pm.hdr) - c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr)) - msg = append(pm.hdr, pm.msg...) - msg = append(msg, _CRLF_...) - } else { - c.pa.hdr = -1 - c.pa.hdb = nil - msg = append(pm.msg, _CRLF_...) - } +func (o *consumer) infoWithSnapAndReply(snap bool, reply string) *ConsumerInfo { + o.mu.Lock() + mset := o.mset + if o.closed || mset == nil || mset.srv == nil { + o.mu.Unlock() + return nil + } + js := o.js + if js == nil { + o.mu.Unlock() + return nil + } - didDeliver := c.processInboundClientMsg(msg) - c.pa.szb = nil - c.flushClients(0) + // Capture raftGroup. + var rg *raftGroup + if o.ca != nil { + rg = o.ca.Group + } - // Check to see if this is a delivery for an observable and - // we failed to deliver the message. If so alert the observable. - if !didDeliver && pm.o != nil && pm.seq > 0 { - pm.o.didNotDeliver(pm.seq) - } - } + priorityGroups := []PriorityGroupState{} + // TODO(jrm): when we introduce supporting many priority groups, we need to update assigning `o.currentNuid` for each group. + if len(o.cfg.PriorityGroups) > 0 { + priorityGroups = append(priorityGroups, PriorityGroupState{ + Group: o.cfg.PriorityGroups[0], + PinnedClientID: o.currentPinId, + PinnedTS: o.pinnedTS, + }) } -} -// Info returns our current consumer state. -func (o *Consumer) Info() *ConsumerInfo { - o.mu.Lock() + cfg := o.cfg info := &ConsumerInfo{ Stream: o.stream, Name: o.name, Created: o.created, - Config: o.config, - Delivered: SequencePair{ + Config: &cfg, + Delivered: SequenceInfo{ Consumer: o.dseq - 1, Stream: o.sseq - 1, }, - AckFloor: SequencePair{ + AckFloor: SequenceInfo{ Consumer: o.adflr, Stream: o.asflr, }, NumAckPending: len(o.pending), NumRedelivered: len(o.rdc), - NumPending: o.sgap, + NumPending: o.checkNumPending(), + PushBound: o.isPushMode() && o.active, + TimeStamp: time.Now().UTC(), + PriorityGroups: priorityGroups, + } + // Reset redelivered for MaxDeliver 1. Redeliveries are disabled so must not report it (is confusing otherwise). + // The state does still keep track of these messages. + if o.cfg.MaxDeliver == 1 { + info.NumRedelivered = 0 + } + if o.cfg.PauseUntil != nil { + p := *o.cfg.PauseUntil + if info.Paused = time.Now().Before(p); info.Paused { + info.PauseRemaining = time.Until(p) + } + } + + // We always need to pull certain data from our store. + if o.store != nil { + state, err := o.store.BorrowState() + if err != nil { + o.mu.Unlock() + return nil + } + + // If we are the leader we could have o.sseq that is skipped ahead. + // To maintain consistency in reporting (e.g. jsz) we always take the state for our delivered/ackfloor stream sequence. + // Only use skipped ahead o.sseq if we're a new consumer and have not yet replicated this state yet. + leader := o.isLeader() + if !leader || o.store.HasState() { + info.Delivered.Consumer, info.Delivered.Stream = state.Delivered.Consumer, state.Delivered.Stream + } + info.AckFloor.Consumer, info.AckFloor.Stream = state.AckFloor.Consumer, state.AckFloor.Stream + if !leader { + info.NumAckPending = len(state.Pending) + info.NumRedelivered = len(state.Redelivered) + } + } + + // Adjust active based on non-zero etc. Also make UTC here. + if !o.ldt.IsZero() { + ldt := o.ldt.UTC() // This copies as well. + info.Delivered.Last = &ldt } + if !o.lat.IsZero() { + lat := o.lat.UTC() // This copies as well. + info.AckFloor.Last = &lat + } + // If we are a pull mode consumer, report on number of waiting requests. if o.isPullMode() { + o.processWaiting(false) info.NumWaiting = o.waiting.len() } + // If we were asked to snapshot do so here. + if snap { + o.ici = info + } + sysc := o.sysc o.mu.Unlock() + + // Do cluster. + if rg != nil { + info.Cluster = js.clusterInfo(rg) + } + + // If we have a reply subject send the response here. + if reply != _EMPTY_ && sysc != nil { + sysc.sendInternalMsg(reply, _EMPTY_, nil, info) + } + return info } // Will signal us that new messages are available. Will break out of waiting. -func (o *Consumer) signalNewMessages() { +func (o *consumer) signalNewMessages() { // Kick our new message channel select { case o.mch <- struct{}{}: @@ -1025,7 +3146,7 @@ func (o *Consumer) signalNewMessages() { } // shouldSample lets us know if we are sampling metrics on acks. -func (o *Consumer) shouldSample() bool { +func (o *consumer) shouldSample() bool { switch { case o.sfreq <= 0: return false @@ -1035,10 +3156,10 @@ func (o *Consumer) shouldSample() bool { // TODO(ripienaar) this is a tad slow so we need to rethink here, however this will only // hit for those with sampling enabled and its not the default - return mrand.Int31n(100) <= o.sfreq + return rand.Int31n(100) <= o.sfreq } -func (o *Consumer) sampleAck(sseq, dseq, dc uint64) { +func (o *consumer) sampleAck(sseq, dseq, dc uint64) { if !o.shouldSample() { return } @@ -1058,27 +3179,58 @@ func (o *Consumer) sampleAck(sseq, dseq, dc uint64) { StreamSeq: sseq, Delay: unow - o.pending[sseq].Timestamp, Deliveries: dc, + Domain: o.srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(e, "", " ") - if err != nil { - return + o.sendAdvisory(o.ackEventT, e) +} + +// Process an ACK. +// Returns `true` if the ack was processed in place and the sender can now respond +// to the client, or `false` if there was an error or the ack is replicated (in which +// case the reply will be sent later). +func (o *consumer) processAckMsg(sseq, dseq, dc uint64, reply string, doSample bool) bool { + o.mu.Lock() + if o.closed { + o.mu.Unlock() + return false } - o.sendAdvisory(o.ackEventT, j) -} + mset := o.mset + if mset == nil || mset.closed.Load() { + o.mu.Unlock() + return false + } -// Process an ack for a message. -func (o *Consumer) ackMsg(sseq, dseq, dc uint64) { - o.processAckMsg(sseq, dseq, dc, true) -} + // Check if this ack is above the current pointer to our next to deliver. + if sseq >= o.sseq { + // Let's make sure this is valid. + // This is only received on the consumer leader, so should never be higher + // than the last stream sequence. But could happen if we've just become + // consumer leader, and we are not up-to-date on the stream yet. + var ss StreamState + mset.store.FastState(&ss) + if sseq > ss.LastSeq { + o.srv.Warnf("JetStream consumer '%s > %s > %s' ACK sequence %d past last stream sequence of %d", + o.acc.Name, o.stream, o.name, sseq, ss.LastSeq) + // FIXME(dlc) - For 2.11 onwards should we return an error here to the caller? + } + // Even though another leader must have delivered a message with this sequence, we must not adjust + // the current pointer. This could otherwise result in a stuck consumer, where messages below this + // sequence can't be redelivered, and we'll have incorrect pending state and ack floors. + o.mu.Unlock() + return false + } -func (o *Consumer) processAckMsg(sseq, dseq, dc uint64, doSample bool) { - o.mu.Lock() - var sagap uint64 + // Let the owning stream know if we are interest or workqueue retention based. + // If this consumer is clustered (o.node != nil) this will be handled by + // processReplicatedAck after the ack has propagated. + ackInPlace := o.node == nil && o.retention != LimitsPolicy + + var sgap, floor uint64 var needSignal bool - switch o.config.AckPolicy { + switch o.cfg.AckPolicy { case AckExplicit: if p, ok := o.pending[sseq]; ok { if doSample { @@ -1090,12 +3242,11 @@ func (o *Consumer) processAckMsg(sseq, dseq, dc uint64, doSample bool) { delete(o.pending, sseq) // Use the original deliver sequence from our pending record. dseq = p.Sequence - // Consumers sequence numbers can skip during re-delivery since - // they always increment. So if we do not have any pending treat - // as all scenario below. Otherwise check that we filled in a gap. + + // Only move floors if we matched an existing pending. if len(o.pending) == 0 { - o.adflr, o.asflr = o.dseq-1, o.sseq-1 - o.pending = nil + o.adflr = o.dseq - 1 + o.asflr = o.sseq - 1 } else if dseq == o.adflr+1 { o.adflr, o.asflr = dseq, sseq for ss := sseq + 1; ss < o.sseq; ss++ { @@ -1107,44 +3258,62 @@ func (o *Consumer) processAckMsg(sseq, dseq, dc uint64, doSample bool) { } } } - } - // We do these regardless. delete(o.rdc, sseq) o.removeFromRedeliverQueue(sseq) case AckAll: // no-op if dseq <= o.adflr || sseq <= o.asflr { o.mu.Unlock() - return + // Return true to let caller respond back to the client. + return true } if o.maxp > 0 && len(o.pending) >= o.maxp { needSignal = true } - sagap = sseq - o.asflr + sgap = sseq - o.asflr + floor = sseq // start at same and set lower as we go. o.adflr, o.asflr = dseq, sseq - for seq := sseq; seq > sseq-sagap; seq-- { + + remove := func(seq uint64) { delete(o.pending, seq) delete(o.rdc, seq) o.removeFromRedeliverQueue(seq) + if seq < floor { + floor = seq + } + } + // Determine if smarter to walk all of pending vs the sequence range. + if sgap > uint64(len(o.pending)) { + for seq := range o.pending { + if seq <= sseq { + remove(seq) + } + } + } else { + for seq := sseq; seq > sseq-sgap && len(o.pending) > 0; seq-- { + remove(seq) + } } case AckNone: // FIXME(dlc) - This is error but do we care? o.mu.Unlock() - return + return ackInPlace } + // No ack replication, so we set reply to "" so that updateAcks does not + // send the reply. The caller will. + if ackInPlace { + reply = _EMPTY_ + } // Update underlying store. - o.store.UpdateAcks(dseq, sseq) - - mset := o.mset + o.updateAcks(dseq, sseq, reply) o.mu.Unlock() - // Let the owning stream know if we are interest or workqueue retention based. - if mset != nil && mset.config.Retention != LimitsPolicy { - if sagap > 1 { - // FIXME(dlc) - This is very inefficient, will need to fix. - for seq := sseq; seq > sseq-sagap; seq-- { + if ackInPlace { + if sgap > 1 { + // FIXME(dlc) - This can very inefficient, will need to fix. + for seq := sseq; seq >= floor; seq-- { mset.ackMsg(o, seq) } } else { @@ -1152,75 +3321,254 @@ func (o *Consumer) processAckMsg(sseq, dseq, dc uint64, doSample bool) { } } - // If we had max ack pending set and were at limit we need to unblock folks. + // If we had max ack pending set and were at limit we need to unblock ourselves. if needSignal { o.signalNewMessages() } + return ackInPlace +} + +// Determine if this is a truly filtered consumer. Modern clients will place filtered subjects +// even if the stream only has a single non-wildcard subject designation. +// Read lock should be held. +func (o *consumer) isFiltered() bool { + if o.subjf == nil { + return false + } + // If we are here we want to check if the filtered subject is + // a direct match for our only listed subject. + mset := o.mset + if mset == nil { + return true + } + + // Protect access to mset.cfg with the cfgMu mutex. + mset.cfgMu.RLock() + msetSubjects := mset.cfg.Subjects + mset.cfgMu.RUnlock() + + // `isFiltered` need to be performant, so we do + // as any checks as possible to avoid unnecessary work. + // Here we avoid iteration over slices if there is only one subject in stream + // and one filter for the consumer. + if len(msetSubjects) == 1 && len(o.subjf) == 1 { + return msetSubjects[0] != o.subjf[0].subject + } + + // if the list is not equal length, we can return early, as this is filtered. + if len(msetSubjects) != len(o.subjf) { + return true + } + + // if in rare case scenario that user passed all stream subjects as consumer filters, + // we need to do a more expensive operation. + // reflect.DeepEqual would return false if the filters are the same, but in different order + // so it can't be used here. + cfilters := make(map[string]struct{}, len(o.subjf)) + for _, val := range o.subjf { + cfilters[val.subject] = struct{}{} + } + for _, val := range msetSubjects { + if _, ok := cfilters[val]; !ok { + return true + } + } + return false } // Check if we need an ack for this store seq. // This is called for interest based retention streams to remove messages. -func (o *Consumer) needAck(sseq uint64) bool { +func (o *consumer) needAck(sseq uint64, subj string) bool { var needAck bool - o.mu.Lock() - switch o.config.AckPolicy { + var asflr, osseq uint64 + var pending map[uint64]*Pending + var rdc map[uint64]uint64 + + o.mu.RLock() + defer o.mu.RUnlock() + + isFiltered := o.isFiltered() + if isFiltered && o.mset == nil { + return false + } + + // Check if we are filtered, and if so check if this is even applicable to us. + if isFiltered { + if subj == _EMPTY_ { + var err error + if subj, err = o.mset.store.SubjectForSeq(sseq); err != nil { + return false + } + } + if !o.isFilteredMatch(subj) { + return false + } + } + if o.isLeader() { + asflr, osseq = o.asflr, o.sseq + pending, rdc = o.pending, o.rdc + } else { + if o.store == nil { + return false + } + state, err := o.store.BorrowState() + if err != nil || state == nil { + // Fall back to what we track internally for now. + return sseq > o.asflr && !o.isFiltered() + } + // If loading state as here, the osseq is +1. + asflr, osseq, pending, rdc = state.AckFloor.Stream, state.Delivered.Stream+1, state.Pending, state.Redelivered + } + + switch o.cfg.AckPolicy { case AckNone, AckAll: - needAck = sseq > o.asflr + needAck = sseq > asflr case AckExplicit: - if sseq > o.asflr { - // Generally this means we need an ack, but just double check pending acks. - needAck = true - if len(o.pending) > 0 && sseq < o.sseq { - _, needAck = o.pending[sseq] + if sseq > asflr { + if sseq >= osseq { + needAck = true + } else { + _, needAck = pending[sseq] } } } - o.mu.Unlock() + + // Finally check if redelivery of this message is tracked. + // If the message is not pending, it should be preserved if it reached max delivery. + if !needAck { + _, needAck = rdc[sseq] + } + return needAck } +type PriorityGroup struct { + Group string `json:"group,omitempty"` + MinPending int64 `json:"min_pending,omitempty"` + MinAckPending int64 `json:"min_ack_pending,omitempty"` + Id string `json:"id,omitempty"` +} + +// Used in nextReqFromMsg, since the json.Unmarshal causes the request +// struct to escape to the heap always. This should reduce GC pressure. +var jsGetNextPool = sync.Pool{ + New: func() any { + return &JSApiConsumerGetNextRequest{} + }, +} + // Helper for the next message requests. -func nextReqFromMsg(msg []byte) (time.Time, int, bool, error) { +func nextReqFromMsg(msg []byte) (time.Time, int, int, bool, time.Duration, time.Time, *PriorityGroup, error) { req := bytes.TrimSpace(msg) switch { case len(req) == 0: - return time.Time{}, 1, false, nil + return time.Time{}, 1, 0, false, 0, time.Time{}, nil, nil case req[0] == '{': - var cr JSApiConsumerGetNextRequest + cr := jsGetNextPool.Get().(*JSApiConsumerGetNextRequest) + defer func() { + *cr = JSApiConsumerGetNextRequest{} + jsGetNextPool.Put(cr) + }() if err := json.Unmarshal(req, &cr); err != nil { - return time.Time{}, -1, false, err + return time.Time{}, -1, 0, false, 0, time.Time{}, nil, err } - return cr.Expires, cr.Batch, cr.NoWait, nil - + var hbt time.Time + if cr.Heartbeat > 0 { + if cr.Heartbeat*2 > cr.Expires { + return time.Time{}, 1, 0, false, 0, time.Time{}, nil, errors.New("heartbeat value too large") + } + hbt = time.Now().Add(cr.Heartbeat) + } + priorityGroup := cr.PriorityGroup + if cr.Expires == time.Duration(0) { + return time.Time{}, cr.Batch, cr.MaxBytes, cr.NoWait, cr.Heartbeat, hbt, &priorityGroup, nil + } + return time.Now().Add(cr.Expires), cr.Batch, cr.MaxBytes, cr.NoWait, cr.Heartbeat, hbt, &priorityGroup, nil default: if n, err := strconv.Atoi(string(req)); err == nil { - return time.Time{}, n, false, nil + return time.Time{}, n, 0, false, 0, time.Time{}, nil, nil } } - return time.Time{}, 1, false, nil + return time.Time{}, 1, 0, false, 0, time.Time{}, nil, nil } // Represents a request that is on the internal waiting queue type waitingRequest struct { - client *client - reply string - n int // For batching - expires time.Time - noWait bool + next *waitingRequest + acc *Account + interest string + reply string + n int // For batching + d int // num delivered + b int // For max bytes tracking + expires time.Time + received time.Time + hb time.Duration + hbt time.Time + noWait bool + priorityGroup *PriorityGroup +} + +// sync.Pool for waiting requests. +var wrPool = sync.Pool{ + New: func() any { + return new(waitingRequest) + }, +} + +// Recycle this request. This request can not be accessed after this call. +func (wr *waitingRequest) recycleIfDone() bool { + if wr != nil && wr.n <= 0 { + wr.recycle() + return true + } + return false +} + +// Force a recycle. +func (wr *waitingRequest) recycle() { + if wr != nil { + wr.next, wr.acc, wr.interest, wr.reply = nil, nil, _EMPTY_, _EMPTY_ + wrPool.Put(wr) + } +} + +// Represents an (optional) request timeout that's sent after waiting for replicated deliveries. +type waitingDelivery struct { + seq uint64 + pn int // Pending messages. + pb int // Pending bytes. +} + +// sync.Pool for waiting deliveries. +var wdPool = sync.Pool{ + New: func() any { + return new(waitingDelivery) + }, +} + +// Force a recycle. +func (wd *waitingDelivery) recycle() { + if wd != nil { + wd.seq, wd.pn, wd.pb = 0, 0, 0 + wdPool.Put(wd) + } } // waiting queue for requests that are waiting for new messages to arrive. type waitQueue struct { - rp, wp int - reqs []*waitingRequest + n, max int + last time.Time + head *waitingRequest + tail *waitingRequest } // Create a new ring buffer with at most max items. func newWaitQueue(max int) *waitQueue { - return &waitQueue{rp: -1, reqs: make([]*waitingRequest, max)} + return &waitQueue{max: max} } var ( @@ -1229,139 +3577,520 @@ var ( ) // Adds in a new request. -func (wq *waitQueue) add(req *waitingRequest) error { +func (wq *waitQueue) add(wr *waitingRequest) error { if wq == nil { return errWaitQueueNil } if wq.isFull() { return errWaitQueueFull } - wq.reqs[wq.wp] = req - // TODO(dlc) - Could make pow2 and get rid of mod. - wq.wp = (wq.wp + 1) % cap(wq.reqs) + if wq.head == nil { + wq.head = wr + } else { + wq.tail.next = wr + } + // Always set tail. + wq.tail = wr + // Make sure nil + wr.next = nil + + // Track last active via when we receive a request. + wq.last = wr.received + wq.n++ + return nil +} + +func (wq *waitQueue) isFull() bool { + if wq == nil { + return false + } + return wq.n == wq.max +} + +func (wq *waitQueue) isEmpty() bool { + if wq == nil { + return true + } + return wq.n == 0 +} + +func (wq *waitQueue) len() int { + if wq == nil { + return 0 + } + return wq.n +} + +// Peek will return the next request waiting or nil if empty. +func (wq *waitQueue) peek() *waitingRequest { + if wq == nil { + return nil + } + return wq.head +} + +func (wq *waitQueue) cycle() { + wr := wq.peek() + if wr != nil { + // Always remove current now on a pop, and move to end if still valid. + // If we were the only one don't need to remove since this can be a no-op. + wq.removeCurrent() + wq.add(wr) + } +} + +// pop will return the next request and move the read cursor. +// This will now place a request that still has pending items at the ends of the list. +func (wq *waitQueue) pop() *waitingRequest { + wr := wq.peek() + if wr != nil { + wr.d++ + wr.n-- + // Always remove current now on a pop, and move to end if still valid. + // If we were the only one don't need to remove since this can be a no-op. + if wr.n > 0 && wq.n > 1 { + wq.removeCurrent() + wq.add(wr) + } else if wr.n <= 0 { + wq.removeCurrent() + } + } + return wr +} + +// Removes the current read pointer (head FIFO) entry. +func (wq *waitQueue) removeCurrent() { + wq.remove(nil, wq.head) +} + +// Remove the wr element from the wait queue. +func (wq *waitQueue) remove(pre, wr *waitingRequest) { + if wr == nil { + return + } + if pre != nil { + pre.next = wr.next + } else if wr == wq.head { + // We are removing head here. + wq.head = wr.next + } + // Check if wr was our tail. + if wr == wq.tail { + // Check if we need to assign to pre. + if wr.next == nil { + wq.tail = pre + } else { + wq.tail = wr.next + } + } + wq.n-- +} + +// Return the map of pending requests keyed by the reply subject. +// No-op if push consumer or invalid etc. +func (o *consumer) pendingRequests() map[string]*waitingRequest { + if o.waiting == nil { + return nil + } + wq, m := o.waiting, make(map[string]*waitingRequest) + for wr := wq.head; wr != nil; wr = wr.next { + m[wr.reply] = wr + } + + return m +} + +func (o *consumer) setPinnedTimer(priorityGroup string) { + if o.pinnedTtl != nil { + o.pinnedTtl.Reset(o.cfg.PinnedTTL) + } else { + o.pinnedTtl = time.AfterFunc(o.cfg.PinnedTTL, func() { + o.mu.Lock() + o.currentPinId = _EMPTY_ + o.sendUnpinnedAdvisoryLocked(priorityGroup, "timeout") + o.mu.Unlock() + o.signalNewMessages() + }) + } +} + +// Return next waiting request. This will check for expirations but not noWait or interest. +// That will be handled by processWaiting. +// Lock should be held. +func (o *consumer) nextWaiting(sz int) *waitingRequest { + if o.waiting == nil || o.waiting.isEmpty() { + return nil + } + + // Check if server needs to assign a new pin id. + needNewPin := o.currentPinId == _EMPTY_ && o.cfg.PriorityPolicy == PriorityPinnedClient + // As long as we support only one priority group, we can capture that group here and reuse it. + var priorityGroup string + if len(o.cfg.PriorityGroups) > 0 { + priorityGroup = o.cfg.PriorityGroups[0] + } + + numCycled := 0 + for wr := o.waiting.peek(); !o.waiting.isEmpty(); wr = o.waiting.peek() { + if wr == nil { + break + } + // Check if we have max bytes set. + if wr.b > 0 { + if sz <= wr.b { + wr.b -= sz + // If we are right now at zero, set batch to 1 to deliver this one but stop after. + if wr.b == 0 { + wr.n = 1 + } + } else { + // Since we can't send that message to the requestor, we need to + // notify that we are closing the request. + const maxBytesT = "NATS/1.0 409 Message Size Exceeds MaxBytes\r\n%s: %d\r\n%s: %d\r\n\r\n" + hdr := fmt.Appendf(nil, maxBytesT, JSPullRequestPendingMsgs, wr.n, JSPullRequestPendingBytes, wr.b) + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + // Remove the current one, no longer valid due to max bytes limit. + o.waiting.removeCurrent() + if o.node != nil { + o.removeClusterPendingRequest(wr.reply) + } + wr.recycle() + continue + } + } + + if wr.expires.IsZero() || time.Now().Before(wr.expires) { + if needNewPin { + if wr.priorityGroup.Id == _EMPTY_ { + o.currentPinId = nuid.Next() + o.pinnedTS = time.Now().UTC() + wr.priorityGroup.Id = o.currentPinId + o.setPinnedTimer(priorityGroup) + + } else { + // There is pin id set, but not a matching one. Send a notification to the client and remove the request. + // Probably this is the old pin id. + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, []byte(JSPullRequestWrongPinID), nil, nil, 0)) + o.waiting.removeCurrent() + if o.node != nil { + o.removeClusterPendingRequest(wr.reply) + } + wr.recycle() + continue + } + } else if o.currentPinId != _EMPTY_ { + // Check if we have a match on the currentNuid + if wr.priorityGroup != nil && wr.priorityGroup.Id == o.currentPinId { + // If we have a match, we do nothing here and will deliver the message later down the code path. + } else if wr.priorityGroup.Id == _EMPTY_ { + o.waiting.cycle() + numCycled++ + if numCycled >= o.waiting.len() { + return nil + } + continue + } else { + // There is pin id set, but not a matching one. Send a notification to the client and remove the request. + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, []byte(JSPullRequestWrongPinID), nil, nil, 0)) + o.waiting.removeCurrent() + if o.node != nil { + o.removeClusterPendingRequest(wr.reply) + } + wr.recycle() + continue + } + } + + if o.cfg.PriorityPolicy == PriorityOverflow { + if wr.priorityGroup != nil && + // We need to check o.npc+1, because before calling nextWaiting, we do o.npc-- + (wr.priorityGroup.MinPending > 0 && wr.priorityGroup.MinPending > o.npc+1 || + wr.priorityGroup.MinAckPending > 0 && wr.priorityGroup.MinAckPending > int64(len(o.pending))) { + o.waiting.cycle() + numCycled++ + // We're done cycling through the requests. + if numCycled >= o.waiting.len() { + return nil + } + continue + } + } + if wr.acc.sl.HasInterest(wr.interest) { + if needNewPin { + o.sendPinnedAdvisoryLocked(priorityGroup) + } + return o.waiting.pop() + } else if time.Since(wr.received) < defaultGatewayRecentSubExpiration && (o.srv.leafNodeEnabled || o.srv.gateway.enabled) { + if needNewPin { + o.sendPinnedAdvisoryLocked(priorityGroup) + } + return o.waiting.pop() + } else if o.srv.gateway.enabled && o.srv.hasGatewayInterest(wr.acc.Name, wr.interest) { + if needNewPin { + o.sendPinnedAdvisoryLocked(priorityGroup) + } + return o.waiting.pop() + } + } else { + // We do check for expiration in `processWaiting`, but it is possible to hit the expiry here, and not there. + rdWait := o.replicateDeliveries() + if rdWait { + // Check if we need to send the timeout after pending replicated deliveries, or can do so immediately. + if wd, ok := o.waitingDeliveries[wr.reply]; !ok { + rdWait = false + } else { + wd.pn, wd.pb = wr.n, wr.b + } + } + if !rdWait { + hdr := fmt.Appendf(nil, "NATS/1.0 408 Request Timeout\r\n%s: %d\r\n%s: %d\r\n\r\n", JSPullRequestPendingMsgs, wr.n, JSPullRequestPendingBytes, wr.b) + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + } + o.waiting.removeCurrent() + if o.node != nil { + o.removeClusterPendingRequest(wr.reply) + } + wr.recycle() + continue - // Adjust read pointer if we were empty. - if wq.rp < 0 { - wq.rp = 0 + } + if wr.interest != wr.reply { + const intExpT = "NATS/1.0 408 Interest Expired\r\n%s: %d\r\n%s: %d\r\n\r\n" + hdr := fmt.Appendf(nil, intExpT, JSPullRequestPendingMsgs, wr.n, JSPullRequestPendingBytes, wr.b) + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + } + // Remove the current one, no longer valid. + o.waiting.removeCurrent() + if o.node != nil { + o.removeClusterPendingRequest(wr.reply) + } + wr.recycle() } return nil } -func (wq *waitQueue) isFull() bool { - return wq.rp == wq.wp +// Next message request. +type nextMsgReq struct { + reply string + msg []byte } -func (wq *waitQueue) len() int { - if wq == nil || wq.rp < 0 { - return 0 - } - if wq.rp < wq.wp { - return wq.wp - wq.rp - } - return cap(wq.reqs) - wq.rp + wq.wp -} +var nextMsgReqPool sync.Pool -// Peek will return the next request waiting or nil if empty. -func (wq *waitQueue) peek() *waitingRequest { - if wq == nil { - return nil - } - var wr *waitingRequest - if wq.rp >= 0 { - wr = wq.reqs[wq.rp] +func newNextMsgReq(reply string, msg []byte) *nextMsgReq { + var nmr *nextMsgReq + m := nextMsgReqPool.Get() + if m != nil { + nmr = m.(*nextMsgReq) + } else { + nmr = &nextMsgReq{} } - return wr + // When getting something from a pool it is critical that all fields are + // initialized. Doing this way guarantees that if someone adds a field to + // the structure, the compiler will fail the build if this line is not updated. + (*nmr) = nextMsgReq{reply, msg} + return nmr } -// pop will return the next request and move the read cursor. -func (wq *waitQueue) pop() *waitingRequest { - wr := wq.peek() - if wr != nil { - wr.n-- - if wr.n <= 0 { - wq.reqs[wq.rp] = nil - wq.rp = (wq.rp + 1) % cap(wq.reqs) - // Check if we are empty. - if wq.rp == wq.wp { - wq.rp, wq.wp = -1, 0 - } - } +func (nmr *nextMsgReq) returnToPool() { + if nmr == nil { + return } - return wr + nmr.reply, nmr.msg = _EMPTY_, nil + nextMsgReqPool.Put(nmr) } // processNextMsgReq will process a request for the next message available. A nil message payload means deliver // a single message. If the payload is a formal request or a number parseable with Atoi(), then we will send a // batch of messages without requiring another request to this endpoint, or an ACK. -func (o *Consumer) processNextMsgReq(_ *subscription, c *client, _, reply string, msg []byte) { +func (o *consumer) processNextMsgReq(_ *subscription, c *client, _ *Account, _, reply string, msg []byte) { + if reply == _EMPTY_ { + return + } + + // Short circuit error here. + if o.nextMsgReqs == nil { + hdr := []byte("NATS/1.0 409 Consumer is push based\r\n\r\n") + o.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + + _, msg = c.msgParts(msg) + o.nextMsgReqs.push(newNextMsgReq(reply, copyBytes(msg))) +} + +func (o *consumer) processNextMsgRequest(reply string, msg []byte) { o.mu.Lock() + defer o.mu.Unlock() + mset := o.mset - if mset == nil || o.isPushMode() { - o.mu.Unlock() + if mset == nil { return } sendErr := func(status int, description string) { - o.mu.Unlock() - hdr := []byte(fmt.Sprintf("NATS/1.0 %d %s\r\n\r\n", status, description)) - pmsg := &jsPubMsg{reply, reply, _EMPTY_, hdr, nil, nil, 0} - o.sendq <- pmsg // Send message. + hdr := fmt.Appendf(nil, "NATS/1.0 %d %s\r\n\r\n", status, description) + o.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) } - if o.waiting.isFull() { - // Try to expire some of the requests. - if expired := o.expireWaiting(); expired == 0 { - // Force expiration if needed. - o.forceExpireFirstWaiting() - } + if o.isPushMode() || o.waiting == nil { + sendErr(409, "Consumer is push based") + return } // Check payload here to see if they sent in batch size or a formal request. - expires, batchSize, noWait, err := nextReqFromMsg(msg) + expires, batchSize, maxBytes, noWait, hb, hbt, priorityGroup, err := nextReqFromMsg(msg) if err != nil { sendErr(400, fmt.Sprintf("Bad Request - %v", err)) return } - // In case we have to queue up this request. This is all on stack pre-allocated. - wr := waitingRequest{client: c, reply: reply, n: batchSize, noWait: noWait, expires: expires} + // Check for request limits + if o.cfg.MaxRequestBatch > 0 && batchSize > o.cfg.MaxRequestBatch { + sendErr(409, fmt.Sprintf("Exceeded MaxRequestBatch of %d", o.cfg.MaxRequestBatch)) + return + } - // If we are in replay mode, defer to processReplay for delivery. - if o.replay { - o.waiting.add(&wr) - o.mu.Unlock() - o.signalNewMessages() + if !expires.IsZero() && o.cfg.MaxRequestExpires > 0 && expires.After(time.Now().Add(o.cfg.MaxRequestExpires)) { + sendErr(409, fmt.Sprintf("Exceeded MaxRequestExpires of %v", o.cfg.MaxRequestExpires)) return } - for i := 0; i < batchSize; i++ { - // See if we have more messages available. - if subj, hdr, msg, seq, dc, ts, err := o.getNextMsg(); err == nil { - o.deliverMsg(reply, subj, hdr, msg, seq, dc, ts) - // Need to discount this from the total n for the request. - wr.n-- - } else { - if wr.noWait { - switch err { - case errMaxAckPending: - sendErr(409, "Exceeded MaxAckPending") - default: - sendErr(404, "No Messages") - } + if maxBytes > 0 && o.cfg.MaxRequestMaxBytes > 0 && maxBytes > o.cfg.MaxRequestMaxBytes { + sendErr(409, fmt.Sprintf("Exceeded MaxRequestMaxBytes of %v", o.cfg.MaxRequestMaxBytes)) + return + } + + if priorityGroup != nil { + if (priorityGroup.MinPending != 0 || priorityGroup.MinAckPending != 0) && o.cfg.PriorityPolicy != PriorityOverflow { + sendErr(400, "Bad Request - Not a Overflow Priority consumer") + } + + if priorityGroup.Id != _EMPTY_ && o.cfg.PriorityPolicy != PriorityPinnedClient { + sendErr(400, "Bad Request - Not a Pinned Client Priority consumer") + } + } + + if priorityGroup != nil && o.cfg.PriorityPolicy != PriorityNone { + if priorityGroup.Group == _EMPTY_ { + sendErr(400, "Bad Request - Priority Group missing") + return + } + + found := false + for _, group := range o.cfg.PriorityGroups { + if group == priorityGroup.Group { + found = true + break + } + } + if !found { + sendErr(400, "Bad Request - Invalid Priority Group") + return + } + + if o.currentPinId != _EMPTY_ { + if priorityGroup.Id == o.currentPinId { + o.setPinnedTimer(priorityGroup.Group) + } else if priorityGroup.Id != _EMPTY_ { + sendErr(423, "Nats-Pin-Id mismatch") + return + } + } + } + + // If we have the max number of requests already pending try to expire. + if o.waiting.isFull() { + // Try to expire some of the requests. + // We do not want to push too hard here so at maximum process once per sec. + if time.Since(o.lwqic) > time.Second { + o.processWaiting(false) + } + } + + // If the request is for noWait and we have pending requests already, check if we have room. + if noWait { + msgsPending := o.numPending() + uint64(len(o.rdq)) + // If no pending at all, decide what to do with request. + // If no expires was set then fail. + if msgsPending == 0 && expires.IsZero() { + o.waiting.last = time.Now() + sendErr(404, "No Messages") + return + } + if msgsPending > 0 { + _, _, batchPending, _ := o.processWaiting(false) + if msgsPending < uint64(batchPending) { + o.waiting.last = time.Now() + sendErr(408, "Requests Pending") return } - o.waiting.add(&wr) + } + // If we are here this should be considered a one-shot situation. + // We will wait for expires but will return as soon as we have any messages. + } + + // If we receive this request though an account export, we need to track that interest subject and account. + acc, interest := trackDownAccountAndInterest(o.acc, reply) + + // Create a waiting request. + wr := wrPool.Get().(*waitingRequest) + wr.acc, wr.interest, wr.reply, wr.n, wr.d, wr.noWait, wr.expires, wr.hb, wr.hbt, wr.priorityGroup = acc, interest, reply, batchSize, 0, noWait, expires, hb, hbt, priorityGroup + wr.b = maxBytes + wr.received = time.Now() + + if err := o.waiting.add(wr); err != nil { + // If the client has a heartbeat interval set, don't bother responding with a 409, + // otherwise we can end up in a hot loop with the client re-requesting instead of + // waiting for the missing heartbeats instead and retrying. + if hb == 0 { + sendErr(409, "Exceeded MaxWaiting") + } + wr.recycle() + return + } + o.signalNewMessages() + // If we are clustered update our followers about this request. + if o.node != nil { + o.addClusterPendingRequest(wr.reply) + } +} + +func trackDownAccountAndInterest(acc *Account, interest string) (*Account, string) { + for strings.HasPrefix(interest, replyPrefix) { + oa := acc + oa.mu.RLock() + if oa.exports.responses == nil { + oa.mu.RUnlock() + break + } + si := oa.exports.responses[interest] + if si == nil { + oa.mu.RUnlock() break } + acc, interest = si.acc, si.to + oa.mu.RUnlock() } - o.mu.Unlock() + return acc, interest +} + +// Return current delivery count for a given sequence. +func (o *consumer) deliveryCount(seq uint64) uint64 { + if o.rdc == nil { + return 1 + } + if dc := o.rdc[seq]; dc >= 1 { + return dc + } + return 1 } // Increase the delivery count for this message. // ONLY used on redelivery semantics. // Lock should be held. -func (o *Consumer) incDeliveryCount(sseq uint64) uint64 { +func (o *consumer) incDeliveryCount(sseq uint64) uint64 { if o.rdc == nil { o.rdc = make(map[uint64]uint64) } @@ -1369,8 +4098,18 @@ func (o *Consumer) incDeliveryCount(sseq uint64) uint64 { return o.rdc[sseq] + 1 } +// Used if we have to adjust on failed delivery or bad lookups. +// Those failed attempts should not increase deliver count. +// Lock should be held. +func (o *consumer) decDeliveryCount(sseq uint64) { + if o.rdc == nil { + o.rdc = make(map[uint64]uint64) + } + o.rdc[sseq] -= 1 +} + // send a delivery exceeded advisory. -func (o *Consumer) notifyDeliveryExceeded(sseq, dc uint64) { +func (o *consumer) notifyDeliveryExceeded(sseq, dc uint64) { e := JSConsumerDeliveryExceededAdvisory{ TypedEvent: TypedEvent{ Type: JSConsumerDeliveryExceededAdvisoryType, @@ -1381,46 +4120,72 @@ func (o *Consumer) notifyDeliveryExceeded(sseq, dc uint64) { Consumer: o.name, StreamSeq: sseq, Deliveries: dc, + Domain: o.srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(e, "", " ") - if err != nil { - return - } - - o.sendAdvisory(o.deliveryExcEventT, j) + o.sendAdvisory(o.deliveryExcEventT, e) } -// Check to see if the candidate subject matches a filter if its present. +// Check if the candidate subject matches a filter if its present. // Lock should be held. -func (o *Consumer) isFilteredMatch(subj string) bool { +func (o *consumer) isFilteredMatch(subj string) bool { // No filter is automatic match. - if o.config.FilterSubject == _EMPTY_ { + if o.subjf == nil { return true } - if !o.filterWC { - return subj == o.config.FilterSubject + for _, filter := range o.subjf { + if !filter.hasWildcard && subj == filter.subject { + return true + } + } + // It's quicker to first check for non-wildcard filters, then + // iterate again to check for subset match. + tsa := [32]string{} + tts := tokenizeSubjectIntoSlice(tsa[:0], subj) + for _, filter := range o.subjf { + if isSubsetMatchTokenized(tts, filter.tokenizedSubject) { + return true + } + } + return false +} + +// Check if the candidate filter subject is equal to or a subset match +// of one of the filter subjects. +// Lock should be held. +func (o *consumer) isEqualOrSubsetMatch(subj string) bool { + for _, filter := range o.subjf { + if !filter.hasWildcard && subj == filter.subject { + return true + } + } + tsa := [32]string{} + tts := tokenizeSubjectIntoSlice(tsa[:0], subj) + for _, filter := range o.subjf { + if isSubsetMatchTokenized(filter.tokenizedSubject, tts) { + return true + } } - // If we are here we have a wildcard filter subject. - // TODO(dlc) at speed might be better to just do a sublist with L2 and/or possibly L1. - return subjectIsSubsetMatch(subj, o.config.FilterSubject) + return false } -var errMaxAckPending = errors.New("max ack pending reached") -var errBadConsumer = errors.New("consumer not valid") +var ( + errMaxAckPending = errors.New("max ack pending reached") + errBadConsumer = errors.New("consumer not valid") + errNoInterest = errors.New("consumer requires interest for delivery subject when ephemeral") +) // Get next available message from underlying store. // Is partition aware and redeliver aware. // Lock should be held. -func (o *Consumer) getNextMsg() (subj string, hdr, msg []byte, seq uint64, dc uint64, ts int64, err error) { - if o.mset == nil { - return _EMPTY_, nil, nil, 0, 0, 0, errBadConsumer - } - for { - seq, dc := o.sseq, uint64(1) - if len(o.rdq) > 0 { - seq = o.rdq[0] - o.rdq = append(o.rdq[:0], o.rdq[1:]...) +func (o *consumer) getNextMsg() (*jsPubMsg, uint64, error) { + if o.mset == nil || o.mset.store == nil { + return nil, 0, errBadConsumer + } + // Process redelivered messages before looking at possibly "skip list" (deliver last per subject) + if o.hasRedeliveries() { + var seq, dc uint64 + for seq = o.getNextToRedeliver(); seq > 0; seq = o.getNextToRedeliver() { dc = o.incDeliveryCount(seq) if o.maxdc > 0 && dc > o.maxdc { // Only send once @@ -1428,153 +4193,577 @@ func (o *Consumer) getNextMsg() (subj string, hdr, msg []byte, seq uint64, dc ui o.notifyDeliveryExceeded(seq, dc-1) } // Make sure to remove from pending. - delete(o.pending, seq) + if p, ok := o.pending[seq]; ok && p != nil { + delete(o.pending, seq) + o.updateDelivered(p.Sequence, seq, dc, p.Timestamp) + } continue } - } else if o.maxp > 0 && len(o.pending) >= o.maxp { - // maxp only set when ack policy != AckNone and user set MaxAckPending - // Stall if we have hit max pending. - return _EMPTY_, nil, nil, 0, 0, 0, errMaxAckPending + pmsg := getJSPubMsgFromPool() + sm, err := o.mset.store.LoadMsg(seq, &pmsg.StoreMsg) + if sm == nil || err != nil { + pmsg.returnToPool() + pmsg, dc = nil, 0 + // Adjust back deliver count. + o.decDeliveryCount(seq) + } + // Message was scheduled for redelivery but was removed in the meantime. + if err == ErrStoreMsgNotFound || err == errDeletedMsg { + // This is a race condition where the message is still in o.pending and + // scheduled for redelivery, but it has been removed from the stream. + // o.processTerm is called in a goroutine so could run after we get here. + // That will correct the pending state and delivery/ack floors, so just skip here. + continue + } + return pmsg, dc, err } + } - subj, hdr, msg, ts, err := o.mset.store.LoadMsg(seq) - if err == nil { - if dc == 1 { // First delivery. - o.sseq++ - if o.config.FilterSubject != _EMPTY_ && !o.isFilteredMatch(subj) { + // Check if we have max pending. + if o.maxp > 0 && len(o.pending) >= o.maxp { + // maxp only set when ack policy != AckNone and user set MaxAckPending + // Stall if we have hit max pending. + return nil, 0, errMaxAckPending + } + + if o.hasSkipListPending() { + seq := o.lss.seqs[0] + if len(o.lss.seqs) == 1 { + o.sseq = o.lss.resume + o.lss = nil + o.updateSkipped(o.sseq) + } else { + o.lss.seqs = o.lss.seqs[1:] + o.sseq = seq + } + pmsg := getJSPubMsgFromPool() + sm, err := o.mset.store.LoadMsg(seq, &pmsg.StoreMsg) + if sm == nil || err != nil { + pmsg.returnToPool() + } + o.sseq++ + return pmsg, 1, err + } + + // Hold onto this since we release the lock. + store := o.mset.store + + var sseq uint64 + var err error + var sm *StoreMsg + var pmsg = getJSPubMsgFromPool() + + // Grab next message applicable to us. + filters, subjf, fseq := o.filters, o.subjf, o.sseq + // Check if we are multi-filtered or not. + if filters != nil { + sm, sseq, err = store.LoadNextMsgMulti(filters, fseq, &pmsg.StoreMsg) + } else if len(subjf) > 0 { // Means single filtered subject since o.filters means > 1. + filter, wc := subjf[0].subject, subjf[0].hasWildcard + sm, sseq, err = store.LoadNextMsg(filter, wc, fseq, &pmsg.StoreMsg) + } else { + // No filter here. + sm, sseq, err = store.LoadNextMsg(_EMPTY_, false, fseq, &pmsg.StoreMsg) + } + if sm == nil { + pmsg.returnToPool() + pmsg = nil + } + // Check if we should move our o.sseq. + if sseq >= o.sseq { + // If we are moving step by step then sseq == o.sseq. + // If we have jumped we should update skipped for other replicas. + if sseq != o.sseq && err == ErrStoreEOF { + o.updateSkipped(sseq + 1) + } + o.sseq = sseq + 1 + } + return pmsg, 1, err +} + +// Will check for expiration and lack of interest on waiting requests. +// Will also do any heartbeats and return the next expiration or HB interval. +func (o *consumer) processWaiting(eos bool) (int, int, int, time.Time) { + var fexp time.Time + if o.srv == nil || o.waiting.isEmpty() { + return 0, 0, 0, fexp + } + // Mark our last check time. + o.lwqic = time.Now() + + var expired, brp int + s, now := o.srv, time.Now() + + wq := o.waiting + remove := func(pre, wr *waitingRequest) *waitingRequest { + expired++ + if o.node != nil { + o.removeClusterPendingRequest(wr.reply) + } + next := wr.next + wq.remove(pre, wr) + wr.recycle() + return next + } + + var pre *waitingRequest + for wr := wq.head; wr != nil; { + // Check expiration. + expires := !wr.expires.IsZero() && now.After(wr.expires) + if (eos && wr.noWait) || expires { + rdWait := o.replicateDeliveries() + if rdWait { + // Check if we need to send the timeout after pending replicated deliveries, or can do so immediately. + if wd, ok := o.waitingDeliveries[wr.reply]; !ok { + rdWait = false + } else { + wd.pn, wd.pb = wr.n, wr.b + } + // If we still need to wait for replicated deliveries, remove from waiting list. + if rdWait { + wr = remove(pre, wr) continue } } - // We have the msg here. - return subj, hdr, msg, seq, dc, ts, nil + // Normally it's a timeout. + if expires { + hdr := fmt.Appendf(nil, "NATS/1.0 408 Request Timeout\r\n%s: %d\r\n%s: %d\r\n\r\n", JSPullRequestPendingMsgs, wr.n, JSPullRequestPendingBytes, wr.b) + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + wr = remove(pre, wr) + continue + } else if wr.expires.IsZero() || wr.d > 0 { + // But if we're NoWait without expiry, we've reached the end of the stream, and we've not delivered any messages. + // Return no messages instead, which is the same as if we'd rejected the pull request initially. + hdr := fmt.Appendf(nil, "NATS/1.0 404 No Messages\r\n\r\n") + o.outq.send(newJSPubMsg(wr.reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + wr = remove(pre, wr) + continue + } + } + // Now check interest. + interest := wr.acc.sl.HasInterest(wr.interest) + if !interest && (s.leafNodeEnabled || s.gateway.enabled) { + // If we are here check on gateways and leaf nodes (as they can mask gateways on the other end). + // If we have interest or the request is too young break and do not expire. + if time.Since(wr.received) < defaultGatewayRecentSubExpiration { + interest = true + } else if s.gateway.enabled && s.hasGatewayInterest(wr.acc.Name, wr.interest) { + interest = true + } + } + // Check if we have interest. + if !interest { + // No more interest here so go ahead and remove this one from our list. + wr = remove(pre, wr) + continue + } + + // If interest, update batch pending requests counter and update fexp timer. + brp += wr.n + if !wr.hbt.IsZero() { + if now.After(wr.hbt) { + // Fire off a heartbeat here. + o.sendIdleHeartbeat(wr.reply) + // Update next HB. + wr.hbt = now.Add(wr.hb) + } + if fexp.IsZero() || wr.hbt.Before(fexp) { + fexp = wr.hbt + } + } + if !wr.expires.IsZero() && (fexp.IsZero() || wr.expires.Before(fexp)) { + fexp = wr.expires + } + // Update pre and wr here. + pre = wr + wr = wr.next + } + + return expired, wq.len(), brp, fexp +} + +// Will check to make sure those waiting still have registered interest. +func (o *consumer) checkWaitingForInterest() bool { + o.processWaiting(true) + return o.waiting.len() > 0 +} + +// Lock should be held. +func (o *consumer) hbTimer() (time.Duration, *time.Timer) { + if o.cfg.Heartbeat == 0 { + return 0, nil + } + return o.cfg.Heartbeat, time.NewTimer(o.cfg.Heartbeat) +} + +// Check here for conditions when our ack floor may have drifted below the streams first sequence. +// In general this is accounted for in normal operations, but if the consumer misses the signal from +// the stream it will not clear the message and move the ack state. +// Should only be called from consumer leader. +func (o *consumer) checkAckFloor() { + o.mu.RLock() + mset, closed, asflr, numPending := o.mset, o.closed, o.asflr, len(o.pending) + o.mu.RUnlock() + + if asflr == 0 || closed || mset == nil { + return + } + + var ss StreamState + mset.store.FastState(&ss) + + // If our floor is equal or greater that is normal and nothing for us to do. + if ss.FirstSeq == 0 || asflr >= ss.FirstSeq-1 { + return + } + + // Check which linear space is less to walk. + if ss.FirstSeq-asflr-1 < uint64(numPending) { + // Process all messages that no longer exist. + for seq := asflr + 1; seq < ss.FirstSeq; seq++ { + // Check if this message was pending. + o.mu.RLock() + p, isPending := o.pending[seq] + rdc := o.deliveryCount(seq) + o.mu.RUnlock() + // If it was pending for us, get rid of it. + if isPending { + o.processTerm(seq, p.Sequence, rdc, ackTermLimitsReason, _EMPTY_) + } + } + } else if numPending > 0 { + // here it is shorter to walk pending. + // toTerm is seq, dseq, rcd for each entry. + toTerm := make([]uint64, 0, numPending*3) + o.mu.RLock() + for seq, p := range o.pending { + if seq < ss.FirstSeq { + var dseq uint64 = 1 + if p != nil { + dseq = p.Sequence + } + rdc := o.deliveryCount(seq) + toTerm = append(toTerm, seq, dseq, rdc) + } + } + o.mu.RUnlock() + + for i := 0; i < len(toTerm); i += 3 { + seq, dseq, rdc := toTerm[i], toTerm[i+1], toTerm[i+2] + o.processTerm(seq, dseq, rdc, ackTermLimitsReason, _EMPTY_) + } + } + + // Do one final check here. + o.mu.Lock() + defer o.mu.Unlock() + + // If we are closed do not change anything and simply return. + if o.closed { + return + } + + // If we are here, and this should be rare, we still are off with our ack floor. + // We will make sure we are not doing un-necessary work here if only off by a bit + // since this could be normal for a high activity wq or stream. + // We will set it explicitly to 1 behind our current lowest in pending, or if + // pending is empty, to our current delivered -1. + const minOffThreshold = 50 + if ss.FirstSeq >= minOffThreshold && o.asflr < ss.FirstSeq-minOffThreshold { + var psseq, pdseq uint64 + for seq, p := range o.pending { + if psseq == 0 || seq < psseq { + psseq, pdseq = seq, p.Sequence + } } - // We got an error here. If this is an EOF we will return, otherwise - // we can continue looking. - if err == ErrStoreEOF || err == ErrStoreClosed { - return _EMPTY_, nil, nil, 0, 0, 0, err + // If we still have none, set to current delivered -1. + if psseq == 0 { + psseq, pdseq = o.sseq-1, o.dseq-1 + // If still not adjusted. + if psseq < ss.FirstSeq-1 { + psseq = ss.FirstSeq - 1 + } + } else { + // Since this was set via the pending, we should not include + // it directly but set floors to -1. + psseq, pdseq = psseq-1, pdseq-1 + } + o.asflr, o.adflr = psseq, pdseq + } +} + +func (o *consumer) processInboundAcks(qch chan struct{}) { + // Grab the server lock to watch for server quit. + o.mu.RLock() + s, mset := o.srv, o.mset + hasInactiveThresh := o.cfg.InactiveThreshold > 0 + + o.mu.RUnlock() + + if s == nil || mset == nil { + return + } + + // We will check this on entry and periodically. + o.checkAckFloor() + + // How often we will check for ack floor drift. + // Spread these out for large numbers on a server restart. + delta := time.Duration(rand.Int63n(int64(time.Minute))) + ticker := time.NewTicker(time.Minute + delta) + defer ticker.Stop() + + for { + select { + case <-o.ackMsgs.ch: + // If we have an inactiveThreshold set, mark our activity. + // Do this before processing acks, otherwise we might race if there are no pending messages + // anymore and the inactivity threshold kicks in before we're able to mark activity. + if hasInactiveThresh { + o.suppressDeletion() + } + + acks := o.ackMsgs.pop() + for _, ack := range acks { + o.processAck(ack.subject, ack.reply, ack.hdr, ack.msg) + ack.returnToPool() + } + o.ackMsgs.recycle(&acks) + case <-ticker.C: + o.checkAckFloor() + case <-qch: + return + case <-s.quitCh: + return + } + } +} + +// Process inbound next message requests. +func (o *consumer) processInboundNextMsgReqs(qch chan struct{}) { + // Grab the server lock to watch for server quit. + o.mu.RLock() + s := o.srv + o.mu.RUnlock() + + for { + select { + case <-o.nextMsgReqs.ch: + reqs := o.nextMsgReqs.pop() + for _, req := range reqs { + o.processNextMsgRequest(req.reply, req.msg) + req.returnToPool() + } + o.nextMsgReqs.recycle(&reqs) + case <-qch: + return + case <-s.quitCh: + return } - // Skip since its probably deleted or expired. - o.sseq++ } } -// forceExpireFirstWaiting will force expire the first waiting. -// Lock should be held. -func (o *Consumer) forceExpireFirstWaiting() *waitingRequest { - // FIXME(dlc) - Should we do advisory here as well? - wr := o.waiting.pop() - if wr == nil { - return wr - } - // If we are expiring this and we think there is still interest, alert. - if rr := o.acc.sl.Match(wr.reply); len(rr.psubs)+len(rr.qsubs) > 0 && o.mset != nil { - // We still appear to have interest, so send alert as courtesy. - hdr := []byte("NATS/1.0 408 Request Timeout\r\n\r\n") - pmsg := &jsPubMsg{wr.reply, wr.reply, _EMPTY_, hdr, nil, nil, 0} - o.sendq <- pmsg // Send message. +// Suppress auto cleanup on ack activity of any kind. +func (o *consumer) suppressDeletion() { + o.mu.Lock() + defer o.mu.Unlock() + + if o.closed { + return } - return wr -} -// Will check for expiration and lack of interest on waiting requests. -func (o *Consumer) expireWaiting() int { - var expired int - now := time.Now() - for wr := o.waiting.peek(); wr != nil; wr = o.waiting.peek() { - if !wr.expires.IsZero() && now.After(wr.expires) { - o.forceExpireFirstWaiting() - expired++ - continue - } - rr := o.acc.sl.Match(wr.reply) - if len(rr.psubs)+len(rr.qsubs) > 0 { - break + if o.isPushMode() && o.dtmr != nil { + // if dtmr is not nil we have started the countdown, simply reset to threshold. + o.dtmr.Reset(o.dthresh) + } else if o.isPullMode() && o.waiting != nil { + // Pull mode always has timer running, update last on waiting queue. + o.waiting.last = time.Now() + if o.dtmr != nil { + o.dtmr.Reset(o.dthresh) } - // No more interest so go ahead and remove this one from our list. - o.forceExpireFirstWaiting() - expired++ } - return expired -} - -// Will check to make sure those waiting still have registered interest. -func (o *Consumer) checkWaitingForInterest() bool { - o.expireWaiting() - return o.waiting.len() > 0 } -func (o *Consumer) loopAndGatherMsgs(s *Server, a *Account) { - // On startup check to see if we are in a a reply situtation where replay policy is not instant. +// loopAndGatherMsgs waits for messages for the consumer. qch is the quit channel, +// upch is the unpause channel which fires when the PauseUntil deadline is reached. +func (o *consumer) loopAndGatherMsgs(qch chan struct{}) { + // On startup check to see if we are in a reply situation where replay policy is not instant. var ( lts int64 // last time stamp seen, used for replay. lseq uint64 ) + o.mu.RLock() + mset := o.mset + getLSeq := o.replay + o.mu.RUnlock() + // consumer is closed when mset is set to nil. + if mset == nil { + return + } + if getLSeq { + lseq = mset.state().LastSeq + } + o.mu.Lock() - if o.replay { - // consumer is closed when mset is set to nil. - if o.mset == nil { - o.mu.Unlock() - return - } - lseq = o.mset.State().LastSeq + s := o.srv + // need to check again if consumer is closed + if o.mset == nil { + o.mu.Unlock() + return } + // For idle heartbeat support. + var hbc <-chan time.Time + hbd, hb := o.hbTimer() + if hb != nil { + hbc = hb.C + } + // Interest changes. + inch := o.inch o.mu.Unlock() + // Grab the stream's retention policy and name + mset.cfgMu.RLock() + stream, rp := mset.cfg.Name, mset.cfg.Retention + mset.cfgMu.RUnlock() + + var err error + // Deliver all the msgs we have now, once done or on a condition, we wait for new ones. for { var ( - seq, dc uint64 - subj, dsubj string - hdr []byte - msg []byte - err error - ts int64 - delay time.Duration + pmsg *jsPubMsg + dc uint64 + dsubj string + ackReply string + delay time.Duration + sz int + wrn, wrb int ) o.mu.Lock() + // consumer is closed when mset is set to nil. - if o.mset == nil { + if o.closed || o.mset == nil { o.mu.Unlock() return } - // If we are in push mode and not active let's stop sending. - if o.isPushMode() && !o.active { + // Clear last error. + err = nil + + // If the consumer is paused then stop sending. + if o.cfg.PauseUntil != nil && !o.cfg.PauseUntil.IsZero() && time.Now().Before(*o.cfg.PauseUntil) { + // If the consumer is paused and we haven't reached the deadline yet then + // go back to waiting. goto waitForMsgs } - // If we are in pull mode and no one is waiting already break and wait. - if o.isPullMode() && !o.checkWaitingForInterest() { + // If we are in push mode and not active or under flowcontrol let's stop sending. + if o.isPushMode() { + if !o.active || (o.maxpb > 0 && o.pbytes > o.maxpb) { + goto waitForMsgs + } + } else if o.waiting.isEmpty() { + // If we are in pull mode and no one is waiting already break and wait. goto waitForMsgs } - subj, hdr, msg, seq, dc, ts, err = o.getNextMsg() + // Grab our next msg. + pmsg, dc, err = o.getNextMsg() + + // We can release the lock now under getNextMsg so need to check this condition again here. + if o.closed || o.mset == nil { + o.mu.Unlock() + return + } // On error either wait or return. - if err != nil { - if err == ErrStoreMsgNotFound || err == ErrStoreEOF || err == errMaxAckPending { + if err != nil || pmsg == nil { + // On EOF we can optionally fast sync num pending state. + if err == ErrStoreEOF { + o.checkNumPendingOnEOF() + } + if err == ErrStoreMsgNotFound || err == errDeletedMsg || err == ErrStoreEOF || err == errMaxAckPending { goto waitForMsgs } else { - o.mu.Unlock() - return + if pmsg != nil { + s.Errorf("Received an error looking up message with sequence %d for consumer '%s > %s > %s': %v", + pmsg.seq, o.mset.acc, stream, o.cfg.Name, err) + } else { + s.Errorf("Received an error looking up message for consumer '%s > %s > %s': %v", + o.mset.acc, stream, o.cfg.Name, err) + } + goto waitForMsgs } } - if wr := o.waiting.pop(); wr != nil { + // Update our cached num pending here first. + if dc == 1 { + o.npc-- + } + // Pre-calculate ackReply + ackReply = o.ackReply(pmsg.seq, o.dseq, dc, pmsg.ts, o.numPending()) + + // If headers only do not send msg payload. + // Add in msg size itself as header. + if o.cfg.HeadersOnly { + convertToHeadersOnly(pmsg) + } + // Calculate payload size. This can be calculated on client side. + // We do not include transport subject here since not generally known on client. + sz = len(pmsg.subj) + len(ackReply) + len(pmsg.hdr) + len(pmsg.msg) + + if o.isPushMode() { + dsubj = o.dsubj + } else if wr := o.nextWaiting(sz); wr != nil { + wrn, wrb = wr.n, wr.b dsubj = wr.reply + if o.cfg.PriorityPolicy == PriorityPinnedClient { + // FIXME(jrm): Can we make this prettier? + if len(pmsg.hdr) == 0 { + pmsg.hdr = genHeader(pmsg.hdr, JSPullRequestNatsPinId, o.currentPinId) + pmsg.buf = append(pmsg.hdr, pmsg.msg...) + } else { + pmsg.hdr = genHeader(pmsg.hdr, JSPullRequestNatsPinId, o.currentPinId) + bufLen := len(pmsg.hdr) + len(pmsg.msg) + pmsg.buf = make([]byte, bufLen) + pmsg.buf = append(pmsg.hdr, pmsg.msg...) + } + + sz = len(pmsg.subj) + len(ackReply) + len(pmsg.hdr) + len(pmsg.msg) + + } + if done := wr.recycleIfDone(); done && o.node != nil { + o.removeClusterPendingRequest(dsubj) + } else if !done && wr.hb > 0 { + wr.hbt = time.Now().Add(wr.hb) + } } else { - dsubj = o.dsubj + // We will redo this one as long as this is not a redelivery. + // Need to also test that this is not going backwards since if + // we fail to deliver we can end up here from rdq but we do not + // want to decrement o.sseq if that is the case. + if dc == 1 && pmsg.seq == o.sseq-1 { + o.sseq-- + o.npc++ + } else if !o.onRedeliverQueue(pmsg.seq) { + // We are not on the rdq so decrement the delivery count + // and add it back. + o.decDeliveryCount(pmsg.seq) + o.addToRedeliverQueue(pmsg.seq) + } + pmsg.returnToPool() + goto waitForMsgs } // If we are in a replay scenario and have not caught up check if we need to delay here. if o.replay && lts > 0 { - if delay = time.Duration(ts - lts); delay > time.Millisecond { - qch := o.qch + if delay = time.Duration(pmsg.ts - lts); delay > time.Millisecond { o.mu.Unlock() select { case <-qch: + pmsg.returnToPool() return case <-time.After(delay): } @@ -1583,18 +4772,18 @@ func (o *Consumer) loopAndGatherMsgs(s *Server, a *Account) { } // Track this regardless. - lts = ts + lts = pmsg.ts // If we have a rate limit set make sure we check that here. if o.rlimit != nil { now := time.Now() - r := o.rlimit.ReserveN(now, len(msg)+len(hdr)+len(subj)+len(dsubj)+len(o.ackReplyT)) + r := o.rlimit.ReserveN(now, sz) delay := r.DelayFrom(now) if delay > 0 { - qch := o.qch o.mu.Unlock() select { case <-qch: + pmsg.returnToPool() return case <-time.After(delay): } @@ -1602,7 +4791,18 @@ func (o *Consumer) loopAndGatherMsgs(s *Server, a *Account) { } } - o.deliverMsg(dsubj, subj, hdr, msg, seq, dc, ts) + // Do actual delivery. + o.deliverMsg(dsubj, ackReply, pmsg, dc, rp) + + // If given request fulfilled batch size, but there are still pending bytes, send information about it. + if wrn <= 0 && wrb > 0 { + msg := fmt.Appendf(nil, JsPullRequestRemainingBytesT, JSPullRequestPendingMsgs, wrn, JSPullRequestPendingBytes, wrb) + o.outq.send(newJSPubMsg(dsubj, _EMPTY_, _EMPTY_, msg, nil, nil, 0)) + } + // Reset our idle heartbeat timer if set. + if hb != nil { + hb.Reset(hbd) + } o.mu.Unlock() continue @@ -1613,182 +4813,464 @@ func (o *Consumer) loopAndGatherMsgs(s *Server, a *Account) { o.replay = false } + // Make sure to process any expired requests that are pending. + var wrExp <-chan time.Time + if o.isPullMode() { + // Dont expire oneshots if we are here because of max ack pending limit. + _, _, _, fexp := o.processWaiting(err != errMaxAckPending) + if !fexp.IsZero() { + expires := time.Until(fexp) + if expires <= 0 { + expires = time.Millisecond + } + wrExp = time.NewTimer(expires).C + } + } + // We will wait here for new messages to arrive. - mch := o.mch - qch := o.qch + mch, odsubj := o.mch, o.cfg.DeliverSubject o.mu.Unlock() select { + case <-mch: + // Messages are waiting. + case interest := <-inch: + // inch can be nil on pull-based, but then this will + // just block and not fire. + o.updateDeliveryInterest(interest) case <-qch: return - case <-mch: + case <-wrExp: + o.mu.Lock() + o.processWaiting(true) + o.mu.Unlock() + case <-hbc: + if o.isActive() { + o.mu.RLock() + o.sendIdleHeartbeat(odsubj) + o.mu.RUnlock() + } + // Reset our idle heartbeat timer. + hb.Reset(hbd) } } } -func (o *Consumer) ackReply(sseq, dseq, dc uint64, ts int64, pending uint64) string { +// Lock should be held. +func (o *consumer) sendIdleHeartbeat(subj string) { + const t = "NATS/1.0 100 Idle Heartbeat\r\n%s: %d\r\n%s: %d\r\n\r\n" + sseq, dseq := o.sseq-1, o.dseq-1 + hdr := fmt.Appendf(nil, t, JSLastConsumerSeq, dseq, JSLastStreamSeq, sseq) + if fcp := o.fcid; fcp != _EMPTY_ { + // Add in that we are stalled on flow control here. + addOn := fmt.Appendf(nil, "%s: %s\r\n\r\n", JSConsumerStalled, fcp) + hdr = append(hdr[:len(hdr)-LEN_CR_LF], []byte(addOn)...) + } + o.outq.send(newJSPubMsg(subj, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) +} + +func (o *consumer) ackReply(sseq, dseq, dc uint64, ts int64, pending uint64) string { return fmt.Sprintf(o.ackReplyT, dc, sseq, dseq, ts, pending) } -// deliverCurrentMsg is the hot path to deliver a message that was just received. -// Will return if the message was delivered or not. -func (o *Consumer) deliverCurrentMsg(subj string, hdr, msg []byte, seq uint64, ts int64) bool { - o.mu.Lock() - if seq != o.sseq { - o.mu.Unlock() - return false +// Used mostly for testing. Sets max pending bytes for flow control setups. +func (o *consumer) setMaxPendingBytes(limit int) { + o.pblimit = limit + o.maxpb = limit / 16 + if o.maxpb == 0 { + o.maxpb = 1 } +} - // If we are in push mode and not active let's stop sending. - if o.isPushMode() && !o.active { - o.mu.Unlock() - return false +// Does some sanity checks to see if we should re-calculate. +// Since there is a race when decrementing when there is contention at the beginning of the stream. +// The race is a getNextMsg skips a deleted msg, and then the decStreamPending call fires. +// This does some quick sanity checks to see if we should re-calculate num pending. +// Lock should be held. +func (o *consumer) checkNumPending() uint64 { + if o.mset != nil && o.mset.store != nil { + var state StreamState + o.mset.store.FastState(&state) + npc := o.numPending() + if o.sseq > state.LastSeq && npc > 0 || npc > state.Msgs { + // Re-calculate. + o.streamNumPending() + } } + return o.numPending() +} - // If we are in pull mode and no one is waiting already break and wait. - if o.isPullMode() && !o.checkWaitingForInterest() { - o.mu.Unlock() - return false +// Lock should be held. +func (o *consumer) numPending() uint64 { + if o.npc < 0 { + return 0 } + return uint64(o.npc) +} - // Since we short circuit the getNextMsg() call where we check for max pending - // we need to do that here as well. - if o.maxp > 0 && len(o.pending) >= o.maxp { - o.mu.Unlock() - return false +// This will do a quick sanity check on num pending when we encounter +// and EOF in the loop and gather. +// Lock should be held. +func (o *consumer) checkNumPendingOnEOF() { + if o.mset == nil { + return + } + var state StreamState + o.mset.store.FastState(&state) + if o.sseq > state.LastSeq && o.npc != 0 { + // We know here we can reset our running state for num pending. + o.npc, o.npf = 0, state.LastSeq } +} - // Bump store sequence here. - o.sseq++ +// Call into streamNumPending after acquiring the consumer lock. +func (o *consumer) streamNumPendingLocked() uint64 { + o.mu.Lock() + defer o.mu.Unlock() + return o.streamNumPending() +} - // If we are partitioned and we do not match, do not consider this a failure. - // Go ahead and return true. - if o.config.FilterSubject != _EMPTY_ && !o.isFilteredMatch(subj) { - o.mu.Unlock() - return true +// Will force a set from the stream store of num pending. +// Depends on delivery policy, for last per subject we calculate differently. +// Lock should be held. +func (o *consumer) streamNumPending() uint64 { + if o.mset == nil || o.mset.store == nil { + o.npc, o.npf = 0, 0 + return 0 } + npc, npf := o.calculateNumPending() + o.npc, o.npf = int64(npc), npf + return o.numPending() +} - var dsubj string - if wr := o.waiting.pop(); wr != nil { - dsubj = wr.reply - } else { - dsubj = o.dsubj +// Will calculate num pending but only requires a read lock. +// Depends on delivery policy, for last per subject we calculate differently. +// At least RLock should be held. +func (o *consumer) calculateNumPending() (npc, npf uint64) { + if o.mset == nil || o.mset.store == nil { + return 0, 0 } - o.deliverMsg(dsubj, subj, hdr, msg, seq, 1, ts) - o.mu.Unlock() + isLastPerSubject := o.cfg.DeliverPolicy == DeliverLastPerSubject + filters, subjf := o.filters, o.subjf - return true + if filters != nil { + return o.mset.store.NumPendingMulti(o.sseq, filters, isLastPerSubject) + } else if len(subjf) > 0 { + filter := subjf[0].subject + return o.mset.store.NumPending(o.sseq, filter, isLastPerSubject) + } + return o.mset.store.NumPending(o.sseq, _EMPTY_, isLastPerSubject) +} + +func convertToHeadersOnly(pmsg *jsPubMsg) { + // If headers only do not send msg payload. + // Add in msg size itself as header. + hdr, msg := pmsg.hdr, pmsg.msg + var bb bytes.Buffer + if len(hdr) == 0 { + bb.WriteString(hdrLine) + } else { + bb.Write(hdr) + bb.Truncate(len(hdr) - LEN_CR_LF) + } + bb.WriteString(JSMsgSize) + bb.WriteString(": ") + bb.WriteString(strconv.FormatInt(int64(len(msg)), 10)) + bb.WriteString(CR_LF) + bb.WriteString(CR_LF) + // Replace underlying buf which we can use directly when we send. + // TODO(dlc) - Probably just use directly when forming bytes.Buffer? + pmsg.buf = pmsg.buf[:0] + pmsg.buf = append(pmsg.buf, bb.Bytes()...) + // Replace with new header. + pmsg.hdr = pmsg.buf + // Cancel msg payload + pmsg.msg = nil } // Deliver a msg to the consumer. // Lock should be held and o.mset validated to be non-nil. -func (o *Consumer) deliverMsg(dsubj, subj string, hdr, msg []byte, seq, dc uint64, ts int64) { +func (o *consumer) deliverMsg(dsubj, ackReply string, pmsg *jsPubMsg, dc uint64, rp RetentionPolicy) { if o.mset == nil { + pmsg.returnToPool() return } - // Update pending on first attempt - if dc == 1 && o.sgap > 0 { - o.sgap-- - } - if len(hdr) > 0 { - hdr = append(hdr[:0:0], hdr...) - } - if len(msg) > 0 { - msg = append(msg[:0:0], msg...) + dseq := o.dseq + o.dseq++ + + pmsg.dsubj, pmsg.reply, pmsg.o = dsubj, ackReply, o + psz := pmsg.size() + + if o.maxpb > 0 { + o.pbytes += psz } - dseq := o.dseq - pmsg := &jsPubMsg{dsubj, subj, o.ackReply(seq, dseq, dc, ts, o.sgap), hdr, msg, o, seq} mset := o.mset - ap := o.config.AckPolicy + ap := o.cfg.AckPolicy - // This needs to be unlocked since the other side may need this lock on a failed delivery. - o.mu.Unlock() - // Send message. - o.sendq <- pmsg - // If we are ack none and mset is interest only we should make sure stream removes interest. - if ap == AckNone && mset.config.Retention == InterestPolicy && !mset.checkInterest(seq, o) { - mset.store.RemoveMsg(seq) - } - // Re-acquire lock. - o.mu.Lock() + // Cant touch pmsg after this sending so capture what we need. + seq, ts := pmsg.seq, pmsg.ts + + // Update delivered first. + o.updateDelivered(dseq, seq, dc, ts) if ap == AckExplicit || ap == AckAll { o.trackPending(seq, dseq) } else if ap == AckNone { - o.adflr = o.dseq + o.adflr = dseq o.asflr = seq } - o.dseq++ + // Send message. + if o.replicateDeliveries() { + o.addReplicatedQueuedMsg(pmsg) + } else { + o.outq.send(pmsg) + } + + // Flow control. + if o.maxpb > 0 && o.needFlowControl(psz) { + o.sendFlowControl() + } + + // If pull mode and we have inactivity threshold, signaled by dthresh, update last activity. + if o.isPullMode() && o.dthresh > 0 { + o.waiting.last = time.Now() + } + + // If we are ack none and mset is interest only we should make sure stream removes interest. + if ap == AckNone && rp != LimitsPolicy { + if mset != nil && mset.ackq != nil && (o.node == nil || o.cfg.Direct) { + mset.ackq.push(seq) + } else { + o.updateAcks(dseq, seq, _EMPTY_) + } + } +} + +// replicateDeliveries returns whether deliveries should be replicated before sending them. +// If we're replicated we MUST only send the message AFTER we've got quorum for updating +// delivered state. Otherwise, we could be in an invalid state after a leader change. +// We can send immediately if not replicated, not using acks, or using flow control (incompatible). +// Lock should be held. +func (o *consumer) replicateDeliveries() bool { + return o.node != nil && o.cfg.AckPolicy != AckNone && !o.cfg.FlowControl +} + +func (o *consumer) needFlowControl(sz int) bool { + if o.maxpb == 0 { + return false + } + // Decide whether to send a flow control message which we will need the user to respond. + // We send when we are over 50% of our current window limit. + if o.fcid == _EMPTY_ && o.pbytes > o.maxpb/2 { + return true + } + // If we have an existing outstanding FC, check to see if we need to expand the o.fcsz + if o.fcid != _EMPTY_ && (o.pbytes-o.fcsz) >= o.maxpb { + o.fcsz += sz + } + return false +} + +func (o *consumer) processFlowControl(_ *subscription, c *client, _ *Account, subj, _ string, _ []byte) { + o.mu.Lock() + defer o.mu.Unlock() + + // Ignore if not the latest we have sent out. + if subj != o.fcid { + return + } + + // For slow starts and ramping up. + if o.maxpb < o.pblimit { + o.maxpb *= 2 + if o.maxpb > o.pblimit { + o.maxpb = o.pblimit + } + } + + // Update accounting. + o.pbytes -= o.fcsz + if o.pbytes < 0 { + o.pbytes = 0 + } + o.fcid, o.fcsz = _EMPTY_, 0 + + o.signalNewMessages() +} + +// Lock should be held. +func (o *consumer) fcReply() string { + var sb strings.Builder + sb.WriteString(jsFlowControlPre) + sb.WriteString(o.stream) + sb.WriteByte(btsep) + sb.WriteString(o.name) + sb.WriteByte(btsep) + var b [4]byte + rn := rand.Int63() + for i, l := 0, rn; i < len(b); i++ { + b[i] = digits[l%base] + l /= base + } + sb.Write(b[:]) + return sb.String() +} - // FIXME(dlc) - Capture errors? - o.store.UpdateDelivered(dseq, seq, dc, ts) +// sendFlowControl will send a flow control packet to the consumer. +// Lock should be held. +func (o *consumer) sendFlowControl() { + if !o.isPushMode() { + return + } + subj, rply := o.cfg.DeliverSubject, o.fcReply() + o.fcsz, o.fcid = o.pbytes, rply + hdr := []byte("NATS/1.0 100 FlowControl Request\r\n\r\n") + o.outq.send(newJSPubMsg(subj, _EMPTY_, rply, hdr, nil, nil, 0)) } // Tracks our outstanding pending acks. Only applicable to AckExplicit mode. // Lock should be held. -func (o *Consumer) trackPending(sseq, dseq uint64) { +func (o *consumer) trackPending(sseq, dseq uint64) { if o.pending == nil { o.pending = make(map[uint64]*Pending) } - if o.ptmr == nil { - o.ptmr = time.AfterFunc(o.ackWait(0), o.checkPending) - } + + now := time.Now() if p, ok := o.pending[sseq]; ok { - p.Timestamp = time.Now().UnixNano() + // Update timestamp but keep original consumer delivery sequence. + // So do not update p.Sequence. + p.Timestamp = now.UnixNano() } else { - o.pending[sseq] = &Pending{dseq, time.Now().UnixNano()} + o.pending[sseq] = &Pending{dseq, now.UnixNano()} + } + + // We could have a backoff that set a timer higher than what we need for this message. + // In that case, reset to lowest backoff required for a message redelivery. + minDelay := o.ackWait(0) + if l := len(o.cfg.BackOff); l > 0 { + bi := int(o.rdc[sseq]) + if bi < 0 { + bi = 0 + } else if bi >= l { + bi = l - 1 + } + minDelay = o.ackWait(o.cfg.BackOff[bi]) + } + minDeadline := now.Add(minDelay) + if o.ptmr == nil || o.ptmrEnd.After(minDeadline) { + o.resetPtmr(minDelay) + } +} + +// Credit back a failed delivery. +// lock should be held. +func (o *consumer) creditWaitingRequest(reply string) { + wq := o.waiting + for wr := wq.head; wr != nil; wr = wr.next { + if wr.reply == reply { + wr.n++ + wr.d-- + return + } } } // didNotDeliver is called when a delivery for a consumer message failed. // Depending on our state, we will process the failure. -func (o *Consumer) didNotDeliver(seq uint64) { +func (o *consumer) didNotDeliver(seq uint64, subj string) { o.mu.Lock() mset := o.mset if mset == nil { o.mu.Unlock() return } + // Adjust back deliver count. + o.decDeliveryCount(seq) + var checkDeliveryInterest bool if o.isPushMode() { o.active = false + checkDeliveryInterest = true } else if o.pending != nil { + // Good chance we did not deliver because no interest so force a check. + o.processWaiting(false) + // If it is still there credit it back. + o.creditWaitingRequest(subj) // pull mode and we have pending. if _, ok := o.pending[seq]; ok { // We found this messsage on pending, we need // to queue it up for immediate redelivery since - // we know it was not delivered. + // we know it was not delivered if !o.onRedeliverQueue(seq) { - o.rdq = append(o.rdq, seq) - o.signalNewMessages() + o.addToRedeliverQueue(seq) + if !o.waiting.isEmpty() { + o.signalNewMessages() + } } } } o.mu.Unlock() + + if checkDeliveryInterest { + localInterest := !o.hasNoLocalInterest() + o.updateDeliveryInterest(localInterest) + } +} + +// Lock should be held. +func (o *consumer) addToRedeliverQueue(seqs ...uint64) { + o.rdq = append(o.rdq, seqs...) + for _, seq := range seqs { + o.rdqi.Insert(seq) + } +} + +// Lock should be held. +func (o *consumer) hasRedeliveries() bool { + return len(o.rdq) > 0 +} + +func (o *consumer) getNextToRedeliver() uint64 { + if len(o.rdq) == 0 { + return 0 + } + seq := o.rdq[0] + if len(o.rdq) == 1 { + o.rdq = nil + o.rdqi.Empty() + } else { + o.rdq = append(o.rdq[:0], o.rdq[1:]...) + o.rdqi.Delete(seq) + } + return seq } // This checks if we already have this sequence queued for redelivery. // FIXME(dlc) - This is O(n) but should be fast with small redeliver size. // Lock should be held. -func (o *Consumer) onRedeliverQueue(seq uint64) bool { - for _, rseq := range o.rdq { - if rseq == seq { - return true - } - } - return false +func (o *consumer) onRedeliverQueue(seq uint64) bool { + return o.rdqi.Exists(seq) } // Remove a sequence from the redelivery queue. // Lock should be held. -func (o *Consumer) removeFromRedeliverQueue(seq uint64) bool { +func (o *consumer) removeFromRedeliverQueue(seq uint64) bool { + if !o.onRedeliverQueue(seq) { + return false + } for i, rseq := range o.rdq { if rseq == seq { - o.rdq = append(o.rdq[:i], o.rdq[i+1:]...) + if len(o.rdq) == 1 { + o.rdq = nil + o.rdqi.Empty() + } else { + o.rdq = append(o.rdq[:i], o.rdq[i+1:]...) + o.rdqi.Delete(seq) + } return true } } @@ -1796,38 +5278,92 @@ func (o *Consumer) removeFromRedeliverQueue(seq uint64) bool { } // Checks the pending messages. -func (o *Consumer) checkPending() { +func (o *consumer) checkPending() { o.mu.Lock() defer o.mu.Unlock() mset := o.mset - if mset == nil { + // On stop, mset and timer will be nil. + if o.closed || mset == nil || o.ptmr == nil { + o.stopAndClearPtmr() return } - ttl := int64(o.config.AckWait) - next := int64(o.ackWait(0)) + + var shouldUpdateState bool + var state StreamState + mset.store.FastState(&state) + fseq := state.FirstSeq + now := time.Now().UnixNano() + ttl := int64(o.cfg.AckWait) + next := int64(o.ackWait(0)) + // However, if there is backoff, initializes with the largest backoff. + // It will be adjusted as needed. + if l := len(o.cfg.BackOff); l > 0 { + next = int64(o.cfg.BackOff[l-1]) + } // Since we can update timestamps, we have to review all pending. - // We may want to unlock here or warn if list is big. + // We will now bail if we see an ack pending inbound to us via o.awl. var expired []uint64 + check := len(o.pending) > 1024 for seq, p := range o.pending { - elapsed := now - p.Timestamp - if elapsed >= ttl { - if !o.onRedeliverQueue(seq) { + if check && atomic.LoadInt64(&o.awl) > 0 { + o.resetPtmr(100 * time.Millisecond) + return + } + // Check if these are no longer valid. + if seq < fseq || seq <= o.asflr { + delete(o.pending, seq) + delete(o.rdc, seq) + o.removeFromRedeliverQueue(seq) + shouldUpdateState = true + // Check if we need to move ack floors. + if seq > o.asflr { + o.asflr = seq + } + if p.Sequence > o.adflr { + o.adflr = p.Sequence + } + continue + } + elapsed, deadline := now-p.Timestamp, ttl + if len(o.cfg.BackOff) > 0 { + // This is ok even if o.rdc is nil, we would get dc == 0, which is what we want. + dc := int(o.rdc[seq]) + if dc < 0 { + // Prevent consumer backoff from going backwards. + dc = 0 + } + // This will be the index for the next backoff, will set to last element if needed. + nbi := dc + 1 + if dc+1 >= len(o.cfg.BackOff) { + dc = len(o.cfg.BackOff) - 1 + nbi = dc + } + deadline = int64(o.cfg.BackOff[dc]) + // Set `next` to the next backoff (if smaller than current `next` value). + if nextBackoff := int64(o.cfg.BackOff[nbi]); nextBackoff < next { + next = nextBackoff + } + } + if elapsed >= deadline { + // We will check if we have hit our max deliveries. Previously we would do this on getNextMsg() which + // worked well for push consumers, but with pull based consumers would require a new pull request to be + // present to process and redelivered could be reported incorrectly. + if !o.onRedeliverQueue(seq) && !o.hasMaxDeliveries(seq) { expired = append(expired, seq) - o.signalNewMessages() } - } else if ttl-elapsed < next { + } else if deadline-elapsed < next { // Update when we should fire next. - next = ttl - elapsed + next = deadline - elapsed } } if len(expired) > 0 { // We need to sort. - sort.Slice(expired, func(i, j int) bool { return expired[i] < expired[j] }) - o.rdq = append(o.rdq, expired...) + slices.Sort(expired) + o.addToRedeliverQueue(expired...) // Now we should update the timestamp here since we are redelivering. // We will use an incrementing time to preserve order for any other redelivery. off := now - o.pending[expired[0]].Timestamp @@ -1836,24 +5372,38 @@ func (o *Consumer) checkPending() { p.Timestamp += off } } + o.signalNewMessages() } if len(o.pending) > 0 { - o.ptmr.Reset(o.ackWait(time.Duration(next))) + o.resetPtmr(time.Duration(next)) } else { - o.ptmr.Stop() - o.ptmr = nil + // Make sure to stop timer and clear out any re delivery queues + o.stopAndClearPtmr() + o.rdq = nil + o.rdqi.Empty() + o.pending = nil + // Mimic behavior in processAckMsg when pending is empty. + o.adflr, o.asflr = o.dseq-1, o.sseq-1 + } + + // Update our state if needed. + if shouldUpdateState { + if err := o.writeStoreStateUnlocked(); err != nil && o.srv != nil && o.mset != nil && !o.closed { + s, acc, mset, name := o.srv, o.acc, o.mset, o.name + s.Warnf("Consumer '%s > %s > %s' error on write store state from check pending: %v", acc, mset.getCfgName(), name, err) + } } } // SeqFromReply will extract a sequence number from a reply subject. -func (o *Consumer) SeqFromReply(reply string) uint64 { +func (o *consumer) seqFromReply(reply string) uint64 { _, dseq, _ := ackReplyInfo(reply) return dseq } // StreamSeqFromReply will extract the stream sequence from the reply subject. -func (o *Consumer) StreamSeqFromReply(reply string) uint64 { +func (o *consumer) streamSeqFromReply(reply string) uint64 { sseq, _, _ := ackReplyInfo(reply) return sseq } @@ -1875,7 +5425,7 @@ func parseAckReplyNum(d string) (n int64) { const expectedNumReplyTokens = 9 // Grab encoded information in the reply subject for a delivered message. -func (o *Consumer) ReplyInfo(subject string) (sseq, dseq, dc uint64, ts int64, pending uint64) { +func replyInfo(subject string) (sseq, dseq, dc uint64, ts int64, pending uint64) { tsa := [expectedNumReplyTokens]string{} start, tokens := 0, tsa[:0] for i := 0; i < len(subject); i++ { @@ -1917,72 +5467,132 @@ func ackReplyInfo(subject string) (sseq, dseq, dc uint64) { return sseq, dseq, dc } -// NextSeq returns the next delivered sequence number for this observable. -func (o *Consumer) NextSeq() uint64 { - o.mu.Lock() +// NextSeq returns the next delivered sequence number for this consumer. +func (o *consumer) nextSeq() uint64 { + o.mu.RLock() dseq := o.dseq - o.mu.Unlock() + o.mu.RUnlock() return dseq } -// This will select the store seq to start with based on the -// partition subject. -func (o *Consumer) selectSubjectLast() { - stats := o.mset.store.State() - if stats.LastSeq == 0 { - o.sseq = stats.LastSeq - return - } - // FIXME(dlc) - this is linear and can be optimized by store layer. - for seq := stats.LastSeq; seq >= stats.FirstSeq; seq-- { - subj, _, _, _, err := o.mset.store.LoadMsg(seq) - if err == ErrStoreMsgNotFound { - continue - } - if o.isFilteredMatch(subj) { - o.sseq = seq - return - } - } +// Used to hold skip list when deliver policy is last per subject. +type lastSeqSkipList struct { + resume uint64 + seqs []uint64 +} + +// Let's us know we have a skip list, which is for deliver last per subject and we are just starting. +// Lock should be held. +func (o *consumer) hasSkipListPending() bool { + return o.lss != nil && len(o.lss.seqs) > 0 } // Will select the starting sequence. -func (o *Consumer) selectStartingSeqNo() { - stats := o.mset.store.State() - if o.config.OptStartSeq == 0 { - if o.config.DeliverPolicy == DeliverAll { - o.sseq = stats.FirstSeq - } else if o.config.DeliverPolicy == DeliverLast { - o.sseq = stats.LastSeq - // If we are partitioned here we may need to walk backwards. - if o.config.FilterSubject != _EMPTY_ { - o.selectSubjectLast() - } - } else if o.config.OptStartTime != nil { - // If we are here we are time based. - // TODO(dlc) - Once clustered can't rely on this. - o.sseq = o.mset.store.GetSeqFromTime(*o.config.OptStartTime) +func (o *consumer) selectStartingSeqNo() { + if o.mset == nil || o.mset.store == nil { + o.sseq = 1 + } else { + var state StreamState + o.mset.store.FastState(&state) + if o.cfg.OptStartSeq == 0 { + if o.cfg.DeliverPolicy == DeliverAll { + o.sseq = state.FirstSeq + } else if o.cfg.DeliverPolicy == DeliverLast { + if o.subjf == nil { + o.sseq = state.LastSeq + } else { + // If we are partitioned here this will be properly set when we become leader. + for _, filter := range o.subjf { + ss := o.mset.store.FilteredState(1, filter.subject) + if ss.Last > o.sseq { + o.sseq = ss.Last + } + } + } + } else if o.cfg.DeliverPolicy == DeliverLastPerSubject { + // If our parent stream is set to max msgs per subject of 1 this is just + // a normal consumer at this point. We can avoid any heavy lifting. + o.mset.cfgMu.RLock() + mmp := o.mset.cfg.MaxMsgsPer + o.mset.cfgMu.RUnlock() + if mmp == 1 { + o.sseq = state.FirstSeq + } else { + filters := make([]string, 0, len(o.subjf)) + if o.subjf == nil { + filters = append(filters, o.cfg.FilterSubject) + } else { + for _, filter := range o.subjf { + filters = append(filters, filter.subject) + } + } + + lss := &lastSeqSkipList{resume: state.LastSeq} + lss.seqs, _ = o.mset.store.MultiLastSeqs(filters, 0, 0) + + if len(lss.seqs) == 0 { + o.sseq = state.LastSeq + } else { + o.sseq = lss.seqs[0] + } + // Assign skip list. + o.lss = lss + } + } else if o.cfg.OptStartTime != nil { + // If we are here we are time based. + // TODO(dlc) - Once clustered can't rely on this. + o.sseq = o.mset.store.GetSeqFromTime(*o.cfg.OptStartTime) + // Here we want to see if we are filtered, and if so possibly close the gap + // to the nearest first given our starting sequence from time. This is so we do + // not force the system to do a linear walk between o.sseq and the real first. + if len(o.subjf) > 0 { + nseq := state.LastSeq + for _, filter := range o.subjf { + // Use first sequence since this is more optimized atm. + ss := o.mset.store.FilteredState(state.FirstSeq, filter.subject) + if ss.First >= o.sseq && ss.First < nseq { + nseq = ss.First + } + } + // Skip ahead if possible. + if nseq > o.sseq && nseq < state.LastSeq { + o.sseq = nseq + } + } + } else { + // DeliverNew + o.sseq = state.LastSeq + 1 + } } else { - // Default is deliver new only. - o.sseq = stats.LastSeq + 1 + o.sseq = o.cfg.OptStartSeq } - } else { - o.sseq = o.config.OptStartSeq - } - if stats.FirstSeq == 0 { - o.sseq = 1 - } else if o.sseq < stats.FirstSeq { - o.sseq = stats.FirstSeq - } else if o.sseq > stats.LastSeq { - o.sseq = stats.LastSeq + 1 + if state.FirstSeq == 0 && (o.cfg.Direct || o.cfg.OptStartSeq == 0) { + // If the stream is empty, deliver only new. + // But only if mirroring/sourcing, or start seq is unset, otherwise need to respect provided value. + o.sseq = 1 + } else if o.sseq > state.LastSeq && (o.cfg.Direct || o.cfg.OptStartSeq == 0) { + // If selected sequence is in the future, clamp back down. + // But only if mirroring/sourcing, or start seq is unset, otherwise need to respect provided value. + o.sseq = state.LastSeq + 1 + } else if o.sseq < state.FirstSeq { + // If the first sequence is further ahead than the starting sequence, + // there are no messages there anymore, so move the sequence up. + o.sseq = state.FirstSeq + } } + // Always set delivery sequence to 1. o.dseq = 1 // Set ack delivery floor to delivery-1 o.adflr = o.dseq - 1 // Set ack store floor to store-1 o.asflr = o.sseq - 1 + // Set our starting sequence state. + // But only if we're not clustered, if clustered we propose upon becoming leader. + if o.store != nil && o.sseq > 0 && o.cfg.replicas(&o.mset.cfg) == 1 { + o.store.SetStarting(o.sseq - 1) + } } // Test whether a config represents a durable subscriber. @@ -1990,88 +5600,155 @@ func isDurableConsumer(config *ConsumerConfig) bool { return config != nil && config.Durable != _EMPTY_ } -func (o *Consumer) isDurable() bool { - return o.config.Durable != _EMPTY_ +func (o *consumer) isDurable() bool { + return o.cfg.Durable != _EMPTY_ } // Are we in push mode, delivery subject, etc. -func (o *Consumer) isPushMode() bool { - return o.config.DeliverSubject != _EMPTY_ +func (o *consumer) isPushMode() bool { + return o.cfg.DeliverSubject != _EMPTY_ } -func (o *Consumer) isPullMode() bool { - return o.config.DeliverSubject == _EMPTY_ +func (o *consumer) isPullMode() bool { + return o.cfg.DeliverSubject == _EMPTY_ } -// Name returns the name of this observable. -func (o *Consumer) Name() string { - o.mu.Lock() +// Name returns the name of this consumer. +func (o *consumer) String() string { + o.mu.RLock() n := o.name - o.mu.Unlock() + o.mu.RUnlock() return n } -// For now size of 6 for randomly created names. -const randConsumerNameLen = 6 - func createConsumerName() string { - var b [256]byte - rand.Read(b[:]) - sha := sha256.New() - sha.Write(b[:]) - return fmt.Sprintf("%x", sha.Sum(nil))[:randConsumerNameLen] + return getHash(nuid.Next()) +} + +// deleteConsumer will delete the consumer from this stream. +func (mset *stream) deleteConsumer(o *consumer) error { + return o.delete() +} + +func (o *consumer) getStream() *stream { + o.mu.RLock() + mset := o.mset + o.mu.RUnlock() + return mset } -// DeleteConsumer will delete the consumer from this stream. -func (mset *Stream) DeleteConsumer(o *Consumer) error { - return o.Delete() +func (o *consumer) streamName() string { + o.mu.RLock() + mset := o.mset + o.mu.RUnlock() + if mset != nil { + return mset.name() + } + return _EMPTY_ } // Active indicates if this consumer is still active. -func (o *Consumer) Active() bool { - o.mu.Lock() +func (o *consumer) isActive() bool { + o.mu.RLock() active := o.active && o.mset != nil - o.mu.Unlock() + o.mu.RUnlock() return active } // hasNoLocalInterest return true if we have no local interest. -func (o *Consumer) hasNoLocalInterest() bool { - o.mu.Lock() - rr := o.acc.sl.Match(o.config.DeliverSubject) - o.mu.Unlock() - return len(rr.psubs)+len(rr.qsubs) == 0 +func (o *consumer) hasNoLocalInterest() bool { + o.mu.RLock() + interest := o.acc.sl.HasInterest(o.cfg.DeliverSubject) + o.mu.RUnlock() + return !interest } // This is when the underlying stream has been purged. -func (o *Consumer) purge(sseq uint64) { +// sseq is the new first seq for the stream after purge. +// Consumer lock should NOT be held but the parent stream +// lock MUST be held. +func (o *consumer) purge(sseq uint64, slseq uint64, isWider bool) { + // Do not update our state unless we know we are the leader. + if !o.isLeader() { + return + } + // Signals all have been purged for this consumer. + if sseq == 0 && !isWider { + sseq = slseq + 1 + } + + var store StreamStore + if isWider { + o.mu.RLock() + if o.mset != nil { + store = o.mset.store + } + o.mu.RUnlock() + } + o.mu.Lock() - o.sseq = sseq - o.asflr = sseq - 1 - o.adflr = o.dseq - 1 - o.sgap = 0 - if len(o.pending) > 0 { - o.pending = nil - if o.ptmr != nil { - o.ptmr.Stop() - // Do not nil this out here. This allows checkPending to fire - // and still be ok and not panic. + // Do not go backwards + if o.sseq < sseq { + o.sseq = sseq + } + + if o.asflr < sseq { + o.asflr = sseq - 1 + // We need to remove those no longer relevant from pending. + for seq, p := range o.pending { + if seq <= o.asflr { + if p.Sequence > o.adflr { + o.adflr = p.Sequence + if o.adflr > o.dseq { + o.dseq = o.adflr + } + } + delete(o.pending, seq) + delete(o.rdc, seq) + // rdq handled below. + } + if isWider && store != nil { + // Our filtered subject, which could be all, is wider than the underlying purge. + // We need to check if the pending items left are still valid. + var smv StoreMsg + if _, err := store.LoadMsg(seq, &smv); err == errDeletedMsg || err == ErrStoreMsgNotFound { + if p.Sequence > o.adflr { + o.adflr = p.Sequence + if o.adflr > o.dseq { + o.dseq = o.adflr + } + } + delete(o.pending, seq) + delete(o.rdc, seq) + } + } } } + + // This means we can reset everything at this point. + if len(o.pending) == 0 { + o.pending, o.rdc = nil, nil + o.adflr, o.asflr = o.dseq-1, o.sseq-1 + } + // We need to remove all those being queued for redelivery under o.rdq if len(o.rdq) > 0 { - var newRDQ []uint64 - for _, sseq := range o.rdq { + rdq := o.rdq + o.rdq = nil + o.rdqi.Empty() + for _, sseq := range rdq { if sseq >= o.sseq { - newRDQ = append(newRDQ, sseq) + o.addToRedeliverQueue(sseq) } } - // Replace with new list. Most of the time this will be nil. - o.rdq = newRDQ } + // Grab some info in case of error below. + s, acc, mset, name := o.srv, o.acc, o.mset, o.name o.mu.Unlock() - o.writeState() + if err := o.writeStoreState(); err != nil && s != nil && mset != nil { + s.Warnf("Consumer '%s > %s > %s' error on write store state from purge: %v", acc, mset.nameLocked(false), name, err) + } } func stopAndClearTimer(tp **time.Timer) { @@ -2085,20 +5762,49 @@ func stopAndClearTimer(tp **time.Timer) { } // Stop will shutdown the consumer for the associated stream. -func (o *Consumer) Stop() error { - return o.stop(false, true, false) +func (o *consumer) stop() error { + return o.stopWithFlags(false, false, true, false) } -func (o *Consumer) deleteWithoutAdvisory() error { - return o.stop(true, true, false) +func (o *consumer) deleteWithoutAdvisory() error { + return o.stopWithFlags(true, false, true, false) } // Delete will delete the consumer for the associated stream and send advisories. -func (o *Consumer) Delete() error { - return o.stop(true, true, true) +func (o *consumer) delete() error { + return o.stopWithFlags(true, false, true, true) +} + +// To test for closed state. +func (o *consumer) isClosed() bool { + o.mu.RLock() + defer o.mu.RUnlock() + return o.closed } -func (o *Consumer) stop(dflag, doSignal, advisory bool) error { +func (o *consumer) stopWithFlags(dflag, sdflag, doSignal, advisory bool) error { + // If dflag is true determine if we are still assigned. + var isAssigned bool + if dflag { + o.mu.RLock() + acc, stream, consumer := o.acc, o.stream, o.name + isClustered := o.js != nil && o.js.isClustered() + o.mu.RUnlock() + if isClustered { + // Grab jsa to check assignment. + var jsa *jsAccount + if acc != nil { + // Need lock here to avoid data race. + acc.mu.RLock() + jsa = acc.js + acc.mu.RUnlock() + } + if jsa != nil { + isAssigned = jsa.consumerAssigned(stream, consumer) + } + } + } + o.mu.Lock() if o.closed { o.mu.Unlock() @@ -2106,178 +5812,532 @@ func (o *Consumer) stop(dflag, doSignal, advisory bool) error { } o.closed = true - if dflag && advisory { - o.sendDeleteAdvisoryLocked() + // Signal to the monitor loop. + // Can't use only qch here, since that's used when stepping down as a leader. + if o.mqch != nil { + close(o.mqch) + o.mqch = nil } - a := o.acc - close(o.qch) + // Check if we are the leader and are being deleted (as a node). + if dflag && o.isLeader() { + // If we are clustered and node leader (probable from above), stepdown. + if node := o.node; node != nil { + node.StepDown() + } + + // dflag does not necessarily mean that the consumer is being deleted, + // just that the consumer node is being removed from this peer, so we + // send delete advisories only if we are no longer assigned at the meta layer, + // or we are not clustered. + if !isAssigned && advisory { + o.sendDeleteAdvisoryLocked() + } + if o.isPullMode() { + // Release any pending. + o.releaseAnyPendingRequests(isAssigned) + } + } + + if o.qch != nil { + close(o.qch) + o.qch = nil + } + a := o.acc store := o.store mset := o.mset o.mset = nil o.active = false - ackSub := o.ackSub - reqSub := o.reqSub + o.unsubscribe(o.ackSub) + o.unsubscribe(o.reqSub) + o.unsubscribe(o.fcSub) o.ackSub = nil o.reqSub = nil - stopAndClearTimer(&o.ptmr) + o.fcSub = nil + if o.infoSub != nil { + o.srv.sysUnsubscribe(o.infoSub) + o.infoSub = nil + } + c := o.client + o.client = nil + sysc := o.sysc + o.sysc = nil + o.stopAndClearPtmr() stopAndClearTimer(&o.dtmr) - delivery := o.config.DeliverSubject + stopAndClearTimer(&o.gwdtmr) + delivery := o.cfg.DeliverSubject o.waiting = nil // Break us out of the readLoop. if doSignal { o.signalNewMessages() } + n := o.node + qgroup := o.cfg.DeliverGroup + o.ackMsgs.unregister() + if o.nextMsgReqs != nil { + o.nextMsgReqs.unregister() + } + + // For cleaning up the node assignment. + var ca *consumerAssignment + if dflag { + ca = o.ca + } + js := o.js o.mu.Unlock() - if delivery != "" { - a.sl.ClearNotification(delivery, o.inch) + if c != nil { + c.closeConnection(ClientClosed) + } + if sysc != nil { + sysc.closeConnection(ClientClosed) } - mset.mu.Lock() - mset.unsubscribe(ackSub) - mset.unsubscribe(reqSub) - mset.deleteConsumer(o) - rp := mset.config.Retention - mset.mu.Unlock() + if delivery != _EMPTY_ { + a.sl.clearNotification(delivery, qgroup, o.inch) + } + + var rp RetentionPolicy + if mset != nil { + mset.mu.Lock() + mset.removeConsumer(o) + // No need for cfgMu's lock since mset.mu.Lock superseeds it. + rp = mset.cfg.Retention + mset.mu.Unlock() + } - // We need to optionally remove all messages since we are interest based retention. + // Cleanup messages that lost interest. if dflag && rp == InterestPolicy { - var seqs []uint64 - o.mu.Lock() - for seq := range o.pending { - seqs = append(seqs, seq) + o.cleanupNoInterestMessages(mset, true) + } + + // Cluster cleanup. + if n != nil { + if dflag { + n.Delete() + } else { + n.Stop() } - o.mu.Unlock() - // Sort just to keep pending sparse array state small. - sort.Slice(seqs, func(i, j int) bool { return seqs[i] < seqs[j] }) - for _, seq := range seqs { - mset.mu.Lock() - hasNoInterest := !mset.checkInterest(seq, o) - mset.mu.Unlock() - if hasNoInterest { - mset.store.RemoveMsg(seq) - } + } + + if ca != nil { + js.mu.Lock() + if ca.Group != nil { + ca.Group.node = nil } + js.mu.Unlock() } + // Clean up our store. var err error if store != nil { if dflag { - err = store.Delete() + if sdflag { + err = store.StreamDelete() + } else { + err = store.Delete() + } } else { err = store.Stop() } + } else if dflag { + // If there's no store (for example, when it's offline), manually delete the directories. + o.mu.RLock() + stream, consumer := o.stream, o.name + o.mu.RUnlock() + accDir := filepath.Join(js.config.StoreDir, a.GetName()) + consumersDir := filepath.Join(accDir, streamsDir, stream, consumerDir) + os.RemoveAll(filepath.Join(consumersDir, consumer)) } + return err } -// Check that we do not form a cycle by delivering to a delivery subject -// that is part of the interest group. -func (mset *Stream) deliveryFormsCycle(deliverySubject string) bool { - mset.mu.RLock() - defer mset.mu.RUnlock() +// We need to optionally remove all messages since we are interest based retention. +// We will do this consistently on all replicas. Note that if in clustered mode the non-leader +// consumers will need to restore state first. +// ignoreInterest marks whether the consumer should be ignored when determining interest. +// No lock held on entry. +func (o *consumer) cleanupNoInterestMessages(mset *stream, ignoreInterest bool) { + o.mu.Lock() + if !o.isLeader() { + o.readStoredState() + } + start := o.asflr + o.mu.Unlock() - for _, subject := range mset.config.Subjects { - if subjectIsSubsetMatch(deliverySubject, subject) { - return true - } + // Make sure we start at worst with first sequence in the stream. + state := mset.state() + if start < state.FirstSeq { + start = state.FirstSeq } - return false -} + stop := state.LastSeq -// This is same as check for delivery cycle. -func (mset *Stream) validSubject(partitionSubject string) bool { - return mset.deliveryFormsCycle(partitionSubject) -} + // Consumer's interests are ignored by default. If we should not ignore interest, unset. + co := o + if !ignoreInterest { + co = nil + } -// SetInActiveDeleteThreshold sets the delete threshold for how long to wait -// before deleting an inactive ephemeral observable. -func (o *Consumer) SetInActiveDeleteThreshold(dthresh time.Duration) error { - o.mu.Lock() - defer o.mu.Unlock() + var rmseqs []uint64 + mset.mu.RLock() - if o.isPullMode() { - return fmt.Errorf("consumer is not push-based") + // If over this amount of messages to check, optimistically call to checkInterestState(). + // It will not always do the right thing in removing messages that lost interest, but ensures + // we don't degrade performance by doing a linear scan through the whole stream. + // Messages might need to expire based on limits to be cleaned up. + // TODO(dlc) - Better way? + const bailThresh = 100_000 + + // Check if we would be spending too much time here and defer to separate go routine. + if len(mset.consumers) == 0 { + mset.mu.RUnlock() + mset.mu.Lock() + defer mset.mu.Unlock() + mset.store.Purge() + var state StreamState + mset.store.FastState(&state) + mset.lseq = state.LastSeq + // Also make sure we clear any pending acks. + mset.clearAllPreAcksBelowFloor(state.FirstSeq) + return + } else if stop-start > bailThresh { + mset.mu.RUnlock() + go mset.checkInterestState() + return } - if o.isDurable() { - return fmt.Errorf("consumer is not durable") + + mset.mu.RUnlock() + mset.mu.Lock() + for seq := start; seq <= stop; seq++ { + if mset.noInterest(seq, co) { + rmseqs = append(rmseqs, seq) + } } - deleteWasRunning := o.dtmr != nil - stopAndClearTimer(&o.dtmr) - o.dthresh = dthresh - if deleteWasRunning { - o.dtmr = time.AfterFunc(o.dthresh, func() { o.Delete() }) + mset.mu.Unlock() + + // These can be removed. + for _, seq := range rmseqs { + mset.store.RemoveMsg(seq) } - return nil +} + +// Check that we do not form a cycle by delivering to a delivery subject +// that is part of the interest group. +func deliveryFormsCycle(cfg *StreamConfig, deliverySubject string) bool { + for _, subject := range cfg.Subjects { + if subjectIsSubsetMatch(deliverySubject, subject) { + return true + } + } + return false } // switchToEphemeral is called on startup when recovering ephemerals. -func (o *Consumer) switchToEphemeral() { +func (o *consumer) switchToEphemeral() { o.mu.Lock() - o.config.Durable = _EMPTY_ + o.cfg.Durable = _EMPTY_ store, ok := o.store.(*consumerFileStore) - rr := o.acc.sl.Match(o.config.DeliverSubject) + interest := o.acc.sl.HasInterest(o.cfg.DeliverSubject) + // Setup dthresh. + o.updateInactiveThreshold(&o.cfg) + o.updatePauseState(&o.cfg) o.mu.Unlock() // Update interest - o.updateDeliveryInterest(len(rr.psubs)+len(rr.qsubs) > 0) + o.updateDeliveryInterest(interest) // Write out new config if ok { - store.updateConfig(o.config) + store.updateConfig(o.cfg) } } // RequestNextMsgSubject returns the subject to request the next message when in pull or worker mode. // Returns empty otherwise. -func (o *Consumer) RequestNextMsgSubject() string { +func (o *consumer) requestNextMsgSubject() string { return o.nextMsgSubj } -// Will set the initial pending. -// mset lock should be held. -func (o *Consumer) setInitialPending() { - mset := o.mset - if mset == nil { +func (o *consumer) decStreamPending(sseq uint64, subj string) { + o.mu.Lock() + + // Update our cached num pending only if we think deliverMsg has not done so. + if sseq >= o.sseq && o.isFilteredMatch(subj) { + o.npc-- + } + + // Check if this message was pending. + p, wasPending := o.pending[sseq] + var rdc uint64 + if wasPending { + rdc = o.deliveryCount(sseq) + } + + o.mu.Unlock() + + // If it was pending process it like an ack. + if wasPending { + // We could have the lock for the stream so do this in a go routine. + // TODO(dlc) - We should do this with ipq vs naked go routines. + go o.processTerm(sseq, p.Sequence, rdc, ackTermUnackedLimitsReason, _EMPTY_) + } +} + +func (o *consumer) account() *Account { + o.mu.RLock() + a := o.acc + o.mu.RUnlock() + return a +} + +// Creates a sublist for consumer. +// All subjects share the same callback. +func (o *consumer) signalSubs() []string { + o.mu.Lock() + defer o.mu.Unlock() + + if o.sigSubs != nil { + return o.sigSubs + } + + if len(o.subjf) == 0 { + subs := []string{fwcs} + o.sigSubs = subs + return subs + } + + subs := make([]string, 0, len(o.subjf)) + for _, filter := range o.subjf { + subs = append(subs, filter.subject) + } + o.sigSubs = subs + return subs +} + +// This is what will be called when our parent stream wants to kick us regarding a new message. +// We know that this subject matches us by how the parent handles registering us with the signaling sublist, +// but we must check if we are leader. +// We do need the sequence of the message however and we use the msg as the encoded seq. +func (o *consumer) processStreamSignal(seq uint64) { + // We can get called here now when not leader, so bail fast + // and without acquiring any locks. + if !o.leader.Load() { return } - // Non-filtering, means we want all messages. - if o.config.FilterSubject == _EMPTY_ { - state := mset.store.State() - if state.Msgs > 0 { - o.sgap = state.Msgs - (o.sseq - state.FirstSeq) - } - } else { - // Here we are filtered. - // FIXME(dlc) - This could be slow with O(n) - for seq := o.sseq; ; seq++ { - subj, _, _, _, err := o.mset.store.LoadMsg(seq) - if err == ErrStoreMsgNotFound { - continue - } else if err == ErrStoreEOF { - break - } else if err == nil && o.isFilteredMatch(subj) { - o.sgap++ - } + o.mu.Lock() + defer o.mu.Unlock() + if o.mset == nil { + return + } + if seq > o.npf { + o.npc++ + } + if seq < o.sseq { + return + } + if o.isPushMode() && o.active || o.isPullMode() && !o.waiting.isEmpty() { + o.signalNewMessages() + } +} + +// Used to compare if two multiple filtered subject lists are equal. +func subjectSliceEqual(slice1 []string, slice2 []string) bool { + if len(slice1) != len(slice2) { + return false + } + set2 := make(map[string]struct{}, len(slice2)) + for _, val := range slice2 { + set2[val] = struct{}{} + } + for _, val := range slice1 { + if _, ok := set2[val]; !ok { + return false } } + return true +} + +// Utility for simpler if conditions in Consumer config checks. +// In future iteration, we can immediately create `o.subjf` and +// use it to validate things. +func gatherSubjectFilters(filter string, filters []string) []string { + if filter != _EMPTY_ { + filters = append(filters, filter) + } + // list of filters should never contain non-empty filter. + return filters } -// addStreamPending will add to the stream pending. -func (o *Consumer) incStreamPending(sseq uint64, subj string) { +// shouldStartMonitor will return true if we should start a monitor +// goroutine or will return false if one is already running. +func (o *consumer) shouldStartMonitor() bool { o.mu.Lock() - if o.isFilteredMatch(subj) { - o.sgap++ + defer o.mu.Unlock() + + if o.inMonitor { + return false } - o.mu.Unlock() + o.monitorWg.Add(1) + o.inMonitor = true + return true +} + +// Clear the monitor running state. The monitor goroutine should +// call this in a defer to clean up on exit. +func (o *consumer) clearMonitorRunning() { + o.mu.Lock() + defer o.mu.Unlock() + + if o.inMonitor { + o.monitorWg.Done() + o.inMonitor = false + } +} + +// Test whether we are in the monitor routine. +func (o *consumer) isMonitorRunning() bool { + o.mu.RLock() + defer o.mu.RUnlock() + return o.inMonitor } -func (o *Consumer) decStreamPending(sseq uint64, subj string) { +// If we detect that our ackfloor is higher than the stream's last sequence, return this error. +var errAckFloorHigherThanLastSeq = errors.New("consumer ack floor is higher than streams last sequence") +var errAckFloorInvalid = errors.New("consumer ack floor is invalid") + +// If we are a consumer of an interest or workqueue policy stream, process that state and make sure consistent. +func (o *consumer) checkStateForInterestStream(ss *StreamState) error { + o.mu.RLock() + // See if we need to process this update if our parent stream is not a limits policy stream. + mset := o.mset + shouldProcessState := mset != nil && o.retention != LimitsPolicy + if o.closed || !shouldProcessState || o.store == nil || ss == nil { + o.mu.RUnlock() + return nil + } + store := mset.store + state, err := o.store.State() + + filters, subjf, filter := o.filters, o.subjf, _EMPTY_ + var wc bool + if filters == nil && subjf != nil { + filter, wc = subjf[0].subject, subjf[0].hasWildcard + } + chkfloor := o.chkflr + o.mu.RUnlock() + + if err != nil { + return err + } + + asflr := state.AckFloor.Stream + // Protect ourselves against rolling backwards. + if asflr&(1<<63) != 0 { + return errAckFloorInvalid + } + dflr := asflr + if len(state.Pending) > 0 && state.Delivered.Stream > dflr { + dflr = state.Delivered.Stream + } + + // Check if the underlying stream's last sequence is less than our floor. + // This can happen if the stream has been reset and has not caught up yet. + if asflr > ss.LastSeq { + return errAckFloorHigherThanLastSeq + } + + var smv StoreMsg + var seq, nseq uint64 + // Start at first stream seq or a previous check floor, whichever is higher. + // Note this will really help for interest retention, with WQ the loadNextMsg + // gets us a long way already since it will skip deleted msgs not for our filter. + fseq := ss.FirstSeq + if chkfloor > fseq { + fseq = chkfloor + } + + var retryAsflr uint64 + for seq = fseq; dflr > 0 && seq <= dflr; seq++ { + if filters != nil { + _, nseq, err = store.LoadNextMsgMulti(filters, seq, &smv) + } else { + _, nseq, err = store.LoadNextMsg(filter, wc, seq, &smv) + } + // if we advanced sequence update our seq. This can be on no error and EOF. + if nseq > seq { + seq = nseq + } + if err == nil { + // Only ack though if no error and seq <= ack floor. + if seq <= asflr { + didRemove := mset.ackMsg(o, seq) + // Removing the message could fail. For example if clustered since we need to propose it. + // Overwrite retry floor (only the first time) to allow us to check next time if the removal was successful. + if didRemove && retryAsflr == 0 { + retryAsflr = seq + } + } else if seq <= dflr { + // Store the first entry above our ack floor, so we don't need to look it up again on retryAsflr=0. + if retryAsflr == 0 { + retryAsflr = seq + } + // If we have pending, we will need to walk through to delivered in case we missed any of those acks as well. + if _, ok := state.Pending[seq]; !ok { + // The filters are already taken into account, + mset.ackMsg(o, seq) + } + } + } else if err == ErrStoreEOF { + break + } + } + // If retry floor was not overwritten, set to ack floor+1, we don't need to account for any retries below it. + // However, our ack floor may be lower than the next message we can receive, so we correct it upward if needed. + if retryAsflr == 0 { + if filters != nil { + _, nseq, err = store.LoadNextMsgMulti(filters, asflr+1, &smv) + } else { + _, nseq, err = store.LoadNextMsg(filter, wc, asflr+1, &smv) + } + if err == nil { + retryAsflr = max(asflr+1, nseq) + } else if err == ErrStoreEOF { + retryAsflr = ss.LastSeq + 1 + } + } + o.mu.Lock() - // Ignore if we have already seen this one. - if sseq >= o.sseq && o.sgap > 0 && o.isFilteredMatch(subj) { - o.sgap-- + // Update our check floor. + // Check floor must never be greater than ack floor+1, otherwise subsequent calls to this function would skip work. + if retryAsflr > o.chkflr { + o.chkflr = retryAsflr } o.mu.Unlock() + return nil +} + +func (o *consumer) resetPtmr(delay time.Duration) { + if o.ptmr == nil { + o.ptmr = time.AfterFunc(delay, o.checkPending) + } else { + o.ptmr.Reset(delay) + } + o.ptmrEnd = time.Now().Add(delay) +} + +func (o *consumer) stopAndClearPtmr() { + stopAndClearTimer(&o.ptmr) + o.ptmrEnd = time.Time{} +} + +func (o *consumer) resetPendingDeliveries() { + for _, pmsg := range o.pendingDeliveries { + pmsg.returnToPool() + } + o.pendingDeliveries = nil + for _, wd := range o.waitingDeliveries { + wd.recycle() + } + o.waitingDeliveries = nil } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go b/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go index 663aabe..6ef11be 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go @@ -1,18 +1,15 @@ -/* - * Copyright 2020 The NATS Authors - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ +// Copyright 2012-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package server @@ -23,7 +20,6 @@ import ( "crypto/sha256" "errors" "fmt" - "io/ioutil" "math" "os" "path/filepath" @@ -31,6 +27,8 @@ import ( "sync" "time" + "github.com/nats-io/nkeys" + "github.com/nats-io/jwt/v2" // only used to decode, not for storage ) @@ -40,27 +38,27 @@ const ( // validatePathExists checks that the provided path exists and is a dir if requested func validatePathExists(path string, dir bool) (string, error) { - if path == "" { - return "", errors.New("path is not specified") + if path == _EMPTY_ { + return _EMPTY_, errors.New("path is not specified") } abs, err := filepath.Abs(path) if err != nil { - return "", fmt.Errorf("error parsing path [%s]: %v", abs, err) + return _EMPTY_, fmt.Errorf("error parsing path [%s]: %v", abs, err) } var finfo os.FileInfo if finfo, err = os.Stat(abs); os.IsNotExist(err) { - return "", fmt.Errorf("the path [%s] doesn't exist", abs) + return _EMPTY_, fmt.Errorf("the path [%s] doesn't exist", abs) } mode := finfo.Mode() if dir && mode.IsRegular() { - return "", fmt.Errorf("the path [%s] is not a directory", abs) + return _EMPTY_, fmt.Errorf("the path [%s] is not a directory", abs) } if !dir && mode.IsDir() { - return "", fmt.Errorf("the path [%s] is not a file", abs) + return _EMPTY_, fmt.Errorf("the path [%s] is not a file", abs) } return abs, nil @@ -82,29 +80,30 @@ type DirJWTStore struct { shard bool readonly bool deleteType deleteType - operator string + operator map[string]struct{} expiration *expirationTracker changed JWTChanged + deleted JWTChanged } func newDir(dirPath string, create bool) (string, error) { fullPath, err := validateDirPath(dirPath) if err != nil { if !create { - return "", err + return _EMPTY_, err } - if err = os.MkdirAll(dirPath, 0755); err != nil { - return "", err + if err = os.MkdirAll(dirPath, defaultDirPerms); err != nil { + return _EMPTY_, err } if fullPath, err = validateDirPath(dirPath); err != nil { - return "", err + return _EMPTY_, err } } return fullPath, nil } // future proofing in case new options will be added -type dirJWTStoreOption interface{} +type dirJWTStoreOption any // Creates a directory based jwt store. // Reads files only, does NOT watch directories and files. @@ -146,8 +145,8 @@ const ( // // limit defines how many files are allowed at any given time. Set to math.MaxInt64 to disable. // evictOnLimit determines the behavior once limit is reached. -// true - Evict based on lru strategy -// false - return an error +// * true - Evict based on lru strategy +// * false - return an error func NewExpiringDirJWTStore(dirPath string, shard bool, create bool, delete deleteType, expireCheck time.Duration, limit int64, evictOnLimit bool, ttl time.Duration, changeNotification JWTChanged, _ ...dirJWTStoreOption) (*DirJWTStore, error) { fullPath, err := newDir(dirPath, create) @@ -175,7 +174,7 @@ func NewExpiringDirJWTStore(dirPath string, shard bool, create bool, delete dele theStore.Lock() err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { if strings.HasSuffix(path, fileExtension) { - if theJwt, err := ioutil.ReadFile(path); err == nil { + if theJwt, err := os.ReadFile(path); err == nil { hash := sha256.Sum256(theJwt) _, file := filepath.Split(path) theStore.expiration.track(strings.TrimSuffix(file, fileExtension), &hash, string(theJwt)) @@ -241,7 +240,7 @@ func (store *DirJWTStore) Pack(maxJWTs int) (string, error) { return nil // only include indexed files } } - jwtBytes, err := ioutil.ReadFile(path) + jwtBytes, err := os.ReadFile(path) if err != nil { return err } @@ -258,7 +257,7 @@ func (store *DirJWTStore) Pack(maxJWTs int) (string, error) { }) store.Unlock() if err != nil { - return "", err + return _EMPTY_, err } else { return strings.Join(pack, "\n"), nil } @@ -285,10 +284,14 @@ func (store *DirJWTStore) PackWalk(maxJWTs int, cb func(partialPackMsg string)) } } store.Unlock() - jwtBytes, err := ioutil.ReadFile(path) + jwtBytes, err := os.ReadFile(path) if err != nil { return err } + if len(jwtBytes) == 0 { + // Skip if no contents in the JWT. + return nil + } if exp != nil { claim, err := jwt.DecodeGeneric(string(jwtBytes)) if err == nil && claim.Expires > 0 && claim.Expires < time.Now().Unix() { @@ -315,7 +318,7 @@ func (store *DirJWTStore) PackWalk(maxJWTs int, cb func(partialPackMsg string)) func (store *DirJWTStore) Merge(pack string) error { newJWTs := strings.Split(pack, "\n") for _, line := range newJWTs { - if line == "" { // ignore blank lines + if line == _EMPTY_ { // ignore blank lines continue } split := strings.Split(line, "|") @@ -323,6 +326,9 @@ func (store *DirJWTStore) Merge(pack string) error { return fmt.Errorf("line in package didn't contain 2 entries: %q", line) } pubKey := split[0] + if !nkeys.IsValidPublicAccountKey(pubKey) { + return fmt.Errorf("key to merge is not a valid public account key") + } if err := store.saveIfNewer(pubKey, split[1]); err != nil { return err } @@ -348,7 +354,7 @@ func (store *DirJWTStore) Reload() error { store.Unlock() return filepath.Walk(store.directory, func(path string, info os.FileInfo, err error) error { if strings.HasSuffix(path, fileExtension) { - if theJwt, err := ioutil.ReadFile(path); err == nil { + if theJwt, err := os.ReadFile(path); err == nil { hash := sha256.Sum256(theJwt) _, file := filepath.Split(path) pkey := strings.TrimSuffix(file, fileExtension) @@ -370,7 +376,10 @@ func (store *DirJWTStore) Reload() error { func (store *DirJWTStore) pathForKey(publicKey string) string { if len(publicKey) < 2 { - return "" + return _EMPTY_ + } + if !nkeys.IsValidPublicKey(publicKey) { + return _EMPTY_ } fileName := fmt.Sprintf("%s%s", publicKey, fileExtension) if store.shard { @@ -386,10 +395,10 @@ func (store *DirJWTStore) pathForKey(publicKey string) string { func (store *DirJWTStore) load(publicKey string) (string, error) { store.Lock() defer store.Unlock() - if path := store.pathForKey(publicKey); path == "" { - return "", fmt.Errorf("invalid public key") - } else if data, err := ioutil.ReadFile(path); err != nil { - return "", err + if path := store.pathForKey(publicKey); path == _EMPTY_ { + return _EMPTY_, fmt.Errorf("invalid public key") + } else if data, err := os.ReadFile(path); err != nil { + return _EMPTY_, err } else { if store.expiration != nil { store.expiration.updateTrack(publicKey) @@ -401,6 +410,9 @@ func (store *DirJWTStore) load(publicKey string) (string, error) { // write that keeps hash of all jwt in sync // Assumes the lock is held. Does return true or an error never both. func (store *DirJWTStore) write(path string, publicKey string, theJWT string) (bool, error) { + if len(theJWT) == 0 { + return false, fmt.Errorf("invalid JWT") + } var newHash *[sha256.Size]byte if store.expiration != nil { h := sha256.Sum256([]byte(theJWT)) @@ -426,7 +438,7 @@ func (store *DirJWTStore) write(path string, publicKey string, theJWT string) (b } } } - if err := ioutil.WriteFile(path, []byte(theJWT), 0644); err != nil { + if err := os.WriteFile(path, []byte(theJWT), defaultFilePerms); err != nil { return false, err } else if store.expiration != nil { store.expiration.track(publicKey, newHash, theJWT) @@ -457,7 +469,7 @@ func (store *DirJWTStore) delete(publicKey string) error { return err } store.expiration.unTrack(publicKey) - // TODO do cb so server can evict the account and associated clients + store.deleted(publicKey) return nil } @@ -469,13 +481,13 @@ func (store *DirJWTStore) save(publicKey string, theJWT string) error { } store.Lock() path := store.pathForKey(publicKey) - if path == "" { + if path == _EMPTY_ { store.Unlock() return fmt.Errorf("invalid public key") } dirPath := filepath.Dir(path) if _, err := validateDirPath(dirPath); err != nil { - if err := os.MkdirAll(dirPath, 0755); err != nil { + if err := os.MkdirAll(dirPath, defaultDirPerms); err != nil { store.Unlock() return err } @@ -490,25 +502,25 @@ func (store *DirJWTStore) save(publicKey string, theJWT string) error { } // Assumes the lock is NOT held, and only updates if the jwt is new, or the one on disk is older -// returns true when the jwt changed +// When changed, invokes jwt changed callback func (store *DirJWTStore) saveIfNewer(publicKey string, theJWT string) error { if store.readonly { return fmt.Errorf("store is read-only") } path := store.pathForKey(publicKey) - if path == "" { + if path == _EMPTY_ { return fmt.Errorf("invalid public key") } dirPath := filepath.Dir(path) if _, err := validateDirPath(dirPath); err != nil { - if err := os.MkdirAll(dirPath, 0755); err != nil { + if err := os.MkdirAll(dirPath, defaultDirPerms); err != nil { return err } } if _, err := os.Stat(path); err == nil { if newJWT, err := jwt.DecodeGeneric(theJWT); err != nil { - // skip if it can't be decoded - } else if existing, err := ioutil.ReadFile(path); err != nil { + return err + } else if existing, err := os.ReadFile(path); err != nil { return err } else if existingJWT, err := jwt.DecodeGeneric(string(existing)); err != nil { // skip if it can't be decoded @@ -516,6 +528,10 @@ func (store *DirJWTStore) saveIfNewer(publicKey string, theJWT string) error { return nil } else if existingJWT.IssuedAt > newJWT.IssuedAt { return nil + } else if newJWT.Subject != publicKey { + return fmt.Errorf("jwt subject nkey and provided nkey do not match") + } else if existingJWT.Subject != newJWT.Subject { + return fmt.Errorf("subject of existing and new jwt do not match") } } store.Lock() @@ -568,7 +584,7 @@ type expirationTracker struct { wg sync.WaitGroup } -func (pq *expirationTracker) Len() int { return len(pq.heap) } +func (q *expirationTracker) Len() int { return len(q.heap) } func (q *expirationTracker) Less(i, j int) bool { pq := q.heap @@ -582,7 +598,7 @@ func (q *expirationTracker) Swap(i, j int) { pq[j].index = j } -func (q *expirationTracker) Push(x interface{}) { +func (q *expirationTracker) Push(x any) { n := len(q.heap) item := x.(*jwtItem) item.index = n @@ -590,7 +606,7 @@ func (q *expirationTracker) Push(x interface{}) { q.idx[item.publicKey] = q.lru.PushBack(item) } -func (q *expirationTracker) Pop() interface{} { +func (q *expirationTracker) Pop() any { old := q.heap n := len(old) item := old[n-1] @@ -607,7 +623,7 @@ func (pq *expirationTracker) updateTrack(publicKey string) { i := e.Value.(*jwtItem) if pq.ttl != 0 { // only update expiration when set - i.expiration = time.Now().Round(time.Second).Add(pq.ttl).Unix() + i.expiration = time.Now().Add(pq.ttl).UnixNano() heap.Fix(pq, i.index) } if pq.evictOnLimit { @@ -631,11 +647,11 @@ func (pq *expirationTracker) track(publicKey string, hash *[sha256.Size]byte, th if pq.ttl == time.Duration(math.MaxInt64) { exp = math.MaxInt64 } else { - exp = time.Now().Round(time.Second).Add(pq.ttl).Unix() + exp = time.Now().Add(pq.ttl).UnixNano() } } else { if g, err := jwt.DecodeGeneric(theJWT); err == nil { - exp = g.Expires + exp = time.Unix(g.Expires, 0).UnixNano() } if exp == 0 { exp = math.MaxInt64 // default to indefinite @@ -683,10 +699,10 @@ func (store *DirJWTStore) startExpiring(reCheck time.Duration, limit int64, evic defer t.Stop() defer pq.wg.Done() for { - now := time.Now() + now := time.Now().UnixNano() store.Lock() if pq.Len() > 0 { - if it := pq.heap[0]; it.expiration <= now.Unix() { + if it := pq.heap[0]; it.expiration <= now { path := store.pathForKey(it.publicKey) if err := os.Remove(path); err == nil { heap.Pop(pq) diff --git a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail.go b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail.go index 8abe3e4..e27c1a7 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2020-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +//go:build !windows && !openbsd && !netbsd && !wasm && !illumos && !solaris package server @@ -23,7 +23,7 @@ import ( func diskAvailable(storeDir string) int64 { var ba int64 if _, err := os.Stat(storeDir); os.IsNotExist(err) { - os.MkdirAll(storeDir, 0755) + os.MkdirAll(storeDir, defaultDirPerms) } var fs syscall.Statfs_t if err := syscall.Statfs(storeDir, &fs); err == nil { diff --git a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_netbsd.go b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_netbsd.go new file mode 100644 index 0000000..dd81a1b --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_netbsd.go @@ -0,0 +1,21 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build netbsd + +package server + +// TODO - See if there is a version of this for NetBSD. +func diskAvailable(storeDir string) int64 { + return JetStreamMaxStoreDefault +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_openbsd.go b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_openbsd.go new file mode 100644 index 0000000..8ffdf12 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_openbsd.go @@ -0,0 +1,37 @@ +// Copyright 2021-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build openbsd + +package server + +import ( + "os" + "syscall" +) + +func diskAvailable(storeDir string) int64 { + var ba int64 + if _, err := os.Stat(storeDir); os.IsNotExist(err) { + os.MkdirAll(storeDir, defaultDirPerms) + } + var fs syscall.Statfs_t + if err := syscall.Statfs(storeDir, &fs); err == nil { + // Estimate 75% of available storage. + ba = int64(uint64(fs.F_bavail) * uint64(fs.F_bsize) / 4 * 3) + } else { + // Used 1TB default as a guess if all else fails. + ba = JetStreamMaxStoreDefault + } + return ba +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_solaris.go b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_solaris.go new file mode 100644 index 0000000..e0febd1 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_solaris.go @@ -0,0 +1,38 @@ +// Copyright 2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build illumos || solaris + +package server + +import ( + "os" + "golang.org/x/sys/unix" +) + +func diskAvailable(storeDir string) int64 { + var ba int64 + if _, err := os.Stat(storeDir); os.IsNotExist(err) { + os.MkdirAll(storeDir, defaultDirPerms) + } + var fs unix.Statvfs_t + if err := unix.Statvfs(storeDir, &fs); err == nil { + // Estimate 75% of available storage. + ba = int64(uint64(fs.Frsize) * uint64(fs.Bavail) / 4 * 3) + } else { + // Used 1TB default as a guess if all else fails. + ba = JetStreamMaxStoreDefault + } + return ba +} + diff --git a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_wasm.go b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_wasm.go new file mode 100644 index 0000000..1946870 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_wasm.go @@ -0,0 +1,20 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build wasm + +package server + +func diskAvailable(storeDir string) int64 { + return JetStreamMaxStoreDefault +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_windows.go index 0e05708..c79c506 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_windows.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/disk_avail_windows.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2020-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build windows +//go:build windows package server diff --git a/vendor/github.com/nats-io/nats-server/v2/server/errors.go b/vendor/github.com/nats-io/nats-server/v2/server/errors.go index 3610352..1a83abc 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/errors.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/errors.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -60,10 +60,16 @@ var ( // connections. ErrTooManyAccountConnections = errors.New("maximum account active connections exceeded") + // ErrLeafNodeLoop signals a leafnode is trying to register for a cluster we already have registered. + ErrLeafNodeLoop = errors.New("leafnode loop detected") + // ErrTooManySubs signals a client that the maximum number of subscriptions per connection // has been reached. ErrTooManySubs = errors.New("maximum subscriptions exceeded") + // ErrTooManySubTokens signals a client that the subject has too many tokens. + ErrTooManySubTokens = errors.New("subject has exceeded number of tokens limit") + // ErrClientConnectedToRoutePort represents an error condition when a client // attempted to connect to the route listen port. ErrClientConnectedToRoutePort = errors.New("attempted to connect to route port") @@ -72,6 +78,13 @@ var ( // attempted to connect to the leaf node listen port. ErrClientConnectedToLeafNodePort = errors.New("attempted to connect to leaf node port") + // ErrLeafNodeHasSameClusterName represents an error condition when a leafnode is a cluster + // and it has the same cluster name as the hub cluster. + ErrLeafNodeHasSameClusterName = errors.New("remote leafnode has same cluster name") + + // ErrLeafNodeDisabled is when we disable leafnodes. + ErrLeafNodeDisabled = errors.New("leafnodes disabled") + // ErrConnectedToWrongPort represents an error condition when a connection is attempted // to the wrong listen port (for instance a LeafNode to a client port, etc...) ErrConnectedToWrongPort = errors.New("attempted to connect to wrong port") @@ -140,6 +153,9 @@ var ( // Gateway's name. ErrWrongGateway = errors.New("wrong gateway") + // ErrGatewayNameHasSpaces signals that the gateway name contains spaces, which is not allowed. + ErrGatewayNameHasSpaces = errors.New("gateway name cannot contain spaces") + // ErrNoSysAccount is returned when an attempt to publish or subscribe is made // when there is no internal system account defined. ErrNoSysAccount = errors.New("system account not setup") @@ -150,6 +166,9 @@ var ( // ErrServerNotRunning is used to signal an error that a server is not running. ErrServerNotRunning = errors.New("server is not running") + // ErrServerNameHasSpaces signals that the server name contains spaces, which is not allowed. + ErrServerNameHasSpaces = errors.New("server name cannot contain spaces") + // ErrBadMsgHeader signals the parser detected a bad message header ErrBadMsgHeader = errors.New("bad message header detected") @@ -167,25 +186,70 @@ var ( // ErrClusterNameRemoteConflict signals that a remote server has a different cluster name. ErrClusterNameRemoteConflict = errors.New("cluster name from remote server conflicts") + // ErrClusterNameHasSpaces signals that the cluster name contains spaces, which is not allowed. + ErrClusterNameHasSpaces = errors.New("cluster name cannot contain spaces") + // ErrMalformedSubject is returned when a subscription is made with a subject that does not conform to subject rules. ErrMalformedSubject = errors.New("malformed subject") // ErrSubscribePermissionViolation is returned when processing of a subscription fails due to permissions. - ErrSubscribePermissionViolation = errors.New("subscribe permission viloation") + ErrSubscribePermissionViolation = errors.New("subscribe permission violation") // ErrNoTransforms signals no subject transforms are available to map this subject. ErrNoTransforms = errors.New("no matching transforms available") - // ErrJetStreamNotEnabled is returned when JetStream is not enabled. - ErrJetStreamNotEnabled = errors.New("jetstream not enabled") + // ErrCertNotPinned is returned when pinned certs are set and the certificate is not in it + ErrCertNotPinned = errors.New("certificate not pinned") + + // ErrDuplicateServerName is returned when processing a server remote connection and + // the server reports that this server name is already used in the cluster. + ErrDuplicateServerName = errors.New("duplicate server name") + + // ErrMinimumVersionRequired is returned when a connection is not at the minimum version required. + ErrMinimumVersionRequired = errors.New("minimum version required") + + // ErrInvalidMappingDestination is used for all subject mapping destination errors + ErrInvalidMappingDestination = errors.New("invalid mapping destination") + + // ErrInvalidMappingDestinationSubject is used to error on a bad transform destination mapping + ErrInvalidMappingDestinationSubject = fmt.Errorf("%w: invalid transform", ErrInvalidMappingDestination) - // ErrJetStreamStreamNotFound is returned when a stream can not be found. - ErrJetStreamStreamNotFound = errors.New("stream not found") + // ErrMappingDestinationNotUsingAllWildcards is used to error on a transform destination not using all of the token wildcards + ErrMappingDestinationNotUsingAllWildcards = fmt.Errorf("%w: not using all of the token wildcard(s)", ErrInvalidMappingDestination) - // ErrJetStreamNotEnabledForAccount is returned JetStream is not enabled for this account. - ErrJetStreamNotEnabledForAccount = errors.New("jetstream not enabled for account") + // ErrUnknownMappingDestinationFunction is returned when a subject mapping destination contains an unknown mustache-escaped mapping function. + ErrUnknownMappingDestinationFunction = fmt.Errorf("%w: unknown function", ErrInvalidMappingDestination) + + // ErrMappingDestinationIndexOutOfRange is returned when the mapping destination function is passed an out of range wildcard index value for one of it's arguments + ErrMappingDestinationIndexOutOfRange = fmt.Errorf("%w: wildcard index out of range", ErrInvalidMappingDestination) + + // ErrMappingDestinationNotEnoughArgs is returned when the mapping destination function is not passed enough arguments + ErrMappingDestinationNotEnoughArgs = fmt.Errorf("%w: not enough arguments passed to the function", ErrInvalidMappingDestination) + + // ErrMappingDestinationInvalidArg is returned when the mapping destination function is passed and invalid argument + ErrMappingDestinationInvalidArg = fmt.Errorf("%w: function argument is invalid or in the wrong format", ErrInvalidMappingDestination) + + // ErrMappingDestinationTooManyArgs is returned when the mapping destination function is passed too many arguments + ErrMappingDestinationTooManyArgs = fmt.Errorf("%w: too many arguments passed to the function", ErrInvalidMappingDestination) + + // ErrMappingDestinationNotSupportedForImport is returned when you try to use a mapping function other than wildcard in a transform that needs to be reversible (i.e. an import) + ErrMappingDestinationNotSupportedForImport = fmt.Errorf("%w: the only mapping function allowed for import transforms is {{Wildcard()}}", ErrInvalidMappingDestination) ) +// mappingDestinationErr is a type of subject mapping destination error +type mappingDestinationErr struct { + token string + err error +} + +func (e *mappingDestinationErr) Error() string { + return fmt.Sprintf("%s in %s", e.err, e.token) +} + +func (e *mappingDestinationErr) Is(target error) bool { + return target == ErrInvalidMappingDestination +} + // configErr is a configuration error. type configErr struct { token token @@ -263,11 +327,11 @@ type errCtx struct { ctx string } -func NewErrorCtx(err error, format string, args ...interface{}) error { +func NewErrorCtx(err error, format string, args ...any) error { return &errCtx{err, fmt.Sprintf(format, args...)} } -// implement to work with errors.Is and errors.As +// Unwrap implement to work with errors.Is and errors.As func (e *errCtx) Unwrap() error { if e == nil { return nil @@ -283,7 +347,7 @@ func (e *errCtx) Context() string { return e.ctx } -// Return Error or, if type is right error and context +// UnpackIfErrorCtx return Error or, if type is right error and context func UnpackIfErrorCtx(err error) string { if e, ok := err.(*errCtx); ok { if _, ok := e.error.(*errCtx); ok { @@ -306,7 +370,7 @@ func errorsUnwrap(err error) error { return u.Unwrap() } -// implements: go 1.13 errors.Is(err, target error) bool +// ErrorIs implements: go 1.13 errors.Is(err, target error) bool // TODO replace with native code once we no longer support go1.12 func ErrorIs(err, target error) bool { // this is an outright copy of go 1.13 errors.Is(err, target error) bool diff --git a/vendor/github.com/nats-io/nats-server/v2/server/errors.json b/vendor/github.com/nats-io/nats-server/v2/server/errors.json new file mode 100644 index 0000000..8b398f2 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/errors.json @@ -0,0 +1,1702 @@ +[ + { + "constant": "JSClusterPeerNotMemberErr", + "code": 400, + "error_code": 10040, + "description": "peer not a member", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerEphemeralWithDurableInSubjectErr", + "code": 400, + "error_code": 10019, + "description": "consumer expected to be ephemeral but detected a durable name set in subject", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamExternalDelPrefixOverlapsErrF", + "code": 400, + "error_code": 10022, + "description": "stream external delivery prefix {prefix} overlaps with stream subject {subject}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSAccountResourcesExceededErr", + "code": 400, + "error_code": 10002, + "description": "resource limits exceeded for account", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterNotAvailErr", + "code": 503, + "error_code": 10008, + "description": "JetStream system temporarily unavailable", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamSubjectOverlapErr", + "code": 400, + "error_code": 10065, + "description": "subjects overlap with an existing stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamWrongLastSequenceErrF", + "code": 400, + "error_code": 10071, + "description": "wrong last sequence: {seq}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSTemplateNameNotMatchSubjectErr", + "code": 400, + "error_code": 10073, + "description": "template name in subject does not match request", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterNoPeersErrF", + "code": 400, + "error_code": 10005, + "description": "{err}", + "comment": "Error causing no peers to be available", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerEphemeralWithDurableNameErr", + "code": 400, + "error_code": 10020, + "description": "consumer expected to be ephemeral but a durable name was set in request", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSInsufficientResourcesErr", + "code": 503, + "error_code": 10023, + "description": "insufficient resources", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamResourcesExceeded" + }, + { + "constant": "JSMirrorMaxMessageSizeTooBigErr", + "code": 400, + "error_code": 10030, + "description": "stream mirror must have max message size \u003e= source", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamTemplateDeleteErrF", + "code": 500, + "error_code": 10067, + "description": "{err}", + "comment": "Generic stream template deletion failed error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSBadRequestErr", + "code": 400, + "error_code": 10003, + "description": "bad request", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterUnSupportFeatureErr", + "code": 503, + "error_code": 10036, + "description": "not currently supported in clustered mode", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerNotFoundErr", + "code": 404, + "error_code": 10014, + "description": "consumer not found", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceMaxMessageSizeTooBigErr", + "code": 400, + "error_code": 10046, + "description": "stream source must have max message size \u003e= target", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamAssignmentErrF", + "code": 500, + "error_code": 10048, + "description": "{err}", + "comment": "Generic stream assignment error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMessageExceedsMaximumErr", + "code": 400, + "error_code": 10054, + "description": "message size exceeds maximum allowed", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamTemplateCreateErrF", + "code": 500, + "error_code": 10066, + "description": "{err}", + "comment": "Generic template creation failed string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSInvalidJSONErr", + "code": 400, + "error_code": 10025, + "description": "invalid JSON: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamInvalidExternalDeliverySubjErrF", + "code": 400, + "error_code": 10024, + "description": "stream external delivery prefix {prefix} must not contain wildcards", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamRestoreErrF", + "code": 500, + "error_code": 10062, + "description": "restore failed: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterIncompleteErr", + "code": 503, + "error_code": 10004, + "description": "incomplete results", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSNoAccountErr", + "code": 503, + "error_code": 10035, + "description": "account not found", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSRaftGeneralErrF", + "code": 500, + "error_code": 10041, + "description": "{err}", + "comment": "General RAFT error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSRestoreSubscribeFailedErrF", + "code": 500, + "error_code": 10042, + "description": "JetStream unable to subscribe to restore snapshot {subject}: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamDeleteErrF", + "code": 500, + "error_code": 10050, + "description": "{err}", + "comment": "General stream deletion error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamExternalApiOverlapErrF", + "code": 400, + "error_code": 10021, + "description": "stream external api prefix {prefix} must not overlap with {subject}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorWithSubjectsErr", + "code": 400, + "error_code": 10034, + "description": "stream mirrors can not contain subjects", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorWithFirstSeqErr", + "code": 400, + "error_code": 10143, + "description": "stream mirrors can not have first sequence configured", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSNotEnabledErr", + "code": 503, + "error_code": 10076, + "description": "JetStream not enabled", + "comment": "", + "help": "This error indicates that JetStream is not enabled at a global level", + "url": "", + "deprecates": "ErrJetStreamNotEnabled" + }, + { + "constant": "JSNotEnabledForAccountErr", + "code": 503, + "error_code": 10039, + "description": "JetStream not enabled for account", + "comment": "", + "help": "This error indicates that JetStream is not enabled for an account account level", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSequenceNotFoundErrF", + "code": 400, + "error_code": 10043, + "description": "sequence {seq} not found", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMirrorNotUpdatableErr", + "code": 400, + "error_code": 10055, + "description": "stream mirror configuration can not be updated", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamSequenceNotMatchErr", + "code": 503, + "error_code": 10063, + "description": "expected stream sequence does not match", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamWrongLastMsgIDErrF", + "code": 400, + "error_code": 10070, + "description": "wrong last msg ID: {id}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSTempStorageFailedErr", + "code": 500, + "error_code": 10072, + "description": "JetStream unable to open temp storage for restore", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStorageResourcesExceededErr", + "code": 500, + "error_code": 10047, + "description": "insufficient storage resources available", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrStorageResourcesExceeded" + }, + { + "constant": "JSStreamMismatchErr", + "code": 400, + "error_code": 10056, + "description": "stream name in subject does not match request", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamNotMatchErr", + "code": 400, + "error_code": 10060, + "description": "expected stream does not match", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorConsumerSetupFailedErrF", + "code": 500, + "error_code": 10029, + "description": "{err}", + "comment": "generic mirror consumer setup failure string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSNotEmptyRequestErr", + "code": 400, + "error_code": 10038, + "description": "expected an empty request payload", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamNameExistErr", + "code": 400, + "error_code": 10058, + "description": "stream name already in use with a different configuration", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamStreamAlreadyUsed" + }, + { + "constant": "JSClusterTagsErr", + "code": 400, + "error_code": 10011, + "description": "tags placement not supported for operation", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMaximumConsumersLimitErr", + "code": 400, + "error_code": 10026, + "description": "maximum consumers limit reached", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceConsumerSetupFailedErrF", + "code": 500, + "error_code": 10045, + "description": "{err}", + "comment": "General source consumer setup failure string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerCreateErrF", + "code": 500, + "error_code": 10012, + "description": "{err}", + "comment": "General consumer creation failure string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDurableNameNotInSubjectErr", + "code": 400, + "error_code": 10016, + "description": "consumer expected to be durable but no durable name set in subject", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamLimitsErrF", + "code": 500, + "error_code": 10053, + "description": "{err}", + "comment": "General stream limits exceeded error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamReplicasNotUpdatableErr", + "code": 400, + "error_code": 10061, + "description": "Replicas configuration can not be updated", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamTemplateNotFoundErr", + "code": 404, + "error_code": 10068, + "description": "template not found", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterNotAssignedErr", + "code": 500, + "error_code": 10007, + "description": "JetStream cluster not assigned to this server", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamNotAssigned" + }, + { + "constant": "JSClusterNotLeaderErr", + "code": 500, + "error_code": 10009, + "description": "JetStream cluster can not handle request", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamNotLeader" + }, + { + "constant": "JSConsumerNameExistErr", + "code": 400, + "error_code": 10013, + "description": "consumer name already in use", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamConsumerAlreadyUsed" + }, + { + "constant": "JSMirrorWithSourcesErr", + "code": 400, + "error_code": 10031, + "description": "stream mirrors can not also contain other sources", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamNotFoundErr", + "code": 404, + "error_code": 10059, + "description": "stream not found", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamStreamNotFound" + }, + { + "constant": "JSClusterRequiredErr", + "code": 503, + "error_code": 10010, + "description": "JetStream clustering support required", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDurableNameNotSetErr", + "code": 400, + "error_code": 10018, + "description": "consumer expected to be durable but a durable name was not set", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMaximumStreamsLimitErr", + "code": 400, + "error_code": 10027, + "description": "maximum number of streams reached", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorWithStartSeqAndTimeErr", + "code": 400, + "error_code": 10032, + "description": "stream mirrors can not have both start seq and start time configured", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamSnapshotErrF", + "code": 500, + "error_code": 10064, + "description": "snapshot failed: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamUpdateErrF", + "code": 500, + "error_code": 10069, + "description": "{err}", + "comment": "Generic stream update error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterNotActiveErr", + "code": 500, + "error_code": 10006, + "description": "JetStream not in clustered mode", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrJetStreamNotClustered" + }, + { + "constant": "JSConsumerDurableNameNotMatchSubjectErr", + "code": 400, + "error_code": 10017, + "description": "consumer name in subject does not match durable name in request", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMemoryResourcesExceededErr", + "code": 500, + "error_code": 10028, + "description": "insufficient memory resources available", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrMemoryResourcesExceeded" + }, + { + "constant": "JSMirrorWithSubjectFiltersErr", + "code": 400, + "error_code": 10033, + "description": "stream mirrors can not contain filtered subjects", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamCreateErrF", + "code": 500, + "error_code": 10049, + "description": "{err}", + "comment": "Generic stream creation error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterServerNotMemberErr", + "code": 400, + "error_code": 10044, + "description": "server is not a member of the cluster", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSNoMessageFoundErr", + "code": 404, + "error_code": 10037, + "description": "no message found", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSnapshotDeliverSubjectInvalidErr", + "code": 400, + "error_code": 10015, + "description": "deliver subject not valid", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamGeneralErrorF", + "code": 500, + "error_code": 10051, + "description": "{err}", + "comment": "General stream failure string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamInvalidConfigF", + "code": 500, + "error_code": 10052, + "description": "{err}", + "comment": "Stream configuration validation error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamReplicasNotSupportedErr", + "code": 500, + "error_code": 10074, + "description": "replicas \u003e 1 not supported in non-clustered mode", + "comment": "", + "help": "", + "url": "", + "deprecates": "ErrReplicasNotSupported" + }, + { + "constant": "JSStreamMsgDeleteFailedF", + "code": 500, + "error_code": 10057, + "description": "{err}", + "comment": "Generic message deletion failure error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSPeerRemapErr", + "code": 503, + "error_code": 10075, + "description": "peer remap failed", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamStoreFailedF", + "code": 503, + "error_code": 10077, + "description": "{err}", + "comment": "Generic error when storing a message failed", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerConfigRequiredErr", + "code": 400, + "error_code": 10078, + "description": "consumer config required", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDeliverToWildcardsErr", + "code": 400, + "error_code": 10079, + "description": "consumer deliver subject has wildcards", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerPushMaxWaitingErr", + "code": 400, + "error_code": 10080, + "description": "consumer in push mode can not set max waiting", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDeliverCycleErr", + "code": 400, + "error_code": 10081, + "description": "consumer deliver subject forms a cycle", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxPendingAckPolicyRequiredErr", + "code": 400, + "error_code": 10082, + "description": "consumer requires ack policy for max ack pending", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerSmallHeartbeatErr", + "code": 400, + "error_code": 10083, + "description": "consumer idle heartbeat needs to be \u003e= 100ms", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerPullRequiresAckErr", + "code": 400, + "error_code": 10084, + "description": "consumer in pull mode requires explicit ack policy on workqueue stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerPullNotDurableErr", + "code": 400, + "error_code": 10085, + "description": "consumer in pull mode requires a durable name", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerPullWithRateLimitErr", + "code": 400, + "error_code": 10086, + "description": "consumer in pull mode can not have rate limit set", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxWaitingNegativeErr", + "code": 400, + "error_code": 10087, + "description": "consumer max waiting needs to be positive", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerHBRequiresPushErr", + "code": 400, + "error_code": 10088, + "description": "consumer idle heartbeat requires a push based consumer", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerFCRequiresPushErr", + "code": 400, + "error_code": 10089, + "description": "consumer flow control requires a push based consumer", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDirectRequiresPushErr", + "code": 400, + "error_code": 10090, + "description": "consumer direct requires a push based consumer", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDirectRequiresEphemeralErr", + "code": 400, + "error_code": 10091, + "description": "consumer direct requires an ephemeral consumer", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerOnMappedErr", + "code": 400, + "error_code": 10092, + "description": "consumer direct on a mapped consumer", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerFilterNotSubsetErr", + "code": 400, + "error_code": 10093, + "description": "consumer filter subject is not a valid subset of the interest subjects", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerInvalidPolicyErrF", + "code": 400, + "error_code": 10094, + "description": "{err}", + "comment": "Generic delivery policy error", + "help": "Error returned for impossible deliver policies when combined with start sequences etc", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerInvalidSamplingErrF", + "code": 400, + "error_code": 10095, + "description": "failed to parse consumer sampling configuration: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamInvalidErr", + "code": 500, + "error_code": 10096, + "description": "stream not valid", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerWQRequiresExplicitAckErr", + "code": 400, + "error_code": 10098, + "description": "workqueue stream requires explicit ack", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerWQMultipleUnfilteredErr", + "code": 400, + "error_code": 10099, + "description": "multiple non-filtered consumers not allowed on workqueue stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerWQConsumerNotUniqueErr", + "code": 400, + "error_code": 10100, + "description": "filtered consumer not unique on workqueue stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerWQConsumerNotDeliverAllErr", + "code": 400, + "error_code": 10101, + "description": "consumer must be deliver all on workqueue stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerNameTooLongErrF", + "code": 400, + "error_code": 10102, + "description": "consumer name is too long, maximum allowed is {max}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerBadDurableNameErr", + "code": 400, + "error_code": 10103, + "description": "durable name can not contain '.', '*', '\u003e'", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerStoreFailedErrF", + "code": 500, + "error_code": 10104, + "description": "error creating store for consumer: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerExistingActiveErr", + "code": 400, + "error_code": 10105, + "description": "consumer already exists and is still active", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerReplacementWithDifferentNameErr", + "code": 400, + "error_code": 10106, + "description": "consumer replacement durable config not the same", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDescriptionTooLongErrF", + "code": 400, + "error_code": 10107, + "description": "consumer description is too long, maximum allowed is {max}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamHeaderExceedsMaximumErr", + "code": 400, + "error_code": 10097, + "description": "header size exceeds maximum allowed of 64k", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerWithFlowControlNeedsHeartbeats", + "code": 400, + "error_code": 10108, + "description": "consumer with flow control also needs heartbeats", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamSealedErr", + "code": 400, + "error_code": 10109, + "description": "invalid operation on sealed stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamPurgeFailedF", + "code": 500, + "error_code": 10110, + "description": "{err}", + "comment": "Generic stream purge failure error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamRollupFailedF", + "code": 500, + "error_code": 10111, + "description": "{err}", + "comment": "Generic stream rollup failure error string", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerInvalidDeliverSubject", + "code": 400, + "error_code": 10112, + "description": "invalid push consumer deliver subject", + "comment": "", + "help": "Returned when the delivery subject on a Push Consumer is not a valid NATS Subject", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMaxBytesRequired", + "code": 400, + "error_code": 10113, + "description": "account requires a stream config to have max bytes set", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxRequestBatchNegativeErr", + "code": 400, + "error_code": 10114, + "description": "consumer max request batch needs to be \u003e 0", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxRequestExpiresToSmall", + "code": 400, + "error_code": 10115, + "description": "consumer max request expires needs to be \u003e= 1ms", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxDeliverBackoffErr", + "code": 400, + "error_code": 10116, + "description": "max deliver is required to be \u003e length of backoff values", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamInfoMaxSubjectsErr", + "code": 500, + "error_code": 10117, + "description": "subject details would exceed maximum allowed", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamOfflineErr", + "code": 500, + "error_code": 10118, + "description": "stream is offline", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerOfflineErr", + "code": 500, + "error_code": 10119, + "description": "consumer is offline", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSNoLimitsErr", + "code": 400, + "error_code": 10120, + "description": "no JetStream default or applicable tiered limit present", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxPendingAckExcessErrF", + "code": 400, + "error_code": 10121, + "description": "consumer max ack pending exceeds system limit of {limit}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMaxStreamBytesExceeded", + "code": 400, + "error_code": 10122, + "description": "stream max bytes exceeds account limit max stream bytes", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMoveAndScaleErr", + "code": 400, + "error_code": 10123, + "description": "can not move and scale a stream in a single update", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMoveInProgressF", + "code": 400, + "error_code": 10124, + "description": "stream move already in progress: {msg}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMaxRequestBatchExceededF", + "code": 400, + "error_code": 10125, + "description": "consumer max request batch exceeds server limit of {limit}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerReplicasExceedsStream", + "code": 400, + "error_code": 10126, + "description": "consumer config replica count exceeds parent stream", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerNameContainsPathSeparatorsErr", + "code": 400, + "error_code": 10127, + "description": "Consumer name can not contain path separators", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamNameContainsPathSeparatorsErr", + "code": 400, + "error_code": 10128, + "description": "Stream name can not contain path separators", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamMoveNotInProgress", + "code": 400, + "error_code": 10129, + "description": "stream move not in progress", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamNameExistRestoreFailedErr", + "code": 400, + "error_code": 10130, + "description": "stream name already in use, cannot restore", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerCreateFilterSubjectMismatchErr", + "code": 400, + "error_code": 10131, + "description": "Consumer create request did not match filtered subject from create subject", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerCreateDurableAndNameMismatch", + "code": 400, + "error_code": 10132, + "description": "Consumer Durable and Name have to be equal if both are provided", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSReplicasCountCannotBeNegative", + "code": 400, + "error_code": 10133, + "description": "replicas count cannot be negative", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerReplicasShouldMatchStream", + "code": 400, + "error_code": 10134, + "description": "consumer config replicas must match interest retention stream's replicas", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMetadataLengthErrF", + "code": 400, + "error_code": 10135, + "description": "consumer metadata exceeds maximum size of {limit}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDuplicateFilterSubjects", + "code": 400, + "error_code": 10136, + "description": "consumer cannot have both FilterSubject and FilterSubjects specified", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerMultipleFiltersNotAllowed", + "code": 400, + "error_code": 10137, + "description": "consumer with multiple subject filters cannot use subject based API", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerOverlappingSubjectFilters", + "code": 400, + "error_code": 10138, + "description": "consumer subject filters cannot overlap", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerEmptyFilter", + "code": 400, + "error_code": 10139, + "description": "consumer filter in FilterSubjects cannot be empty", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceDuplicateDetected", + "code": 400, + "error_code": 10140, + "description": "duplicate source configuration detected", + "comment": "source stream, filter and transform (plus external if present) must form a unique combination", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceInvalidStreamName", + "code": 400, + "error_code": 10141, + "description": "sourced stream name is invalid", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorInvalidStreamName", + "code": 400, + "error_code": 10142, + "description": "mirrored stream name is invalid", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceMultipleFiltersNotAllowed", + "code": 400, + "error_code": 10144, + "description": "source with multiple subject transforms cannot also have a single subject filter", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceInvalidSubjectFilter", + "code": 400, + "error_code": 10145, + "description": "source transform source: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceInvalidTransformDestination", + "code": 400, + "error_code": 10146, + "description": "source transform: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSSourceOverlappingSubjectFilters", + "code": 400, + "error_code": 10147, + "description": "source filters can not overlap", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerAlreadyExists", + "code": 400, + "error_code": 10148, + "description": "consumer already exists", + "comment": "action CREATE is used for a existing consumer with a different config", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerDoesNotExist", + "code": 400, + "error_code": 10149, + "description": "consumer does not exist", + "comment": "action UPDATE is used for a nonexisting consumer", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorMultipleFiltersNotAllowed", + "code": 400, + "error_code": 10150, + "description": "mirror with multiple subject transforms cannot also have a single subject filter", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorInvalidSubjectFilter", + "code": 400, + "error_code": 10151, + "description": "mirror transform source: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorOverlappingSubjectFilters", + "code": 400, + "error_code": 10152, + "description": "mirror subject filters can not overlap", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerInactiveThresholdExcess", + "code": 400, + "error_code": 10153, + "description": "consumer inactive threshold exceeds system limit of {limit}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMirrorInvalidTransformDestination", + "code": 400, + "error_code": 10154, + "description": "mirror transform: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamTransformInvalidSource", + "code": 400, + "error_code": 10155, + "description": "stream transform source: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamTransformInvalidDestination", + "code": 400, + "error_code": 10156, + "description": "stream transform: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSPedanticErrF", + "code": 400, + "error_code": 10157, + "description": "pedantic mode: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamDuplicateMessageConflict", + "code": 409, + "error_code": 10158, + "description": "duplicate message id is in process", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerPriorityPolicyWithoutGroup", + "code": 400, + "error_code": 10159, + "description": "Setting PriorityPolicy requires at least one PriorityGroup to be set", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerInvalidPriorityGroupErr", + "code": 400, + "error_code": 10160, + "description": "Provided priority group does not exist for this consumer", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerEmptyGroupName", + "code": 400, + "error_code": 10161, + "description": "Group name cannot be an empty string", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerInvalidGroupNameErr", + "code": 400, + "error_code": 10162, + "description": "Valid priority group name must match A-Z, a-z, 0-9, -_/=)+ and may not exceed 16 characters", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamExpectedLastSeqPerSubjectNotReady", + "code": 503, + "error_code": 10163, + "description": "expected last sequence per subject temporarily unavailable", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamWrongLastSequenceConstantErr", + "code": 400, + "error_code": 10164, + "description": "wrong last sequence", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMessageTTLInvalidErr", + "code": 400, + "error_code": 10165, + "description": "invalid per-message TTL", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSMessageTTLDisabledErr", + "code": 400, + "error_code": 10166, + "description": "per-message TTL is disabled", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamTooManyRequests", + "code": 429, + "error_code": 10167, + "description": "too many requests", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerPushWithPriorityGroupErr", + "code": 400, + "error_code": 10178, + "description": "priority groups can not be used with push consumers", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSStreamOfflineReasonErrF", + "code": 500, + "error_code": 10194, + "description": "stream is offline: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSConsumerOfflineReasonErrF", + "code": 500, + "error_code": 10195, + "description": "consumer is offline: {err}", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + }, + { + "constant": "JSClusterServerMemberChangeInflightErr", + "code": 400, + "error_code": 10202, + "description": "cluster member change is in progress", + "comment": "", + "help": "", + "url": "", + "deprecates": "" + } +] diff --git a/vendor/github.com/nats-io/nats-server/v2/server/events.go b/vendor/github.com/nats-io/nats-server/v2/server/events.go index 9d3862d..b0d7624 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/events.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/events.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The NATS Authors +// Copyright 2018-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,20 +15,26 @@ package server import ( "bytes" + "compress/gzip" "crypto/sha256" - "encoding/base64" + "crypto/x509" "encoding/json" "errors" "fmt" + "math" "math/rand" "net/http" + "runtime" + "runtime/debug" "strconv" "strings" "sync" "sync/atomic" "time" + "github.com/klauspost/compress/s2" "github.com/nats-io/jwt/v2" + "github.com/nats-io/nats-server/v2/server/certidp" "github.com/nats-io/nats-server/v2/server/pse" ) @@ -42,23 +48,33 @@ const ( connectEventSubj = "$SYS.ACCOUNT.%s.CONNECT" disconnectEventSubj = "$SYS.ACCOUNT.%s.DISCONNECT" - accReqSubj = "$SYS.REQ.ACCOUNT.%s.%s" + accDirectReqSubj = "$SYS.REQ.ACCOUNT.%s.%s" + accPingReqSubj = "$SYS.REQ.ACCOUNT.PING.%s" // atm. only used for STATZ and CONNZ import from system account // kept for backward compatibility when using http resolver // this overlaps with the names for events but you'd have to have the operator private key in order to succeed. - accUpdateEventSubjOld = "$SYS.ACCOUNT.%s.CLAIMS.UPDATE" - accUpdateEventSubjNew = "$SYS.REQ.ACCOUNT.%s.CLAIMS.UPDATE" - connsRespSubj = "$SYS._INBOX_.%s" - accConnsEventSubjNew = "$SYS.ACCOUNT.%s.SERVER.CONNS" - accConnsEventSubjOld = "$SYS.SERVER.ACCOUNT.%s.CONNS" // kept for backward compatibility - shutdownEventSubj = "$SYS.SERVER.%s.SHUTDOWN" - authErrorEventSubj = "$SYS.SERVER.%s.CLIENT.AUTH.ERR" - serverStatsSubj = "$SYS.SERVER.%s.STATSZ" - serverDirectReqSubj = "$SYS.REQ.SERVER.%s.%s" - serverPingReqSubj = "$SYS.REQ.SERVER.PING.%s" - serverStatsPingReqSubj = "$SYS.REQ.SERVER.PING" // use $SYS.REQ.SERVER.PING.STATSZ instead - leafNodeConnectEventSubj = "$SYS.ACCOUNT.%s.LEAFNODE.CONNECT" - remoteLatencyEventSubj = "$SYS.LATENCY.M2.%s" - inboxRespSubj = "$SYS._INBOX.%s.%s" + accUpdateEventSubjOld = "$SYS.ACCOUNT.%s.CLAIMS.UPDATE" + accUpdateEventSubjNew = "$SYS.REQ.ACCOUNT.%s.CLAIMS.UPDATE" + connsRespSubj = "$SYS._INBOX_.%s" + accConnsEventSubjNew = "$SYS.ACCOUNT.%s.SERVER.CONNS" + accConnsEventSubjOld = "$SYS.SERVER.ACCOUNT.%s.CONNS" // kept for backward compatibility + lameDuckEventSubj = "$SYS.SERVER.%s.LAMEDUCK" + shutdownEventSubj = "$SYS.SERVER.%s.SHUTDOWN" + clientKickReqSubj = "$SYS.REQ.SERVER.%s.KICK" + clientLDMReqSubj = "$SYS.REQ.SERVER.%s.LDM" + authErrorEventSubj = "$SYS.SERVER.%s.CLIENT.AUTH.ERR" + authErrorAccountEventSubj = "$SYS.ACCOUNT.CLIENT.AUTH.ERR" + serverStatsSubj = "$SYS.SERVER.%s.STATSZ" + serverDirectReqSubj = "$SYS.REQ.SERVER.%s.%s" + serverPingReqSubj = "$SYS.REQ.SERVER.PING.%s" + serverStatsPingReqSubj = "$SYS.REQ.SERVER.PING" // use $SYS.REQ.SERVER.PING.STATSZ instead + serverReloadReqSubj = "$SYS.REQ.SERVER.%s.RELOAD" // with server ID + leafNodeConnectEventSubj = "$SYS.ACCOUNT.%s.LEAFNODE.CONNECT" // for internal use only + remoteLatencyEventSubj = "$SYS.LATENCY.M2.%s" + inboxRespSubj = "$SYS._INBOX.%s.%s" + + // Used to return information to a user on bound account and user permissions. + userDirectInfoSubj = "$SYS.REQ.USER.INFO" + userDirectReqSubj = "$SYS.REQ.USER.%s.INFO" // FIXME(dlc) - Should account scope, even with wc for now, but later on // we can then shard as needed. @@ -75,29 +91,59 @@ const ( accReqTokens = 5 accReqAccIndex = 3 + + ocspPeerRejectEventSubj = "$SYS.SERVER.%s.OCSP.PEER.CONN.REJECT" + ocspPeerChainlinkInvalidEventSubj = "$SYS.SERVER.%s.OCSP.PEER.LINK.INVALID" ) // FIXME(dlc) - make configurable. var eventsHBInterval = 30 * time.Second +var statsHBInterval = 10 * time.Second + +// Default minimum wait time for sending statsz +const defaultStatszRateLimit = 1 * time.Second + +// Variable version so we can set in tests. +var statszRateLimit = defaultStatszRateLimit + +type sysMsgHandler func(sub *subscription, client *client, acc *Account, subject, reply string, hdr, msg []byte) + +// Used if we have to queue things internally to avoid the route/gw path. +type inSysMsg struct { + sub *subscription + c *client + acc *Account + subj string + rply string + hdr []byte + msg []byte + cb sysMsgHandler +} // Used to send and receive messages from inside the server. type internal struct { - account *Account - client *client - seq uint64 - sid int - servers map[string]*serverUpdate - sweeper *time.Timer - stmr *time.Timer - replies map[string]msgHandler - sendq chan *pubMsg - resetCh chan struct{} - wg sync.WaitGroup - orphMax time.Duration - chkOrph time.Duration - statsz time.Duration - shash string - inboxPre string + account *Account + client *client + seq uint64 + sid int + servers map[string]*serverUpdate + sweeper *time.Timer + stmr *time.Timer + replies map[string]msgHandler + sendq *ipQueue[*pubMsg] + recvq *ipQueue[*inSysMsg] + recvqp *ipQueue[*inSysMsg] // For STATSZ/Pings + resetCh chan struct{} + wg sync.WaitGroup + sq *sendq + orphMax time.Duration + chkOrph time.Duration + statsz time.Duration + cstatsz time.Duration + shash string + inboxPre string + remoteStatsSub *subscription + lastStatsz time.Time } // ServerStatsMsg is sent periodically with stats updates. @@ -130,16 +176,54 @@ type DisconnectEventMsg struct { // DisconnectEventMsgType is the schema type for DisconnectEventMsg const DisconnectEventMsgType = "io.nats.server.advisory.v1.client_disconnect" +// OCSPPeerRejectEventMsg is sent when a peer TLS handshake is ultimately rejected due to OCSP invalidation. +// A "peer" can be an inbound client connection or a leaf connection to a remote server. Peer in event payload +// is always the peer's (TLS) leaf cert, which may or may be the invalid cert (See also OCSPPeerChainlinkInvalidEventMsg) +type OCSPPeerRejectEventMsg struct { + TypedEvent + Kind string `json:"kind"` + Peer certidp.CertInfo `json:"peer"` + Server ServerInfo `json:"server"` + Reason string `json:"reason"` +} + +// OCSPPeerRejectEventMsgType is the schema type for OCSPPeerRejectEventMsg +const OCSPPeerRejectEventMsgType = "io.nats.server.advisory.v1.ocsp_peer_reject" + +// OCSPPeerChainlinkInvalidEventMsg is sent when a certificate (link) in a valid TLS chain is found to be OCSP invalid +// during a peer TLS handshake. A "peer" can be an inbound client connection or a leaf connection to a remote server. +// Peer and Link may be the same if the invalid cert was the peer's leaf cert +type OCSPPeerChainlinkInvalidEventMsg struct { + TypedEvent + Link certidp.CertInfo `json:"link"` + Peer certidp.CertInfo `json:"peer"` + Server ServerInfo `json:"server"` + Reason string `json:"reason"` +} + +// OCSPPeerChainlinkInvalidEventMsgType is the schema type for OCSPPeerChainlinkInvalidEventMsg +const OCSPPeerChainlinkInvalidEventMsgType = "io.nats.server.advisory.v1.ocsp_peer_link_invalid" + // AccountNumConns is an event that will be sent from a server that is tracking // a given account when the number of connections changes. It will also HB // updates in the absence of any changes. type AccountNumConns struct { TypedEvent - Server ServerInfo `json:"server"` - Account string `json:"acc"` - Conns int `json:"conns"` - LeafNodes int `json:"leafnodes"` - TotalConns int `json:"total_conns"` + Server ServerInfo `json:"server"` + AccountStat +} + +// AccountStat contains the data common between AccountNumConns and AccountStatz +type AccountStat struct { + Account string `json:"acc"` + Name string `json:"name"` + Conns int `json:"conns"` + LeafNodes int `json:"leafnodes"` + TotalConns int `json:"total_conns"` + NumSubs uint32 `json:"num_subscriptions"` + Sent DataStats `json:"sent"` + Received DataStats `json:"received"` + SlowConsumers int64 `json:"slow_consumers"` } const AccountNumConnsMsgType = "io.nats.server.advisory.v1.account_connections" @@ -151,48 +235,151 @@ type accNumConnsReq struct { Account string `json:"acc"` } +// ServerID is basic static info for a server. +type ServerID struct { + Name string `json:"name"` + Host string `json:"host"` + ID string `json:"id"` +} + +// Type for our server capabilities. +type ServerCapability uint64 + // ServerInfo identifies remote servers. type ServerInfo struct { - Name string `json:"name"` - Host string `json:"host"` - ID string `json:"id"` - Cluster string `json:"cluster,omitempty"` - Version string `json:"ver"` - Seq uint64 `json:"seq"` - JetStream bool `json:"jetstream"` - Time time.Time `json:"time"` + Name string `json:"name"` + Host string `json:"host"` + ID string `json:"id"` + Cluster string `json:"cluster,omitempty"` + Domain string `json:"domain,omitempty"` + Version string `json:"ver"` + Tags []string `json:"tags,omitempty"` + // Whether JetStream is enabled (deprecated in favor of the `ServerCapability`). + JetStream bool `json:"jetstream"` + // Generic capability flags + Flags ServerCapability `json:"flags"` + // Sequence and Time from the remote server for this message. + Seq uint64 `json:"seq"` + Time time.Time `json:"time"` +} + +const ( + JetStreamEnabled ServerCapability = 1 << iota // Server had JetStream enabled. + BinaryStreamSnapshot // New stream snapshot capability. + AccountNRG // Move NRG traffic out of system account. +) + +// Set JetStream capability. +func (si *ServerInfo) SetJetStreamEnabled() { + si.Flags |= JetStreamEnabled + // Still set old version. + si.JetStream = true +} + +// JetStreamEnabled indicates whether or not we have JetStream enabled. +func (si *ServerInfo) JetStreamEnabled() bool { + // Take into account old version. + return si.Flags&JetStreamEnabled != 0 || si.JetStream +} + +// Set binary stream snapshot capability. +func (si *ServerInfo) SetBinaryStreamSnapshot() { + si.Flags |= BinaryStreamSnapshot +} + +// JetStreamEnabled indicates whether or not we have binary stream snapshot capbilities. +func (si *ServerInfo) BinaryStreamSnapshot() bool { + return si.Flags&BinaryStreamSnapshot != 0 +} + +// Set account NRG capability. +func (si *ServerInfo) SetAccountNRG() { + si.Flags |= AccountNRG +} + +// AccountNRG indicates whether or not we support moving the NRG traffic out of the +// system account and into the asset account. +func (si *ServerInfo) AccountNRG() bool { + return si.Flags&AccountNRG != 0 } // ClientInfo is detailed information about the client forming a connection. type ClientInfo struct { - Start time.Time `json:"start,omitempty"` - Host string `json:"host,omitempty"` - ID uint64 `json:"id"` - Account string `json:"acc"` - User string `json:"user,omitempty"` - Name string `json:"name,omitempty"` - Lang string `json:"lang,omitempty"` - Version string `json:"ver,omitempty"` - RTT string `json:"rtt,omitempty"` - Server string `json:"server,omitempty"` - Stop *time.Time `json:"stop,omitempty"` + Start *time.Time `json:"start,omitempty"` + Host string `json:"host,omitempty"` + ID uint64 `json:"id,omitempty"` + Account string `json:"acc,omitempty"` + Service string `json:"svc,omitempty"` + User string `json:"user,omitempty"` + Name string `json:"name,omitempty"` + Lang string `json:"lang,omitempty"` + Version string `json:"ver,omitempty"` + RTT time.Duration `json:"rtt,omitempty"` + Server string `json:"server,omitempty"` + Cluster string `json:"cluster,omitempty"` + Alternates []string `json:"alts,omitempty"` + Stop *time.Time `json:"stop,omitempty"` + Jwt string `json:"jwt,omitempty"` + IssuerKey string `json:"issuer_key,omitempty"` + NameTag string `json:"name_tag,omitempty"` + Tags jwt.TagList `json:"tags,omitempty"` + Kind string `json:"kind,omitempty"` + ClientType string `json:"client_type,omitempty"` + MQTTClient string `json:"client_id,omitempty"` // This is the MQTT client ID + Nonce string `json:"nonce,omitempty"` +} + +// forAssignmentSnap returns the minimum amount of ClientInfo we need for assignment snapshots. +func (ci *ClientInfo) forAssignmentSnap() *ClientInfo { + return &ClientInfo{ + Account: ci.Account, + Service: ci.Service, + Cluster: ci.Cluster, + } +} + +// forProposal returns the minimum amount of ClientInfo we need for assignment proposals. +func (ci *ClientInfo) forProposal() *ClientInfo { + if ci == nil { + return nil + } + cci := *ci + cci.Jwt = _EMPTY_ + cci.IssuerKey = _EMPTY_ + return &cci +} + +// forAdvisory returns the minimum amount of ClientInfo we need for JS advisory events. +func (ci *ClientInfo) forAdvisory() *ClientInfo { + if ci == nil { + return nil + } + cci := *ci + cci.Jwt = _EMPTY_ + cci.Alternates = nil + return &cci } // ServerStats hold various statistics that we will periodically send out. type ServerStats struct { - Start time.Time `json:"start"` - Mem int64 `json:"mem"` - Cores int `json:"cores"` - CPU float64 `json:"cpu"` - Connections int `json:"connections"` - TotalConnections uint64 `json:"total_connections"` - ActiveAccounts int `json:"active_accounts"` - NumSubs uint32 `json:"subscriptions"` - Sent DataStats `json:"sent"` - Received DataStats `json:"received"` - SlowConsumers int64 `json:"slow_consumers"` - Routes []*RouteStat `json:"routes,omitempty"` - Gateways []*GatewayStat `json:"gateways,omitempty"` + Start time.Time `json:"start"` + Mem int64 `json:"mem"` + Cores int `json:"cores"` + CPU float64 `json:"cpu"` + Connections int `json:"connections"` + TotalConnections uint64 `json:"total_connections"` + ActiveAccounts int `json:"active_accounts"` + NumSubs uint32 `json:"subscriptions"` + Sent DataStats `json:"sent"` + Received DataStats `json:"received"` + SlowConsumers int64 `json:"slow_consumers"` + SlowConsumersStats *SlowConsumersStats `json:"slow_consumer_stats,omitempty"` + Routes []*RouteStat `json:"routes,omitempty"` + Gateways []*GatewayStat `json:"gateways,omitempty"` + ActiveServers int `json:"active_servers,omitempty"` + JetStream *JetStreamVarz `json:"jetstream,omitempty"` + MemLimit int64 `json:"gomemlimit,omitempty"` + MaxProcs int `json:"gomaxprocs,omitempty"` } // RouteStat holds route statistics. @@ -213,22 +400,59 @@ type GatewayStat struct { NumInbound int `json:"inbound_connections"` } -// DataStats reports how may msg and bytes. Applicable for both sent and received. -type DataStats struct { +type MsgBytes struct { Msgs int64 `json:"msgs"` Bytes int64 `json:"bytes"` } +// DataStats reports how may msg and bytes. Applicable for both sent and received. +type DataStats struct { + MsgBytes + Gateways *MsgBytes `json:"gateways,omitempty"` + Routes *MsgBytes `json:"routes,omitempty"` + Leafs *MsgBytes `json:"leafs,omitempty"` +} + // Used for internally queueing up messages that the server wants to send. type pubMsg struct { - acc *Account + c *client sub string rply string si *ServerInfo - msg interface{} + hdr []byte + msg any + oct compressionType + echo bool last bool } +var pubMsgPool sync.Pool + +func newPubMsg(c *client, sub, rply string, si *ServerInfo, hdr []byte, + msg any, oct compressionType, echo, last bool) *pubMsg { + + var m *pubMsg + pm := pubMsgPool.Get() + if pm != nil { + m = pm.(*pubMsg) + } else { + m = &pubMsg{} + } + // When getting something from a pool it is critical that all fields are + // initialized. Doing this way guarantees that if someone adds a field to + // the structure, the compiler will fail the build if this line is not updated. + (*m) = pubMsg{c, sub, rply, si, hdr, msg, oct, echo, last} + return m +} + +func (pm *pubMsg) returnToPool() { + if pm == nil { + return + } + pm.c, pm.sub, pm.rply, pm.si, pm.hdr, pm.msg = nil, _EMPTY_, _EMPTY_, nil, nil, nil + pubMsgPool.Put(pm) +} + // Used to track server updates. type serverUpdate struct { seq uint64 @@ -243,104 +467,192 @@ type TypedEvent struct { Time time.Time `json:"timestamp"` } +// internalReceiveLoop will be responsible for dispatching all messages that +// a server receives and needs to internally process, e.g. internal subs. +func (s *Server) internalReceiveLoop(recvq *ipQueue[*inSysMsg]) { + for s.eventsRunning() { + select { + case <-recvq.ch: + msgs := recvq.pop() + for _, m := range msgs { + if m.cb != nil { + m.cb(m.sub, m.c, m.acc, m.subj, m.rply, m.hdr, m.msg) + } + } + recvq.recycle(&msgs) + case <-s.quitCh: + return + } + } +} + // internalSendLoop will be responsible for serializing all messages that // a server wants to send. func (s *Server) internalSendLoop(wg *sync.WaitGroup) { defer wg.Done() RESET: - s.mu.Lock() + s.mu.RLock() if s.sys == nil || s.sys.sendq == nil { - s.mu.Unlock() + s.mu.RUnlock() return } - c := s.sys.client + sysc := s.sys.client resetCh := s.sys.resetCh - sysacc := s.sys.account sendq := s.sys.sendq id := s.info.ID host := s.info.Host servername := s.info.Name + domain := s.info.Domain seqp := &s.sys.seq - js := s.js != nil + js := s.info.JetStream cluster := s.info.Cluster if s.gateway.enabled { cluster = s.getGatewayName() } - s.mu.Unlock() + s.mu.RUnlock() - // Warn when internal send queue is backed up past 75% - warnThresh := 3 * internalSendQLen / 4 - warnFreq := time.Second - last := time.Now().Add(-warnFreq) + // Grab tags. + tags := s.getOpts().Tags for s.eventsRunning() { - // Setup information for next message - if len(sendq) > warnThresh && time.Since(last) >= warnFreq { - s.Warnf("Internal system send queue > 75%%") - last = time.Now() - } - select { - case pm := <-sendq: - if pm.si != nil { - pm.si.Name = servername - pm.si.Host = host - pm.si.Cluster = cluster - pm.si.ID = id - pm.si.Seq = atomic.AddUint64(seqp, 1) - pm.si.Version = VERSION - pm.si.Time = time.Now() - pm.si.JetStream = js - } - var b []byte - if pm.msg != nil { - switch v := pm.msg.(type) { - case string: - b = []byte(v) - case []byte: - b = v - default: - b, _ = json.MarshalIndent(pm.msg, _EMPTY_, " ") + case <-sendq.ch: + msgs := sendq.pop() + for _, pm := range msgs { + if si := pm.si; si != nil { + si.Name = servername + si.Domain = domain + si.Host = host + si.Cluster = cluster + si.ID = id + si.Seq = atomic.AddUint64(seqp, 1) + si.Version = VERSION + si.Time = time.Now().UTC() + si.Tags = tags + si.Flags = 0 + if js { + // New capability based flags. + si.SetJetStreamEnabled() + si.SetBinaryStreamSnapshot() + if s.accountNRGAllowed.Load() { + si.SetAccountNRG() + } + } + } + var b []byte + if pm.msg != nil { + switch v := pm.msg.(type) { + case string: + b = []byte(v) + case []byte: + b = v + default: + b, _ = json.Marshal(pm.msg) + } + } + // Setup our client. If the user wants to use a non-system account use our internal + // account scoped here so that we are not changing out accounts for the system client. + var c *client + if pm.c != nil { + c = pm.c + } else { + c = sysc } - } - c.mu.Lock() - // We can have an override for account here. - if pm.acc != nil { - c.acc = pm.acc - } else { - c.acc = sysacc - } + // Grab client lock. + c.mu.Lock() - // Prep internal structures needed to send message. - c.pa.subject = []byte(pm.sub) - c.pa.size = len(b) - c.pa.szb = []byte(strconv.FormatInt(int64(len(b)), 10)) - c.pa.reply = []byte(pm.rply) - trace := c.trace - c.mu.Unlock() + // Prep internal structures needed to send message. + c.pa.subject, c.pa.reply = []byte(pm.sub), []byte(pm.rply) + c.pa.size, c.pa.szb = len(b), []byte(strconv.FormatInt(int64(len(b)), 10)) + c.pa.hdr, c.pa.hdb = -1, nil + trace := c.trace + + // Now check for optional compression. + var contentHeader string + var bb bytes.Buffer + + if len(b) > 0 { + switch pm.oct { + case gzipCompression: + zw := gzip.NewWriter(&bb) + zw.Write(b) + zw.Close() + b = bb.Bytes() + contentHeader = "gzip" + case snappyCompression: + sw := s2.NewWriter(&bb, s2.WriterSnappyCompat()) + sw.Write(b) + sw.Close() + b = bb.Bytes() + contentHeader = "snappy" + case unsupportedCompression: + contentHeader = "identity" + } + } + // Optional Echo + replaceEcho := c.echo != pm.echo + if replaceEcho { + c.echo = !c.echo + } + c.mu.Unlock() + + // Add in NL + b = append(b, _CRLF_...) + + // Optional raw header addition. + if pm.hdr != nil { + b = append(pm.hdr, b...) + nhdr := len(pm.hdr) + nsize := len(b) - LEN_CR_LF + // MQTT producers don't have CRLF, so add it back. + if c.isMqtt() { + nsize += LEN_CR_LF + } + // Update pubArgs + // If others will use this later we need to save and restore original. + c.pa.hdr = nhdr + c.pa.size = nsize + c.pa.hdb = []byte(strconv.Itoa(nhdr)) + c.pa.szb = []byte(strconv.Itoa(nsize)) + } - // Add in NL - b = append(b, _CRLF_...) + // Check if we should set content-encoding + if contentHeader != _EMPTY_ { + b = c.setHeader(contentEncodingHeader, contentHeader, b) + } - if trace { - c.traceInOp(fmt.Sprintf("PUB %s %s %d", - c.pa.subject, c.pa.reply, c.pa.size), nil) - c.traceMsg(b) - } + // Tracing + if trace { + c.traceInOp(fmt.Sprintf("PUB %s %s %d", c.pa.subject, c.pa.reply, c.pa.size), nil) + c.traceMsg(b) + } - c.processInboundClientMsg(b) - // See if we are doing graceful shutdown. - if !pm.last { - c.flushClients(0) // Never spend time in place. - } else { - // For the Shutdown event, we need to send in place otherwise - // there is a chance that the process will exit before the - // writeLoop has a chance to send it. - c.flushClients(time.Second) - return + // Process like a normal inbound msg. + c.processInboundClientMsg(b) + + // Put echo back if needed. + if replaceEcho { + c.mu.Lock() + c.echo = !c.echo + c.mu.Unlock() + } + + // See if we are doing graceful shutdown. + if !pm.last { + c.flushClients(0) // Never spend time in place. + } else { + // For the Shutdown event, we need to send in place otherwise + // there is a chance that the process will exit before the + // writeLoop has a chance to send it. + c.flushClients(time.Second) + sendq.recycle(&msgs) + return + } + pm.returnToPool() } + sendq.recycle(&msgs) case <-resetCh: goto RESET case <-s.quitCh: @@ -349,6 +661,19 @@ RESET: } } +// Will send a shutdown message for lame-duck. Unlike sendShutdownEvent, this will +// not close off the send queue or reply handler, as we may still have a workload +// that needs migrating off. +// Lock should be held. +func (s *Server) sendLDMShutdownEventLocked() { + if s.sys == nil || s.sys.sendq == nil { + return + } + subj := fmt.Sprintf(lameDuckEventSubj, s.info.ID) + si := &ServerInfo{} + s.sys.sendq.push(newPubMsg(nil, subj, _EMPTY_, si, nil, si, noCompression, false, true)) +} + // Will send a shutdown message. func (s *Server) sendShutdownEvent() { s.mu.Lock() @@ -362,61 +687,121 @@ func (s *Server) sendShutdownEvent() { s.sys.sendq = nil // Unhook all msgHandlers. Normal client cleanup will deal with subs, etc. s.sys.replies = nil - s.mu.Unlock() // Send to the internal queue and mark as last. - sendq <- &pubMsg{nil, subj, _EMPTY_, nil, nil, true} + si := &ServerInfo{} + sendq.push(newPubMsg(nil, subj, _EMPTY_, si, nil, si, noCompression, false, true)) + s.mu.Unlock() } // Used to send an internal message to an arbitrary account. -func (s *Server) sendInternalAccountMsg(a *Account, subject string, msg interface{}) error { - s.mu.Lock() +func (s *Server) sendInternalAccountMsg(a *Account, subject string, msg any) error { + return s.sendInternalAccountMsgWithReply(a, subject, _EMPTY_, nil, msg, false) +} + +// Used to send an internal message with an optional reply to an arbitrary account. +func (s *Server) sendInternalAccountMsgWithReply(a *Account, subject, reply string, hdr []byte, msg any, echo bool) error { + s.mu.RLock() if s.sys == nil || s.sys.sendq == nil { - s.mu.Unlock() + s.mu.RUnlock() + if s.isShuttingDown() { + // Skip in case this was called at the end phase during shut down + // to avoid too many entries in the logs. + return nil + } return ErrNoSysAccount } - sendq := s.sys.sendq - // Don't hold lock while placing on the channel. - s.mu.Unlock() - sendq <- &pubMsg{a, subject, "", nil, msg, false} + c := s.sys.client + // Replace our client with the account's internal client. + if a != nil { + a.mu.Lock() + c = a.internalClient() + a.mu.Unlock() + } + s.sys.sendq.push(newPubMsg(c, subject, reply, nil, hdr, msg, noCompression, echo, false)) + s.mu.RUnlock() return nil } +// Send system style message to an account scope. +func (s *Server) sendInternalAccountSysMsg(a *Account, subj string, si *ServerInfo, msg any, ct compressionType) { + s.mu.RLock() + if s.sys == nil || s.sys.sendq == nil || a == nil { + s.mu.RUnlock() + return + } + sendq := s.sys.sendq + s.mu.RUnlock() + + a.mu.Lock() + c := a.internalClient() + a.mu.Unlock() + + sendq.push(newPubMsg(c, subj, _EMPTY_, si, nil, msg, ct, false, false)) +} + // This will queue up a message to be sent. // Lock should not be held. -func (s *Server) sendInternalMsgLocked(sub, rply string, si *ServerInfo, msg interface{}) { - s.mu.Lock() - s.sendInternalMsg(sub, rply, si, msg) - s.mu.Unlock() +func (s *Server) sendInternalMsgLocked(subj, rply string, si *ServerInfo, msg any) { + s.mu.RLock() + s.sendInternalMsg(subj, rply, si, msg) + s.mu.RUnlock() } // This will queue up a message to be sent. // Assumes lock is held on entry. -func (s *Server) sendInternalMsg(sub, rply string, si *ServerInfo, msg interface{}) { +func (s *Server) sendInternalMsg(subj, rply string, si *ServerInfo, msg any) { if s.sys == nil || s.sys.sendq == nil { return } - sendq := s.sys.sendq - // Don't hold lock while placing on the channel. - s.mu.Unlock() - sendq <- &pubMsg{nil, sub, rply, si, msg, false} - s.mu.Lock() + s.sys.sendq.push(newPubMsg(nil, subj, rply, si, nil, msg, noCompression, false, false)) +} + +// Will send an api response. +func (s *Server) sendInternalResponse(subj string, response *ServerAPIResponse) { + s.mu.RLock() + if s.sys == nil || s.sys.sendq == nil { + s.mu.RUnlock() + return + } + s.sys.sendq.push(newPubMsg(nil, subj, _EMPTY_, response.Server, nil, response, response.compress, false, false)) + s.mu.RUnlock() +} + +// Used to send internal messages from other system clients to avoid no echo issues. +func (c *client) sendInternalMsg(subj, rply string, si *ServerInfo, msg any) { + if c == nil { + return + } + s := c.srv + if s == nil { + return + } + s.mu.RLock() + if s.sys == nil || s.sys.sendq == nil { + s.mu.RUnlock() + return + } + s.sys.sendq.push(newPubMsg(c, subj, rply, si, nil, msg, noCompression, false, false)) + s.mu.RUnlock() } // Locked version of checking if events system running. Also checks server. func (s *Server) eventsRunning() bool { - s.mu.Lock() - er := s.running && s.eventsEnabled() - s.mu.Unlock() + if s == nil { + return false + } + s.mu.RLock() + er := s.isRunning() && s.eventsEnabled() + s.mu.RUnlock() return er } // EventsEnabled will report if the server has internal events enabled via // a defined system account. func (s *Server) EventsEnabled() bool { - s.mu.Lock() - ee := s.eventsEnabled() - s.mu.Unlock() - return ee + s.mu.RLock() + defer s.mu.RUnlock() + return s.eventsEnabled() } // eventsEnabled will report if events are enabled. @@ -428,13 +813,12 @@ func (s *Server) eventsEnabled() bool { // TrackedRemoteServers returns how many remote servers we are tracking // from a system events perspective. func (s *Server) TrackedRemoteServers() int { - s.mu.Lock() - if !s.running || !s.eventsEnabled() { + s.mu.RLock() + defer s.mu.RUnlock() + if !s.isRunning() || !s.eventsEnabled() { return -1 } - ns := len(s.sys.servers) - s.mu.Unlock() - return ns + return len(s.sys.servers) } // Check for orphan servers who may have gone away without notification. @@ -446,7 +830,6 @@ func (s *Server) checkRemoteServers() { s.Debugf("Detected orphan remote server: %q", sid) // Simulate it going away. s.processRemoteServerShutdown(sid) - delete(s.sys.servers, sid) } } if s.sys.sweeper != nil { @@ -455,13 +838,15 @@ func (s *Server) checkRemoteServers() { } // Grab RSS and PCPU -func updateServerUsage(v *ServerStats) { - var rss, vss int64 - var pcpu float64 - pse.ProcUsage(&pcpu, &rss, &vss) - v.Mem = rss - v.CPU = pcpu - v.Cores = numCores +// Server lock will be held but released. +func (s *Server) updateServerUsage(v *ServerStats) { + var vss int64 + pse.ProcUsage(&v.CPU, &v.Mem, &vss) + v.Cores = runtime.NumCPU() + v.MaxProcs = runtime.GOMAXPROCS(-1) + if mm := debug.SetMemoryLimit(-1); mm < math.MaxInt64 { + v.MemLimit = mm + } } // Generate a route stat for our statz update. @@ -470,15 +855,21 @@ func routeStat(r *client) *RouteStat { return nil } r.mu.Lock() + // Note: *client.out[Msgs|Bytes] are not set using atomics, + // unlike in[Msgs|Bytes]. rs := &RouteStat{ ID: r.cid, Sent: DataStats{ - Msgs: atomic.LoadInt64(&r.outMsgs), - Bytes: atomic.LoadInt64(&r.outBytes), + MsgBytes: MsgBytes{ + Msgs: r.outMsgs, + Bytes: r.outBytes, + }, }, Received: DataStats{ - Msgs: atomic.LoadInt64(&r.inMsgs), - Bytes: atomic.LoadInt64(&r.inBytes), + MsgBytes: MsgBytes{ + Msgs: atomic.LoadInt64(&r.inMsgs), + Bytes: atomic.LoadInt64(&r.inBytes), + }, }, Pending: int(r.out.pb), } @@ -492,8 +883,56 @@ func routeStat(r *client) *RouteStat { // Actual send method for statz updates. // Lock should be held. func (s *Server) sendStatsz(subj string) { - m := ServerStatsMsg{} - updateServerUsage(&m.Stats) + var m ServerStatsMsg + s.updateServerUsage(&m.Stats) + + if s.limitStatsz(subj) { + return + } + + s.mu.RLock() + defer s.mu.RUnlock() + + // Check that we have a system account, etc. + if s.sys == nil || s.sys.account == nil { + return + } + + shouldCheckInterest := func() bool { + opts := s.getOpts() + if opts.Cluster.Port != 0 || opts.Gateway.Port != 0 || opts.LeafNode.Port != 0 { + return false + } + // If we are here we have no clustering or gateways and are not a leafnode hub. + // Check for leafnode remotes that connect the system account. + if len(opts.LeafNode.Remotes) > 0 { + sysAcc := s.sys.account.GetName() + for _, r := range opts.LeafNode.Remotes { + if r.LocalAccount == sysAcc { + return false + } + } + } + return true + } + + // if we are running standalone, check for interest. + if shouldCheckInterest() { + // Check if we even have interest in this subject. + sacc := s.sys.account + rr := sacc.sl.Match(subj) + totalSubs := len(rr.psubs) + len(rr.qsubs) + if totalSubs == 0 { + return + } else if totalSubs == 1 && len(rr.psubs) == 1 { + // For the broadcast subject we listen to that ourselves with no echo for remote updates. + // If we are the only ones listening do not send either. + if rr.psubs[0] == s.sys.remoteStatsSub { + return + } + } + } + m.Stats.Start = s.start m.Stats.Connections = len(s.clients) m.Stats.TotalConnections = s.totalClients @@ -503,11 +942,22 @@ func (s *Server) sendStatsz(subj string) { m.Stats.Sent.Msgs = atomic.LoadInt64(&s.outMsgs) m.Stats.Sent.Bytes = atomic.LoadInt64(&s.outBytes) m.Stats.SlowConsumers = atomic.LoadInt64(&s.slowConsumers) + // Evaluate the slow consumer stats, but set it only if one of the value is not 0. + scs := &SlowConsumersStats{ + Clients: s.NumSlowConsumersClients(), + Routes: s.NumSlowConsumersRoutes(), + Gateways: s.NumSlowConsumersGateways(), + Leafs: s.NumSlowConsumersLeafs(), + } + if scs.Clients != 0 || scs.Routes != 0 || scs.Gateways != 0 || scs.Leafs != 0 { + m.Stats.SlowConsumersStats = scs + } m.Stats.NumSubs = s.numSubscriptions() - - for _, r := range s.routes { + // Routes + s.forEachRoute(func(r *client) { m.Stats.Routes = append(m.Stats.Routes, routeStat(r)) - } + }) + // Gateways if s.gateway.enabled { gw := s.gateway gw.RLock() @@ -515,9 +965,13 @@ func (s *Server) sendStatsz(subj string) { gs := &GatewayStat{Name: name} c.mu.Lock() gs.ID = c.cid + // Note that *client.out[Msgs|Bytes] are not set using atomic, + // unlike the in[Msgs|bytes]. gs.Sent = DataStats{ - Msgs: atomic.LoadInt64(&c.outMsgs), - Bytes: atomic.LoadInt64(&c.outBytes), + MsgBytes: MsgBytes{ + Msgs: c.outMsgs, + Bytes: c.outBytes, + }, } c.mu.Unlock() // Gather matching inbound connections @@ -535,21 +989,126 @@ func (s *Server) sendStatsz(subj string) { } gw.RUnlock() } + // Active Servers + m.Stats.ActiveServers = len(s.sys.servers) + 1 + + // JetStream + if js := s.js.Load(); js != nil { + jStat := &JetStreamVarz{} + s.mu.RUnlock() + js.mu.RLock() + c := js.config + c.StoreDir = _EMPTY_ + jStat.Config = &c + js.mu.RUnlock() + jStat.Stats = js.usageStats() + // Update our own usage since we do not echo so we will not hear ourselves. + ourNode := getHash(s.serverName()) + if v, ok := s.nodeToInfo.Load(ourNode); ok && v != nil { + ni := v.(nodeInfo) + ni.stats = jStat.Stats + ni.cfg = jStat.Config + s.optsMu.RLock() + ni.tags = copyStrings(s.opts.Tags) + s.optsMu.RUnlock() + s.nodeToInfo.Store(ourNode, ni) + } + // Metagroup info. + if mg := js.getMetaGroup(); mg != nil { + if mg.Leader() { + if ci := s.raftNodeToClusterInfo(mg); ci != nil { + jStat.Meta = &MetaClusterInfo{ + Name: ci.Name, + Leader: ci.Leader, + Peer: getHash(ci.Leader), + Replicas: ci.Replicas, + Size: mg.ClusterSize(), + } + } + } else { + // non leader only include a shortened version without peers + leader := s.serverNameForNode(mg.GroupLeader()) + jStat.Meta = &MetaClusterInfo{ + Name: mg.Group(), + Leader: leader, + Peer: getHash(leader), + Size: mg.ClusterSize(), + } + } + if ipq := s.jsAPIRoutedReqs; ipq != nil && jStat.Meta != nil { + jStat.Meta.Pending = ipq.len() + } + } + jStat.Limits = &s.getOpts().JetStreamLimits + m.Stats.JetStream = jStat + s.mu.RLock() + } + // Send message. s.sendInternalMsg(subj, _EMPTY_, &m.Server, &m) } +// Limit updates to the heartbeat interval, max one second by default. +func (s *Server) limitStatsz(subj string) bool { + s.mu.Lock() + defer s.mu.Unlock() + + if s.sys == nil { + return true + } + + // Only limit the normal broadcast subject. + if subj != fmt.Sprintf(serverStatsSubj, s.ID()) { + return false + } + + interval := statszRateLimit + if s.sys.cstatsz < interval { + interval = s.sys.cstatsz + } + if time.Since(s.sys.lastStatsz) < interval { + // Reschedule heartbeat for the next interval. + if s.sys.stmr != nil { + s.sys.stmr.Reset(time.Until(s.sys.lastStatsz.Add(interval))) + } + return true + } + s.sys.lastStatsz = time.Now() + return false +} + // Send out our statz update. // This should be wrapChk() to setup common locking. func (s *Server) heartbeatStatsz() { if s.sys.stmr != nil { - s.sys.stmr.Reset(s.sys.statsz) + // Increase after startup to our max. + if s.sys.cstatsz < s.sys.statsz { + s.sys.cstatsz *= 2 + if s.sys.cstatsz > s.sys.statsz { + s.sys.cstatsz = s.sys.statsz + } + } + s.sys.stmr.Reset(s.sys.cstatsz) } - s.sendStatsz(fmt.Sprintf(serverStatsSubj, s.info.ID)) + // Do in separate Go routine. + go s.sendStatszUpdate() +} + +// Reset statsz rate limit for the next broadcast. +// This should be wrapChk() to setup common locking. +func (s *Server) resetLastStatsz() { + s.sys.lastStatsz = time.Time{} +} + +func (s *Server) sendStatszUpdate() { + s.sendStatsz(fmt.Sprintf(serverStatsSubj, s.ID())) } // This should be wrapChk() to setup common locking. func (s *Server) startStatszTimer() { - s.sys.stmr = time.AfterFunc(s.sys.statsz, s.wrapChk(s.heartbeatStatsz)) + // We will start by sending out more of these and trail off to the statsz being the max. + s.sys.cstatsz = 250 * time.Millisecond + // Send out the first one quickly, we will slowly back off. + s.sys.stmr = time.AfterFunc(s.sys.cstatsz, s.wrapChk(s.heartbeatStatsz)) } // Start a ticker that will fire periodically and check for orphaned servers. @@ -559,7 +1118,33 @@ func (s *Server) startRemoteServerSweepTimer() { } // Length of our system hash used for server targeted messages. -const sysHashLen = 6 +const sysHashLen = 8 + +// Computes a hash of 8 characters for the name. +func getHash(name string) string { + return getHashSize(name, sysHashLen) +} + +// Computes a hash for the given `name`. The result will be `size` characters long. +func getHashSize(name string, size int) string { + sha := sha256.New() + sha.Write([]byte(name)) + b := sha.Sum(nil) + for i := 0; i < size; i++ { + b[i] = digits[int(b[i]%base)] + } + return string(b[:size]) +} + +// Returns the node name for this server which is a hash of the server name. +func (s *Server) Node() string { + s.mu.RLock() + defer s.mu.RUnlock() + if s.sys != nil { + return s.sys.shash + } + return _EMPTY_ +} // This will setup our system wide tracking subs. // For now we will setup one wildcard subscription to @@ -568,38 +1153,64 @@ const sysHashLen = 6 // Tradeoff is subscription and interest graph events vs connect and // disconnect events, etc. func (s *Server) initEventTracking() { - if !s.EventsEnabled() { + // Capture sys in case we are shutdown while setting up. + s.mu.RLock() + sys := s.sys + s.mu.RUnlock() + + if sys == nil || sys.client == nil || sys.account == nil { return } // Create a system hash which we use for other servers to target us specifically. - sha := sha256.New() - sha.Write([]byte(s.info.ID)) - s.sys.shash = base64.RawURLEncoding.EncodeToString(sha.Sum(nil))[:sysHashLen] + sys.shash = getHash(s.info.Name) // This will be for all inbox responses. - subject := fmt.Sprintf(inboxRespSubj, s.sys.shash, "*") + subject := fmt.Sprintf(inboxRespSubj, sys.shash, "*") if _, err := s.sysSubscribe(subject, s.inboxReply); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } - s.sys.inboxPre = subject + sys.inboxPre = subject // This is for remote updates for connection accounting. subject = fmt.Sprintf(accConnsEventSubjOld, "*") - if _, err := s.sysSubscribe(subject, s.remoteConnsUpdate); err != nil { + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteConnsUpdate)); err != nil { s.Errorf("Error setting up internal tracking for %s: %v", subject, err) + return } // This will be for responses for account info that we send out. subject = fmt.Sprintf(connsRespSubj, s.info.ID) - if _, err := s.sysSubscribe(subject, s.remoteConnsUpdate); err != nil { + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteConnsUpdate)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } // Listen for broad requests to respond with number of subscriptions for a given subject. - if _, err := s.sysSubscribe(accNumSubsReqSubj, s.nsubsRequest); err != nil { + if _, err := s.sysSubscribe(accNumSubsReqSubj, s.noInlineCallback(s.nsubsRequest)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return + } + // Listen for statsz from others. + subject = fmt.Sprintf(serverStatsSubj, "*") + if sub, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteServerUpdate)); err != nil { + s.Errorf("Error setting up internal tracking: %v", err) + return + } else { + // Keep track of this one. + sys.remoteStatsSub = sub } + // Listen for all server shutdowns. subject = fmt.Sprintf(shutdownEventSubj, "*") - if _, err := s.sysSubscribe(subject, s.remoteServerShutdown); err != nil { + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteServerShutdown)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return + } + // Listen for servers entering lame-duck mode. + // NOTE: This currently is handled in the same way as a server shutdown, but has + // a different subject in case we need to handle differently in future. + subject = fmt.Sprintf(lameDuckEventSubj, "*") + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteServerShutdown)); err != nil { + s.Errorf("Error setting up internal tracking: %v", err) + return } // Listen for account claims updates. subscribeToUpdate := true @@ -608,68 +1219,116 @@ func (s *Server) initEventTracking() { } if subscribeToUpdate { for _, sub := range []string{accUpdateEventSubjOld, accUpdateEventSubjNew} { - if _, err := s.sysSubscribe(fmt.Sprintf(sub, "*"), s.accountClaimUpdate); err != nil { + if _, err := s.sysSubscribe(fmt.Sprintf(sub, "*"), s.noInlineCallback(s.accountClaimUpdate)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } } } // Listen for ping messages that will be sent to all servers for statsz. // This subscription is kept for backwards compatibility. Got replaced by ...PING.STATZ from below - if _, err := s.sysSubscribe(serverStatsPingReqSubj, s.statszReq); err != nil { + if _, err := s.sysSubscribe(serverStatsPingReqSubj, s.noInlineCallbackStatsz(s.statszReq)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } - monSrvc := map[string]msgHandler{ + monSrvc := map[string]sysMsgHandler{ + "IDZ": s.idzReq, "STATSZ": s.statszReq, - "VARZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "VARZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &VarzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Varz(&optz.VarzOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Varz(&optz.VarzOptions) }) }, - "SUBSZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "SUBSZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &SubszEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Subsz(&optz.SubszOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Subsz(&optz.SubszOptions) }) }, - "CONNZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "CONNZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &ConnzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Connz(&optz.ConnzOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Connz(&optz.ConnzOptions) }) }, - "ROUTEZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "ROUTEZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &RoutezEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Routez(&optz.RoutezOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Routez(&optz.RoutezOptions) }) }, - "GATEWAYZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "GATEWAYZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &GatewayzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Gatewayz(&optz.GatewayzOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Gatewayz(&optz.GatewayzOptions) }) }, - "LEAFZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "LEAFZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &LeafzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Leafz(&optz.LeafzOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Leafz(&optz.LeafzOptions) }) }, - "ACCOUNTZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "ACCOUNTZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &AccountzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Accountz(&optz.AccountzOptions) }) + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Accountz(&optz.AccountzOptions) }) + }, + "JSZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &JszEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Jsz(&optz.JSzOptions) }) + }, + "HEALTHZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &HealthzEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.healthz(&optz.HealthzOptions), nil }) + }, + "PROFILEZ": nil, // Special case, see below + "EXPVARZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &ExpvarzEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.expvarz(optz), nil }) }, + "IPQUEUESZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &IpqueueszEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Ipqueuesz(&optz.IpqueueszOptions), nil }) + }, + "RAFTZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &RaftzEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { return s.Raftz(&optz.RaftzOptions), nil }) + }, + } + profilez := func(_ *subscription, c *client, _ *Account, _, rply string, rmsg []byte) { + hdr, msg := c.msgParts(rmsg) + // Need to copy since we are passing those to the go routine below. + hdr, msg = copyBytes(hdr), copyBytes(msg) + // Execute in its own go routine because CPU profiling, for instance, + // could take several seconds to complete. + go func() { + optz := &ProfilezEventOptions{} + s.zReq(c, rply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { + return s.profilez(&optz.ProfilezOptions), nil + }) + }() } for name, req := range monSrvc { + var h msgHandler + switch name { + case "PROFILEZ": + h = profilez + case "STATSZ": + h = s.noInlineCallbackStatsz(req) + default: + h = s.noInlineCallback(req) + } subject = fmt.Sprintf(serverDirectReqSubj, s.info.ID, name) - if _, err := s.sysSubscribe(subject, req); err != nil { + if _, err := s.sysSubscribe(subject, h); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } subject = fmt.Sprintf(serverPingReqSubj, name) - if _, err := s.sysSubscribe(subject, req); err != nil { + if _, err := s.sysSubscribe(subject, h); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } } extractAccount := func(subject string) (string, error) { if tk := strings.Split(subject, tsep); len(tk) != accReqTokens { - return "", fmt.Errorf("subject %q is malformed", subject) + return _EMPTY_, fmt.Errorf("subject %q is malformed", subject) } else { return tk[accReqAccIndex], nil } } - monAccSrvc := map[string]msgHandler{ - "SUBSZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + monAccSrvc := map[string]sysMsgHandler{ + "SUBSZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &SubszEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { if acc, err := extractAccount(subject); err != nil { return nil, err } else { @@ -679,9 +1338,9 @@ func (s *Server) initEventTracking() { } }) }, - "CONNZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "CONNZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &ConnzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { if acc, err := extractAccount(subject); err != nil { return nil, err } else { @@ -690,9 +1349,9 @@ func (s *Server) initEventTracking() { } }) }, - "LEAFZ": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "LEAFZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &LeafzEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { if acc, err := extractAccount(subject); err != nil { return nil, err } else { @@ -701,9 +1360,20 @@ func (s *Server) initEventTracking() { } }) }, - "INFO": func(sub *subscription, _ *client, subject, reply string, msg []byte) { + "JSZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &JszEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { + if acc, err := extractAccount(subject); err != nil { + return nil, err + } else { + optz.Account = acc + return s.JszAccount(&optz.JSzOptions) + } + }) + }, + "INFO": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { optz := &AccInfoEventOptions{} - s.zReq(reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { if acc, err := extractAccount(subject); err != nil { return nil, err } else { @@ -711,28 +1381,157 @@ func (s *Server) initEventTracking() { } }) }, + // STATZ is essentially a duplicate of CONNS with an envelope identical to the others. + // For historical reasons CONNS is the odd one out. + // STATZ is also less heavy weight than INFO + "STATZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &AccountStatzEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { + if acc, err := extractAccount(subject); err != nil { + return nil, err + } else if acc == "PING" { // Filter PING subject. Happens for server as well. But wildcards are not used + return nil, errSkipZreq + } else { + optz.Accounts = []string{acc} + if stz, err := s.AccountStatz(&optz.AccountStatzOptions); err != nil { + return nil, err + } else if len(stz.Accounts) == 0 && !optz.IncludeUnused { + return nil, errSkipZreq + } else { + return stz, nil + } + } + }) + }, "CONNS": s.connsRequest, } for name, req := range monAccSrvc { - if _, err := s.sysSubscribe(fmt.Sprintf(accReqSubj, "*", name), req); err != nil { + if _, err := s.sysSubscribe(fmt.Sprintf(accDirectReqSubj, "*", name), s.noInlineCallback(req)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } } + // User info. Do not propagate interest so that we know the local server to the connection + // is the only one that will answer the requests. + if _, err := s.sysSubscribeInternal(fmt.Sprintf(userDirectReqSubj, "*"), s.userInfoReq); err != nil { + s.Errorf("Error setting up internal tracking: %v", err) + return + } + + // For now only the STATZ subject has an account specific ping equivalent. + if _, err := s.sysSubscribe(fmt.Sprintf(accPingReqSubj, "STATZ"), + s.noInlineCallback(func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + optz := &AccountStatzEventOptions{} + s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) { + if stz, err := s.AccountStatz(&optz.AccountStatzOptions); err != nil { + return nil, err + } else if len(stz.Accounts) == 0 && !optz.IncludeUnused { + return nil, errSkipZreq + } else { + return stz, nil + } + }) + })); err != nil { + s.Errorf("Error setting up internal tracking: %v", err) + return + } + // Listen for updates when leaf nodes connect for a given account. This will // force any gateway connections to move to `modeInterestOnly` subject = fmt.Sprintf(leafNodeConnectEventSubj, "*") - if _, err := s.sysSubscribe(subject, s.leafNodeConnected); err != nil { + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.leafNodeConnected)); err != nil { s.Errorf("Error setting up internal tracking: %v", err) + return } // For tracking remote latency measurements. - subject = fmt.Sprintf(remoteLatencyEventSubj, s.sys.shash) - if _, err := s.sysSubscribe(subject, s.remoteLatencyUpdate); err != nil { + subject = fmt.Sprintf(remoteLatencyEventSubj, sys.shash) + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.remoteLatencyUpdate)); err != nil { s.Errorf("Error setting up internal latency tracking: %v", err) + return } // This is for simple debugging of number of subscribers that exist in the system. - if _, err := s.sysSubscribeInternal(accSubsSubj, s.debugSubscribers); err != nil { + if _, err := s.sysSubscribeInternal(accSubsSubj, s.noInlineCallback(s.debugSubscribers)); err != nil { s.Errorf("Error setting up internal debug service for subscribers: %v", err) + return + } + + // Listen for requests to reload the server configuration. + subject = fmt.Sprintf(serverReloadReqSubj, s.info.ID) + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.reloadConfig)); err != nil { + s.Errorf("Error setting up server reload handler: %v", err) + return + } + + // Client connection kick + subject = fmt.Sprintf(clientKickReqSubj, s.info.ID) + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.kickClient)); err != nil { + s.Errorf("Error setting up client kick service: %v", err) + return + } + // Client connection LDM + subject = fmt.Sprintf(clientLDMReqSubj, s.info.ID) + if _, err := s.sysSubscribe(subject, s.noInlineCallback(s.ldmClient)); err != nil { + s.Errorf("Error setting up client LDM service: %v", err) + return + } +} + +// UserInfo returns basic information to a user about bound account and user permissions. +// For account information they will need to ping that separately, and this allows security +// controls on each subsystem if desired, e.g. account info, jetstream account info, etc. +type UserInfo struct { + UserID string `json:"user"` + Account string `json:"account"` + Permissions *Permissions `json:"permissions,omitempty"` + Expires time.Duration `json:"expires,omitempty"` +} + +// Process a user info request. +func (s *Server) userInfoReq(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + if !s.EventsEnabled() || reply == _EMPTY_ { + return + } + + response := &ServerAPIResponse{Server: &ServerInfo{}} + + ci, _, _, _, err := s.getRequestInfo(c, msg) + if err != nil { + response.Error = &ApiError{Code: http.StatusBadRequest} + s.sendInternalResponse(reply, response) + return + } + + response.Data = &UserInfo{ + UserID: ci.User, + Account: ci.Account, + Permissions: c.publicPermissions(), + Expires: c.claimExpiration(), + } + s.sendInternalResponse(reply, response) +} + +// register existing accounts with any system exports. +func (s *Server) registerSystemImportsForExisting() { + var accounts []*Account + + s.mu.RLock() + if s.sys == nil { + s.mu.RUnlock() + return + } + sacc := s.sys.account + s.accounts.Range(func(k, v any) bool { + a := v.(*Account) + if a != sacc { + accounts = append(accounts, a) + } + return true + }) + s.mu.RUnlock() + + for _, a := range accounts { + s.registerSystemImports(a) } } @@ -741,17 +1540,59 @@ func (s *Server) addSystemAccountExports(sacc *Account) { if !s.EventsEnabled() { return } - if err := sacc.AddServiceExport(accSubsSubj, nil); err != nil { - s.Errorf("Error adding system service export for %q: %v", accSubsSubj, err) + accConnzSubj := fmt.Sprintf(accDirectReqSubj, "*", "CONNZ") + // prioritize not automatically added exports + if !sacc.hasServiceExportMatching(accConnzSubj) { + // pick export type that clamps importing account id into subject + if err := sacc.addServiceExportWithResponseAndAccountPos(accConnzSubj, Streamed, nil, 4); err != nil { + //if err := sacc.AddServiceExportWithResponse(accConnzSubj, Streamed, nil); err != nil { + s.Errorf("Error adding system service export for %q: %v", accConnzSubj, err) + } + } + // prioritize not automatically added exports + accStatzSubj := fmt.Sprintf(accDirectReqSubj, "*", "STATZ") + if !sacc.hasServiceExportMatching(accStatzSubj) { + // pick export type that clamps importing account id into subject + if err := sacc.addServiceExportWithResponseAndAccountPos(accStatzSubj, Streamed, nil, 4); err != nil { + s.Errorf("Error adding system service export for %q: %v", accStatzSubj, err) + } + } + // FIXME(dlc) - Old experiment, Remove? + if !sacc.hasServiceExportMatching(accSubsSubj) { + if err := sacc.AddServiceExport(accSubsSubj, nil); err != nil { + s.Errorf("Error adding system service export for %q: %v", accSubsSubj, err) + } + } + + // User info export. + userInfoSubj := fmt.Sprintf(userDirectReqSubj, "*") + if !sacc.hasServiceExportMatching(userInfoSubj) { + if err := sacc.AddServiceExport(userInfoSubj, nil); err != nil { + s.Errorf("Error adding system service export for %q: %v", userInfoSubj, err) + } + mappedSubj := fmt.Sprintf(userDirectReqSubj, sacc.GetName()) + if err := sacc.AddServiceImport(sacc, userDirectInfoSubj, mappedSubj); err != nil { + s.Errorf("Error setting up system service import %s: %v", mappedSubj, err) + } + // Make sure to share details. + sacc.setServiceImportSharing(sacc, mappedSubj, false, true) + } + + // Register any accounts that existed prior. + s.registerSystemImportsForExisting() + + // in case of a mixed mode setup, enable js exports anyway + if s.JetStreamEnabled() || !s.standAloneMode() { + s.checkJetStreamExports() } } // accountClaimUpdate will receive claim updates for accounts. -func (s *Server) accountClaimUpdate(sub *subscription, _ *client, subject, resp string, msg []byte) { +func (s *Server) accountClaimUpdate(sub *subscription, c *client, _ *Account, subject, resp string, hdr, msg []byte) { if !s.EventsEnabled() { return } - pubKey := "" + var pubKey string toks := strings.Split(subject, tsep) if len(toks) == accUpdateTokensNew { pubKey = toks[accReqAccIndex] @@ -761,7 +1602,10 @@ func (s *Server) accountClaimUpdate(sub *subscription, _ *client, subject, resp s.Debugf("Received account claims update on bad subject %q", subject) return } - if claim, err := jwt.DecodeAccountClaims(string(msg)); err != nil { + if len(msg) == 0 { + err := errors.New("request body is empty") + respondToUpdate(s, resp, pubKey, "jwt update error", err) + } else if claim, err := jwt.DecodeAccountClaims(string(msg)); err != nil { respondToUpdate(s, resp, pubKey, "jwt update resulted in error", err) } else if claim.Subject != pubKey { err := errors.New("subject does not match jwt content") @@ -779,14 +1623,29 @@ func (s *Server) accountClaimUpdate(sub *subscription, _ *client, subject, resp // Will update the remote count for clients. // Lock assume held. func (s *Server) processRemoteServerShutdown(sid string) { - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { v.(*Account).removeRemoteServer(sid) return true }) + // Update any state in nodeInfo. + s.nodeToInfo.Range(func(k, v any) bool { + ni := v.(nodeInfo) + if ni.id == sid { + ni.offline = true + s.nodeToInfo.Store(k, ni) + return false + } + return true + }) + delete(s.sys.servers, sid) } -// remoteServerShutdownEvent is called when we get an event from another server shutting down. -func (s *Server) remoteServerShutdown(sub *subscription, _ *client, subject, reply string, msg []byte) { +func (s *Server) sameDomain(domain string) bool { + return domain == _EMPTY_ || s.info.Domain == _EMPTY_ || domain == s.info.Domain +} + +// remoteServerShutdown is called when we get an event from another server shutting down. +func (s *Server) remoteServerShutdown(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { s.mu.Lock() defer s.mu.Unlock() if !s.eventsEnabled() { @@ -797,39 +1656,160 @@ func (s *Server) remoteServerShutdown(sub *subscription, _ *client, subject, rep s.Debugf("Received remote server shutdown on bad subject %q", subject) return } + + if len(msg) == 0 { + s.Errorf("Remote server sent invalid (empty) shutdown message to %q", subject) + return + } + + // We have an optional serverInfo here, remove from nodeToX lookups. + var si ServerInfo + if err := json.Unmarshal(msg, &si); err != nil { + s.Debugf("Received bad server info for remote server shutdown") + return + } + + // JetStream node updates if applicable. + node := getHash(si.Name) + if v, ok := s.nodeToInfo.Load(node); ok && v != nil { + ni := v.(nodeInfo) + ni.offline = true + s.nodeToInfo.Store(node, ni) + } + sid := toks[serverSubjectIndex] - su := s.sys.servers[sid] - if su != nil { + if su := s.sys.servers[sid]; su != nil { s.processRemoteServerShutdown(sid) } } +// remoteServerUpdate listens for statsz updates from other servers. +func (s *Server) remoteServerUpdate(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + var ssm ServerStatsMsg + if len(msg) == 0 { + s.Debugf("Received empty server info for remote server update") + return + } else if err := json.Unmarshal(msg, &ssm); err != nil { + s.Debugf("Received bad server info for remote server update") + return + } + si := ssm.Server + + // Should do normal updates before bailing if wrong domain. + s.mu.Lock() + if s.isRunning() && s.eventsEnabled() && ssm.Server.ID != s.info.ID { + s.updateRemoteServer(&si) + } + s.mu.Unlock() + + // JetStream node updates. + if !s.sameDomain(si.Domain) { + return + } + + var cfg *JetStreamConfig + var stats *JetStreamStats + + if ssm.Stats.JetStream != nil { + cfg = ssm.Stats.JetStream.Config + stats = ssm.Stats.JetStream.Stats + } + + node := getHash(si.Name) + accountNRG := si.AccountNRG() + oldInfo, _ := s.nodeToInfo.Swap(node, nodeInfo{ + name: si.Name, + version: si.Version, + cluster: si.Cluster, + domain: si.Domain, + id: si.ID, + tags: si.Tags, + cfg: cfg, + stats: stats, + offline: false, + js: si.JetStreamEnabled(), + binarySnapshots: si.BinaryStreamSnapshot(), + accountNRG: accountNRG, + }) + if oldInfo == nil || accountNRG != oldInfo.(nodeInfo).accountNRG { + // One of the servers we received statsz from changed its mind about + // whether or not it supports in-account NRG, so update the groups + // with this information. + s.updateNRGAccountStatus() + } +} + // updateRemoteServer is called when we have an update from a remote server. // This allows us to track remote servers, respond to shutdown messages properly, // make sure that messages are ordered, and allow us to prune dead servers. // Lock should be held upon entry. -func (s *Server) updateRemoteServer(ms *ServerInfo) { - su := s.sys.servers[ms.ID] +func (s *Server) updateRemoteServer(si *ServerInfo) { + su := s.sys.servers[si.ID] if su == nil { - s.sys.servers[ms.ID] = &serverUpdate{ms.Seq, time.Now()} - s.processNewServer(ms) + s.sys.servers[si.ID] = &serverUpdate{si.Seq, time.Now()} + s.processNewServer(si) } else { // Should always be going up. - if ms.Seq <= su.seq { - s.Errorf("Received out of order remote server update from: %q", ms.ID) + if si.Seq <= su.seq { + s.Errorf("Received out of order remote server update from: %q", si.ID) return } - su.seq = ms.Seq + su.seq = si.Seq su.ltime = time.Now() } } // processNewServer will hold any logic we want to use when we discover a new server. // Lock should be held upon entry. -func (s *Server) processNewServer(ms *ServerInfo) { +func (s *Server) processNewServer(si *ServerInfo) { // Right now we only check if we have leafnode servers and if so send another // connect update to make sure they switch this account to interest only mode. s.ensureGWsInterestOnlyForLeafNodes() + + // Add to our nodeToName + if s.sameDomain(si.Domain) { + node := getHash(si.Name) + // Only update if non-existent + if _, ok := s.nodeToInfo.Load(node); !ok { + s.nodeToInfo.Store(node, nodeInfo{ + name: si.Name, + version: si.Version, + cluster: si.Cluster, + domain: si.Domain, + id: si.ID, + tags: si.Tags, + cfg: nil, + stats: nil, + offline: false, + js: si.JetStreamEnabled(), + binarySnapshots: si.BinaryStreamSnapshot(), + accountNRG: si.AccountNRG(), + }) + } + } + go s.updateNRGAccountStatus() + // Announce ourselves.. + // Do this in a separate Go routine. + go s.sendStatszUpdate() +} + +// Works out whether all nodes support moving the NRG traffic into +// the account and moves it appropriately. +// Server lock MUST NOT be held on entry. +func (s *Server) updateNRGAccountStatus() { + s.rnMu.RLock() + raftNodes := make([]RaftNode, 0, len(s.raftNodes)) + for _, n := range s.raftNodes { + raftNodes = append(raftNodes, n) + } + s.rnMu.RUnlock() + for _, n := range raftNodes { + // In the event that the node is happy that all nodes that + // it cares about haven't changed, this will be a no-op. + if err := n.RecreateInternalSubs(); err != nil { + n.Stop() + } + } } // If GW is enabled on this server and there are any leaf node connections, @@ -860,28 +1840,33 @@ func (s *Server) shutdownEventing() { s.mu.Lock() clearTimer(&s.sys.sweeper) clearTimer(&s.sys.stmr) + rc := s.sys.resetCh + s.sys.resetCh = nil + wg := &s.sys.wg s.mu.Unlock() // We will queue up a shutdown event and wait for the // internal send loop to exit. s.sendShutdownEvent() - s.sys.wg.Wait() - close(s.sys.resetCh) + wg.Wait() s.mu.Lock() defer s.mu.Unlock() // Whip through all accounts. - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { v.(*Account).clearEventing() return true }) // Turn everything off here. s.sys = nil + // Make sure this is done after s.sys = nil, so that we don't + // get sends to closed channels on badly-timed config reloads. + close(rc) } // Request for our local connection count. -func (s *Server) connsRequest(sub *subscription, _ *client, subject, reply string, msg []byte) { +func (s *Server) connsRequest(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { if !s.eventsRunning() { return } @@ -892,9 +1877,11 @@ func (s *Server) connsRequest(sub *subscription, _ *client, subject, reply strin } a := tk[accReqAccIndex] m := accNumConnsReq{Account: a} - if err := json.Unmarshal(msg, &m); err != nil { - s.sys.client.Errorf("Error unmarshalling account connections request message: %v", err) - return + if len(msg) > 0 { + if err := json.Unmarshal(msg, &m); err != nil { + s.sys.client.Errorf("Error unmarshalling account connections request message: %v", err) + return + } } if m.Account != a { s.sys.client.Errorf("Error unmarshalled account does not match subject") @@ -918,16 +1905,16 @@ func (s *Server) connsRequest(sub *subscription, _ *client, subject, reply strin } // leafNodeConnected is an event we will receive when a leaf node for a given account connects. -func (s *Server) leafNodeConnected(sub *subscription, _ *client, subject, reply string, msg []byte) { +func (s *Server) leafNodeConnected(sub *subscription, _ *client, _ *Account, subject, reply string, hdr, msg []byte) { m := accNumConnsReq{} if err := json.Unmarshal(msg, &m); err != nil { s.sys.client.Errorf("Error unmarshalling account connections request message: %v", err) return } - s.mu.Lock() - na := m.Account == "" || !s.eventsEnabled() || !s.gateway.enabled - s.mu.Unlock() + s.mu.RLock() + na := m.Account == _EMPTY_ || !s.eventsEnabled() || !s.gateway.enabled + s.mu.RUnlock() if na { return @@ -940,9 +1927,11 @@ func (s *Server) leafNodeConnected(sub *subscription, _ *client, subject, reply // Common filter options for system requests STATSZ VARZ SUBSZ CONNZ ROUTEZ GATEWAYZ LEAFZ type EventFilterOptions struct { - Name string `json:"server_name,omitempty"` // filter by server name - Cluster string `json:"cluster,omitempty"` // filter by cluster name - Host string `json:"host,omitempty"` // filter by host name + Name string `json:"server_name,omitempty"` // filter by server name + Cluster string `json:"cluster,omitempty"` // filter by cluster name + Host string `json:"host,omitempty"` // filter by host name + Tags []string `json:"tags,omitempty"` // filter by tags (must match all tags) + Domain string `json:"domain,omitempty"` // filter by JS domain } // StatszEventOptions are options passed to Statsz @@ -981,75 +1970,269 @@ type VarzEventOptions struct { EventFilterOptions } -// In the context of system events, GatewayzEventOptions are options passed to Gatewayz -type GatewayzEventOptions struct { - GatewayzOptions - EventFilterOptions +// In the context of system events, GatewayzEventOptions are options passed to Gatewayz +type GatewayzEventOptions struct { + GatewayzOptions + EventFilterOptions +} + +// In the context of system events, LeafzEventOptions are options passed to Leafz +type LeafzEventOptions struct { + LeafzOptions + EventFilterOptions +} + +// In the context of system events, AccountzEventOptions are options passed to Accountz +type AccountzEventOptions struct { + AccountzOptions + EventFilterOptions +} + +// In the context of system events, AccountzEventOptions are options passed to Accountz +type AccountStatzEventOptions struct { + AccountStatzOptions + EventFilterOptions +} + +// In the context of system events, JszEventOptions are options passed to Jsz +type JszEventOptions struct { + JSzOptions + EventFilterOptions +} + +// In the context of system events, HealthzEventOptions are options passed to Healthz +type HealthzEventOptions struct { + HealthzOptions + EventFilterOptions +} + +// In the context of system events, ProfilezEventOptions are options passed to Profilez +type ProfilezEventOptions struct { + ProfilezOptions + EventFilterOptions +} + +// In the context of system events, ExpvarzEventOptions are options passed to Expvarz +type ExpvarzEventOptions struct { + EventFilterOptions +} + +// In the context of system events, IpqueueszEventOptions are options passed to Ipqueuesz +type IpqueueszEventOptions struct { + EventFilterOptions + IpqueueszOptions +} + +// In the context of system events, RaftzEventOptions are options passed to Raftz +type RaftzEventOptions struct { + EventFilterOptions + RaftzOptions +} + +// returns true if the request does NOT apply to this server and can be ignored. +// DO NOT hold the server lock when +func (s *Server) filterRequest(fOpts *EventFilterOptions) bool { + if fOpts.Name != _EMPTY_ && !strings.Contains(s.info.Name, fOpts.Name) { + return true + } + if fOpts.Host != _EMPTY_ && !strings.Contains(s.info.Host, fOpts.Host) { + return true + } + if fOpts.Cluster != _EMPTY_ { + if !strings.Contains(s.ClusterName(), fOpts.Cluster) { + return true + } + } + if len(fOpts.Tags) > 0 { + opts := s.getOpts() + for _, t := range fOpts.Tags { + if !opts.Tags.Contains(t) { + return true + } + } + } + if fOpts.Domain != _EMPTY_ && s.getOpts().JetStreamDomain != fOpts.Domain { + return true + } + return false +} + +// Encoding support (compression) +type compressionType int8 + +const ( + noCompression = compressionType(iota) + gzipCompression + snappyCompression + unsupportedCompression +) + +// ServerAPIResponse is the response type for the server API like varz, connz etc. +type ServerAPIResponse struct { + Server *ServerInfo `json:"server"` + Data any `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` + + // Private to indicate compression if any. + compress compressionType +} + +// Specialized response types for unmarshalling. These structures are not +// used in the server code and only there for users of the Z endpoints to +// unmarshal the data without having to create these structs in their code + +// ServerAPIConnzResponse is the response type connz +type ServerAPIConnzResponse struct { + Server *ServerInfo `json:"server"` + Data *Connz `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPIRoutezResponse is the response type for routez +type ServerAPIRoutezResponse struct { + Server *ServerInfo `json:"server"` + Data *Routez `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPIGatewayzResponse is the response type for gatewayz +type ServerAPIGatewayzResponse struct { + Server *ServerInfo `json:"server"` + Data *Gatewayz `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPIJszResponse is the response type for jsz +type ServerAPIJszResponse struct { + Server *ServerInfo `json:"server"` + Data *JSInfo `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPIHealthzResponse is the response type for healthz +type ServerAPIHealthzResponse struct { + Server *ServerInfo `json:"server"` + Data *HealthStatus `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPIVarzResponse is the response type for varz +type ServerAPIVarzResponse struct { + Server *ServerInfo `json:"server"` + Data *Varz `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPISubszResponse is the response type for subsz +type ServerAPISubszResponse struct { + Server *ServerInfo `json:"server"` + Data *Subsz `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPILeafzResponse is the response type for leafz +type ServerAPILeafzResponse struct { + Server *ServerInfo `json:"server"` + Data *Leafz `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` +} + +// ServerAPIAccountzResponse is the response type for accountz +type ServerAPIAccountzResponse struct { + Server *ServerInfo `json:"server"` + Data *Accountz `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` } -// In the context of system events, LeafzEventOptions are options passed to Leafz -type LeafzEventOptions struct { - LeafzOptions - EventFilterOptions +// ServerAPIExpvarzResponse is the response type for expvarz +type ServerAPIExpvarzResponse struct { + Server *ServerInfo `json:"server"` + Data *ExpvarzStatus `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` } -// In the context of system events, AccountzEventOptions are options passed to Accountz -type AccountzEventOptions struct { - AccountzOptions - EventFilterOptions +// ServerAPIpqueueszResponse is the response type for ipqueuesz +type ServerAPIpqueueszResponse struct { + Server *ServerInfo `json:"server"` + Data *IpqueueszStatus `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` } -// returns true if the request does NOT apply to this server and can be ignored. -// DO NOT hold the server lock when -func (s *Server) filterRequest(fOpts *EventFilterOptions) bool { - if fOpts.Name != "" && !strings.Contains(s.info.Name, fOpts.Name) { - return true - } - if fOpts.Host != "" && !strings.Contains(s.info.Host, fOpts.Host) { - return true - } - if fOpts.Cluster != "" { - s.mu.Lock() - cluster := s.info.Cluster - s.mu.Unlock() - if !strings.Contains(cluster, fOpts.Cluster) { - return true - } - } - return false +// ServerAPIRaftzResponse is the response type for raftz +type ServerAPIRaftzResponse struct { + Server *ServerInfo `json:"server"` + Data *RaftzStatus `json:"data,omitempty"` + Error *ApiError `json:"error,omitempty"` } // statszReq is a request for us to respond with current statsz. -func (s *Server) statszReq(sub *subscription, _ *client, subject, reply string, msg []byte) { - if !s.EventsEnabled() || reply == _EMPTY_ { +func (s *Server) statszReq(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + if !s.EventsEnabled() { return } + + // No reply is a signal that we should use our normal broadcast subject. + if reply == _EMPTY_ { + reply = fmt.Sprintf(serverStatsSubj, s.info.ID) + s.wrapChk(s.resetLastStatsz) + } + opts := StatszEventOptions{} if len(msg) != 0 { if err := json.Unmarshal(msg, &opts); err != nil { - server := &ServerInfo{} - response := map[string]interface{}{"server": server} - response["error"] = map[string]interface{}{ - "code": http.StatusBadRequest, - "description": err.Error(), + response := &ServerAPIResponse{ + Server: &ServerInfo{}, + Error: &ApiError{Code: http.StatusBadRequest, Description: err.Error()}, } - s.sendInternalMsgLocked(reply, _EMPTY_, server, response) + s.sendInternalMsgLocked(reply, _EMPTY_, response.Server, response) return } else if ignore := s.filterRequest(&opts.EventFilterOptions); ignore { return } } - s.mu.Lock() s.sendStatsz(reply) - s.mu.Unlock() } -func (s *Server) zReq(reply string, msg []byte, fOpts *EventFilterOptions, optz interface{}, respf func() (interface{}, error)) { +// idzReq is for a request for basic static server info. +// Try to not hold the write lock or dynamically create data. +func (s *Server) idzReq(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + s.mu.RLock() + defer s.mu.RUnlock() + id := &ServerID{ + Name: s.info.Name, + Host: s.info.Host, + ID: s.info.ID, + } + s.sendInternalMsg(reply, _EMPTY_, nil, &id) +} + +var errSkipZreq = errors.New("filtered response") + +const ( + acceptEncodingHeader = "Accept-Encoding" + contentEncodingHeader = "Content-Encoding" +) + +// This is not as formal as it could be. We see if anything has s2 or snappy first, then gzip. +func getAcceptEncoding(hdr []byte) compressionType { + ae := strings.ToLower(string(getHeader(acceptEncodingHeader, hdr))) + if ae == _EMPTY_ { + return noCompression + } + if strings.Contains(ae, "snappy") || strings.Contains(ae, "s2") { + return snappyCompression + } + if strings.Contains(ae, "gzip") { + return gzipCompression + } + return unsupportedCompression +} + +func (s *Server) zReq(_ *client, reply string, hdr, msg []byte, fOpts *EventFilterOptions, optz any, respf func() (any, error)) { if !s.EventsEnabled() || reply == _EMPTY_ { return } - server := &ServerInfo{} - response := map[string]interface{}{"server": server} + response := &ServerAPIResponse{Server: &ServerInfo{}} var err error status := 0 if len(msg) != 0 { @@ -1060,25 +2243,31 @@ func (s *Server) zReq(reply string, msg []byte, fOpts *EventFilterOptions, optz } } if err == nil { - response["data"], err = respf() - status = http.StatusInternalServerError + response.Data, err = respf() + if errors.Is(err, errSkipZreq) { + return + } else if err != nil { + status = http.StatusInternalServerError + } } if err != nil { - response["error"] = map[string]interface{}{ - "code": status, - "description": err.Error(), - } + response.Error = &ApiError{Code: status, Description: err.Error()} + } else if len(hdr) > 0 { + response.compress = getAcceptEncoding(hdr) } - s.sendInternalMsgLocked(reply, _EMPTY_, server, response) + s.sendInternalResponse(reply, response) } // remoteConnsUpdate gets called when we receive a remote update from another server. -func (s *Server) remoteConnsUpdate(sub *subscription, _ *client, subject, reply string, msg []byte) { +func (s *Server) remoteConnsUpdate(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { if !s.eventsRunning() { return } - m := AccountNumConns{} - if err := json.Unmarshal(msg, &m); err != nil { + var m AccountNumConns + if len(msg) == 0 { + s.sys.client.Errorf("No message body provided") + return + } else if err := json.Unmarshal(msg, &m); err != nil { s.sys.client.Errorf("Error unmarshalling account connection event message: %v", err) return } @@ -1097,7 +2286,7 @@ func (s *Server) remoteConnsUpdate(sub *subscription, _ *client, subject, reply s.mu.Lock() // check again here if we have been shutdown. - if !s.running || !s.eventsEnabled() { + if !s.isRunning() || !s.eventsEnabled() { s.mu.Unlock() return } @@ -1117,6 +2306,40 @@ func (s *Server) remoteConnsUpdate(sub *subscription, _ *client, subject, reply } } +// This will import any system level exports. +func (s *Server) registerSystemImports(a *Account) { + if a == nil || !s.EventsEnabled() { + return + } + sacc := s.SystemAccount() + if sacc == nil || sacc == a { + return + } + dstAccName := sacc.Name + // FIXME(dlc) - make a shared list between sys exports etc. + + importSrvc := func(subj, mappedSubj string) { + if !a.serviceImportExists(dstAccName, subj) { + if err := a.addServiceImportWithClaim(sacc, subj, mappedSubj, nil, true); err != nil { + s.Errorf("Error setting up system service import %s -> %s for account: %v", + subj, mappedSubj, err) + } + } + } + // Add in this to the account in 2 places. + // "$SYS.REQ.SERVER.PING.CONNZ" and "$SYS.REQ.ACCOUNT.PING.CONNZ" + mappedConnzSubj := fmt.Sprintf(accDirectReqSubj, a.Name, "CONNZ") + importSrvc(fmt.Sprintf(accPingReqSubj, "CONNZ"), mappedConnzSubj) + importSrvc(fmt.Sprintf(serverPingReqSubj, "CONNZ"), mappedConnzSubj) + importSrvc(fmt.Sprintf(accPingReqSubj, "STATZ"), fmt.Sprintf(accDirectReqSubj, a.Name, "STATZ")) + + // This is for user's looking up their own info. + mappedSubject := fmt.Sprintf(userDirectReqSubj, a.Name) + importSrvc(userDirectInfoSubj, mappedSubject) + // Make sure to share details. + a.setServiceImportSharing(sacc, mappedSubject, false, true) +} + // Setup tracking for this account. This allows us to track global account activity. // Lock should be held on entry. func (s *Server) enableAccountTracking(a *Account) { @@ -1128,7 +2351,7 @@ func (s *Server) enableAccountTracking(a *Account) { // May need to ensure we do so only if there is a known interest. // This can get complicated with gateways. - subj := fmt.Sprintf(accReqSubj, a.Name, "CONNS") + subj := fmt.Sprintf(accDirectReqSubj, a.Name, "CONNS") reply := fmt.Sprintf(connsRespSubj, s.info.ID) m := accNumConnsReq{Account: a.Name} s.sendInternalMsg(subj, reply, &m.Server, &m) @@ -1154,7 +2377,7 @@ func (s *Server) sendLeafNodeConnect(a *Account) { func (s *Server) sendLeafNodeConnectMsg(accName string) { subj := fmt.Sprintf(leafNodeConnectEventSubj, accName) m := accNumConnsReq{Account: accName} - s.sendInternalMsg(subj, "", &m.Server, &m) + s.sendInternalMsg(subj, _EMPTY_, &m.Server, &m) } // sendAccConnsUpdate is called to send out our information on the @@ -1171,21 +2394,17 @@ func (s *Server) sendAccConnsUpdate(a *Account, subj ...string) { // Build event with account name and number of local clients and leafnodes. eid := s.nextEventID() a.mu.Lock() - s.mu.Unlock() - localConns := a.numLocalConnections() - m := &AccountNumConns{ + stat := a.statz() + m := AccountNumConns{ TypedEvent: TypedEvent{ Type: AccountNumConnsMsgType, ID: eid, Time: time.Now().UTC(), }, - Account: a.Name, - Conns: localConns, - LeafNodes: a.numLocalLeafNodes(), - TotalConns: localConns + a.numLocalLeafNodes(), + AccountStat: *stat, } // Set timer to fire again unless we are at zero. - if localConns == 0 { + if m.TotalConns == 0 { clearTimer(&a.ctmr) } else { // Check to see if we have an HB running and update. @@ -1196,25 +2415,77 @@ func (s *Server) sendAccConnsUpdate(a *Account, subj ...string) { } } for _, sub := range subj { - msg := &pubMsg{nil, sub, _EMPTY_, &m.Server, &m, false} - select { - case sendQ <- msg: - default: - a.mu.Unlock() - sendQ <- msg - a.mu.Lock() - } + msg := newPubMsg(nil, sub, _EMPTY_, &m.Server, nil, &m, noCompression, false, false) + sendQ.push(msg) } a.mu.Unlock() - s.mu.Lock() +} + +// Lock should be held on entry. +func (a *Account) statz() *AccountStat { + localConns := a.numLocalConnections() + leafConns := a.numLocalLeafNodes() + + a.stats.Lock() + received := DataStats{ + MsgBytes: MsgBytes{ + Msgs: a.stats.inMsgs, + Bytes: a.stats.inBytes, + }, + Gateways: &MsgBytes{ + Msgs: a.stats.gw.inMsgs, + Bytes: a.stats.gw.inBytes, + }, + Routes: &MsgBytes{ + Msgs: a.stats.rt.inMsgs, + Bytes: a.stats.rt.inBytes, + }, + Leafs: &MsgBytes{ + Msgs: a.stats.ln.inMsgs, + Bytes: a.stats.ln.inBytes, + }, + } + sent := DataStats{ + MsgBytes: MsgBytes{ + Msgs: a.stats.outMsgs, + Bytes: a.stats.outBytes, + }, + Gateways: &MsgBytes{ + Msgs: a.stats.gw.outMsgs, + Bytes: a.stats.gw.outBytes, + }, + Routes: &MsgBytes{ + Msgs: a.stats.rt.outMsgs, + Bytes: a.stats.rt.outBytes, + }, + Leafs: &MsgBytes{ + Msgs: a.stats.ln.outMsgs, + Bytes: a.stats.ln.outBytes, + }, + } + slowConsumers := a.stats.slowConsumers + a.stats.Unlock() + + return &AccountStat{ + Account: a.Name, + Name: a.getNameTagLocked(), + Conns: localConns, + LeafNodes: leafConns, + TotalConns: localConns + leafConns, + NumSubs: a.sl.Count(), + Received: received, + Sent: sent, + SlowConsumers: slowConsumers, + } } // accConnsUpdate is called whenever there is a change to the account's // number of active connections, or during a heartbeat. +// We will not send for $G. func (s *Server) accConnsUpdate(a *Account) { s.mu.Lock() defer s.mu.Unlock() - if !s.eventsEnabled() || a == nil { + if !s.eventsEnabled() || a == nil || a == s.gacc { return } s.sendAccConnsUpdate(a, fmt.Sprintf(accConnsEventSubjOld, a.Name), fmt.Sprintf(accConnsEventSubjNew, a.Name)) @@ -1251,19 +2522,26 @@ func (s *Server) accountConnectEvent(c *client) { Time: time.Now().UTC(), }, Client: ClientInfo{ - Start: c.start, - Host: c.host, - ID: c.cid, - Account: accForClient(c), - User: c.getRawAuthUser(), - Name: c.opts.Name, - Lang: c.opts.Lang, - Version: c.opts.Version, + Start: &c.start, + Host: c.host, + ID: c.cid, + Account: accForClient(c), + User: c.getRawAuthUser(), + Name: c.opts.Name, + Lang: c.opts.Lang, + Version: c.opts.Version, + Jwt: c.opts.JWT, + IssuerKey: issuerForClient(c), + Tags: c.tags, + NameTag: c.acc.getNameTag(), + Kind: c.kindString(), + ClientType: c.clientTypeString(), + MQTTClient: c.getMQTTClientID(), }, } + subj := fmt.Sprintf(connectEventSubj, c.acc.Name) c.mu.Unlock() - subj := fmt.Sprintf(connectEventSubj, c.acc.Name) s.sendInternalMsgLocked(subj, _EMPTY_, &m.Server, &m) } @@ -1291,27 +2569,38 @@ func (s *Server) accountDisconnectEvent(c *client, now time.Time, reason string) TypedEvent: TypedEvent{ Type: DisconnectEventMsgType, ID: eid, - Time: now.UTC(), + Time: now, }, Client: ClientInfo{ - Start: c.start, - Stop: &now, - Host: c.host, - ID: c.cid, - Account: accForClient(c), - User: c.getRawAuthUser(), - Name: c.opts.Name, - Lang: c.opts.Lang, - Version: c.opts.Version, - RTT: c.getRTT(), + Start: &c.start, + Stop: &now, + Host: c.host, + ID: c.cid, + Account: accForClient(c), + User: c.getRawAuthUser(), + Name: c.opts.Name, + Lang: c.opts.Lang, + Version: c.opts.Version, + RTT: c.getRTT(), + Jwt: c.opts.JWT, + IssuerKey: issuerForClient(c), + Tags: c.tags, + NameTag: c.acc.getNameTag(), + Kind: c.kindString(), + ClientType: c.clientTypeString(), + MQTTClient: c.getMQTTClientID(), }, Sent: DataStats{ - Msgs: atomic.LoadInt64(&c.inMsgs), - Bytes: atomic.LoadInt64(&c.inBytes), + MsgBytes: MsgBytes{ + Msgs: atomic.LoadInt64(&c.inMsgs), + Bytes: atomic.LoadInt64(&c.inBytes), + }, }, Received: DataStats{ - Msgs: c.outMsgs, - Bytes: c.outBytes, + MsgBytes: MsgBytes{ + Msgs: c.outMsgs, + Bytes: c.outBytes, + }, }, Reason: reason, } @@ -1322,6 +2611,7 @@ func (s *Server) accountDisconnectEvent(c *client, now time.Time, reason string) s.sendInternalMsgLocked(subj, _EMPTY_, &m.Server, &m) } +// This is the system level event sent to the system account for operators. func (s *Server) sendAuthErrorEvent(c *client) { s.mu.Lock() if !s.eventsEnabled() { @@ -1330,33 +2620,45 @@ func (s *Server) sendAuthErrorEvent(c *client) { } eid := s.nextEventID() s.mu.Unlock() - now := time.Now() + + now := time.Now().UTC() c.mu.Lock() m := DisconnectEventMsg{ TypedEvent: TypedEvent{ Type: DisconnectEventMsgType, ID: eid, - Time: now.UTC(), + Time: now, }, Client: ClientInfo{ - Start: c.start, - Stop: &now, - Host: c.host, - ID: c.cid, - Account: accForClient(c), - User: c.getRawAuthUser(), - Name: c.opts.Name, - Lang: c.opts.Lang, - Version: c.opts.Version, - RTT: c.getRTT(), + Start: &c.start, + Stop: &now, + Host: c.host, + ID: c.cid, + Account: accForClient(c), + User: c.getRawAuthUser(), + Name: c.opts.Name, + Lang: c.opts.Lang, + Version: c.opts.Version, + RTT: c.getRTT(), + Jwt: c.opts.JWT, + IssuerKey: issuerForClient(c), + Tags: c.tags, + NameTag: c.acc.getNameTag(), + Kind: c.kindString(), + ClientType: c.clientTypeString(), + MQTTClient: c.getMQTTClientID(), }, Sent: DataStats{ - Msgs: c.inMsgs, - Bytes: c.inBytes, + MsgBytes: MsgBytes{ + Msgs: c.inMsgs, + Bytes: c.inBytes, + }, }, Received: DataStats{ - Msgs: c.outMsgs, - Bytes: c.outBytes, + MsgBytes: MsgBytes{ + Msgs: c.outMsgs, + Bytes: c.outBytes, + }, }, Reason: AuthenticationViolation.String(), } @@ -1368,34 +2670,140 @@ func (s *Server) sendAuthErrorEvent(c *client) { s.mu.Unlock() } -// Internal message callback. If the msg is needed past the callback it is -// required to be copied. -type msgHandler func(sub *subscription, client *client, subject, reply string, msg []byte) +// This is the account level event sent to the origin account for account owners. +func (s *Server) sendAccountAuthErrorEvent(c *client, acc *Account, reason string) { + if acc == nil { + return + } + s.mu.Lock() + if !s.eventsEnabled() { + s.mu.Unlock() + return + } + eid := s.nextEventID() + s.mu.Unlock() + + now := time.Now().UTC() + c.mu.Lock() + m := DisconnectEventMsg{ + TypedEvent: TypedEvent{ + Type: DisconnectEventMsgType, + ID: eid, + Time: now, + }, + Client: ClientInfo{ + Start: &c.start, + Stop: &now, + Host: c.host, + ID: c.cid, + Account: acc.Name, + User: c.getRawAuthUser(), + Name: c.opts.Name, + Lang: c.opts.Lang, + Version: c.opts.Version, + RTT: c.getRTT(), + Jwt: c.opts.JWT, + IssuerKey: issuerForClient(c), + Tags: c.tags, + NameTag: c.acc.getNameTag(), + Kind: c.kindString(), + ClientType: c.clientTypeString(), + MQTTClient: c.getMQTTClientID(), + }, + Sent: DataStats{ + MsgBytes: MsgBytes{ + Msgs: c.inMsgs, + Bytes: c.inBytes, + }, + }, + Received: DataStats{ + MsgBytes: MsgBytes{ + Msgs: c.outMsgs, + Bytes: c.outBytes, + }, + }, + Reason: reason, + } + c.mu.Unlock() + + s.sendInternalAccountSysMsg(acc, authErrorAccountEventSubj, &m.Server, &m, noCompression) +} + +// Internal message callback. +// If the msg is needed past the callback it is required to be copied. +// rmsg contains header and the message. use client.msgParts(rmsg) to split them apart +type msgHandler func(sub *subscription, client *client, acc *Account, subject, reply string, rmsg []byte) + +const ( + recvQMuxed = 1 + recvQStatsz = 2 +) + +// Create a wrapped callback handler for the subscription that will move it to an +// internal recvQ for processing not inline with routes etc. +func (s *Server) noInlineCallback(cb sysMsgHandler) msgHandler { + return s.noInlineCallbackRecvQSelect(cb, recvQMuxed) +} + +// Create a wrapped callback handler for the subscription that will move it to an +// internal recvQ for Statsz/Pings for processing not inline with routes etc. +func (s *Server) noInlineCallbackStatsz(cb sysMsgHandler) msgHandler { + return s.noInlineCallbackRecvQSelect(cb, recvQStatsz) +} + +// Create a wrapped callback handler for the subscription that will move it to an +// internal IPQueue for processing not inline with routes etc. +func (s *Server) noInlineCallbackRecvQSelect(cb sysMsgHandler, recvQSelect int) msgHandler { + s.mu.RLock() + if !s.eventsEnabled() { + s.mu.RUnlock() + return nil + } + // Capture here for direct reference to avoid any unnecessary blocking inline with routes, gateways etc. + var recvq *ipQueue[*inSysMsg] + switch recvQSelect { + case recvQStatsz: + recvq = s.sys.recvqp + default: + recvq = s.sys.recvq + } + s.mu.RUnlock() + + return func(sub *subscription, c *client, acc *Account, subj, rply string, rmsg []byte) { + // Need to copy and split here. + hdr, msg := c.msgParts(rmsg) + recvq.push(&inSysMsg{sub, c, acc, subj, rply, copyBytes(hdr), copyBytes(msg), cb}) + } +} // Create an internal subscription. sysSubscribeQ for queue groups. func (s *Server) sysSubscribe(subject string, cb msgHandler) (*subscription, error) { - return s.systemSubscribe(subject, "", false, cb) + return s.systemSubscribe(subject, _EMPTY_, false, nil, cb) } // Create an internal subscription with queue func (s *Server) sysSubscribeQ(subject, queue string, cb msgHandler) (*subscription, error) { - return s.systemSubscribe(subject, queue, false, cb) + return s.systemSubscribe(subject, queue, false, nil, cb) } // Create an internal subscription but do not forward interest. func (s *Server) sysSubscribeInternal(subject string, cb msgHandler) (*subscription, error) { - return s.systemSubscribe(subject, "", true, cb) + return s.systemSubscribe(subject, _EMPTY_, true, nil, cb) } -func (s *Server) systemSubscribe(subject, queue string, internalOnly bool, cb msgHandler) (*subscription, error) { +func (s *Server) systemSubscribe(subject, queue string, internalOnly bool, c *client, cb msgHandler) (*subscription, error) { + s.mu.Lock() if !s.eventsEnabled() { + s.mu.Unlock() return nil, ErrNoSysAccount } if cb == nil { + s.mu.Unlock() return nil, fmt.Errorf("undefined message handler") } - s.mu.Lock() - c := s.sys.client + if c == nil { + c = s.sys.client + } trace := c.trace s.sys.sid++ sid := strconv.Itoa(s.sys.sid) @@ -1407,22 +2815,29 @@ func (s *Server) systemSubscribe(subject, queue string, internalOnly bool, cb ms } var q []byte - if queue != "" { + if queue != _EMPTY_ { q = []byte(queue) } + // Now create the subscription return c.processSub([]byte(subject), q, []byte(sid), cb, internalOnly) } func (s *Server) sysUnsubscribe(sub *subscription) { - if sub == nil || !s.eventsEnabled() { + if sub == nil { return } - s.mu.Lock() - acc := s.sys.account - c := s.sys.client - s.mu.Unlock() - c.unsubscribe(acc, sub, true, true) + s.mu.RLock() + if !s.eventsEnabled() { + s.mu.RUnlock() + return + } + c := sub.client + s.mu.RUnlock() + + if c != nil { + c.processUnsub(sub.sid) + } } // This will generate the tracking subject for remote latency from the response subject. @@ -1436,11 +2851,11 @@ func remoteLatencySubjectForResponse(subject []byte) string { } // remoteLatencyUpdate is used to track remote latency measurements for tracking on exported services. -func (s *Server) remoteLatencyUpdate(sub *subscription, _ *client, subject, _ string, msg []byte) { +func (s *Server) remoteLatencyUpdate(sub *subscription, _ *client, _ *Account, subject, _ string, hdr, msg []byte) { if !s.eventsRunning() { return } - rl := remoteLatency{} + var rl remoteLatency if err := json.Unmarshal(msg, &rl); err != nil { s.Errorf("Error unmarshalling remote latency measurement: %v", err) return @@ -1462,25 +2877,22 @@ func (s *Server) remoteLatencyUpdate(sub *subscription, _ *client, subject, _ st acc.mu.RUnlock() return } - m1 := si.m1 - m2 := rl.M2 - lsub := si.latency.subject acc.mu.RUnlock() + si.acc.mu.Lock() + m1 := si.m1 + m2 := rl.M2 + // So we have not processed the response tracking measurement yet. if m1 == nil { - si.acc.mu.Lock() - // Double check since could have slipped in. - m1 = si.m1 - if m1 == nil { - // Store our value there for them to pick up. - si.m1 = &m2 - } - si.acc.mu.Unlock() - if m1 == nil { - return - } + // Store our value there for them to pick up. + si.m1 = &m2 + } + si.acc.mu.Unlock() + + if m1 == nil { + return } // Calculate the correct latencies given M1 and M2. @@ -1491,25 +2903,23 @@ func (s *Server) remoteLatencyUpdate(sub *subscription, _ *client, subject, _ st si.rc = nil acc.mu.Unlock() - // Make sure we remove the entry here. - acc.removeServiceImport(si.from) // Send the metrics s.sendInternalAccountMsg(acc, lsub, m1) } // This is used for all inbox replies so that we do not send supercluster wide interest // updates for every request. Same trick used in modern NATS clients. -func (s *Server) inboxReply(sub *subscription, c *client, subject, reply string, msg []byte) { - s.mu.Lock() +func (s *Server) inboxReply(sub *subscription, c *client, acc *Account, subject, reply string, msg []byte) { + s.mu.RLock() if !s.eventsEnabled() || s.sys.replies == nil { - s.mu.Unlock() + s.mu.RUnlock() return } cb, ok := s.sys.replies[subject] - s.mu.Unlock() + s.mu.RUnlock() if ok && cb != nil { - cb(sub, c, subject, reply, msg) + cb(sub, c, acc, subject, reply, msg) } } @@ -1572,7 +2982,7 @@ func totalSubs(rr *SublistResult, qg []byte) (nsubs int32) { // Allows users of large systems to debug active subscribers for a given subject. // Payload should be the subject of interest. -func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply string, msg []byte) { +func (s *Server) debugSubscribers(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { // Even though this is an internal only subscription, meaning interest was not forwarded, we could // get one here from a GW in optimistic mode. Ignore for now. // FIXME(dlc) - Should we send no interest here back to the GW? @@ -1580,12 +2990,33 @@ func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply s return } - var nsubs int32 + var ci ClientInfo + if len(hdr) > 0 { + if err := json.Unmarshal(getHeader(ClientInfoHdr, hdr), &ci); err != nil { + return + } + } + + var acc *Account + if ci.Service != _EMPTY_ { + acc, _ = s.LookupAccount(ci.Service) + } else if ci.Account != _EMPTY_ { + acc, _ = s.LookupAccount(ci.Account) + } else { + // Direct $SYS access. + acc = c.acc + if acc == nil { + acc = s.SystemAccount() + } + } + if acc == nil { + return + } // We could have a single subject or we could have a subject and a wildcard separated by whitespace. args := strings.Split(strings.TrimSpace(string(msg)), " ") if len(args) == 0 { - s.sendInternalAccountMsg(c.acc, reply, 0) + s.sendInternalAccountMsg(acc, reply, 0) return } @@ -1595,15 +3026,17 @@ func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply s qgroup = []byte(args[1]) } + var nsubs int32 + if subjectIsLiteral(tsubj) { // We will look up subscribers locally first then determine if we need to solicit other servers. - rr := c.acc.sl.Match(tsubj) + rr := acc.sl.Match(tsubj) nsubs = totalSubs(rr, qgroup) } else { // We have a wildcard, so this is a bit slower path. var _subs [32]*subscription subs := _subs[:0] - c.acc.sl.All(&subs) + acc.sl.All(&subs) for _, sub := range subs { if subjectIsSubsetMatch(string(sub.subject), tsubj) { if qgroup != nil && !bytes.Equal(qgroup, sub.queue) { @@ -1617,7 +3050,7 @@ func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply s } // We should have an idea of how many responses to expect from remote servers. - var expected = c.acc.expectedRemoteResponses() + var expected = acc.expectedRemoteResponses() // If we are only local, go ahead and return. if expected == 0 { @@ -1634,8 +3067,8 @@ func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply s // Create direct reply inbox that we multiplex under the WC replies. replySubj := s.newRespInbox() // Store our handler. - s.sys.replies[replySubj] = func(sub *subscription, _ *client, subject, _ string, msg []byte) { - if n, err := strconv.Atoi(string(msg)); err == nil { + s.sys.replies[replySubj] = func(sub *subscription, _ *client, _ *Account, subject, _ string, msg []byte) { + if n, err := strconv.ParseInt(string(msg), 10, 32); err == nil { atomic.AddInt32(&nsubs, int32(n)) } if atomic.AddInt32(&responses, 1) >= expected { @@ -1647,7 +3080,7 @@ func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply s } // Send the request to the other servers. request := &accNumSubsReq{ - Account: c.acc.Name, + Account: acc.Name, Subject: tsubj, Queue: qgroup, } @@ -1661,22 +3094,31 @@ func (s *Server) debugSubscribers(sub *subscription, c *client, subject, reply s case <-time.After(500 * time.Millisecond): } // Cleanup the WC entry. + var sendResponse bool s.mu.Lock() - delete(s.sys.replies, replySubj) + if s.sys != nil && s.sys.replies != nil { + delete(s.sys.replies, replySubj) + sendResponse = true + } s.mu.Unlock() - // Send the response. - s.sendInternalAccountMsg(nil, reply, atomic.LoadInt32(&nsubs)) + if sendResponse { + // Send the response. + s.sendInternalAccountMsg(nil, reply, atomic.LoadInt32(&nsubs)) + } }() } // Request for our local subscription count. This will come from a remote origin server // that received the initial request. -func (s *Server) nsubsRequest(sub *subscription, _ *client, subject, reply string, msg []byte) { +func (s *Server) nsubsRequest(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { if !s.eventsRunning() { return } m := accNumSubsReq{} - if err := json.Unmarshal(msg, &m); err != nil { + if len(msg) == 0 { + s.sys.client.Errorf("request requires a body") + return + } else if err := json.Unmarshal(msg, &m); err != nil { s.sys.client.Errorf("Error unmarshalling account nsubs request message: %v", err) return } @@ -1707,6 +3149,61 @@ func (s *Server) nsubsRequest(sub *subscription, _ *client, subject, reply strin s.sendInternalMsgLocked(reply, _EMPTY_, nil, nsubs) } +func (s *Server) reloadConfig(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + if !s.eventsRunning() { + return + } + + optz := &EventFilterOptions{} + s.zReq(c, reply, hdr, msg, optz, optz, func() (any, error) { + // Reload the server config, as requested. + return nil, s.Reload() + }) +} + +type KickClientReq struct { + CID uint64 `json:"cid"` +} + +type LDMClientReq struct { + CID uint64 `json:"cid"` +} + +func (s *Server) kickClient(_ *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + if !s.eventsRunning() { + return + } + + var req KickClientReq + if err := json.Unmarshal(msg, &req); err != nil { + s.sys.client.Errorf("Error unmarshalling kick client request: %v", err) + return + } + + optz := &EventFilterOptions{} + s.zReq(c, reply, hdr, msg, optz, optz, func() (any, error) { + return nil, s.DisconnectClientByID(req.CID) + }) + +} + +func (s *Server) ldmClient(_ *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) { + if !s.eventsRunning() { + return + } + + var req LDMClientReq + if err := json.Unmarshal(msg, &req); err != nil { + s.sys.client.Errorf("Error unmarshalling kick client request: %v", err) + return + } + + optz := &EventFilterOptions{} + s.zReq(c, reply, hdr, msg, optz, optz, func() (any, error) { + return nil, s.LDMClientByID(req.CID) + }) +} + // Helper to grab account name for a client. func accForClient(c *client) string { if c.acc != nil { @@ -1715,6 +3212,18 @@ func accForClient(c *client) string { return "N/A" } +// Helper to grab issuer for a client. +func issuerForClient(c *client) (issuerKey string) { + if c == nil || c.user == nil { + return + } + issuerKey = c.user.SigningKey + if issuerKey == _EMPTY_ && c.user.Account != nil { + issuerKey = c.user.Account.Name + } + return +} + // Helper to clear timers. func clearTimer(tp **time.Timer) { if t := *tp; t != nil { @@ -1736,3 +3245,74 @@ func (s *Server) wrapChk(f func()) func() { s.mu.Unlock() } } + +// sendOCSPPeerRejectEvent sends a system level event to system account when a peer connection is +// rejected due to OCSP invalid status of its trust chain(s). +func (s *Server) sendOCSPPeerRejectEvent(kind string, peer *x509.Certificate, reason string) { + s.mu.Lock() + defer s.mu.Unlock() + if !s.eventsEnabled() { + return + } + if peer == nil { + s.Errorf(certidp.ErrPeerEmptyNoEvent) + return + } + eid := s.nextEventID() + now := time.Now().UTC() + m := OCSPPeerRejectEventMsg{ + TypedEvent: TypedEvent{ + Type: OCSPPeerRejectEventMsgType, + ID: eid, + Time: now, + }, + Kind: kind, + Peer: certidp.CertInfo{ + Subject: certidp.GetSubjectDNForm(peer), + Issuer: certidp.GetIssuerDNForm(peer), + Fingerprint: certidp.GenerateFingerprint(peer), + Raw: peer.Raw, + }, + Reason: reason, + } + subj := fmt.Sprintf(ocspPeerRejectEventSubj, s.info.ID) + s.sendInternalMsg(subj, _EMPTY_, &m.Server, &m) +} + +// sendOCSPPeerChainlinkInvalidEvent sends a system level event to system account when a link in a peer's trust chain +// is OCSP invalid. +func (s *Server) sendOCSPPeerChainlinkInvalidEvent(peer *x509.Certificate, link *x509.Certificate, reason string) { + s.mu.Lock() + defer s.mu.Unlock() + if !s.eventsEnabled() { + return + } + if peer == nil || link == nil { + s.Errorf(certidp.ErrPeerEmptyNoEvent) + return + } + eid := s.nextEventID() + now := time.Now().UTC() + m := OCSPPeerChainlinkInvalidEventMsg{ + TypedEvent: TypedEvent{ + Type: OCSPPeerChainlinkInvalidEventMsgType, + ID: eid, + Time: now, + }, + Link: certidp.CertInfo{ + Subject: certidp.GetSubjectDNForm(link), + Issuer: certidp.GetIssuerDNForm(link), + Fingerprint: certidp.GenerateFingerprint(link), + Raw: link.Raw, + }, + Peer: certidp.CertInfo{ + Subject: certidp.GetSubjectDNForm(peer), + Issuer: certidp.GetIssuerDNForm(peer), + Fingerprint: certidp.GenerateFingerprint(peer), + Raw: peer.Raw, + }, + Reason: reason, + } + subj := fmt.Sprintf(ocspPeerChainlinkInvalidEventSubj, s.info.ID) + s.sendInternalMsg(subj, _EMPTY_, &m.Server, &m) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/filestore.go b/vendor/github.com/nats-io/nats-server/v2/server/filestore.go index da13e9e..60a96ca 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/filestore.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/filestore.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,28 +15,40 @@ package server import ( "archive/tar" - "bufio" "bytes" - "compress/gzip" + "crypto/aes" + "crypto/cipher" + "crypto/rand" "crypto/sha256" "encoding/binary" "encoding/hex" "encoding/json" "errors" "fmt" - "hash" "io" - "io/ioutil" - "math/rand" + "io/fs" + "math" + mrand "math/rand" "net" "os" - "path" + "path/filepath" + "runtime" + "slices" "sort" + "strings" "sync" "sync/atomic" "time" + "github.com/klauspost/compress/s2" "github.com/minio/highwayhash" + "github.com/nats-io/nats-server/v2/server/ats" + "github.com/nats-io/nats-server/v2/server/avl" + "github.com/nats-io/nats-server/v2/server/gsl" + "github.com/nats-io/nats-server/v2/server/stree" + "github.com/nats-io/nats-server/v2/server/thw" + "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/chacha20poly1305" ) type FileStoreConfig struct { @@ -46,8 +58,21 @@ type FileStoreConfig struct { BlockSize uint64 // CacheExpire is how long with no activity until we expire the cache. CacheExpire time.Duration + // SubjectStateExpire is how long with no activity until we expire a msg block's subject state. + SubjectStateExpire time.Duration // SyncInterval is how often we sync to disk in the background. SyncInterval time.Duration + // SyncAlways is when the stream should sync all data writes. + SyncAlways bool + // AsyncFlush allows async flush to batch write operations. + AsyncFlush bool + // Cipher is the cipher to use when encrypting. + Cipher StoreCipher + // Compression is the algorithm to use when compressing. + Compression StoreCompression + + // Internal reference to our server. + srv *Server } // FileStreamInfo allows us to remember created time. @@ -56,35 +81,71 @@ type FileStreamInfo struct { StreamConfig } -// Need an alias (which does not have MarshalJSON/UnmarshalJSON) to avoid -// recursive calls which would lead to stack overflow. -type fileStreamInfoAlias FileStreamInfo +type StoreCipher int + +const ( + ChaCha StoreCipher = iota + AES + NoCipher +) -// We will use this struct definition to serialize/deserialize FileStreamInfo -// object. This embeds FileStreamInfo (the alias to prevent recursive calls) -// and makes the non-public options public so they can be persisted/recovered. -type fileStreamInfoJSON struct { - fileStreamInfoAlias - Internal bool `json:"internal,omitempty"` - AllowNoSubject bool `json:"allow_no_subject,omitempty"` +func (cipher StoreCipher) String() string { + switch cipher { + case ChaCha: + return "ChaCha20-Poly1305" + case AES: + return "AES-GCM" + case NoCipher: + return "None" + default: + return "Unknown StoreCipher" + } } -func (fsi FileStreamInfo) MarshalJSON() ([]byte, error) { - return json.Marshal(&fileStreamInfoJSON{ - fileStreamInfoAlias(fsi), - fsi.internal, - fsi.allowNoSubject, - }) +type StoreCompression uint8 + +const ( + NoCompression StoreCompression = iota + S2Compression +) + +func (alg StoreCompression) String() string { + switch alg { + case NoCompression: + return "None" + case S2Compression: + return "S2" + default: + return "Unknown StoreCompression" + } +} + +func (alg StoreCompression) MarshalJSON() ([]byte, error) { + var str string + switch alg { + case S2Compression: + str = "s2" + case NoCompression: + str = "none" + default: + return nil, fmt.Errorf("unknown compression algorithm") + } + return json.Marshal(str) } -func (fsi *FileStreamInfo) UnmarshalJSON(b []byte) error { - fsiJSON := &fileStreamInfoJSON{} - if err := json.Unmarshal(b, &fsiJSON); err != nil { +func (alg *StoreCompression) UnmarshalJSON(b []byte) error { + var str string + if err := json.Unmarshal(b, &str); err != nil { return err } - *fsi = FileStreamInfo(fsiJSON.fileStreamInfoAlias) - fsi.internal = fsiJSON.Internal - fsi.allowNoSubject = fsiJSON.AllowNoSubject + switch str { + case "s2": + *alg = S2Compression + case "none": + *alg = NoCompression + default: + return fmt.Errorf("unknown compression algorithm") + } return nil } @@ -95,87 +156,119 @@ type FileConsumerInfo struct { ConsumerConfig } -// See fileStreamInfoAlias, etc.. for details on how this all work. -type fileConsumerInfoAlias FileConsumerInfo - -type fileConsumerInfoJSON struct { - fileConsumerInfoAlias - AllowNoInterest bool `json:"allow_no_interest,omitempty"` -} - -func (fci FileConsumerInfo) MarshalJSON() ([]byte, error) { - return json.Marshal(&fileConsumerInfoJSON{ - fileConsumerInfoAlias(fci), - fci.allowNoInterest, - }) -} +// Default file and directory permissions. +const ( + defaultDirPerms = os.FileMode(0700) + defaultFilePerms = os.FileMode(0600) +) -func (fci *FileConsumerInfo) UnmarshalJSON(b []byte) error { - fciJSON := &fileConsumerInfoJSON{} - if err := json.Unmarshal(b, &fciJSON); err != nil { - return err - } - *fci = FileConsumerInfo(fciJSON.fileConsumerInfoAlias) - fci.allowNoInterest = fciJSON.AllowNoInterest - return nil +type psi struct { + total uint64 + fblk uint32 + lblk uint32 } type fileStore struct { - mu sync.RWMutex - state StreamState - scb StorageUpdateHandler - ageChk *time.Timer - syncTmr *time.Timer - cfg FileStreamInfo - fcfg FileStoreConfig - lmb *msgBlock - blks []*msgBlock - hh hash.Hash64 - qch chan struct{} - cfs []*consumerFileStore - closed bool - expiring bool - sips int + srv *Server + mu sync.RWMutex + state StreamState + tombs []uint64 + ld *LostStreamData + scb StorageUpdateHandler + rmcb StorageRemoveMsgHandler + sdmcb SubjectDeleteMarkerUpdateHandler + ageChk *time.Timer // Timer to expire messages. + ageChkRun bool // Whether message expiration is currently running. + ageChkTime int64 // When the message expiration is scheduled to run. + syncTmr *time.Timer + cfg FileStreamInfo + fcfg FileStoreConfig + prf keyGen + oldprf keyGen + aek cipher.AEAD + lmb *msgBlock + blks []*msgBlock + bim map[uint32]*msgBlock + psim *stree.SubjectTree[psi] + tsl int + adml int + hh *highwayhash.Digest64 + qch chan struct{} + fsld chan struct{} + cmu sync.RWMutex + cfs []ConsumerStore + sips int + dirty int + closing bool + closed atomic.Bool // Atomic to reduce contention on ConsumerStores. + fip bool + receivedAny bool + firstMoved bool + ttls *thw.HashWheel + sdm *SDMMeta + lpex time.Time // Last PurgeEx call. } // Represents a message store block and its data. type msgBlock struct { - mu sync.RWMutex - mfn string - mfd *os.File - ifn string - ifd *os.File - liwsz int64 - index uint64 - bytes uint64 - msgs uint64 - first msgId - last msgId - lwts int64 - llts int64 - lrts int64 - hh hash.Hash64 - cache *cache - cloads uint64 - cexp time.Duration - ctmr *time.Timer - loading bool - flusher bool - dmap map[uint64]struct{} - fch chan struct{} - qch chan struct{} - lchk [8]byte + // Here for 32bit systems and atomic. + first msgId + last msgId + mu sync.RWMutex + fs *fileStore + aek cipher.AEAD + bek cipher.Stream + seed []byte + nonce []byte + mfn string + mfd *os.File + cmp StoreCompression // Effective compression at the time of loading the block + liwsz int64 + index uint32 + bytes uint64 // User visible bytes count. + rbytes uint64 // Total bytes (raw) including deleted. Used for rolling to new blk. + cbytes uint64 // Bytes count after last compaction. 0 if no compaction happened yet. + msgs uint64 // User visible message count. + fss *stree.SubjectTree[SimpleState] + kfn string + lwts int64 + llts int64 + lrts int64 + lsts int64 + llseq uint64 + hh *highwayhash.Digest64 + cache *cache + cloads uint64 + cexp time.Duration + fexp time.Duration + ctmr *time.Timer + werr error + dmap avl.SequenceSet + fch chan struct{} + qch chan struct{} + lchk [8]byte + loading bool + flusher bool + noTrack bool + needSync bool + syncAlways bool + noCompact bool + closed bool + ttls uint64 // How many msgs have TTLs? + + // Used to mock write failures. + mockWriteErr bool } // Write through caching layer that is also used on loading messages. type cache struct { - buf []byte - off int - wp int - idx []uint32 - lrl uint32 - fseq uint64 - flush bool + buf []byte + off int + wp int + idx []uint32 + lrl uint32 + fseq uint64 + nra bool } type msgId struct { @@ -183,21 +276,13 @@ type msgId struct { ts int64 } -type fileStoredMsg struct { - subj string - hdr []byte - msg []byte - seq uint64 - ts int64 // nanoseconds - mb *msgBlock - off int64 // offset into block file -} - const ( // Magic is used to identify the file store files. magic = uint8(22) // Version version = uint8(1) + // New IndexInfo Version + newVersion = uint8(2) // hdrLen hdrLen = 2 // This is where we keep the streams. @@ -208,48 +293,85 @@ const ( purgeDir = "__msgs__" // used to scan blk file names. blkScan = "%d.blk" + // suffix of a block file + blkSuffix = ".blk" + // used for compacted blocks that are staged. + newScan = "%d.new" // used to scan index file names. indexScan = "%d.idx" + // used to store our block encryption key. + keyScan = "%d.key" + // to look for orphans + keyScanAll = "*.key" // This is where we keep state on consumers. consumerDir = "obs" // Index file for a consumer. consumerState = "o.dat" + // The suffix that will be given to a new temporary block for compression or when rewriting the full file. + blkTmpSuffix = ".tmp" // This is where we keep state on templates. tmplsDir = "templates" // Maximum size of a write buffer we may consider for re-use. maxBufReuse = 2 * 1024 * 1024 // default cache buffer expiration - defaultCacheBufferExpiration = 5 * time.Second - // cache idx expiration - defaultCacheIdxExpiration = 5 * time.Minute + defaultCacheBufferExpiration = 10 * time.Second // default sync interval - defaultSyncInterval = 10 * time.Second + defaultSyncInterval = 2 * time.Minute + // default idle timeout to close FDs. + closeFDsIdle = 30 * time.Second + // default expiration time for mb.fss when idle. + defaultFssExpiration = 2 * time.Minute // coalesceMinimum - coalesceMinimum = 4 * 1024 + coalesceMinimum = 16 * 1024 // maxFlushWait is maximum we will wait to gather messages to flush. maxFlushWait = 8 * time.Millisecond + // Metafiles for streams and consumers. JetStreamMetaFile = "meta.inf" JetStreamMetaFileSum = "meta.sum" + JetStreamMetaFileKey = "meta.key" + + // This is the full snapshotted state for the stream. + streamStreamStateFile = "index.db" + + // This is the encoded time hash wheel for TTLs. + ttlStreamStateFile = "thw.db" + + // AEK key sizes + minMetaKeySize = 64 + minBlkKeySize = 64 // Default stream block size. - defaultStreamBlockSize = 64 * 1024 * 1024 // 64MB + defaultLargeBlockSize = 8 * 1024 * 1024 // 8MB // Default for workqueue or interest based. - defaultOtherBlockSize = 32 * 1024 * 1024 // 32MB + defaultMediumBlockSize = 4 * 1024 * 1024 // 4MB + // For smaller reuse buffers. Usually being generated during contention on the lead write buffer. + // E.g. mirrors/sources etc. + defaultSmallBlockSize = 1 * 1024 * 1024 // 1MB + // Maximum size for the encrypted head block. + maximumEncryptedBlockSize = 2 * 1024 * 1024 // 2MB + // Default for KV based + defaultKVBlockSize = defaultMediumBlockSize // max block size for now. - maxBlockSize = 2 * defaultStreamBlockSize + maxBlockSize = defaultLargeBlockSize + // Compact minimum threshold. + compactMinimum = 2 * 1024 * 1024 // 2MB // FileStoreMinBlkSize is minimum size we will do for a blk size. FileStoreMinBlkSize = 32 * 1000 // 32kib // FileStoreMaxBlkSize is maximum size we will do for a blk size. FileStoreMaxBlkSize = maxBlockSize + // Check for bad record length value due to corrupt data. + rlBadThresh = 32 * 1024 * 1024 + // Checksum size for hash for msg records. + recordHashSize = 8 ) func newFileStore(fcfg FileStoreConfig, cfg StreamConfig) (*fileStore, error) { - return newFileStoreWithCreated(fcfg, cfg, time.Now()) + return newFileStoreWithCreated(fcfg, cfg, time.Now().UTC(), nil, nil) } -func newFileStoreWithCreated(fcfg FileStoreConfig, cfg StreamConfig, created time.Time) (*fileStore, error) { - if cfg.Name == "" { +func newFileStoreWithCreated(fcfg FileStoreConfig, cfg StreamConfig, created time.Time, prf, oldprf keyGen) (fs *fileStore, err error) { + if cfg.Name == _EMPTY_ { return nil, fmt.Errorf("name required") } if cfg.Storage != FileStorage { @@ -257,97 +379,296 @@ func newFileStoreWithCreated(fcfg FileStoreConfig, cfg StreamConfig, created tim } // Default values. if fcfg.BlockSize == 0 { - fcfg.BlockSize = dynBlkSize(cfg.Retention, cfg.MaxBytes) + fcfg.BlockSize = dynBlkSize(cfg.Retention, cfg.MaxBytes, prf != nil) } if fcfg.BlockSize > maxBlockSize { - return nil, fmt.Errorf("filestore max block size is %s", FriendlyBytes(maxBlockSize)) + return nil, fmt.Errorf("filestore max block size is %s", friendlyBytes(maxBlockSize)) } if fcfg.CacheExpire == 0 { fcfg.CacheExpire = defaultCacheBufferExpiration } + if fcfg.SubjectStateExpire == 0 { + fcfg.SubjectStateExpire = defaultFssExpiration + } if fcfg.SyncInterval == 0 { fcfg.SyncInterval = defaultSyncInterval } // Check the directory if stat, err := os.Stat(fcfg.StoreDir); os.IsNotExist(err) { - if err := os.MkdirAll(fcfg.StoreDir, 0755); err != nil { + if err := os.MkdirAll(fcfg.StoreDir, defaultDirPerms); err != nil { return nil, fmt.Errorf("could not create storage directory - %v", err) } } else if stat == nil || !stat.IsDir() { - return nil, fmt.Errorf("store directory is not a directory") + return nil, fmt.Errorf("storage directory is not a directory") } - tmpfile, err := ioutil.TempFile(fcfg.StoreDir, "_test_") + tmpfile, err := os.CreateTemp(fcfg.StoreDir, "_test_") if err != nil { return nil, fmt.Errorf("storage directory is not writable") } + + tmpfile.Close() + <-dios os.Remove(tmpfile.Name()) + dios <- struct{}{} + + fs = &fileStore{ + fcfg: fcfg, + psim: stree.NewSubjectTree[psi](), + bim: make(map[uint32]*msgBlock), + cfg: FileStreamInfo{Created: created, StreamConfig: cfg}, + prf: prf, + oldprf: oldprf, + qch: make(chan struct{}), + fsld: make(chan struct{}), + srv: fcfg.srv, + } + + // Register with access time service. + ats.Register() - fs := &fileStore{ - fcfg: fcfg, - cfg: FileStreamInfo{Created: created, StreamConfig: cfg}, - qch: make(chan struct{}), + // If we error before completion make sure to cleanup. + defer func() { + if err != nil { + ats.Unregister() + } + }() + + // Only create a THW if we're going to allow TTLs. + if cfg.AllowMsgTTL { + fs.ttls = thw.NewHashWheel() } + // Set flush in place to AsyncFlush which by default is false. + fs.fip = !fcfg.AsyncFlush + // Check if this is a new setup. - mdir := path.Join(fcfg.StoreDir, msgDir) - odir := path.Join(fcfg.StoreDir, consumerDir) - if err := os.MkdirAll(mdir, 0755); err != nil { + mdir := filepath.Join(fcfg.StoreDir, msgDir) + odir := filepath.Join(fcfg.StoreDir, consumerDir) + if err := os.MkdirAll(mdir, defaultDirPerms); err != nil { return nil, fmt.Errorf("could not create message storage directory - %v", err) } - if err := os.MkdirAll(odir, 0755); err != nil { - return nil, fmt.Errorf("could not create message storage directory - %v", err) + if err := os.MkdirAll(odir, defaultDirPerms); err != nil { + return nil, fmt.Errorf("could not create consumer storage directory - %v", err) } // Create highway hash for message blocks. Use sha256 of directory as key. key := sha256.Sum256([]byte(cfg.Name)) - fs.hh, err = highwayhash.New64(key[:]) + fs.hh, err = highwayhash.NewDigest64(key[:]) if err != nil { return nil, fmt.Errorf("could not create hash: %v", err) } - // Recover our state. - if err := fs.recoverMsgs(); err != nil { + keyFile := filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFileKey) + _, err = os.Stat(keyFile) + // Either the file should exist (err=nil), or it shouldn't. Any other error is reported. + if err != nil && !os.IsNotExist(err) { return nil, err } + // Make sure we do not have an encrypted store underneath of us but no main key. + if fs.prf == nil && err == nil { + return nil, errNoMainKey + } else if fs.prf != nil && err == nil { + // If encryption is configured and the key file exists, recover our keys. + if err = fs.recoverAEK(); err != nil { + return nil, err + } + } - // Write our meta data iff does not exist. - meta := path.Join(fcfg.StoreDir, JetStreamMetaFile) - if _, err := os.Stat(meta); err != nil && os.IsNotExist(err) { + // Attempt to recover our state. + err = fs.recoverFullState() + if err != nil { + if !os.IsNotExist(err) { + fs.warn("Recovering stream state from index errored: %v", err) + } + // Hold onto state + prior := fs.state + // Reset anything that could have been set from above. + fs.state = StreamState{} + fs.psim, fs.tsl = fs.psim.Empty(), 0 + fs.bim = make(map[uint32]*msgBlock) + fs.blks = nil + fs.tombs = nil + + // Recover our message state the old way + if err := fs.recoverMsgs(); err != nil { + return nil, err + } + + // Check if our prior state remembers a last sequence past where we can see. + if prior.LastSeq > fs.state.LastSeq { + fs.state.LastSeq, fs.state.LastTime = prior.LastSeq, prior.LastTime + if fs.state.Msgs == 0 { + fs.state.FirstSeq = fs.state.LastSeq + 1 + fs.state.FirstTime = time.Time{} + } + if fs.ld != nil { + if _, err := fs.newMsgBlockForWrite(); err == nil { + if err = fs.writeTombstone(prior.LastSeq, prior.LastTime.UnixNano()); err != nil { + return nil, err + } + } else { + return nil, err + } + } + } + // Since we recovered here, make sure to kick ourselves to write out our stream state. + fs.dirty++ + } + + // See if we can bring back our TTL timed hash wheel state from disk. + if cfg.AllowMsgTTL { + if err = fs.recoverTTLState(); err != nil && !os.IsNotExist(err) { + fs.warn("Recovering TTL state from index errored: %v", err) + } + } + + // Also make sure we get rid of old idx and fss files on return. + // Do this in separate go routine vs inline and at end of processing. + defer func() { + if fs != nil { + go fs.cleanupOldMeta() + } + }() + + // Lock while we do enforcements and removals. + fs.mu.Lock() + + // Check if we have any left over tombstones to process. + if len(fs.tombs) > 0 { + for _, seq := range fs.tombs { + fs.removeMsg(seq, false, true, false) + fs.removeFromLostData(seq) + } + // Not needed after this phase. + fs.tombs = nil + } + + // Limits checks and enforcement. + fs.enforceMsgLimit() + fs.enforceBytesLimit() + + // Do age checks too, make sure to call in place. + if fs.cfg.MaxAge != 0 { + err := fs.expireMsgsOnRecover() + if isPermissionError(err) { + return nil, err + } + fs.startAgeChk() + } + + // If we have max msgs per subject make sure the is also enforced. + if fs.cfg.MaxMsgsPer > 0 { + fs.enforceMsgPerSubjectLimit(false) + } + + // Grab first sequence for check below while we have lock. + firstSeq := fs.state.FirstSeq + fs.mu.Unlock() + + // If the stream has an initial sequence number then make sure we + // have purged up until that point. We will do this only if the + // recovered first sequence number is before our configured first + // sequence. Need to do this locked as by now the age check timer + // has started. + if cfg.FirstSeq > 0 && firstSeq < cfg.FirstSeq { + if _, err := fs.purge(cfg.FirstSeq); err != nil { + return nil, err + } + } + + // Write our meta data if it does not exist or is zero'd out. + meta := filepath.Join(fcfg.StoreDir, JetStreamMetaFile) + fi, err := os.Stat(meta) + if err != nil && os.IsNotExist(err) || fi != nil && fi.Size() == 0 { if err := fs.writeStreamMeta(); err != nil { return nil, err } } - fs.syncTmr = time.AfterFunc(fs.fcfg.SyncInterval, fs.syncBlocks) + // If we expect to be encrypted check that what we are restoring is not plaintext. + // This can happen on snapshot restores or conversions. + if fs.prf != nil { + if _, err := os.Stat(keyFile); err != nil && os.IsNotExist(err) { + if err := fs.writeStreamMeta(); err != nil { + return nil, err + } + } + } + + // Setup our sync timer. + fs.setSyncTimer() + + // Spin up the go routine that will write out our full state stream index. + go fs.flushStreamStateLoop(fs.qch, fs.fsld) return fs, nil } +// Lock all existing message blocks. +// Lock held on entry. +func (fs *fileStore) lockAllMsgBlocks() { + for _, mb := range fs.blks { + mb.mu.Lock() + } +} + +// Unlock all existing message blocks. +// Lock held on entry. +func (fs *fileStore) unlockAllMsgBlocks() { + for _, mb := range fs.blks { + mb.mu.Unlock() + } +} + func (fs *fileStore) UpdateConfig(cfg *StreamConfig) error { + start := time.Now() + defer func() { + if took := time.Since(start); took > time.Minute { + fs.warn("UpdateConfig took %v", took.Round(time.Millisecond)) + } + }() + if fs.isClosed() { return ErrStoreClosed } - - if cfg.Name == "" { + if cfg.Name == _EMPTY_ { return fmt.Errorf("name required") } if cfg.Storage != FileStorage { return fmt.Errorf("fileStore requires file storage type in config") } + if cfg.MaxMsgsPer < -1 { + cfg.MaxMsgsPer = -1 + } fs.mu.Lock() new_cfg := FileStreamInfo{Created: fs.cfg.Created, StreamConfig: *cfg} old_cfg := fs.cfg + // The reference story has changed here, so this full msg block lock + // may not be needed. + fs.lockAllMsgBlocks() fs.cfg = new_cfg + fs.unlockAllMsgBlocks() if err := fs.writeStreamMeta(); err != nil { + fs.lockAllMsgBlocks() fs.cfg = old_cfg + fs.unlockAllMsgBlocks() fs.mu.Unlock() return err } + + // Create or delete the THW if needed. + if cfg.AllowMsgTTL && fs.ttls == nil { + fs.recoverTTLState() + } else if !cfg.AllowMsgTTL && fs.ttls != nil { + fs.ttls = nil + } + // Limits checks and enforcement. fs.enforceMsgLimit() fs.enforceBytesLimit() + // Do age timers. if fs.ageChk == nil && fs.cfg.MaxAge != 0 { fs.startAgeChk() @@ -355,2285 +676,9575 @@ func (fs *fileStore) UpdateConfig(cfg *StreamConfig) error { if fs.ageChk != nil && fs.cfg.MaxAge == 0 { fs.ageChk.Stop() fs.ageChk = nil + fs.ageChkTime = 0 + } + + if fs.cfg.MaxMsgsPer > 0 && (old_cfg.MaxMsgsPer == 0 || fs.cfg.MaxMsgsPer < old_cfg.MaxMsgsPer) { + fs.enforceMsgPerSubjectLimit(true) } fs.mu.Unlock() - if cfg.MaxAge != 0 { + if cfg.MaxAge != 0 || cfg.AllowMsgTTL { fs.expireMsgs() } return nil } -func dynBlkSize(retention RetentionPolicy, maxBytes int64) uint64 { +func dynBlkSize(retention RetentionPolicy, maxBytes int64, encrypted bool) uint64 { if maxBytes > 0 { blkSize := (maxBytes / 4) + 1 // (25% overhead) // Round up to nearest 100 if m := blkSize % 100; m != 0 { blkSize += 100 - m } - if blkSize < FileStoreMinBlkSize { + if blkSize <= FileStoreMinBlkSize { blkSize = FileStoreMinBlkSize - } - if blkSize > FileStoreMaxBlkSize { + } else if blkSize >= FileStoreMaxBlkSize { blkSize = FileStoreMaxBlkSize + } else { + blkSize = defaultMediumBlockSize + } + if encrypted && blkSize > maximumEncryptedBlockSize { + // Notes on this below. + blkSize = maximumEncryptedBlockSize } return uint64(blkSize) } - if retention == LimitsPolicy { + switch { + case encrypted: + // In the case of encrypted stores, large blocks can result in worsened perf + // since many writes on disk involve re-encrypting the entire block. For now, + // we will enforce a cap on the block size when encryption is enabled to avoid + // this. + return maximumEncryptedBlockSize + case retention == LimitsPolicy: // TODO(dlc) - Make the blocksize relative to this if set. - return defaultStreamBlockSize - } else { + return defaultLargeBlockSize + default: // TODO(dlc) - Make the blocksize relative to this if set. - return defaultOtherBlockSize + return defaultMediumBlockSize } } -// Write out meta and the checksum. -// Lock should be held. -func (fs *fileStore) writeStreamMeta() error { - meta := path.Join(fs.fcfg.StoreDir, JetStreamMetaFile) - if _, err := os.Stat(meta); err != nil && !os.IsNotExist(err) { - return err - } - b, err := json.MarshalIndent(fs.cfg, _EMPTY_, " ") - if err != nil { - return err - } - if err := ioutil.WriteFile(meta, b, 0644); err != nil { - return err - } - fs.hh.Reset() - fs.hh.Write(b) - checksum := hex.EncodeToString(fs.hh.Sum(nil)) - sum := path.Join(fs.fcfg.StoreDir, JetStreamMetaFileSum) - if err := ioutil.WriteFile(sum, []byte(checksum), 0644); err != nil { - return err +func genEncryptionKey(sc StoreCipher, seed []byte) (ek cipher.AEAD, err error) { + if sc == ChaCha { + ek, err = chacha20poly1305.NewX(seed) + } else if sc == AES { + block, e := aes.NewCipher(seed) + if e != nil { + return nil, e + } + ek, err = cipher.NewGCMWithNonceSize(block, block.BlockSize()) + } else { + err = errUnknownCipher } - return nil + return ek, err } -const msgHdrSize = 22 -const checksumSize = 8 +// Generate an asset encryption key from the context and server PRF. +func (fs *fileStore) genEncryptionKeys(context string) (aek cipher.AEAD, bek cipher.Stream, seed, encrypted []byte, err error) { + if fs.prf == nil { + return nil, nil, nil, nil, errNoEncryption + } + // Generate key encryption key. + rb, err := fs.prf([]byte(context)) + if err != nil { + return nil, nil, nil, nil, err + } -// This is the max room needed for index header. -const indexHdrSize = 7*binary.MaxVarintLen64 + hdrLen + checksumSize + sc := fs.fcfg.Cipher -func (fs *fileStore) recoverMsgBlock(fi os.FileInfo, index uint64) *msgBlock { - var le = binary.LittleEndian + kek, err := genEncryptionKey(sc, rb) + if err != nil { + return nil, nil, nil, nil, err + } + // Generate random asset encryption key seed. - mb := &msgBlock{index: index, cexp: fs.fcfg.CacheExpire} + const seedSize = 32 + seed = make([]byte, seedSize) + if n, err := rand.Read(seed); err != nil { + return nil, nil, nil, nil, err + } else if n != seedSize { + return nil, nil, nil, nil, fmt.Errorf("not enough seed bytes read (%d != %d", n, seedSize) + } - mdir := path.Join(fs.fcfg.StoreDir, msgDir) - mb.mfn = path.Join(mdir, fi.Name()) - mb.ifn = path.Join(mdir, fmt.Sprintf(indexScan, index)) + aek, err = genEncryptionKey(sc, seed) + if err != nil { + return nil, nil, nil, nil, err + } - if mb.hh == nil { - key := sha256.Sum256(fs.hashKeyForBlock(index)) - mb.hh, _ = highwayhash.New64(key[:]) + // Generate our nonce. Use same buffer to hold encrypted seed. + nonce := make([]byte, kek.NonceSize(), kek.NonceSize()+len(seed)+kek.Overhead()) + if n, err := rand.Read(nonce); err != nil { + return nil, nil, nil, nil, err + } else if n != len(nonce) { + return nil, nil, nil, nil, fmt.Errorf("not enough nonce bytes read (%d != %d)", n, len(nonce)) } - // Open up the message file, but we will try to recover from the index file. - // We will check that the last checksums match. - file, err := os.Open(mb.mfn) + bek, err = genBlockEncryptionKey(sc, seed[:], nonce) if err != nil { - return nil + return nil, nil, nil, nil, err } - defer file.Close() - // Read our index file. Use this as source of truth if possible. - if err := mb.readIndexInfo(); err == nil { - // Quick sanity check here. - // Note this only checks that the message blk file is not newer then this file. - var lchk [8]byte - file.ReadAt(lchk[:], fi.Size()-8) - if bytes.Equal(lchk[:], mb.lchk[:]) { - fs.blks = append(fs.blks, mb) - return mb + return aek, bek, seed, kek.Seal(nonce, nonce, seed, nil), nil +} + +// Will generate the block encryption key. +func genBlockEncryptionKey(sc StoreCipher, seed, nonce []byte) (cipher.Stream, error) { + if sc == ChaCha { + return chacha20.NewUnauthenticatedCipher(seed, nonce) + } else if sc == AES { + block, err := aes.NewCipher(seed) + if err != nil { + return nil, err } - // Fall back on the data file itself. We will keep the delete map if present. - mb.msgs = 0 - mb.bytes = 0 - mb.first.seq = 0 + return cipher.NewCTR(block, nonce), nil } + return nil, errUnknownCipher +} - addToDmap := func(seq uint64) { - if seq == 0 { - return +// Lock should be held. +func (fs *fileStore) recoverAEK() error { + if fs.prf != nil && fs.aek == nil { + ekey, err := os.ReadFile(filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFileKey)) + if err != nil { + return err + } + rb, err := fs.prf([]byte(fs.cfg.Name)) + if err != nil { + return err } - if mb.dmap == nil { - mb.dmap = make(map[uint64]struct{}) + kek, err := genEncryptionKey(fs.fcfg.Cipher, rb) + if err != nil { + return err } - mb.dmap[seq] = struct{}{} - } - - // Use data file itself to rebuild. - var hdr [msgHdrSize]byte - var offset int64 - - for { - if _, err := file.ReadAt(hdr[:], offset); err != nil { - // FIXME(dlc) - If this is not EOF we probably should try to fix. - break + ns := kek.NonceSize() + seed, err := kek.Open(nil, ekey[:ns], ekey[ns:], nil) + if err != nil { + return err } - rl := le.Uint32(hdr[0:]) - seq := le.Uint64(hdr[4:]) - - // Can't recover with zero record length. - if rl == 0 { - return nil + aek, err := genEncryptionKey(fs.fcfg.Cipher, seed) + if err != nil { + return err } + fs.aek = aek + } + return nil +} - // This is an old erased message, or a new one that we can track. - if seq == 0 || seq&ebit != 0 { - seq = seq &^ ebit - addToDmap(seq) - offset += int64(rl) - continue +// Lock should be held. +func (fs *fileStore) setupAEK() error { + if fs.prf != nil && fs.aek == nil { + key, _, _, encrypted, err := fs.genEncryptionKeys(fs.cfg.Name) + if err != nil { + return err } - ts := int64(le.Uint64(hdr[12:])) - if mb.first.seq == 0 { - mb.first.seq = seq - mb.first.ts = ts + keyFile := filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFileKey) + if _, err := os.Stat(keyFile); err != nil && !os.IsNotExist(err) { + return err } - mb.last.seq = seq - mb.last.ts = ts - - mb.msgs++ - mb.bytes += uint64(rl) - offset += int64(rl) + err = fs.writeFileWithOptionalSync(keyFile, encrypted, defaultFilePerms) + if err != nil { + return err + } + // Set our aek. + fs.aek = key } - // Rewrite this to make sure we are sync'd. - mb.writeIndexInfo() - fs.blks = append(fs.blks, mb) - fs.lmb = mb - return mb + return nil } -func (fs *fileStore) recoverMsgs() error { - fs.mu.Lock() - defer fs.mu.Unlock() - - // Check for any left over purged messages. - pdir := path.Join(fs.fcfg.StoreDir, purgeDir) - if _, err := os.Stat(pdir); err == nil { - os.RemoveAll(pdir) +// Write out meta and the checksum. +// Lock should be held. +func (fs *fileStore) writeStreamMeta() error { + if err := fs.setupAEK(); err != nil { + return err } - mdir := path.Join(fs.fcfg.StoreDir, msgDir) - fis, err := ioutil.ReadDir(mdir) + meta := filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFile) + if _, err := os.Stat(meta); err != nil && !os.IsNotExist(err) { + return err + } + b, err := json.Marshal(fs.cfg) if err != nil { - return errNotReadable + return err } - - // Recover all of the msg blocks. - // These can come in a random order, so account for that. - for _, fi := range fis { - var index uint64 - if n, err := fmt.Sscanf(fi.Name(), blkScan, &index); err == nil && n == 1 { - if mb := fs.recoverMsgBlock(fi, index); mb != nil { - if fs.state.FirstSeq == 0 || mb.first.seq < fs.state.FirstSeq { - fs.state.FirstSeq = mb.first.seq - fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() - } - if mb.last.seq > fs.state.LastSeq { - fs.state.LastSeq = mb.last.seq - fs.state.LastTime = time.Unix(0, mb.last.ts).UTC() - } - fs.state.Msgs += mb.msgs - fs.state.Bytes += mb.bytes - } + // Encrypt if needed. + if fs.aek != nil { + nonce := make([]byte, fs.aek.NonceSize(), fs.aek.NonceSize()+len(b)+fs.aek.Overhead()) + if n, err := rand.Read(nonce); err != nil { + return err + } else if n != len(nonce) { + return fmt.Errorf("not enough nonce bytes read (%d != %d)", n, len(nonce)) } + b = fs.aek.Seal(nonce, nonce, b, nil) } - // Now make sure to sort blks for efficient lookup later with selectMsgBlock(). - if len(fs.blks) > 0 { - sort.Slice(fs.blks, func(i, j int) bool { return fs.blks[i].index < fs.blks[j].index }) - fs.lmb = fs.blks[len(fs.blks)-1] - err = fs.enableLastMsgBlockForWriting() - } else { - _, err = fs.newMsgBlockForWrite() + err = fs.writeFileWithOptionalSync(meta, b, defaultFilePerms) + if err != nil { + return err } - + fs.hh.Reset() + fs.hh.Write(b) + var hb [highwayhash.Size64]byte + checksum := hex.EncodeToString(fs.hh.Sum(hb[:0])) + sum := filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFileSum) + err = fs.writeFileWithOptionalSync(sum, []byte(checksum), defaultFilePerms) if err != nil { return err } + return nil +} - // Limits checks and enforcement. - fs.enforceMsgLimit() - fs.enforceBytesLimit() +// Pools to recycle the blocks to help with memory pressure. +var blkPoolBig sync.Pool // 16MB +var blkPoolMedium sync.Pool // 8MB +var blkPoolSmall sync.Pool // 2MB - // Do age checks too, make sure to call in place. - if fs.cfg.MaxAge != 0 && fs.state.Msgs > 0 { - fs.startAgeChk() - fs.expireMsgsLocked() - } - return nil -} - -// GetSeqFromTime looks for the first sequence number that has -// the message with >= timestamp. -// FIXME(dlc) - inefficient, and dumb really. Make this better. -func (fs *fileStore) GetSeqFromTime(t time.Time) uint64 { - fs.mu.RLock() - lastSeq := fs.state.LastSeq - closed := fs.closed - fs.mu.RUnlock() - - if closed { - return 0 - } - - mb := fs.selectMsgBlockForStart(t) - if mb == nil { - return lastSeq + 1 +// Get a new msg block based on sz estimate. +func getMsgBlockBuf(sz int) (buf []byte) { + var pb any + if sz <= defaultSmallBlockSize { + pb = blkPoolSmall.Get() + } else if sz <= defaultMediumBlockSize { + pb = blkPoolMedium.Get() + } else { + pb = blkPoolBig.Get() } - - mb.mu.RLock() - fseq := mb.first.seq - lseq := mb.last.seq - mb.mu.RUnlock() - - // Linear search, hence the dumb part.. - ts := t.UnixNano() - for seq := fseq; seq <= lseq; seq++ { - sm, _ := mb.fetchMsg(seq) - if sm != nil && sm.ts >= ts { - return sm.seq + if pb != nil { + buf = *(pb.(*[]byte)) + } else { + // Here we need to make a new blk. + // If small leave as is.. + if sz > defaultSmallBlockSize && sz <= defaultMediumBlockSize { + sz = defaultMediumBlockSize + } else if sz > defaultMediumBlockSize { + sz = defaultLargeBlockSize } + buf = make([]byte, sz) } - return 0 + return buf[:0] } -// RegisterStorageUpdates registers a callback for updates to storage changes. -// It will present number of messages and bytes as a signed integer and an -// optional sequence number of the message if a single. -func (fs *fileStore) RegisterStorageUpdates(cb StorageUpdateHandler) { - fs.mu.Lock() - fs.scb = cb - bsz := fs.state.Bytes - fs.mu.Unlock() - if cb != nil && bsz > 0 { - cb(0, int64(bsz), 0, _EMPTY_) +// Recycle the msg block. +func recycleMsgBlockBuf(buf []byte) { + if buf == nil || cap(buf) < defaultSmallBlockSize { + return + } + // Make sure to reset before placing back into pool. + buf = buf[:0] + + // We need to make sure the load code gets a block that can fit the maximum for a size block. + // E.g. 8, 16 etc. otherwise we thrash and actually make things worse by pulling it out, and putting + // it right back in and making a new []byte. + // From above we know its already >= defaultSmallBlockSize + if sz := cap(buf); sz < defaultMediumBlockSize { + blkPoolSmall.Put(&buf) + } else if sz < defaultLargeBlockSize { + blkPoolMedium.Put(&buf) + } else { + blkPoolBig.Put(&buf) } } -// Helper to get hash key for specific message block. -// Lock should be held -func (fs *fileStore) hashKeyForBlock(index uint64) []byte { - return []byte(fmt.Sprintf("%s-%d", fs.cfg.Name, index)) -} +const ( + msgHdrSize = 22 + checksumSize = 8 + emptyRecordLen = msgHdrSize + checksumSize +) -// This rolls to a new append msg block. // Lock should be held. -func (fs *fileStore) newMsgBlockForWrite() (*msgBlock, error) { - index := uint64(1) - if fs.lmb != nil { - index = fs.lmb.index + 1 - } - - mb := &msgBlock{index: index, cexp: fs.fcfg.CacheExpire} +func (fs *fileStore) noTrackSubjects() bool { + return !(fs.psim.Size() > 0 || len(fs.cfg.Subjects) > 0 || fs.cfg.Mirror != nil || len(fs.cfg.Sources) > 0) +} - // Now do local hash. - key := sha256.Sum256(fs.hashKeyForBlock(index)) - hh, err := highwayhash.New64(key[:]) - if err != nil { - return nil, fmt.Errorf("could not create hash: %v", err) +// Will init the basics for a message block. +func (fs *fileStore) initMsgBlock(index uint32) *msgBlock { + mb := &msgBlock{ + fs: fs, + index: index, + cexp: fs.fcfg.CacheExpire, + fexp: fs.fcfg.SubjectStateExpire, + noTrack: fs.noTrackSubjects(), + syncAlways: fs.fcfg.SyncAlways, } - mb.hh = hh - mdir := path.Join(fs.fcfg.StoreDir, msgDir) - mb.mfn = path.Join(mdir, fmt.Sprintf(blkScan, mb.index)) - mfd, err := os.OpenFile(mb.mfn, os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - mb.dirtyCloseWithRemove(true) - return nil, fmt.Errorf("Error creating msg block file [%q]: %v", mb.mfn, err) - } - mb.mfd = mfd + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + mb.mfn = filepath.Join(mdir, fmt.Sprintf(blkScan, index)) - mb.ifn = path.Join(mdir, fmt.Sprintf(indexScan, mb.index)) - ifd, err := os.OpenFile(mb.ifn, os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - mb.dirtyCloseWithRemove(true) - return nil, fmt.Errorf("Error creating msg index file [%q]: %v", mb.mfn, err) + if mb.hh == nil { + key := sha256.Sum256(fs.hashKeyForBlock(index)) + mb.hh, _ = highwayhash.NewDigest64(key[:]) } - mb.ifd = ifd - - // Set cache time to creation time to start. - ts := time.Now().UnixNano() - mb.llts, mb.lrts, mb.lwts = ts, ts, ts - - // Remember our last sequence number. - mb.first.seq = fs.state.LastSeq + 1 - mb.last.seq = fs.state.LastSeq - - // We know we will need this so go ahead and spin up. - mb.spinUpFlushLoop() - - // Add to our list of blocks and mark as last. - fs.blks = append(fs.blks, mb) - fs.lmb = mb - - return mb, nil + return mb } -// Make sure we can write to the last message block. -// Lock should be held. -func (fs *fileStore) enableLastMsgBlockForWriting() error { - mb := fs.lmb - if mb == nil { - return fmt.Errorf("no last message block assigned, can not enable for writing") - } - if mb.mfd != nil { - return nil - } - mfd, err := os.OpenFile(mb.mfn, os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - return fmt.Errorf("error opening msg block file [%q]: %v", mb.mfn, err) +// Check for encryption, we do not load keys on startup anymore so might need to load them here. +// Lock for fs should be held. +func (mb *msgBlock) checkAndLoadEncryption() error { + if mb.fs != nil && mb.fs.prf != nil && (mb.aek == nil || mb.bek == nil) { + if err := mb.fs.loadEncryptionForMsgBlock(mb); err != nil { + return err + } } - mb.mfd = mfd return nil } -// Store stores a message. We hold the main filestore lock for any write operation. -func (fs *fileStore) StoreMsg(subj string, hdr, msg []byte) (uint64, int64, error) { - fs.mu.Lock() - - if fs.closed { - fs.mu.Unlock() - return 0, 0, ErrStoreClosed +// Lock for fs should be held. +func (fs *fileStore) loadEncryptionForMsgBlock(mb *msgBlock) error { + if fs.prf == nil { + return nil } - // Check if we are discarding new messages when we reach the limit. - if fs.cfg.Discard == DiscardNew { - if fs.cfg.MaxMsgs > 0 && fs.state.Msgs >= uint64(fs.cfg.MaxMsgs) { - fs.mu.Unlock() - return 0, 0, ErrMaxMsgs + var createdKeys bool + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + ekey, err := os.ReadFile(filepath.Join(mdir, fmt.Sprintf(keyScan, mb.index))) + if err != nil { + // We do not seem to have keys even though we should. Could be a plaintext conversion. + // Create the keys and we will double check below. + if err := fs.genEncryptionKeysForBlock(mb); err != nil { + return err } - if fs.cfg.MaxBytes > 0 && fs.state.Bytes+uint64(len(msg)+len(hdr)) >= uint64(fs.cfg.MaxBytes) { - fs.mu.Unlock() - return 0, 0, ErrMaxBytes + createdKeys = true + } else { + if len(ekey) < minBlkKeySize { + return errBadKeySize + } + // Recover key encryption key. + rb, err := fs.prf([]byte(fmt.Sprintf("%s:%d", fs.cfg.Name, mb.index))) + if err != nil { + return err } - } - - seq := fs.state.LastSeq + 1 - n, ts, err := fs.writeMsgRecord(seq, subj, hdr, msg) - if err != nil { - fs.mu.Unlock() - return 0, 0, err + sc := fs.fcfg.Cipher + kek, err := genEncryptionKey(sc, rb) + if err != nil { + return err + } + ns := kek.NonceSize() + seed, err := kek.Open(nil, ekey[:ns], ekey[ns:], nil) + if err != nil { + // We may be here on a cipher conversion, so attempt to convert. + if err = mb.convertCipher(); err != nil { + return err + } + } else { + mb.seed, mb.nonce = seed, ekey[:ns] + } + mb.aek, err = genEncryptionKey(sc, mb.seed) + if err != nil { + return err + } + if mb.bek, err = genBlockEncryptionKey(sc, mb.seed, mb.nonce); err != nil { + return err + } } - if fs.state.Msgs == 0 { - fs.state.FirstSeq = seq - fs.state.FirstTime = time.Unix(0, ts).UTC() + // If we created keys here, let's check the data and if it is plaintext convert here. + if createdKeys { + if err := mb.convertToEncrypted(); err != nil { + return err + } } - fs.state.Msgs++ - fs.state.Bytes += n - fs.state.LastSeq = seq - fs.state.LastTime = time.Unix(0, ts).UTC() + return nil +} - // Limits checks and enforcement. - // If they do any deletions they will update the - // byte count on their own, so no need to compensate. - fs.enforceMsgLimit() - fs.enforceBytesLimit() +// Load a last checksum if needed from the block file. +// Lock should be held. +func (mb *msgBlock) ensureLastChecksumLoaded() { + var empty [8]byte + if mb.lchk != empty { + return + } + copy(mb.lchk[0:], mb.lastChecksum()) +} - // Check if we have and need the age expiration timer running. - if fs.ageChk == nil && fs.cfg.MaxAge != 0 { - fs.startAgeChk() +// Lock held on entry +func (fs *fileStore) recoverMsgBlock(index uint32) (*msgBlock, error) { + mb := fs.initMsgBlock(index) + // Open up the message file, but we will try to recover from the index file. + // We will check that the last checksums match. + file, err := mb.openBlock() + if err != nil { + return nil, err } - cb := fs.scb - fs.mu.Unlock() + defer file.Close() - // Update the upper layers regarding storage used. - if cb != nil { - cb(1, int64(n), seq, subj) + if fi, err := file.Stat(); fi != nil { + mb.rbytes = uint64(fi.Size()) + } else { + return nil, err } - return seq, ts, nil -} + // Make sure encryption loaded if needed. + fs.loadEncryptionForMsgBlock(mb) -// skipMsg will update this message block for a skipped message. -// If we do not have any messages, just update the metadata, otherwise -// we will place and empty record marking the sequence as used. The -// sequence will be marked erased. -// fs lock should be held. -func (mb *msgBlock) skipMsg(seq uint64, now time.Time) { - if mb == nil { - return + // Grab last checksum from main block file. + var lchk [8]byte + if mb.rbytes >= checksumSize { + if mb.bek != nil { + if buf, _ := mb.loadBlock(nil); len(buf) >= checksumSize { + mb.bek.XORKeyStream(buf, buf) + copy(lchk[0:], buf[len(buf)-checksumSize:]) + } + } else { + file.ReadAt(lchk[:], int64(mb.rbytes)-checksumSize) + } } - var needsRecord bool - mb.mu.Lock() - // If we are empty can just do meta. - if mb.msgs == 0 { - mb.last.seq = seq - mb.last.ts = now.UnixNano() - mb.first.seq = seq + 1 - mb.first.ts = now.UnixNano() + file.Close() - } else { - needsRecord = true - if mb.dmap == nil { - mb.dmap = make(map[uint64]struct{}) + // Read our index file. Use this as source of truth if possible. + // This not applicable in >= 2.10 servers. Here for upgrade paths from < 2.10. + if err := mb.readIndexInfo(); err == nil { + // Quick sanity check here. + // Note this only checks that the message blk file is not newer then this file, or is empty and we expect empty. + if (mb.rbytes == 0 && mb.msgs == 0) || bytes.Equal(lchk[:], mb.lchk[:]) { + if mb.msgs > 0 && !mb.noTrack && fs.psim != nil { + fs.populateGlobalPerSubjectInfo(mb) + // Try to dump any state we needed on recovery. + mb.tryForceExpireCacheLocked() + } + fs.addMsgBlock(mb) + return mb, nil } - mb.dmap[seq] = struct{}{} - mb.msgs-- - mb.bytes -= emptyRecordLen } - mb.mu.Unlock() - if needsRecord { - mb.writeMsgRecord(emptyRecordLen, seq|ebit, _EMPTY_, nil, nil, now.UnixNano()) - } else { - mb.kickFlusher() + // If we get data loss rebuilding the message block state record that with the fs itself. + ld, tombs, _ := mb.rebuildState() + if ld != nil { + fs.addLostData(ld) } -} - -// SkipMsg will use the next sequence number but not store anything. -func (fs *fileStore) SkipMsg() uint64 { - fs.mu.Lock() - defer fs.mu.Unlock() - - // Grab time. - now := time.Now().UTC() - seq := fs.state.LastSeq + 1 - fs.state.LastSeq = seq - fs.state.LastTime = now - if fs.state.Msgs == 0 { - fs.state.FirstSeq = seq - fs.state.FirstTime = now + // Collect all tombstones. + if len(tombs) > 0 { + fs.tombs = append(fs.tombs, tombs...) } - if seq == fs.state.FirstSeq { - fs.state.FirstSeq = seq + 1 - fs.state.FirstTime = now + + if mb.msgs > 0 && !mb.noTrack && fs.psim != nil { + fs.populateGlobalPerSubjectInfo(mb) + // Try to dump any state we needed on recovery. + mb.tryForceExpireCacheLocked() } - fs.lmb.skipMsg(seq, now) - return seq + mb.closeFDs() + fs.addMsgBlock(mb) + + return mb, nil } -// Will check the msg limit and drop firstSeq msg if needed. -// Lock should be held. -func (fs *fileStore) enforceMsgLimit() { - if fs.cfg.MaxMsgs <= 0 || fs.state.Msgs <= uint64(fs.cfg.MaxMsgs) { - return - } - for nmsgs := fs.state.Msgs; nmsgs > uint64(fs.cfg.MaxMsgs); nmsgs = fs.state.Msgs { - fs.deleteFirstMsgLocked() +func (fs *fileStore) lostData() *LostStreamData { + fs.mu.RLock() + defer fs.mu.RUnlock() + if fs.ld == nil { + return nil } + nld := *fs.ld + return &nld } -// Will check the bytes limit and drop msgs if needed. // Lock should be held. -func (fs *fileStore) enforceBytesLimit() { - if fs.cfg.MaxBytes <= 0 || fs.state.Bytes <= uint64(fs.cfg.MaxBytes) { +func (fs *fileStore) addLostData(ld *LostStreamData) { + if ld == nil { return } - for bs := fs.state.Bytes; bs > uint64(fs.cfg.MaxBytes); bs = fs.state.Bytes { - fs.deleteFirstMsgLocked() + if fs.ld != nil { + var added bool + for _, seq := range ld.Msgs { + if _, found := fs.ld.exists(seq); !found { + fs.ld.Msgs = append(fs.ld.Msgs, seq) + added = true + } + } + if added { + msgs := fs.ld.Msgs + slices.Sort(msgs) + fs.ld.Bytes += ld.Bytes + } + } else { + fs.ld = ld } } -// Lock should be held but will be released during actual remove. -func (fs *fileStore) deleteFirstMsgLocked() (bool, error) { - fs.mu.Unlock() - defer fs.mu.Lock() - return fs.removeMsg(fs.state.FirstSeq, false) -} - -// Lock should NOT be held. -func (fs *fileStore) deleteFirstMsg() (bool, error) { - fs.mu.RLock() - seq := fs.state.FirstSeq - fs.mu.RUnlock() - return fs.removeMsg(seq, false) +// Helper to see if we already have this sequence reported in our lost data. +func (ld *LostStreamData) exists(seq uint64) (int, bool) { + i := slices.IndexFunc(ld.Msgs, func(i uint64) bool { + return i == seq + }) + return i, i > -1 } -// RemoveMsg will remove the message from this store. -// Will return the number of bytes removed. -func (fs *fileStore) RemoveMsg(seq uint64) (bool, error) { - return fs.removeMsg(seq, false) +func (fs *fileStore) removeFromLostData(seq uint64) { + if fs.ld == nil { + return + } + if i, found := fs.ld.exists(seq); found { + fs.ld.Msgs = append(fs.ld.Msgs[:i], fs.ld.Msgs[i+1:]...) + if len(fs.ld.Msgs) == 0 { + fs.ld = nil + } + } } -func (fs *fileStore) EraseMsg(seq uint64) (bool, error) { - return fs.removeMsg(seq, true) +func (fs *fileStore) rebuildState(ld *LostStreamData) { + fs.mu.Lock() + defer fs.mu.Unlock() + fs.rebuildStateLocked(ld) } -// Remove a message, optionally rewriting the mb file. -func (fs *fileStore) removeMsg(seq uint64, secure bool) (bool, error) { - fs.mu.Lock() +// Lock should be held. +func (fs *fileStore) rebuildStateLocked(ld *LostStreamData) { + fs.addLostData(ld) - if fs.closed { - fs.mu.Unlock() - return false, ErrStoreClosed - } - if fs.sips > 0 { - fs.mu.Unlock() - return false, ErrStoreSnapshotInProgress - } + fs.state.Msgs, fs.state.Bytes = 0, 0 + fs.state.FirstSeq, fs.state.LastSeq = 0, 0 - mb := fs.selectMsgBlock(seq) - if mb == nil { - var err = ErrStoreEOF - if seq <= fs.state.LastSeq { - err = ErrStoreMsgNotFound + for _, mb := range fs.blks { + mb.mu.RLock() + fs.state.Msgs += mb.msgs + fs.state.Bytes += mb.bytes + fseq := atomic.LoadUint64(&mb.first.seq) + if fs.state.FirstSeq == 0 || (fseq < fs.state.FirstSeq && mb.first.ts != 0) { + fs.state.FirstSeq = fseq + if mb.first.ts == 0 { + fs.state.FirstTime = time.Time{} + } else { + fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() + } } - fs.mu.Unlock() - return false, err + // Preserve last time, could have erased the last message in one block, and then + // have a tombstone with the proper timestamp afterward in another block + if lseq := atomic.LoadUint64(&mb.last.seq); lseq >= fs.state.LastSeq { + fs.state.LastSeq = lseq + if mb.last.ts == 0 { + fs.state.LastTime = time.Time{} + } else { + fs.state.LastTime = time.Unix(0, mb.last.ts).UTC() + } + } + mb.mu.RUnlock() } +} + +// Attempt to convert the cipher used for this message block. +func (mb *msgBlock) convertCipher() error { + fs := mb.fs + sc := fs.fcfg.Cipher - // If we have a callback grab the message since we need the subject. - // TODO(dlc) - This will cause whole buffer to be loaded which I was trying - // to avoid. Maybe use side cache for subjects or understand when we really need them. - // Meaning if the stream above is only a single subject no need to store, this is just - // for updating stream pending for consumers. - var sm *fileStoredMsg - if fs.scb != nil { - sm, _ = mb.fetchMsg(seq) + var osc StoreCipher + switch sc { + case ChaCha: + osc = AES + case AES: + osc = ChaCha } - mb.mu.Lock() + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + ekey, err := os.ReadFile(filepath.Join(mdir, fmt.Sprintf(keyScan, mb.index))) + if err != nil { + return err + } + if len(ekey) < minBlkKeySize { + return errBadKeySize + } + type prfWithCipher struct { + keyGen + StoreCipher + } + var prfs []prfWithCipher + if fs.prf != nil { + prfs = append(prfs, prfWithCipher{fs.prf, sc}) + prfs = append(prfs, prfWithCipher{fs.prf, osc}) + } + if fs.oldprf != nil { + prfs = append(prfs, prfWithCipher{fs.oldprf, sc}) + prfs = append(prfs, prfWithCipher{fs.oldprf, osc}) + } - // Check cache. This should be very rare. - if mb.cache == nil || mb.cache.idx == nil { - mb.mu.Unlock() - fs.mu.Unlock() - if err := mb.loadMsgs(); err != nil { - return false, err + for _, prf := range prfs { + // Recover key encryption key. + rb, err := prf.keyGen([]byte(fmt.Sprintf("%s:%d", fs.cfg.Name, mb.index))) + if err != nil { + continue } - fs.mu.Lock() - mb.mu.Lock() + kek, err := genEncryptionKey(prf.StoreCipher, rb) + if err != nil { + continue + } + ns := kek.NonceSize() + seed, err := kek.Open(nil, ekey[:ns], ekey[ns:], nil) + if err != nil { + continue + } + nonce := ekey[:ns] + bek, err := genBlockEncryptionKey(prf.StoreCipher, seed, nonce) + if err != nil { + return err + } + + buf, _ := mb.loadBlock(nil) + bek.XORKeyStream(buf, buf) + // Check for compression, and make sure we can parse with old cipher and key file. + if nbuf, err := mb.decompressIfNeeded(buf); err != nil { + return err + } else if _, _, err = mb.rebuildStateFromBufLocked(nbuf, false); err != nil { + return err + } else if err = mb.indexCacheBuf(nbuf); err != nil { + return err + } + + // Reset the cache since we just read everything in. + mb.cache = nil + + // Generate new keys. If we error for some reason then we will put + // the old keyfile back. + if err := fs.genEncryptionKeysForBlock(mb); err != nil { + keyFile := filepath.Join(mdir, fmt.Sprintf(keyScan, mb.index)) + fs.writeFileWithOptionalSync(keyFile, ekey, defaultFilePerms) + return err + } + mb.bek.XORKeyStream(buf, buf) + <-dios + err = os.WriteFile(mb.mfn, buf, defaultFilePerms) + dios <- struct{}{} + if err != nil { + return err + } + return nil } + return fmt.Errorf("unable to recover keys") +} - // See if the sequence numbers is still relevant. Check first and cache first. - if seq < mb.first.seq || seq < mb.cache.fseq || (seq-mb.cache.fseq) >= uint64(len(mb.cache.idx)) { - mb.mu.Unlock() - fs.mu.Unlock() - return false, nil +// Convert a plaintext block to encrypted. +func (mb *msgBlock) convertToEncrypted() error { + if mb.bek == nil { + return nil + } + buf, err := mb.loadBlock(nil) + if err != nil { + return err + } + // Check for compression. + if buf, err = mb.decompressIfNeeded(buf); err != nil { + return err + } else if _, _, err = mb.rebuildStateFromBufLocked(buf, false); err != nil { + return err + } else if err = mb.indexCacheBuf(buf); err != nil { + // This likely indicates this was already encrypted or corrupt. + mb.cache = nil + return err + } + // Undo cache from above for later. + mb.cache = nil + mb.bek.XORKeyStream(buf, buf) + <-dios + err = os.WriteFile(mb.mfn, buf, defaultFilePerms) + dios <- struct{}{} + if err != nil { + return err } + return nil +} - // Now check dmap if it is there. - if mb.dmap != nil { - if _, ok := mb.dmap[seq]; ok { - mb.mu.Unlock() - fs.mu.Unlock() - return false, nil +// Return the mb's index. +func (mb *msgBlock) getIndex() uint32 { + mb.mu.RLock() + defer mb.mu.RUnlock() + return mb.index +} + +// Rebuild the state of the blk based on what we have on disk in the N.blk file. +// We will return any lost data, and we will return any delete tombstones we encountered. +func (mb *msgBlock) rebuildState() (*LostStreamData, []uint64, error) { + mb.mu.Lock() + defer mb.mu.Unlock() + return mb.rebuildStateLocked() +} + +// Rebuild the state of the blk based on what we have on disk in the N.blk file. +// Lock should be held. +func (mb *msgBlock) rebuildStateLocked() (*LostStreamData, []uint64, error) { + // Remove the .fss file and clear any cache we have set. + mb.clearCacheAndOffset() + + buf, err := mb.loadBlock(nil) + defer recycleMsgBlockBuf(buf) + + if err != nil || len(buf) == 0 { + var ld *LostStreamData + // No data to rebuild from here. + if mb.msgs > 0 { + // We need to declare lost data here. + ld = &LostStreamData{Msgs: make([]uint64, 0, mb.msgs), Bytes: mb.bytes} + firstSeq, lastSeq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) + for seq := firstSeq; seq <= lastSeq; seq++ { + if !mb.dmap.Exists(seq) { + ld.Msgs = append(ld.Msgs, seq) + } + } + // Clear invalid state. We will let this blk be added in here. + mb.msgs, mb.bytes, mb.rbytes, mb.fss = 0, 0, 0, nil + mb.dmap.Empty() + atomic.StoreUint64(&mb.first.seq, atomic.LoadUint64(&mb.last.seq)+1) } + return ld, nil, err } - // Set cache timestamp for last remove. - mb.lrts = time.Now().UnixNano() - - // Grab record length from idx. - slot := seq - mb.cache.fseq - ri, rl, _, _ := mb.slotInfo(int(slot)) - msz := uint64(rl) + // Check if we need to decrypt. + if err = mb.encryptOrDecryptIfNeeded(buf); err != nil { + return nil, nil, err + } + // Check for compression. + if buf, err = mb.decompressIfNeeded(buf); err != nil { + return nil, nil, err + } + return mb.rebuildStateFromBufLocked(buf, true) +} - // Global stats - fs.state.Msgs-- - fs.state.Bytes -= msz +// Lock should be held. +func (mb *msgBlock) rebuildStateFromBufLocked(buf []byte, allowTruncate bool) (*LostStreamData, []uint64, error) { + var err error + startLastSeq := atomic.LoadUint64(&mb.last.seq) - // Now local mb updates. - mb.msgs-- - mb.bytes -= msz + // Clear state we need to rebuild. + mb.msgs, mb.bytes, mb.rbytes, mb.fss = 0, 0, 0, nil + atomic.StoreUint64(&mb.last.seq, 0) + mb.last.ts = 0 + firstNeedsSet := true - var shouldWriteIndex bool - var firstSeqNeedsUpdate bool + mb.rbytes = uint64(len(buf)) - if secure { - mb.eraseMsg(seq, int(ri), int(rl)) + addToDmap := func(seq uint64) { + if seq == 0 { + return + } + mb.dmap.Insert(seq) } - // Optimize for FIFO case. - if seq == mb.first.seq { - mb.selectNextFirst() - if mb.isEmpty() { - fs.removeMsgBlock(mb) - firstSeqNeedsUpdate = seq == fs.state.FirstSeq + var le = binary.LittleEndian + + truncate := func(index uint32) { + // There are cases where we're not allowed to truncate, like for an encrypted or compressed + // block since the index will be the decrypted and decompressed index. + if !allowTruncate { + return + } + + var fd *os.File + if mb.mfd != nil { + fd = mb.mfd } else { - shouldWriteIndex = true - if seq == fs.state.FirstSeq { - fs.state.FirstSeq = mb.first.seq // new one. - fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() + <-dios + fd, err = os.OpenFile(mb.mfn, os.O_RDWR, defaultFilePerms) + dios <- struct{}{} + if err == nil { + defer fd.Close() } } - } else { - // Out of order delete. - if mb.dmap == nil { - mb.dmap = make(map[uint64]struct{}) + if fd == nil { + return + } + if err := fd.Truncate(int64(index)); err == nil { + // Update our checksum. + if index >= 8 { + var lchk [8]byte + fd.ReadAt(lchk[:], int64(index-8)) + copy(mb.lchk[0:], lchk[:]) + } + fd.Sync() } - mb.dmap[seq] = struct{}{} - shouldWriteIndex = true } - var qch, fch chan struct{} - if shouldWriteIndex { - qch = mb.qch - fch = mb.fch + gatherLost := func(lb uint32) *LostStreamData { + var ld LostStreamData + for seq := atomic.LoadUint64(&mb.last.seq) + 1; seq <= startLastSeq; seq++ { + ld.Msgs = append(ld.Msgs, seq) + } + ld.Bytes = uint64(lb) + return &ld } - cb := fs.scb - mb.mu.Unlock() - // Kick outside of lock. - if shouldWriteIndex { - if qch == nil { - mb.spinUpFlushLoop() + // For tombstones that we find and collect. + var ( + tombstones []uint64 + maxTombstoneSeq uint64 + maxTombstoneTs int64 + ) + + // To detect gaps from compaction, and to ensure the sequence keeps moving up. + var last uint64 + var hb [highwayhash.Size64]byte + + updateLast := func(seq uint64, ts int64) { + // The sequence needs to only ever move up. + if seq <= last { + return } - select { - case fch <- struct{}{}: - default: + + // Check for any gaps from compaction, meaning no ebit entry. + if last > 0 && seq != last+1 && mb.msgs != 0 { + for dseq := last + 1; dseq < seq; dseq++ { + addToDmap(dseq) + } } + last = seq + atomic.StoreUint64(&mb.last.seq, last) + mb.last.ts = ts } - // If we emptied the current message block and the seq was state.First.Seq - // then we need to jump message blocks. - if firstSeqNeedsUpdate { - fs.selectNextFirst() + for index, lbuf := uint32(0), uint32(len(buf)); index < lbuf; { + if index+msgHdrSize > lbuf { + truncate(index) + return gatherLost(lbuf - index), tombstones, nil + } + + hdr := buf[index : index+msgHdrSize] + rl, slen := le.Uint32(hdr[0:]), int(le.Uint16(hdr[20:])) + + hasHeaders := rl&hbit != 0 + var ttl int64 + if mb.fs.ttls != nil && len(hdr) > 0 { + ttl, _ = getMessageTTL(hdr) + } + // Clear any headers bit that could be set. + rl &^= hbit + dlen := int(rl) - msgHdrSize + // Do some quick sanity checks here. + if dlen < 0 || slen > (dlen-recordHashSize) || dlen > int(rl) || index+rl > lbuf || rl > rlBadThresh { + truncate(index) + return gatherLost(lbuf - index), tombstones, errBadMsg{mb.mfn, fmt.Sprintf("sanity check failed (dlen %d slen %d rl %d index %d lbuf %d)", dlen, slen, rl, index, lbuf)} + } + + // Check for checksum failures before additional processing. + data := buf[index+msgHdrSize : index+rl] + if hh := mb.hh; hh != nil { + hh.Reset() + hh.Write(hdr[4:20]) + hh.Write(data[:slen]) + if hasHeaders { + hh.Write(data[slen+4 : dlen-recordHashSize]) + } else { + hh.Write(data[slen : dlen-recordHashSize]) + } + checksum := hh.Sum(hb[:0]) + if !bytes.Equal(checksum, data[len(data)-recordHashSize:]) { + truncate(index) + return gatherLost(lbuf - index), tombstones, errBadMsg{mb.mfn, "invalid checksum"} + } + copy(mb.lchk[0:], checksum) + } + + // Grab our sequence and timestamp. + seq := le.Uint64(hdr[4:]) + ts := int64(le.Uint64(hdr[12:])) + + // Check if this is a delete tombstone. + if seq&tbit != 0 { + seq = seq &^ tbit + // Need to process this here and make sure we have accounted for this properly. + tombstones = append(tombstones, seq) + if maxTombstoneSeq == 0 || seq > maxTombstoneSeq { + maxTombstoneSeq, maxTombstoneTs = seq, ts + } + index += rl + continue + } + + fseq := atomic.LoadUint64(&mb.first.seq) + // This is an old erased message, or a new one that we can track. + if seq == 0 || seq&ebit != 0 || seq < fseq { + seq = seq &^ ebit + if seq >= fseq { + updateLast(seq, ts) + if mb.msgs == 0 { + atomic.StoreUint64(&mb.first.seq, seq+1) + mb.first.ts = 0 + } else if seq != 0 { + // Only add to dmap if past recorded first seq and non-zero. + addToDmap(seq) + } + } + index += rl + continue + } + + // This is for when we have index info that adjusts for deleted messages + // at the head. So the first.seq will be already set here. If this is larger + // replace what we have with this seq. + if firstNeedsSet && seq >= fseq { + atomic.StoreUint64(&mb.first.seq, seq) + firstNeedsSet, mb.first.ts = false, ts + } + + // The sequence needs to only ever move up. + if seq <= last { + // Advance to next record. + // We've already accounted for this sequence and marked it as deleted. + index += rl + continue + } + if !mb.dmap.Exists(seq) { + mb.msgs++ + mb.bytes += uint64(rl) + if mb.fs.ttls != nil && ttl > 0 { + expires := time.Duration(ts) + (time.Second * time.Duration(ttl)) + mb.fs.ttls.Add(seq, int64(expires)) + mb.ttls++ + } + } + + updateLast(seq, ts) + + // Advance to next record. + index += rl } - fs.mu.Unlock() - // Storage updates. - if cb != nil { - subj := _EMPTY_ - if sm != nil { - subj = sm.subj + // For empty msg blocks make sure we recover last seq correctly based off of first. + // Or if we seem to have no messages but had a tombstone, which we use to remember + // sequences and timestamps now, use that to properly setup the first and last. + if mb.msgs == 0 { + fseq := atomic.LoadUint64(&mb.first.seq) + if fseq > 0 { + atomic.StoreUint64(&mb.last.seq, fseq-1) + } else if fseq == 0 && maxTombstoneSeq > 0 { + atomic.StoreUint64(&mb.first.seq, maxTombstoneSeq+1) + mb.first.ts = 0 + if mb.last.seq == 0 { + atomic.StoreUint64(&mb.last.seq, maxTombstoneSeq) + mb.last.ts = maxTombstoneTs + } } - delta := int64(msz) - cb(-1, -delta, seq, subj) } - return true, nil + return nil, tombstones, nil } -// Grab info from a slot. +// For doing warn logging. // Lock should be held. -func (mb *msgBlock) slotInfo(slot int) (uint32, uint32, bool, error) { - if mb.cache == nil || slot >= len(mb.cache.idx) { - return 0, 0, false, errPartialCache - } - bi := mb.cache.idx[slot] - ri := (bi &^ hbit) - hashChecked := (bi & hbit) != 0 - // Determine record length - var rl uint32 - if len(mb.cache.idx) > slot+1 { - ni := mb.cache.idx[slot+1] &^ hbit - rl = ni - ri - } else { - rl = mb.cache.lrl - } - if rl < msgHdrSize { - return 0, 0, false, errBadMsg +func (fs *fileStore) warn(format string, args ...any) { + // No-op if no server configured. + if fs.srv == nil { + return } - return uint32(ri), rl, hashChecked, nil -} - -func (fs *fileStore) isClosed() bool { - fs.mu.RLock() - closed := fs.closed - fs.mu.RUnlock() - return closed + fs.srv.Warnf(fmt.Sprintf("Filestore [%s] %s", fs.cfg.Name, format), args...) } -// Will spin up our flush loop. -func (mb *msgBlock) spinUpFlushLoop() { - mb.mu.Lock() - // Are we already running? - if mb.flusher { - mb.mu.Unlock() +// For doing debug logging. +// Lock should be held. +func (fs *fileStore) debug(format string, args ...any) { + // No-op if no server configured. + if fs.srv == nil { return } - mb.flusher = true - mb.fch = make(chan struct{}, 1) - mb.qch = make(chan struct{}) - fch, qch := mb.fch, mb.qch - mb.mu.Unlock() - - go mb.flushLoop(fch, qch) + fs.srv.Debugf(fmt.Sprintf("Filestore [%s] %s", fs.cfg.Name, format), args...) } -// Raw low level kicker for flush loops. -func kickFlusher(fch chan struct{}) { - if fch != nil { - select { - case fch <- struct{}{}: - default: - } +// Track local state but ignore timestamps here. +func updateTrackingState(state *StreamState, mb *msgBlock) { + if state.FirstSeq == 0 { + state.FirstSeq = mb.first.seq + } else if mb.first.seq < state.FirstSeq && mb.first.ts != 0 { + state.FirstSeq = mb.first.seq + } + if mb.last.seq > state.LastSeq { + state.LastSeq = mb.last.seq } + state.Msgs += mb.msgs + state.Bytes += mb.bytes } -// Kick flusher for this message block. -func (mb *msgBlock) kickFlusher() { - mb.mu.RLock() - defer mb.mu.RUnlock() - kickFlusher(mb.fch) +// Determine if our tracking states are the same. +func trackingStatesEqual(fs, mb *StreamState) bool { + // When a fs is brand new the fs state will have first seq of 0, but tracking mb may have 1. + // If either has a first sequence that is not 0 or 1 we will check if they are the same, otherwise skip. + if (fs.FirstSeq > 1 && mb.FirstSeq > 1) || mb.FirstSeq > 1 { + return fs.Msgs == mb.Msgs && fs.FirstSeq == mb.FirstSeq && fs.LastSeq == mb.LastSeq && fs.Bytes == mb.Bytes + } + return fs.Msgs == mb.Msgs && fs.LastSeq == mb.LastSeq && fs.Bytes == mb.Bytes } -func (mb *msgBlock) setInFlusher() { - mb.mu.Lock() - mb.flusher = true - mb.mu.Unlock() -} +// recoverFullState will attempt to receover our last full state and re-process any state changes +// that happened afterwards. +func (fs *fileStore) recoverFullState() (rerr error) { + fs.mu.Lock() + defer fs.mu.Unlock() -func (mb *msgBlock) clearInFlusher() { - mb.mu.Lock() - mb.flusher = false - mb.mu.Unlock() -} + // Check for any left over purged messages. + <-dios + pdir := filepath.Join(fs.fcfg.StoreDir, purgeDir) + if _, err := os.Stat(pdir); err == nil { + os.RemoveAll(pdir) + } + // Grab our stream state file and load it in. + fn := filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile) + buf, err := os.ReadFile(fn) + dios <- struct{}{} -// flushLoop watches for messages, index info, or recently closed msg block updates. -func (mb *msgBlock) flushLoop(fch, qch chan struct{}) { - mb.setInFlusher() - defer mb.clearInFlusher() + if err != nil { + if !os.IsNotExist(err) { + fs.warn("Could not read stream state file: %v", err) + } + return err + } - // Will use to test if we have meta data updates. - var firstSeq, lastSeq uint64 - var dmapLen int + const minLen = 32 + if len(buf) < minLen { + os.Remove(fn) + fs.warn("Stream state too short (%d bytes)", len(buf)) + return errCorruptState + } - infoChanged := func() bool { - mb.mu.RLock() - defer mb.mu.RUnlock() - var changed bool - if firstSeq != mb.first.seq || lastSeq != mb.last.seq || dmapLen != len(mb.dmap) { - changed = true - firstSeq, lastSeq = mb.first.seq, mb.last.seq - dmapLen = len(mb.dmap) + // The highwayhash will be on the end. Check that it still matches. + h := buf[len(buf)-highwayhash.Size64:] + buf = buf[:len(buf)-highwayhash.Size64] + fs.hh.Reset() + fs.hh.Write(buf) + var hb [highwayhash.Size64]byte + if !bytes.Equal(h, fs.hh.Sum(hb[:0])) { + os.Remove(fn) + fs.warn("Stream state checksum did not match") + return errCorruptState + } + + // Decrypt if needed. + // We can be setup for encryption but if this is a snapshot restore we will be missing the keyfile + // since snapshots strip encryption. + if fs.prf != nil && fs.aek != nil { + ns := fs.aek.NonceSize() + buf, err = fs.aek.Open(nil, buf[:ns], buf[ns:], nil) + if err != nil { + fs.warn("Stream state error reading encryption key: %v", err) + return err } - return changed } - for { - select { - case <-fch: - // If we have pending messages process them first. - if waiting := mb.pendingWriteSize(); waiting != 0 { - ts := 1 * time.Millisecond - var waited time.Duration + version := buf[1] + if buf[0] != fullStateMagic || version < fullStateMinVersion || version > fullStateVersion { + os.Remove(fn) + fs.warn("Stream state magic and version mismatch") + return errCorruptState + } - for waiting < coalesceMinimum { - time.Sleep(ts) - select { - case <-qch: - return - default: - } - newWaiting := mb.pendingWriteSize() - if waited = waited + ts; waited > maxFlushWait || newWaiting <= waiting { - break - } - waiting = newWaiting - ts *= 2 + bi := hdrLen + + readU64 := func() uint64 { + if bi < 0 { + return 0 + } + v, n := binary.Uvarint(buf[bi:]) + if n <= 0 { + bi = -1 + return 0 + } + bi += n + return v + } + readI64 := func() int64 { + if bi < 0 { + return 0 + } + v, n := binary.Varint(buf[bi:]) + if n <= 0 { + bi = -1 + return -1 + } + bi += n + return v + } + + setTime := func(t *time.Time, ts int64) { + if ts == 0 { + *t = time.Time{} + } else { + *t = time.Unix(0, ts).UTC() + } + } + + var state StreamState + state.Msgs = readU64() + state.Bytes = readU64() + state.FirstSeq = readU64() + baseTime := readI64() + setTime(&state.FirstTime, baseTime) + state.LastSeq = readU64() + setTime(&state.LastTime, readI64()) + + // Check for per subject info. + if numSubjects := int(readU64()); numSubjects > 0 { + fs.psim, fs.tsl = fs.psim.Empty(), 0 + for i := 0; i < numSubjects; i++ { + if lsubj := int(readU64()); lsubj > 0 { + if bi+lsubj > len(buf) { + os.Remove(fn) + fs.warn("Stream state bad subject len (%d)", lsubj) + return errCorruptState } - mb.flushPendingMsgs() - } - if infoChanged() { - mb.writeIndexInfo() + // If we have lots of subjects this will alloc for each one. + // We could reference the underlying buffer, but we could guess wrong if + // number of blocks is large and subjects is low, since we would reference buf. + subj := buf[bi : bi+lsubj] + // We had a bug that could cause memory corruption in the PSIM that could have gotten stored to disk. + // Only would affect subjects, so do quick check. + if !isValidSubject(bytesToString(subj), true) { + os.Remove(fn) + fs.warn("Stream state corrupt subject detected") + return errCorruptState + } + bi += lsubj + psi := psi{total: readU64(), fblk: uint32(readU64())} + if psi.total > 1 { + psi.lblk = uint32(readU64()) + } else { + psi.lblk = psi.fblk + } + fs.psim.Insert(subj, psi) + fs.tsl += lsubj } - case <-qch: - return } } -} -// Lock should be held. -func (mb *msgBlock) eraseMsg(seq uint64, ri, rl int) error { - var le = binary.LittleEndian - var hdr [msgHdrSize]byte + // Track the state as represented by the blocks themselves. + var mstate StreamState - le.PutUint32(hdr[0:], uint32(rl)) - le.PutUint64(hdr[4:], seq|ebit) - le.PutUint64(hdr[12:], 0) - le.PutUint16(hdr[20:], 0) + if numBlocks := readU64(); numBlocks > 0 { + lastIndex := int(numBlocks - 1) + fs.blks = make([]*msgBlock, 0, numBlocks) + for i := 0; i < int(numBlocks); i++ { + index, nbytes, fseq, fts, lseq, lts, numDeleted := uint32(readU64()), readU64(), readU64(), readI64(), readU64(), readI64(), readU64() + var ttls uint64 + if version >= 2 { + ttls = readU64() + } + if bi < 0 { + os.Remove(fn) + return errCorruptState + } + mb := fs.initMsgBlock(index) + atomic.StoreUint64(&mb.first.seq, fseq) + atomic.StoreUint64(&mb.last.seq, lseq) + mb.msgs, mb.bytes = lseq-fseq+1, nbytes + mb.first.ts, mb.last.ts = fts+baseTime, lts+baseTime + mb.ttls = ttls + if numDeleted > 0 { + dmap, n, err := avl.Decode(buf[bi:]) + if err != nil { + os.Remove(fn) + fs.warn("Stream state error decoding avl dmap: %v", err) + return errCorruptState + } + mb.dmap = *dmap + if mb.msgs > numDeleted { + mb.msgs -= numDeleted + } else { + mb.msgs = 0 + } + bi += n + } - // Randomize record - data := make([]byte, rl-emptyRecordLen) - rand.Read(data) + // Pre-emptively mark block as closed, we'll confirm this block + // still exists on disk and report it as lost if not. + mb.closed = true - // Now write to underlying buffer. - var b bytes.Buffer - b.Write(hdr[:]) - b.Write(data) + // Only add in if not empty or the lmb. + if mb.msgs > 0 || i == lastIndex { + fs.addMsgBlock(mb) + updateTrackingState(&mstate, mb) + } else { + // Mark dirty to cleanup. + fs.dirty++ + } + } + } - // Calculate hash. - mb.hh.Reset() - mb.hh.Write(hdr[4:20]) - mb.hh.Write(data) - checksum := mb.hh.Sum(nil) - // Write to msg record. - b.Write(checksum) + // Pull in last block index for the block that had last checksum when we wrote the full state. + blkIndex := uint32(readU64()) + var lchk [8]byte + if bi+len(lchk) > len(buf) { + bi = -1 + } else { + copy(lchk[0:], buf[bi:bi+len(lchk)]) + } - // Update both cache and disk. - nbytes := b.Bytes() + // Check if we had any errors. + if bi < 0 { + os.Remove(fn) + fs.warn("Stream state has no checksum present") + return errCorruptState + } - // Cache - if ri >= mb.cache.off { - li := ri - mb.cache.off - buf := mb.cache.buf[li : li+rl] - copy(buf, nbytes) + // Move into place our state, msgBlks and subject info. + fs.state = state + + // First let's check the happy path, open the blk file that was the lmb when we created the full state. + // See if we have the last block available. + var matched bool + mb := fs.lmb + if mb == nil || mb.index != blkIndex { + os.Remove(fn) + fs.warn("Stream state block does not exist or index mismatch") + return errCorruptState } - // Disk - if mb.cache.off+mb.cache.wp > ri { - mfd, err := os.OpenFile(mb.mfn, os.O_RDWR, 0644) - if err != nil { - return err + if _, err := os.Stat(mb.mfn); err != nil && os.IsNotExist(err) { + // If our saved state is past what we see on disk, fallback and rebuild. + if ld, _, _ := mb.rebuildState(); ld != nil { + fs.addLostData(ld) + } + fs.warn("Stream state detected prior state, could not locate msg block %d", blkIndex) + return errPriorState + } + if matched = bytes.Equal(mb.lastChecksum(), lchk[:]); !matched { + // Detected a stale index.db, we didn't write it upon shutdown so can't rely on it being correct. + fs.warn("Stream state outdated, last block has additional entries, will rebuild") + return errPriorState + } + + // We need to see if any blocks exist after our last one even though we matched the last record exactly. + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + var dirs []os.DirEntry + + <-dios + if f, err := os.Open(mdir); err == nil { + dirs, _ = f.ReadDir(-1) + f.Close() + } + dios <- struct{}{} + + var index uint32 + for _, fi := range dirs { + // Ensure it's actually a block file, otherwise fmt.Sscanf also matches %d.blk.tmp + if !strings.HasSuffix(fi.Name(), blkSuffix) { + continue } - defer mfd.Close() - if _, err = mfd.WriteAt(nbytes, int64(ri)); err == nil { - mfd.Sync() + if n, err := fmt.Sscanf(fi.Name(), blkScan, &index); err == nil && n == 1 { + if index > blkIndex { + fs.warn("Stream state outdated, found extra blocks, will rebuild") + return errPriorState + } else if mb, ok := fs.bim[index]; ok { + mb.closed = false + } } - if err != nil { - return err + } + + var rebuild bool + for _, mb := range fs.blks { + if mb.closed { + rebuild = true + if ld, _, _ := mb.rebuildState(); ld != nil { + fs.addLostData(ld) + } + fs.warn("Stream state detected prior state, could not locate msg block %d", mb.index) } } + if rebuild { + return errPriorState + } + + // We check first and last seq and number of msgs and bytes. If there is a difference, + // return and error so we rebuild from the message block state on disk. + if !trackingStatesEqual(&fs.state, &mstate) { + os.Remove(fn) + fs.warn("Stream state encountered internal inconsistency on recover") + return errCorruptState + } + return nil } // Lock should be held. -func (mb *msgBlock) isEmpty() bool { - return mb.first.seq > mb.last.seq -} +func (fs *fileStore) recoverTTLState() error { + // See if we have a timed hash wheel for TTLs. + <-dios + fn := filepath.Join(fs.fcfg.StoreDir, msgDir, ttlStreamStateFile) + buf, err := os.ReadFile(fn) + dios <- struct{}{} -// Lock should be held. -func (mb *msgBlock) selectNextFirst() { - var seq uint64 - for seq = mb.first.seq + 1; seq <= mb.last.seq; seq++ { - if _, ok := mb.dmap[seq]; ok { - // We will move past this so we can delete the entry. - delete(mb.dmap, seq) - } else { - break + if err != nil && !os.IsNotExist(err) { + return err + } + + fs.ttls = thw.NewHashWheel() + + var ttlseq uint64 + if err == nil { + ttlseq, err = fs.ttls.Decode(buf) + if err != nil { + fs.warn("Error decoding TTL state: %s", err) + os.Remove(fn) } } - // Set new first sequence. - mb.first.seq = seq - // Check if we are empty.. - if mb.isEmpty() { - mb.first.ts = 0 - return + if ttlseq < fs.state.FirstSeq { + ttlseq = fs.state.FirstSeq + } + + defer fs.resetAgeChk(0) + if fs.state.Msgs > 0 && ttlseq <= fs.state.LastSeq { + fs.warn("TTL state is outdated; attempting to recover using linear scan (seq %d to %d)", ttlseq, fs.state.LastSeq) + var ( + mb *msgBlock + sm StoreMsg + mblseq uint64 + ) + for seq := ttlseq; seq <= fs.state.LastSeq; seq++ { + retry: + if mb == nil { + if mb = fs.selectMsgBlock(seq); mb == nil { + // Selecting the message block should return a block that contains this sequence, + // or a later block if it can't be found. + // It's an error if we can't find any block within the bounds of first and last seq. + fs.warn("Error loading msg block with seq %d for recovering TTL", seq) + continue + } + seq = atomic.LoadUint64(&mb.first.seq) + mblseq = atomic.LoadUint64(&mb.last.seq) + } + if mb.ttls == 0 { + // None of the messages in the block have message TTLs so don't + // bother doing anything further with this block, skip to the end. + seq = atomic.LoadUint64(&mb.last.seq) + 1 + } + if seq > mblseq { + // We've reached the end of the loaded block, so let's go back to the + // beginning and process the next block. + mb.tryForceExpireCache() + mb = nil + if seq <= fs.state.LastSeq { + goto retry + } + // Done. + break + } + msg, _, err := mb.fetchMsgNoCopy(seq, &sm) + if err != nil { + fs.warn("Error loading msg seq %d for recovering TTL: %s", seq, err) + continue + } + if len(msg.hdr) == 0 { + continue + } + if ttl, _ := getMessageTTL(msg.hdr); ttl > 0 { + expires := time.Duration(msg.ts) + (time.Second * time.Duration(ttl)) + fs.ttls.Add(seq, int64(expires)) + } + } } + return nil +} - // Need to get the timestamp. - // We will try the cache direct and fallback if needed. - sm, _ := mb.cacheLookupWithLock(seq) - if sm == nil { - // Slow path, need to unlock. - mb.mu.Unlock() - sm, _ = mb.fetchMsg(seq) - mb.mu.Lock() +// Grabs last checksum for the named block file. +// Takes into account encryption etc. +func (mb *msgBlock) lastChecksum() []byte { + f, err := mb.openBlock() + if err != nil { + return nil } - if sm != nil { - mb.first.ts = sm.ts + defer f.Close() + + var lchk [8]byte + if fi, _ := f.Stat(); fi != nil { + mb.rbytes = uint64(fi.Size()) + } + if mb.rbytes < checksumSize { + return lchk[:] + } + // Encrypted? + if err := mb.checkAndLoadEncryption(); err != nil { + return nil + } + if mb.bek != nil { + if buf, _ := mb.loadBlock(nil); len(buf) >= checksumSize { + if err = mb.encryptOrDecryptIfNeeded(buf); err != nil { + return nil + } + copy(lchk[0:], buf[len(buf)-checksumSize:]) + } } else { - mb.first.ts = 0 + f.ReadAt(lchk[:], int64(mb.rbytes)-checksumSize) } + return lchk[:] } -// Select the next FirstSeq -func (fs *fileStore) selectNextFirst() { +// This will make sure we clean up old idx and fss files. +func (fs *fileStore) cleanupOldMeta() { + fs.mu.RLock() + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + fs.mu.RUnlock() + + <-dios + f, err := os.Open(mdir) + dios <- struct{}{} + if err != nil { + return + } + + dirs, _ := f.ReadDir(-1) + f.Close() + + const ( + minLen = 4 + idxSuffix = ".idx" + fssSuffix = ".fss" + ) + for _, fi := range dirs { + if name := fi.Name(); strings.HasSuffix(name, idxSuffix) || strings.HasSuffix(name, fssSuffix) { + os.Remove(filepath.Join(mdir, name)) + } + } +} + +func (fs *fileStore) recoverMsgs() error { + fs.mu.Lock() + defer fs.mu.Unlock() + + // Check for any left over purged messages. + <-dios + pdir := filepath.Join(fs.fcfg.StoreDir, purgeDir) + if _, err := os.Stat(pdir); err == nil { + os.RemoveAll(pdir) + } + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + f, err := os.Open(mdir) + if err != nil { + dios <- struct{}{} + return errNotReadable + } + dirs, err := f.ReadDir(-1) + f.Close() + dios <- struct{}{} + + if err != nil { + return errNotReadable + } + + indices := make(sort.IntSlice, 0, len(dirs)) + var index int + for _, fi := range dirs { + // Ensure it's actually a block file, otherwise fmt.Sscanf also matches %d.blk.tmp + if !strings.HasSuffix(fi.Name(), blkSuffix) { + continue + } + if n, err := fmt.Sscanf(fi.Name(), blkScan, &index); err == nil && n == 1 { + indices = append(indices, index) + } + } + indices.Sort() + + // Recover all of the msg blocks. + // We now guarantee they are coming in order. + for _, index := range indices { + if mb, err := fs.recoverMsgBlock(uint32(index)); err == nil && mb != nil { + // This is a truncate block with possibly no index. If the OS got shutdown + // out from underneath of us this is possible. + if mb.first.seq == 0 { + mb.dirtyCloseWithRemove(true) + fs.removeMsgBlockFromList(mb) + continue + } + // If the stream is empty, reset the first/last sequences so these can + // properly move up based purely on tombstones spread over multiple blocks. + if fs.state.Msgs == 0 { + fs.state.FirstSeq, fs.state.LastSeq = 0, 0 + fs.state.FirstTime, fs.state.LastTime = time.Time{}, time.Time{} + } + fseq := atomic.LoadUint64(&mb.first.seq) + if fs.state.FirstSeq == 0 || (fseq < fs.state.FirstSeq && mb.first.ts != 0) { + fs.state.FirstSeq = fseq + if mb.first.ts == 0 { + fs.state.FirstTime = time.Time{} + } else { + fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() + } + } + // Preserve last time, could have erased the last message in one block, and then + // have a tombstone with the proper timestamp afterward in another block + if lseq := atomic.LoadUint64(&mb.last.seq); lseq >= fs.state.LastSeq { + fs.state.LastSeq = lseq + if mb.last.ts == 0 { + fs.state.LastTime = time.Time{} + } else { + fs.state.LastTime = time.Unix(0, mb.last.ts).UTC() + } + } + fs.state.Msgs += mb.msgs + fs.state.Bytes += mb.bytes + } else { + return err + } + } + if len(fs.blks) > 0 { - mb := fs.blks[0] - mb.mu.RLock() - fs.state.FirstSeq = mb.first.seq - fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() - mb.mu.RUnlock() + fs.lmb = fs.blks[len(fs.blks)-1] } else { - // Could not find anything, so treat like purge - fs.state.FirstSeq = fs.state.LastSeq + 1 - fs.state.FirstTime = time.Time{} + _, err = fs.newMsgBlockForWrite() + } + + // Check if we encountered any lost data. + if fs.ld != nil { + var emptyBlks []*msgBlock + for _, mb := range fs.blks { + if mb.msgs == 0 && mb.rbytes == 0 && mb != fs.lmb { + emptyBlks = append(emptyBlks, mb) + } + } + for _, mb := range emptyBlks { + // Need the mb lock here. + mb.mu.Lock() + fs.removeMsgBlock(mb) + mb.mu.Unlock() + } } + + if err != nil { + return err + } + + // Check for keyfiles orphans. + if kms, err := filepath.Glob(filepath.Join(mdir, keyScanAll)); err == nil && len(kms) > 0 { + valid := make(map[uint32]bool) + for _, mb := range fs.blks { + valid[mb.index] = true + } + for _, fn := range kms { + var index uint32 + shouldRemove := true + if n, err := fmt.Sscanf(filepath.Base(fn), keyScan, &index); err == nil && n == 1 && valid[index] { + shouldRemove = false + } + if shouldRemove { + os.Remove(fn) + } + } + } + + return nil } -// Lock should be held. -func (mb *msgBlock) resetCacheExpireTimer(td time.Duration) { - if td == 0 { - td = mb.cexp +// Will expire msgs that have aged out on restart. +// We will treat this differently in case we have a recovery +// that will expire alot of messages on startup. +// Should only be called on startup. +func (fs *fileStore) expireMsgsOnRecover() error { + if fs.state.Msgs == 0 { + return nil } - if mb.ctmr == nil { - mb.ctmr = time.AfterFunc(td, mb.expireCache) - } else { - mb.ctmr.Reset(td) + + // If subject delete markers is configured, can't expire on recover. + // When clustered we need to go through proposals. + if fs.cfg.SubjectDeleteMarkerTTL > 0 { + return nil + } + + var minAge = time.Now().UnixNano() - int64(fs.cfg.MaxAge) + var purged, bytes uint64 + var deleted int + var nts int64 + + // If we expire all make sure to write out a tombstone. Need to be done by hand here, + // usually taken care of by fs.removeMsgBlock() but we do not call that here. + var last msgId + + deleteEmptyBlock := func(mb *msgBlock) error { + // If we are the last keep state to remember first/last sequence. + // Do this part by hand since not deleting one by one. + if mb == fs.lmb { + last.seq = atomic.LoadUint64(&mb.last.seq) + last.ts = mb.last.ts + } + // Make sure we do subject cleanup as well. + mb.ensurePerSubjectInfoLoaded() + mb.fss.IterOrdered(func(bsubj []byte, ss *SimpleState) bool { + subj := bytesToString(bsubj) + for i := uint64(0); i < ss.Msgs; i++ { + fs.removePerSubject(subj) + } + return true + }) + err := mb.dirtyCloseWithRemove(true) + if isPermissionError(err) { + return err + } + deleted++ + return nil + } + + for _, mb := range fs.blks { + mb.mu.Lock() + if minAge < mb.first.ts { + nts = mb.first.ts + mb.mu.Unlock() + break + } + // Can we remove whole block here? + if mb.last.ts <= minAge { + purged += mb.msgs + bytes += mb.bytes + err := deleteEmptyBlock(mb) + mb.mu.Unlock() + if isPermissionError(err) { + return err + } + continue + } + + // If we are here we have to process the interior messages of this blk. + // This will load fss as well. + if err := mb.loadMsgsWithLock(); err != nil { + mb.mu.Unlock() + break + } + + var smv StoreMsg + var needNextFirst bool + + // Walk messages and remove if expired. + fseq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) + for seq := fseq; seq <= lseq; seq++ { + sm, err := mb.cacheLookupNoCopy(seq, &smv) + // Process interior deleted msgs. + if err == errDeletedMsg { + // Update dmap. + if mb.dmap.Exists(seq) { + mb.dmap.Delete(seq) + } + // Keep this updated just in case since we are removing dmap entries. + atomic.StoreUint64(&mb.first.seq, seq) + needNextFirst = true + continue + } + // Break on other errors. + if err != nil || sm == nil { + atomic.StoreUint64(&mb.first.seq, seq) + needNextFirst = true + break + } + + // No error and sm != nil from here onward. + + // Check for done. + if minAge < sm.ts { + atomic.StoreUint64(&mb.first.seq, sm.seq) + mb.first.ts = sm.ts + needNextFirst = false + nts = sm.ts + break + } + + // Delete the message here. + if mb.msgs > 0 { + atomic.StoreUint64(&mb.first.seq, seq) + needNextFirst = true + sz := fileStoreMsgSize(sm.subj, sm.hdr, sm.msg) + if sz > mb.bytes { + sz = mb.bytes + } + mb.bytes -= sz + bytes += sz + mb.msgs-- + purged++ + } + // Update fss + // Make sure we have fss loaded. + mb.removeSeqPerSubject(sm.subj, seq) + fs.removePerSubject(sm.subj) + } + // Make sure we have a proper next first sequence. + if needNextFirst { + mb.selectNextFirst() + } + // Check if empty after processing, could happen if tail of messages are all deleted. + if mb.msgs == 0 { + deleteEmptyBlock(mb) + } + mb.mu.Unlock() + break + } + + if nts > 0 { + // Make sure to set age check based on this value. + fs.resetAgeChk(nts - minAge) + } + + if deleted > 0 { + // Update block map. + if fs.bim != nil { + for _, mb := range fs.blks[:deleted] { + delete(fs.bim, mb.index) + } + } + // Update blks slice. + fs.blks = copyMsgBlocks(fs.blks[deleted:]) + if lb := len(fs.blks); lb == 0 { + fs.lmb = nil + } else { + fs.lmb = fs.blks[lb-1] + } + } + // Update top level accounting. + if purged < fs.state.Msgs { + fs.state.Msgs -= purged + } else { + fs.state.Msgs = 0 + } + if bytes < fs.state.Bytes { + fs.state.Bytes -= bytes + } else { + fs.state.Bytes = 0 + } + // Make sure to we properly set the fs first sequence and timestamp. + fs.selectNextFirst() + + // Check if we have no messages and blocks left. + if fs.lmb == nil && last.seq != 0 { + if lmb, _ := fs.newMsgBlockForWrite(); lmb != nil { + fs.writeTombstone(last.seq, last.ts) + } + // Clear any global subject state. + fs.psim, fs.tsl = fs.psim.Empty(), 0 + } + + // If we purged anything, make sure we kick flush state loop. + if purged > 0 { + fs.dirty++ + } + return nil +} + +func copyMsgBlocks(src []*msgBlock) []*msgBlock { + if src == nil { + return nil + } + dst := make([]*msgBlock, len(src)) + copy(dst, src) + return dst +} + +// GetSeqFromTime looks for the first sequence number that has +// the message with >= timestamp. +func (fs *fileStore) GetSeqFromTime(t time.Time) uint64 { + fs.mu.RLock() + lastSeq := fs.state.LastSeq + closed := fs.isClosed() + fs.mu.RUnlock() + + if closed { + return 0 + } + + mb := fs.selectMsgBlockForStart(t) + if mb == nil { + return lastSeq + 1 + } + + fseq := atomic.LoadUint64(&mb.first.seq) + lseq := atomic.LoadUint64(&mb.last.seq) + + var ( + smv StoreMsg + cts int64 + cseq uint64 + off uint64 + ) + ts := t.UnixNano() + + // Using a binary search, but need to be aware of interior deletes in the block. + seq := lseq + 1 +loop: + for fseq <= lseq { + mid := fseq + (lseq-fseq)/2 + off = 0 + // Potentially skip over gaps. We keep the original middle but keep track of a + // potential delete range with an offset. + for { + sm, _, err := mb.fetchMsgNoCopy(mid+off, &smv) + if err != nil || sm == nil { + off++ + if mid+off <= lseq { + continue + } else { + // Continue search to the left. Purposely ignore the skipped deletes here. + lseq = mid - 1 + continue loop + } + } + cts = sm.ts + cseq = sm.seq + break + } + if cts >= ts { + seq = cseq + if mid == fseq { + break + } + // Continue search to the left. + lseq = mid - 1 + } else { + // Continue search to the right (potentially skipping over interior deletes). + fseq = mid + off + 1 + } + } + return seq +} + +// Find the first matching message against a sublist. +func (mb *msgBlock) firstMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm *StoreMsg) (*StoreMsg, bool, error) { + mb.mu.Lock() + var didLoad bool + var updateLLTS bool + defer func() { + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + }() + + if mb.fssNotLoaded() { + // Make sure we have fss loaded. + if err := mb.loadMsgsWithLock(); err != nil { + return nil, false, err + } + didLoad = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + // Make sure to start at mb.first.seq if fseq < mb.first.seq + if seq := atomic.LoadUint64(&mb.first.seq); seq > start { + start = seq + } + lseq := atomic.LoadUint64(&mb.last.seq) + + // If the FSS state has fewer entries than sequences in the linear scan, + // then use intersection instead as likely going to be cheaper. This will + // often be the case with high numbers of deletes, as well as a smaller + // number of subjects in the block. + if uint64(mb.fss.Size()) < lseq-start { + // If there are no subject matches then this is effectively no-op. + hseq := uint64(math.MaxUint64) + var ierr error + stree.IntersectGSL(mb.fss, sl, func(subj []byte, ss *SimpleState) { + if ierr != nil { + return + } + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + // mb is already loaded into the cache so should be fast-ish. + mb.recalculateForSubj(bytesToString(subj), ss) + } + first := max(start, ss.First) + if first > ss.Last || first >= hseq { + // The start cutoff is after the last sequence for this subject, + // or we think we already know of a subject with an earlier msg + // than our first seq for this subject. + return + } + // Need messages loaded from here on out. + if mb.cacheNotLoaded() { + if ierr = mb.loadMsgsWithLock(); ierr != nil { + return + } + didLoad = true + } + if sm == nil { + sm = new(StoreMsg) + } + if first == ss.First { + // If the start floor is below where this subject starts then we can + // short-circuit, avoiding needing to scan for the next message. + if fsm, err := mb.cacheLookup(ss.First, sm); err == nil { + sm = fsm + hseq = ss.First + } + return + } + for seq := first; seq <= ss.Last; seq++ { + // Otherwise we have a start floor that intersects where this subject + // has messages in the block, so we need to walk up until we find a + // message matching the subject. + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + // Instead we will update it only once in a defer. + updateLLTS = true + continue + } + llseq := mb.llseq + fsm, err := mb.cacheLookup(seq, sm) + if err != nil { + continue + } + updateLLTS = false // cacheLookup already updated it. + if sl.HasInterest(fsm.subj) { + hseq = seq + sm = fsm + break + } + // If we are here we did not match, so put the llseq back. + mb.llseq = llseq + } + }) + if ierr != nil { + return nil, false, ierr + } + if hseq < uint64(math.MaxUint64) && sm != nil { + return sm, didLoad && start == lseq, nil + } + } else { + // Need messages loaded from here on out. + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return nil, false, err + } + didLoad = true + } + if sm == nil { + sm = new(StoreMsg) + } + + for seq := start; seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + // Instead we will update it only once in a defer. + updateLLTS = true + continue + } + llseq := mb.llseq + fsm, err := mb.cacheLookup(seq, sm) + if err != nil { + continue + } + expireOk := seq == lseq && mb.llseq != llseq && mb.llseq == seq + updateLLTS = false // cacheLookup already updated it. + if sl.HasInterest(fsm.subj) { + return fsm, expireOk, nil + } + // If we are here we did not match, so put the llseq back. + mb.llseq = llseq + } + } + + return nil, didLoad, ErrStoreMsgNotFound +} + +// Find the first matching message. +// fs lock should be held. +func (mb *msgBlock) firstMatching(filter string, wc bool, start uint64, sm *StoreMsg) (*StoreMsg, bool, error) { + mb.mu.Lock() + var updateLLTS bool + defer func() { + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + }() + + fseq, isAll := start, filter == _EMPTY_ || filter == fwcs + + var didLoad bool + if mb.fssNotLoaded() { + // Make sure we have fss loaded. + mb.loadMsgsWithLock() + didLoad = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + if filter == _EMPTY_ { + filter = fwcs + wc = true + } + + // If we only have 1 subject currently and it matches our filter we can also set isAll. + if !isAll && mb.fss.Size() == 1 { + if !wc { + _, isAll = mb.fss.Find(stringToBytes(filter)) + } else { + // Since mb.fss.Find won't work if filter is a wildcard, need to use Match instead. + mb.fss.Match(stringToBytes(filter), func(subject []byte, _ *SimpleState) { + isAll = true + }) + } + // If the only subject in this block isn't our filter, can simply short-circuit. + if !isAll { + return nil, didLoad, ErrStoreMsgNotFound + } + } + // Make sure to start at mb.first.seq if fseq < mb.first.seq + fseq = max(fseq, atomic.LoadUint64(&mb.first.seq)) + lseq := atomic.LoadUint64(&mb.last.seq) + + // Optionally build the isMatch for wildcard filters. + var isMatch func(subj string) bool + // Decide to build. + if wc { + _tsa, _fsa := [32]string{}, [32]string{} + tsa, fsa := _tsa[:0], tokenizeSubjectIntoSlice(_fsa[:0], filter) + isMatch = func(subj string) bool { + tsa = tokenizeSubjectIntoSlice(tsa[:0], subj) + return isSubsetMatchTokenized(tsa, fsa) + } + } + + subjs := mb.fs.cfg.Subjects + // If isAll or our single filter matches the filter arg do linear scan. + doLinearScan := isAll || (wc && len(subjs) == 1 && subjs[0] == filter) + // If we do not think we should do a linear scan check how many fss we + // would need to scan vs the full range of the linear walk. Optimize for + // 25th quantile of a match in a linear walk. Filter should be a wildcard. + // We should consult fss if our cache is not loaded and we only have fss loaded. + if !doLinearScan && wc && mb.cacheAlreadyLoaded() { + doLinearScan = mb.fss.Size()*4 > int(lseq-fseq) + } + + if !doLinearScan { + // If we have a wildcard match against all tracked subjects we know about. + fseq = lseq + 1 + if bfilter := stringToBytes(filter); wc { + mb.fss.Match(bfilter, func(bsubj []byte, ss *SimpleState) { + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(bytesToString(bsubj), ss) + } + if start <= ss.Last { + fseq = min(fseq, max(start, ss.First)) + } + }) + } else if ss, _ := mb.fss.Find(bfilter); ss != nil { + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(filter, ss) + } + if start <= ss.Last { + fseq = min(fseq, max(start, ss.First)) + } + } + } + + if fseq > lseq { + return nil, didLoad, ErrStoreMsgNotFound + } + + // Need messages loaded from here on out. + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return nil, false, err + } + didLoad = true + } + + if sm == nil { + sm = new(StoreMsg) + } + + for seq := fseq; seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + // Instead we will update it only once in a defer. + updateLLTS = true + continue + } + llseq := mb.llseq + fsm, err := mb.cacheLookup(seq, sm) + if err != nil { + if err == errPartialCache || err == errNoCache { + return nil, false, err + } + continue + } + updateLLTS = false // cacheLookup already updated it. + expireOk := seq == lseq && mb.llseq != llseq && mb.llseq == seq + if isAll { + return fsm, expireOk, nil + } + if wc && isMatch(sm.subj) { + return fsm, expireOk, nil + } else if !wc && fsm.subj == filter { + return fsm, expireOk, nil + } + // If we are here we did not match, so put the llseq back. + mb.llseq = llseq + } + + return nil, didLoad, ErrStoreMsgNotFound +} + +// Find the previous matching message against a sublist, working BACKWARDS from start. +func (mb *msgBlock) prevMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm *StoreMsg) (*StoreMsg, bool, error) { + mb.mu.Lock() + var didLoad bool + var updateLLTS bool + defer func() { + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + }() + + // Need messages loaded from here on out. + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return nil, false, err + } + didLoad = true + } + + // Make sure to start at mb.last.seq if lseq < mb.last.seq + if seq := atomic.LoadUint64(&mb.last.seq); start > seq { + start = seq + } + lseq := atomic.LoadUint64(&mb.first.seq) + + if sm == nil { + sm = new(StoreMsg) + } + + // If the FSS state has fewer entries than sequences in the linear scan, + // then use intersection instead as likely going to be cheaper. This will + // often be the case with high numbers of deletes, as well as a smaller + // number of subjects in the block. + if uint64(mb.fss.Size()) < start-lseq { + // If there are no subject matches then this is effectively no-op. + hseq := uint64(0) + stree.IntersectGSL(mb.fss, sl, func(subj []byte, ss *SimpleState) { + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + // mb is already loaded into the cache so should be fast-ish. + mb.recalculateForSubj(bytesToString(subj), ss) + } + first := min(start, ss.Last) + // Skip if cutoff is before this subject's first, or if we already + // have a higher-or-equal candidate (hseq holds the highest found). + if first < ss.First || first <= hseq { + // The start cutoff is before the first sequence for this subject, + // or we already know of a subject with a later-or-equal msg. + return + } + if first == ss.Last { + // If the start floor is above where this subject starts then we can + // short-circuit, avoiding needing to scan for the next message. + if fsm, err := mb.cacheLookup(ss.Last, sm); err == nil { + sm = fsm + hseq = ss.Last + } + return + } + for seq := first; seq >= ss.First; seq-- { + // Otherwise we have a start floor that intersects where this subject + // has messages in the block, so we need to walk up until we find a + // message matching the subject. + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + // Instead we will update it only once in a defer. + updateLLTS = true + continue + } + llseq := mb.llseq + fsm, err := mb.cacheLookup(seq, sm) + if err != nil { + continue + } + updateLLTS = false // cacheLookup already updated it. + if sl.HasInterest(fsm.subj) { + hseq = seq + sm = fsm + break + } + // If we are here we did not match, so put the llseq back. + mb.llseq = llseq + } + }) + if hseq > 0 && sm != nil { + return sm, didLoad && start == lseq, nil + } + } else { + for seq := start; seq >= lseq; seq-- { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + // Instead we will update it only once in a defer. + updateLLTS = true + continue + } + llseq := mb.llseq + fsm, err := mb.cacheLookup(seq, sm) + if err != nil { + continue + } + expireOk := seq == lseq && mb.llseq != llseq && mb.llseq == seq + updateLLTS = false // cacheLookup already updated it. + if sl.HasInterest(fsm.subj) { + return fsm, expireOk, nil + } + // If we are here we did not match, so put the llseq back. + mb.llseq = llseq + } + } + + return nil, didLoad, ErrStoreMsgNotFound +} + +// This will traverse a message block and generate the filtered pending. +func (mb *msgBlock) filteredPending(subj string, wc bool, seq uint64) (total, first, last uint64) { + mb.mu.Lock() + defer mb.mu.Unlock() + return mb.filteredPendingLocked(subj, wc, seq) +} + +// This will traverse a message block and generate the filtered pending. +// Lock should be held. +func (mb *msgBlock) filteredPendingLocked(filter string, wc bool, sseq uint64) (total, first, last uint64) { + isAll := filter == _EMPTY_ || filter == fwcs + + // First check if we can optimize this part. + // This means we want all and the starting sequence was before this block. + if isAll { + if fseq := atomic.LoadUint64(&mb.first.seq); sseq <= fseq { + return mb.msgs, fseq, atomic.LoadUint64(&mb.last.seq) + } + } + + if filter == _EMPTY_ { + filter, wc = fwcs, true + } + + update := func(ss *SimpleState) { + total += ss.Msgs + if first == 0 || ss.First < first { + first = ss.First + } + if ss.Last > last { + last = ss.Last + } + } + + // Make sure we have fss loaded. + mb.ensurePerSubjectInfoLoaded() + + var havePartial bool + + // If we are not a wildcard just use Find() here. Avoids allocations. + if !wc { + if ss, ok := mb.fss.Find(stringToBytes(filter)); ok && ss != nil { + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(filter, ss) + } + if sseq <= ss.First { + update(ss) + } else if sseq <= ss.Last { + // We matched but its a partial. + havePartial = true + } + } + } else { + mb.fss.Match(stringToBytes(filter), func(bsubj []byte, ss *SimpleState) { + if havePartial { + // If we already found a partial then don't do anything else. + return + } + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(bytesToString(bsubj), ss) + } + if sseq <= ss.First { + update(ss) + } else if sseq <= ss.Last { + // We matched but its a partial. + havePartial = true + } + }) + } + + // If we did not encounter any partials we can return here. + if !havePartial { + return total, first, last + } + + // If we are here we need to scan the msgs. + // Clear what we had. + total, first, last = 0, 0, 0 + + // If we load the cache for a linear scan we want to expire that cache upon exit. + var shouldExpire bool + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + + _tsa, _fsa := [32]string{}, [32]string{} + tsa, fsa := _tsa[:0], _fsa[:0] + var isMatch func(subj string) bool + + if !wc { + isMatch = func(subj string) bool { return subj == filter } + } else { + fsa = tokenizeSubjectIntoSlice(fsa[:0], filter) + isMatch = func(subj string) bool { + tsa = tokenizeSubjectIntoSlice(tsa[:0], subj) + return isSubsetMatchTokenized(tsa, fsa) + } + } + + // 1. See if we match any subs from fss. + // 2. If we match and the sseq is past ss.Last then we can use meta only. + // 3. If we match and we need to do a partial, break and clear any totals and do a full scan like num pending. + + var smv StoreMsg + for seq, lseq := sseq, atomic.LoadUint64(&mb.last.seq); seq <= lseq; seq++ { + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil { + continue + } + if isAll || isMatch(sm.subj) { + total++ + if first == 0 || seq < first { + first = seq + } + if seq > last { + last = seq + } + } + } + // If we loaded this block for this operation go ahead and expire it here. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + + return total, first, last +} + +// FilteredState will return the SimpleState associated with the filtered subject and a proposed starting sequence. +func (fs *fileStore) FilteredState(sseq uint64, subj string) SimpleState { + fs.mu.RLock() + defer fs.mu.RUnlock() + + lseq := fs.state.LastSeq + if sseq < fs.state.FirstSeq { + sseq = fs.state.FirstSeq + } + + // Returned state. + var ss SimpleState + + // If past the end no results. + if sseq > lseq { + // Make sure we track sequences + ss.First = fs.state.FirstSeq + ss.Last = fs.state.LastSeq + return ss + } + + // If we want all msgs that match we can shortcircuit. + // TODO(dlc) - This can be extended for all cases but would + // need to be careful on total msgs calculations etc. + if sseq == fs.state.FirstSeq { + fs.numFilteredPending(subj, &ss) + } else { + wc := subjectHasWildcard(subj) + // Tracking subject state. + // TODO(dlc) - Optimize for 2.10 with avl tree and no atomics per block. + for _, mb := range fs.blks { + // Skip blocks that are less than our starting sequence. + if sseq > atomic.LoadUint64(&mb.last.seq) { + continue + } + t, f, l := mb.filteredPending(subj, wc, sseq) + ss.Msgs += t + if ss.First == 0 || (f > 0 && f < ss.First) { + ss.First = f + } + if l > ss.Last { + ss.Last = l + } + } + } + + return ss +} + +// This is used to see if we can selectively jump start blocks based on filter subject and a starting block index. +// Will return -1 and ErrStoreEOF if no matches at all or no more from where we are. +func (fs *fileStore) checkSkipFirstBlock(filter string, wc bool, bi int) (int, error) { + // If we match everything, just move to next blk. + if filter == _EMPTY_ || filter == fwcs { + return bi + 1, nil + } + // Move through psim to gather start and stop bounds. + start, stop := uint32(math.MaxUint32), uint32(0) + if wc { + fs.psim.Match(stringToBytes(filter), func(_ []byte, psi *psi) { + if psi.fblk < start { + start = psi.fblk + } + if psi.lblk > stop { + stop = psi.lblk + } + }) + } else if psi, ok := fs.psim.Find(stringToBytes(filter)); ok { + start, stop = psi.fblk, psi.lblk + } + // Nothing was found. + if start == uint32(math.MaxUint32) { + return -1, ErrStoreEOF + } + return fs.selectSkipFirstBlock(bi, start, stop) +} + +// This is used to see if we can selectively jump start blocks based on filter subjects and a starting block index. +// Will return -1 and ErrStoreEOF if no matches at all or no more from where we are. +func (fs *fileStore) checkSkipFirstBlockMulti(sl *gsl.SimpleSublist, bi int) (int, error) { + // Move through psim to gather start and stop bounds. + start, stop := uint32(math.MaxUint32), uint32(0) + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { + if psi.fblk < start { + start = psi.fblk + } + if psi.lblk > stop { + stop = psi.lblk + } + }) + // Nothing was found. + if start == uint32(math.MaxUint32) { + return -1, ErrStoreEOF + } + return fs.selectSkipFirstBlock(bi, start, stop) +} + +func (fs *fileStore) selectSkipFirstBlock(bi int, start, stop uint32) (int, error) { + // Can not be nil so ok to inline dereference. + mbi := fs.blks[bi].getIndex() + // All matching msgs are behind us. + // Less than AND equal is important because we were called because we missed searching bi. + if stop <= mbi { + return -1, ErrStoreEOF + } + // If start is > index return dereference of fs.blks index. + if start > mbi { + if mb := fs.bim[start]; mb != nil { + ni, _ := fs.selectMsgBlockWithIndex(atomic.LoadUint64(&mb.last.seq)) + return ni, nil + } + } + // Otherwise just bump to the next one. + return bi + 1, nil +} + +// Optimized way for getting all num pending matching a filter subject. +// Lock should be held. +func (fs *fileStore) numFilteredPending(filter string, ss *SimpleState) { + fs.numFilteredPendingWithLast(filter, true, ss) +} + +// Optimized way for getting all num pending matching a filter subject and first sequence only. +// Lock should be held. +func (fs *fileStore) numFilteredPendingNoLast(filter string, ss *SimpleState) { + fs.numFilteredPendingWithLast(filter, false, ss) +} + +// Optimized way for getting all num pending matching a filter subject. +// Optionally look up last sequence. Sometimes do not need last and this avoids cost. +// Read lock should be held. +func (fs *fileStore) numFilteredPendingWithLast(filter string, last bool, ss *SimpleState) { + isAll := filter == _EMPTY_ || filter == fwcs + + // If isAll we do not need to do anything special to calculate the first and last and total. + if isAll { + ss.First = fs.state.FirstSeq + ss.Last = fs.state.LastSeq + ss.Msgs = fs.state.Msgs + return + } + // Always reset. + ss.First, ss.Last, ss.Msgs = 0, 0, 0 + + // We do need to figure out the first and last sequences. + wc := subjectHasWildcard(filter) + start, stop := uint32(math.MaxUint32), uint32(0) + + if wc { + fs.psim.Match(stringToBytes(filter), func(_ []byte, psi *psi) { + ss.Msgs += psi.total + // Keep track of start and stop indexes for this subject. + if psi.fblk < start { + start = psi.fblk + } + if psi.lblk > stop { + stop = psi.lblk + } + }) + } else if psi, ok := fs.psim.Find(stringToBytes(filter)); ok { + ss.Msgs += psi.total + start, stop = psi.fblk, psi.lblk + } + + // Did not find anything. + if stop == 0 { + return + } + + // Do start + mb := fs.bim[start] + if mb != nil { + _, f, _ := mb.filteredPending(filter, wc, 0) + ss.First = f + } + + if ss.First == 0 { + // This is a miss. This can happen since psi.fblk is lazy. + // We will make sure to update fblk. + + // Hold this outside loop for psim fblk updates when done. + i := start + 1 + for ; i <= stop; i++ { + mb := fs.bim[i] + if mb == nil { + continue + } + if _, f, _ := mb.filteredPending(filter, wc, 0); f > 0 { + ss.First = f + break + } + } + // Update fblk since fblk was outdated. + // We only require read lock here as that is desirable, + // so we need to do this in a go routine to acquire write lock. + go func() { + fs.mu.Lock() + defer fs.mu.Unlock() + if !wc { + if info, ok := fs.psim.Find(stringToBytes(filter)); ok { + if i > info.fblk { + info.fblk = i + } + } + } else { + fs.psim.Match(stringToBytes(filter), func(subj []byte, psi *psi) { + if i > psi.fblk { + psi.fblk = i + } + }) + } + }() + } + // Now gather last sequence if asked to do so. + if last { + if mb = fs.bim[stop]; mb != nil { + _, _, l := mb.filteredPending(filter, wc, 0) + ss.Last = l + } + } +} + +// SubjectsState returns a map of SimpleState for all matching subjects. +func (fs *fileStore) SubjectsState(subject string) map[string]SimpleState { + fs.mu.RLock() + defer fs.mu.RUnlock() + + if fs.state.Msgs == 0 || fs.noTrackSubjects() { + return nil + } + + if subject == _EMPTY_ { + subject = fwcs + } + + start, stop := fs.blks[0], fs.lmb + // We can short circuit if not a wildcard using psim for start and stop. + if !subjectHasWildcard(subject) { + info, ok := fs.psim.Find(stringToBytes(subject)) + if !ok { + return nil + } + if f := fs.bim[info.fblk]; f != nil { + start = f + } + if l := fs.bim[info.lblk]; l != nil { + stop = l + } + } + + // Aggregate fss. + fss := make(map[string]SimpleState) + var startFound bool + + for _, mb := range fs.blks { + if !startFound { + if mb != start { + continue + } + startFound = true + } + + mb.mu.Lock() + var shouldExpire bool + if mb.fssNotLoaded() { + // Make sure we have fss loaded. + mb.loadMsgsWithLock() + shouldExpire = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + mb.fss.Match(stringToBytes(subject), func(bsubj []byte, ss *SimpleState) { + subj := string(bsubj) + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(subj, ss) + } + oss := fss[subj] + if oss.First == 0 { // New + fss[subj] = *ss + } else { + // Merge here. + oss.Last, oss.Msgs = ss.Last, oss.Msgs+ss.Msgs + fss[subj] = oss + } + }) + if shouldExpire { + // Expire this cache before moving on. + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() + + if mb == stop { + break + } + } + + return fss +} + +// AllLastSeqs will return a sorted list of last sequences for all subjects. +func (fs *fileStore) AllLastSeqs() ([]uint64, error) { + fs.mu.RLock() + defer fs.mu.RUnlock() + return fs.allLastSeqsLocked() +} + +// allLastSeqsLocked will return a sorted list of last sequences for all +// subjects, but won't take the lock to do it, to avoid the issue of compounding +// read locks causing a deadlock with a write lock. +func (fs *fileStore) allLastSeqsLocked() ([]uint64, error) { + if fs.state.Msgs == 0 || fs.noTrackSubjects() { + return nil, nil + } + + numSubjects := fs.psim.Size() + seqs := make([]uint64, 0, numSubjects) + subs := make(map[string]struct{}, numSubjects) + + for i := len(fs.blks) - 1; i >= 0; i-- { + if len(subs) == numSubjects { + break + } + mb := fs.blks[i] + mb.mu.Lock() + + var shouldExpire bool + if mb.fssNotLoaded() { + // Make sure we have fss loaded. + mb.loadMsgsWithLock() + shouldExpire = true + } + + mb.fss.IterFast(func(bsubj []byte, ss *SimpleState) bool { + // Check if already been processed and accounted. + if _, ok := subs[string(bsubj)]; !ok { + seqs = append(seqs, ss.Last) + subs[string(bsubj)] = struct{}{} + } + return true + }) + if shouldExpire { + // Expire this cache before moving on. + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() + } + + slices.Sort(seqs) + return seqs, nil +} + +// Helper to determine if the filter(s) represent all the subjects. +// Most clients send in subjects even if they match the stream's ingest subjects. +// Lock should be held. +func (fs *fileStore) filterIsAll(filters []string) bool { + if len(filters) != len(fs.cfg.Subjects) { + return false + } + // Sort so we can compare. + slices.Sort(filters) + for i, subj := range filters { + if !subjectIsSubsetMatch(fs.cfg.Subjects[i], subj) { + return false + } + } + return true +} + +// MultiLastSeqs will return a sorted list of sequences that match all subjects presented in filters. +// We will not exceed the maxSeq, which if 0 becomes the store's last sequence. +func (fs *fileStore) MultiLastSeqs(filters []string, maxSeq uint64, maxAllowed int) ([]uint64, error) { + fs.mu.RLock() + defer fs.mu.RUnlock() + + if fs.state.Msgs == 0 || fs.noTrackSubjects() { + return nil, nil + } + + // See if we can short circuit if we think they are asking for all last sequences and have no maxSeq or maxAllowed set. + if maxSeq == 0 && maxAllowed <= 0 && fs.filterIsAll(filters) { + return fs.allLastSeqsLocked() + } + + lastBlkIndex := len(fs.blks) - 1 + lastMB := fs.blks[lastBlkIndex] + + // Implied last sequence. + if maxSeq == 0 { + maxSeq = fs.state.LastSeq + } else { + // Udate last mb index if not last seq. + lastBlkIndex, lastMB = fs.selectMsgBlockWithIndex(maxSeq) + } + // Make sure non-nil + if lastMB == nil { + return nil, nil + } + + // Grab our last mb index (not same as blk index). + lastMB.mu.RLock() + lastMBIndex := lastMB.index + lastMB.mu.RUnlock() + + subs := make(map[string]*psi) + var numLess int + var maxBlk uint32 + + for _, filter := range filters { + fs.psim.Match(stringToBytes(filter), func(subj []byte, psi *psi) { + subs[string(subj)] = psi + if psi.lblk < lastMBIndex { + numLess++ + if psi.lblk > maxBlk { + maxBlk = psi.lblk + } + } + }) + } + + // If all subjects have a lower last index, select the largest for our walk backwards. + if numLess == len(subs) { + lastMB = fs.bim[maxBlk] + } + + // Collect all sequences needed. + seqs := make([]uint64, 0, len(subs)) + for i, lnf := lastBlkIndex, false; i >= 0; i-- { + if len(subs) == 0 { + break + } + mb := fs.blks[i] + if !lnf { + if mb != lastMB { + continue + } + lnf = true + } + // We can start properly looking here. + mb.mu.Lock() + mb.ensurePerSubjectInfoLoaded() + + // Iterate the fss and check against our subs. We will delete from subs as we add. + // Once len(subs) == 0 we are done. + mb.fss.IterFast(func(bsubj []byte, ss *SimpleState) bool { + // Already been processed and accounted for was not matched in the first place. + if subs[string(bsubj)] == nil { + return true + } + // Check if we need to recalculate. We only care about the last sequence. + if ss.lastNeedsUpdate { + // mb is already loaded into the cache so should be fast-ish. + mb.recalculateForSubj(bytesToString(bsubj), ss) + } + // If we are equal or below just add to seqs slice. + if ss.Last <= maxSeq { + seqs = append(seqs, ss.Last) + delete(subs, bytesToString(bsubj)) + } else { + // Need to search for the real last since recorded last is > maxSeq. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + } + var smv StoreMsg + fseq := atomic.LoadUint64(&mb.first.seq) + lseq := min(atomic.LoadUint64(&mb.last.seq), maxSeq) + ssubj := bytesToString(bsubj) + for seq := lseq; seq >= fseq; seq-- { + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil || sm.subj != ssubj { + continue + } + seqs = append(seqs, sm.seq) + delete(subs, ssubj) + break + } + } + return true + }) + mb.mu.Unlock() + + // If maxAllowed was sepcified check that we will not exceed that. + if maxAllowed > 0 && len(seqs) > maxAllowed { + return nil, ErrTooManyResults + } + } + if len(seqs) == 0 { + return nil, nil + } + slices.Sort(seqs) + return seqs, nil +} + +// NumPending will return the number of pending messages matching the filter subject starting at sequence. +// Optimized for stream num pending calculations for consumers. +func (fs *fileStore) NumPending(sseq uint64, filter string, lastPerSubject bool) (total, validThrough uint64) { + fs.mu.RLock() + defer fs.mu.RUnlock() + + // This can always be last for these purposes. + validThrough = fs.state.LastSeq + + if fs.state.Msgs == 0 || sseq > fs.state.LastSeq { + return 0, validThrough + } + + // If sseq is less then our first set to first. + if sseq < fs.state.FirstSeq { + sseq = fs.state.FirstSeq + } + // Track starting for both block for the sseq and staring block that matches any subject. + var seqStart int + // See if we need to figure out starting block per sseq. + if sseq > fs.state.FirstSeq { + // This should not, but can return -1, so make sure we check to avoid panic below. + if seqStart, _ = fs.selectMsgBlockWithIndex(sseq); seqStart < 0 { + seqStart = 0 + } + } + + isAll := filter == _EMPTY_ || filter == fwcs + if isAll && filter == _EMPTY_ { + filter = fwcs + } + wc := subjectHasWildcard(filter) + + // See if filter was provided but its the only subject. + if !isAll && !wc && fs.psim.Size() == 1 { + _, isAll = fs.psim.Find(stringToBytes(filter)) + } + // If we are isAll and have no deleted we can do a simpler calculation. + if !lastPerSubject && isAll && (fs.state.LastSeq-fs.state.FirstSeq+1) == fs.state.Msgs { + if sseq == 0 { + return fs.state.Msgs, validThrough + } + return fs.state.LastSeq - sseq + 1, validThrough + } + + _tsa, _fsa := [32]string{}, [32]string{} + tsa, fsa := _tsa[:0], _fsa[:0] + if wc { + fsa = tokenizeSubjectIntoSlice(fsa[:0], filter) + } + + isMatch := func(subj string) bool { + if isAll { + return true + } + if !wc { + return subj == filter + } + tsa = tokenizeSubjectIntoSlice(tsa[:0], subj) + return isSubsetMatchTokenized(tsa, fsa) + } + + // Handle last by subject a bit differently. + // We will scan PSIM since we accurately track the last block we have seen the subject in. This + // allows us to only need to load at most one block now. + // For the last block, we need to track the subjects that we know are in that block, and track seen + // while in the block itself, but complexity there worth it. + if lastPerSubject { + // If we want all and our start sequence is equal or less than first return number of subjects. + if isAll && sseq <= fs.state.FirstSeq { + return uint64(fs.psim.Size()), validThrough + } + // If we are here we need to scan. We are going to scan the PSIM looking for lblks that are >= seqStart. + // This will build up a list of all subjects from the selected block onward. + lbm := make(map[string]bool) + mb := fs.blks[seqStart] + bi := mb.index + + fs.psim.Match(stringToBytes(filter), func(subj []byte, psi *psi) { + // If the select blk start is greater than entry's last blk skip. + if bi > psi.lblk { + return + } + total++ + // We will track the subjects that are an exact match to the last block. + // This is needed for last block processing. + if psi.lblk == bi { + lbm[string(subj)] = true + } + }) + + // Now check if we need to inspect the seqStart block. + // Grab write lock in case we need to load in msgs. + mb.mu.Lock() + var updateLLTS bool + var shouldExpire bool + // We need to walk this block to correct accounting from above. + if sseq > mb.first.seq { + // Track the ones we add back in case more than one. + seen := make(map[string]bool) + // We need to discount the total by subjects seen before sseq, but also add them right back in if they are >= sseq for this blk. + // This only should be subjects we know have the last blk in this block. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + var smv StoreMsg + for seq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq); seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + updateLLTS = true + continue + } + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil || sm.subj == _EMPTY_ || !lbm[sm.subj] { + continue + } + updateLLTS = false // cacheLookup already updated it. + if isMatch(sm.subj) { + // If less than sseq adjust off of total as long as this subject matched the last block. + if seq < sseq { + if !seen[sm.subj] { + total-- + seen[sm.subj] = true + } + } else if seen[sm.subj] { + // This is equal or more than sseq, so add back in. + total++ + // Make sure to not process anymore. + delete(seen, sm.subj) + } + } + } + } + // If we loaded the block try to force expire. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + return total, validThrough + } + + // If we would need to scan more from the beginning, revert back to calculating directly here. + // TODO(dlc) - Redo properly with sublists etc for subject-based filtering. + if seqStart >= (len(fs.blks) / 2) { + for i := seqStart; i < len(fs.blks); i++ { + var shouldExpire bool + mb := fs.blks[i] + // Hold write lock in case we need to load cache. + mb.mu.Lock() + if isAll && sseq <= atomic.LoadUint64(&mb.first.seq) { + total += mb.msgs + mb.mu.Unlock() + continue + } + // If we are here we need to at least scan the subject fss. + // Make sure we have fss loaded. + if mb.fssNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + var t uint64 + var havePartial bool + mb.fss.Match(stringToBytes(filter), func(bsubj []byte, ss *SimpleState) { + if havePartial { + // If we already found a partial then don't do anything else. + return + } + subj := bytesToString(bsubj) + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(subj, ss) + } + if sseq <= ss.First { + t += ss.Msgs + } else if sseq <= ss.Last { + // We matched but its a partial. + havePartial = true + } + }) + + // See if we need to scan msgs here. + if havePartial { + // Make sure we have the cache loaded. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + // Clear on partial. + t = 0 + start := sseq + if fseq := atomic.LoadUint64(&mb.first.seq); fseq > start { + start = fseq + } + var smv StoreMsg + for seq, lseq := start, atomic.LoadUint64(&mb.last.seq); seq <= lseq; seq++ { + if sm, _ := mb.cacheLookupNoCopy(seq, &smv); sm != nil && isMatch(sm.subj) { + t++ + } + } + } + // If we loaded this block for this operation go ahead and expire it here. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() + total += t + } + return total, validThrough + } + + // If we are here it's better to calculate totals from psim and adjust downward by scanning less blocks. + // TODO(dlc) - Eventually when sublist uses generics, make this sublist driven instead. + start := uint32(math.MaxUint32) + fs.psim.Match(stringToBytes(filter), func(_ []byte, psi *psi) { + total += psi.total + // Keep track of start index for this subject. + if psi.fblk < start { + start = psi.fblk + } + }) + // See if we were asked for all, if so we are done. + if sseq <= fs.state.FirstSeq { + return total, validThrough + } + + // If we are here we need to calculate partials for the first blocks. + firstSubjBlk := fs.bim[start] + var firstSubjBlkFound bool + // Adjust in case not found. + if firstSubjBlk == nil { + firstSubjBlkFound = true + } + + // Track how many we need to adjust against the total. + var adjust uint64 + for i := 0; i <= seqStart; i++ { + mb := fs.blks[i] + // We can skip blks if we know they are below the first one that has any subject matches. + if !firstSubjBlkFound { + if firstSubjBlkFound = (mb == firstSubjBlk); !firstSubjBlkFound { + continue + } + } + // We need to scan this block. + var shouldExpire bool + var updateLLTS bool + mb.mu.Lock() + // Check if we should include all of this block in adjusting. If so work with metadata. + if sseq > atomic.LoadUint64(&mb.last.seq) { + if isAll { + adjust += mb.msgs + } else { + // We need to adjust for all matches in this block. + // Make sure we have fss loaded. This loads whole block now. + if mb.fssNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + mb.fss.Match(stringToBytes(filter), func(bsubj []byte, ss *SimpleState) { + adjust += ss.Msgs + }) + } + } else { + // This is the last block. We need to scan per message here. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + var last = atomic.LoadUint64(&mb.last.seq) + if sseq < last { + last = sseq + } + // We need to walk all messages in this block + var smv StoreMsg + for seq := atomic.LoadUint64(&mb.first.seq); seq < last; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + updateLLTS = true + continue + } + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil || sm.subj == _EMPTY_ { + continue + } + updateLLTS = false // cacheLookup already updated it. + // Check if it matches our filter. + if sm.seq < sseq && isMatch(sm.subj) { + adjust++ + } + } + } + // If we loaded the block try to force expire. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + } + // Make final adjustment. + total -= adjust + + return total, validThrough +} + +// NumPending will return the number of pending messages matching any subject in the sublist starting at sequence. +// Optimized for stream num pending calculations for consumers with lots of filtered subjects. +// Subjects should not overlap, this property is held when doing multi-filtered consumers. +func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPerSubject bool) (total, validThrough uint64) { + fs.mu.RLock() + defer fs.mu.RUnlock() + + // This can always be last for these purposes. + validThrough = fs.state.LastSeq + + if fs.state.Msgs == 0 || sseq > fs.state.LastSeq { + return 0, validThrough + } + + // If sseq is less then our first set to first. + if sseq < fs.state.FirstSeq { + sseq = fs.state.FirstSeq + } + // Track starting for both block for the sseq and staring block that matches any subject. + var seqStart int + // See if we need to figure out starting block per sseq. + if sseq > fs.state.FirstSeq { + // This should not, but can return -1, so make sure we check to avoid panic below. + if seqStart, _ = fs.selectMsgBlockWithIndex(sseq); seqStart < 0 { + seqStart = 0 + } + } + + isAll := sl == nil + + // See if filter was provided but its the only subject. + if !isAll && fs.psim.Size() == 1 { + fs.psim.IterFast(func(subject []byte, _ *psi) bool { + isAll = sl.HasInterest(bytesToString(subject)) + return true + }) + } + // If we are isAll and have no deleted we can do a simpler calculation. + if !lastPerSubject && isAll && (fs.state.LastSeq-fs.state.FirstSeq+1) == fs.state.Msgs { + if sseq == 0 { + return fs.state.Msgs, validThrough + } + return fs.state.LastSeq - sseq + 1, validThrough + } + // Setup the isMatch function. + isMatch := func(subj string) bool { + if isAll { + return true + } + return sl.HasInterest(subj) + } + + // Handle last by subject a bit differently. + // We will scan PSIM since we accurately track the last block we have seen the subject in. This + // allows us to only need to load at most one block now. + // For the last block, we need to track the subjects that we know are in that block, and track seen + // while in the block itself, but complexity there worth it. + if lastPerSubject { + // If we want all and our start sequence is equal or less than first return number of subjects. + if isAll && sseq <= fs.state.FirstSeq { + return uint64(fs.psim.Size()), validThrough + } + // If we are here we need to scan. We are going to scan the PSIM looking for lblks that are >= seqStart. + // This will build up a list of all subjects from the selected block onward. + lbm := make(map[string]bool) + mb := fs.blks[seqStart] + bi := mb.index + + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { + // If the select blk start is greater than entry's last blk skip. + if bi > psi.lblk { + return + } + total++ + // We will track the subjects that are an exact match to the last block. + // This is needed for last block processing. + if psi.lblk == bi { + lbm[string(subj)] = true + } + }) + + // Now check if we need to inspect the seqStart block. + // Grab write lock in case we need to load in msgs. + mb.mu.Lock() + var shouldExpire bool + var updateLLTS bool + // We need to walk this block to correct accounting from above. + if sseq > mb.first.seq { + // Track the ones we add back in case more than one. + seen := make(map[string]bool) + // We need to discount the total by subjects seen before sseq, but also add them right back in if they are >= sseq for this blk. + // This only should be subjects we know have the last blk in this block. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + var smv StoreMsg + for seq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq); seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + updateLLTS = true + continue + } + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil || sm.subj == _EMPTY_ || !lbm[sm.subj] { + continue + } + updateLLTS = false // cacheLookup already updated it. + if isMatch(sm.subj) { + // If less than sseq adjust off of total as long as this subject matched the last block. + if seq < sseq { + if !seen[sm.subj] { + total-- + seen[sm.subj] = true + } + } else if seen[sm.subj] { + // This is equal or more than sseq, so add back in. + total++ + // Make sure to not process anymore. + delete(seen, sm.subj) + } + } + } + } + // If we loaded the block try to force expire. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + return total, validThrough + } + + // If we would need to scan more from the beginning, revert back to calculating directly here. + if seqStart >= (len(fs.blks) / 2) { + for i := seqStart; i < len(fs.blks); i++ { + var shouldExpire bool + mb := fs.blks[i] + // Hold write lock in case we need to load cache. + mb.mu.Lock() + if isAll && sseq <= atomic.LoadUint64(&mb.first.seq) { + total += mb.msgs + mb.mu.Unlock() + continue + } + // If we are here we need to at least scan the subject fss. + // Make sure we have fss loaded. + if mb.fssNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + var t uint64 + var havePartial bool + var updateLLTS bool + stree.IntersectGSL[SimpleState](mb.fss, sl, func(bsubj []byte, ss *SimpleState) { + subj := bytesToString(bsubj) + if havePartial { + // If we already found a partial then don't do anything else. + return + } + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(subj, ss) + } + if sseq <= ss.First { + t += ss.Msgs + } else if sseq <= ss.Last { + // We matched but its a partial. + havePartial = true + } + }) + + // See if we need to scan msgs here. + if havePartial { + // Make sure we have the cache loaded. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + // Clear on partial. + t = 0 + start := sseq + if fseq := atomic.LoadUint64(&mb.first.seq); fseq > start { + start = fseq + } + var smv StoreMsg + for seq, lseq := start, atomic.LoadUint64(&mb.last.seq); seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + updateLLTS = true + continue + } + if sm, _ := mb.cacheLookupNoCopy(seq, &smv); sm != nil && isMatch(sm.subj) { + t++ + updateLLTS = false // cacheLookup already updated it. + } + } + } + // If we loaded this block for this operation go ahead and expire it here. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + total += t + } + return total, validThrough + } + + // If we are here it's better to calculate totals from psim and adjust downward by scanning less blocks. + start := uint32(math.MaxUint32) + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { + total += psi.total + // Keep track of start index for this subject. + if psi.fblk < start { + start = psi.fblk + } + }) + + // See if we were asked for all, if so we are done. + if sseq <= fs.state.FirstSeq { + return total, validThrough + } + + // If we are here we need to calculate partials for the first blocks. + firstSubjBlk := fs.bim[start] + var firstSubjBlkFound bool + // Adjust in case not found. + if firstSubjBlk == nil { + firstSubjBlkFound = true + } + + // Track how many we need to adjust against the total. + var adjust uint64 + for i := 0; i <= seqStart; i++ { + mb := fs.blks[i] + // We can skip blks if we know they are below the first one that has any subject matches. + if !firstSubjBlkFound { + if firstSubjBlkFound = (mb == firstSubjBlk); !firstSubjBlkFound { + continue + } + } + // We need to scan this block. + var shouldExpire bool + var updateLLTS bool + mb.mu.Lock() + // Check if we should include all of this block in adjusting. If so work with metadata. + if sseq > atomic.LoadUint64(&mb.last.seq) { + if isAll { + adjust += mb.msgs + } else { + // We need to adjust for all matches in this block. + // Make sure we have fss loaded. This loads whole block now. + if mb.fssNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + stree.IntersectGSL(mb.fss, sl, func(bsubj []byte, ss *SimpleState) { + adjust += ss.Msgs + }) + } + } else { + // This is the last block. We need to scan per message here. + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + var last = atomic.LoadUint64(&mb.last.seq) + if sseq < last { + last = sseq + } + // We need to walk all messages in this block + var smv StoreMsg + for seq := atomic.LoadUint64(&mb.first.seq); seq < last; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + updateLLTS = true + continue + } + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil || sm.subj == _EMPTY_ { + continue + } + updateLLTS = false // cacheLookup already updated it. + // Check if it matches our filter. + if sm.seq < sseq && isMatch(sm.subj) { + adjust++ + } + } + } + // If we loaded the block try to force expire. + if shouldExpire { + mb.tryForceExpireCacheLocked() + } + if updateLLTS { + mb.llts = ats.AccessTime() + } + mb.mu.Unlock() + } + // Make final adjustment. + total -= adjust + + return total, validThrough +} + +// SubjectsTotals return message totals per subject. +func (fs *fileStore) SubjectsTotals(filter string) map[string]uint64 { + fs.mu.RLock() + defer fs.mu.RUnlock() + return fs.subjectsTotalsLocked(filter) +} + +// Lock should be held. +func (fs *fileStore) subjectsTotalsLocked(filter string) map[string]uint64 { + if fs.psim.Size() == 0 { + return nil + } + // Match all if no filter given. + if filter == _EMPTY_ { + filter = fwcs + } + fst := make(map[string]uint64) + fs.psim.Match(stringToBytes(filter), func(subj []byte, psi *psi) { + fst[string(subj)] = psi.total + }) + return fst +} + +// RegisterStorageUpdates registers a callback for updates to storage changes. +// It will present number of messages and bytes as a signed integer and an +// optional sequence number of the message if a single. +func (fs *fileStore) RegisterStorageUpdates(cb StorageUpdateHandler) { + fs.mu.Lock() + fs.scb = cb + bsz := fs.state.Bytes + fs.mu.Unlock() + if cb != nil && bsz > 0 { + cb(0, int64(bsz), 0, _EMPTY_) + } +} + +// RegisterStorageRemoveMsg registers a callback to remove messages. +// Replicated streams should propose removals, R1 can remove inline. +func (fs *fileStore) RegisterStorageRemoveMsg(cb StorageRemoveMsgHandler) { + fs.mu.Lock() + fs.rmcb = cb + fs.mu.Unlock() +} + +// RegisterSubjectDeleteMarkerUpdates registers a callback for updates to new tombstones. +func (fs *fileStore) RegisterSubjectDeleteMarkerUpdates(cb SubjectDeleteMarkerUpdateHandler) { + fs.mu.Lock() + fs.sdmcb = cb + fs.mu.Unlock() +} + +// Helper to get hash key for specific message block. +// Lock should be held +func (fs *fileStore) hashKeyForBlock(index uint32) []byte { + return []byte(fmt.Sprintf("%s-%d", fs.cfg.Name, index)) +} + +func (mb *msgBlock) setupWriteCache(buf []byte) { + // Make sure we have a cache setup. + if mb.cache != nil { + return + } + + // Setup simple cache. + mb.cache = &cache{buf: buf} + // Make sure we set the proper cache offset if we have existing data. + var fi os.FileInfo + if mb.mfd != nil { + fi, _ = mb.mfd.Stat() + } else if mb.mfn != _EMPTY_ { + fi, _ = os.Stat(mb.mfn) + } + if fi != nil { + mb.cache.off = int(fi.Size()) + } + mb.llts = ats.AccessTime() + mb.startCacheExpireTimer() +} + +// This rolls to a new append msg block. +// Lock should be held. +func (fs *fileStore) newMsgBlockForWrite() (*msgBlock, error) { + index := uint32(1) + var rbuf []byte + + if lmb := fs.lmb; lmb != nil { + lmb.mu.Lock() + index = lmb.index + 1 + + // Flush any pending messages. + lmb.flushPendingMsgsLocked() + // Determine if we can reclaim any resources here. + lmb.closeFDsLockedNoCheck() + if lmb.cache != nil { + // Reset write timestamp and see if we can expire this cache. + rbuf = lmb.tryExpireWriteCache() + } + lmb.mu.Unlock() + + if fs.fcfg.Compression != NoCompression { + // We've now reached the end of this message block, if we want + // to compress blocks then now's the time to do it. + go func() { + lmb.mu.Lock() + defer lmb.mu.Unlock() + lmb.recompressOnDiskIfNeeded() + }() + } + } + + mb := fs.initMsgBlock(index) + // Lock should be held to quiet race detector. + mb.mu.Lock() + mb.setupWriteCache(rbuf) + mb.fss = stree.NewSubjectTree[SimpleState]() + + // Set cache time to creation time to start. + mb.llts, mb.lwts = 0, ats.AccessTime() + // Remember our last sequence number. + atomic.StoreUint64(&mb.first.seq, fs.state.LastSeq+1) + atomic.StoreUint64(&mb.last.seq, fs.state.LastSeq) + mb.mu.Unlock() + + // Now do local hash. + key := sha256.Sum256(fs.hashKeyForBlock(index)) + hh, err := highwayhash.NewDigest64(key[:]) + if err != nil { + return nil, fmt.Errorf("could not create hash: %v", err) + } + mb.hh = hh + + <-dios + mfd, err := os.OpenFile(mb.mfn, os.O_CREATE|os.O_RDWR, defaultFilePerms) + dios <- struct{}{} + + if err != nil { + if isPermissionError(err) { + return nil, err + } + mb.dirtyCloseWithRemove(true) + return nil, fmt.Errorf("Error creating msg block file: %v", err) + } + mb.mfd = mfd + + // Check if encryption is enabled. + if fs.prf != nil { + if err := fs.genEncryptionKeysForBlock(mb); err != nil { + return nil, err + } + } + + // If we know we will need this so go ahead and spin up. + if !fs.fip { + mb.spinUpFlushLoop() + } + + // Add to our list of blocks and mark as last. + fs.addMsgBlock(mb) + + return mb, nil +} + +// Generate the keys for this message block and write them out. +func (fs *fileStore) genEncryptionKeysForBlock(mb *msgBlock) error { + if mb == nil { + return nil + } + key, bek, seed, encrypted, err := fs.genEncryptionKeys(fmt.Sprintf("%s:%d", fs.cfg.Name, mb.index)) + if err != nil { + return err + } + mb.aek, mb.bek, mb.seed, mb.nonce = key, bek, seed, encrypted[:key.NonceSize()] + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + keyFile := filepath.Join(mdir, fmt.Sprintf(keyScan, mb.index)) + if _, err := os.Stat(keyFile); err != nil && !os.IsNotExist(err) { + return err + } + err = fs.writeFileWithOptionalSync(keyFile, encrypted, defaultFilePerms) + if err != nil { + return err + } + mb.kfn = keyFile + return nil +} + +// Stores a raw message with expected sequence number and timestamp. +// Lock should be held. +func (fs *fileStore) storeRawMsg(subj string, hdr, msg []byte, seq uint64, ts, ttl int64) (err error) { + if fs.isClosed() { + return ErrStoreClosed + } + + // Per subject max check needed. + mmp := uint64(fs.cfg.MaxMsgsPer) + var psmc uint64 + psmax := mmp > 0 && len(subj) > 0 + if psmax { + if info, ok := fs.psim.Find(stringToBytes(subj)); ok { + psmc = info.total + } + } + + var fseq uint64 + // Check if we are discarding new messages when we reach the limit. + if fs.cfg.Discard == DiscardNew { + var asl bool + if psmax && psmc >= mmp { + // If we are instructed to discard new per subject, this is an error. + if fs.cfg.DiscardNewPer { + return ErrMaxMsgsPerSubject + } + if fseq, err = fs.firstSeqForSubj(subj); err != nil { + return err + } + asl = true + } + // If we are discard new and limits policy and clustered, we do the enforcement + // above and should not disqualify the message here since it could cause replicas to drift. + if fs.cfg.Retention == LimitsPolicy || fs.cfg.Replicas == 1 { + if fs.cfg.MaxMsgs > 0 && fs.state.Msgs >= uint64(fs.cfg.MaxMsgs) && !asl { + return ErrMaxMsgs + } + if fs.cfg.MaxBytes > 0 && fs.state.Bytes+fileStoreMsgSize(subj, hdr, msg) >= uint64(fs.cfg.MaxBytes) { + if !asl || fs.sizeForSeq(fseq) <= int(fileStoreMsgSize(subj, hdr, msg)) { + return ErrMaxBytes + } + } + } + } + + // Check sequence. + if seq != fs.state.LastSeq+1 { + if seq > 0 { + return ErrSequenceMismatch + } + seq = fs.state.LastSeq + 1 + } + + // Write msg record. + // Add expiry bit to sequence if needed. This is so that if we need to + // rebuild, we know which messages to look at more quickly. + n, err := fs.writeMsgRecord(seq, ts, subj, hdr, msg) + if err != nil { + return err + } + + // Adjust top level tracking of per subject msg counts. + if len(subj) > 0 && fs.psim != nil { + index := fs.lmb.index + if info, ok := fs.psim.Find(stringToBytes(subj)); ok { + info.total++ + if index > info.lblk { + info.lblk = index + } + } else { + fs.psim.Insert(stringToBytes(subj), psi{total: 1, fblk: index, lblk: index}) + fs.tsl += len(subj) + } + } + + // Adjust first if needed. + now := time.Unix(0, ts).UTC() + if fs.state.Msgs == 0 { + fs.state.FirstSeq = seq + fs.state.FirstTime = now + } + + fs.state.Msgs++ + fs.state.Bytes += n + fs.state.LastSeq = seq + fs.state.LastTime = now + + // Enforce per message limits. + // We snapshotted psmc before our actual write, so >= comparison needed. + if psmax && psmc >= mmp { + // We may have done this above. + if fseq == 0 { + fseq, _ = fs.firstSeqForSubj(subj) + } + if ok, _ := fs.removeMsgViaLimits(fseq); ok { + // Make sure we are below the limit. + if psmc--; psmc >= mmp { + bsubj := stringToBytes(subj) + for info, ok := fs.psim.Find(bsubj); ok && info.total > mmp; info, ok = fs.psim.Find(bsubj) { + if seq, _ := fs.firstSeqForSubj(subj); seq > 0 { + if ok, _ := fs.removeMsgViaLimits(seq); !ok { + break + } + } else { + break + } + } + } + } else if mb := fs.selectMsgBlock(fseq); mb != nil { + // If we are here we could not remove fseq from above, so rebuild. + var ld *LostStreamData + if ld, _, _ = mb.rebuildState(); ld != nil { + fs.rebuildStateLocked(ld) + } + } + } + + // Limits checks and enforcement. + // If they do any deletions they will update the + // byte count on their own, so no need to compensate. + fs.enforceMsgLimit() + fs.enforceBytesLimit() + + // Per-message TTL. + if fs.ttls != nil && ttl > 0 { + expires := time.Duration(ts) + (time.Second * time.Duration(ttl)) + fs.ttls.Add(seq, int64(expires)) + fs.lmb.ttls++ + } + + // Check if we have and need the age expiration timer running. + switch { + case fs.ttls != nil && ttl > 0: + fs.resetAgeChk(0) + case fs.ageChk == nil && (fs.cfg.MaxAge > 0 || fs.ttls != nil): + fs.startAgeChk() + } + + return nil +} + +// StoreRawMsg stores a raw message with expected sequence number and timestamp. +func (fs *fileStore) StoreRawMsg(subj string, hdr, msg []byte, seq uint64, ts, ttl int64) error { + fs.mu.Lock() + err := fs.storeRawMsg(subj, hdr, msg, seq, ts, ttl) + cb := fs.scb + // Check if first message timestamp requires expiry + // sooner than initial replica expiry timer set to MaxAge when initializing. + if !fs.receivedAny && fs.cfg.MaxAge != 0 && ts > 0 { + fs.receivedAny = true + fs.resetAgeChk(0) + } + fs.mu.Unlock() + + if err == nil && cb != nil { + cb(1, int64(fileStoreMsgSize(subj, hdr, msg)), seq, subj) + } + + return err +} + +// Store stores a message. We hold the main filestore lock for any write operation. +func (fs *fileStore) StoreMsg(subj string, hdr, msg []byte, ttl int64) (uint64, int64, error) { + fs.mu.Lock() + seq, ts := fs.state.LastSeq+1, time.Now().UnixNano() + err := fs.storeRawMsg(subj, hdr, msg, seq, ts, ttl) + cb := fs.scb + fs.mu.Unlock() + + if err != nil { + seq, ts = 0, 0 + } else if cb != nil { + cb(1, int64(fileStoreMsgSize(subj, hdr, msg)), seq, subj) + } + + return seq, ts, err +} + +// skipMsg will update this message block for a skipped message. +// If we do not have any messages, just update the metadata, otherwise +// we will place an empty record marking the sequence as used. The +// sequence will be marked erased. +// fs lock should be held. +func (mb *msgBlock) skipMsg(seq uint64, now int64) { + if mb == nil { + return + } + var needsRecord bool + + mb.mu.Lock() + // If we are empty can just do meta. + if mb.msgs == 0 { + atomic.StoreUint64(&mb.last.seq, seq) + mb.last.ts = now + atomic.StoreUint64(&mb.first.seq, seq+1) + mb.first.ts = 0 + needsRecord = mb == mb.fs.lmb + } else { + needsRecord = true + mb.dmap.Insert(seq) + } + if needsRecord { + mb.writeMsgRecordLocked(emptyRecordLen, seq|ebit, _EMPTY_, nil, nil, now, true, true) + } + mb.mu.Unlock() + if !needsRecord { + mb.kickFlusher() + } +} + +// SkipMsg will use the next sequence number but not store anything. +func (fs *fileStore) SkipMsg(seq uint64) (uint64, error) { + // Grab time. + now := ats.AccessTime() + + fs.mu.Lock() + defer fs.mu.Unlock() + + // Check sequence matches our last sequence. + if seq != fs.state.LastSeq+1 { + if seq > 0 { + return 0, ErrSequenceMismatch + } + seq = fs.state.LastSeq + 1 + } + + // Grab our current last message block. + mb, err := fs.checkLastBlock(emptyRecordLen) + if err != nil { + return 0, err + } + + // Write skip msg. + mb.skipMsg(seq, now) + + // Update fs state. + fs.state.LastSeq, fs.state.LastTime = seq, time.Unix(0, now).UTC() + if fs.state.Msgs == 0 { + fs.state.FirstSeq, fs.state.FirstTime = seq, time.Time{} + } + if seq == fs.state.FirstSeq { + fs.state.FirstSeq, fs.state.FirstTime = seq+1, time.Time{} + } + // Mark as dirty for stream state. + fs.dirty++ + + return seq, nil +} + +// Skip multiple msgs. We will determine if we can fit into current lmb or we need to create a new block. +func (fs *fileStore) SkipMsgs(seq uint64, num uint64) error { + fs.mu.Lock() + defer fs.mu.Unlock() + + // Check sequence matches our last sequence. + if seq != fs.state.LastSeq+1 { + if seq > 0 { + return ErrSequenceMismatch + } + seq = fs.state.LastSeq + 1 + } + + // Limit number of dmap entries + const maxDeletes = 64 * 1024 + mb := fs.lmb + + numDeletes := int(num) + if mb != nil { + numDeletes += mb.dmap.Size() + } + if mb == nil || numDeletes > maxDeletes && mb.msgs > 0 || mb.msgs > 0 && mb.blkSize()+emptyRecordLen > fs.fcfg.BlockSize { + var err error + if mb, err = fs.newMsgBlockForWrite(); err != nil { + return err + } + } + + // Insert into dmap all entries and place last as marker. + now := ats.AccessTime() + lseq := seq + num - 1 + + mb.mu.Lock() + // If we are empty update meta directly. + if mb.msgs == 0 { + atomic.StoreUint64(&mb.last.seq, lseq) + mb.last.ts = now + atomic.StoreUint64(&mb.first.seq, lseq+1) + mb.first.ts = 0 + } else { + for ; seq <= lseq; seq++ { + mb.dmap.Insert(seq) + } + } + // Write out our placeholder. + mb.writeMsgRecordLocked(emptyRecordLen, lseq|ebit, _EMPTY_, nil, nil, now, true, true) + mb.mu.Unlock() + + // Now update FS accounting. + // Update fs state. + fs.state.LastSeq, fs.state.LastTime = lseq, time.Unix(0, now).UTC() + if fs.state.Msgs == 0 { + fs.state.FirstSeq, fs.state.FirstTime = lseq+1, time.Time{} + } + + // Mark as dirty for stream state. + fs.dirty++ + + return nil +} + +// Lock should be held. +func (fs *fileStore) rebuildFirst() { + if len(fs.blks) == 0 { + return + } + fmb := fs.blks[0] + if fmb == nil { + return + } + + ld, _, _ := fmb.rebuildState() + fmb.mu.RLock() + isEmpty := fmb.msgs == 0 + fmb.mu.RUnlock() + if isEmpty { + fmb.mu.Lock() + fs.removeMsgBlock(fmb) + fmb.mu.Unlock() + } + fs.selectNextFirst() + fs.rebuildStateLocked(ld) +} + +// Optimized helper function to return first sequence. +// subj will always be publish subject here, meaning non-wildcard. +// We assume a fast check that this subj even exists already happened. +// Write lock should be held. +func (fs *fileStore) firstSeqForSubj(subj string) (uint64, error) { + if len(fs.blks) == 0 { + return 0, nil + } + + // See if we can optimize where we start. + start, stop := fs.blks[0].index, fs.lmb.index + if info, ok := fs.psim.Find(stringToBytes(subj)); ok { + start, stop = info.fblk, info.lblk + } + + for i := start; i <= stop; i++ { + mb := fs.bim[i] + if mb == nil { + continue + } + // If we need to load msgs here and we need to walk multiple blocks this + // could tie up the upper fs lock, so release while dealing with the block. + fs.mu.Unlock() + + mb.mu.Lock() + var shouldExpire bool + if mb.fssNotLoaded() { + // Make sure we have fss loaded. + if err := mb.loadMsgsWithLock(); err != nil { + mb.mu.Unlock() + // Re-acquire fs lock + fs.mu.Lock() + return 0, err + } + shouldExpire = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + bsubj := stringToBytes(subj) + if ss, ok := mb.fss.Find(bsubj); ok && ss != nil { + // Adjust first if it was not where we thought it should be. + if i != start { + if info, ok := fs.psim.Find(bsubj); ok { + info.fblk = i + } + } + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.recalculateForSubj(subj, ss) + } + mb.mu.Unlock() + // Re-acquire fs lock + fs.mu.Lock() + return ss.First, nil + } + // If we did not find it and we loaded this msgBlock try to expire as long as not the last. + if shouldExpire { + // Expire this cache before moving on. + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() + // Re-acquire fs lock + fs.mu.Lock() + } + return 0, nil +} + +// Will check the msg limit and drop firstSeq msg if needed. +// Lock should be held. +func (fs *fileStore) enforceMsgLimit() { + if fs.cfg.Discard != DiscardOld { + return + } + if fs.cfg.MaxMsgs <= 0 || fs.state.Msgs <= uint64(fs.cfg.MaxMsgs) { + return + } + for nmsgs := fs.state.Msgs; nmsgs > uint64(fs.cfg.MaxMsgs); nmsgs = fs.state.Msgs { + // If the first block can be removed fully, purge it entirely without needing to walk sequences. + if len(fs.blks) > 0 { + fmb := fs.blks[0] + fmb.mu.RLock() + msgs := fmb.msgs + fmb.mu.RUnlock() + if nmsgs-msgs > uint64(fs.cfg.MaxMsgs) { + fs.purgeMsgBlock(fmb) + continue + } + } + if removed, err := fs.deleteFirstMsg(); err != nil || !removed { + fs.rebuildFirst() + return + } + } +} + +// Will check the bytes limit and drop msgs if needed. +// Lock should be held. +func (fs *fileStore) enforceBytesLimit() { + if fs.cfg.Discard != DiscardOld { + return + } + if fs.cfg.MaxBytes <= 0 || fs.state.Bytes <= uint64(fs.cfg.MaxBytes) { + return + } + for bs := fs.state.Bytes; bs > uint64(fs.cfg.MaxBytes); bs = fs.state.Bytes { + // If the first block can be removed fully, purge it entirely without needing to walk sequences. + if len(fs.blks) > 0 { + fmb := fs.blks[0] + fmb.mu.RLock() + bytes := fmb.bytes + fmb.mu.RUnlock() + if bs-bytes > uint64(fs.cfg.MaxBytes) { + fs.purgeMsgBlock(fmb) + continue + } + } + if removed, err := fs.deleteFirstMsg(); err != nil || !removed { + fs.rebuildFirst() + return + } + } +} + +// Will make sure we have limits honored for max msgs per subject on recovery or config update. +// We will make sure to go through all msg blocks etc. but in practice this +// will most likely only be the last one, so can take a more conservative approach. +// Lock should be held. +func (fs *fileStore) enforceMsgPerSubjectLimit(fireCallback bool) { + start := time.Now() + defer func() { + if took := time.Since(start); took > time.Minute { + fs.warn("enforceMsgPerSubjectLimit took %v", took.Round(time.Millisecond)) + } + }() + + maxMsgsPer := uint64(fs.cfg.MaxMsgsPer) + + // We may want to suppress callbacks from remove during this process + // since these should have already been deleted and accounted for. + if !fireCallback { + cb := fs.scb + fs.scb = nil + defer func() { fs.scb = cb }() + } + + var numMsgs uint64 + + // collect all that are not correct. + needAttention := stree.NewSubjectTree[uint64]() + fblk, lblk := uint32(math.MaxUint32), uint32(0) + fs.psim.IterFast(func(subj []byte, psi *psi) bool { + numMsgs += psi.total + if psi.total > maxMsgsPer { + needAttention.Insert(subj, psi.total) + if psi.fblk < fblk { + fblk = psi.fblk + } + if psi.lblk > lblk { + lblk = psi.lblk + } + } + return true + }) + + // We had an issue with a use case where psim (and hence fss) were correct but idx was not and was not properly being caught. + // So do a quick sanity check here. If we detect a skew do a rebuild then re-check. + if numMsgs != fs.state.Msgs { + fs.warn("Detected skew in subject-based total (%d) vs raw total (%d), rebuilding", numMsgs, fs.state.Msgs) + // Clear any global subject state. + fs.psim, fs.tsl = fs.psim.Empty(), 0 + for _, mb := range fs.blks { + ld, _, err := mb.rebuildState() + if err != nil && ld != nil { + fs.addLostData(ld) + } + fs.populateGlobalPerSubjectInfo(mb) + } + // Rebuild fs state too. + fs.rebuildStateLocked(nil) + // Need to redo blocks that need attention. + needAttention.Empty() + fblk, lblk = uint32(math.MaxUint32), uint32(0) + fs.psim.IterFast(func(subj []byte, psi *psi) bool { + if psi.total > maxMsgsPer { + needAttention.Insert(subj, psi.total) + if psi.fblk < fblk { + fblk = psi.fblk + } + if psi.lblk > lblk { + lblk = psi.lblk + } + } + return true + }) + } + + // If nothing to do then stop. + if fblk == math.MaxUint32 { + return + } + + // Collect all the msgBlks we alter. + blks := make(map[*msgBlock]struct{}) + + // For re-use below. + var sm StoreMsg + var fss *stree.SubjectTree[*SimpleState] + for i := fblk; i <= lblk; i++ { + mb := fs.bim[i] + if mb == nil { + continue + } + mb.mu.Lock() + mb.ensurePerSubjectInfoLoaded() + // It isn't safe to intersect mb.fss directly, because removeMsgViaLimits modifies it + // during the iteration, which can cause us to miss keys. We won't copy the entire + // SimpleState structs though but rather just take pointers for speed. + fss = fss.Empty() + mb.fss.IterFast(func(subject []byte, val *SimpleState) bool { + fss.Insert(subject, val) + return true + }) + mb.mu.Unlock() + stree.LazyIntersect(needAttention, fss, func(subj []byte, total *uint64, ssptr **SimpleState) { + if ssptr == nil || total == nil { + return + } + ss := *ssptr + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + mb.mu.Lock() + mb.recalculateForSubj(bytesToString(subj), ss) + mb.mu.Unlock() + } + for first := ss.First; *total > maxMsgsPer && first <= ss.Last; { + m, _, err := mb.firstMatching(bytesToString(subj), false, first, &sm) + if err != nil { + break + } + first = m.seq + 1 + if removed, _ := fs.removeMsgViaLimits(m.seq); removed { + blks[mb] = struct{}{} + *total-- + } + } + }) + } + + // Expire the cache if we can. + for mb := range blks { + mb.mu.Lock() + if mb.msgs > 0 { + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() + } +} + +// Lock should be held. +func (fs *fileStore) deleteFirstMsg() (bool, error) { + return fs.removeMsgViaLimits(fs.state.FirstSeq) +} + +// If we remove via limits that can always be recovered on a restart we +// do not force the system to update the index file. +// Lock should be held. +func (fs *fileStore) removeMsgViaLimits(seq uint64) (bool, error) { + return fs.removeMsg(seq, false, true, false) +} + +// RemoveMsg will remove the message from this store. +// Will return the number of bytes removed. +func (fs *fileStore) RemoveMsg(seq uint64) (bool, error) { + return fs.removeMsg(seq, false, false, true) +} + +func (fs *fileStore) EraseMsg(seq uint64) (bool, error) { + return fs.removeMsg(seq, true, false, true) +} + +// Convenience function to remove per subject tracking at the filestore level. +// Lock should be held. +func (fs *fileStore) removePerSubject(subj string) uint64 { + if len(subj) == 0 || fs.psim == nil { + return 0 + } + // We do not update sense of fblk here but will do so when we resolve during lookup. + bsubj := stringToBytes(subj) + if info, ok := fs.psim.Find(bsubj); ok { + info.total-- + if info.total == 1 { + info.fblk = info.lblk + } else if info.total == 0 { + if _, ok = fs.psim.Delete(bsubj); ok { + fs.tsl -= len(subj) + return 0 + } + } + return info.total + } + return 0 +} + +// Remove a message, optionally rewriting the mb file. +func (fs *fileStore) removeMsg(seq uint64, secure, viaLimits, needFSLock bool) (bool, error) { + if seq == 0 { + return false, ErrStoreMsgNotFound + } + fsLock := func() { + if needFSLock { + fs.mu.Lock() + } + } + fsUnlock := func() { + if needFSLock { + fs.mu.Unlock() + } + } + + fsLock() + + if fs.isClosed() { + fsUnlock() + return false, ErrStoreClosed + } + // If in encrypted mode negate secure rewrite here. + if secure && fs.prf != nil { + secure = false + } + + mb := fs.selectMsgBlock(seq) + if mb == nil { + var err = ErrStoreEOF + if seq <= fs.state.LastSeq { + err = ErrStoreMsgNotFound + } + fsUnlock() + return false, err + } + + mb.mu.Lock() + + // See if we are closed or the sequence number is still relevant or if we know its deleted. + if mb.closed || seq < atomic.LoadUint64(&mb.first.seq) || mb.dmap.Exists(seq) { + mb.mu.Unlock() + fsUnlock() + return false, nil + } + + fifo := seq == atomic.LoadUint64(&mb.first.seq) + isLastBlock := mb == fs.lmb + isEmpty := mb.msgs == 1 // ... about to be zero though. + + // We used to not have to load in the messages except with callbacks or the filtered subject state (which is now always on). + // Now just load regardless. + // TODO(dlc) - Figure out a way not to have to load it in, we need subject tracking outside main data block. + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + mb.mu.Unlock() + fsUnlock() + return false, err + } + } + + var smv StoreMsg + var sm *StoreMsg + var err error + if secure { + // For a secure erase we can't use NoCopy, as eraseMsg will overwrite the + // cache and we won't be able to access sm.subj etc anymore later on. + sm, err = mb.cacheLookup(seq, &smv) + } else { + // For a non-secure erase it's fine to use NoCopy, as the cache won't change + // from underneath us. + sm, err = mb.cacheLookupNoCopy(seq, &smv) + } + if err != nil { + mb.mu.Unlock() + fsUnlock() + // Mimic err behavior from above check to dmap. No error returned if already removed. + if err == errDeletedMsg { + err = nil + } + return false, err + } + + // Check if we need to write a deleted record tombstone. + // This is for user initiated removes or to hold the first seq + // when the last block is empty. + // If not via limits and not empty (empty writes tombstone below if last) write tombstone. + if !viaLimits && !isEmpty && sm != nil { + mb.mu.Unlock() // Only safe way to checkLastBlock is to unlock here... + lmb, err := fs.checkLastBlock(emptyRecordLen) + if err != nil { + fsUnlock() + return false, err + } + if err := lmb.writeTombstone(sm.seq, sm.ts); err != nil { + fsUnlock() + return false, err + } + mb.mu.Lock() // We'll need the lock back to carry on safely. + } + + // Grab size + msz := fileStoreMsgSize(sm.subj, sm.hdr, sm.msg) + + // Set cache timestamp for last remove. + mb.lrts = ats.AccessTime() + + // Must always perform the erase, even if the block is empty as it could contain tombstones. + if secure { + // Grab record info, but use the pre-computed record length. + ri, _, _, err := mb.slotInfo(int(seq - mb.cache.fseq)) + if err != nil { + mb.mu.Unlock() + fsUnlock() + return false, err + } + if err := mb.eraseMsg(seq, int(ri), int(msz), isLastBlock); err != nil { + mb.mu.Unlock() + fsUnlock() + return false, err + } + } + + // Global stats + if fs.state.Msgs > 0 { + fs.state.Msgs-- + } + if msz < fs.state.Bytes { + fs.state.Bytes -= msz + } else { + fs.state.Bytes = 0 + } + + // Now local mb updates. + if mb.msgs > 0 { + mb.msgs-- + } + if msz < mb.bytes { + mb.bytes -= msz + } else { + mb.bytes = 0 + } + + // Allow us to check compaction again. + mb.noCompact = false + + // Mark as dirty for stream state. + fs.dirty++ + + // If we are tracking subjects here make sure we update that accounting. + mb.ensurePerSubjectInfoLoaded() + + // If we are tracking multiple subjects here make sure we update that accounting. + mb.removeSeqPerSubject(sm.subj, seq) + fs.removePerSubject(sm.subj) + if fs.ttls != nil { + if ttl, err := getMessageTTL(sm.hdr); err == nil { + expires := time.Duration(sm.ts) + (time.Second * time.Duration(ttl)) + fs.ttls.Remove(seq, int64(expires)) + } + } + + if fifo { + mb.selectNextFirst() + if !isEmpty { + // Can update this one in place. + if seq == fs.state.FirstSeq { + fs.state.FirstSeq = atomic.LoadUint64(&mb.first.seq) // new one. + if mb.first.ts == 0 { + fs.state.FirstTime = time.Time{} + } else { + fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() + } + } + } + } else if !isEmpty { + // Out of order delete. + mb.dmap.Insert(seq) + // Make simple check here similar to Compact(). If we can save 50% and over a certain threshold do inline. + // All other more thorough cleanup will happen in syncBlocks logic. + // Note that we do not have to store empty records for the deleted, so don't use to calculate. + // TODO(dlc) - This should not be inline, should kick the sync routine. + if !isLastBlock && mb.shouldCompactInline() { + mb.compact() + } + } + + if secure { + if ld, _ := mb.flushPendingMsgsLocked(); ld != nil { + // We have the mb lock here, this needs the mb locks so do in its own go routine. + go fs.rebuildState(ld) + } + } + + // If empty remove this block and check if we need to update first sequence. + // We will write a tombstone at the end. + var firstSeqNeedsUpdate bool + if isEmpty { + // This writes tombstone iff mb == lmb, so no need to do above. + fs.removeMsgBlock(mb) + firstSeqNeedsUpdate = seq == fs.state.FirstSeq + } + mb.mu.Unlock() + + // If we emptied the current message block and the seq was state.FirstSeq + // then we need to jump message blocks. We will also write the index so + // we don't lose track of the first sequence. + if firstSeqNeedsUpdate { + fs.selectNextFirst() + } + + if cb := fs.scb; cb != nil { + // If we have a callback registered we need to release lock regardless since cb might need it to lookup msg, etc. + fs.mu.Unlock() + // Storage updates. + delta := int64(msz) + cb(-1, -delta, seq, sm.subj) + + if !needFSLock { + fs.mu.Lock() + } + } else if needFSLock { + // We acquired it so release it. + fs.mu.Unlock() + } + + return true, nil +} + +// Tests whether we should try to compact this block while inline removing msgs. +// We will want rbytes to be over the minimum and have a 2x potential savings. +// If we compacted before but rbytes didn't improve much, guard against constantly compacting. +// Lock should be held. +func (mb *msgBlock) shouldCompactInline() bool { + return mb.rbytes > compactMinimum && mb.bytes*2 < mb.rbytes && (mb.cbytes == 0 || mb.bytes*2 < mb.cbytes) +} + +// Tests whether we should try to compact this block while running periodic sync. +// We will want rbytes to be over the minimum and have a 2x potential savings. +// Ignores 2MB minimum. +// Lock should be held. +func (mb *msgBlock) shouldCompactSync() bool { + return mb.bytes*2 < mb.rbytes && !mb.noCompact +} + +// This will compact and rewrite this block. This version will not process any tombstone cleanup. +// Write lock needs to be held. +func (mb *msgBlock) compact() { + mb.compactWithFloor(0) +} + +// This will compact and rewrite this block. This should only be called when we know we want to rewrite this block. +// This should not be called on the lmb since we will prune tail deleted messages which could cause issues with +// writing new messages. We will silently bail on any issues with the underlying block and let someone else detect. +// if fseq > 0 we will attempt to cleanup stale tombstones. +// Write lock needs to be held. +func (mb *msgBlock) compactWithFloor(floor uint64) { + wasLoaded := mb.cacheAlreadyLoaded() + if !wasLoaded { + if err := mb.loadMsgsWithLock(); err != nil { + return + } + } + + buf := mb.cache.buf + nbuf := getMsgBlockBuf(len(buf)) + // Recycle our nbuf when we are done. + defer recycleMsgBlockBuf(nbuf) + + var le = binary.LittleEndian + var firstSet bool + var last uint64 + var msgs uint64 + + fseq := atomic.LoadUint64(&mb.first.seq) + lseq := atomic.LoadUint64(&mb.last.seq) + isDeleted := func(seq uint64) bool { + return seq == 0 || seq&ebit != 0 || mb.dmap.Exists(seq) || seq < fseq + } + + for index, lbuf := uint32(0), uint32(len(buf)); index < lbuf; { + if index+msgHdrSize > lbuf { + return + } + hdr := buf[index : index+msgHdrSize] + rl, slen := le.Uint32(hdr[0:]), int(le.Uint16(hdr[20:])) + // Clear any headers bit that could be set. + rl &^= hbit + dlen := int(rl) - msgHdrSize + // Do some quick sanity checks here. + if dlen < 0 || slen > (dlen-recordHashSize) || dlen > int(rl) || index+rl > lbuf || rl > rlBadThresh { + return + } + // Only need to process non-deleted messages. + seq := le.Uint64(hdr[4:]) + ts := int64(le.Uint64(hdr[12:])) + + if !isDeleted(seq) { + // Check for tombstones. + if seq&tbit != 0 { + seq = seq &^ tbit + // If this entry is for a lower seq than ours then keep around. + // We also check that it is greater than our floor. Floor is zero on normal + // calls to compact. + if seq < fseq && seq >= floor { + nbuf = append(nbuf, buf[index:index+rl]...) + } + } else { + // Normal message here. + msgs++ + nbuf = append(nbuf, buf[index:index+rl]...) + if !firstSet { + firstSet = true + atomic.StoreUint64(&mb.first.seq, seq) + } + if seq >= last { + last = seq + atomic.StoreUint64(&mb.last.seq, last) + mb.last.ts = ts + } + } + } + // Advance to next record. + index += rl + } + + // Handle compression + if mb.cmp != NoCompression && len(nbuf) > 0 { + cbuf, err := mb.cmp.Compress(nbuf) + if err != nil { + return + } + meta := &CompressionInfo{ + Algorithm: mb.cmp, + OriginalSize: uint64(len(nbuf)), + } + nbuf = append(meta.MarshalMetadata(), cbuf...) + } + + // Check for encryption. + if mb.bek != nil && len(nbuf) > 0 { + // Recreate to reset counter. + rbek, err := genBlockEncryptionKey(mb.fs.fcfg.Cipher, mb.seed, mb.nonce) + if err != nil { + return + } + rbek.XORKeyStream(nbuf, nbuf) + } + + // Close FDs first. + mb.closeFDsLocked() + + // We will write to a new file and mv/rename it in case of failure. + mfn := filepath.Join(mb.fs.fcfg.StoreDir, msgDir, fmt.Sprintf(newScan, mb.index)) + <-dios + err := os.WriteFile(mfn, nbuf, defaultFilePerms) + dios <- struct{}{} + if err != nil { + os.Remove(mfn) + return + } + if err := os.Rename(mfn, mb.mfn); err != nil { + os.Remove(mfn) + return + } + + // Make sure to sync + mb.needSync = true + + // Capture the updated rbytes. + if rbytes := uint64(len(nbuf)); rbytes == mb.rbytes { + // No change, so set our noCompact bool here to avoid attempting to continually compress in syncBlocks. + mb.noCompact = true + } else { + mb.rbytes = rbytes + } + mb.cbytes = mb.bytes + + // Remove any seqs from the beginning of the blk. + for seq, nfseq := fseq, atomic.LoadUint64(&mb.first.seq); seq < nfseq; seq++ { + mb.dmap.Delete(seq) + } + // Remove any seqs from the ending of the blk. + for seq, nlseq := lseq, atomic.LoadUint64(&mb.last.seq); seq > nlseq; seq-- { + mb.dmap.Delete(seq) + } + // If the block itself has no messages anymore (could still contain tombstones though), + // then we need to account for that by resetting the last sequence and timestamp. + if msgs == 0 { + atomic.StoreUint64(&mb.last.seq, fseq-1) + mb.last.ts = 0 + mb.dmap.Empty() + } + // Make sure we clear the cache since no longer valid. + mb.clearCacheAndOffset() + // If we entered with the msgs loaded make sure to reload them. + if wasLoaded { + mb.loadMsgsWithLock() + } +} + +// Grab info from a slot. +// Lock should be held. +func (mb *msgBlock) slotInfo(slot int) (uint32, uint32, bool, error) { + if slot < 0 || mb.cache == nil || slot >= len(mb.cache.idx) { + return 0, 0, false, errPartialCache + } + + bi := mb.cache.idx[slot] + ri, hashChecked := (bi &^ cbit), (bi&cbit) != 0 + + // If this is a deleted slot return here. + if bi == dbit { + return 0, 0, false, errDeletedMsg + } + + // Determine record length + var rl uint32 + if slot >= len(mb.cache.idx) { + rl = mb.cache.lrl + } else { + // Need to account for dbit markers in idx. + // So we will walk until we find valid idx slot to calculate rl. + for i := 1; slot+i < len(mb.cache.idx); i++ { + ni := mb.cache.idx[slot+i] &^ cbit + if ni == dbit { + continue + } + rl = ni - ri + break + } + // check if we had all trailing dbits. + // If so use len of cache buf minus ri. + if rl == 0 { + rl = uint32(len(mb.cache.buf)) - ri + } + } + if rl < msgHdrSize { + return 0, 0, false, errBadMsg{mb.mfn, fmt.Sprintf("length too short for slot %d", slot)} + } + return uint32(ri), rl, hashChecked, nil +} + +func (fs *fileStore) isClosed() bool { + return fs.closed.Load() +} + +// Will spin up our flush loop. +func (mb *msgBlock) spinUpFlushLoop() { + mb.mu.Lock() + defer mb.mu.Unlock() + mb.spinUpFlushLoopLocked() +} + +// Will spin up our flush loop. +// Lock should be held. +func (mb *msgBlock) spinUpFlushLoopLocked() { + // Are we already running or closed? + if mb.flusher || mb.closed { + return + } + mb.flusher = true + mb.fch = make(chan struct{}, 1) + mb.qch = make(chan struct{}) + fch, qch := mb.fch, mb.qch + + go mb.flushLoop(fch, qch) +} + +// Raw low level kicker for flush loops. +func kickFlusher(fch chan struct{}) { + if fch != nil { + select { + case fch <- struct{}{}: + default: + } + } +} + +// Kick flusher for this message block. +func (mb *msgBlock) kickFlusher() { + mb.mu.RLock() + defer mb.mu.RUnlock() + kickFlusher(mb.fch) +} + +func (mb *msgBlock) setInFlusher() { + mb.mu.Lock() + mb.flusher = true + mb.mu.Unlock() +} + +func (mb *msgBlock) clearInFlusher() { + mb.mu.Lock() + mb.flusher = false + mb.mu.Unlock() +} + +// flushLoop watches for messages, index info, or recently closed msg block updates. +func (mb *msgBlock) flushLoop(fch, qch chan struct{}) { + mb.setInFlusher() + defer mb.clearInFlusher() + + for { + select { + case <-fch: + // If we have pending messages process them first. + if waiting := mb.pendingWriteSize(); waiting != 0 { + ts := 1 * time.Millisecond + var waited time.Duration + + for waiting < coalesceMinimum { + time.Sleep(ts) + select { + case <-qch: + return + default: + } + newWaiting := mb.pendingWriteSize() + if waited = waited + ts; waited > maxFlushWait || newWaiting <= waiting { + break + } + waiting = newWaiting + ts *= 2 + } + mb.flushPendingMsgs() + // Check if we are no longer the last message block. If we are + // not we can close FDs and exit. + mb.fs.mu.RLock() + notLast := mb != mb.fs.lmb + mb.fs.mu.RUnlock() + if notLast { + if err := mb.closeFDs(); err == nil { + return + } + } + } + case <-qch: + return + } + } +} + +// Lock should be held. +func (mb *msgBlock) eraseMsg(seq uint64, ri, rl int, isLastBlock bool) error { + var le = binary.LittleEndian + var hdr [msgHdrSize]byte + + le.PutUint32(hdr[0:], uint32(rl)) + le.PutUint64(hdr[4:], seq|ebit) + le.PutUint64(hdr[12:], 0) + le.PutUint16(hdr[20:], 0) + + // Randomize record + data := make([]byte, rl-emptyRecordLen) + if n, err := rand.Read(data); err != nil { + return err + } else if n != len(data) { + return fmt.Errorf("not enough overwrite bytes read (%d != %d)", n, len(data)) + } + + // Now write to underlying buffer. + var b bytes.Buffer + b.Write(hdr[:]) + b.Write(data) + + // Calculate hash. + mb.hh.Reset() + mb.hh.Write(hdr[4:20]) + mb.hh.Write(data) + var hb [highwayhash.Size64]byte + checksum := mb.hh.Sum(hb[:0]) + // Write to msg record. + b.Write(checksum) + + // Update both cache and disk. + nbytes := b.Bytes() + + // Cache + if ri >= mb.cache.off { + li := ri - mb.cache.off + buf := mb.cache.buf[li : li+rl] + copy(buf, nbytes) + } + + // Disk + if mb.cache.off+mb.cache.wp > ri { + if err := mb.atomicOverwriteFile(mb.cache.buf, !isLastBlock); err != nil { + return err + } + } + return nil +} + +// Truncate this message block to the tseq and ts. +// Lock should be held. +func (mb *msgBlock) truncate(tseq uint64, ts int64) (nmsgs, nbytes uint64, err error) { + // Make sure we are loaded to process messages etc. + if err := mb.loadMsgsWithLock(); err != nil { + return 0, 0, err + } + + // Calculate new eof using slot info from our new last sm. + ri, rl, _, err := mb.slotInfo(int(tseq - mb.cache.fseq)) + if err != nil { + return 0, 0, err + } + // Calculate new eof. + eof := int64(ri + rl) + + var purged, bytes uint64 + + checkDmap := mb.dmap.Size() > 0 + var smv StoreMsg + + for seq := atomic.LoadUint64(&mb.last.seq); seq > tseq; seq-- { + if checkDmap { + if mb.dmap.Exists(seq) { + // Delete and skip to next. + mb.dmap.Delete(seq) + checkDmap = !mb.dmap.IsEmpty() + continue + } + } + // We should have a valid msg to calculate removal stats. + if m, err := mb.cacheLookupNoCopy(seq, &smv); err == nil { + if mb.msgs > 0 { + rl := fileStoreMsgSize(m.subj, m.hdr, m.msg) + mb.msgs-- + if rl > mb.bytes { + rl = mb.bytes + } + mb.bytes -= rl + mb.rbytes -= rl + // For return accounting. + purged++ + bytes += uint64(rl) + } + } + } + + // If the block is compressed then we have to load it into memory + // and decompress it, truncate it and then write it back out. + // Otherwise, truncate the file itself and close the descriptor. + if mb.cmp != NoCompression { + buf, err := mb.loadBlock(nil) + if err != nil { + return 0, 0, fmt.Errorf("failed to load block from disk: %w", err) + } + if err = mb.encryptOrDecryptIfNeeded(buf); err != nil { + return 0, 0, err + } + if buf, err = mb.decompressIfNeeded(buf); err != nil { + return 0, 0, fmt.Errorf("failed to decompress block: %w", err) + } + buf = buf[:eof] + copy(mb.lchk[0:], buf[:len(buf)-checksumSize]) + // We did decompress but don't recompress the truncated buffer here since we're the last block + // and would otherwise have compressed data and allow to write uncompressed data in the same block. + if err = mb.atomicOverwriteFile(buf, false); err != nil { + return 0, 0, err + } + } else if mb.mfd != nil { + mb.mfd.Truncate(eof) + mb.mfd.Sync() + // Update our checksum. + var lchk [8]byte + mb.mfd.ReadAt(lchk[:], eof-8) + copy(mb.lchk[0:], lchk[:]) + } else { + return 0, 0, fmt.Errorf("failed to truncate msg block %d, file not open", mb.index) + } + + // Update our last msg. + atomic.StoreUint64(&mb.last.seq, tseq) + mb.last.ts = ts + + // Clear our cache. + mb.clearCacheAndOffset() + + // Redo per subject info for this block. + mb.resetPerSubjectInfo() + + // Load msgs again. + mb.loadMsgsWithLock() + + return purged, bytes, nil +} + +// Helper to determine if the mb is empty. +func (mb *msgBlock) isEmpty() bool { + return atomic.LoadUint64(&mb.first.seq) > atomic.LoadUint64(&mb.last.seq) +} + +// Lock should be held. +func (mb *msgBlock) selectNextFirst() { + var seq uint64 + fseq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) + for seq = fseq + 1; seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // We will move past this so we can delete the entry. + mb.dmap.Delete(seq) + } else { + break + } + } + // Set new first sequence. + atomic.StoreUint64(&mb.first.seq, seq) + + // Check if we are empty.. + if seq > lseq { + mb.first.ts = 0 + return + } + + // Need to get the timestamp. + // We will try the cache direct and fallback if needed. + var smv StoreMsg + sm, _ := mb.cacheLookupNoCopy(seq, &smv) + if sm == nil { + // Slow path, need to unlock. + mb.mu.Unlock() + sm, _, _ = mb.fetchMsgNoCopy(seq, &smv) + mb.mu.Lock() + } + if sm != nil { + mb.first.ts = sm.ts + } else { + mb.first.ts = 0 + } +} + +// Select the next FirstSeq +// Also cleans up empty blocks at the start only containing tombstones. +// Lock should be held. +func (fs *fileStore) selectNextFirst() { + if len(fs.blks) > 0 { + for len(fs.blks) > 1 { + mb := fs.blks[0] + mb.mu.Lock() + empty := mb.msgs == 0 + if !empty { + mb.mu.Unlock() + break + } + fs.forceRemoveMsgBlock(mb) + mb.mu.Unlock() + } + mb := fs.blks[0] + mb.mu.RLock() + fs.state.FirstSeq = atomic.LoadUint64(&mb.first.seq) + if mb.first.ts == 0 { + fs.state.FirstTime = time.Time{} + } else { + fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() + } + mb.mu.RUnlock() + } else { + // Could not find anything, so treat like purge + fs.state.FirstSeq = fs.state.LastSeq + 1 + fs.state.FirstTime = time.Time{} + } + // Mark first as moved. Plays into tombstone cleanup for syncBlocks. + fs.firstMoved = true +} + +// Lock should be held. +func (mb *msgBlock) resetCacheExpireTimer(td time.Duration) { + if td == 0 { + td = mb.cexp + 100*time.Millisecond + } + if mb.ctmr == nil { + mb.ctmr = time.AfterFunc(td, mb.expireCache) + } else { + mb.ctmr.Reset(td) + } +} + +// Lock should be held. +func (mb *msgBlock) startCacheExpireTimer() { + mb.resetCacheExpireTimer(0) +} + +// Used when we load in a message block. +// Lock should be held. +func (mb *msgBlock) clearCacheAndOffset() { + // Reset linear scan tracker. + mb.llseq = 0 + if mb.cache != nil { + mb.cache.off = 0 + mb.cache.wp = 0 + } + mb.clearCache() +} + +// Lock should be held. +func (mb *msgBlock) clearCache() { + if mb.ctmr != nil { + tsla := mb.sinceLastActivity() + if mb.fss == nil || tsla > mb.fexp { + // Force + mb.fss = nil + mb.ctmr.Stop() + mb.ctmr = nil + } else { + mb.resetCacheExpireTimer(mb.fexp - tsla) + } + } + + if mb.cache == nil { + return + } + + buf := mb.cache.buf + if mb.cache.off == 0 { + mb.cache = nil + } else { + // Clear msgs and index. + mb.cache.buf = nil + mb.cache.idx = nil + mb.cache.wp = 0 + } + recycleMsgBlockBuf(buf) +} + +// Called to possibly expire a message block cache. +func (mb *msgBlock) expireCache() { + mb.mu.Lock() + defer mb.mu.Unlock() + mb.expireCacheLocked() +} + +func (mb *msgBlock) tryForceExpireCache() { + mb.mu.Lock() + defer mb.mu.Unlock() + mb.tryForceExpireCacheLocked() +} + +// We will attempt to force expire this by temporarily clearing the last load time. +func (mb *msgBlock) tryForceExpireCacheLocked() { + llts := mb.llts + mb.llts = 0 + mb.expireCacheLocked() + mb.llts = llts +} + +// This is for expiration of the write cache, which will be partial with fip. +// So we want to bypass the Pools here. +// Lock should be held. +func (mb *msgBlock) tryExpireWriteCache() []byte { + if mb.cache == nil { + return nil + } + lwts, buf, llts, nra := mb.lwts, mb.cache.buf, mb.llts, mb.cache.nra + mb.lwts, mb.cache.nra = 0, true + mb.expireCacheLocked() + mb.lwts = lwts + if mb.cache != nil { + mb.cache.nra = nra + } + // We could check for a certain time since last load, but to be safe just reuse if no loads at all. + if llts == 0 && (mb.cache == nil || mb.cache.buf == nil) { + // Clear last write time since we now are about to move on to a new lmb. + mb.lwts = 0 + return buf[:0] + } + return nil +} + +// Lock should be held. +func (mb *msgBlock) expireCacheLocked() { + if mb.cache == nil && mb.fss == nil { + if mb.ctmr != nil { + mb.ctmr.Stop() + mb.ctmr = nil + } + return + } + + // Can't expire if we still have pending. + if mb.cache != nil && len(mb.cache.buf)-int(mb.cache.wp) > 0 { + mb.resetCacheExpireTimer(mb.cexp) + return + } + + // Grab timestamp to compare. + tns := ats.AccessTime() + + // For the core buffer of messages, we care about reads and writes, but not removes. + bufts := mb.llts + if mb.lwts > bufts { + bufts = mb.lwts + } + + // Check for activity on the cache that would prevent us from expiring. + if tns-bufts <= int64(mb.cexp) { + mb.resetCacheExpireTimer(mb.cexp - time.Duration(tns-bufts)) + return + } + + // If we are here we will at least expire the core msg buffer. + // We need to capture offset in case we do a write next before a full load. + if mb.cache != nil { + mb.cache.off += len(mb.cache.buf) + if !mb.cache.nra { + recycleMsgBlockBuf(mb.cache.buf) + } + mb.cache.buf = nil + mb.cache.wp = 0 + } + + // Check if we can clear out our idx unless under force expire. + // fss we keep longer and expire under sync timer checks. + mb.clearCache() +} + +func (fs *fileStore) startAgeChk() { + if fs.ageChk != nil { + return + } + if fs.cfg.MaxAge != 0 || fs.ttls != nil { + fs.ageChk = time.AfterFunc(fs.cfg.MaxAge, fs.expireMsgs) + } +} + +// Lock should be held. +func (fs *fileStore) resetAgeChk(delta int64) { + // If we're already expiring messages, it will make sure to reset. + // Don't trigger again, as that could result in many expire goroutines. + if fs.ageChkRun { + return + } + + var next int64 = math.MaxInt64 + if fs.ttls != nil { + next = fs.ttls.GetNextExpiration(next) + } + + // If there's no MaxAge and there's nothing waiting to be expired then + // don't bother continuing. The next storeRawMsg() will wake us up if + // needs be. + if fs.cfg.MaxAge <= 0 && next == math.MaxInt64 { + clearTimer(&fs.ageChk) + return + } + + // Check to see if we should be firing sooner than MaxAge for an expiring TTL. + fireIn := fs.cfg.MaxAge + + // If delta for next-to-expire message is unset, but we still have messages to remove. + // Assume messages are removed through proposals, and we need to speed up subsequent age check. + if delta == 0 && fs.state.Msgs > 0 { + if until := 2 * time.Second; until < fireIn { + fireIn = until + } + } + + if next < math.MaxInt64 { + // Looks like there's a next expiration, use it either if there's no + // MaxAge set or if it looks to be sooner than MaxAge is. + if until := time.Until(time.Unix(0, next)); fireIn == 0 || until < fireIn { + fireIn = until + } + } + + // If not then look at the delta provided (usually gap to next age expiry). + if delta > 0 { + if fireIn == 0 || time.Duration(delta) < fireIn { + fireIn = time.Duration(delta) + } + } + + // Make sure we aren't firing too often either way, otherwise we can + // negatively impact stream ingest performance. + if fireIn < 250*time.Millisecond { + fireIn = 250 * time.Millisecond + } + + // If we want to kick the timer to run later than what was assigned before, don't reset it. + // Otherwise, we could get in a situation where the timer is continuously reset, and it never runs. + expires := ats.AccessTime() + fireIn.Nanoseconds() + if fs.ageChkTime > 0 && expires > fs.ageChkTime { + return + } + + fs.ageChkTime = expires + if fs.ageChk != nil { + fs.ageChk.Reset(fireIn) + } else { + fs.ageChk = time.AfterFunc(fireIn, fs.expireMsgs) + } +} + +// Lock should be held. +func (fs *fileStore) cancelAgeChk() { + if fs.ageChk != nil { + fs.ageChk.Stop() + fs.ageChk = nil + fs.ageChkTime = 0 + } +} + +// Will expire msgs that are too old. +func (fs *fileStore) expireMsgs() { + // We need to delete one by one here and can not optimize for the time being. + // Reason is that we need more information to adjust ack pending in consumers. + var smv StoreMsg + var sm *StoreMsg + + fs.mu.Lock() + maxAge := int64(fs.cfg.MaxAge) + minAge := ats.AccessTime() - maxAge + rmcb := fs.rmcb + sdmcb := fs.sdmcb + sdmTTL := int64(fs.cfg.SubjectDeleteMarkerTTL.Seconds()) + sdmEnabled := sdmTTL > 0 + + // If SDM is enabled, but handlers aren't set up yet. Try again later. + if sdmEnabled && (rmcb == nil || sdmcb == nil) { + fs.resetAgeChk(0) + fs.mu.Unlock() + return + } + fs.ageChkRun = true + fs.mu.Unlock() + + if maxAge > 0 { + var seq uint64 + for sm, seq, _ = fs.LoadNextMsg(fwcs, true, 0, &smv); sm != nil && sm.ts <= minAge; sm, seq, _ = fs.LoadNextMsg(fwcs, true, seq+1, &smv) { + if len(sm.hdr) > 0 { + if ttl, err := getMessageTTL(sm.hdr); err == nil && ttl < 0 { + // The message has a negative TTL, therefore it must "never expire". + minAge = ats.AccessTime() - maxAge + continue + } + } + // Remove the message and then, if LimitsTTL is enabled, try and work out + // if it was the last message of that particular subject that we just deleted. + if sdmEnabled { + if last, ok := fs.shouldProcessSdm(seq, sm.subj); ok { + sdm := last && !isSubjectDeleteMarker(sm.hdr) + fs.handleRemovalOrSdm(seq, sm.subj, sdm, sdmTTL) + } + } else { + fs.mu.Lock() + fs.removeMsgViaLimits(sm.seq) + fs.mu.Unlock() + } + // Recalculate in case we are expiring a bunch. + minAge = ats.AccessTime() - maxAge + } + } + var ageDelta int64 + if sm != nil { + ageDelta = sm.ts - minAge + } + + fs.mu.Lock() + defer fs.mu.Unlock() + + // TODO: Not great that we're holding the lock here, but the timed hash wheel isn't thread-safe. + nextTTL := int64(math.MaxInt64) + var rmSeqs []thw.HashWheelEntry + if fs.ttls != nil { + fs.ttls.ExpireTasks(func(seq uint64, ts int64) bool { + rmSeqs = append(rmSeqs, thw.HashWheelEntry{Seq: seq, Expires: ts}) + // We might need to remove messages out of band, those can fail, and we can be shutdown halfway + // through so don't remove from THW just yet. + return false + }) + nextTTL = fs.ttls.GetNextExpiration(math.MaxInt64) + } + + // Remove messages collected by THW. + if !sdmEnabled { + for _, rm := range rmSeqs { + fs.removeMsg(rm.Seq, false, false, false) + } + } else { + // THW is unordered, so must sort by sequence and must not be holding the lock. + fs.mu.Unlock() + slices.SortFunc(rmSeqs, func(a, b thw.HashWheelEntry) int { + if a.Seq == b.Seq { + return 0 + } else if a.Seq < b.Seq { + return -1 + } else { + return 1 + } + }) + for _, rm := range rmSeqs { + // Need to grab subject for the specified sequence if for SDM, and check + // if the message hasn't been removed in the meantime. + // We need to grab the message and check if we should process SDM while holding the lock, + // otherwise we can race if a deletion of this message is in progress. + fs.mu.Lock() + sm, _ = fs.msgForSeqLocked(rm.Seq, &smv, false) + if sm == nil { + fs.ttls.Remove(rm.Seq, rm.Expires) + fs.mu.Unlock() + continue + } + last, ok := fs.shouldProcessSdmLocked(rm.Seq, sm.subj) + fs.mu.Unlock() + if ok { + sdm := last && !isSubjectDeleteMarker(sm.hdr) + fs.handleRemovalOrSdm(rm.Seq, sm.subj, sdm, sdmTTL) + } + } + fs.mu.Lock() + } + + // Only cancel if no message left, not on potential lookup error that would result in sm == nil. + fs.ageChkRun, fs.ageChkTime = false, 0 + if fs.state.Msgs == 0 && nextTTL == math.MaxInt64 { + fs.cancelAgeChk() + } else { + fs.resetAgeChk(ageDelta) + } +} + +func (fs *fileStore) shouldProcessSdm(seq uint64, subj string) (bool, bool) { + fs.mu.Lock() + defer fs.mu.Unlock() + return fs.shouldProcessSdmLocked(seq, subj) +} + +// Lock should be held. +func (fs *fileStore) shouldProcessSdmLocked(seq uint64, subj string) (bool, bool) { + if fs.sdm == nil { + fs.sdm = newSDMMeta() + } + + if p, ok := fs.sdm.pending[seq]; ok { + // Don't allow more proposals for the same sequence if we already did recently. + if time.Since(time.Unix(0, p.ts)) < 2*time.Second { + return p.last, false + } + // If we're about to use the cached value, and we knew it was last before, + // quickly check that we don't have more remaining messages for the subject now. + // Which means we are not the last anymore and must reset to not remove later data. + if p.last { + msgs := fs.subjectsTotalsLocked(subj)[subj] + numPending := fs.sdm.totals[subj] + if remaining := msgs - numPending; remaining > 0 { + p.last = false + } + } + fs.sdm.pending[seq] = SDMBySeq{p.last, time.Now().UnixNano()} + return p.last, true + } + + msgs := fs.subjectsTotalsLocked(subj)[subj] + if msgs == 0 { + return false, true + } + numPending := fs.sdm.totals[subj] + remaining := msgs - numPending + return fs.sdm.trackPending(seq, subj, remaining == 1), true +} + +func (fs *fileStore) handleRemovalOrSdm(seq uint64, subj string, sdm bool, sdmTTL int64) { + if sdm { + var _hdr [128]byte + hdr := fmt.Appendf( + _hdr[:0], + "NATS/1.0\r\n%s: %s\r\n%s: %s\r\n%s: %s\r\n\r\n", + JSMarkerReason, JSMarkerReasonMaxAge, + JSMessageTTL, time.Duration(sdmTTL)*time.Second, + JSMsgRollup, JSMsgRollupSubject, + ) + msg := &inMsg{ + subj: subj, + hdr: hdr, + } + fs.sdmcb(msg) + } else { + fs.rmcb(seq) + } +} + +// Lock should be held. +func (fs *fileStore) checkAndFlushAllBlocks() { + for _, mb := range fs.blks { + if mb.pendingWriteSize() > 0 { + // Since fs lock is held need to pull this apart in case we need to rebuild state. + mb.mu.Lock() + ld, _ := mb.flushPendingMsgsLocked() + mb.mu.Unlock() + if ld != nil { + fs.rebuildStateLocked(ld) + } + } + } +} + +// This will check all the checksums on messages and report back any sequence numbers with errors. +func (fs *fileStore) checkMsgs() *LostStreamData { + fs.mu.Lock() + defer fs.mu.Unlock() + + fs.checkAndFlushAllBlocks() + + // Clear any global subject state. + fs.psim, fs.tsl = fs.psim.Empty(), 0 + + for _, mb := range fs.blks { + // Make sure encryption loaded if needed for the block. + fs.loadEncryptionForMsgBlock(mb) + // FIXME(dlc) - check tombstones here too? + if ld, _, err := mb.rebuildState(); err != nil && ld != nil { + // Rebuild fs state too. + fs.rebuildStateLocked(ld) + } + fs.populateGlobalPerSubjectInfo(mb) + } + + return fs.ld +} + +// Lock should be held. +func (mb *msgBlock) enableForWriting(fip bool) error { + if mb == nil { + return errNoMsgBlk + } + if mb.mfd != nil { + return nil + } + <-dios + mfd, err := os.OpenFile(mb.mfn, os.O_CREATE|os.O_RDWR, defaultFilePerms) + dios <- struct{}{} + if err != nil { + return fmt.Errorf("error opening msg block file [%q]: %v", mb.mfn, err) + } + mb.mfd = mfd + + // Spin up our flusher loop if needed. + if !fip { + mb.spinUpFlushLoopLocked() + } + + return nil +} + +// Helper function to place a delete tombstone. +func (mb *msgBlock) writeTombstone(seq uint64, ts int64) error { + return mb.writeMsgRecord(emptyRecordLen, seq|tbit, _EMPTY_, nil, nil, ts, true) +} + +// Helper function to place a delete tombstone without flush. +// Lock should not be held. +func (mb *msgBlock) writeTombstoneNoFlush(seq uint64, ts int64) error { + mb.mu.Lock() + defer mb.mu.Unlock() + return mb.writeMsgRecordLocked(emptyRecordLen, seq|tbit, _EMPTY_, nil, nil, ts, false, false) +} + +// Will write the message record to the underlying message block. +// filestore lock will be held. +func (mb *msgBlock) writeMsgRecord(rl, seq uint64, subj string, mhdr, msg []byte, ts int64, flush bool) error { + mb.mu.Lock() + defer mb.mu.Unlock() + return mb.writeMsgRecordLocked(rl, seq, subj, mhdr, msg, ts, flush, true) +} + +// Will write the message record to the underlying message block. +// filestore lock will be held. +// mb lock should be held. +func (mb *msgBlock) writeMsgRecordLocked(rl, seq uint64, subj string, mhdr, msg []byte, ts int64, flush, kick bool) error { + // Enable for writing if our mfd is not open. + if mb.mfd == nil { + if err := mb.enableForWriting(flush && kick); err != nil { + return err + } + } + + // Make sure we have a cache setup. + if mb.cache == nil { + mb.setupWriteCache(nil) + } + + // Check if we are tracking per subject for our simple state. + // Do this before changing the cache that would trigger a flush pending msgs call + // if we needed to regenerate the per subject info. + // Note that tombstones have no subject so will not trigger here. + if len(subj) > 0 && !mb.noTrack { + if err := mb.ensurePerSubjectInfoLoaded(); err != nil { + return err + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + if ss, ok := mb.fss.Find(stringToBytes(subj)); ok && ss != nil { + ss.Msgs++ + ss.Last = seq + ss.lastNeedsUpdate = false + } else { + mb.fss.Insert(stringToBytes(subj), SimpleState{Msgs: 1, First: seq, Last: seq}) + } + } + + // Indexing + index := len(mb.cache.buf) + int(mb.cache.off) + + // Formats + // Format with no header + // total_len(4) sequence(8) timestamp(8) subj_len(2) subj msg hash(8) + // With headers, high bit on total length will be set. + // total_len(4) sequence(8) timestamp(8) subj_len(2) subj hdr_len(4) hdr msg hash(8) + + var le = binary.LittleEndian + + l := uint32(rl) + hasHeaders := len(mhdr) > 0 + if hasHeaders { + l |= hbit + } + + // Reserve space for the header on the underlying buffer. + mb.cache.buf = append(mb.cache.buf, make([]byte, msgHdrSize)...) + hdr := mb.cache.buf[len(mb.cache.buf)-msgHdrSize : len(mb.cache.buf)] + le.PutUint32(hdr[0:], l) + le.PutUint64(hdr[4:], seq) + le.PutUint64(hdr[12:], uint64(ts)) + le.PutUint16(hdr[20:], uint16(len(subj))) + + // Now write to underlying buffer. + mb.cache.buf = append(mb.cache.buf, subj...) + + if hasHeaders { + var hlen [4]byte + le.PutUint32(hlen[0:], uint32(len(mhdr))) + mb.cache.buf = append(mb.cache.buf, hlen[:]...) + mb.cache.buf = append(mb.cache.buf, mhdr...) + } + mb.cache.buf = append(mb.cache.buf, msg...) + + // Calculate hash. + mb.hh.Reset() + mb.hh.Write(hdr[4:20]) + mb.hh.Write(stringToBytes(subj)) + if hasHeaders { + mb.hh.Write(mhdr) + } + mb.hh.Write(msg) + checksum := mb.hh.Sum(mb.lchk[:0:highwayhash.Size64]) + copy(mb.lchk[0:], checksum) + + // Update write through cache. + // Write to msg record. + mb.cache.buf = append(mb.cache.buf, checksum...) + mb.cache.lrl = uint32(rl) + + // Set cache timestamp for last store. + mb.lwts = ts + + // Only update index and do accounting if not a delete tombstone. + if seq&tbit == 0 { + // Accounting, do this before stripping ebit, it is ebit aware. + mb.updateAccounting(seq, ts, rl) + // Strip ebit if set. + seq = seq &^ ebit + if mb.cache.fseq == 0 { + mb.cache.fseq = seq + } + // Write index + mb.cache.idx = append(mb.cache.idx, uint32(index)|cbit) + } else { + // If the block is empty, still adjust the accounting accordingly. + tseq := seq &^ tbit + if mb.msgs == 0 && tseq > atomic.LoadUint64(&mb.last.seq) { + atomic.StoreUint64(&mb.last.seq, tseq) + mb.last.ts = ts + atomic.StoreUint64(&mb.first.seq, tseq+1) + mb.first.ts = 0 + } + // Make sure to account for tombstones in rbytes. + mb.rbytes += rl + } + + fch, werr := mb.fch, mb.werr + + // If we should be flushing, or had a write error, do so here. + if flush || werr != nil { + ld, err := mb.flushPendingMsgsLocked() + if ld != nil && mb.fs != nil { + // We have the mb lock here, this needs the mb locks so do in its own go routine. + go mb.fs.rebuildState(ld) + } + if err != nil { + return err + } + } else if kick { + // Kick the flusher here. + kickFlusher(fch) + } + + return nil +} + +// How many bytes pending to be written for this message block. +func (mb *msgBlock) pendingWriteSize() int { + if mb == nil { + return 0 + } + mb.mu.RLock() + defer mb.mu.RUnlock() + return mb.pendingWriteSizeLocked() +} + +// How many bytes pending to be written for this message block. +func (mb *msgBlock) pendingWriteSizeLocked() int { + if mb == nil { + return 0 + } + var pending int + if !mb.closed && mb.mfd != nil && mb.cache != nil { + pending = len(mb.cache.buf) - int(mb.cache.wp) + } + return pending +} + +// Try to close our FDs if we can. +func (mb *msgBlock) closeFDs() error { + mb.mu.Lock() + defer mb.mu.Unlock() + return mb.closeFDsLocked() +} + +func (mb *msgBlock) closeFDsLocked() error { + if buf, _ := mb.bytesPending(); len(buf) > 0 { + return errPendingData + } + mb.closeFDsLockedNoCheck() + return nil +} + +func (mb *msgBlock) closeFDsLockedNoCheck() { + if mb.mfd != nil { + mb.mfd.Close() + mb.mfd = nil + } +} + +// bytesPending returns the buffer to be used for writing to the underlying file. +// This marks we are in flush and will return nil if asked again until cleared. +// Lock should be held. +func (mb *msgBlock) bytesPending() ([]byte, error) { + if mb == nil || mb.mfd == nil { + return nil, errNoPending + } + if mb.cache == nil { + return nil, errNoCache + } + if len(mb.cache.buf) <= mb.cache.wp { + return nil, errNoPending + } + buf := mb.cache.buf[mb.cache.wp:] + if len(buf) == 0 { + return nil, errNoPending + } + return buf, nil +} + +// Returns the current blkSize including deleted msgs etc. +func (mb *msgBlock) blkSize() uint64 { + if mb == nil { + return 0 + } + mb.mu.RLock() + nb := mb.rbytes + mb.mu.RUnlock() + return nb +} + +// Update accounting on a write msg. +// Lock should be held. +func (mb *msgBlock) updateAccounting(seq uint64, ts int64, rl uint64) { + isDeleted := seq&ebit != 0 + if isDeleted { + seq = seq &^ ebit + } + + fseq := atomic.LoadUint64(&mb.first.seq) + if (fseq == 0 || mb.first.ts == 0) && seq >= fseq { + atomic.StoreUint64(&mb.first.seq, seq) + mb.first.ts = ts + } + // Need atomics here for selectMsgBlock speed. + atomic.StoreUint64(&mb.last.seq, seq) + mb.last.ts = ts + mb.rbytes += rl + if !isDeleted { + mb.bytes += rl + mb.msgs++ + } +} + +// Helper to check last msg block and create new one if too big. +// Lock should be held. +func (fs *fileStore) checkLastBlock(rl uint64) (lmb *msgBlock, err error) { + // Grab our current last message block. + lmb = fs.lmb + rbytes := lmb.blkSize() + if lmb == nil || (rbytes > 0 && rbytes+rl > fs.fcfg.BlockSize) { + if lmb, err = fs.newMsgBlockForWrite(); err != nil { + return nil, err + } + } + return lmb, nil +} + +// Lock should be held. +func (fs *fileStore) writeMsgRecord(seq uint64, ts int64, subj string, hdr, msg []byte) (uint64, error) { + // Get size for this message. + rl := fileStoreMsgSize(subj, hdr, msg) + if rl&hbit != 0 || rl > rlBadThresh { + return 0, ErrMsgTooLarge + } + // Grab our current last message block. + mb, err := fs.checkLastBlock(rl) + if err != nil { + return 0, err + } + + // Mark as dirty for stream state. + fs.dirty++ + + // Ask msg block to store in write through cache. + err = mb.writeMsgRecord(rl, seq, subj, hdr, msg, ts, fs.fip) + + return rl, err +} + +// For writing tombstones to our lmb. This version will enforce maximum block sizes. +// Lock should be held. +func (fs *fileStore) writeTombstone(seq uint64, ts int64) error { + // Grab our current last message block. + lmb, err := fs.checkLastBlock(emptyRecordLen) + if err != nil { + return err + } + return lmb.writeTombstone(seq, ts) +} + +// For writing tombstones to our lmb. This version will enforce maximum block sizes. +// This version does not flush contents. +// Lock should be held. +func (fs *fileStore) writeTombstoneNoFlush(seq uint64, ts int64) error { + lmb, err := fs.checkLastBlock(emptyRecordLen) + if err != nil { + return err + } + // Write tombstone without flush or kick. + return lmb.writeTombstoneNoFlush(seq, ts) +} + +// Lock should be held. +func (mb *msgBlock) recompressOnDiskIfNeeded() error { + alg := mb.fs.fcfg.Compression + + // Open up the file block and read in the entire contents into memory. + // One of two things will happen: + // 1. The block will be compressed already and have a valid metadata + // header, in which case we do nothing. + // 2. The block will be uncompressed, in which case we will compress it + // and then write it back out to disk, re-encrypting if necessary. + <-dios + origBuf, err := os.ReadFile(mb.mfn) + dios <- struct{}{} + + if err != nil { + return fmt.Errorf("failed to read original block from disk: %w", err) + } + + // If the block is encrypted then we will need to decrypt it before + // doing anything. We always encrypt after compressing because then the + // compression can be as efficient as possible on the raw data, whereas + // the encrypted ciphertext will not compress anywhere near as well. + // The block encryption also covers the optional compression metadata. + if err = mb.encryptOrDecryptIfNeeded(origBuf); err != nil { + return err + } + + meta := &CompressionInfo{} + if _, err := meta.UnmarshalMetadata(origBuf); err != nil { + // An error is only returned here if there's a problem with parsing + // the metadata. If the file has no metadata at all, no error is + // returned and the algorithm defaults to no compression. + return fmt.Errorf("failed to read existing metadata header: %w", err) + } + if meta.Algorithm == alg { + // The block is already compressed with the chosen algorithm so there + // is nothing else to do. This is not a common case, it is here only + // to ensure we don't do unnecessary work in case something asked us + // to recompress an already compressed block with the same algorithm. + return nil + } else if alg != NoCompression { + // The block is already compressed using some algorithm, so we need + // to decompress the block using the existing algorithm before we can + // recompress it with the new one. + if origBuf, err = meta.Algorithm.Decompress(origBuf); err != nil { + return fmt.Errorf("failed to decompress original block: %w", err) + } + } + + return mb.atomicOverwriteFile(origBuf, true) +} + +// Lock should be held. +func (mb *msgBlock) atomicOverwriteFile(buf []byte, allowCompress bool) error { + if mb.mfd != nil { + mb.closeFDsLockedNoCheck() + defer mb.enableForWriting(mb.fs.fip) + } + + origFN := mb.mfn // The original message block on disk. + tmpFN := mb.mfn + blkTmpSuffix // The new block will be written here. + + // Rather than modifying the existing block on disk (which is a dangerous + // operation if something goes wrong), create a new temporary file. We will + // write out the new block here and then swap the files around afterwards + // once everything else has succeeded correctly. + <-dios + tmpFD, err := os.OpenFile(tmpFN, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, defaultFilePerms) + dios <- struct{}{} + + if err != nil { + return fmt.Errorf("failed to create temporary file: %w", err) + } + + errorCleanup := func(err error) error { + tmpFD.Close() + os.Remove(tmpFN) + return err + } + + alg := NoCompression + if calg := mb.fs.fcfg.Compression; calg != NoCompression && allowCompress { + alg = calg + // The original buffer at this point is uncompressed, so we will now compress + // it if needed. Note that if the selected algorithm is NoCompression, the + // Compress function will just return the input buffer unmodified. + if buf, err = alg.Compress(buf); err != nil { + return errorCleanup(fmt.Errorf("failed to compress block: %w", err)) + } + + // We only need to write out the metadata header if compression is enabled. + // If we're trying to uncompress the file on disk at this point, don't bother + // writing metadata. + meta := &CompressionInfo{ + Algorithm: alg, + OriginalSize: uint64(len(buf)), + } + buf = append(meta.MarshalMetadata(), buf...) + } + + // Re-encrypt the block if necessary. + if err = mb.encryptOrDecryptIfNeeded(buf); err != nil { + return errorCleanup(err) + } + + // Write the new block data (which might be compressed or encrypted) to the + // temporary file. + if n, err := tmpFD.Write(buf); err != nil { + return errorCleanup(fmt.Errorf("failed to write to temporary file: %w", err)) + } else if n != len(buf) { + return errorCleanup(fmt.Errorf("short write to temporary file (%d != %d)", n, len(buf))) + } + if err := tmpFD.Sync(); err != nil { + return errorCleanup(fmt.Errorf("failed to sync temporary file: %w", err)) + } + if err := tmpFD.Close(); err != nil { + return errorCleanup(fmt.Errorf("failed to close temporary file: %w", err)) + } + + // Now replace the original file with the newly updated temp file. + if err := os.Rename(tmpFN, origFN); err != nil { + return fmt.Errorf("failed to move temporary file into place: %w", err) + } + + // Since the message block might be retained in memory, make sure the + // compression algorithm is up-to-date, since this will be needed when + // compacting or truncating. + mb.cmp = alg + + // Also update rbytes + mb.rbytes = uint64(len(buf)) + + return nil +} + +// Lock should be held. +func (mb *msgBlock) decompressIfNeeded(buf []byte) ([]byte, error) { + var meta CompressionInfo + if n, err := meta.UnmarshalMetadata(buf); err != nil { + // There was a problem parsing the metadata header of the block. + // If there's no metadata header, an error isn't returned here, + // we will instead just use default values of no compression. + return nil, err + } else if n == 0 { + // There were no metadata bytes, so we assume the block is not + // compressed and return it as-is. + return buf, nil + } else { + // Metadata was present so it's quite likely the block contents + // are compressed. If by any chance the metadata claims that the + // block is uncompressed, then the input slice is just returned + // unmodified. + return meta.Algorithm.Decompress(buf[n:]) + } +} + +// Lock should be held. +func (mb *msgBlock) encryptOrDecryptIfNeeded(buf []byte) error { + if mb.bek != nil && len(buf) > 0 { + bek, err := genBlockEncryptionKey(mb.fs.fcfg.Cipher, mb.seed, mb.nonce) + if err != nil { + return err + } + mb.bek = bek + mb.bek.XORKeyStream(buf, buf) + } + return nil +} + +// Lock should be held. +func (mb *msgBlock) ensureRawBytesLoaded() error { + if mb.rbytes > 0 { + return nil + } + f, err := mb.openBlock() + if err != nil { + return err + } + defer f.Close() + if fi, err := f.Stat(); fi != nil && err == nil { + mb.rbytes = uint64(fi.Size()) + } else { + return err + } + return nil +} + +// Sync msg and index files as needed. This is called from a timer. +func (fs *fileStore) syncBlocks() { + if fs.isClosed() { + return + } + fs.mu.Lock() + blks := append([]*msgBlock(nil), fs.blks...) + lmb, firstMoved, firstSeq := fs.lmb, fs.firstMoved, fs.state.FirstSeq + // Clear first moved. + fs.firstMoved = false + fs.mu.Unlock() + + var markDirty bool + for _, mb := range blks { + // Do actual sync. Hold lock for consistency. + mb.mu.Lock() + if mb.closed { + mb.mu.Unlock() + continue + } + // See if we can close FDs due to being idle. + if mb.mfd != nil && mb.sinceLastWriteActivity() > closeFDsIdle && mb.pendingWriteSizeLocked() == 0 { + mb.dirtyCloseWithRemove(false) + } + // If our first has moved and we are set to noCompact (which is from tombstones), + // clear so that we might cleanup tombstones. + if firstMoved && mb.noCompact { + mb.noCompact = false + } + // Check if we should compact here as well. + // Do not compact last mb. + var needsCompact bool + if mb != lmb && mb.ensureRawBytesLoaded() == nil && mb.shouldCompactSync() { + needsCompact = true + markDirty = true + } + + // Flush anything that may be pending. + mb.flushPendingMsgsLocked() + // Check if we need to sync. We will not hold lock during actual sync. + needSync := mb.needSync + mb.mu.Unlock() + + // Check if we should compact here. + // Need to hold fs lock in case we reference psim when loading in the mb and we may remove this block if truly empty. + if needsCompact { + fs.mu.RLock() + mb.mu.Lock() + mb.compactWithFloor(firstSeq) + // If this compact removed all raw bytes due to tombstone cleanup, schedule to remove. + shouldRemove := mb.rbytes == 0 + mb.mu.Unlock() + fs.mu.RUnlock() + + // Check if we should remove. This will not be common, so we will re-take fs write lock here vs changing + // it above which we would prefer to be a readlock such that other lookups can occur while compacting this block. + if shouldRemove { + fs.mu.Lock() + mb.mu.Lock() + fs.removeMsgBlock(mb) + mb.mu.Unlock() + fs.mu.Unlock() + needSync = false + } + } + + // Check if we need to sync this block. + if needSync { + mb.mu.Lock() + var fd *os.File + var didOpen bool + if mb.mfd != nil { + fd = mb.mfd + } else { + <-dios + fd, _ = os.OpenFile(mb.mfn, os.O_RDWR, defaultFilePerms) + dios <- struct{}{} + didOpen = true + } + // If we have an fd. + if fd != nil { + canClear := fd.Sync() == nil + // If we opened the file close the fd. + if didOpen { + fd.Close() + } + // Only clear sync flag on success. + if canClear { + mb.needSync = false + } + } + mb.mu.Unlock() + } + } + + if fs.isClosed() { + return + } + fs.mu.Lock() + fs.setSyncTimer() + if markDirty { + fs.dirty++ + } + + // Sync state file if we are not running with sync always. + if !fs.fcfg.SyncAlways { + fn := filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile) + <-dios + fd, _ := os.OpenFile(fn, os.O_RDWR, defaultFilePerms) + dios <- struct{}{} + if fd != nil { + fd.Sync() + fd.Close() + } + } + fs.mu.Unlock() +} + +// Select the message block where this message should be found. +// Return nil if not in the set. +// Read lock should be held. +func (fs *fileStore) selectMsgBlock(seq uint64) *msgBlock { + _, mb := fs.selectMsgBlockWithIndex(seq) + return mb +} + +// Lock should be held. +func (fs *fileStore) selectMsgBlockWithIndex(seq uint64) (int, *msgBlock) { + // Check for out of range. + if seq < fs.state.FirstSeq || seq > fs.state.LastSeq || fs.state.Msgs == 0 { + return -1, nil + } + + const linearThresh = 32 + nb := len(fs.blks) - 1 + + if nb < linearThresh { + for i, mb := range fs.blks { + if seq <= atomic.LoadUint64(&mb.last.seq) { + return i, mb + } + } + return -1, nil + } + + // Do traditional binary search here since we know the blocks are sorted by sequence first and last. + for low, high, mid := 0, nb, nb/2; low <= high; mid = (low + high) / 2 { + mb := fs.blks[mid] + // Right now these atomic loads do not factor in, so fine to leave. Was considering + // uplifting these to fs scope to avoid atomic load but not needed. + first, last := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) + if seq > last { + low = mid + 1 + } else if seq < first { + // A message block's first sequence can change here meaning we could find a gap. + // We want to behave like above, which if inclusive (we check at start) should + // always return an index and a valid mb. + // If we have a gap then our seq would be > fs.blks[mid-1].last.seq + if mid == 0 || seq > atomic.LoadUint64(&fs.blks[mid-1].last.seq) { + return mid, mb + } + high = mid - 1 + } else { + return mid, mb + } + } + + return -1, nil +} + +// Select the message block where this message should be found. +// Return nil if not in the set. +func (fs *fileStore) selectMsgBlockForStart(minTime time.Time) *msgBlock { + fs.mu.RLock() + defer fs.mu.RUnlock() + + // Binary search for first block where last.ts >= t. + i, _ := slices.BinarySearchFunc(fs.blks, minTime.UnixNano(), func(mb *msgBlock, target int64) int { + mb.mu.RLock() + last := mb.last.ts + mb.mu.RUnlock() + switch { + case last < target: + return -1 + case last > target: + return 1 + default: + return 0 + } + }) + + // BinarySearchFunc returns an insertion point if not found. + // Either way, i is the index of the first mb where mb.last.ts >= t. + if i < len(fs.blks) { + return fs.blks[i] + } + return nil +} + +// Index a raw msg buffer. +// Lock should be held. +func (mb *msgBlock) indexCacheBuf(buf []byte) error { + var le = binary.LittleEndian + + var fseq uint64 + var idx []uint32 + var index uint32 + + mbFirstSeq := atomic.LoadUint64(&mb.first.seq) + mbLastSeq := atomic.LoadUint64(&mb.last.seq) + + // Sanity check here since we calculate size to allocate based on this. + if mbFirstSeq > (mbLastSeq + 1) { // Purged state first == last + 1 + mb.fs.warn("indexCacheBuf corrupt state in %s: mb.first %d mb.last %d", mb.mfn, mbFirstSeq, mbLastSeq) + // This would cause idxSz to wrap. + return errCorruptState + } + + idxSz := mbLastSeq - mbFirstSeq + 1 + + if mb.cache == nil || mb.cache.buf == nil { + // Approximation, may adjust below. + fseq = mbFirstSeq + if mb.cache != nil && mb.cache.idx != nil { + idx = mb.cache.idx[:0] + } else { + idx = make([]uint32, 0, idxSz) + } + if mb.cache == nil { + mb.cache = &cache{} + } else { + *mb.cache = cache{} + } + } else { + fseq = mb.cache.fseq + idx = mb.cache.idx + if len(idx) == 0 { + idx = make([]uint32, 0, idxSz) + } + index = uint32(len(mb.cache.buf)) + buf = append(mb.cache.buf, buf...) + } + + // Create FSS if we should track. + var popFss bool + if mb.fssNotLoaded() { + mb.fss = stree.NewSubjectTree[SimpleState]() + popFss = true + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + mb.ttls = 0 + + lbuf := uint32(len(buf)) + var seq, ttls uint64 + var sm StoreMsg // Used for finding TTL headers + + // To ensure the sequence keeps moving up. As well as confirming our index + // is aligned with the mb's first and last sequence. + var first uint64 + var last uint64 + + for index < lbuf { + if index+msgHdrSize > lbuf { + return errCorruptState + } + hdr := buf[index : index+msgHdrSize] + rl, slen := le.Uint32(hdr[0:]), int(le.Uint16(hdr[20:])) + seq = le.Uint64(hdr[4:]) + + // Clear any headers bit that could be set. + hasHeaders := rl&hbit != 0 + rl &^= hbit + dlen := int(rl) - msgHdrSize + + // Do some quick sanity checks here. + if dlen < 0 || slen > (dlen-recordHashSize) || dlen > int(rl) || index+rl > lbuf || rl > rlBadThresh { + mb.fs.warn("indexCacheBuf corrupt record state in %s: dlen %d slen %d index %d rl %d lbuf %d", mb.mfn, dlen, slen, index, rl, lbuf) + // This means something is off. + // TODO(dlc) - Add into bad list? + return errCorruptState + } + + // Check for tombstones which we can skip in terms of indexing. + if seq&tbit != 0 { + index += rl + continue + } + + // Clear any erase bits. + erased := seq&ebit != 0 + seq = seq &^ ebit + + // The sequence needs to only ever move up. + if seq <= last { + // Advance to next record. + // We've already accounted for this sequence and marked it as deleted. + index += rl + continue + } + // We defer checksum checks to individual msg cache lookups to amortorize costs and + // not introduce latency for first message from a newly loaded block. + if seq >= mbFirstSeq { + last = seq + + // If the first sequence doesn't align with what we had in-memory, we need to rebuild. + if first == 0 { + first = seq + if mbFirstSeq != first { + return errCorruptState + } + } + + // Track that we do not have holes. + if slot := int(seq - mbFirstSeq); slot != len(idx) { + // If we have a hole fill it. + for dseq := mbFirstSeq + uint64(len(idx)); dseq < seq; dseq++ { + idx = append(idx, dbit) + if dseq != 0 { + mb.dmap.Insert(dseq) + } + } + } + // Add to our index. + idx = append(idx, index) + mb.cache.lrl = uint32(rl) + // Adjust if we guessed wrong. + if seq != 0 && seq < fseq { + fseq = seq + } + + // Make sure our dmap has this entry if it was erased. + // If not, that means this erased message was not accounted for in our in-memory state. + if erased && seq != 0 && !mb.dmap.Exists(seq) { + return errCorruptState + } + + // Handle FSS inline here. + if popFss && slen > 0 && !mb.noTrack && !erased && !mb.dmap.Exists(seq) { + bsubj := buf[index+msgHdrSize : index+msgHdrSize+uint32(slen)] + if ss, ok := mb.fss.Find(bsubj); ok && ss != nil { + ss.Msgs++ + ss.Last = seq + ss.lastNeedsUpdate = false + } else { + mb.fss.Insert(bsubj, SimpleState{ + Msgs: 1, + First: seq, + Last: seq, + }) + } + } + + // Count how many TTLs we think are in this message block. + // TODO(nat): Not terribly optimal... + if hasHeaders { + if fsm, err := mb.msgFromBufNoCopy(buf[index:], &sm, nil); err == nil && fsm != nil { + if ttl := sliceHeader(JSMessageTTL, fsm.hdr); len(ttl) > 0 { + ttls++ + } + } + } + } + index += rl + } + + // If we ended up with a smaller or larger index, or the first/last sequence + // doesn't align with what we had in-memory, we need to rebuild. + if len(idx) != int(idxSz) || (first > 0 && mbFirstSeq != first) || (last > 0 && mbLastSeq != last) { + return errCorruptState + } + + mb.cache.buf = buf + mb.cache.idx = idx + mb.cache.fseq = mbFirstSeq + mb.cache.wp = int(lbuf) + mb.ttls = ttls + + return nil +} + +// flushPendingMsgs writes out any messages for this message block. +func (mb *msgBlock) flushPendingMsgs() error { + mb.mu.Lock() + fsLostData, err := mb.flushPendingMsgsLocked() + fs := mb.fs + mb.mu.Unlock() + + // Signals us that we need to rebuild filestore state. + if fsLostData != nil && fs != nil { + // Rebuild fs state too. + fs.rebuildState(fsLostData) + } + return err +} + +// Write function for actual data. +// mb.mfd should not be nil. +// Lock should held. +func (mb *msgBlock) writeAt(buf []byte, woff int64) (int, error) { + // Used to mock write failures. + if mb.mockWriteErr { + // Reset on trip. + mb.mockWriteErr = false + return 0, errors.New("mock write error") + } + <-dios + n, err := mb.mfd.WriteAt(buf, woff) + dios <- struct{}{} + return n, err +} + +// flushPendingMsgsLocked writes out any messages for this message block. +// Lock should be held. +func (mb *msgBlock) flushPendingMsgsLocked() (*LostStreamData, error) { + // Signals us that we need to rebuild filestore state. + var fsLostData *LostStreamData + + if mb.cache == nil || mb.mfd == nil { + return nil, nil + } + + buf, err := mb.bytesPending() + // If we got an error back return here. + if err != nil { + // No pending data to be written is not an error. + if err == errNoPending || err == errNoCache { + err = nil + } + return nil, err + } + + woff := int64(mb.cache.off + mb.cache.wp) + lob := len(buf) + + // TODO(dlc) - Normally we would not hold the lock across I/O so we can improve performance. + // We will hold to stabilize the code base, as we have had a few anomalies with partial cache errors + // under heavy load. + + // Check if we need to encrypt. + if err := mb.checkAndLoadEncryption(); err != nil { + return nil, err + } + if mb.bek != nil && lob > 0 { + // Need to leave original alone. + var dst []byte + if lob <= defaultLargeBlockSize { + dst = getMsgBlockBuf(lob)[:lob] + } else { + dst = make([]byte, lob) + } + mb.bek.XORKeyStream(dst, buf) + buf = dst + } + + // Append new data to the message block file. + for lbb := lob; lbb > 0; lbb = len(buf) { + n, err := mb.writeAt(buf, woff) + if err != nil { + mb.dirtyCloseWithRemove(false) + ld, _, _ := mb.rebuildStateLocked() + mb.werr = err + return ld, err + } + // Update our write offset. + woff += int64(n) + // Partial write. + if n != lbb { + buf = buf[n:] + } else { + // Done. + break + } + } + + // Clear any error. + mb.werr = nil + + // Cache may be gone. + if mb.cache == nil || mb.mfd == nil { + return fsLostData, mb.werr + } + + // Check if we are in sync always mode. + if mb.syncAlways { + mb.mfd.Sync() + } else { + mb.needSync = true + } + + // Check for additional writes while we were writing to the disk. + moreBytes := len(mb.cache.buf) - mb.cache.wp - lob + + // Decide what we want to do with the buffer in hand. If we have load interest + // we will hold onto the whole thing, otherwise empty the buffer, possibly reusing it. + if ts := ats.AccessTime(); ts < mb.llts || (ts-mb.llts) <= int64(mb.cexp) { + mb.cache.wp += lob + } else { + if moreBytes == 0 { + if cap(mb.cache.buf) <= maxBufReuse { + // Reuse the entire underlying buffer + buf = mb.cache.buf[:0] + } else { + recycleMsgBlockBuf(mb.cache.buf) + buf = nil + } + } else { + // Move the additional bytes to the beginning of the buffer and re-slice so + // we will have more usable capacity at the end again for additional writes. + copy(mb.cache.buf[:moreBytes], mb.cache.buf[len(mb.cache.buf)-moreBytes:]) + buf = mb.cache.buf[:moreBytes] + } + // Update our cache offset. + mb.cache.off = int(woff) + // Reset write pointer. + mb.cache.wp = 0 + // Place buffer back in the cache structure. + mb.cache.buf = buf + // Mark fseq to 0 + mb.cache.fseq = 0 + } + + return fsLostData, mb.werr +} + +// Lock should be held. +func (mb *msgBlock) clearLoading() { + mb.loading = false +} + +// Will load msgs from disk. +func (mb *msgBlock) loadMsgs() error { + // We hold the lock here the whole time by design. + mb.mu.Lock() + defer mb.mu.Unlock() + return mb.loadMsgsWithLock() +} + +// Lock should be held. +func (mb *msgBlock) cacheAlreadyLoaded() bool { + if mb.cache == nil || mb.cache.off != 0 || mb.cache.fseq == 0 || len(mb.cache.buf) == 0 { + return false + } + numEntries := mb.msgs + uint64(mb.dmap.Size()) + (atomic.LoadUint64(&mb.first.seq) - mb.cache.fseq) + return numEntries == uint64(len(mb.cache.idx)) +} + +// Lock should be held. +func (mb *msgBlock) cacheNotLoaded() bool { + return !mb.cacheAlreadyLoaded() +} + +// Report if our fss is not loaded. +// Lock should be held. +func (mb *msgBlock) fssNotLoaded() bool { + return mb.fss == nil && !mb.noTrack +} + +// Wrap openBlock for the gated semaphore processing. +// Lock should be held +func (mb *msgBlock) openBlock() (*os.File, error) { + // Gate with concurrent IO semaphore. + <-dios + f, err := os.Open(mb.mfn) + dios <- struct{}{} + return f, err +} + +// Used to load in the block contents. +// Lock should be held and all conditionals satisfied prior. +func (mb *msgBlock) loadBlock(buf []byte) ([]byte, error) { + var f *os.File + // Re-use if we have mfd open. + if mb.mfd != nil { + f = mb.mfd + if n, err := f.Seek(0, 0); n != 0 || err != nil { + f = nil + mb.closeFDsLockedNoCheck() + } + } + if f == nil { + var err error + f, err = mb.openBlock() + if err != nil { + if os.IsNotExist(err) { + err = errNoBlkData + } + return nil, err + } + defer f.Close() + } + + var sz int + if info, err := f.Stat(); err == nil { + sz64 := info.Size() + if int64(int(sz64)) == sz64 { + sz = int(sz64) + } else { + return nil, errMsgBlkTooBig + } + } + + if buf == nil { + buf = getMsgBlockBuf(sz) + if sz > cap(buf) { + // We know we will make a new one so just recycle for now. + recycleMsgBlockBuf(buf) + buf = nil + } + } + + if sz > cap(buf) { + buf = make([]byte, sz) + } else { + buf = buf[:sz] + } + + <-dios + n, err := io.ReadFull(f, buf) + dios <- struct{}{} + // On success capture raw bytes size. + if err == nil { + mb.rbytes = uint64(n) + } + return buf[:n], err +} + +// Lock should be held. +func (mb *msgBlock) loadMsgsWithLock() error { + if err := mb.checkAndLoadEncryption(); err != nil { + return err + } + + // Check to see if we are loading already. + if mb.loading { + return nil + } + + // Set loading status. + mb.loading = true + defer mb.clearLoading() + + var nchecks int + +checkCache: + nchecks++ + if nchecks > 8 { + return errNoCache + } + + // Check to see if we have a full cache. + if mb.cacheAlreadyLoaded() { + return nil + } + + mb.llts = ats.AccessTime() + + // FIXME(dlc) - We could be smarter here. + if buf, _ := mb.bytesPending(); len(buf) > 0 { + ld, err := mb.flushPendingMsgsLocked() + if ld != nil && mb.fs != nil { + // We do not know if fs is locked or not at this point. + // This should be an exceptional condition so do so in Go routine. + go mb.fs.rebuildState(ld) + } + if err != nil { + return err + } + goto checkCache + } + + // Load in the whole block. + // We want to hold the mb lock here to avoid any changes to state. + buf, err := mb.loadBlock(nil) + if err != nil { + mb.fs.warn("loadBlock error: %v", err) + if err == errNoBlkData { + if ld, _, err := mb.rebuildStateLocked(); err != nil && ld != nil { + // Rebuild fs state too. + go mb.fs.rebuildState(ld) + } + } + return err + } + + // Reset the cache since we just read everything in. + // Make sure this is cleared in case we had a partial when we started. + mb.clearCacheAndOffset() + + // Check if we need to decrypt. + if err = mb.encryptOrDecryptIfNeeded(buf); err != nil { + return err + } + // Check for compression. + if buf, err = mb.decompressIfNeeded(buf); err != nil { + return err + } + + if err := mb.indexCacheBuf(buf); err != nil { + if err == errCorruptState { + var ld *LostStreamData + ld, _, err = mb.rebuildStateLocked() + // We do not know if fs is locked or not at this point. + // This should be an exceptional condition so do so in Go routine. + // Always rebuild the filestore's state if indexing fails, even if no data was lost, + // our in-memory state was stale in that case. + go mb.fs.rebuildState(ld) + } + if err != nil { + return err + } + goto checkCache + } + + if len(buf) > 0 { + mb.cloads++ + mb.startCacheExpireTimer() + } + + return nil +} + +// Fetch a message from this block, possibly reading in and caching the messages. +// We assume the block was selected and is correct, so we do not do range checks. +// Lock should not be held. +func (mb *msgBlock) fetchMsg(seq uint64, sm *StoreMsg) (*StoreMsg, bool, error) { + return mb.fetchMsgEx(seq, sm, true) +} + +// Fetch a message from this block, possibly reading in and caching the messages. +// We assume the block was selected and is correct, so we do not do range checks. +// We will not copy the msg data. +// Lock should not be held. +func (mb *msgBlock) fetchMsgNoCopy(seq uint64, sm *StoreMsg) (*StoreMsg, bool, error) { + return mb.fetchMsgEx(seq, sm, false) +} + +// Fetch a message from this block, possibly reading in and caching the messages. +// We assume the block was selected and is correct, so we do not do range checks. +// We will copy the msg data based on doCopy boolean. +// Lock should not be held. +func (mb *msgBlock) fetchMsgEx(seq uint64, sm *StoreMsg, doCopy bool) (*StoreMsg, bool, error) { + mb.mu.Lock() + defer mb.mu.Unlock() + + fseq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) + if seq < fseq || seq > lseq { + return nil, false, ErrStoreMsgNotFound + } + + // See if we can short circuit if we already know msg deleted. + if mb.dmap.Exists(seq) { + // Update for scanning like cacheLookup would have. + llseq := mb.llseq + if mb.llseq == 0 || seq < mb.llseq || seq == mb.llseq+1 || seq == mb.llseq-1 { + mb.llseq = seq + } + expireOk := (seq == lseq && llseq == seq-1) || (seq == fseq && llseq == seq+1) + return nil, expireOk, errDeletedMsg + } + + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return nil, false, err + } + } + llseq := mb.llseq + + fsm, err := mb.cacheLookupEx(seq, sm, doCopy) + if err != nil { + return nil, false, err + } + expireOk := (seq == lseq && llseq == seq-1) || (seq == fseq && llseq == seq+1) + return fsm, expireOk, err +} + +var ( + errNoCache = errors.New("no message cache") + errDeletedMsg = errors.New("deleted message") + errPartialCache = errors.New("partial cache") + errNoPending = errors.New("message block does not have pending data") + errNotReadable = errors.New("storage directory not readable") + errCorruptState = errors.New("corrupt state file") + errPriorState = errors.New("prior state file") + errPendingData = errors.New("pending data still present") + errNoEncryption = errors.New("encryption not enabled") + errBadKeySize = errors.New("encryption bad key size") + errNoMsgBlk = errors.New("no message block") + errMsgBlkTooBig = errors.New("message block size exceeded int capacity") + errUnknownCipher = errors.New("unknown cipher") + errNoMainKey = errors.New("encrypted store encountered with no main key") + errNoBlkData = errors.New("message block data missing") + errStateTooBig = errors.New("store state too big for optional write") +) + +type ( + errBadMsg struct{ fn, detail string } +) + +func (e errBadMsg) Error() string { + if e.detail != _EMPTY_ { + return fmt.Sprintf("malformed or corrupt message in %s: %s", filepath.Base(e.fn), e.detail) + } + return fmt.Sprintf("malformed or corrupt message in %s", filepath.Base(e.fn)) +} + +const ( + // "Checksum bit" is used in "mb.cache.idx" for marking messages that have had their checksums checked. + cbit = 1 << 31 + // "Delete bit" is used in "mb.cache.idx" to mark an index as deleted and non-existent. + dbit = 1 << 30 + // "Header bit" is used in "rl" to signal a message record with headers. + hbit = 1 << 31 + // "Erase bit" is used in "seq" for marking erased messages sequences. + ebit = 1 << 63 + // "Tombstone bit" is used in "seq" for marking tombstone sequences. + tbit = 1 << 62 +) + +// Will do a lookup from cache. +// This will copy the msg from the cache. +// Lock should be held. +func (mb *msgBlock) cacheLookup(seq uint64, sm *StoreMsg) (*StoreMsg, error) { + return mb.cacheLookupEx(seq, sm, true) +} + +// Will do a lookup from cache. +// This will NOT copy the msg from the cache. +// Lock should be held. +func (mb *msgBlock) cacheLookupNoCopy(seq uint64, sm *StoreMsg) (*StoreMsg, error) { + return mb.cacheLookupEx(seq, sm, false) +} + +// Will do a lookup from cache. +// Lock should be held. +func (mb *msgBlock) cacheLookupEx(seq uint64, sm *StoreMsg, doCopy bool) (*StoreMsg, error) { + if seq < atomic.LoadUint64(&mb.first.seq) || seq > atomic.LoadUint64(&mb.last.seq) { + return nil, ErrStoreMsgNotFound + } + + // The llseq signals us when we can expire a cache at the end of a linear scan. + // We want to only update when we know the last reads (multiple consumers) are sequential. + // We want to account for forwards and backwards linear scans. + if mb.llseq == 0 || seq < mb.llseq || seq == mb.llseq+1 || seq == mb.llseq-1 { + mb.llseq = seq + } + + // If we have a delete map check it. + if mb.dmap.Exists(seq) { + mb.llts = ats.AccessTime() + return nil, errDeletedMsg + } + + // Detect no cache loaded. + if mb.cache == nil || mb.cache.fseq == 0 || len(mb.cache.idx) == 0 || len(mb.cache.buf) == 0 { + var reason string + if mb.cache == nil { + reason = "no cache" + } else if mb.cache.fseq == 0 { + reason = "fseq is 0" + } else if len(mb.cache.idx) == 0 { + reason = "no idx present" + } else { + reason = "cache buf empty" + } + mb.fs.warn("Cache lookup detected no cache: %s", reason) + return nil, errNoCache + } + // Check partial cache status. + if seq < mb.cache.fseq { + mb.fs.warn("Cache lookup detected partial cache: seq %d vs cache fseq %d", seq, mb.cache.fseq) + return nil, errPartialCache + } + + bi, _, hashChecked, err := mb.slotInfo(int(seq - mb.cache.fseq)) + if err != nil { + return nil, err + } + + // Update cache activity. + mb.llts = ats.AccessTime() + + li := int(bi) - mb.cache.off + if li >= len(mb.cache.buf) { + return nil, errPartialCache + } + buf := mb.cache.buf[li:] + + // We use the high bit to denote we have already checked the checksum. + var hh *highwayhash.Digest64 + if !hashChecked { + hh = mb.hh // This will force the hash check in msgFromBuf. + } + + // Parse from the raw buffer. + fsm, err := mb.msgFromBufEx(buf, sm, hh, doCopy) + if err != nil || fsm == nil { + return nil, err + } + + // Deleted messages that are decoded return a 0 for sequence. + if fsm.seq == 0 { + return nil, errDeletedMsg + } + + if seq != fsm.seq { // See TestFileStoreInvalidIndexesRebuilt. + recycleMsgBlockBuf(mb.cache.buf) + mb.cache.buf = nil + return nil, fmt.Errorf("sequence numbers for cache load did not match, %d vs %d", seq, fsm.seq) + } + + // Clear the check bit here after we know all is good. + if !hashChecked { + mb.cache.idx[seq-mb.cache.fseq] = (bi | cbit) + } + + return fsm, nil +} + +// Used when we are checking if discarding a message due to max msgs per subject will give us +// enough room for a max bytes condition. +// Lock should be already held. +func (fs *fileStore) sizeForSeq(seq uint64) int { + if seq == 0 { + return 0 + } + var smv StoreMsg + if mb := fs.selectMsgBlock(seq); mb != nil { + if sm, _, _ := mb.fetchMsgNoCopy(seq, &smv); sm != nil { + return int(fileStoreMsgSize(sm.subj, sm.hdr, sm.msg)) + } + } + return 0 +} + +// Will return message for the given sequence number. +// This will be returned to external callers. +func (fs *fileStore) msgForSeq(seq uint64, sm *StoreMsg) (*StoreMsg, error) { + return fs.msgForSeqLocked(seq, sm, true) +} + +// Will return message for the given sequence number. +func (fs *fileStore) msgForSeqLocked(seq uint64, sm *StoreMsg, needFSLock bool) (*StoreMsg, error) { + if fs.isClosed() { + return nil, ErrStoreClosed + } + // TODO(dlc) - Since Store, Remove, Skip all hold the write lock on fs this will + // be stalled. Need another lock if want to happen in parallel. + if needFSLock { + fs.mu.RLock() + } + // Indicates we want first msg. + if seq == 0 { + seq = fs.state.FirstSeq + } + // Make sure to snapshot here. + mb, lseq := fs.selectMsgBlock(seq), fs.state.LastSeq + if needFSLock { + fs.mu.RUnlock() + } + + if mb == nil { + var err = ErrStoreEOF + if seq <= lseq { + err = ErrStoreMsgNotFound + } + return nil, err + } + + fsm, expireOk, err := mb.fetchMsg(seq, sm) + if err != nil { + return nil, err + } + + // We detected a linear scan and access to the last message. + // If we are not the last message block we can try to expire the cache. + if expireOk { + mb.tryForceExpireCache() + } + + return fsm, nil +} + +// Internal function to return msg parts from a raw buffer. +// Raw buffer will be copied into sm. +// Lock should be held. +func (mb *msgBlock) msgFromBuf(buf []byte, sm *StoreMsg, hh *highwayhash.Digest64) (*StoreMsg, error) { + return mb.msgFromBufEx(buf, sm, hh, true) +} + +// Internal function to return msg parts from a raw buffer. +// Raw buffer will NOT be copied into sm. +// Only use for internal use, any message that is passed to upper layers should use mb.msgFromBuf. +// Lock should be held. +func (mb *msgBlock) msgFromBufNoCopy(buf []byte, sm *StoreMsg, hh *highwayhash.Digest64) (*StoreMsg, error) { + return mb.msgFromBufEx(buf, sm, hh, false) +} + +// Internal function to return msg parts from a raw buffer. +// copy boolean will determine if we make a copy or not. +// Lock should be held. +func (mb *msgBlock) msgFromBufEx(buf []byte, sm *StoreMsg, hh *highwayhash.Digest64, doCopy bool) (*StoreMsg, error) { + if len(buf) < emptyRecordLen { + return nil, errBadMsg{mb.mfn, "record too short"} + } + var le = binary.LittleEndian + + hdr := buf[:msgHdrSize] + rl := le.Uint32(hdr[0:]) + hasHeaders := rl&hbit != 0 + rl &^= hbit // clear header bit + dlen := int(rl) - msgHdrSize + slen := int(le.Uint16(hdr[20:])) + // Simple sanity check. + if dlen < 0 || slen > (dlen-recordHashSize) || dlen > int(rl) || int(rl) > len(buf) || rl > rlBadThresh { + return nil, errBadMsg{mb.mfn, fmt.Sprintf("sanity check failed (dlen %d slen %d rl %d buf %d)", dlen, slen, rl, buf)} + } + data := buf[msgHdrSize : msgHdrSize+dlen] + // Do checksum tests here if requested. + if hh != nil { + hh.Reset() + hh.Write(hdr[4:20]) + hh.Write(data[:slen]) + if hasHeaders { + hh.Write(data[slen+4 : dlen-recordHashSize]) + } else { + hh.Write(data[slen : dlen-recordHashSize]) + } + var hb [highwayhash.Size64]byte + if !bytes.Equal(hh.Sum(hb[:0]), data[len(data)-8:]) { + return nil, errBadMsg{mb.mfn, "invalid checksum"} + } + } + seq := le.Uint64(hdr[4:]) + if seq&ebit != 0 { + seq = 0 + } + ts := int64(le.Uint64(hdr[12:])) + + // Create a StoreMsg if needed. + if sm == nil { + sm = new(StoreMsg) + } else { + sm.clear() + } + // To recycle the large blocks we can never pass back a reference, so need to copy for the upper + // layers and for us to be safe to expire, and recycle, the large msgBlocks. + end := dlen - 8 + if len(data) < end { + return nil, errBadMsg{mb.mfn, "invalid data length"} + } + + if hasHeaders { + if slen+4 > len(data) { + return nil, errBadMsg{mb.mfn, "invalid subject length greataer than data length"} + } + hl := le.Uint32(data[slen:]) + bi := slen + 4 + li := bi + int(hl) + if bi > end { + return nil, errBadMsg{mb.mfn, "invalid buffer index"} + } + if doCopy { + sm.buf = append(sm.buf, data[bi:end]...) + } else { + sm.buf = data[bi:end] + } + li, end = li-bi, end-bi + if li > len(sm.buf) || end > len(sm.buf) { + return nil, errBadMsg{mb.mfn, "invalid message length or end greater than buffer length"} + } + sm.hdr = sm.buf[0:li:li] + sm.msg = sm.buf[li:end] + } else { + if slen > end { + return nil, errBadMsg{mb.mfn, "invalid subject length greater than end"} + } + if doCopy { + sm.buf = append(sm.buf, data[slen:end]...) + } else { + sm.buf = data[slen:end] + } + mlen := end - slen + if mlen > len(sm.buf) { + return nil, errBadMsg{mb.mfn, "invalid message length greater than buffer length"} + } + sm.msg = sm.buf[0:mlen] + } + sm.seq, sm.ts = seq, ts + if slen > 0 { + if slen > len(data) { + return nil, errBadMsg{mb.mfn, "invalid subject length greater than data length"} + } + if doCopy { + // Make a copy since sm.subj lifetime may last longer. + sm.subj = string(data[:slen]) + } else { + sm.subj = bytesToString(data[:slen]) + } + } + + return sm, nil +} + +// SubjectForSeq will return what the subject is for this sequence if found. +func (fs *fileStore) SubjectForSeq(seq uint64) (string, error) { + fs.mu.RLock() + if seq < fs.state.FirstSeq { + fs.mu.RUnlock() + return _EMPTY_, ErrStoreMsgNotFound + } + var smv StoreMsg + mb := fs.selectMsgBlock(seq) + fs.mu.RUnlock() + if mb != nil { + if sm, _, _ := mb.fetchMsgNoCopy(seq, &smv); sm != nil { + return sm.subj, nil + } + } + return _EMPTY_, ErrStoreMsgNotFound +} + +// LoadMsg will lookup the message by sequence number and return it if found. +func (fs *fileStore) LoadMsg(seq uint64, sm *StoreMsg) (*StoreMsg, error) { + return fs.msgForSeq(seq, sm) +} + +// loadLast will load the last message for a subject. Subject should be non empty and not ">". +func (fs *fileStore) loadLast(subj string, sm *StoreMsg) (lsm *StoreMsg, err error) { + if fs.isClosed() { + return nil, ErrStoreClosed + } + + fs.mu.RLock() + defer fs.mu.RUnlock() + + if fs.lmb == nil { + return nil, ErrStoreClosed + } + + if len(fs.blks) == 0 { + return nil, ErrStoreMsgNotFound + } + + wc := subjectHasWildcard(subj) + var start, stop uint32 + + // If literal subject check for presence. + if wc { + start = fs.lmb.index + fs.psim.Match(stringToBytes(subj), func(_ []byte, psi *psi) { + // Keep track of start and stop indexes for this subject. + if psi.fblk < start { + start = psi.fblk + } + if psi.lblk > stop { + stop = psi.lblk + } + }) + // None matched. + if stop == 0 { + return nil, ErrStoreMsgNotFound + } + // These need to be swapped. + start, stop = stop, start + } else if info, ok := fs.psim.Find(stringToBytes(subj)); ok { + start, stop = info.lblk, info.fblk + } else { + return nil, ErrStoreMsgNotFound + } + + // Walk blocks backwards. + for i := start; i >= stop; i-- { + mb := fs.bim[i] + if mb == nil { + continue + } + mb.mu.Lock() + if err := mb.ensurePerSubjectInfoLoaded(); err != nil { + mb.mu.Unlock() + return nil, err + } + // Mark fss activity. + mb.lsts = ats.AccessTime() + + var l uint64 + // Optimize if subject is not a wildcard. + if !wc { + if ss, ok := mb.fss.Find(stringToBytes(subj)); ok && ss != nil { + l = ss.Last + } + } + if l == 0 { + _, _, l = mb.filteredPendingLocked(subj, wc, atomic.LoadUint64(&mb.first.seq)) + } + if l > 0 { + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + mb.mu.Unlock() + return nil, err + } + } + lsm, err = mb.cacheLookup(l, sm) + } + mb.mu.Unlock() + if l > 0 { + break + } + } + return lsm, err +} + +// LoadLastMsg will return the last message we have that matches a given subject. +// The subject can be a wildcard. +func (fs *fileStore) LoadLastMsg(subject string, smv *StoreMsg) (sm *StoreMsg, err error) { + if subject == _EMPTY_ || subject == fwcs { + sm, err = fs.msgForSeq(fs.lastSeq(), smv) + } else { + sm, err = fs.loadLast(subject, smv) + } + if sm == nil || (err != nil && err != ErrStoreClosed) { + err = ErrStoreMsgNotFound + } + return sm, err +} + +// LoadNextMsgMulti will find the next message matching any entry in the sublist. +func (fs *fileStore) LoadNextMsgMulti(sl *gsl.SimpleSublist, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) { + if fs.isClosed() { + return nil, 0, ErrStoreClosed + } + if sl == nil { + return fs.LoadNextMsg(_EMPTY_, false, start, smp) + } + fs.mu.RLock() + defer fs.mu.RUnlock() + + if fs.state.Msgs == 0 || start > fs.state.LastSeq { + return nil, fs.state.LastSeq, ErrStoreEOF + } + if start < fs.state.FirstSeq { + start = fs.state.FirstSeq + } + + // If start is less than or equal to beginning of our stream, meaning our first call, + // let's check the psim to see if we can skip ahead. + if start <= fs.state.FirstSeq { + var total uint64 + blkStart := uint32(math.MaxUint32) + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { + total += psi.total + // Keep track of start index for this subject. + if psi.fblk < blkStart { + blkStart = psi.fblk + } + }) + // Nothing available. + if total == 0 { + return nil, fs.state.LastSeq, ErrStoreEOF + } + // We can skip ahead. + if mb := fs.bim[blkStart]; mb != nil { + fseq := atomic.LoadUint64(&mb.first.seq) + if fseq > start { + start = fseq + } + } + } + + if bi, _ := fs.selectMsgBlockWithIndex(start); bi >= 0 { + for i := bi; i < len(fs.blks); i++ { + mb := fs.blks[i] + if sm, expireOk, err := mb.firstMatchingMulti(sl, start, smp); err == nil { + if expireOk { + mb.tryForceExpireCache() + } + return sm, sm.seq, nil + } else if err != ErrStoreMsgNotFound { + return nil, 0, err + } else { + // Nothing found in this block. We missed, if first block (bi) check psim. + // Similar to above if start <= first seq. + // TODO(dlc) - For v2 track these by filter subject since they will represent filtered consumers. + // We should not do this at all if we are already on the last block. + if i == bi && i < len(fs.blks)-1 { + nbi, err := fs.checkSkipFirstBlockMulti(sl, bi) + // Nothing available. + if err == ErrStoreEOF { + return nil, fs.state.LastSeq, ErrStoreEOF + } + // See if we can jump ahead here. + // Right now we can only spin on first, so if we have interior sparseness need to favor checking per block fss if loaded. + // For v2 will track all blocks that have matches for psim. + if nbi > i { + i = nbi - 1 // For the iterator condition i++ + } + } + // Check if we can expire. + if expireOk { + mb.tryForceExpireCache() + } + } + } + } + + return nil, fs.state.LastSeq, ErrStoreEOF + +} + +func (fs *fileStore) LoadNextMsg(filter string, wc bool, start uint64, sm *StoreMsg) (*StoreMsg, uint64, error) { + if fs.isClosed() { + return nil, 0, ErrStoreClosed + } + + fs.mu.RLock() + defer fs.mu.RUnlock() + + if fs.state.Msgs == 0 || start > fs.state.LastSeq { + return nil, fs.state.LastSeq, ErrStoreEOF + } + if start < fs.state.FirstSeq { + start = fs.state.FirstSeq + } + + // If start is less than or equal to beginning of our stream, meaning our first call, + // let's check the psim to see if we can skip ahead. + if start <= fs.state.FirstSeq { + var ss SimpleState + fs.numFilteredPendingNoLast(filter, &ss) + // Nothing available. + if ss.Msgs == 0 { + return nil, fs.state.LastSeq, ErrStoreEOF + } + // We can skip ahead. + if ss.First > start { + start = ss.First + } + } + + if bi, _ := fs.selectMsgBlockWithIndex(start); bi >= 0 { + for i := bi; i < len(fs.blks); i++ { + mb := fs.blks[i] + if sm, expireOk, err := mb.firstMatching(filter, wc, start, sm); err == nil { + if expireOk { + mb.tryForceExpireCache() + } + return sm, sm.seq, nil + } else if err != ErrStoreMsgNotFound { + return nil, 0, err + } else { + // Nothing found in this block. We missed, if first block (bi) check psim. + // Similar to above if start <= first seq. + // TODO(dlc) - For v2 track these by filter subject since they will represent filtered consumers. + // We should not do this at all if we are already on the last block. + // Also if we are a wildcard do not check if large subject space. + const wcMaxSizeToCheck = 64 * 1024 + if i == bi && i < len(fs.blks)-1 && (!wc || fs.psim.Size() < wcMaxSizeToCheck) { + nbi, err := fs.checkSkipFirstBlock(filter, wc, bi) + // Nothing available. + if err == ErrStoreEOF { + return nil, fs.state.LastSeq, ErrStoreEOF + } + // See if we can jump ahead here. + // Right now we can only spin on first, so if we have interior sparseness need to favor checking per block fss if loaded. + // For v2 will track all blocks that have matches for psim. + if nbi > i { + i = nbi - 1 // For the iterator condition i++ + } + } + // Check if we can expire. + if expireOk { + mb.tryForceExpireCache() + } + } + } } -} -// Lock should be held. -func (mb *msgBlock) startCacheExpireTimer() { - mb.resetCacheExpireTimer(0) + return nil, fs.state.LastSeq, ErrStoreEOF } -// Used when we load in a message block. -// Lock should be held. -func (mb *msgBlock) clearCacheAndOffset() { - if mb.cache != nil { - mb.cache.off = 0 - mb.cache.wp = 0 +// Will load the next non-deleted msg starting at the start sequence and walking backwards. +func (fs *fileStore) LoadPrevMsg(start uint64, smp *StoreMsg) (sm *StoreMsg, err error) { + if fs.isClosed() { + return nil, ErrStoreClosed } - mb.clearCache() -} -// Lock should be held. -func (mb *msgBlock) clearCache() { - if mb.ctmr != nil { - mb.ctmr.Stop() - mb.ctmr = nil - } - if mb.cache == nil { - return + fs.mu.RLock() + defer fs.mu.RUnlock() + + if fs.state.Msgs == 0 || start < fs.state.FirstSeq { + return nil, ErrStoreEOF } - if mb.cache.off == 0 { - mb.cache = nil - } else { - // Clear msgs and index. - mb.cache.buf = nil - mb.cache.idx = nil - mb.cache.wp = 0 + if start > fs.state.LastSeq { + start = fs.state.LastSeq + } + if smp == nil { + smp = new(StoreMsg) } -} -// Called to possibly expire a message block cache. -func (mb *msgBlock) expireCache() { - mb.mu.Lock() - defer mb.mu.Unlock() + if bi, _ := fs.selectMsgBlockWithIndex(start); bi >= 0 { + for i := bi; i >= 0; i-- { + mb := fs.blks[i] + mb.mu.Lock() + // Need messages loaded from here on out. + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + mb.mu.Unlock() + return nil, err + } + } - if mb.cache == nil { - if mb.ctmr != nil { - mb.ctmr.Stop() - mb.ctmr = nil + lseq, fseq := atomic.LoadUint64(&mb.last.seq), atomic.LoadUint64(&mb.first.seq) + if start > lseq { + start = lseq + } + for seq := start; seq >= fseq; seq-- { + if mb.dmap.Exists(seq) { + continue + } + if sm, err := mb.cacheLookup(seq, smp); err == nil { + mb.mu.Unlock() + return sm, nil + } + } + mb.mu.Unlock() } - return - } - - // Can't expire if we are flushing or still have pending. - if mb.cache.flush || (len(mb.cache.buf)-int(mb.cache.wp) > 0) { - mb.resetCacheExpireTimer(mb.cexp) - return } - // Grab timestamp to compare. - tns := time.Now().UnixNano() + return nil, ErrStoreEOF +} - // For the core buffer of messages, we care about reads and writes, but not removes. - bufts := mb.llts - if mb.lwts > bufts { - bufts = mb.lwts +// LoadPrevMsgMulti will find the previous message matching any entry in the sublist. +func (fs *fileStore) LoadPrevMsgMulti(sl *gsl.SimpleSublist, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) { + if fs.isClosed() { + return nil, 0, ErrStoreClosed } - // Check for activity on the cache that would prevent us from expiring. - if tns-bufts <= int64(mb.cexp) { - mb.resetCacheExpireTimer(mb.cexp - time.Duration(tns-bufts)) + if sl == nil { + sm, err = fs.LoadPrevMsg(start, smp) return } + fs.mu.RLock() + defer fs.mu.RUnlock() - // If we are here we will at least expire the core msg buffer. - // We need to capture offset in case we do a write next before a full load. - mb.cache.off += len(mb.cache.buf) - mb.cache.buf = nil - mb.cache.wp = 0 - - // The idx is used in removes, and will have a longer timeframe. - // See if we should also remove the idx. - if tns-mb.lrts > int64(defaultCacheIdxExpiration) { - mb.clearCache() - } else { - mb.resetCacheExpireTimer(mb.cexp) + if fs.state.Msgs == 0 || start < fs.state.FirstSeq { + return nil, fs.state.FirstSeq, ErrStoreEOF + } + if start > fs.state.LastSeq { + start = fs.state.LastSeq } -} -func (fs *fileStore) startAgeChk() { - if fs.ageChk == nil && fs.cfg.MaxAge != 0 { - fs.ageChk = time.AfterFunc(fs.cfg.MaxAge, fs.expireMsgs) + if bi, _ := fs.selectMsgBlockWithIndex(start); bi >= 0 { + for i := bi; i >= 0; i-- { + mb := fs.blks[i] + if sm, expireOk, err := mb.prevMatchingMulti(sl, start, smp); err == nil { + if expireOk { + mb.tryForceExpireCache() + } + return sm, sm.seq, nil + } else if err != ErrStoreMsgNotFound { + return nil, 0, err + } else if expireOk { + mb.tryForceExpireCache() + } + } } + + return nil, fs.state.FirstSeq, ErrStoreEOF } +// Type returns the type of the underlying store. +func (fs *fileStore) Type() StorageType { + return FileStorage +} + +// Returns number of subjects in this store. // Lock should be held. -func (fs *fileStore) expireMsgsLocked() { - fs.mu.Unlock() - fs.expireMsgs() - fs.mu.Lock() +func (fs *fileStore) numSubjects() int { + return fs.psim.Size() } -// Will expire msgs that are too old. -func (fs *fileStore) expireMsgs() { - // Make sure this is only running one at a time. - fs.mu.Lock() - if fs.expiring { - fs.mu.Unlock() - return +// numConsumers uses new lock. +func (fs *fileStore) numConsumers() int { + fs.cmu.RLock() + defer fs.cmu.RUnlock() + return len(fs.cfs) +} + +// FastState will fill in state with only the following. +// Msgs, Bytes, First and Last Sequence and Time and NumDeleted. +func (fs *fileStore) FastState(state *StreamState) { + fs.mu.RLock() + state.Msgs = fs.state.Msgs + state.Bytes = fs.state.Bytes + state.FirstSeq = fs.state.FirstSeq + state.FirstTime = fs.state.FirstTime + state.LastSeq = fs.state.LastSeq + state.LastTime = fs.state.LastTime + // Make sure to reset if being re-used. + state.Deleted, state.NumDeleted = nil, 0 + if state.LastSeq > state.FirstSeq { + state.NumDeleted = int((state.LastSeq - state.FirstSeq + 1) - state.Msgs) + if state.NumDeleted < 0 { + state.NumDeleted = 0 + } } - fs.expiring = true - fs.mu.Unlock() + state.Consumers = fs.numConsumers() + state.NumSubjects = fs.numSubjects() + fs.mu.RUnlock() +} - defer func() { - fs.mu.Lock() - fs.expiring = false - fs.mu.Unlock() - }() +// State returns the current state of the stream. +func (fs *fileStore) State() StreamState { + fs.mu.RLock() + state := fs.state + state.Consumers = fs.numConsumers() + state.NumSubjects = fs.numSubjects() + state.Deleted = nil // make sure. - now := time.Now().UnixNano() - minAge := now - int64(fs.cfg.MaxAge) + if numDeleted := int((state.LastSeq - state.FirstSeq + 1) - state.Msgs); numDeleted > 0 { + state.Deleted = make([]uint64, 0, numDeleted) + cur := fs.state.FirstSeq - for { - sm, _ := fs.msgForSeq(0) - if sm != nil && sm.ts <= minAge { - fs.deleteFirstMsg() - } else { - fs.mu.Lock() - if sm == nil { - if fs.ageChk != nil { - fs.ageChk.Stop() - fs.ageChk = nil - } - } else { - fireIn := time.Duration(sm.ts-now) + fs.cfg.MaxAge - if fs.ageChk != nil { - fs.ageChk.Reset(fireIn) - } else { - fs.ageChk = time.AfterFunc(fireIn, fs.expireMsgs) + for _, mb := range fs.blks { + mb.mu.Lock() + fseq := atomic.LoadUint64(&mb.first.seq) + // Account for messages missing from the head. + if fseq > cur { + for seq := cur; seq < fseq; seq++ { + state.Deleted = append(state.Deleted, seq) } } - fs.mu.Unlock() - return + // Only advance cur if we are increasing. We could have marker blocks with just tombstones. + if last := atomic.LoadUint64(&mb.last.seq); last >= cur { + cur = last + 1 // Expected next first. + } + // Add in deleted. + mb.dmap.Range(func(seq uint64) bool { + state.Deleted = append(state.Deleted, seq) + return true + }) + mb.mu.Unlock() } } -} - -// Check all the checksums for a message block. -func checkMsgBlockFile(fp *os.File, hh hash.Hash) []uint64 { - var le = binary.LittleEndian - var hdr [msgHdrSize]byte - var bad []uint64 + fs.mu.RUnlock() - r := bufio.NewReaderSize(fp, 64*1024*1024) + state.Lost = fs.lostData() - for { - if _, err := io.ReadFull(r, hdr[0:]); err != nil { - break - } - rl := le.Uint32(hdr[0:]) - seq := le.Uint64(hdr[4:]) - slen := le.Uint16(hdr[20:]) - dlen := int(rl) - msgHdrSize - if dlen < 0 || int(slen) > dlen || dlen > int(rl) { - bad = append(bad, seq) - break - } - data := make([]byte, dlen) - if _, err := io.ReadFull(r, data); err != nil { - bad = append(bad, seq) - break - } - hh.Reset() - hh.Write(hdr[4:20]) - hh.Write(data[:slen]) - hh.Write(data[slen : dlen-8]) - checksum := hh.Sum(nil) - if !bytes.Equal(checksum, data[len(data)-8:]) { - bad = append(bad, seq) - } + // Can not be guaranteed to be sorted. + if len(state.Deleted) > 0 { + slices.Sort(state.Deleted) + state.NumDeleted = len(state.Deleted) } - return bad + return state } -// Lock should be held. -func (fs *fileStore) checkAndFlushAllBlocks() { +func (fs *fileStore) Utilization() (total, reported uint64, err error) { + fs.mu.RLock() + defer fs.mu.RUnlock() for _, mb := range fs.blks { - if mb.pendingWriteSize() > 0 { - mb.flushPendingMsgsAndWait() - } - mb.writeIndexInfo() + mb.mu.RLock() + reported += mb.bytes + total += mb.rbytes + mb.mu.RUnlock() } + return total, reported, nil } -// This will check all the checksums on messages and report back any sequence numbers with errors. -func (fs *fileStore) checkMsgs() []uint64 { - fs.mu.Lock() - defer fs.mu.Unlock() - - fs.checkAndFlushAllBlocks() - - mdir := path.Join(fs.fcfg.StoreDir, msgDir) - fis, err := ioutil.ReadDir(mdir) - if err != nil { - return nil +func fileStoreMsgSizeRaw(slen, hlen, mlen int) uint64 { + if hlen == 0 { + // length of the message record (4bytes) + seq(8) + ts(8) + subj_len(2) + subj + msg + hash(8) + return uint64(22 + slen + mlen + 8) } + // length of the message record (4bytes) + seq(8) + ts(8) + subj_len(2) + subj + hdr_len(4) + hdr + msg + hash(8) + return uint64(22 + slen + 4 + hlen + mlen + 8) +} - var bad []uint64 +func fileStoreMsgSize(subj string, hdr, msg []byte) uint64 { + return fileStoreMsgSizeRaw(len(subj), len(hdr), len(msg)) +} - // Check all of the msg blocks. - for _, fi := range fis { - var index uint64 - if n, err := fmt.Sscanf(fi.Name(), blkScan, &index); err == nil && n == 1 { - if fp, err := os.Open(path.Join(mdir, fi.Name())); err != nil { - continue - } else { - key := sha256.Sum256(fs.hashKeyForBlock(index)) - hh, _ := highwayhash.New64(key[:]) - bad = append(bad, checkMsgBlockFile(fp, hh)...) - fp.Close() - } - } - } - return bad +func fileStoreMsgSizeEstimate(slen, maxPayload int) uint64 { + return uint64(emptyRecordLen + slen + 4 + maxPayload) } -// Will write the message record to the underlying message block. -// filestore lock will be held. -func (mb *msgBlock) writeMsgRecord(rl, seq uint64, subj string, mhdr, msg []byte, ts int64) { - mb.mu.Lock() +// Determine time since any last activity, read/load, write or remove. +func (mb *msgBlock) sinceLastActivity() time.Duration { + if mb.closed { + return 0 + } + last := mb.lwts + if mb.lrts > last { + last = mb.lrts + } + if mb.llts > last { + last = mb.llts + } + if mb.lsts > last { + last = mb.lsts + } + return time.Since(time.Unix(0, last).UTC()) +} - // Make sure we have a cache setup. - if mb.cache == nil { - mb.cache = &cache{} - mb.startCacheExpireTimer() +// Determine time since last write or remove of a message. +// Read lock should be held. +func (mb *msgBlock) sinceLastWriteActivity() time.Duration { + if mb.closed { + return 0 } + last := mb.lwts + if mb.lrts > last { + last = mb.lrts + } + return time.Since(time.Unix(0, last).UTC()) +} - // Indexing - index := len(mb.cache.buf) - if mb.cache.off > 0 { - index += int(mb.cache.off) +func checkNewHeader(hdr []byte) error { + if len(hdr) < 2 || hdr[0] != magic || + (hdr[1] != version && hdr[1] != newVersion) { + return errCorruptState } + return nil +} - // Formats - // Format with no header - // total_len(4) sequence(8) timestamp(8) subj_len(2) subj msg hash(8) - // With headers, high bit on total length will be set. - // total_len(4) sequence(8) timestamp(8) subj_len(2) subj hdr_len(4) hdr msg hash(8) +// readIndexInfo will read in the index information for the message block. +func (mb *msgBlock) readIndexInfo() error { + ifn := filepath.Join(mb.fs.fcfg.StoreDir, msgDir, fmt.Sprintf(indexScan, mb.index)) + buf, err := os.ReadFile(ifn) + if err != nil { + return err + } - // First write header, etc. - var le = binary.LittleEndian - var hdr [msgHdrSize]byte + // Set if first time. + if mb.liwsz == 0 { + mb.liwsz = int64(len(buf)) + } - l := uint32(rl) - hasHeaders := len(mhdr) > 0 - if hasHeaders { - l |= hbit + // Decrypt if needed. + if mb.aek != nil { + buf, err = mb.aek.Open(buf[:0], mb.nonce, buf, nil) + if err != nil { + return err + } } - le.PutUint32(hdr[0:], l) - le.PutUint64(hdr[4:], seq) - le.PutUint64(hdr[12:], uint64(ts)) - le.PutUint16(hdr[20:], uint16(len(subj))) + if err := checkNewHeader(buf); err != nil { + defer os.Remove(ifn) + return fmt.Errorf("bad index file") + } - // Now write to underlying buffer. - mb.cache.buf = append(mb.cache.buf, hdr[:]...) - mb.cache.buf = append(mb.cache.buf, subj...) + bi := hdrLen - if hasHeaders { - var hlen [4]byte - le.PutUint32(hlen[0:], uint32(len(mhdr))) - mb.cache.buf = append(mb.cache.buf, hlen[:]...) - mb.cache.buf = append(mb.cache.buf, mhdr...) + // Helpers, will set i to -1 on error. + readSeq := func() uint64 { + if bi < 0 { + return 0 + } + seq, n := binary.Uvarint(buf[bi:]) + if n <= 0 { + bi = -1 + return 0 + } + bi += n + return seq &^ ebit } - mb.cache.buf = append(mb.cache.buf, msg...) - - // Calculate hash. - mb.hh.Reset() - mb.hh.Write(hdr[4:20]) - mb.hh.Write([]byte(subj)) - if hasHeaders { - mb.hh.Write(mhdr) + readCount := readSeq + readTimeStamp := func() int64 { + if bi < 0 { + return 0 + } + ts, n := binary.Varint(buf[bi:]) + if n <= 0 { + bi = -1 + return -1 + } + bi += n + return ts } - mb.hh.Write(msg) - checksum := mb.hh.Sum(nil) - // Grab last checksum - copy(mb.lchk[0:], checksum) + mb.msgs = readCount() + mb.bytes = readCount() + atomic.StoreUint64(&mb.first.seq, readSeq()) + mb.first.ts = readTimeStamp() + atomic.StoreUint64(&mb.last.seq, readSeq()) + mb.last.ts = readTimeStamp() + dmapLen := readCount() - // Update writethrough cache. - // Write to msg record. - mb.cache.buf = append(mb.cache.buf, checksum...) - // Write index - mb.cache.idx = append(mb.cache.idx, uint32(index)|hbit) - mb.cache.lrl = uint32(rl) - if mb.cache.fseq == 0 { - mb.cache.fseq = seq + // Check if this is a short write index file. + if bi < 0 || bi+checksumSize > len(buf) { + os.Remove(ifn) + return fmt.Errorf("short index file") } - // Set cache timestamp for last store. - mb.lwts = ts + // Check for consistency if accounting. If something is off bail and we will rebuild. + if mb.msgs != (atomic.LoadUint64(&mb.last.seq)-atomic.LoadUint64(&mb.first.seq)+1)-dmapLen { + os.Remove(ifn) + return fmt.Errorf("accounting inconsistent") + } - // Accounting - mb.updateAccounting(seq, ts, rl) + // Checksum + copy(mb.lchk[0:], buf[bi:bi+checksumSize]) + bi += checksumSize - fch := mb.fch - mb.mu.Unlock() + // Now check for presence of a delete map + if dmapLen > 0 { + // New version is encoded avl seqset. + if buf[1] == newVersion { + dmap, _, err := avl.Decode(buf[bi:]) + if err != nil { + return fmt.Errorf("could not decode avl dmap: %v", err) + } + mb.dmap = *dmap + } else { + // This is the old version. + for i, fseq := 0, atomic.LoadUint64(&mb.first.seq); i < int(dmapLen); i++ { + seq := readSeq() + if seq == 0 { + break + } + mb.dmap.Insert(seq + fseq) + } + } + } - // Flush the kicker here. - kickFlusher(fch) + return nil } -// How many bytes pending to be written for this message block. -func (mb *msgBlock) pendingWriteSize() int { - if mb == nil { - return 0 - } - var pending int - mb.mu.RLock() - if mb.mfd != nil && mb.cache != nil { - pending = len(mb.cache.buf) - int(mb.cache.wp) +// Will return total number of cache loads. +func (fs *fileStore) cacheLoads() uint64 { + var tl uint64 + fs.mu.RLock() + for _, mb := range fs.blks { + tl += mb.cloads } - mb.mu.RUnlock() - return pending + fs.mu.RUnlock() + return tl } -// Lock should be held. -func (mb *msgBlock) clearFlushing() { - if mb.cache != nil { - mb.cache.flush = false +// Will return total number of cached bytes. +func (fs *fileStore) cacheSize() uint64 { + var sz uint64 + fs.mu.RLock() + for _, mb := range fs.blks { + mb.mu.RLock() + if mb.cache != nil { + sz += uint64(len(mb.cache.buf)) + } + mb.mu.RUnlock() } + fs.mu.RUnlock() + return sz } -// Lock should be held. -func (mb *msgBlock) setFlushing() { - if mb.cache != nil { - mb.cache.flush = true +// Will return total number of dmapEntries for all msg blocks. +func (fs *fileStore) dmapEntries() int { + var total int + fs.mu.RLock() + for _, mb := range fs.blks { + total += mb.dmap.Size() } + fs.mu.RUnlock() + return total } -// bytesPending returns the buffer to be used for writing to the underlying file. -// This marks we are in flush and will return nil if asked again until cleared. -// Lock should be held. -func (mb *msgBlock) bytesPending() ([]byte, error) { - if mb == nil || mb.mfd == nil { - return nil, errNoPending - } - if mb.cache == nil { - return nil, errNoCache - } - if mb.cache.flush { - return nil, errFlushRunning - } - buf := mb.cache.buf[mb.cache.wp:] - if len(buf) == 0 { - return nil, errNoPending - } - return buf, nil +// Fixed helper for iterating. +func subjectsEqual(a, b string) bool { + return a == b } -// Return the number of bytes in this message block. -func (mb *msgBlock) numBytes() uint64 { - mb.mu.RLock() - nb := mb.bytes - mb.mu.RUnlock() - return nb +func subjectsAll(a, b string) bool { + return true } -// Update accounting on a write msg. -// Lock should be held. -func (mb *msgBlock) updateAccounting(seq uint64, ts int64, rl uint64) { - if mb.first.seq == 0 || mb.first.ts == 0 { - mb.first.seq = seq - mb.first.ts = ts +func compareFn(subject string) func(string, string) bool { + if subject == _EMPTY_ || subject == fwcs { + return subjectsAll } - // Need atomics here for selectMsgBlock speed. - atomic.StoreUint64(&mb.last.seq, seq) - mb.last.ts = ts - mb.bytes += rl - mb.msgs++ + if subjectHasWildcard(subject) { + return subjectIsSubsetMatch + } + return subjectsEqual } -// Lock should be held. -func (fs *fileStore) writeMsgRecord(seq uint64, subj string, mhdr, msg []byte) (uint64, int64, error) { - var err error +// PurgeEx will remove messages based on subject filters, sequence and number of messages to keep. +// Will return the number of purged messages. +func (fs *fileStore) PurgeEx(subject string, sequence, keep uint64) (purged uint64, err error) { + if subject == _EMPTY_ || subject == fwcs { + if keep == 0 && sequence == 0 { + return fs.purge(0) + } + if sequence > 1 { + return fs.compact(sequence) + } + } - // Get size for this message. - rl := fileStoreMsgSize(subj, mhdr, msg) - if rl&hbit != 0 { - return 0, 0, ErrMsgTooLarge + // Make sure to not leave subject if empty and we reach this spot. + if subject == _EMPTY_ { + subject = fwcs } - // Grab our current last message block. - mb := fs.lmb - if mb == nil || mb.numBytes()+rl > fs.fcfg.BlockSize { - if mb, err = fs.newMsgBlockForWrite(); err != nil { - return 0, 0, err + + eq, wc := compareFn(subject), subjectHasWildcard(subject) + var firstSeqNeedsUpdate bool + var bytes uint64 + + // If we have a "keep" designation need to get full filtered state so we know how many to purge. + var maxp uint64 + if keep > 0 { + ss := fs.FilteredState(1, subject) + if keep >= ss.Msgs { + return 0, nil } + maxp = ss.Msgs - keep } - // Grab time - ts := time.Now().UnixNano() + var smv StoreMsg + var tombs []msgId + var lowSeq uint64 - // Ask msg block to store in write through cache. - mb.writeMsgRecord(rl, seq, subj, mhdr, msg, ts) + fs.mu.Lock() + // We may remove blocks as we purge, so don't range directly on fs.blks + // otherwise we may jump over some (see https://github.com/nats-io/nats-server/issues/3528) + for i := 0; i < len(fs.blks); i++ { + mb := fs.blks[i] + mb.mu.Lock() - return rl, ts, nil -} + // If we do not have our fss, try to expire the cache if we have no items in this block. + shouldExpire := mb.fssNotLoaded() -// Sync msg and index files as needed. This is called from a timer. -func (fs *fileStore) syncBlocks() { - fs.mu.RLock() - if fs.closed { - fs.mu.RUnlock() - return - } - blks := append([]*msgBlock(nil), fs.blks...) - fs.mu.RUnlock() + t, f, l := mb.filteredPendingLocked(subject, wc, atomic.LoadUint64(&mb.first.seq)) + if t == 0 { + // Expire if we were responsible for loading. + if shouldExpire { + // Expire this cache before moving on. + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() + continue + } - for _, mb := range blks { - mb.mu.RLock() - mfd := mb.mfd - ifd := mb.ifd - liwsz := mb.liwsz - mb.mu.RUnlock() + if sequence > 1 && sequence <= l { + l = sequence - 1 + } + + if mb.cacheNotLoaded() { + mb.loadMsgsWithLock() + shouldExpire = true + } + + var nrg uint64 // Number of remaining messages globally after removal from psim. + + for seq, te := f, len(tombs); seq <= l; seq++ { + if sm, _ := mb.cacheLookupNoCopy(seq, &smv); sm != nil && eq(sm.subj, subject) { + rl := fileStoreMsgSize(sm.subj, sm.hdr, sm.msg) + // Do fast in place remove. + // Stats + if mb.msgs > 0 { + // Msgs + fs.state.Msgs-- + mb.msgs-- + // Bytes, make sure to not go negative. + if rl > fs.state.Bytes { + rl = fs.state.Bytes + } + if rl > mb.bytes { + rl = mb.bytes + } + fs.state.Bytes -= rl + mb.bytes -= rl + // Totals + purged++ + bytes += rl + } + // PSIM and FSS updates. + nr := mb.removeSeqPerSubject(sm.subj, seq) + nrg = fs.removePerSubject(sm.subj) + + // Track tombstones we need to write. + tombs = append(tombs, msgId{sm.seq, sm.ts}) + if sm.seq < lowSeq || lowSeq == 0 { + lowSeq = sm.seq + } + + // Check for first message. + if seq == atomic.LoadUint64(&mb.first.seq) { + mb.selectNextFirst() + if mb.isEmpty() { + // Since we are removing this block don't need to write tombstones. + tombs = tombs[:te] + fs.removeMsgBlock(mb) + i-- + // keep flag set, if set previously + firstSeqNeedsUpdate = firstSeqNeedsUpdate || seq == fs.state.FirstSeq + } else if seq == fs.state.FirstSeq { + fs.state.FirstSeq = atomic.LoadUint64(&mb.first.seq) // new one. + if mb.first.ts == 0 { + fs.state.FirstTime = time.Time{} + } else { + fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC() + } + } + } else { + // Out of order delete. + mb.dmap.Insert(seq) + } + // Break if we have emptied this block or if we set a maximum purge count. + if mb.isEmpty() || (maxp > 0 && purged >= maxp) { + break + } + // Also break if we know we have no more messages matching here. + // This is only applicable for non-wildcarded filters. + if !wc && nr == 0 { + break + } + } + } + // Expire if we were responsible for loading and we do not seem to be doing successive purgeEx calls. + // On successive calls - most likely from KV purge deletes, we want to keep the data loaded. + if shouldExpire && time.Since(fs.lpex) > time.Second { + // Expire this cache before moving on. + mb.tryForceExpireCacheLocked() + } + mb.mu.Unlock() - if mfd != nil { - mfd.Sync() + // Check if we should break out of top level too. + if maxp > 0 && purged >= maxp { + break } - if ifd != nil { - ifd.Sync() - ifd.Truncate(liwsz) + // Also check if not wildcarded and we have no remaining matches. + if !wc && nrg == 0 { + break } } + if firstSeqNeedsUpdate { + fs.selectNextFirst() + } - fs.mu.RLock() - cfs := append([]*consumerFileStore(nil), fs.cfs...) - fs.mu.RUnlock() + // Update the last purgeEx call time. + defer func() { fs.lpex = time.Now() }() - // Do consumers. - for _, o := range cfs { - o.syncStateFile() + // Write any tombstones as needed. + // When writing multiple tombstones we will flush at the end. + if len(tombs) > 0 { + for _, tomb := range tombs { + if err := fs.writeTombstoneNoFlush(tomb.seq, tomb.ts); err != nil { + return purged, err + } + } + // Flush any pending. If we change blocks the newMsgBlockForWrite() will flush any pending for us. + if lmb := fs.lmb; lmb != nil { + lmb.flushPendingMsgs() + } } - fs.mu.Lock() - fs.syncTmr = time.AfterFunc(fs.fcfg.SyncInterval, fs.syncBlocks) + fs.dirty++ + cb := fs.scb fs.mu.Unlock() -} -// Select the message block where this message should be found. -// Return nil if not in the set. -// Read lock should be held. -func (fs *fileStore) selectMsgBlock(seq uint64) *msgBlock { - // Check for out of range. - if seq < fs.state.FirstSeq || seq > fs.state.LastSeq { - return nil - } - // blks are sorted in ascending order. - // TODO(dlc) - Can be smarter here, when lots of blks maybe use binary search. - // For now this is cache friendly for small to medium numbers of blks. - for _, mb := range fs.blks { - if seq <= atomic.LoadUint64(&mb.last.seq) { - return mb + if cb != nil { + if purged == 1 { + cb(-int64(purged), -int64(bytes), lowSeq, subject) + } else { + // FIXME(dlc) - Since we track lowSeq we could send to upper layer if they dealt with the condition properly. + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) } } - return nil + + return purged, nil } -// Select the message block where this message should be found. -// Return nil if not in the set. -func (fs *fileStore) selectMsgBlockForStart(minTime time.Time) *msgBlock { - fs.mu.RLock() - defer fs.mu.RUnlock() +// Purge will remove all messages from this store. +// Will return the number of purged messages. +func (fs *fileStore) Purge() (uint64, error) { + return fs.purge(0) +} - t := minTime.UnixNano() - for _, mb := range fs.blks { - mb.mu.RLock() - found := t <= mb.last.ts - mb.mu.RUnlock() - if found { - return mb - } +func (fs *fileStore) purge(fseq uint64) (uint64, error) { + if fs.isClosed() { + return 0, ErrStoreClosed } - return nil -} -// Index a raw msg buffer. -// Lock should be held. -func (mb *msgBlock) indexCacheBuf(buf []byte) error { - var le = binary.LittleEndian + fs.mu.Lock() - var fseq uint64 - var idx []uint32 - var index uint32 + purged := fs.state.Msgs + rbytes := int64(fs.state.Bytes) - if mb.cache == nil { - // Approximation, may adjust below. - fseq = mb.first.seq - idx = make([]uint32, 0, mb.msgs) - mb.cache = &cache{} - } else { - fseq = mb.cache.fseq - idx = mb.cache.idx - if len(idx) == 0 { - idx = make([]uint32, 0, mb.msgs) - } - index = uint32(len(mb.cache.buf)) - buf = append(mb.cache.buf, buf...) + fs.state.FirstSeq = fs.state.LastSeq + 1 + fs.state.FirstTime = time.Time{} + + fs.state.Bytes = 0 + fs.state.Msgs = 0 + + for _, mb := range fs.blks { + mb.dirtyClose() } - lbuf := uint32(len(buf)) + fs.blks = nil + fs.lmb = nil + fs.bim = make(map[uint32]*msgBlock) + // Clear any per subject tracking. + fs.psim, fs.tsl = fs.psim.Empty(), 0 + fs.sdm.empty() + // Mark dirty. + fs.dirty++ - for index < lbuf { - hdr := buf[index : index+msgHdrSize] - rl := le.Uint32(hdr[0:]) - seq := le.Uint64(hdr[4:]) - slen := le.Uint16(hdr[20:]) + // Move the msgs directory out of the way, will delete out of band. + // FIXME(dlc) - These can error and we need to change api above to propagate? + mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) + pdir := filepath.Join(fs.fcfg.StoreDir, purgeDir) + // If purge directory still exists then we need to wait + // in place and remove since rename would fail. + if _, err := os.Stat(pdir); err == nil { + <-dios + os.RemoveAll(pdir) + dios <- struct{}{} + } - // Clear any headers bit that could be set. - rl &^= hbit + <-dios + os.Rename(mdir, pdir) + dios <- struct{}{} - dlen := int(rl) - msgHdrSize + go func() { + <-dios + os.RemoveAll(pdir) + dios <- struct{}{} + }() - // Do some quick sanity checks here. - if dlen < 0 || int(slen) > dlen || dlen > int(rl) { - // This means something is off. - // TODO(dlc) - Add into bad list? - return errBadMsg - } - // Adjust if we guessed wrong. - if seq != 0 && seq < fseq { - fseq = seq - } - // We defer checksum checks to individual msg cache lookups to amortorize costs and - // not introduce latency for first message from a newly loaded block. - idx = append(idx, index) - mb.cache.lrl = uint32(rl) - index += mb.cache.lrl - } - mb.cache.buf = buf - mb.cache.idx = idx - mb.cache.fseq = fseq - mb.cache.wp += int(lbuf) + // Create new one. + <-dios + os.MkdirAll(mdir, defaultDirPerms) + dios <- struct{}{} - return nil -} + // Make sure we have a lmb to write to. + if _, err := fs.newMsgBlockForWrite(); err != nil { + fs.mu.Unlock() + return purged, err + } -func (mb *msgBlock) quitChan() chan struct{} { - mb.mu.RLock() - defer mb.mu.RUnlock() - return mb.qch -} + // Check if we need to set the first seq to a new number. + if fseq > fs.state.FirstSeq { + fs.state.FirstSeq = fseq + fs.state.LastSeq = fseq - 1 + } -// When called directly, flushPending could be busy already and return errFlushRunning. -// This function is called for in place flushing so we need to wait. -func (mb *msgBlock) flushPendingMsgsAndWait() error { - var err error + lmb := fs.lmb + atomic.StoreUint64(&lmb.first.seq, fs.state.FirstSeq) + atomic.StoreUint64(&lmb.last.seq, fs.state.LastSeq) + lmb.last.ts = fs.state.LastTime.UnixNano() - // If we are in flush wait for that to clear. - for err = mb.flushPendingMsgs(); err == errFlushRunning; err = mb.flushPendingMsgs() { - qch := mb.quitChan() - select { - case <-qch: - return nil - case <-time.After(time.Millisecond): - } + if lseq := atomic.LoadUint64(&lmb.last.seq); lseq > 0 { + // Leave a tombstone so we can remember our starting sequence in case + // full state becomes corrupted. + fs.writeTombstone(lseq, lmb.last.ts) } - return err -} -// flushPendingMsgs writes out any messages for this message block. -func (mb *msgBlock) flushPendingMsgs() error { - // We will not hold the lock across I/O so we can add more messages - // in parallel but we allow only one flush to be running. - mb.mu.Lock() - if mb.cache == nil || mb.mfd == nil { - mb.mu.Unlock() - return nil + cb := fs.scb + fs.mu.Unlock() + + // Force a new index.db to be written. + if purged > 0 { + fs.forceWriteFullState() } - // bytesPending will return with errFlushRunning - // if we are already flushing this message block. - buf, err := mb.bytesPending() - // If we got an error back return here. - if err != nil { - mb.mu.Unlock() - return err + if cb != nil { + cb(-int64(purged), -rbytes, 0, _EMPTY_) } - woff := int64(mb.cache.off + mb.cache.wp) - lob := len(buf) + return purged, nil +} - // Only one can be flushing at a time. - mb.setFlushing() - mfd := mb.mfd - mb.mu.Unlock() +// Compact will remove all messages from this store up to +// but not including the seq parameter. +// Will return the number of purged messages. +func (fs *fileStore) Compact(seq uint64) (uint64, error) { + return fs.compact(seq) +} - var tn int +func (fs *fileStore) compact(seq uint64) (uint64, error) { + if seq == 0 { + return fs.purge(seq) + } - // Append new data to the message block file. - for lbb := lob; lbb > 0; lbb = len(buf) { - n, err := mfd.WriteAt(buf, woff) - if err != nil { - // FIXME(dlc) - What is the correct behavior here? - mb.removeIndexFile() - mb.mu.Lock() - mb.clearFlushing() - mb.mu.Unlock() - return err - } - woff += int64(n) - tn += n + var purged, bytes uint64 + + fs.mu.Lock() + // Same as purge all. + if lseq := fs.state.LastSeq; seq > lseq { + fs.mu.Unlock() + return fs.purge(seq) + } + // Short-circuit if the store was already compacted past this point. + if fs.state.FirstSeq > seq { + fs.mu.Unlock() + return purged, nil + } + // We have to delete interior messages. + smb := fs.selectMsgBlock(seq) + if smb == nil { + fs.mu.Unlock() + return 0, nil + } - // Success - if n == lbb { + // All msgblocks up to this one can be thrown away. + var deleted int + for _, mb := range fs.blks { + if mb == smb { break } - // Partial write.. - buf = buf[n:] + mb.mu.Lock() + purged += mb.msgs + bytes += mb.bytes + // Make sure we do subject cleanup as well. + mb.ensurePerSubjectInfoLoaded() + mb.fss.IterOrdered(func(bsubj []byte, ss *SimpleState) bool { + subj := bytesToString(bsubj) + for i := uint64(0); i < ss.Msgs; i++ { + fs.removePerSubject(subj) + } + return true + }) + // Now close. + mb.dirtyCloseWithRemove(true) + mb.mu.Unlock() + deleted++ } - // We did a successful write. - // Re-acquire lock to update. - mb.mu.Lock() - defer mb.mu.Unlock() - // Clear on exit. - defer mb.clearFlushing() + var smv StoreMsg + var err error + var tombs []msgId - // Cache may be gone. - if mb.cache == nil || mb.mfd == nil { - return nil + smb.mu.Lock() + if atomic.LoadUint64(&smb.first.seq) == seq { + fs.state.FirstSeq = atomic.LoadUint64(&smb.first.seq) + fs.state.FirstTime = time.Unix(0, smb.first.ts).UTC() + goto SKIP } - // Check for additional writes while we were writing to the disk. - moreBytes := len(mb.cache.buf) - mb.cache.wp - lob - - // Decide what we want to do with the buffer in hand. If we have load interest - // we will hold onto the whole thing, otherwise empty the buffer, possibly reusing it. - if ts := time.Now().UnixNano(); ts < mb.llts || (ts-mb.llts) <= int64(mb.cexp) { - mb.cache.wp += tn - } else { - if cap(buf) <= maxBufReuse { - buf = buf[:0] - } else { - buf = nil + // Make sure we have the messages loaded. + if smb.cacheNotLoaded() { + if err = smb.loadMsgsWithLock(); err != nil { + goto SKIP } - if moreBytes > 0 { - nbuf := mb.cache.buf[len(mb.cache.buf)-moreBytes:] - if moreBytes > (len(mb.cache.buf)/4*3) && cap(nbuf) <= maxBufReuse { - buf = nbuf - } else { - buf = append(buf, nbuf...) + } + for mseq := atomic.LoadUint64(&smb.first.seq); mseq < seq; mseq++ { + sm, err := smb.cacheLookupNoCopy(mseq, &smv) + if err == errDeletedMsg { + // Update dmap. + if !smb.dmap.IsEmpty() { + smb.dmap.Delete(mseq) + } + } else if sm != nil { + sz := fileStoreMsgSize(sm.subj, sm.hdr, sm.msg) + if smb.msgs > 0 { + smb.msgs-- + if sz > smb.bytes { + sz = smb.bytes + } + smb.bytes -= sz + bytes += sz + purged++ } + // Update fss + smb.removeSeqPerSubject(sm.subj, mseq) + fs.removePerSubject(sm.subj) + tombs = append(tombs, msgId{sm.seq, sm.ts}) } - // Update our cache offset. - mb.cache.off = int(woff) - // Reset write pointer. - mb.cache.wp = 0 - // Place buffer back in the cache structure. - mb.cache.buf = buf } - return nil -} + // Check if empty after processing, could happen if tail of messages are all deleted. + if isEmpty := smb.msgs == 0; isEmpty { + // Only remove if not the last block. + if smb != fs.lmb { + smb.dirtyCloseWithRemove(true) + deleted++ + } else { + // Make sure to sync changes. + smb.needSync = true + } + // Update fs first here as well. + fs.state.FirstSeq = atomic.LoadUint64(&smb.last.seq) + 1 + fs.state.FirstTime = time.Time{} -// Lock should be held. -func (mb *msgBlock) clearLoading() { - mb.loading = false -} + } else { + // Make sure to sync changes. + smb.needSync = true + // Just for start condition for selectNextFirst. + if smb.first.seq < seq { + atomic.StoreUint64(&smb.first.seq, seq-1) + } else { + // selectNextFirst always adds 1, so need to subtract 1 here. + atomic.StoreUint64(&smb.first.seq, smb.first.seq-1) + } + smb.selectNextFirst() + + fs.state.FirstSeq = atomic.LoadUint64(&smb.first.seq) + fs.state.FirstTime = time.Unix(0, smb.first.ts).UTC() + + // Check if we should reclaim the head space from this block. + // This will be optimistic only, so don't continue if we encounter any errors here. + if smb.rbytes > compactMinimum && smb.bytes*2 < smb.rbytes { + var moff uint32 + moff, _, _, err = smb.slotInfo(int(atomic.LoadUint64(&smb.first.seq) - smb.cache.fseq)) + if err != nil || moff >= uint32(len(smb.cache.buf)) { + goto SKIP + } + buf := smb.cache.buf[moff:] + // Don't reuse, copy to new recycled buf. + nbuf := getMsgBlockBuf(len(buf)) + nbuf = append(nbuf, buf...) + smb.closeFDsLockedNoCheck() + // Check for encryption. + if smb.bek != nil && len(nbuf) > 0 { + // Recreate to reset counter. + bek, err := genBlockEncryptionKey(smb.fs.fcfg.Cipher, smb.seed, smb.nonce) + if err != nil { + goto SKIP + } + // For future writes make sure to set smb.bek to keep counter correct. + smb.bek = bek + smb.bek.XORKeyStream(nbuf, nbuf) + } + // Recompress if necessary (smb.cmp contains the algorithm used when + // the block was loaded from disk, or defaults to NoCompression if not) + if nbuf, err = smb.cmp.Compress(nbuf); err != nil { + goto SKIP + } -// Will load msgs from disk. -func (mb *msgBlock) loadMsgs() error { - // We hold the lock here the whole time by design. - mb.mu.Lock() - defer mb.mu.Unlock() + // We will write to a new file and mv/rename it in case of failure. + mfn := filepath.Join(smb.fs.fcfg.StoreDir, msgDir, fmt.Sprintf(newScan, smb.index)) + <-dios + err := os.WriteFile(mfn, nbuf, defaultFilePerms) + dios <- struct{}{} + if err != nil { + os.Remove(mfn) + goto SKIP + } + if err := os.Rename(mfn, smb.mfn); err != nil { + os.Remove(mfn) + goto SKIP + } - // Check to see if we are loading already. - if mb.loading { - return nil + // Make sure to remove fss state. + smb.fss = nil + smb.clearCacheAndOffset() + smb.rbytes = uint64(len(nbuf)) + // Make sure we don't write any additional tombstones. + tombs = nil + } } - // Set loading status. - mb.loading = true - defer mb.clearLoading() +SKIP: + smb.mu.Unlock() -checkCache: - // Check to see if we have a full cache. - if mb.cache != nil && len(mb.cache.idx) == int(mb.msgs) && mb.cache.off == 0 && len(mb.cache.buf) > 0 { - return nil + // Write any tombstones as needed. + // When writing multiple tombstones we will flush at the end. + if len(tombs) > 0 { + for _, tomb := range tombs { + if err := fs.writeTombstoneNoFlush(tomb.seq, tomb.ts); err != nil { + return purged, err + } + } + // Flush any pending. If we change blocks the newMsgBlockForWrite() will flush any pending for us. + if lmb := fs.lmb; lmb != nil { + lmb.flushPendingMsgs() + } } - mfn := mb.mfn - mb.llts = time.Now().UnixNano() + if deleted > 0 { + // Update block map. + if fs.bim != nil { + for _, mb := range fs.blks[:deleted] { + delete(fs.bim, mb.index) + } + } + // Update blks slice. + fs.blks = copyMsgBlocks(fs.blks[deleted:]) + if lb := len(fs.blks); lb == 0 { + fs.lmb = nil + } else { + fs.lmb = fs.blks[lb-1] + } + } - // FIXME(dlc) - We could be smarter here. - if mb.cache != nil && len(mb.cache.buf)-mb.cache.wp > 0 { - mb.mu.Unlock() - mb.flushPendingMsgsAndWait() - mb.writeIndexInfo() - mb.mu.Lock() - goto checkCache + // Update top level accounting. + if purged > fs.state.Msgs { + purged = fs.state.Msgs + } + fs.state.Msgs -= purged + if fs.state.Msgs == 0 { + fs.state.FirstSeq = fs.state.LastSeq + 1 + fs.state.FirstTime = time.Time{} } - // Load in the whole block. We want to hold the mb lock here to avoid any changes to - // state. - buf, err := ioutil.ReadFile(mfn) - if err != nil { - return err + if bytes > fs.state.Bytes { + bytes = fs.state.Bytes } + fs.state.Bytes -= bytes - // Reset the cache since we just read everything in. - // Make sure this is cleared in case we had a partial when we started. - mb.clearCacheAndOffset() + // Any existing state file no longer applicable. We will force write a new one + // after we release the lock. + os.Remove(filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile)) + fs.dirty++ + cb := fs.scb + fs.mu.Unlock() - if err := mb.indexCacheBuf(buf); err != nil { - return err + // Force a new index.db to be written. + if purged > 0 { + fs.forceWriteFullState() } - if len(buf) > 0 { - mb.cloads++ - mb.startCacheExpireTimer() + if cb != nil && purged > 0 { + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) } - return nil + return purged, err } -// Fetch a message from this block, possibly reading in and caching the messages. -// We assume the block was selected and is correct, so we do not do range checks. -func (mb *msgBlock) fetchMsg(seq uint64) (*fileStoredMsg, error) { - var sm *fileStoredMsg +// Will completely reset our store. +func (fs *fileStore) reset() error { + if fs.isClosed() { + return ErrStoreClosed + } + + fs.mu.Lock() - sm, err := mb.cacheLookup(seq) - if err == nil || (err != errNoCache && err != errPartialCache) { - return sm, err + var purged, bytes uint64 + cb := fs.scb + + for _, mb := range fs.blks { + mb.mu.Lock() + purged += mb.msgs + bytes += mb.bytes + mb.dirtyCloseWithRemove(true) + mb.mu.Unlock() } - // We have a cache miss here. - if err := mb.loadMsgs(); err != nil { - return nil, err + // Reset + fs.state.FirstSeq = 0 + fs.state.FirstTime = time.Time{} + fs.state.LastSeq = 0 + fs.state.LastTime = time.Now().UTC() + // Update msgs and bytes. + fs.state.Msgs = 0 + fs.state.Bytes = 0 + + // Reset blocks. + fs.blks, fs.lmb = nil, nil + + // Reset subject mappings. + fs.psim, fs.tsl = fs.psim.Empty(), 0 + fs.sdm.empty() + fs.bim = make(map[uint32]*msgBlock) + + // If we purged anything, make sure we kick flush state loop. + if purged > 0 { + fs.dirty++ } - return mb.cacheLookup(seq) -} -var ( - errNoCache = errors.New("no message cache") - errBadMsg = errors.New("malformed or corrupt message") - errDeletedMsg = errors.New("deleted message") - errPartialCache = errors.New("partial cache") - errNoPending = errors.New("message block does not have pending data") - errNotReadable = errors.New("storage directory not readable") - errFlushRunning = errors.New("flush is already running") - errCorruptState = errors.New("corrupt state file") -) + fs.mu.Unlock() -// Used for marking messages that have had their checksums checked. -// Used to signal a message record with headers. -const hbit = 1 << 31 + if cb != nil { + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) + } -// Used for marking erased messages sequences. -const ebit = 1 << 63 + return nil +} -// Will do a lookup from the cache. -func (mb *msgBlock) cacheLookup(seq uint64) (*fileStoredMsg, error) { - // Currently grab the write lock for optional use of mb.hh. Prefer this for now - // vs read lock and promote. Also defer based on 1.14 performance. +// Return all active tombstones in this msgBlock. +func (mb *msgBlock) tombs() []msgId { mb.mu.Lock() defer mb.mu.Unlock() - return mb.cacheLookupWithLock(seq) + return mb.tombsLocked() } -// Will do a lookup from cache assuming lock is held. -func (mb *msgBlock) cacheLookupWithLock(seq uint64) (*fileStoredMsg, error) { - if mb.cache == nil || len(mb.cache.idx) == 0 { - return nil, errNoCache +// Return all active tombstones in this msgBlock. +// Write lock should be held. +func (mb *msgBlock) tombsLocked() []msgId { + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return nil + } } - if seq < mb.first.seq || seq < mb.cache.fseq || seq > mb.last.seq { - return nil, ErrStoreMsgNotFound - } + var tombs []msgId + var le = binary.LittleEndian + buf := mb.cache.buf - // If we have a delete map check it. - if mb.dmap != nil { - if _, ok := mb.dmap[seq]; ok { - return nil, errDeletedMsg + for index, lbuf := uint32(0), uint32(len(buf)); index < lbuf; { + if index+msgHdrSize > lbuf { + return tombs + } + hdr := buf[index : index+msgHdrSize] + rl, seq := le.Uint32(hdr[0:]), le.Uint64(hdr[4:]) + // Clear any headers bit that could be set. + rl &^= hbit + // Check for tombstones. + if seq&tbit != 0 { + ts := int64(le.Uint64(hdr[12:])) + tombs = append(tombs, msgId{seq &^ tbit, ts}) } + // Advance to next record. + index += rl } - if mb.cache.off > 0 { - return nil, errPartialCache + return tombs +} + +// Truncate will truncate a stream store up to seq. Sequence needs to be valid. +func (fs *fileStore) Truncate(seq uint64) error { + if fs.isClosed() { + return ErrStoreClosed } - bi, _, hashChecked, err := mb.slotInfo(int(seq - mb.cache.fseq)) - if err != nil { - return nil, errPartialCache + // Check for request to reset. + if seq == 0 { + return fs.reset() } - // Update cache activity. - mb.llts = time.Now().UnixNano() + fs.mu.Lock() - // We use the high bit to denote we have already checked the checksum. - var hh hash.Hash64 - if !hashChecked { - hh = mb.hh // This will force the hash check in msgFromBuf. - mb.cache.idx[seq-mb.cache.fseq] = (bi | hbit) + // Any existing state file will no longer be applicable. We will force write a new one + // at the end, after we release the lock. + os.Remove(filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile)) + + var lsm *StoreMsg + smb := fs.selectMsgBlock(seq) + if smb != nil { + lsm, _, _ = smb.fetchMsgNoCopy(seq, nil) } - li := int(bi) - mb.cache.off - buf := mb.cache.buf[li:] + // Reset last so new block doesn't contain truncated sequences/timestamps. + var lastTime int64 + if lsm != nil { + lastTime = lsm.ts + } else if smb != nil { + lastTime = smb.last.ts + } else { + lastTime = fs.state.LastTime.UnixNano() + } + fs.state.LastSeq = seq + fs.state.LastTime = time.Unix(0, lastTime).UTC() - // Parse from the raw buffer. - subj, hdr, msg, mseq, ts, err := msgFromBuf(buf, hh) + // Always create a new write block for any tombstones. + // We'll truncate the selected message block as the last step, so can't write tombstones to it. + // If we end up not needing to write tombstones, this block will be cleaned up at the end. + tmb, err := fs.newMsgBlockForWrite() if err != nil { - return nil, err - } - if seq != mseq { - return nil, fmt.Errorf("sequence numbers for cache load did not match, %d vs %d", seq, mseq) - } - sm := &fileStoredMsg{ - subj: subj, - hdr: hdr, - msg: msg, - seq: seq, - ts: ts, - mb: mb, - off: int64(bi), + return err } - return sm, nil -} -// Will return message for the given sequence number. -func (fs *fileStore) msgForSeq(seq uint64) (*fileStoredMsg, error) { - // TODO(dlc) - Since Store, Remove, Skip all hold the write lock on fs this will - // be stalled. Need another lock if want to happen in parallel. - fs.mu.RLock() - if fs.closed { - fs.mu.RUnlock() - return nil, ErrStoreClosed + // The selected message block needs to be removed if it needs to be fully truncated. + var removeSmb bool + if smb != nil { + removeSmb = atomic.LoadUint64(&smb.first.seq) > seq } - // Indicates we want first msg. - if seq == 0 { - seq = fs.state.FirstSeq + + // If the selected block is not found or the message was deleted, we'll need to write a tombstone + // at the truncated sequence so we don't roll backward on our last sequence and timestamp. + if lsm == nil || removeSmb { + fs.writeTombstone(seq, lastTime) } - // Make sure to snapshot here. - lseq := fs.state.LastSeq - mb := fs.selectMsgBlock(seq) - fs.mu.RUnlock() - if mb == nil { - var err = ErrStoreEOF - if seq <= lseq { - err = ErrStoreMsgNotFound + var purged, bytes uint64 + + // Remove any left over msg blocks. + getLastMsgBlock := func() *msgBlock { + // Start at one before last, tmb will be the last most of the time + // unless a new block gets added for tombstones. + for i := len(fs.blks) - 2; i >= 0; i-- { + if mb := fs.blks[i]; mb.index < tmb.index { + return mb + } } - return nil, err + return nil } - // TODO(dlc) - older design had a check to prefetch when we knew we were - // loading in order and getting close to end of current mb. Should add - // something like it back in. - return mb.fetchMsg(seq) -} + for mb := getLastMsgBlock(); mb != nil && mb != smb; mb = getLastMsgBlock() { + mb.mu.Lock() + purged += mb.msgs + bytes += mb.bytes -// Internal function to return msg parts from a raw buffer. -func msgFromBuf(buf []byte, hh hash.Hash64) (string, []byte, []byte, uint64, int64, error) { - if len(buf) < msgHdrSize { - return _EMPTY_, nil, nil, 0, 0, errBadMsg + // We could have tombstones for messages before the truncated sequence. + // Need to store those for blocks we're about to remove. + if tombs := mb.tombsLocked(); len(tombs) > 0 { + // Temporarily unlock while we write tombstones. + mb.mu.Unlock() + for _, tomb := range tombs { + if tomb.seq < seq { + fs.writeTombstone(tomb.seq, tomb.ts) + } + } + mb.mu.Lock() + } + fs.forceRemoveMsgBlock(mb) + mb.mu.Unlock() } - var le = binary.LittleEndian - hdr := buf[:msgHdrSize] - rl := le.Uint32(hdr[0:]) - hasHeaders := rl&hbit != 0 - rl &^= hbit // clear header bit - dlen := int(rl) - msgHdrSize - slen := int(le.Uint16(hdr[20:])) - // Simple sanity check. - if dlen < 0 || slen > dlen || int(rl) > len(buf) { - return _EMPTY_, nil, nil, 0, 0, errBadMsg - } - data := buf[msgHdrSize : msgHdrSize+dlen] - // Do checksum tests here if requested. - if hh != nil { - hh.Reset() - hh.Write(hdr[4:20]) - hh.Write(data[:slen]) - if hasHeaders { - hh.Write(data[slen+4 : dlen-8]) - } else { - hh.Write(data[slen : dlen-8]) + hasWrittenTombstones := len(tmb.tombs()) > 0 + if smb != nil { + smb.mu.Lock() + if removeSmb { + purged += smb.msgs + bytes += smb.bytes + + // We could have tombstones for messages before the truncated sequence. + if tombs := smb.tombsLocked(); len(tombs) > 0 { + // Temporarily unlock while we write tombstones. + smb.mu.Unlock() + for _, tomb := range tombs { + if tomb.seq < seq { + fs.writeTombstone(tomb.seq, tomb.ts) + } + } + smb.mu.Lock() + } + fs.forceRemoveMsgBlock(smb) + smb.mu.Unlock() + goto SKIP + } + + // Make sure writeable. + if err := smb.enableForWriting(fs.fip); err != nil { + smb.mu.Unlock() + fs.mu.Unlock() + return err + } + + // Truncate our selected message block. + nmsgs, nbytes, err := smb.truncate(seq, lastTime) + if err != nil { + smb.mu.Unlock() + fs.mu.Unlock() + return fmt.Errorf("smb.truncate: %w", err) } - if !bytes.Equal(hh.Sum(nil), data[len(data)-8:]) { - return _EMPTY_, nil, nil, 0, 0, errBadMsg + // Account for the truncated msgs and bytes. + purged += nmsgs + bytes += nbytes + + // The selected message block is not the last anymore, need to close down resources. + if hasWrittenTombstones { + // Quit our loops. + if smb.qch != nil { + close(smb.qch) + smb.qch = nil + } + smb.closeFDsLockedNoCheck() + smb.recompressOnDiskIfNeeded() } + smb.mu.Unlock() } - seq := le.Uint64(hdr[4:]) - if seq&ebit != 0 { - seq = 0 + +SKIP: + // If no tombstones were written, we can remove the block and + // purely rely on the selected block as the last block. + if !hasWrittenTombstones { + fs.lmb = smb + tmb.mu.Lock() + fs.forceRemoveMsgBlock(tmb) + tmb.mu.Unlock() } - ts := int64(le.Uint64(hdr[12:])) - // FIXME(dlc) - We need to not allow appends to the underlying buffer, so we will - // fix the capacity. This will cause a copy though in stream:internalSendLoop when - // we append CRLF but this was causing a race. Need to rethink more to avoid this copy. - end := dlen - 8 - var mhdr, msg []byte - if hasHeaders { - hl := le.Uint32(data[slen:]) - bi := slen + 4 - li := bi + int(hl) - mhdr = data[bi:li:li] - msg = data[li:end:end] - } else { - msg = data[slen:end:end] + + // Reset last. + fs.state.LastSeq = seq + fs.state.LastTime = time.Unix(0, lastTime).UTC() + // Update msgs and bytes. + if purged > fs.state.Msgs { + purged = fs.state.Msgs } - return string(data[:slen]), mhdr, msg, seq, ts, nil -} + fs.state.Msgs -= purged + if bytes > fs.state.Bytes { + bytes = fs.state.Bytes + } + fs.state.Bytes -= bytes -// LoadMsg will lookup the message by sequence number and return it if found. -func (fs *fileStore) LoadMsg(seq uint64) (string, []byte, []byte, int64, error) { - sm, err := fs.msgForSeq(seq) - if sm != nil { - return sm.subj, sm.hdr, sm.msg, sm.ts, nil + // Reset our subject lookup info. + fs.resetGlobalPerSubjectInfo() + + fs.dirty++ + + cb := fs.scb + fs.mu.Unlock() + + // Force a new index.db to be written. + if purged > 0 { + fs.forceWriteFullState() + } + + if cb != nil { + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) } - return "", nil, nil, 0, err + + return nil } -// State returns the current state of the stream. -func (fs *fileStore) State() StreamState { +func (fs *fileStore) lastSeq() uint64 { fs.mu.RLock() - state := fs.state - state.Consumers = len(fs.cfs) + seq := fs.state.LastSeq fs.mu.RUnlock() - return state + return seq } -const emptyRecordLen = 22 + 8 +// Returns number of msg blks. +func (fs *fileStore) numMsgBlocks() int { + fs.mu.RLock() + defer fs.mu.RUnlock() + return len(fs.blks) +} -func fileStoreMsgSize(subj string, hdr, msg []byte) uint64 { - if len(hdr) == 0 { - // length of the message record (4bytes) + seq(8) + ts(8) + subj_len(2) + subj + msg + hash(8) - return uint64(22 + len(subj) + len(msg) + 8) +// Will add a new msgBlock. +// Lock should be held. +func (fs *fileStore) addMsgBlock(mb *msgBlock) { + fs.blks = append(fs.blks, mb) + fs.lmb = mb + fs.bim[mb.index] = mb +} + +// Remove from our list of blks. +// Both locks should be held. +func (fs *fileStore) removeMsgBlockFromList(mb *msgBlock) { + // Remove from list. + for i, omb := range fs.blks { + if mb == omb { + fs.dirty++ + blks := append(fs.blks[:i], fs.blks[i+1:]...) + fs.blks = copyMsgBlocks(blks) + if fs.bim != nil { + delete(fs.bim, mb.index) + } + break + } } - // length of the message record (4bytes) + seq(8) + ts(8) + subj_len(2) + subj + hdr_len(4) + hdr + msg + hash(8) - return uint64(22 + len(subj) + 4 + len(hdr) + len(msg) + 8) } -func fileStoreMsgSizeEstimate(slen, maxPayload int) uint64 { - return uint64(emptyRecordLen + slen + 4 + maxPayload) +// Removes the msgBlock +// Both locks should be held. +func (fs *fileStore) removeMsgBlock(mb *msgBlock) { + // Check for us being last message block + lseq, lts := atomic.LoadUint64(&mb.last.seq), mb.last.ts + if mb == fs.lmb { + // Creating a new message write block requires that the lmb lock is not held. + mb.mu.Unlock() + // Write the tombstone to remember since this was last block. + if lmb, _ := fs.newMsgBlockForWrite(); lmb != nil { + fs.writeTombstone(lseq, lts) + } + mb.mu.Lock() + } else if lseq == fs.state.LastSeq { + // Need to write a tombstone for the last sequence if we're removing the block containing it. + fs.writeTombstone(lseq, lts) + } + // Only delete message block after (potentially) writing a tombstone. + fs.forceRemoveMsgBlock(mb) +} + +// Removes the msgBlock, without writing tombstones to ensure the last sequence is preserved. +// Both locks should be held. +func (fs *fileStore) forceRemoveMsgBlock(mb *msgBlock) { + mb.dirtyCloseWithRemove(true) + fs.removeMsgBlockFromList(mb) } -// Write index info to the appropriate file. -func (mb *msgBlock) writeIndexInfo() error { - // HEADER: magic version msgs bytes fseq fts lseq lts checksum - var hdr [indexHdrSize]byte +// Purges and removes the msgBlock from the store. +// Lock should be held. +func (fs *fileStore) purgeMsgBlock(mb *msgBlock) { + mb.mu.Lock() + // Adjust per-subject tracking if present. + if err := mb.ensurePerSubjectInfoLoaded(); err == nil && mb.fss != nil { + mb.fss.IterFast(func(bsubj []byte, ss *SimpleState) bool { + subj := bytesToString(bsubj) + for range ss.Msgs { + fs.removePerSubject(subj) + } + return true + }) + } + // Update top level accounting. + msgs, bytes := mb.msgs, mb.bytes + if msgs > fs.state.Msgs { + msgs = fs.state.Msgs + } + if bytes > fs.state.Bytes { + bytes = fs.state.Bytes + } + fs.state.Msgs -= msgs + fs.state.Bytes -= bytes + fs.removeMsgBlock(mb) + mb.tryForceExpireCacheLocked() + mb.mu.Unlock() + fs.selectNextFirst() - // Write header - hdr[0] = magic - hdr[1] = version + if cb := fs.scb; cb != nil { + // If we have a callback registered, we need to release lock regardless since consumers will recalculate pending. + fs.mu.Unlock() + // Storage updates. + cb(-int64(msgs), -int64(bytes), 0, _EMPTY_) + fs.mu.Lock() + } +} +// Called by purge to simply get rid of the cache and close our fds. +// Lock should not be held. +func (mb *msgBlock) dirtyClose() { mb.mu.Lock() defer mb.mu.Unlock() + mb.dirtyCloseWithRemove(false) +} - n := hdrLen - n += binary.PutUvarint(hdr[n:], mb.msgs) - n += binary.PutUvarint(hdr[n:], mb.bytes) - n += binary.PutUvarint(hdr[n:], mb.first.seq) - n += binary.PutVarint(hdr[n:], mb.first.ts) - n += binary.PutUvarint(hdr[n:], mb.last.seq) - n += binary.PutVarint(hdr[n:], mb.last.ts) - n += binary.PutUvarint(hdr[n:], uint64(len(mb.dmap))) - buf := append(hdr[:n], mb.lchk[:]...) - - // Append a delete map if needed - if len(mb.dmap) > 0 { - buf = append(buf, mb.genDeleteMap()...) +// Should be called with lock held. +func (mb *msgBlock) dirtyCloseWithRemove(remove bool) error { + if mb == nil { + return nil } - var err error - if mb.ifd == nil { - ifd, err := os.OpenFile(mb.ifn, os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - return err - } - mb.ifd = ifd + // Stop cache expiration timer. + if mb.ctmr != nil { + mb.ctmr.Stop() + mb.ctmr = nil } - - if n, err = mb.ifd.WriteAt(buf, 0); err == nil { - mb.liwsz = int64(n) + // Close cache + mb.clearCacheAndOffset() + // Quit our loops. + if mb.qch != nil { + close(mb.qch) + mb.qch = nil } - - return err + if mb.mfd != nil { + mb.mfd.Close() + mb.mfd = nil + } + if remove { + // Clear any tracking by subject if we are removing. + mb.fss = nil + if mb.mfn != _EMPTY_ { + err := os.Remove(mb.mfn) + if isPermissionError(err) { + return err + } + mb.mfn = _EMPTY_ + } + if mb.kfn != _EMPTY_ { + err := os.Remove(mb.kfn) + if isPermissionError(err) { + return err + } + } + } + return nil } -// readIndexInfo will read in the index information for the message block. -func (mb *msgBlock) readIndexInfo() error { - buf, err := ioutil.ReadFile(mb.ifn) - if err != nil { - return err +// Remove a seq from the fss and select new first. +// Lock should be held. +func (mb *msgBlock) removeSeqPerSubject(subj string, seq uint64) uint64 { + mb.ensurePerSubjectInfoLoaded() + if mb.fss == nil { + return 0 + } + bsubj := stringToBytes(subj) + ss, ok := mb.fss.Find(bsubj) + if !ok || ss == nil { + return 0 } - if err := checkHeader(buf); err != nil { - defer os.Remove(mb.ifn) - return fmt.Errorf("bad index file") + mb.fs.sdm.removeSeqAndSubject(seq, subj) + if ss.Msgs == 1 { + mb.fss.Delete(bsubj) + return 0 } - bi := hdrLen + ss.Msgs-- - // Helpers, will set i to -1 on error. - readSeq := func() uint64 { - if bi < 0 { - return 0 + // Only one left. + if ss.Msgs == 1 { + if !ss.lastNeedsUpdate && seq != ss.Last { + ss.First = ss.Last + ss.firstNeedsUpdate = false + return 1 } - seq, n := binary.Uvarint(buf[bi:]) - if n <= 0 { - bi = -1 - return 0 + if !ss.firstNeedsUpdate && seq != ss.First { + ss.Last = ss.First + ss.lastNeedsUpdate = false + return 1 } - bi += n - return seq &^ ebit } - readCount := readSeq - readTimeStamp := func() int64 { - if bi < 0 { - return 0 - } - ts, n := binary.Varint(buf[bi:]) - if n <= 0 { - bi = -1 - return -1 + + // We can lazily calculate the first/last sequence when needed. + ss.firstNeedsUpdate = seq == ss.First || ss.firstNeedsUpdate + ss.lastNeedsUpdate = seq == ss.Last || ss.lastNeedsUpdate + + return ss.Msgs +} + +// Will recalculate the first and/or last sequence for this subject in this block. +// Will avoid slower path message lookups and scan the cache directly instead. +func (mb *msgBlock) recalculateForSubj(subj string, ss *SimpleState) { + // Need to make sure messages are loaded. + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return } - bi += n - return ts } - mb.msgs = readCount() - mb.bytes = readCount() - mb.first.seq = readSeq() - mb.first.ts = readTimeStamp() - mb.last.seq = readSeq() - mb.last.ts = readTimeStamp() - dmapLen := readCount() - // Checksum - copy(mb.lchk[0:], buf[bi:bi+checksumSize]) - bi += checksumSize + startSlot := int(ss.First - mb.cache.fseq) + if startSlot < 0 { + startSlot = 0 + } + if startSlot >= len(mb.cache.idx) { + ss.First = ss.Last + ss.firstNeedsUpdate = false + ss.lastNeedsUpdate = false + return + } - // Now check for presence of a delete map - if dmapLen > 0 { - mb.dmap = make(map[uint64]struct{}, dmapLen) - for i := 0; i < int(dmapLen); i++ { - seq := readSeq() - if seq == 0 { + endSlot := int(ss.Last - mb.cache.fseq) + if endSlot < 0 { + endSlot = 0 + } + if endSlot >= len(mb.cache.idx) || startSlot > endSlot { + return + } + + var le = binary.LittleEndian + if ss.firstNeedsUpdate { + // Mark first as updated. + ss.firstNeedsUpdate = false + + fseq := ss.First + 1 + if mbFseq := atomic.LoadUint64(&mb.first.seq); fseq < mbFseq { + fseq = mbFseq + } + for slot := startSlot; slot < len(mb.cache.idx); slot++ { + bi := mb.cache.idx[slot] &^ cbit + if bi == dbit { + // delete marker so skip. + continue + } + li := int(bi) - mb.cache.off + if li >= len(mb.cache.buf) { + ss.First = ss.Last + // Only need to reset ss.lastNeedsUpdate, ss.firstNeedsUpdate is already reset above. + ss.lastNeedsUpdate = false + return + } + buf := mb.cache.buf[li:] + hdr := buf[:msgHdrSize] + slen := int(le.Uint16(hdr[20:])) + if subj == bytesToString(buf[msgHdrSize:msgHdrSize+slen]) { + seq := le.Uint64(hdr[4:]) + if seq < fseq || seq&ebit != 0 || mb.dmap.Exists(seq) { + continue + } + ss.First = seq + if ss.Msgs == 1 { + ss.Last = seq + ss.lastNeedsUpdate = false + return + } + // Skip the start slot ahead, if we need to recalculate last we can stop early. + startSlot = slot break } - mb.dmap[seq+mb.first.seq] = struct{}{} } } + if ss.lastNeedsUpdate { + // Mark last as updated. + ss.lastNeedsUpdate = false - return nil + lseq := ss.Last - 1 + if mbLseq := atomic.LoadUint64(&mb.last.seq); lseq > mbLseq { + lseq = mbLseq + } + for slot := endSlot; slot >= startSlot; slot-- { + bi := mb.cache.idx[slot] &^ cbit + if bi == dbit { + // delete marker so skip. + continue + } + li := int(bi) - mb.cache.off + if li >= len(mb.cache.buf) { + // Can't overwrite ss.Last, just skip. + return + } + buf := mb.cache.buf[li:] + hdr := buf[:msgHdrSize] + slen := int(le.Uint16(hdr[20:])) + if subj == bytesToString(buf[msgHdrSize:msgHdrSize+slen]) { + seq := le.Uint64(hdr[4:]) + if seq > lseq || seq&ebit != 0 || mb.dmap.Exists(seq) { + continue + } + // Sequence should never be lower, but guard against it nonetheless. + if seq < ss.First { + seq = ss.First + } + ss.Last = seq + if ss.Msgs == 1 { + ss.First = seq + ss.firstNeedsUpdate = false + } + return + } + } + } } -func (mb *msgBlock) genDeleteMap() []byte { - if len(mb.dmap) == 0 { - return nil +// Lock should be held. +func (fs *fileStore) resetGlobalPerSubjectInfo() { + // Clear any global subject state. + fs.psim, fs.tsl = fs.psim.Empty(), 0 + if fs.noTrackSubjects() { + return } - buf := make([]byte, len(mb.dmap)*binary.MaxVarintLen64) - // We use first seq as an offset to cut down on size. - fseq, n := uint64(mb.first.seq), 0 - for seq := range mb.dmap { - // This is for lazy cleanup as the first sequence moves up. - if seq <= fseq { - delete(mb.dmap, seq) - } else { - n += binary.PutUvarint(buf[n:], seq-fseq) - } + for _, mb := range fs.blks { + fs.populateGlobalPerSubjectInfo(mb) } - return buf[:n] } -func syncAndClose(mfd, ifd *os.File) { - if mfd != nil { - mfd.Sync() - mfd.Close() +// Lock should be held. +func (mb *msgBlock) resetPerSubjectInfo() error { + mb.fss = nil + return mb.generatePerSubjectInfo() +} + +// generatePerSubjectInfo will generate the per subject info via the raw msg block. +// Lock should be held. +func (mb *msgBlock) generatePerSubjectInfo() error { + // Check if this mb is empty. This can happen when its the last one and we are holding onto it for seq and timestamp info. + if mb.msgs == 0 { + return nil } - if ifd != nil { - ifd.Sync() - ifd.Close() + + if mb.cacheNotLoaded() { + if err := mb.loadMsgsWithLock(); err != nil { + return err + } + // indexCacheBuf can produce fss now, so if non-nil we are good. + if mb.fss != nil { + return nil + } } -} -// Will return total number of cache loads. -func (fs *fileStore) cacheLoads() uint64 { - var tl uint64 - fs.mu.RLock() - for _, mb := range fs.blks { - tl += mb.cloads + // Create new one regardless. + mb.fss = mb.fss.Empty() + + var smv StoreMsg + fseq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) + for seq := fseq; seq <= lseq; seq++ { + if mb.dmap.Exists(seq) { + // Optimisation to avoid calling cacheLookup which hits time.Now(). + // It gets set later on if the fss is non-empty anyway. + continue + } + sm, err := mb.cacheLookupNoCopy(seq, &smv) + if err != nil { + // Since we are walking by sequence we can ignore some errors that are benign to rebuilding our state. + if err == ErrStoreMsgNotFound || err == errDeletedMsg { + continue + } + if err == errNoCache { + return nil + } + return err + } + if sm != nil && len(sm.subj) > 0 { + if ss, ok := mb.fss.Find(stringToBytes(sm.subj)); ok && ss != nil { + ss.Msgs++ + ss.Last = seq + ss.lastNeedsUpdate = false + } else { + mb.fss.Insert(stringToBytes(sm.subj), SimpleState{Msgs: 1, First: seq, Last: seq}) + } + } } - fs.mu.RUnlock() - return tl + + if mb.fss.Size() > 0 { + // Make sure we run the cache expire timer. + mb.llts = ats.AccessTime() + // Mark fss activity same as load time. + mb.lsts = mb.llts + mb.startCacheExpireTimer() + } + return nil } -// Will return total number of cached bytes. -func (fs *fileStore) cacheSize() uint64 { - var sz uint64 - fs.mu.RLock() - for _, mb := range fs.blks { - mb.mu.RLock() - if mb.cache != nil { - sz += uint64(len(mb.cache.buf)) +// Helper to make sure fss loaded if we are tracking. +// Lock should be held +func (mb *msgBlock) ensurePerSubjectInfoLoaded() error { + if mb.fss != nil || mb.noTrack { + if mb.fss != nil { + // Mark fss activity. + mb.lsts = ats.AccessTime() } - mb.mu.RUnlock() + return nil + } + if mb.msgs == 0 { + mb.fss = stree.NewSubjectTree[SimpleState]() + return nil } - fs.mu.RUnlock() - return sz + return mb.generatePerSubjectInfo() } -// Will return total number of dmapEntries for all msg blocks. -func (fs *fileStore) dmapEntries() int { - var total int - fs.mu.RLock() - for _, mb := range fs.blks { - total += len(mb.dmap) +// Called on recovery to populate the global psim state. +// Lock should be held. +func (fs *fileStore) populateGlobalPerSubjectInfo(mb *msgBlock) { + mb.mu.Lock() + defer mb.mu.Unlock() + + if err := mb.ensurePerSubjectInfoLoaded(); err != nil { + return } - fs.mu.RUnlock() - return total + + // Now populate psim. + mb.fss.IterFast(func(bsubj []byte, ss *SimpleState) bool { + if len(bsubj) > 0 { + if info, ok := fs.psim.Find(bsubj); ok { + info.total += ss.Msgs + if mb.index > info.lblk { + info.lblk = mb.index + } + } else { + fs.psim.Insert(bsubj, psi{total: ss.Msgs, fblk: mb.index, lblk: mb.index}) + fs.tsl += len(bsubj) + } + } + return true + }) } -// Purge will remove all messages from this store. -// Will return the number of purged messages. -func (fs *fileStore) Purge() (uint64, error) { - fs.mu.Lock() - if fs.closed { - fs.mu.Unlock() - return 0, ErrStoreClosed +// Close the message block. +func (mb *msgBlock) close(sync bool) { + if mb == nil { + return } + mb.mu.Lock() + defer mb.mu.Unlock() - purged := fs.state.Msgs - rbytes := int64(fs.state.Bytes) + if mb.closed { + return + } - fs.state.FirstSeq = fs.state.LastSeq + 1 - fs.state.FirstTime = time.Time{} + // Stop cache expiration timer. + if mb.ctmr != nil { + mb.ctmr.Stop() + mb.ctmr = nil + } - fs.state.Bytes = 0 - fs.state.Msgs = 0 + // Clear fss. + mb.fss = nil + + // Close cache + mb.clearCacheAndOffset() + // Quit our loops. + if mb.qch != nil { + close(mb.qch) + mb.qch = nil + } + if mb.mfd != nil { + if sync { + mb.mfd.Sync() + } + mb.mfd.Close() + } + mb.mfd = nil + // Mark as closed. + mb.closed = true +} +func (fs *fileStore) closeAllMsgBlocks(sync bool) { for _, mb := range fs.blks { - mb.dirtyClose() + mb.close(sync) } +} - fs.blks = nil - fs.lmb = nil +func (fs *fileStore) Delete() error { + if fs.isClosed() { + // Always attempt to remove since we could have been closed beforehand. + os.RemoveAll(fs.fcfg.StoreDir) + // Since we did remove, if we did have anything remaining make sure to + // call into any storage updates that had been registered. + fs.mu.Lock() + cb, msgs, bytes := fs.scb, int64(fs.state.Msgs), int64(fs.state.Bytes) + // Guard against double accounting if called twice. + fs.state.Msgs, fs.state.Bytes = 0, 0 + fs.mu.Unlock() + if msgs > 0 && cb != nil { + cb(-msgs, -bytes, 0, _EMPTY_) + } + return ErrStoreClosed + } - // Move the msgs directory out of the way, will delete out of band. - // FIXME(dlc) - These can error and we need to change api above to propagate? - mdir := path.Join(fs.fcfg.StoreDir, msgDir) - pdir := path.Join(fs.fcfg.StoreDir, purgeDir) + pdir := filepath.Join(fs.fcfg.StoreDir, purgeDir) // If purge directory still exists then we need to wait // in place and remove since rename would fail. if _, err := os.Stat(pdir); err == nil { os.RemoveAll(pdir) } - os.Rename(mdir, pdir) - go os.RemoveAll(pdir) - // Create new one. - os.MkdirAll(mdir, 0755) - - // Make sure we have a lmb to write to. - fs.newMsgBlockForWrite() - - fs.lmb.first.seq = fs.state.FirstSeq - fs.lmb.last.seq = fs.state.LastSeq - fs.lmb.writeIndexInfo() + // Quickly close all blocks and simulate a purge w/o overhead an new write block. + fs.mu.Lock() + for _, mb := range fs.blks { + mb.dirtyClose() + } + dmsgs := fs.state.Msgs + dbytes := int64(fs.state.Bytes) + fs.state.Msgs, fs.state.Bytes = 0, 0 + fs.blks = nil cb := fs.scb fs.mu.Unlock() if cb != nil { - cb(-int64(purged), -rbytes, 0, _EMPTY_) + cb(-int64(dmsgs), -dbytes, 0, _EMPTY_) } - return purged, nil + if err := fs.stop(true, false); err != nil { + return err + } + + // Make sure we will not try to recover if killed before removal below completes. + if err := os.Remove(filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFile)); err != nil { + return err + } + // Now move into different directory with "." prefix. + ndir := filepath.Join(filepath.Dir(fs.fcfg.StoreDir), tsep+filepath.Base(fs.fcfg.StoreDir)) + if err := os.Rename(fs.fcfg.StoreDir, ndir); err != nil { + return err + } + // Do this in separate Go routine in case lots of blocks. + // Purge above protects us as does the removal of meta artifacts above. + go func() { + <-dios + err := os.RemoveAll(ndir) + dios <- struct{}{} + if err == nil { + return + } + ttl := time.Now().Add(time.Second) + for time.Now().Before(ttl) { + time.Sleep(10 * time.Millisecond) + <-dios + err = os.RemoveAll(ndir) + dios <- struct{}{} + if err == nil { + return + } + } + }() + + return nil } -// Compact will remove all messages from this store up to -// but not including the seq parameter. -// Will return the number of purged messages. -func (fs *fileStore) Compact(seq uint64) (uint64, error) { - if seq == 0 { - return fs.Purge() +// Lock should be held. +func (fs *fileStore) setSyncTimer() { + if fs.syncTmr != nil { + fs.syncTmr.Reset(fs.fcfg.SyncInterval) + } else { + // First time this fires will be between SyncInterval/2 and SyncInterval, + // so that different stores are spread out, rather than having many of + // them trying to all sync at once, causing blips and contending dios. + start := (fs.fcfg.SyncInterval / 2) + (time.Duration(mrand.Int63n(int64(fs.fcfg.SyncInterval / 2)))) + fs.syncTmr = time.AfterFunc(start, fs.syncBlocks) } +} - if _, err := fs.msgForSeq(seq); err != nil { - return 0, err +// Lock should be held. +func (fs *fileStore) cancelSyncTimer() { + if fs.syncTmr != nil { + fs.syncTmr.Stop() + fs.syncTmr = nil } +} - var purged uint64 - for fseq := fs.firstSeq(); fseq < seq; fseq = fs.firstSeq() { - if found, err := fs.removeMsg(fseq, false); err != nil { - if err == ErrStoreMsgNotFound { - continue - } else if err == ErrStoreEOF { - err = nil +// The full state file is versioned. +// - 0x1: original binary index.db format +// - 0x2: adds support for TTL count field after num deleted +const ( + fullStateMagic = uint8(11) + fullStateMinVersion = uint8(1) // What is the minimum version we know how to parse? + fullStateVersion = uint8(2) // What is the current version written out to index.db? +) + +// This go routine periodically writes out our full stream state index. +func (fs *fileStore) flushStreamStateLoop(qch, done chan struct{}) { + // Signal we are done on exit. + defer close(done) + + // Make sure we do not try to write these out too fast. + // Spread these out for large numbers on a server restart. + const writeThreshold = 2 * time.Minute + writeJitter := time.Duration(mrand.Int63n(int64(30 * time.Second))) + t := time.NewTicker(writeThreshold + writeJitter) + defer t.Stop() + + for { + select { + case <-t.C: + err := fs.writeFullState() + if isPermissionError(err) && fs.srv != nil { + fs.warn("File system permission denied when flushing stream state, disabling JetStream: %v", err) + // messages in block cache could be lost in the worst case. + // In the clustered mode it is very highly unlikely as a result of replication. + fs.srv.DisableJetStream() + return } - return purged, err - } else if found { - purged++ + + case <-qch: + return } } +} - return purged, nil +// Helper since unixnano of zero time undefined. +func timestampNormalized(t time.Time) int64 { + if t.IsZero() { + return 0 + } + return t.UnixNano() } -func (fs *fileStore) firstSeq() uint64 { - fs.mu.RLock() - fseq := fs.state.FirstSeq - fs.mu.RUnlock() - return fseq +// writeFullState will proceed to write the full meta state iff not complex and time consuming. +// Since this is for quick recovery it is optional and should not block/stall normal operations. +func (fs *fileStore) writeFullState() error { + return fs._writeFullState(false, true) } -// Returns number of msg blks. -func (fs *fileStore) numMsgBlocks() int { - fs.mu.RLock() - defer fs.mu.RUnlock() - return len(fs.blks) +// forceWriteFullState will proceed to write the full meta state. +func (fs *fileStore) forceWriteFullState() error { + return fs._writeFullState(true, true) } -// Will remove our index file. -func (mb *msgBlock) removeIndexFile() { - mb.mu.RLock() - defer mb.mu.RUnlock() - if mb.ifd != nil { - mb.ifd.Close() - mb.ifd = nil - } - if mb.ifn != _EMPTY_ { - os.Remove(mb.ifn) - } +// forceWriteFullStateLocked will proceed to write the full meta state. This should only be called by stop() +func (fs *fileStore) forceWriteFullStateLocked() error { + return fs._writeFullState(true, false) } -// Removes the msgBlock -// Both locks should be held. -func (fs *fileStore) removeMsgBlock(mb *msgBlock) { - mb.dirtyCloseWithRemove(true) +// This will write the full binary state for the stream. +// This plus everything new since last hash will be the total recovered state. +// This state dump will have the following. +// 1. Stream summary - Msgs, Bytes, First and Last (Sequence and Timestamp) +// 2. PSIM - Per Subject Index Map - Tracks first and last blocks with subjects present. +// 3. MBs - Index, Bytes, First and Last Sequence and Timestamps, and the deleted map (avl.seqset). +// 4. Last block index and hash of record inclusive to this stream state. +func (fs *fileStore) _writeFullState(force, needLock bool) error { + if fs.isClosed() { + return nil + } - // Remove from list. - for i, omb := range fs.blks { - if mb == omb { - fs.blks = append(fs.blks[:i], fs.blks[i+1:]...) - break + fsLock := func() { + if needLock { + fs.mu.Lock() } } - // Check for us being last message block - if mb == fs.lmb { - fs.newMsgBlockForWrite() + fsUnlock := func() { + if needLock { + fs.mu.Unlock() + } } -} -// Called by purge to simply get rid of the cache and close and fds. -// Lock should not be held. -func (mb *msgBlock) dirtyClose() { - mb.mu.Lock() - mb.dirtyCloseWithRemove(false) - mb.mu.Unlock() -} + start := time.Now() + fsLock() + if fs.dirty == 0 { + fsUnlock() + return nil + } -// Should be called with lock held. -func (mb *msgBlock) dirtyCloseWithRemove(remove bool) { - if mb == nil { - return + // For calculating size and checking time costs for non forced calls. + numSubjects := fs.numSubjects() + + // If we are not being forced to write out our state, check the complexity for time costs as to not + // block or stall normal operations. + // We will base off of number of subjects and interior deletes. A very large number of msg blocks could also + // be used, but for next server version will redo all meta handling to be disk based. So this is temporary. + if !force { + const numThreshold = 1_000_000 + // Calculate interior deletes. + var numDeleted int + if fs.state.LastSeq > fs.state.FirstSeq { + numDeleted = int((fs.state.LastSeq - fs.state.FirstSeq + 1) - fs.state.Msgs) + } + if numSubjects > numThreshold || numDeleted > numThreshold { + fsUnlock() + return errStateTooBig + } } - // Close cache - mb.clearCacheAndOffset() - // Quit our loops. - if mb.qch != nil { - close(mb.qch) - mb.qch = nil + + // We track this through subsequent runs to get an avg per blk used for subsequent runs. + avgDmapLen := fs.adml + // If first time through could be 0 + if avgDmapLen == 0 && ((fs.state.LastSeq-fs.state.FirstSeq+1)-fs.state.Msgs) > 0 { + avgDmapLen = 1024 } - if mb.mfd != nil { - mb.mfd.Close() - mb.mfd = nil + + // Calculate and estimate of the uper bound on the size to avoid multiple allocations. + sz := hdrLen + // Magic and Version + (binary.MaxVarintLen64 * 6) + // FS data + binary.MaxVarintLen64 + fs.tsl + // NumSubjects + total subject length + numSubjects*(binary.MaxVarintLen64*4) + // psi record + binary.MaxVarintLen64 + // Num blocks. + len(fs.blks)*((binary.MaxVarintLen64*8)+avgDmapLen) + // msg blocks, avgDmapLen is est for dmaps + binary.MaxVarintLen64 + 8 + 8 // last index + record checksum + full state checksum + + // Do 4k on stack if possible. + const ssz = 4 * 1024 + var buf []byte + + if sz <= ssz { + var _buf [ssz]byte + buf, sz = _buf[0:hdrLen:ssz], ssz + } else { + buf = make([]byte, hdrLen, sz) + } + + buf[0], buf[1] = fullStateMagic, fullStateVersion + buf = binary.AppendUvarint(buf, fs.state.Msgs) + buf = binary.AppendUvarint(buf, fs.state.Bytes) + buf = binary.AppendUvarint(buf, fs.state.FirstSeq) + buf = binary.AppendVarint(buf, timestampNormalized(fs.state.FirstTime)) + buf = binary.AppendUvarint(buf, fs.state.LastSeq) + buf = binary.AppendVarint(buf, timestampNormalized(fs.state.LastTime)) + + // Do per subject information map if applicable. + buf = binary.AppendUvarint(buf, uint64(numSubjects)) + if numSubjects > 0 { + fs.psim.Match([]byte(fwcs), func(subj []byte, psi *psi) { + buf = binary.AppendUvarint(buf, uint64(len(subj))) + buf = append(buf, subj...) + buf = binary.AppendUvarint(buf, psi.total) + buf = binary.AppendUvarint(buf, uint64(psi.fblk)) + if psi.total > 1 { + buf = binary.AppendUvarint(buf, uint64(psi.lblk)) + } + }) + } + + // Now walk all blocks and write out first and last and optional dmap encoding. + var lbi uint32 + var lchk [8]byte + + nb := len(fs.blks) + buf = binary.AppendUvarint(buf, uint64(nb)) + + // Use basetime to save some space. + baseTime := timestampNormalized(fs.state.FirstTime) + var scratch [8 * 1024]byte + + // Track the state as represented by the mbs. + var mstate StreamState + + var dmapTotalLen int + for _, mb := range fs.blks { + mb.mu.RLock() + buf = binary.AppendUvarint(buf, uint64(mb.index)) + buf = binary.AppendUvarint(buf, mb.bytes) + buf = binary.AppendUvarint(buf, atomic.LoadUint64(&mb.first.seq)) + buf = binary.AppendVarint(buf, mb.first.ts-baseTime) + buf = binary.AppendUvarint(buf, atomic.LoadUint64(&mb.last.seq)) + buf = binary.AppendVarint(buf, mb.last.ts-baseTime) + + numDeleted := mb.dmap.Size() + buf = binary.AppendUvarint(buf, uint64(numDeleted)) + buf = binary.AppendUvarint(buf, mb.ttls) // Field is new in version 2 + if numDeleted > 0 { + dmap, _ := mb.dmap.Encode(scratch[:0]) + dmapTotalLen += len(dmap) + buf = append(buf, dmap...) + } + // If this is the last one grab the last checksum and the block index, e.g. 22.blk, 22 is the block index. + // We use this to quickly open this file on recovery. + if mb == fs.lmb { + lbi = mb.index + mb.ensureLastChecksumLoaded() + copy(lchk[0:], mb.lchk[:]) + } + updateTrackingState(&mstate, mb) + mb.mu.RUnlock() } - if mb.ifd != nil { - mb.ifd.Close() - mb.ifd = nil + if dmapTotalLen > 0 { + fs.adml = dmapTotalLen / len(fs.blks) } - if remove { - if mb.ifn != _EMPTY_ { - os.Remove(mb.ifn) - mb.ifn = _EMPTY_ + + // Place block index and hash onto the end. + buf = binary.AppendUvarint(buf, uint64(lbi)) + buf = append(buf, lchk[:]...) + + // Encrypt if needed. + if fs.prf != nil { + if err := fs.setupAEK(); err != nil { + fsUnlock() + return err } - if mb.mfn != _EMPTY_ { - os.Remove(mb.mfn) - mb.mfn = _EMPTY_ + nonce := make([]byte, fs.aek.NonceSize(), fs.aek.NonceSize()+len(buf)+fs.aek.Overhead()) + if n, err := rand.Read(nonce); err != nil { + fsUnlock() + return err + } else if n != len(nonce) { + fsUnlock() + return fmt.Errorf("not enough nonce bytes read (%d != %d)", n, len(nonce)) } + buf = fs.aek.Seal(nonce, nonce, buf, nil) } -} -func (mb *msgBlock) close(sync bool) { - if mb == nil { - return + fn := filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile) + + fs.hh.Reset() + fs.hh.Write(buf) + buf = fs.hh.Sum(buf) + + // Snapshot prior dirty count. + priorDirty := fs.dirty + + statesEqual := trackingStatesEqual(&fs.state, &mstate) + // Release lock. + fsUnlock() + + // Check consistency here. + if !statesEqual { + fs.warn("Stream state encountered internal inconsistency on write") + // Rebuild our fs state from the mb state. + if needLock { + fs.rebuildState(nil) + } else { + fs.rebuildStateLocked(nil) + } + return errCorruptState } - mb.mu.Lock() - defer mb.mu.Unlock() - if mb.qch == nil { - return + if cap(buf) > sz { + fs.debug("WriteFullState reallocated from %d to %d", sz, cap(buf)) } - // Close cache - mb.clearCacheAndOffset() - // Quit our loops. - if mb.qch != nil { - close(mb.qch) - mb.qch = nil + // Only warn about construction time since file write not holding any locks. + if took := time.Since(start); took > time.Minute { + fs.warn("WriteFullState took %v (%d bytes)", took.Round(time.Millisecond), len(buf)) } - if sync { - syncAndClose(mb.mfd, mb.ifd) - } else { - go syncAndClose(mb.mfd, mb.ifd) + + // Write our update index.db + // Protect with dios. + <-dios + err := os.WriteFile(fn, buf, defaultFilePerms) + // if file system is not writable isPermissionError is set to true + dios <- struct{}{} + if isPermissionError(err) { + return err } - mb.mfd = nil - mb.ifd = nil -} -func (fs *fileStore) closeAllMsgBlocks(sync bool) { - for _, mb := range fs.blks { - mb.close(sync) + // Update dirty if successful. + if err == nil { + fsLock() + fs.dirty -= priorDirty + fsUnlock() } + + return fs.writeTTLState(needLock) } -func (fs *fileStore) Delete() error { - if fs.isClosed() { - return ErrStoreClosed +func (fs *fileStore) writeTTLState(needLock bool) error { + if needLock { + fs.mu.RLock() } - fs.Purge() - if err := fs.Stop(); err != nil { - return err + if fs.ttls == nil { + if needLock { + fs.mu.RUnlock() + } + return nil + } + fn := filepath.Join(fs.fcfg.StoreDir, msgDir, ttlStreamStateFile) + // Must be lseq+1 to identify up to which sequence the TTLs are valid. + buf := fs.ttls.Encode(fs.state.LastSeq + 1) + if needLock { + fs.mu.RUnlock() } - return os.RemoveAll(fs.fcfg.StoreDir) + + return fs.writeFileWithOptionalSync(fn, buf, defaultFilePerms) } +// Stop the current filestore. func (fs *fileStore) Stop() error { + return fs.stop(false, true) +} + +// Stop the current filestore. +func (fs *fileStore) stop(delete, writeState bool) error { + if fs.isClosed() { + return ErrStoreClosed + } + fs.mu.Lock() - if fs.closed { + if fs.closing { fs.mu.Unlock() return ErrStoreClosed } - fs.closed = true - fs.lmb = nil - fs.checkAndFlushAllBlocks() - fs.closeAllMsgBlocks(true) + // Mark as closing. Do before releasing the lock to wait on the state flush loop + // so we don't end up with this function running more than once. + fs.closing = true + + // Release the state flusher loop. + if fs.qch != nil { + close(fs.qch) + fs.qch = nil + } + + if writeState { + // Wait for the state flush loop to exit. + fsld := fs.fsld + fs.mu.Unlock() + <-fsld + fs.mu.Lock() + } + fs.closeAllMsgBlocks(false) + + fs.cancelSyncTimer() + fs.cancelAgeChk() - if fs.syncTmr != nil { - fs.syncTmr.Stop() - fs.syncTmr = nil - } - if fs.ageChk != nil { - fs.ageChk.Stop() - fs.ageChk = nil + if writeState { + // Write full state if needed. If not dirty this is a no-op. + fs.forceWriteFullStateLocked() } - var _cfs [256]*consumerFileStore + // Mark as closed. Last message block needs to be cleared after + // writeFullState has completed. + fs.closed.Store(true) + fs.lmb = nil + + // We should update the upper usage layer on a stop. + cb, bytes := fs.scb, int64(fs.state.Bytes) + fs.mu.Unlock() + + fs.cmu.Lock() + var _cfs [256]ConsumerStore cfs := append(_cfs[:0], fs.cfs...) fs.cfs = nil - fs.mu.Unlock() + fs.cmu.Unlock() for _, o := range cfs { - o.Stop() + if delete { + o.StreamDelete() + } else { + o.Stop() + } + } + + if bytes > 0 && cb != nil { + cb(0, -bytes, 0, _EMPTY_) } + // Unregister from the access time service. + ats.Unregister() + return nil } const errFile = "errors.txt" -// Stream our snapshot through gzip and tar. -func (fs *fileStore) streamSnapshot(w io.WriteCloser, blks []*msgBlock, includeConsumers bool) { +// Stream our snapshot through S2 compression and tar. +func (fs *fileStore) streamSnapshot(w io.WriteCloser, includeConsumers bool, errCh chan string) { + defer close(errCh) defer w.Close() - bw := bufio.NewWriter(w) - defer bw.Flush() + enc := s2.NewWriter(w) + defer enc.Close() - gzw, _ := gzip.NewWriterLevel(bw, gzip.BestSpeed) - defer gzw.Close() - - tw := tar.NewWriter(gzw) + tw := tar.NewWriter(enc) defer tw.Close() defer func() { @@ -2665,27 +10276,24 @@ func (fs *fileStore) streamSnapshot(w io.WriteCloser, blks []*msgBlock, includeC writeErr := func(err string) { writeFile(errFile, []byte(err)) + errCh <- err } fs.mu.Lock() - // Write our general meta data. - if err := fs.writeStreamMeta(); err != nil { - fs.mu.Unlock() - writeErr(fmt.Sprintf("Could not write stream meta file: %v", err)) - return - } - meta, err := ioutil.ReadFile(path.Join(fs.fcfg.StoreDir, JetStreamMetaFile)) - if err != nil { - fs.mu.Unlock() - writeErr(fmt.Sprintf("Could not read stream meta file: %v", err)) - return - } - sum, err := ioutil.ReadFile(path.Join(fs.fcfg.StoreDir, JetStreamMetaFileSum)) + blks := fs.blks + // Grab our general meta data. + // We do this now instead of pulling from files since they could be encrypted. + meta, err := json.Marshal(fs.cfg) if err != nil { fs.mu.Unlock() - writeErr(fmt.Sprintf("Could not read stream checksum file: %v", err)) + writeErr(fmt.Sprintf("Could not gather stream meta file: %v", err)) return } + hh := fs.hh + hh.Reset() + hh.Write(meta) + var hb [highwayhash.Size64]byte + sum := []byte(hex.EncodeToString(fs.hh.Sum(hb[:0]))) fs.mu.Unlock() // Meta first. @@ -2696,66 +10304,100 @@ func (fs *fileStore) streamSnapshot(w io.WriteCloser, blks []*msgBlock, includeC return } - // Can't use join path here, zip only recognizes relative paths with forward slashes. + // Can't use join path here, tar only recognizes relative paths with forward slashes. msgPre := msgDir + "/" + var bbuf []byte // Now do messages themselves. for _, mb := range blks { if mb.pendingWriteSize() > 0 { - mb.flushPendingMsgsAndWait() - mb.writeIndexInfo() + mb.flushPendingMsgs() } mb.mu.Lock() - buf, err := ioutil.ReadFile(mb.ifn) + // We could stream but don't want to hold the lock and prevent changes, so just read in and + // release the lock for now. + bbuf, err = mb.loadBlock(bbuf) if err != nil { mb.mu.Unlock() - writeErr(fmt.Sprintf("Could not read message block [%d] meta file: %v", mb.index, err)) + writeErr(fmt.Sprintf("Could not read message block [%d]: %v", mb.index, err)) return } - if writeFile(msgPre+fmt.Sprintf(indexScan, mb.index), buf) != nil { - mb.mu.Unlock() - return + // Check for encryption. + if mb.bek != nil && len(bbuf) > 0 { + rbek, err := genBlockEncryptionKey(fs.fcfg.Cipher, mb.seed, mb.nonce) + if err != nil { + mb.mu.Unlock() + writeErr(fmt.Sprintf("Could not create encryption key for message block [%d]: %v", mb.index, err)) + return + } + rbek.XORKeyStream(bbuf, bbuf) } - // We could stream but don't want to hold the lock and prevent changes, so just read in and - // release the lock for now. - // TODO(dlc) - Maybe reuse buffer? - buf, err = ioutil.ReadFile(mb.mfn) - if err != nil { + // Check for compression. + if bbuf, err = mb.decompressIfNeeded(bbuf); err != nil { mb.mu.Unlock() - writeErr(fmt.Sprintf("Could not read message block [%d]: %v", mb.index, err)) + writeErr(fmt.Sprintf("Could not decompress message block [%d]: %v", mb.index, err)) return } mb.mu.Unlock() + // Do this one unlocked. - if writeFile(msgPre+fmt.Sprintf(blkScan, mb.index), buf) != nil { + if writeFile(msgPre+fmt.Sprintf(blkScan, mb.index), bbuf) != nil { return } } + // Do index.db last. We will force a write as well. + // Write out full state as well before proceeding. + if err := fs.forceWriteFullState(); err == nil { + const minLen = 32 + sfn := filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile) + if buf, err := os.ReadFile(sfn); err == nil && len(buf) >= minLen { + if fs.aek != nil { + ns := fs.aek.NonceSize() + buf, err = fs.aek.Open(nil, buf[:ns], buf[ns:len(buf)-highwayhash.Size64], nil) + if err == nil { + // Redo hash checksum at end on plaintext. + fs.mu.Lock() + hh.Reset() + hh.Write(buf) + buf = fs.hh.Sum(buf) + fs.mu.Unlock() + } + } + if err == nil && writeFile(msgPre+streamStreamStateFile, buf) != nil { + return + } + } + } + // Bail if no consumers requested. if !includeConsumers { return } // Do consumers' state last. - fs.mu.Lock() + fs.cmu.RLock() cfs := fs.cfs - fs.mu.Unlock() + fs.cmu.RUnlock() - for _, o := range cfs { - o.mu.Lock() - meta, err := ioutil.ReadFile(path.Join(o.odir, JetStreamMetaFile)) - if err != nil { - o.mu.Unlock() - writeErr(fmt.Sprintf("Could not read consumer meta file for %q: %v", o.name, err)) - return + for _, cs := range cfs { + o, ok := cs.(*consumerFileStore) + if !ok { + continue } - sum, err := ioutil.ReadFile(path.Join(o.odir, JetStreamMetaFileSum)) + o.mu.Lock() + // Grab our general meta data. + // We do this now instead of pulling from files since they could be encrypted. + meta, err := json.Marshal(o.cfg) if err != nil { o.mu.Unlock() - writeErr(fmt.Sprintf("Could not read consumer checksum file for %q: %v", o.name, err)) + writeErr(fmt.Sprintf("Could not gather consumer meta file for %q: %v", o.name, err)) return } + o.hh.Reset() + o.hh.Write(meta) + var hb [highwayhash.Size64]byte + sum := []byte(hex.EncodeToString(o.hh.Sum(hb[:0]))) // We can have the running state directly encoded now. state, err := o.encodeState() @@ -2764,27 +10406,28 @@ func (fs *fileStore) streamSnapshot(w io.WriteCloser, blks []*msgBlock, includeC writeErr(fmt.Sprintf("Could not encode consumer state for %q: %v", o.name, err)) return } - odirPre := consumerDir + "/" + o.name + odirPre := filepath.Join(consumerDir, o.name) o.mu.Unlock() // Write all the consumer files. - if writeFile(path.Join(odirPre, JetStreamMetaFile), meta) != nil { + if writeFile(filepath.Join(odirPre, JetStreamMetaFile), meta) != nil { return } - if writeFile(path.Join(odirPre, JetStreamMetaFileSum), sum) != nil { + if writeFile(filepath.Join(odirPre, JetStreamMetaFileSum), sum) != nil { return } - writeFile(path.Join(odirPre, consumerState), state) + writeFile(filepath.Join(odirPre, consumerState), state) } } // Create a snapshot of this stream and its consumer's state along with messages. func (fs *fileStore) Snapshot(deadline time.Duration, checkMsgs, includeConsumers bool) (*SnapshotResult, error) { - fs.mu.Lock() - if fs.closed { - fs.mu.Unlock() + if fs.isClosed() { return nil, ErrStoreClosed } + + fs.mu.Lock() + // Only allow one at a time. if fs.sips > 0 { fs.mu.Unlock() @@ -2792,14 +10435,12 @@ func (fs *fileStore) Snapshot(deadline time.Duration, checkMsgs, includeConsumer } // Mark us as snapshotting fs.sips += 1 - blks := fs.blks - blkSize := int(fs.fcfg.BlockSize) fs.mu.Unlock() if checkMsgs { - bad := fs.checkMsgs() - if len(bad) > 0 { - return nil, fmt.Errorf("snapshot check detected %d bad messages", len(bad)) + ld := fs.checkMsgs() + if ld != nil && len(ld.Msgs) > 0 { + return nil, fmt.Errorf("snapshot check detected %d bad messages", len(ld.Msgs)) } } @@ -2809,10 +10450,16 @@ func (fs *fileStore) Snapshot(deadline time.Duration, checkMsgs, includeConsumer if deadline > 0 { pw.SetWriteDeadline(time.Now().Add(deadline)) } + + // We can add to our stream while snapshotting but not "user" delete anything. + var state StreamState + fs.FastState(&state) + // Stream in separate Go routine. - go fs.streamSnapshot(pw, blks, includeConsumers) + errCh := make(chan string, 1) + go fs.streamSnapshot(pw, includeConsumers, errCh) - return &SnapshotResult{pr, blkSize, len(blks)}, nil + return &SnapshotResult{pr, state, errCh}, nil } // Helper to return the config. @@ -2822,6 +10469,139 @@ func (fs *fileStore) fileStoreConfig() FileStoreConfig { return fs.fcfg } +// Read lock all existing message blocks. +// Lock held on entry. +func (fs *fileStore) readLockAllMsgBlocks() { + for _, mb := range fs.blks { + mb.mu.RLock() + } +} + +// Read unlock all existing message blocks. +// Lock held on entry. +func (fs *fileStore) readUnlockAllMsgBlocks() { + for _, mb := range fs.blks { + mb.mu.RUnlock() + } +} + +// Binary encoded state snapshot, >= v2.10 server. +func (fs *fileStore) EncodedStreamState(failed uint64) ([]byte, error) { + fs.mu.RLock() + defer fs.mu.RUnlock() + + // Calculate deleted. + var numDeleted int64 + if fs.state.LastSeq > fs.state.FirstSeq { + numDeleted = int64(fs.state.LastSeq-fs.state.FirstSeq+1) - int64(fs.state.Msgs) + if numDeleted < 0 { + numDeleted = 0 + } + } + + // Encoded is Msgs, Bytes, FirstSeq, LastSeq, Failed, NumDeleted and optional DeletedBlocks + var buf [1024]byte + buf[0], buf[1] = streamStateMagic, streamStateVersion + n := hdrLen + n += binary.PutUvarint(buf[n:], fs.state.Msgs) + n += binary.PutUvarint(buf[n:], fs.state.Bytes) + n += binary.PutUvarint(buf[n:], fs.state.FirstSeq) + n += binary.PutUvarint(buf[n:], fs.state.LastSeq) + n += binary.PutUvarint(buf[n:], failed) + n += binary.PutUvarint(buf[n:], uint64(numDeleted)) + + b := buf[0:n] + + if numDeleted > 0 { + var scratch [4 * 1024]byte + + fs.readLockAllMsgBlocks() + defer fs.readUnlockAllMsgBlocks() + + for _, db := range fs.deleteBlocks() { + switch db := db.(type) { + case *DeleteRange: + first, _, num := db.State() + scratch[0] = runLengthMagic + i := 1 + i += binary.PutUvarint(scratch[i:], first) + i += binary.PutUvarint(scratch[i:], num) + b = append(b, scratch[0:i]...) + case *avl.SequenceSet: + buf, err := db.Encode(scratch[:0]) + if err != nil { + return nil, err + } + b = append(b, buf...) + default: + return nil, errors.New("no impl") + } + } + } + + return b, nil +} + +// We used to be more sophisticated to save memory, but speed is more important. +// All blocks should be at least read locked. +func (fs *fileStore) deleteBlocks() DeleteBlocks { + var dbs DeleteBlocks + var prevLast uint64 + + for _, mb := range fs.blks { + // Detect if we have a gap between these blocks. + fseq := atomic.LoadUint64(&mb.first.seq) + if prevLast > 0 && prevLast+1 != fseq { + dbs = append(dbs, &DeleteRange{First: prevLast + 1, Num: fseq - prevLast - 1}) + } + if mb.dmap.Size() > 0 { + dbs = append(dbs, &mb.dmap) + } + prevLast = atomic.LoadUint64(&mb.last.seq) + } + return dbs +} + +// SyncDeleted will make sure this stream has same deleted state as dbs. +// This will only process deleted state within our current state. +func (fs *fileStore) SyncDeleted(dbs DeleteBlocks) { + if len(dbs) == 0 { + return + } + + fs.mu.Lock() + defer fs.mu.Unlock() + + lseq := fs.state.LastSeq + var needsCheck DeleteBlocks + + fs.readLockAllMsgBlocks() + mdbs := fs.deleteBlocks() + for i, db := range dbs { + first, last, num := db.State() + // If the block is same as what we have we can skip. + if i < len(mdbs) { + eFirst, eLast, eNum := mdbs[i].State() + if first == eFirst && last == eLast && num == eNum { + continue + } + } else if first > lseq { + // Skip blocks not applicable to our current state. + continue + } + // Need to insert these. + needsCheck = append(needsCheck, db) + } + fs.readUnlockAllMsgBlocks() + + for _, db := range needsCheck { + db.Range(func(dseq uint64) bool { + fs.removeMsg(dseq, false, true, false) + return true + }) + } +} + //////////////////////////////////////////////////////////////////////////////// // Consumers //////////////////////////////////////////////////////////////////////////////// @@ -2830,17 +10610,18 @@ type consumerFileStore struct { mu sync.Mutex fs *fileStore cfg *FileConsumerInfo + prf keyGen + aek cipher.AEAD name string odir string ifn string - ifd *os.File - lwsz int64 - hh hash.Hash64 + hh *highwayhash.Digest64 state ConsumerState fch chan struct{} qch chan struct{} flusher bool writing bool + dirty bool closed bool } @@ -2851,49 +10632,189 @@ func (fs *fileStore) ConsumerStore(name string, cfg *ConsumerConfig) (ConsumerSt if fs.isClosed() { return nil, ErrStoreClosed } - if cfg == nil || name == "" { + if cfg == nil || name == _EMPTY_ { return nil, fmt.Errorf("bad consumer config") } - odir := path.Join(fs.fcfg.StoreDir, consumerDir, name) - if err := os.MkdirAll(odir, 0755); err != nil { + + // We now allow overrides from a stream being a filestore type and forcing a consumer to be memory store. + if cfg.MemoryStorage { + // Create directly here. + o := &consumerMemStore{ms: fs, cfg: *cfg} + fs.AddConsumer(o) + return o, nil + } + + odir := filepath.Join(fs.fcfg.StoreDir, consumerDir, name) + if err := os.MkdirAll(odir, defaultDirPerms); err != nil { return nil, fmt.Errorf("could not create consumer directory - %v", err) } - csi := &FileConsumerInfo{ConsumerConfig: *cfg} + csi := &FileConsumerInfo{Name: name, Created: time.Now().UTC(), ConsumerConfig: *cfg} o := &consumerFileStore{ fs: fs, cfg: csi, + prf: fs.prf, name: name, odir: odir, - ifn: path.Join(odir, consumerState), + ifn: filepath.Join(odir, consumerState), } key := sha256.Sum256([]byte(fs.cfg.Name + "/" + name)) - hh, err := highwayhash.New64(key[:]) + hh, err := highwayhash.NewDigest64(key[:]) if err != nil { return nil, fmt.Errorf("could not create hash: %v", err) } o.hh = hh + // Check for encryption. + if o.prf != nil { + if ekey, err := os.ReadFile(filepath.Join(odir, JetStreamMetaFileKey)); err == nil { + if len(ekey) < minBlkKeySize { + return nil, errBadKeySize + } + // Recover key encryption key. + rb, err := fs.prf([]byte(fs.cfg.Name + tsep + o.name)) + if err != nil { + return nil, err + } + + sc := fs.fcfg.Cipher + kek, err := genEncryptionKey(sc, rb) + if err != nil { + return nil, err + } + ns := kek.NonceSize() + nonce := ekey[:ns] + seed, err := kek.Open(nil, nonce, ekey[ns:], nil) + if err != nil { + // We may be here on a cipher conversion, so attempt to convert. + if err = o.convertCipher(); err != nil { + return nil, err + } + } else { + o.aek, err = genEncryptionKey(sc, seed) + } + if err != nil { + return nil, err + } + } + } + + // Track if we are creating the directory so that we can clean up if we encounter an error. + var didCreate bool + // Write our meta data iff does not exist. - meta := path.Join(odir, JetStreamMetaFile) + meta := filepath.Join(odir, JetStreamMetaFile) if _, err := os.Stat(meta); err != nil && os.IsNotExist(err) { + didCreate = true csi.Created = time.Now().UTC() if err := o.writeConsumerMeta(); err != nil { + os.RemoveAll(odir) return nil, err } } + // If we expect to be encrypted check that what we are restoring is not plaintext. + // This can happen on snapshot restores or conversions. + if o.prf != nil { + keyFile := filepath.Join(odir, JetStreamMetaFileKey) + if _, err := os.Stat(keyFile); err != nil && os.IsNotExist(err) { + if err := o.writeConsumerMeta(); err != nil { + if didCreate { + os.RemoveAll(odir) + } + return nil, err + } + // Redo the state file as well here if we have one and we can tell it was plaintext. + if buf, err := os.ReadFile(o.ifn); err == nil { + if _, err := decodeConsumerState(buf); err == nil { + state, err := o.encryptState(buf) + if err != nil { + return nil, err + } + err = fs.writeFileWithOptionalSync(o.ifn, state, defaultFilePerms) + if err != nil { + if didCreate { + os.RemoveAll(odir) + } + return nil, err + } + } + } + } + } + // Create channels to control our flush go routine. o.fch = make(chan struct{}, 1) o.qch = make(chan struct{}) - go o.flushLoop() + go o.flushLoop(o.fch, o.qch) - fs.mu.Lock() - fs.cfs = append(fs.cfs, o) - fs.mu.Unlock() + // Make sure to load in our state from disk if needed. + if err = o.loadState(); err != nil { + return nil, err + } + + // Assign to filestore. + fs.AddConsumer(o) return o, nil } +func (o *consumerFileStore) convertCipher() error { + fs := o.fs + odir := filepath.Join(fs.fcfg.StoreDir, consumerDir, o.name) + + ekey, err := os.ReadFile(filepath.Join(odir, JetStreamMetaFileKey)) + if err != nil { + return err + } + if len(ekey) < minBlkKeySize { + return errBadKeySize + } + // Recover key encryption key. + rb, err := fs.prf([]byte(fs.cfg.Name + tsep + o.name)) + if err != nil { + return err + } + + // Do these in reverse since converting. + sc := fs.fcfg.Cipher + osc := AES + if sc == AES { + osc = ChaCha + } + kek, err := genEncryptionKey(osc, rb) + if err != nil { + return err + } + ns := kek.NonceSize() + nonce := ekey[:ns] + seed, err := kek.Open(nil, nonce, ekey[ns:], nil) + if err != nil { + return err + } + aek, err := genEncryptionKey(osc, seed) + if err != nil { + return err + } + // Now read in and decode our state using the old cipher. + buf, err := os.ReadFile(o.ifn) + if err != nil { + return err + } + buf, err = aek.Open(nil, buf[:ns], buf[ns:], nil) + if err != nil { + return err + } + + // Since we are here we recovered our old state. + // Now write our meta, which will generate the new keys with the new cipher. + if err := o.writeConsumerMeta(); err != nil { + return err + } + + // Now write out or state with the new cipher. + return o.writeState(buf) +} + // Kick flusher for this consumer. // Lock should be held. func (o *consumerFileStore) kickFlusher() { @@ -2903,6 +10824,7 @@ func (o *consumerFileStore) kickFlusher() { default: } } + o.dirty = true } // Set in flusher status @@ -2927,22 +10849,40 @@ func (o *consumerFileStore) inFlusher() bool { } // flushLoop watches for consumer updates and the quit channel. -func (o *consumerFileStore) flushLoop() { - o.mu.Lock() - fch, qch := o.fch, o.qch - o.mu.Unlock() +func (o *consumerFileStore) flushLoop(fch, qch chan struct{}) { o.setInFlusher() defer o.clearInFlusher() + // Maintain approximately 10 updates per second per consumer under load. + const minTime = 100 * time.Millisecond + var lastWrite time.Time + var dt *time.Timer + + setDelayTimer := func(addWait time.Duration) { + if dt == nil { + dt = time.NewTimer(addWait) + return + } + if !dt.Stop() { + select { + case <-dt.C: + default: + } + } + dt.Reset(addWait) + } + for { select { case <-fch: - time.Sleep(5 * time.Millisecond) - select { - case <-qch: - return - default: + if ts := time.Since(lastWrite); ts < minTime { + setDelayTimer(minTime - ts) + select { + case <-dt.C: + case <-qch: + return + } } o.mu.Lock() if o.closed { @@ -2955,13 +10895,56 @@ func (o *consumerFileStore) flushLoop() { return } // TODO(dlc) - if we error should start failing upwards. - o.writeState(buf) + if err := o.writeState(buf); err == nil { + lastWrite = time.Now() + } case <-qch: return } } } +// SetStarting sets our starting stream sequence. +func (o *consumerFileStore) SetStarting(sseq uint64) error { + o.mu.Lock() + o.state.Delivered.Stream = sseq + buf, err := o.encodeState() + o.mu.Unlock() + if err != nil { + return err + } + return o.writeState(buf) +} + +// UpdateStarting updates our starting stream sequence. +func (o *consumerFileStore) UpdateStarting(sseq uint64) { + o.mu.Lock() + defer o.mu.Unlock() + + if sseq > o.state.Delivered.Stream { + o.state.Delivered.Stream = sseq + // For AckNone just update delivered and ackfloor at the same time. + if o.cfg.AckPolicy == AckNone { + o.state.AckFloor.Stream = sseq + } + } + // Make sure we flush to disk. + o.kickFlusher() +} + +// HasState returns if this store has a recorded state. +func (o *consumerFileStore) HasState() bool { + o.mu.Lock() + // We have a running state, or stored on disk but not yet initialized. + if o.state.Delivered.Consumer != 0 || o.state.Delivered.Stream != 0 { + o.mu.Unlock() + return true + } + _, err := os.Stat(o.ifn) + o.mu.Unlock() + return err == nil +} + // UpdateDelivered is called whenever a new message has been delivered. func (o *consumerFileStore) UpdateDelivered(dseq, sseq, dc uint64, ts int64) error { o.mu.Lock() @@ -2971,6 +10954,11 @@ func (o *consumerFileStore) UpdateDelivered(dseq, sseq, dc uint64, ts int64) err return ErrNoAckPolicy } + // On restarts the old leader may get a replay from the raft logs that are old. + if dseq <= o.state.AckFloor.Consumer { + return nil + } + // See if we expect an ack for this. if o.cfg.AckPolicy != AckNone { // Need to create pending records here. @@ -2981,28 +10969,44 @@ func (o *consumerFileStore) UpdateDelivered(dseq, sseq, dc uint64, ts int64) err // Check for an update to a message already delivered. if sseq <= o.state.Delivered.Stream { if p = o.state.Pending[sseq]; p != nil { + // Do not update p.Sequence, that should be the original delivery sequence. p.Timestamp = ts } + } else { + // Add to pending. + o.state.Pending[sseq] = &Pending{dseq, ts} } - if p == nil { - // Move delivered if this is new. + // Update delivered as needed. + if dseq > o.state.Delivered.Consumer { o.state.Delivered.Consumer = dseq + } + if sseq > o.state.Delivered.Stream { o.state.Delivered.Stream = sseq - p = &Pending{dseq, ts} } + if dc > 1 { + if maxdc := uint64(o.cfg.MaxDeliver); maxdc > 0 && dc > maxdc { + // Make sure to remove from pending. + delete(o.state.Pending, sseq) + } if o.state.Redelivered == nil { o.state.Redelivered = make(map[uint64]uint64) } - o.state.Redelivered[sseq] = dc - 1 + // Only update if greater than what we already have. + if o.state.Redelivered[sseq] < dc-1 { + o.state.Redelivered[sseq] = dc - 1 + } } - o.state.Pending[sseq] = &Pending{dseq, ts} } else { // For AckNone just update delivered and ackfloor at the same time. - o.state.Delivered.Consumer = dseq - o.state.Delivered.Stream = sseq - o.state.AckFloor.Consumer = dseq - o.state.AckFloor.Stream = sseq + if dseq > o.state.Delivered.Consumer { + o.state.Delivered.Consumer = dseq + o.state.AckFloor.Consumer = dseq + } + if sseq > o.state.Delivered.Stream { + o.state.Delivered.Stream = sseq + o.state.AckFloor.Stream = sseq + } } // Make sure we flush to disk. o.kickFlusher() @@ -3018,33 +11022,57 @@ func (o *consumerFileStore) UpdateAcks(dseq, sseq uint64) error { if o.cfg.AckPolicy == AckNone { return ErrNoAckPolicy } - if len(o.state.Pending) == 0 { - return ErrStoreMsgNotFound + + // On restarts the old leader may get a replay from the raft logs that are old. + if dseq <= o.state.AckFloor.Consumer { + return nil } - p := o.state.Pending[sseq] - if p == nil { + + if len(o.state.Pending) == 0 || o.state.Pending[sseq] == nil { + delete(o.state.Redelivered, sseq) return ErrStoreMsgNotFound } - // Delete from our state. - delete(o.state.Pending, sseq) - if len(o.state.Redelivered) > 0 { - delete(o.state.Redelivered, sseq) - if len(o.state.Redelivered) == 0 { - o.state.Redelivered = nil + + // Check for AckAll here. + if o.cfg.AckPolicy == AckAll { + sgap := sseq - o.state.AckFloor.Stream + o.state.AckFloor.Consumer = dseq + o.state.AckFloor.Stream = sseq + if sgap > uint64(len(o.state.Pending)) { + for seq := range o.state.Pending { + if seq <= sseq { + delete(o.state.Pending, seq) + delete(o.state.Redelivered, seq) + } + } + } else { + for seq := sseq; seq > sseq-sgap && len(o.state.Pending) > 0; seq-- { + delete(o.state.Pending, seq) + delete(o.state.Redelivered, seq) + } } + o.kickFlusher() + return nil } + // AckExplicit + + // First delete from our pending state. + if p, ok := o.state.Pending[sseq]; ok { + delete(o.state.Pending, sseq) + if dseq > p.Sequence && p.Sequence > 0 { + dseq = p.Sequence // Use the original. + } + } if len(o.state.Pending) == 0 { - o.state.Pending = nil o.state.AckFloor.Consumer = o.state.Delivered.Consumer o.state.AckFloor.Stream = o.state.Delivered.Stream - } else if o.state.AckFloor.Consumer == dseq-1 { - notFirst := o.state.AckFloor.Consumer != 0 + } else if dseq == o.state.AckFloor.Consumer+1 { o.state.AckFloor.Consumer = dseq o.state.AckFloor.Stream = sseq - // Close the gap if needed. - if notFirst && o.state.Delivered.Consumer > dseq { - for ss := sseq + 1; ss < o.state.Delivered.Stream; ss++ { + + if o.state.Delivered.Consumer > dseq { + for ss := sseq + 1; ss <= o.state.Delivered.Stream; ss++ { if p, ok := o.state.Pending[ss]; ok { if p.Sequence > 0 { o.state.AckFloor.Consumer = p.Sequence - 1 @@ -3055,6 +11083,9 @@ func (o *consumerFileStore) UpdateAcks(dseq, sseq uint64) error { } } } + // We do these regardless. + delete(o.state.Redelivered, sseq) + o.kickFlusher() return nil } @@ -3063,79 +11094,35 @@ const seqsHdrSize = 6*binary.MaxVarintLen64 + hdrLen // Encode our consumer state, version 2. // Lock should be held. -func (o *consumerFileStore) encodeState() ([]byte, error) { - if o.closed { - return nil, ErrStoreClosed - } - - var hdr [seqsHdrSize]byte - var buf []byte - - maxSize := seqsHdrSize - if lp := len(o.state.Pending); lp > 0 { - maxSize += lp*(3*binary.MaxVarintLen64) + binary.MaxVarintLen64 - } - if lr := len(o.state.Redelivered); lr > 0 { - maxSize += lr*(2*binary.MaxVarintLen64) + binary.MaxVarintLen64 - } - if maxSize == seqsHdrSize { - buf = hdr[:seqsHdrSize] - } else { - buf = make([]byte, maxSize) - } - - now := time.Now() - - // Write header - buf[0] = magic - buf[1] = 2 - - n := hdrLen - n += binary.PutUvarint(buf[n:], o.state.AckFloor.Consumer) - n += binary.PutUvarint(buf[n:], o.state.AckFloor.Stream) - n += binary.PutUvarint(buf[n:], o.state.Delivered.Consumer) - n += binary.PutUvarint(buf[n:], o.state.Delivered.Stream) - n += binary.PutUvarint(buf[n:], uint64(len(o.state.Pending))) - asflr := o.state.AckFloor.Stream - adflr := o.state.AckFloor.Consumer - - // These are optional, but always write len. This is to avoid a truncate inline. - if len(o.state.Pending) > 0 { - // To save space we will use now rounded to seconds to be base timestamp. - mints := now.Round(time.Second).Unix() - // Write minimum timestamp we found from above. - n += binary.PutVarint(buf[n:], mints) +func (o *consumerFileStore) EncodedState() ([]byte, error) { + o.mu.Lock() + defer o.mu.Unlock() + return o.encodeState() +} - for k, v := range o.state.Pending { - n += binary.PutUvarint(buf[n:], k-asflr) - n += binary.PutUvarint(buf[n:], v.Sequence-adflr) - // Downsample to seconds to save on space. - // Subsecond resolution not needed for recovery etc. - ts := v.Timestamp / 1_000_000_000 - n += binary.PutVarint(buf[n:], mints-ts) - } +func (o *consumerFileStore) encodeState() ([]byte, error) { + // Grab reference to state, but make sure we load in if needed, so do not reference o.state directly. + state, err := o.stateWithCopyLocked(false) + if err != nil { + return nil, err } + return encodeConsumerState(state), nil +} - // We always write the redelivered len. - n += binary.PutUvarint(buf[n:], uint64(len(o.state.Redelivered))) +func (o *consumerFileStore) UpdateConfig(cfg *ConsumerConfig) error { + o.mu.Lock() + defer o.mu.Unlock() - // We expect these to be small. - if len(o.state.Redelivered) > 0 { - for k, v := range o.state.Redelivered { - n += binary.PutUvarint(buf[n:], k-asflr) - n += binary.PutUvarint(buf[n:], v) - } - } + // This is mostly unchecked here. We are assuming the upper layers have done sanity checking. + csi := o.cfg + csi.ConsumerConfig = *cfg - return buf[:n], nil + return o.writeConsumerMeta() } func (o *consumerFileStore) Update(state *ConsumerState) error { // Sanity checks. - if state.Delivered.Consumer < 1 || state.Delivered.Stream < 1 { - return fmt.Errorf("bad delivered sequences") - } if state.AckFloor.Consumer > state.Delivered.Consumer { return fmt.Errorf("bad ack floor for consumer") } @@ -3150,8 +11137,6 @@ func (o *consumerFileStore) Update(state *ConsumerState) error { pending = make(map[uint64]*Pending, len(state.Pending)) for seq, p := range state.Pending { pending[seq] = &Pending{p.Sequence, p.Timestamp} - } - for seq := range pending { if seq <= state.AckFloor.Stream || seq > state.Delivered.Stream { return fmt.Errorf("bad pending entry, sequence [%d] out of range", seq) } @@ -3166,16 +11151,62 @@ func (o *consumerFileStore) Update(state *ConsumerState) error { // Replace our state. o.mu.Lock() + defer o.mu.Unlock() + + // Check to see if this is an outdated update. + if state.Delivered.Consumer < o.state.Delivered.Consumer || state.AckFloor.Stream < o.state.AckFloor.Stream { + return fmt.Errorf("old update ignored") + } + o.state.Delivered = state.Delivered o.state.AckFloor = state.AckFloor o.state.Pending = pending o.state.Redelivered = redelivered - o.mu.Unlock() o.kickFlusher() + return nil } +// Will encrypt the state with our asset key. Will be a no-op if encryption not enabled. +// Lock should be held. +func (o *consumerFileStore) encryptState(buf []byte) ([]byte, error) { + if o.aek == nil { + return buf, nil + } + // TODO(dlc) - Optimize on space usage a bit? + nonce := make([]byte, o.aek.NonceSize(), o.aek.NonceSize()+len(buf)+o.aek.Overhead()) + if n, err := rand.Read(nonce); err != nil { + return nil, err + } else if n != len(nonce) { + return nil, fmt.Errorf("not enough nonce bytes read (%d != %d)", n, len(nonce)) + } + return o.aek.Seal(nonce, nonce, buf, nil), nil +} + +// Used to limit number of disk IO calls in flight since they could all be blocking an OS thread. +// https://github.com/nats-io/nats-server/issues/2742 +var dios chan struct{} + +// Used to setup our simplistic counting semaphore using buffered channels. +// golang.org's semaphore seemed a bit heavy. +func init() { + // Limit ourselves to a sensible number of blocking I/O calls. Range between + // 4-16 concurrent disk I/Os based on CPU cores, or 50% of cores if greater + // than 32 cores. + mp := runtime.GOMAXPROCS(-1) + nIO := min(16, max(4, mp)) + if mp > 32 { + // If the system has more than 32 cores then limit dios to 50% of cores. + nIO = max(16, min(mp, mp/2)) + } + dios = make(chan struct{}, nIO) + // Fill it up to start. + for i := 0; i < nIO; i++ { + dios <- struct{}{} + } +} + func (o *consumerFileStore) writeState(buf []byte) error { // Check if we have the index file open. o.mu.Lock() @@ -3183,19 +11214,26 @@ func (o *consumerFileStore) writeState(buf []byte) error { o.mu.Unlock() return nil } - if err := o.ensureStateFileOpen(); err != nil { - o.mu.Unlock() - return err + + // Check on encryption. + if o.aek != nil { + var err error + if buf, err = o.encryptState(buf); err != nil { + return err + } } + o.writing = true - ifd := o.ifd + o.dirty = false + ifn := o.ifn o.mu.Unlock() - n, err := ifd.WriteAt(buf, 0) + // Lock not held here but we do limit number of outstanding calls that could block OS threads. + err := o.fs.writeFileWithOptionalSync(ifn, buf, defaultFilePerms) o.mu.Lock() - if err == nil { - o.lwsz = int64(n) + if err != nil { + o.dirty = true } o.writing = false o.mu.Unlock() @@ -3214,59 +11252,63 @@ func (o *consumerFileStore) updateConfig(cfg ConsumerConfig) error { // Write out the consumer meta data, i.e. state. // Lock should be held. func (cfs *consumerFileStore) writeConsumerMeta() error { - meta := path.Join(cfs.odir, JetStreamMetaFile) - if _, err := os.Stat(meta); (err != nil && !os.IsNotExist(err)) || err == nil { + meta := filepath.Join(cfs.odir, JetStreamMetaFile) + if _, err := os.Stat(meta); err != nil && !os.IsNotExist(err) { return err } - b, err := json.MarshalIndent(cfs.cfg, _EMPTY_, " ") + + if cfs.prf != nil && cfs.aek == nil { + fs := cfs.fs + key, _, _, encrypted, err := fs.genEncryptionKeys(fs.cfg.Name + tsep + cfs.name) + if err != nil { + return err + } + cfs.aek = key + keyFile := filepath.Join(cfs.odir, JetStreamMetaFileKey) + if _, err := os.Stat(keyFile); err != nil && !os.IsNotExist(err) { + return err + } + err = cfs.fs.writeFileWithOptionalSync(keyFile, encrypted, defaultFilePerms) + if err != nil { + return err + } + } + + b, err := json.Marshal(cfs.cfg) if err != nil { return err } - if err := ioutil.WriteFile(meta, b, 0644); err != nil { + // Encrypt if needed. + if cfs.aek != nil { + nonce := make([]byte, cfs.aek.NonceSize(), cfs.aek.NonceSize()+len(b)+cfs.aek.Overhead()) + if n, err := rand.Read(nonce); err != nil { + return err + } else if n != len(nonce) { + return fmt.Errorf("not enough nonce bytes read (%d != %d)", n, len(nonce)) + } + b = cfs.aek.Seal(nonce, nonce, b, nil) + } + + err = cfs.fs.writeFileWithOptionalSync(meta, b, defaultFilePerms) + if err != nil { return err } cfs.hh.Reset() cfs.hh.Write(b) - checksum := hex.EncodeToString(cfs.hh.Sum(nil)) - sum := path.Join(cfs.odir, JetStreamMetaFileSum) - if err := ioutil.WriteFile(sum, []byte(checksum), 0644); err != nil { - return err - } - return nil -} - -func (o *consumerFileStore) syncStateFile() { - // FIXME(dlc) - Hold last error? - o.mu.Lock() - if o.ifd != nil { - o.ifd.Sync() - o.ifd.Truncate(o.lwsz) - } - o.mu.Unlock() -} - -// Lock should be held. -func (o *consumerFileStore) ensureStateFileOpen() error { - if o.ifd == nil { - ifd, err := os.OpenFile(o.ifn, os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - return err - } - o.ifd = ifd - } - return nil -} + var hb [highwayhash.Size64]byte + checksum := hex.EncodeToString(cfs.hh.Sum(hb[:0])) + sum := filepath.Join(cfs.odir, JetStreamMetaFileSum) -// Make sure the header is correct. -func checkHeader(hdr []byte) error { - if hdr == nil || len(hdr) < 2 || hdr[0] != magic || hdr[1] != version { - return errCorruptState + err = cfs.fs.writeFileWithOptionalSync(sum, []byte(checksum), defaultFilePerms) + if err != nil { + return err } return nil } +// Consumer version. func checkConsumerHeader(hdr []byte) (uint8, error) { - if hdr == nil || len(hdr) < 2 || hdr[0] != magic { + if len(hdr) < 2 || hdr[0] != magic { return 0, errCorruptState } version := hdr[1] @@ -3293,30 +11335,61 @@ func (o *consumerFileStore) copyRedelivered() map[uint64]uint64 { return redelivered } +// Type returns the type of the underlying store. +func (o *consumerFileStore) Type() StorageType { return FileStorage } + // State retrieves the state from the state file. // This is not expected to be called in high performance code, only on startup. func (o *consumerFileStore) State() (*ConsumerState, error) { + return o.stateWithCopy(true) +} + +// This will not copy pending or redelivered, so should only be done under the +// consumer owner's lock. +func (o *consumerFileStore) BorrowState() (*ConsumerState, error) { + return o.stateWithCopy(false) +} + +func (o *consumerFileStore) stateWithCopy(doCopy bool) (*ConsumerState, error) { o.mu.Lock() defer o.mu.Unlock() + return o.stateWithCopyLocked(doCopy) +} + +// Lock should be held. +func (o *consumerFileStore) stateWithCopyLocked(doCopy bool) (*ConsumerState, error) { + if o.closed { + return nil, ErrStoreClosed + } - var state *ConsumerState + state := &ConsumerState{} // See if we have a running state or if we need to read in from disk. - if o.state.Delivered.Consumer != 0 { - state = &ConsumerState{} + if o.state.Delivered.Consumer != 0 || o.state.Delivered.Stream != 0 { state.Delivered = o.state.Delivered state.AckFloor = o.state.AckFloor if len(o.state.Pending) > 0 { - state.Pending = o.copyPending() + if doCopy { + state.Pending = o.copyPending() + } else { + state.Pending = o.state.Pending + } } if len(o.state.Redelivered) > 0 { - state.Redelivered = o.copyRedelivered() + if doCopy { + state.Redelivered = o.copyRedelivered() + } else { + state.Redelivered = o.state.Redelivered + } } return state, nil } // Read the state in here from disk.. - buf, err := ioutil.ReadFile(o.ifn) + <-dios + buf, err := os.ReadFile(o.ifn) + dios <- struct{}{} + if err != nil && !os.IsNotExist(err) { return nil, err } @@ -3325,13 +11398,68 @@ func (o *consumerFileStore) State() (*ConsumerState, error) { return state, nil } + // Check on encryption. + if o.aek != nil { + ns := o.aek.NonceSize() + buf, err = o.aek.Open(nil, buf[:ns], buf[ns:], nil) + if err != nil { + return nil, err + } + } + + state, err = decodeConsumerState(buf) + if err != nil { + return nil, err + } + + // Copy this state into our own. + o.state.Delivered = state.Delivered + o.state.AckFloor = state.AckFloor + if len(state.Pending) > 0 { + if doCopy { + o.state.Pending = make(map[uint64]*Pending, len(state.Pending)) + for seq, p := range state.Pending { + o.state.Pending[seq] = &Pending{p.Sequence, p.Timestamp} + } + } else { + o.state.Pending = state.Pending + } + } + if len(state.Redelivered) > 0 { + if doCopy { + o.state.Redelivered = make(map[uint64]uint64, len(state.Redelivered)) + for seq, dc := range state.Redelivered { + o.state.Redelivered[seq] = dc + } + } else { + o.state.Redelivered = state.Redelivered + } + } + + return state, nil +} + +// Lock should be held. Called at startup. +func (o *consumerFileStore) loadState() error { + if _, err := os.Stat(o.ifn); err == nil { + // This will load our state in from disk. + _, err = o.stateWithCopyLocked(false) + return err + } else if os.IsNotExist(err) { + return nil + } else { + return err + } +} + +// Decode consumer state. +func decodeConsumerState(buf []byte) (*ConsumerState, error) { version, err := checkConsumerHeader(buf) if err != nil { return nil, err } bi := hdrLen - // Helpers, will set i to -1 on error. readSeq := func() uint64 { if bi < 0 { @@ -3361,7 +11489,7 @@ func (o *consumerFileStore) State() (*ConsumerState, error) { readLen := readSeq readCount := readSeq - state = &ConsumerState{} + state := &ConsumerState{} state.AckFloor.Consumer = readSeq() state.AckFloor.Stream = readSeq() state.Delivered.Consumer = readSeq() @@ -3373,14 +11501,22 @@ func (o *consumerFileStore) State() (*ConsumerState, error) { if version == 1 { // Adjust back. Version 1 also stored delivered as next to be delivered, // so adjust that back down here. - state.Delivered.Consumer += state.AckFloor.Consumer - 1 - state.Delivered.Stream += state.AckFloor.Stream - 1 + if state.AckFloor.Consumer > 1 { + state.Delivered.Consumer += state.AckFloor.Consumer - 1 + } + if state.AckFloor.Stream > 1 { + state.Delivered.Stream += state.AckFloor.Stream - 1 + } } - numPending := readLen() + // Protect ourselves against rolling backwards. + const hbit = 1 << 63 + if state.AckFloor.Stream&hbit != 0 || state.Delivered.Stream&hbit != 0 { + return nil, errCorruptState + } // We have additional stuff. - if numPending > 0 { + if numPending := readLen(); numPending > 0 { mints := readTimeStamp() state.Pending = make(map[uint64]*Pending, numPending) for i := 0; i < int(numPending); i++ { @@ -3390,11 +11526,15 @@ func (o *consumerFileStore) State() (*ConsumerState, error) { dseq = readSeq() } ts := readTimeStamp() - if sseq == 0 || ts == -1 { + // Check the state machine for corruption, not the value which could be -1. + if bi == -1 { return nil, errCorruptState } // Adjust seq back. sseq += state.AckFloor.Stream + if sseq == 0 { + return nil, errCorruptState + } if version == 2 { dseq += state.AckFloor.Consumer } @@ -3409,34 +11549,15 @@ func (o *consumerFileStore) State() (*ConsumerState, error) { } } - numRedelivered := readLen() - // We have redelivered entries here. - if numRedelivered > 0 { + if numRedelivered := readLen(); numRedelivered > 0 { state.Redelivered = make(map[uint64]uint64, numRedelivered) for i := 0; i < int(numRedelivered); i++ { - seq := readSeq() - n := readCount() - if seq == 0 || n == 0 { - return nil, errCorruptState + if seq, n := readSeq(), readCount(); seq > 0 && n > 0 { + // Adjust seq back. + seq += state.AckFloor.Stream + state.Redelivered[seq] = n } - state.Redelivered[seq] = n - } - } - - // Copy this state into our own. - o.state.Delivered = state.Delivered - o.state.AckFloor = state.AckFloor - if len(state.Pending) > 0 { - o.state.Pending = make(map[uint64]*Pending, len(state.Pending)) - for seq, p := range state.Pending { - o.state.Pending[seq] = &Pending{p.Sequence, p.Timestamp} - } - } - if len(state.Redelivered) > 0 { - o.state.Redelivered = make(map[uint64]uint64, len(state.Redelivered)) - for seq, dc := range state.Redelivered { - o.state.Redelivered[seq] = dc } } @@ -3455,36 +11576,59 @@ func (o *consumerFileStore) Stop() error { o.qch = nil } - err := o.ensureStateFileOpen() - ifd := o.ifd + var err error + var buf []byte - if err == nil { - var buf []byte + if o.dirty { // Make sure to write this out.. - if buf, err = o.encodeState(); err == nil { - _, err = ifd.WriteAt(buf, 0) + if buf, err = o.encodeState(); err == nil && len(buf) > 0 { + if o.aek != nil { + if buf, err = o.encryptState(buf); err != nil { + return err + } + } } } - o.ifd, o.odir = nil, _EMPTY_ - fs := o.fs + o.odir = _EMPTY_ o.closed = true - o.kickFlusher() + ifn, fs := o.ifn, o.fs o.mu.Unlock() - if ifd != nil { - ifd.Sync() - ifd.Close() - } + fs.RemoveConsumer(o) - fs.removeConsumer(o) + if len(buf) > 0 { + o.waitOnFlusher() + err = o.fs.writeFileWithOptionalSync(ifn, buf, defaultFilePerms) + } return err } +func (o *consumerFileStore) waitOnFlusher() { + if !o.inFlusher() { + return + } + + timeout := time.Now().Add(100 * time.Millisecond) + for time.Now().Before(timeout) { + if !o.inFlusher() { + return + } + time.Sleep(10 * time.Millisecond) + } +} + // Delete the consumer. func (o *consumerFileStore) Delete() error { - o.mu.Lock() + return o.delete(false) +} + +func (o *consumerFileStore) StreamDelete() error { + return o.delete(true) +} +func (o *consumerFileStore) delete(streamDeleted bool) error { + o.mu.Lock() if o.closed { o.mu.Unlock() return nil @@ -3494,32 +11638,44 @@ func (o *consumerFileStore) Delete() error { o.qch = nil } - if o.ifd != nil { - o.ifd.Close() - o.ifd = nil - } var err error - if o.odir != _EMPTY_ { - err = os.RemoveAll(o.odir) - } - o.ifd, o.odir = nil, _EMPTY_ + odir := o.odir + o.odir = _EMPTY_ o.closed = true fs := o.fs o.mu.Unlock() - fs.removeConsumer(o) + // If our stream was not deleted this will remove the directories. + if odir != _EMPTY_ && !streamDeleted { + <-dios + err = os.RemoveAll(odir) + dios <- struct{}{} + } + + if !streamDeleted { + fs.RemoveConsumer(o) + } + return err } -func (fs *fileStore) removeConsumer(cfs *consumerFileStore) { - fs.mu.Lock() - defer fs.mu.Unlock() - for i, o := range fs.cfs { +func (fs *fileStore) AddConsumer(o ConsumerStore) error { + fs.cmu.Lock() + defer fs.cmu.Unlock() + fs.cfs = append(fs.cfs, o) + return nil +} + +func (fs *fileStore) RemoveConsumer(o ConsumerStore) error { + fs.cmu.Lock() + defer fs.cmu.Unlock() + for i, cfs := range fs.cfs { if o == cfs { fs.cfs = append(fs.cfs[:i], fs.cfs[i+1:]...) break } } + return nil } //////////////////////////////////////////////////////////////////////////////// @@ -3528,48 +11684,202 @@ func (fs *fileStore) removeConsumer(cfs *consumerFileStore) { type templateFileStore struct { dir string - hh hash.Hash64 + hh *highwayhash.Digest64 } func newTemplateFileStore(storeDir string) *templateFileStore { - tdir := path.Join(storeDir, tmplsDir) + tdir := filepath.Join(storeDir, tmplsDir) key := sha256.Sum256([]byte("templates")) - hh, err := highwayhash.New64(key[:]) + hh, err := highwayhash.NewDigest64(key[:]) if err != nil { return nil } return &templateFileStore{dir: tdir, hh: hh} } -func (ts *templateFileStore) Store(t *StreamTemplate) error { - dir := path.Join(ts.dir, t.Name) - if err := os.MkdirAll(dir, 0755); err != nil { +func (ts *templateFileStore) Store(t *streamTemplate) error { + dir := filepath.Join(ts.dir, t.Name) + if err := os.MkdirAll(dir, defaultDirPerms); err != nil { return fmt.Errorf("could not create templates storage directory for %q- %v", t.Name, err) } - meta := path.Join(dir, JetStreamMetaFile) + meta := filepath.Join(dir, JetStreamMetaFile) if _, err := os.Stat(meta); (err != nil && !os.IsNotExist(err)) || err == nil { return err } t.mu.Lock() - b, err := json.MarshalIndent(t, _EMPTY_, " ") + b, err := json.Marshal(t) t.mu.Unlock() if err != nil { return err } - if err := ioutil.WriteFile(meta, b, 0644); err != nil { + if err := os.WriteFile(meta, b, defaultFilePerms); err != nil { return err } // FIXME(dlc) - Do checksum ts.hh.Reset() ts.hh.Write(b) - checksum := hex.EncodeToString(ts.hh.Sum(nil)) - sum := path.Join(dir, JetStreamMetaFileSum) - if err := ioutil.WriteFile(sum, []byte(checksum), 0644); err != nil { + var hb [highwayhash.Size64]byte + checksum := hex.EncodeToString(ts.hh.Sum(hb[:0])) + sum := filepath.Join(dir, JetStreamMetaFileSum) + if err := os.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil { return err } return nil } -func (ts *templateFileStore) Delete(t *StreamTemplate) error { - return os.RemoveAll(path.Join(ts.dir, t.Name)) +func (ts *templateFileStore) Delete(t *streamTemplate) error { + return os.RemoveAll(filepath.Join(ts.dir, t.Name)) +} + +//////////////////////////////////////////////////////////////////////////////// +// Compression +//////////////////////////////////////////////////////////////////////////////// + +type CompressionInfo struct { + Algorithm StoreCompression + OriginalSize uint64 +} + +func (c *CompressionInfo) MarshalMetadata() []byte { + b := make([]byte, 14) // 4 + potentially up to 10 for uint64 + b[0], b[1], b[2] = 'c', 'm', 'p' + b[3] = byte(c.Algorithm) + n := binary.PutUvarint(b[4:], c.OriginalSize) + return b[:4+n] +} + +func (c *CompressionInfo) UnmarshalMetadata(b []byte) (int, error) { + c.Algorithm = NoCompression + c.OriginalSize = 0 + if len(b) < 5 { // 4 + min 1 for uvarint uint64 + return 0, nil + } + if b[0] != 'c' || b[1] != 'm' || b[2] != 'p' { + return 0, nil + } + var n int + c.Algorithm = StoreCompression(b[3]) + c.OriginalSize, n = binary.Uvarint(b[4:]) + if n <= 0 { + return 0, fmt.Errorf("metadata incomplete") + } + return 4 + n, nil +} + +func (alg StoreCompression) Compress(buf []byte) ([]byte, error) { + if len(buf) < checksumSize { + return nil, fmt.Errorf("uncompressed buffer is too short") + } + bodyLen := int64(len(buf) - checksumSize) + var output bytes.Buffer + var writer io.WriteCloser + switch alg { + case NoCompression: + return buf, nil + case S2Compression: + writer = s2.NewWriter(&output) + default: + return nil, fmt.Errorf("compression algorithm not known") + } + + input := bytes.NewReader(buf[:bodyLen]) + checksum := buf[bodyLen:] + + // Compress the block content, but don't compress the checksum. + // We will preserve it at the end of the block as-is. + if n, err := io.CopyN(writer, input, bodyLen); err != nil { + return nil, fmt.Errorf("error writing to compression writer: %w", err) + } else if n != bodyLen { + return nil, fmt.Errorf("short write on body (%d != %d)", n, bodyLen) + } + if err := writer.Close(); err != nil { + return nil, fmt.Errorf("error closing compression writer: %w", err) + } + + // Now add the checksum back onto the end of the block. + if n, err := output.Write(checksum); err != nil { + return nil, fmt.Errorf("error writing checksum: %w", err) + } else if n != checksumSize { + return nil, fmt.Errorf("short write on checksum (%d != %d)", n, checksumSize) + } + + return output.Bytes(), nil +} + +func (alg StoreCompression) Decompress(buf []byte) ([]byte, error) { + if len(buf) < checksumSize { + return nil, fmt.Errorf("compressed buffer is too short") + } + bodyLen := int64(len(buf) - checksumSize) + input := bytes.NewReader(buf[:bodyLen]) + + var reader io.ReadCloser + switch alg { + case NoCompression: + return buf, nil + case S2Compression: + reader = io.NopCloser(s2.NewReader(input)) + default: + return nil, fmt.Errorf("compression algorithm not known") + } + + // Decompress the block content. The checksum isn't compressed so + // we can preserve it from the end of the block as-is. + checksum := buf[bodyLen:] + output, err := io.ReadAll(reader) + if err != nil { + return nil, fmt.Errorf("error reading compression reader: %w", err) + } + output = append(output, checksum...) + + return output, reader.Close() +} + +// writeFileWithOptionalSync is equivalent to os.WriteFile() but optionally +// sets O_SYNC on the open file if SyncAlways is set. The dios semaphore is +// handled automatically by this function, so don't wrap calls to it in dios. +func (fs *fileStore) writeFileWithOptionalSync(name string, data []byte, perm fs.FileMode) error { + return writeAtomically(name, data, perm, fs.fcfg.SyncAlways) +} + +func writeFileWithSync(name string, data []byte, perm fs.FileMode) error { + return writeAtomically(name, data, perm, true) +} + +func writeAtomically(name string, data []byte, perm fs.FileMode, sync bool) error { + tmp := name + ".tmp" + flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC + if sync { + flags = flags | os.O_SYNC + } + <-dios + defer func() { + dios <- struct{}{} + }() + f, err := os.OpenFile(tmp, flags, perm) + if err != nil { + return err + } + if _, err := f.Write(data); err != nil { + _ = f.Close() + _ = os.Remove(tmp) + return err + } + if err := f.Close(); err != nil { + _ = os.Remove(tmp) + return err + } + if err := os.Rename(tmp, name); err != nil { + _ = os.Remove(tmp) + return err + } + if sync { + // To ensure that the file rename was persisted on all filesystems, + // also try to flush the directory metadata. + if d, err := os.Open(filepath.Dir(name)); err == nil { + _ = d.Sync() + _ = d.Close() + } + } + return nil } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/gateway.go b/vendor/github.com/nats-io/nats-server/v2/server/gateway.go index 5f7a290..550d1cc 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/gateway.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/gateway.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The NATS Authors +// Copyright 2018-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,16 +15,18 @@ package server import ( "bytes" + "cmp" "crypto/sha256" "crypto/tls" - "crypto/x509" "encoding/json" + "errors" "fmt" "math/rand" "net" "net/url" - "sort" + "slices" "strconv" + "strings" "sync" "sync/atomic" "time" @@ -34,7 +36,7 @@ const ( defaultSolicitGatewaysDelay = time.Second defaultGatewayConnectDelay = time.Second defaultGatewayReconnectDelay = time.Second - defaultGatewayRecentSubExpiration = 250 * time.Millisecond + defaultGatewayRecentSubExpiration = 2 * time.Second defaultGatewayMaxRUnsubBeforeSwitch = 1000 oldGWReplyPrefix = "$GR." @@ -119,6 +121,14 @@ func (im GatewayInterestMode) String() string { } } +var gwDoNotForceInterestOnlyMode bool + +// GatewayDoNotForceInterestOnlyMode is used ONLY in tests. +// DO NOT USE in normal code or if you embed the NATS Server. +func GatewayDoNotForceInterestOnlyMode(doNotForce bool) { + gwDoNotForceInterestOnlyMode = doNotForce +} + type srvGateway struct { totalQSubs int64 //total number of queue subs in all remote gateways (used with atomic operations) sync.RWMutex @@ -155,12 +165,21 @@ type srvGateway struct { m map[string]map[string]*sitally } - // This is to track recent subscriptions for a given connection + // This is to track recent subscriptions for a given account rsubs sync.Map resolver netResolver // Used to resolve host name before calling net.Dial() sqbsz int // Max buffer size to send queue subs protocol. Used for testing. recSubExp time.Duration // For how long do we check if there is a subscription match for a message with reply + + // These are used for routing of mapped replies. + sIDHash []byte // Server ID hash (6 bytes) + routesIDByHash sync.Map // Route's server ID is hashed (6 bytes) and stored in this map. + + // If a server has its own configuration in the "Gateways" remotes configuration + // we will keep track of the URLs that are defined in the config so they can + // be reported in monitoring. + ownCfgURLs []string } // Subject interest tally. Also indicates if the key in the map is a @@ -185,16 +204,23 @@ type gatewayCfg struct { // Struct for client's gateway related fields type gateway struct { name string - outbound bool cfg *gatewayCfg connectURL *url.URL // Needed when sending CONNECT after receiving INFO from remote outsim *sync.Map // Per-account subject interest (or no-interest) (outbound conn) insim map[string]*insie // Per-account subject no-interest sent or modeInterestOnly mode (inbound conn) + // This is an outbound GW connection + outbound bool // Set/check in readLoop without lock. This is to know that an inbound has sent the CONNECT protocol first connected bool // Set to true if outbound is to a server that only knows about $GR, not $GNR useOldPrefix bool + // If true, it indicates that the inbound side will switch any account to + // interest-only mode "immediately", so the outbound should disregard + // the optimistic mode when checking for interest. + interestOnlyMode bool + // Name of the remote server + remoteName string } // Outbound subject interest entry. @@ -235,6 +261,29 @@ type gwReplyMap struct { exp int64 } +type gwReplyMapping struct { + // Indicate if we should check the map or not. Since checking the map is done + // when processing inbound messages and requires the lock we want to + // check only when needed. This is set/get using atomic, so needs to + // be memory aligned. + check int32 + // To keep track of gateway replies mapping + mapping map[string]*gwReplyMap +} + +// Returns the corresponding gw routed subject, and `true` to indicate that a +// mapping was found. If no entry is found, the passed subject is returned +// as-is and `false` is returned to indicate that no mapping was found. +// Caller is responsible to ensure the locking. +func (g *gwReplyMapping) get(subject []byte) ([]byte, bool) { + rm, ok := g.mapping[string(subject)] + if !ok { + return subject, false + } + subj := []byte(rm.ms) + return subj, true +} + // clone returns a deep copy of the RemoteGatewayOpts object func (r *RemoteGatewayOpts) clone() *RemoteGatewayOpts { if r == nil { @@ -253,36 +302,36 @@ func (r *RemoteGatewayOpts) clone() *RemoteGatewayOpts { // Ensure that gateway is properly configured. func validateGatewayOptions(o *Options) error { - if o.Gateway.Name == "" && o.Gateway.Port == 0 { + if o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 { return nil } - if o.Gateway.Name == "" { - return fmt.Errorf("gateway has no name") + if o.Gateway.Name == _EMPTY_ { + return errors.New("gateway has no name") + } + if strings.Contains(o.Gateway.Name, " ") { + return ErrGatewayNameHasSpaces } if o.Gateway.Port == 0 { return fmt.Errorf("gateway %q has no port specified (select -1 for random port)", o.Gateway.Name) } for i, g := range o.Gateway.Gateways { - if g.Name == "" { + if g.Name == _EMPTY_ { return fmt.Errorf("gateway in the list %d has no name", i) } if len(g.URLs) == 0 { return fmt.Errorf("gateway %q has no URL", g.Name) } } + if err := validatePinnedCerts(o.Gateway.TLSPinnedCerts); err != nil { + return fmt.Errorf("gateway %q: %v", o.Gateway.Name, err) + } return nil } -// Computes a hash of 8 characters for the name. +// Computes a hash of 6 characters for the name. // This will be used for routing of replies. -func getHash(name string) []byte { - sha := sha256.New() - sha.Write([]byte(name)) - b := sha.Sum(nil) - for i := 0; i < gwHashLen; i++ { - b[i] = digits[int(b[i]%base)] - } - return b[:gwHashLen] +func getGWHash(name string) []byte { + return []byte(getHashSize(name, gwHashLen)) } func getOldHash(name string) []byte { @@ -311,13 +360,13 @@ func (s *Server) newGateway(opts *Options) error { gateway.Lock() defer gateway.Unlock() - s.hash = getHash(s.info.ID) - clusterHash := getHash(opts.Gateway.Name) + gateway.sIDHash = getGWHash(s.info.ID) + clusterHash := getGWHash(opts.Gateway.Name) prefix := make([]byte, 0, gwSubjectOffset) prefix = append(prefix, gwReplyPrefix...) prefix = append(prefix, clusterHash...) prefix = append(prefix, '.') - prefix = append(prefix, s.hash...) + prefix = append(prefix, gateway.sIDHash...) prefix = append(prefix, '.') gateway.replyPfx = prefix @@ -337,11 +386,12 @@ func (s *Server) newGateway(opts *Options) error { for _, rgo := range opts.Gateway.Gateways { // Ignore if there is a remote gateway with our name. if rgo.Name == gateway.name { + gateway.ownCfgURLs = getURLsAsString(rgo.URLs) continue } cfg := &gatewayCfg{ RemoteGatewayOpts: rgo.clone(), - hash: getHash(rgo.Name), + hash: getGWHash(rgo.Name), oldHash: getOldHash(rgo.Name), urls: make(map[string]*url.URL, len(rgo.URLs)), } @@ -370,12 +420,53 @@ func (s *Server) newGateway(opts *Options) error { return nil } -// Returns the Gateway's name of this server. -func (g *srvGateway) getName() string { - g.RLock() - n := g.name - g.RUnlock() - return n +// Update remote gateways TLS configurations after a config reload. +func (g *srvGateway) updateRemotesTLSConfig(opts *Options) { + g.Lock() + defer g.Unlock() + // Instead of going over opts.Gateway.Gateways, which would include only + // explicit remotes, we are going to go through g.remotes. + for name, cfg := range g.remotes { + if name == g.name { + continue + } + var ro *RemoteGatewayOpts + // We now need to go back and find the RemoteGatewayOpts but only if + // this remote is explicit (otherwise it won't be found). + if !cfg.isImplicit() { + for _, r := range opts.Gateway.Gateways { + if r.Name == name { + ro = r + break + } + } + } + cfg.Lock() + // If we have an `ro` (that means an explicitly defined remote gateway) + // and it has an explicit TLS config, use that one, otherwise (no explicit + // TLS config in the remote, or implicit remote), use the TLS config from + // the main block. + if ro != nil && ro.TLSConfig != nil { + cfg.TLSConfig = ro.TLSConfig.Clone() + } else if opts.Gateway.TLSConfig != nil { + cfg.TLSConfig = opts.Gateway.TLSConfig.Clone() + } + // Ensure that OCSP callbacks are always setup after a reload if needed. + mustStaple := opts.OCSPConfig != nil && opts.OCSPConfig.Mode == OCSPModeAlways + if mustStaple && opts.Gateway.TLSConfig != nil { + clientCB := opts.Gateway.TLSConfig.GetClientCertificate + verifyCB := opts.Gateway.TLSConfig.VerifyConnection + if mustStaple && cfg.TLSConfig != nil { + if clientCB != nil && cfg.TLSConfig.GetClientCertificate == nil { + cfg.TLSConfig.GetClientCertificate = clientCB + } + if verifyCB != nil && cfg.TLSConfig.VerifyConnection == nil { + cfg.TLSConfig.VerifyConnection = verifyCB + } + } + } + cfg.Unlock() + } } // Returns if this server rejects connections from gateways that are not @@ -416,6 +507,10 @@ func (s *Server) startGateways() { // This starts the gateway accept loop in a go routine, unless it // is detected that the server has already been shutdown. func (s *Server) startGatewayAcceptLoop() { + if s.isShuttingDown() { + return + } + // Snapshot server options. opts := s.getOpts() @@ -425,12 +520,9 @@ func (s *Server) startGatewayAcceptLoop() { } s.mu.Lock() - if s.shutdown { - s.mu.Unlock() - return - } hp := net.JoinHostPort(opts.Gateway.Host, strconv.Itoa(port)) l, e := natsListen("tcp", hp) + s.gatewayListenerErr = e if e != nil { s.mu.Unlock() s.Fatalf("Error listening on gateway port: %d - %v", opts.Gateway.Port, e) @@ -453,7 +545,16 @@ func (s *Server) startGatewayAcceptLoop() { Gateway: opts.Gateway.Name, GatewayNRP: true, Headers: s.supportsHeaders(), + Proto: s.getServerProto(), } + // Unless in some tests we want to keep the old behavior, we are now + // (since v2.9.0) indicate that this server will switch all accounts + // to InterestOnly mode when accepting an inbound or when a new + // account is fetched. + if !gwDoNotForceInterestOnlyMode { + info.GatewayIOM = true + } + // If we have selected a random port... if port == 0 { // Write resolved port back to options. @@ -547,7 +648,7 @@ func (g *srvGateway) generateInfoJSON() { // We could be here when processing a route INFO that has a gateway URL, // but this server is not configured for gateways, so simply ignore here. // The configuration mismatch is reported somewhere else. - if !g.enabled { + if !g.enabled || g.info == nil { return } g.info.GatewayURLs = g.URLs.getAsStringSlice() @@ -656,7 +757,7 @@ func (s *Server) solicitGateway(cfg *gatewayCfg, firstConnect bool) { s.gateway.Lock() // We could have just accepted an inbound for this remote gateway. // So if there is an inbound, let's try again to connect. - if len(s.gateway.in) > 0 { + if s.gateway.hasInbound(cfg.Name) { s.gateway.Unlock() continue } @@ -674,6 +775,20 @@ func (s *Server) solicitGateway(cfg *gatewayCfg, firstConnect bool) { } } +// Returns true if there is an inbound for the given `name`. +// Lock held on entry. +func (g *srvGateway) hasInbound(name string) bool { + for _, ig := range g.in { + ig.mu.Lock() + igname := ig.gw.name + ig.mu.Unlock() + if igname == name { + return true + } + } + return false +} + // Called when a gateway connection is either accepted or solicited. // If accepted, the gateway is marked as inbound. // If solicited, the gateway is marked as outbound. @@ -687,11 +802,6 @@ func (s *Server) createGateway(cfg *gatewayCfg, url *url.URL, conn net.Conn) { // Are we creating the gateway based on the configuration solicit := cfg != nil var tlsRequired bool - if solicit { - tlsRequired = cfg.TLSConfig != nil - } else { - tlsRequired = opts.Gateway.TLSConfig != nil - } s.gateway.RLock() infoJSON := s.gateway.infoJSON @@ -703,86 +813,78 @@ func (s *Server) createGateway(cfg *gatewayCfg, url *url.URL, conn net.Conn) { c.gw = &gateway{} if solicit { // This is an outbound gateway connection + cfg.RLock() + tlsRequired = cfg.TLSConfig != nil + cfgName := cfg.Name + cfg.RUnlock() c.gw.outbound = true - c.gw.name = cfg.Name + c.gw.name = cfgName c.gw.cfg = cfg cfg.bumpConnAttempts() // Since we are delaying the connect until after receiving // the remote's INFO protocol, save the URL we need to connect to. c.gw.connectURL = url - c.Noticef("Creating outbound gateway connection to %q", cfg.Name) + c.Noticef("Creating outbound gateway connection to %q", cfgName) } else { c.flags.set(expectConnect) // Inbound gateway connection c.Noticef("Processing inbound gateway connection") + // Check if TLS is required for inbound GW connections. + tlsRequired = opts.Gateway.TLSConfig != nil + // We expect a CONNECT from the accepted connection. + c.setAuthTimer(secondsToDuration(opts.Gateway.AuthTimeout)) } // Check for TLS if tlsRequired { - var host string + var tlsConfig *tls.Config + var tlsName string var timeout float64 - // If we solicited, we will act like the client, otherwise the server. + if solicit { - c.Debugf("Starting TLS gateway client handshake") + var ( + mustStaple = opts.OCSPConfig != nil && opts.OCSPConfig.Mode == OCSPModeAlways + clientCB func(*tls.CertificateRequestInfo) (*tls.Certificate, error) + verifyCB func(tls.ConnectionState) error + ) + // Snapshot callbacks for OCSP outside an ongoing reload which might be happening. + if mustStaple { + s.reloadMu.RLock() + s.optsMu.RLock() + clientCB = s.opts.Gateway.TLSConfig.GetClientCertificate + verifyCB = s.opts.Gateway.TLSConfig.VerifyConnection + s.optsMu.RUnlock() + s.reloadMu.RUnlock() + } + cfg.RLock() - tlsName := cfg.tlsName - tlsConfig := cfg.TLSConfig.Clone() + tlsName = cfg.tlsName + tlsConfig = cfg.TLSConfig.Clone() timeout = cfg.TLSTimeout - cfg.RUnlock() - if tlsConfig.ServerName == "" { - // If the given url is a hostname, use this hostname for the - // ServerName. If it is an IP, use the cfg's tlsName. If none - // is available, resort to current IP. - host = url.Hostname() - if tlsName != "" && net.ParseIP(host) != nil { - host = tlsName + + // Ensure that OCSP callbacks are always setup on gateway reconnect when OCSP policy is set to always. + if mustStaple { + if clientCB != nil && tlsConfig.GetClientCertificate == nil { + tlsConfig.GetClientCertificate = clientCB + } + if verifyCB != nil && tlsConfig.VerifyConnection == nil { + tlsConfig.VerifyConnection = verifyCB } - tlsConfig.ServerName = host } - c.nc = tls.Client(c.nc, tlsConfig) + cfg.RUnlock() } else { - c.Debugf("Starting TLS gateway server handshake") - c.nc = tls.Server(c.nc, opts.Gateway.TLSConfig) + tlsConfig = opts.Gateway.TLSConfig timeout = opts.Gateway.TLSTimeout } - conn := c.nc.(*tls.Conn) - - // Setup the timeout - ttl := secondsToDuration(timeout) - time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) - conn.SetReadDeadline(time.Now().Add(ttl)) - - c.mu.Unlock() - if err := conn.Handshake(); err != nil { - if solicit { - // Based on type of error, possibly clear the saved tlsName - // See: https://github.com/nats-io/nats-server/issues/1256 - if _, ok := err.(x509.HostnameError); ok { - cfg.Lock() - if host == cfg.tlsName { - cfg.tlsName = "" - } - cfg.Unlock() - } + // Perform (either server or client side) TLS handshake. + if resetTLSName, err := c.doTLSHandshake("gateway", solicit, url, tlsConfig, tlsName, timeout, opts.Gateway.TLSPinnedCerts); err != nil { + if resetTLSName { + cfg.Lock() + cfg.tlsName = _EMPTY_ + cfg.Unlock() } - c.Errorf("TLS gateway handshake error: %v", err) - c.sendErr("Secure Connection - TLS Required") - c.closeConnection(TLSHandshakeError) - return - } - // Reset the read deadline - conn.SetReadDeadline(time.Time{}) - - // Re-Grab lock - c.mu.Lock() - - // To be consistent with client, set this flag to indicate that handshake is done - c.flags.set(handshakeComplete) - - // Verify that the connection did not go away while we released the lock. - if c.isClosed() { c.mu.Unlock() return } @@ -824,14 +926,27 @@ func (s *Server) createGateway(cfg *gatewayCfg, url *url.URL, conn net.Conn) { c.Debugf("TLS version %s, cipher suite %s", tlsVersion(cs.Version), tlsCipher(cs.CipherSuite)) } - // Set the Ping timer after sending connect and info. - s.setFirstPingTimer(c) + // For outbound, we can't set the normal ping timer yet since the other + // side would fail with a parse error should it receive anything but the + // CONNECT protocol as the first protocol. We still want to make sure + // that the connection is not stale until the first INFO from the remote + // is received. + if solicit { + c.watchForStaleConnection(adjustPingInterval(GATEWAY, opts.PingInterval), opts.MaxPingsOut) + } c.mu.Unlock() + + // Announce ourselves again to new connections. + if solicit && s.EventsEnabled() { + s.sendStatszUpdate() + } } // Builds and sends the CONNECT protocol for a gateway. -func (c *client) sendGatewayConnect() { +// Client lock held on entry. +func (c *client) sendGatewayConnect(opts *Options) { + // FIXME: This can race with updateRemotesTLSConfig tlsRequired := c.gw.cfg.TLSConfig != nil url := c.gw.connectURL c.gw.connectURL = nil @@ -839,6 +954,9 @@ func (c *client) sendGatewayConnect() { if userInfo := url.User; userInfo != nil { user = userInfo.Username() pass, _ = userInfo.Password() + } else if opts != nil { + user = opts.Gateway.Username + pass = opts.Gateway.Password } cinfo := connectInfo{ Verbose: false, @@ -847,7 +965,7 @@ func (c *client) sendGatewayConnect() { Pass: pass, TLS: tlsRequired, Name: c.srv.info.ID, - Gateway: c.srv.getGatewayName(), + Gateway: c.srv.gateway.name, } b, err := json.Marshal(cinfo) if err != nil { @@ -888,14 +1006,11 @@ func (c *client) processGatewayConnect(arg []byte) error { return ErrWrongGateway } - // For a gateway connection, c.gw is guaranteed not to be nil here - // (created in createGateway() and never set to nil). - // For inbound connections, it is important to know in the parser - // if the CONNECT was received first, so we use this boolean (as - // opposed to client.flags that require locking) to indicate that - // CONNECT was processed. Again, this boolean is set/read in the - // readLoop without locking. + c.mu.Lock() c.gw.connected = true + // Set the Ping timer after sending connect and info. + c.setFirstPingTimer() + c.mu.Unlock() return nil } @@ -938,6 +1053,10 @@ func (c *client) processGatewayInfo(info *Info) { } if isFirstINFO { c.opts.Name = info.ID + // Get the protocol version from the INFO protocol. This will be checked + // to see if this connection supports message tracing for instance. + c.opts.Protocol = info.Proto + c.gw.remoteName = info.Name } c.mu.Unlock() @@ -976,6 +1095,13 @@ func (c *client) processGatewayInfo(info *Info) { return } + // Check for duplicate server name with servers in our cluster + if s.isDuplicateServerName(info.Name) { + c.Errorf("Remote server has a duplicate name: %q", info.Name) + c.closeConnection(DuplicateServerName) + return + } + // Possibly add URLs that we get from the INFO protocol. if len(info.GatewayURLs) > 0 { cfg.updateURLs(info.GatewayURLs) @@ -988,12 +1114,14 @@ func (c *client) processGatewayInfo(info *Info) { s.gateway.RUnlock() supportsHeaders := s.supportsHeaders() + opts := s.getOpts() // Note, if we want to support NKeys, then we would get the nonce // from this INFO protocol and can sign it in the CONNECT we are // going to send now. c.mu.Lock() - c.sendGatewayConnect() + c.gw.interestOnlyMode = info.GatewayIOM + c.sendGatewayConnect(opts) c.Debugf("Gateway connect protocol sent to %q", gwName) // Send INFO too c.enqueueProto(infoJSON) @@ -1007,6 +1135,10 @@ func (c *client) processGatewayInfo(info *Info) { c.Noticef("Outbound gateway connection to %q (%s) registered", gwName, info.ID) // Now that the outbound gateway is registered, we can remove from temp map. s.removeFromTempClients(cid) + // Set the Ping timer after sending connect and info. + c.mu.Lock() + c.setFirstPingTimer() + c.mu.Unlock() } else { // There was a bug that would cause a connection to possibly // be called twice resulting in reconnection of twice the @@ -1042,6 +1174,13 @@ func (c *client) processGatewayInfo(info *Info) { } else if isFirstINFO { // This is the first INFO of an inbound connection... + // Check for duplicate server name with servers in our cluster + if s.isDuplicateServerName(info.Name) { + c.Errorf("Remote server has a duplicate name: %q", info.Name) + c.closeConnection(DuplicateServerName) + return + } + s.registerInboundGatewayConnection(cid, c) c.Noticef("Inbound gateway connection from %q (%s) registered", info.Gateway, info.ID) @@ -1064,6 +1203,37 @@ func (c *client) processGatewayInfo(info *Info) { s.mu.Lock() s.ensureGWsInterestOnlyForLeafNodes() s.mu.Unlock() + js := s.js.Load() + + // If running in some tests, maintain the original behavior. + if gwDoNotForceInterestOnlyMode && js != nil { + // Switch JetStream accounts to interest-only mode. + var accounts []string + js.mu.Lock() + if len(js.accounts) > 0 { + accounts = make([]string, 0, len(js.accounts)) + for accName := range js.accounts { + accounts = append(accounts, accName) + } + } + js.mu.Unlock() + for _, accName := range accounts { + if acc, err := s.LookupAccount(accName); err == nil && acc != nil { + if acc.JetStreamEnabled() { + s.switchAccountToInterestMode(acc.GetName()) + } + } + } + } else if !gwDoNotForceInterestOnlyMode { + // Starting 2.9.0, we are phasing out the optimistic mode, so change + // all accounts to interest-only mode, unless instructed not to do so + // in some tests. + s.accounts.Range(func(_, v any) bool { + acc := v.(*Account) + s.switchAccountToInterestMode(acc.GetName()) + return true + }) + } } } @@ -1117,11 +1287,11 @@ func (s *Server) forwardNewGatewayToLocalCluster(oinfo *Info) { b, _ := json.Marshal(info) infoJSON := []byte(fmt.Sprintf(InfoProto, b)) - for _, r := range s.routes { + s.forEachRemote(func(r *client) { r.mu.Lock() r.enqueueProto(infoJSON) r.mu.Unlock() - } + }) } // Sends queue subscriptions interest to remote gateway. @@ -1129,22 +1299,22 @@ func (s *Server) forwardNewGatewayToLocalCluster(oinfo *Info) { // messages from the remote's outbound connection. This side is // the one sending the subscription interest. func (s *Server) sendQueueSubsToGateway(c *client) { - s.sendSubsToGateway(c, nil) + s.sendSubsToGateway(c, _EMPTY_) } // Sends all subscriptions for the given account to the remove gateway // This is sent from the inbound side, that is, the side that receives // messages from the remote's outbound connection. This side is // the one sending the subscription interest. -func (s *Server) sendAccountSubsToGateway(c *client, accName []byte) { +func (s *Server) sendAccountSubsToGateway(c *client, accName string) { s.sendSubsToGateway(c, accName) } -func gwBuildSubProto(buf *bytes.Buffer, accName []byte, acc map[string]*sitally, doQueues bool) { +func gwBuildSubProto(buf *bytes.Buffer, accName string, acc map[string]*sitally, doQueues bool) { for saq, si := range acc { if doQueues && si.q || !doQueues && !si.q { buf.Write(rSubBytes) - buf.Write(accName) + buf.WriteString(accName) buf.WriteByte(' ') // For queue subs (si.q is true), saq will be // subject + ' ' + queue, for plain subs, this is @@ -1159,7 +1329,7 @@ func gwBuildSubProto(buf *bytes.Buffer, accName []byte, acc map[string]*sitally, } // Sends subscriptions to remote gateway. -func (s *Server) sendSubsToGateway(c *client, accountName []byte) { +func (s *Server) sendSubsToGateway(c *client, accountName string) { var ( bufa = [32 * 1024]byte{} bbuf = bytes.NewBuffer(bufa[:0]) @@ -1172,22 +1342,22 @@ func (s *Server) sendSubsToGateway(c *client, accountName []byte) { defer gw.pasi.Unlock() // If account is specified... - if accountName != nil { + if accountName != _EMPTY_ { // Simply send all plain subs (no queues) for this specific account - gwBuildSubProto(bbuf, accountName, gw.pasi.m[string(accountName)], false) + gwBuildSubProto(bbuf, accountName, gw.pasi.m[accountName], false) // Instruct to send all subs (RS+/-) for this account from now on. c.mu.Lock() - e := c.gw.insim[string(accountName)] + e := c.gw.insim[accountName] if e == nil { e = &insie{} - c.gw.insim[string(accountName)] = e + c.gw.insim[accountName] = e } e.mode = InterestOnly c.mu.Unlock() } else { // Send queues for all accounts for accName, acc := range gw.pasi.m { - gwBuildSubProto(bbuf, []byte(accName), acc, true) + gwBuildSubProto(bbuf, accName, acc, true) } } @@ -1211,7 +1381,7 @@ func (s *Server) sendSubsToGateway(c *client, accountName []byte) { // This function will then execute appropriate function based on the command // contained in the protocol. // -func (s *Server) processGatewayInfoFromRoute(info *Info, routeSrvID string, route *client) { +func (s *Server) processGatewayInfoFromRoute(info *Info, routeSrvID string) { switch info.GatewayCmd { case gatewayCmdGossip: s.processImplicitGateway(info) @@ -1222,7 +1392,7 @@ func (s *Server) processGatewayInfoFromRoute(info *Info, routeSrvID string, rout // Sends INFO protocols to the given route connection for each known Gateway. // These will be processed by the route and delegated to the gateway code to -// imvoke processImplicitGateway. +// invoke processImplicitGateway. func (s *Server) sendGatewayConfigsToRoute(route *client) { gw := s.gateway gw.RLock() @@ -1292,7 +1462,7 @@ func (s *Server) processImplicitGateway(info *Info) { opts := s.getOpts() cfg = &gatewayCfg{ RemoteGatewayOpts: &RemoteGatewayOpts{Name: gwName}, - hash: getHash(gwName), + hash: getGWHash(gwName), oldHash: getOldHash(gwName), urls: make(map[string]*url.URL, len(info.GatewayURLs)), implicit: true, @@ -1415,6 +1585,13 @@ func (g *gatewayCfg) updateURLs(infoURLs []string) { } // Then add the ones from the infoURLs array we got. g.addURLs(infoURLs) + // The call above will set varzUpdateURLs only when finding ULRs in infoURLs + // that are not present in the config. That does not cover the case where + // previously "discovered" URLs are now gone. We could check "before" size + // of g.urls and if bigger than current size, set the boolean to true. + // Not worth it... simply set this to true to allow a refresh of gateway + // URLs in varz. + g.varzUpdateURLs = true g.Unlock() } @@ -1472,7 +1649,7 @@ func (s *Server) addGatewayURL(urlStr string) bool { // Returns true if the URL has been removed, false otherwise. // Server lock held on entry func (s *Server) removeGatewayURL(urlStr string) bool { - if s.shutdown { + if s.isShuttingDown() { return false } s.gateway.Lock() @@ -1508,7 +1685,8 @@ func (s *Server) getGatewayURL() string { // Returns this server gateway name. // Same than calling s.gateway.getName() func (s *Server) getGatewayName() string { - return s.gateway.getName() + // This is immutable + return s.gateway.name } // All gateway connections (outbound and inbound) are put in the given map. @@ -1575,9 +1753,7 @@ func (s *Server) getOutboundGatewayConnections(a *[]*client) { // Gateway write lock is held on entry func (g *srvGateway) orderOutboundConnectionsLocked() { // Order the gateways by lowest RTT - sort.Slice(g.outo, func(i, j int) bool { - return g.outo[i].getRTTValue() < g.outo[j].getRTTValue() - }) + slices.SortFunc(g.outo, func(i, j *client) int { return cmp.Compare(i.getRTTValue(), j.getRTTValue()) }) } // Orders the array of outbound connections. @@ -1604,6 +1780,15 @@ func (s *Server) removeRemoteGatewayConnection(c *client) { cid := c.cid isOutbound := c.gw.outbound gwName := c.gw.name + if isOutbound && c.gw.outsim != nil { + // We do this to allow the GC to release this connection. + // Since the map is used by the rest of the code without client lock, + // we can't simply set it to nil, instead, just make sure we empty it. + c.gw.outsim.Range(func(k, _ any) bool { + c.gw.outsim.Delete(k) + return true + }) + } c.mu.Unlock() gw := s.gateway @@ -1640,6 +1825,7 @@ func (s *Server) removeRemoteGatewayConnection(c *client) { qSubsRemoved++ } } + c.subs = nil c.mu.Unlock() // Update total count of qsubs in remote gateways. atomic.AddInt64(&c.srv.gateway.totalQSubs, -qSubsRemoved) @@ -1654,6 +1840,7 @@ func (s *Server) removeRemoteGatewayConnection(c *client) { for _, sub := range c.subs { subs = append(subs, sub) } + c.subs = nil c.mu.Unlock() for _, sub := range subs { c.removeReplySub(sub) @@ -1735,7 +1922,7 @@ func (c *client) processGatewayAccountSub(accName string) error { // the sublist if present. // func (c *client) processGatewayRUnsub(arg []byte) error { - accName, subject, queue, err := c.parseUnsubProto(arg) + _, accName, subject, queue, err := c.parseUnsubProto(arg, true, false) if err != nil { return fmt.Errorf("processGatewaySubjectUnsub %s", err.Error()) } @@ -1765,6 +1952,10 @@ func (c *client) processGatewayRUnsub(arg []byte) error { return nil } defer c.mu.Unlock() + // If closed, c.subs map will be nil, so bail out. + if c.isClosed() { + return nil + } ei, _ := c.gw.outsim.Load(accName) if ei != nil { @@ -1795,7 +1986,7 @@ func (c *client) processGatewayRUnsub(arg []byte) error { return nil } if e.sl.Remove(sub) == nil { - delete(c.subs, string(key)) + delete(c.subs, bytesToString(key)) if queue != nil { e.qsubs-- atomic.AddInt64(&c.srv.gateway.totalQSubs, -1) @@ -1871,8 +2062,12 @@ func (c *client) processGatewayRSub(arg []byte) error { return nil } defer c.mu.Unlock() + // If closed, c.subs map will be nil, so bail out. + if c.isClosed() { + return nil + } - ei, _ := c.gw.outsim.Load(string(accName)) + ei, _ := c.gw.outsim.Load(bytesToString(accName)) // We should always have an existing entry for plain subs because // in optimistic mode we would have received RS- first, and // in full knowledge, we are receiving RS+ for an account after @@ -1934,7 +2129,7 @@ func (c *client) processGatewayRSub(arg []byte) error { srv = c.srv callUpdate = true } else { - subj := string(subject) + subj := bytesToString(subject) // If this is an RS+ for a wc subject, then // remove from the no interest map all subjects // that are a subset of this wc subject. @@ -1957,7 +2152,7 @@ func (c *client) processGatewayRSub(arg []byte) error { // for queue subscriptions. // -func (c *client) gatewayInterest(acc, subj string) (bool, *SublistResult) { +func (c *client) gatewayInterest(acc string, subj []byte) (bool, *SublistResult) { ei, accountInMap := c.gw.outsim.Load(acc) // If there is an entry for this account and ei is nil, // it means that the remote is not interested at all in @@ -1965,30 +2160,38 @@ func (c *client) gatewayInterest(acc, subj string) (bool, *SublistResult) { if accountInMap && ei == nil { return false, nil } - // Assume interest if account not in map. - psi := !accountInMap + // Assume interest if account not in map, unless we support + // only interest-only mode. + psi := !accountInMap && !c.gw.interestOnlyMode var r *SublistResult if accountInMap { // If in map, check for subs interest with sublist. e := ei.(*outsie) e.RLock() - // We may be in transition to modeInterestOnly + // Unless each side has agreed on interest-only mode, + // we may be in transition to modeInterestOnly // but until e.ni is nil, use it to know if we // should suppress interest or not. - if e.ni != nil { - if _, inMap := e.ni[subj]; !inMap { + if !c.gw.interestOnlyMode && e.ni != nil { + if _, inMap := e.ni[string(subj)]; !inMap { psi = true } } // If we are in modeInterestOnly (e.ni will be nil) // or if we have queue subs, we also need to check sl.Match. if e.ni == nil || e.qsubs > 0 { - r = e.sl.Match(subj) + r = e.sl.MatchBytes(subj) if len(r.psubs) > 0 { psi = true } } e.RUnlock() + // Since callers may just check if the sublist result is nil or not, + // make sure that if what is returned by sl.Match() is the emptyResult, then + // we return nil to the caller. + if r == emptyResult { + r = nil + } } return psi, r } @@ -2037,8 +2240,8 @@ func (s *Server) maybeSendSubOrUnsubToGateways(accName string, sub *subscription accProtoa [256]byte accProto []byte proto []byte - subject = string(sub.subject) - hasWc = subjectHasWildcard(subject) + subject = bytesToString(sub.subject) + hasWC = subjectHasWildcard(subject) ) for _, c := range gws { proto = nil @@ -2053,7 +2256,7 @@ func (s *Server) maybeSendSubOrUnsubToGateways(accName string, sub *subscription // For wildcard subjects, we will remove from our no-interest // map, all subjects that are a subset of this wc subject, but we // still send the wc subject and let the remote do its own cleanup. - if hasWc { + if hasWC { for enis := range e.ni { if subjectIsSubsetMatch(enis, subject) { delete(e.ni, enis) @@ -2176,6 +2379,10 @@ func (s *Server) sendQueueSubOrUnsubToGateways(accName string, qsub *subscriptio // func (s *Server) gatewayUpdateSubInterest(accName string, sub *subscription, change int32) { + if sub.si { + return + } + var ( keya [1024]byte key = keya[:0] @@ -2215,13 +2422,13 @@ func (s *Server) gatewayUpdateSubInterest(accName string, sub *subscription, cha if change < 0 { return } - entry = &sitally{n: 1, q: sub.queue != nil} + entry = &sitally{n: change, q: sub.queue != nil} st[string(key)] = entry first = true } else { entry.n += change if entry.n <= 0 { - delete(st, string(key)) + delete(st, bytesToString(key)) last = true if len(st) == 0 { delete(accMap, accName) @@ -2230,13 +2437,13 @@ func (s *Server) gatewayUpdateSubInterest(accName string, sub *subscription, cha } if sub.client != nil { rsubs := &s.gateway.rsubs - c := sub.client - sli, _ := rsubs.Load(c) + acc := sub.client.acc + sli, _ := rsubs.Load(acc) if change > 0 { var sl *Sublist if sli == nil { sl = NewSublistNoCache() - rsubs.Store(c, sl) + rsubs.Store(acc, sl) } else { sl = sli.(*Sublist) } @@ -2248,7 +2455,7 @@ func (s *Server) gatewayUpdateSubInterest(accName string, sub *subscription, cha sl := sli.(*Sublist) sl.Remove(sub) if sl.Count() == 0 { - rsubs.Delete(c) + rsubs.Delete(acc) } } } @@ -2265,7 +2472,7 @@ func (s *Server) gatewayUpdateSubInterest(accName string, sub *subscription, cha // that is, starts with $GNR and is long enough to contain cluster/server hash // and subject. func isGWRoutedReply(subj []byte) bool { - return len(subj) > gwSubjectOffset && string(subj[:gwReplyPrefixLen]) == gwReplyPrefix + return len(subj) > gwSubjectOffset && bytesToString(subj[:gwReplyPrefixLen]) == gwReplyPrefix } // Same than isGWRoutedReply but accepts the old prefix $GR and returns @@ -2274,7 +2481,7 @@ func isGWRoutedSubjectAndIsOldPrefix(subj []byte) (bool, bool) { if isGWRoutedReply(subj) { return true, false } - if len(subj) > oldGWReplyStart && string(subj[:oldGWReplyPrefixLen]) == oldGWReplyPrefix { + if len(subj) > oldGWReplyStart && bytesToString(subj[:oldGWReplyPrefixLen]) == oldGWReplyPrefix { return true, true } return false, false @@ -2283,26 +2490,20 @@ func isGWRoutedSubjectAndIsOldPrefix(subj []byte) (bool, bool) { // Returns true if subject starts with "$GNR.". This is to check that // clients can't publish on this subject. func hasGWRoutedReplyPrefix(subj []byte) bool { - return len(subj) > gwReplyPrefixLen && string(subj[:gwReplyPrefixLen]) == gwReplyPrefix + return len(subj) > gwReplyPrefixLen && bytesToString(subj[:gwReplyPrefixLen]) == gwReplyPrefix } // Evaluates if the given reply should be mapped or not. -func (g *srvGateway) shouldMapReplyForGatewaySend(c *client, acc *Account, reply []byte) bool { - // If the reply is a service reply (_R_), we will use the account's internal - // clientinstead of the client handed to us. This client holds the wildcard - // for all service replies. - if isServiceReply(reply) { - c = acc.internalClient() - } - // If for this client there is a recent matching subscription interest +func (g *srvGateway) shouldMapReplyForGatewaySend(acc *Account, reply []byte) bool { + // If for this account there is a recent matching subscription interest // then we will map. - sli, _ := g.rsubs.Load(c) + sli, _ := g.rsubs.Load(acc) if sli == nil { return false } sl := sli.(*Sublist) if sl.Count() > 0 { - if r := sl.Match(string(reply)); len(r.psubs)+len(r.qsubs) > 0 { + if sl.HasInterest(string(reply)) { return true } } @@ -2311,7 +2512,7 @@ func (g *srvGateway) shouldMapReplyForGatewaySend(c *client, acc *Account, reply } var subPool = &sync.Pool{ - New: func() interface{} { + New: func() any { return &subscription{} }, } @@ -2320,14 +2521,25 @@ var subPool = &sync.Pool{ // that the message is not sent to a given gateway if for instance // it is known that this gateway has no interest in the account or // subject, etc.. +// When invoked from a LEAF connection, `checkLeafQF` should be passed as `true` +// so that we skip any queue subscription interest that is not part of the +// `c.pa.queues` filter (similar to what we do in `processMsgResults`). However, +// when processing service imports, then this boolean should be passes as `false`, +// regardless if it is a LEAF connection or not. // -func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgroups [][]byte) bool { +func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgroups [][]byte, checkLeafQF bool) bool { + // We had some times when we were sending across a GW with no subject, and the other side would break + // due to parser error. These need to be fixed upstream but also double check here. + if len(subject) == 0 { + return false + } gwsa := [16]*client{} gws := gwsa[:0] // This is in fast path, so avoid calling functions when possible. // Get the outbound connections in place instead of calling // getOutboundGatewayConnections(). - gw := c.srv.gateway + srv := c.srv + gw := srv.gateway gw.RLock() for i := 0; i < len(gw.outo); i++ { gws = append(gws, gw.outo[i]) @@ -2338,8 +2550,22 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr if len(gws) == 0 { return false } + + // Copy off original pa in case it changes. + pa := c.pa + + mt, _ := c.isMsgTraceEnabled() + if mt != nil { + // We are going to replace "pa" with our copy of c.pa, but to restore + // to the original copy of c.pa, we need to save it again. + cpa := c.pa + msg = mt.setOriginAccountHeaderIfNeeded(c, acc, msg) + defer func() { c.pa = cpa }() + // Update pa with our current c.pa state. + pa = c.pa + } + var ( - subj = string(subject) queuesa = [512]byte{} queues = queuesa[:0] accName = acc.Name @@ -2348,6 +2574,9 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr dstHash []byte checkReply = len(reply) > 0 didDeliver bool + prodIsMQTT = c.isMqtt() + dlvMsgs int64 + dlvExtraSz int64 ) // Get a subscription from the pool @@ -2381,7 +2610,7 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr } } else { // Plain sub interest and queue sub results for this account/subject - psi, qr := gwc.gatewayInterest(accName, subj) + psi, qr := gwc.gatewayInterest(accName, subject) if !psi && qr == nil { continue } @@ -2391,6 +2620,21 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr qsubs := qr.qsubs[i] if len(qsubs) > 0 { queue := qsubs[0].queue + if checkLeafQF { + // Skip any queue that is not in the leaf's queue filter. + skip := true + for _, qn := range c.pa.queues { + if bytes.Equal(queue, qn) { + skip = false + break + } + } + if skip { + continue + } + // Now we still need to check that it was not delivered + // locally by checking the given `qgroups`. + } add := true for _, qn := range qgroups { if bytes.Equal(queue, qn) { @@ -2416,7 +2660,7 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr // Assume we will use original mreply = reply // Decide if we should map. - if gw.shouldMapReplyForGatewaySend(c, acc, reply) { + if gw.shouldMapReplyForGatewaySend(acc, reply) { mreply = mreplya[:0] gwc.mu.Lock() useOldPrefix := gwc.gw.useOldPrefix @@ -2429,6 +2673,14 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr mreply = append(mreply, reply...) } } + + // Assume original message + dmsg := msg + if mt != nil { + // If trace is enabled, we need to set the hop header per gateway. + dmsg = mt.setHopHeader(c, dmsg) + } + // Setup the message header. // Make sure we are an 'R' proto by default c.msgb[0] = 'R' @@ -2438,7 +2690,7 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr mh = append(mh, subject...) mh = append(mh, ' ') if len(queues) > 0 { - if reply != nil { + if len(reply) > 0 { mh = append(mh, "+ "...) // Signal that there is a reply. mh = append(mh, mreply...) mh = append(mh, ' ') @@ -2446,7 +2698,7 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr mh = append(mh, "| "...) // Only queues } mh = append(mh, queues...) - } else if reply != nil { + } else if len(reply) > 0 { mh = append(mh, mreply...) mh = append(mh, ' ') } @@ -2476,10 +2728,41 @@ func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgr sub.nm, sub.max = 0, 0 sub.client = gwc sub.subject = subject - didDeliver = c.deliverMsg(sub, subject, mreply, mh, msg, false) || didDeliver + if c.deliverMsg(prodIsMQTT, sub, acc, subject, mreply, mh, dmsg, false) { + // We don't count internal deliveries so count only if sub.icb is nil + if sub.icb == nil { + dlvMsgs++ + dlvExtraSz += int64(len(dmsg) - len(msg)) + } + didDeliver = true + } + + // If we set the header reset the origin pub args. + if mt != nil { + c.pa = pa + } + } + if dlvMsgs > 0 { + totalBytes := dlvMsgs*int64(len(msg)) + dlvExtraSz + // For non MQTT producers, remove the CR_LF * number of messages + if !prodIsMQTT { + totalBytes -= dlvMsgs * int64(LEN_CR_LF) + } + if acc != nil { + acc.stats.Lock() + acc.stats.outMsgs += dlvMsgs + acc.stats.outBytes += totalBytes + acc.stats.gw.outMsgs += dlvMsgs + acc.stats.gw.outBytes += totalBytes + acc.stats.Unlock() + } + atomic.AddInt64(&srv.outMsgs, dlvMsgs) + atomic.AddInt64(&srv.outBytes, totalBytes) } // Done with subscription, put back to pool. We don't need // to reset content since we explicitly set when using it. + // However, make sure to not hold a reference to a connection. + sub.client = nil subPool.Put(sub) return didDeliver } @@ -2541,12 +2824,11 @@ func (s *Server) gatewayHandleSubjectNoInterest(c *client, acc *Account, accName // If there is no subscription for this account, we would normally // send an A-, however, if this account has the internal subscription // for service reply, send a specific RS- for the subject instead. - hasSubs := acc.sl.Count() > 0 - if !hasSubs { - acc.mu.RLock() - hasSubs = acc.siReply != nil - acc.mu.RUnlock() - } + // Need to grab the lock here since sublist can change during reload. + acc.mu.RLock() + hasSubs := acc.sl.Count() > 0 || acc.siReply != nil + acc.mu.RUnlock() + // If there is at least a subscription, possibly send RS- if hasSubs { sendProto := false @@ -2604,13 +2886,52 @@ func (g *srvGateway) getClusterHash() []byte { return clusterHash } +// Store this route in map with the key being the remote server's name hash +// and the remote server's ID hash used by gateway replies mapping routing. +func (s *Server) storeRouteByHash(srvIDHash string, c *client) { + if !s.gateway.enabled { + return + } + s.gateway.routesIDByHash.Store(srvIDHash, c) +} + +// Remove the route with the given keys from the map. +func (s *Server) removeRouteByHash(srvIDHash string) { + if !s.gateway.enabled { + return + } + s.gateway.routesIDByHash.Delete(srvIDHash) +} + // Returns the route with given hash or nil if not found. -func (s *Server) getRouteByHash(srvHash []byte) *client { - var route *client - if v, ok := s.routesByHash.Load(string(srvHash)); ok { - route = v.(*client) +// This is for gateways only. +func (s *Server) getRouteByHash(hash, accName []byte) (*client, bool) { + id := bytesToString(hash) + var perAccount bool + if v, ok := s.accRouteByHash.Load(bytesToString(accName)); ok { + if v == nil { + id += bytesToString(accName) + perAccount = true + } else { + id += strconv.Itoa(v.(int)) + } + } + if v, ok := s.gateway.routesIDByHash.Load(id); ok { + return v.(*client), perAccount + } else if !perAccount { + // Check if we have a "no pool" connection at index 0. + if v, ok := s.gateway.routesIDByHash.Load(bytesToString(hash) + "0"); ok { + if r := v.(*client); r != nil { + r.mu.Lock() + noPool := r.route.noPool + r.mu.Unlock() + if noPool { + return r, false + } + } + } } - return route + return nil, perAccount } // Returns the subject from the routed reply @@ -2623,11 +2944,11 @@ func getSubjectFromGWRoutedReply(reply []byte, isOldPrefix bool) []byte { // This should be invoked only from processInboundGatewayMsg() or // processInboundRoutedMsg() and is checking if the subject -// (c.pa.subject) has the $GNR prefix. If so, this is processed +// (c.pa.subject) has the _GR_ prefix. If so, this is processed // as a GW reply and `true` is returned to indicate to the caller // that it should stop processing. // If gateway is not enabled on this server or if the subject -// does not start with $GR, `false` is returned and caller should +// does not start with _GR_, `false` is returned and caller should // process message as usual. func (c *client) handleGatewayReply(msg []byte) (processed bool) { // Do not handle GW prefixed messages if this server does not have @@ -2666,10 +2987,11 @@ func (c *client) handleGatewayReply(msg []byte) (processed bool) { } var route *client + var perAccount bool // If the origin is not this server, get the route this should be sent to. - if c.kind == GATEWAY && srvHash != nil && !bytes.Equal(srvHash, c.srv.hash) { - route = c.srv.getRouteByHash(srvHash) + if c.kind == GATEWAY && srvHash != nil && !bytes.Equal(srvHash, c.srv.gateway.sIDHash) { + route, perAccount = c.srv.getRouteByHash(srvHash, c.pa.account) // This will be possibly nil, and in this case we will try to process // the interest from this server. } @@ -2681,8 +3003,12 @@ func (c *client) handleGatewayReply(msg []byte) (processed bool) { // getAccAndResultFromCache() var _pacache [256]byte pacache := _pacache[:0] - pacache = append(pacache, c.pa.account...) - pacache = append(pacache, ' ') + // For routes that are dedicated to an account, do not put the account + // name in the pacache. + if c.kind == GATEWAY || (c.kind == ROUTER && c.route != nil && len(c.route.accName) == 0) { + pacache = append(pacache, c.pa.account...) + pacache = append(pacache, ' ') + } pacache = append(pacache, c.pa.subject...) c.pa.pacache = pacache @@ -2702,7 +3028,7 @@ func (c *client) handleGatewayReply(msg []byte) (processed bool) { // If route is nil, we will process the incoming message locally. if route == nil { // Check if this is a service reply subject (_R_) - isServiceReply := len(acc.imports.services) > 0 && isServiceReply(c.pa.subject) + isServiceReply := isServiceReply(c.pa.subject) var queues [][]byte if len(r.psubs)+len(r.qsubs) > 0 { @@ -2719,7 +3045,7 @@ func (c *client) handleGatewayReply(msg []byte) (processed bool) { // we now need to send the message with the real subject to // gateways in case they have interest on that reply subject. if !isServiceReply { - c.sendMsgToGateways(acc, msg, c.pa.subject, c.pa.reply, queues) + c.sendMsgToGateways(acc, msg, c.pa.subject, c.pa.reply, queues, false) } } else if c.kind == GATEWAY { // Only if we are a gateway connection should we try to route @@ -2727,15 +3053,28 @@ func (c *client) handleGatewayReply(msg []byte) (processed bool) { var bufa [256]byte var buf = bufa[:0] buf = append(buf, msgHeadProto...) - buf = append(buf, acc.Name...) - buf = append(buf, ' ') + if !perAccount { + buf = append(buf, acc.Name...) + buf = append(buf, ' ') + } buf = append(buf, orgSubject...) buf = append(buf, ' ') if len(c.pa.reply) > 0 { buf = append(buf, c.pa.reply...) buf = append(buf, ' ') } - buf = append(buf, c.pa.szb...) + szb := c.pa.szb + if c.pa.hdr >= 0 { + if route.headers { + buf[0] = 'H' + buf = append(buf, c.pa.hdb...) + buf = append(buf, ' ') + } else { + szb = []byte(strconv.Itoa(c.pa.size - c.pa.hdr)) + msg = msg[c.pa.hdr:] + } + } + buf = append(buf, szb...) mhEnd := len(buf) buf = append(buf, _CRLF_...) buf = append(buf, msg...) @@ -2759,7 +3098,8 @@ func (c *client) processInboundGatewayMsg(msg []byte) { // Update statistics c.in.msgs++ // The msg includes the CR_LF, so pull back out for accounting. - c.in.bytes += int32(len(msg) - LEN_CR_LF) + size := len(msg) - LEN_CR_LF + c.in.bytes += int32(size) if c.opts.Verbose { c.sendOK() @@ -2784,10 +3124,17 @@ func (c *client) processInboundGatewayMsg(msg []byte) { return } + acc.stats.Lock() + acc.stats.inMsgs++ + acc.stats.inBytes += int64(size) + acc.stats.gw.inMsgs++ + acc.stats.gw.inBytes += int64(size) + acc.stats.Unlock() + // Check if this is a service reply subject (_R_) noInterest := len(r.psubs) == 0 checkNoInterest := true - if acc.imports.services != nil { + if acc.NumServiceImports() > 0 { if isServiceReply(c.pa.subject) { checkNoInterest = false } else { @@ -2795,7 +3142,10 @@ func (c *client) processInboundGatewayMsg(msg []byte) { // make sure we send the proper no interest if the service import is the only interest. noInterest = true for _, sub := range r.psubs { - if sub.client.kind != ACCOUNT { + // sub.si indicates that this is a subscription for service import, and is immutable. + // So sub.si is false, then this is a subscription for something else, so there is + // actually proper interest. + if !sub.si { noInterest = false break } @@ -2826,7 +3176,7 @@ func (c *client) gatewayAllSubsReceiveStart(info *Info) { return } - c.Noticef("Gateway %q: switching account %q to %s mode", + c.Debugf("Gateway %q: switching account %q to %s mode", info.Gateway, account, InterestOnly) // Since the remote would send us this start command @@ -2855,13 +3205,13 @@ func (c *client) gatewayAllSubsReceiveStart(info *Info) { // func (c *client) gatewayAllSubsReceiveComplete(info *Info) { account := getAccountFromGatewayCommand(c, info, "complete") - if account == "" { + if account == _EMPTY_ { return } // Done receiving all subs from remote. Set the `ni` // map to nil so that gatewayInterest() no longer // uses it. - ei, _ := c.gw.outsim.Load(string(account)) + ei, _ := c.gw.outsim.Load(account) if ei != nil { e := ei.(*outsie) // Needs locking here since `ni` is checked by @@ -2871,7 +3221,7 @@ func (c *client) gatewayAllSubsReceiveComplete(info *Info) { e.mode = InterestOnly e.Unlock() - c.Noticef("Gateway %q: switching account %q to %s mode complete", + c.Debugf("Gateway %q: switching account %q to %s mode complete", info.Gateway, account, InterestOnly) } } @@ -2881,7 +3231,7 @@ func getAccountFromGatewayCommand(c *client, info *Info, cmd string) string { if info.GatewayCmdPayload == nil { c.sendErrAndErr(fmt.Sprintf("Account absent from receive-all-subscriptions-%s command", cmd)) c.closeConnection(ProtocolViolation) - return "" + return _EMPTY_ } return string(info.GatewayCmdPayload) } @@ -2906,7 +3256,7 @@ func (c *client) gatewaySwitchAccountToSendAllSubs(e *insie, accName string) { s := c.srv remoteGWName := c.gw.name - c.Noticef("Gateway %q: switching account %q to %s mode", + c.Debugf("Gateway %q: switching account %q to %s mode", remoteGWName, accName, InterestOnly) // Function that will create an INFO protocol @@ -2915,9 +3265,9 @@ func (c *client) gatewaySwitchAccountToSendAllSubs(e *insie, accName string) { // Use bare server info and simply set the // gateway name and command info := Info{ - Gateway: s.getGatewayName(), + Gateway: s.gateway.name, GatewayCmd: cmd, - GatewayCmdPayload: []byte(accName), + GatewayCmdPayload: stringToBytes(accName), } b, _ := json.Marshal(&info) @@ -2942,44 +3292,61 @@ func (c *client) gatewaySwitchAccountToSendAllSubs(e *insie, accName string) { s.startGoRoutine(func() { defer s.grWG.Done() - s.sendAccountSubsToGateway(c, []byte(accName)) + s.sendAccountSubsToGateway(c, accName) // Send the complete command. When the remote receives // this, it will not send a message unless it has a // matching sub from us. sendCmd(gatewayCmdAllSubsComplete, true) - c.Noticef("Gateway %q: switching account %q to %s mode complete", + c.Debugf("Gateway %q: switching account %q to %s mode complete", remoteGWName, accName, InterestOnly) }) } -// Keeps track of the routed reply to be used when/if application -// sends back a message on the reply without the prefix. -// Client lock held on entry. This is a server receiver because -// we use a timer interval that is avail in Server.gateway object. -func (s *Server) trackGWReply(c *client, reply []byte) { - ttl := s.gateway.recSubExp - rm := c.gwrm - var we bool // will be true if map was empty on entry - if rm == nil { - rm = make(map[string]*gwReplyMap) - c.gwrm = rm - we = true +// Keeps track of the routed reply to be used when/if application sends back a +// message on the reply without the prefix. +// If `client` is not nil, it will be stored in the client gwReplyMapping structure, +// and client lock is held on entry. +// If `client` is nil, the mapping is stored in the client's account's gwReplyMapping +// structure. Account lock will be explicitly acquired. +// This is a server receiver because we use a timer interval that is avail in +// Server.gateway object. +func (s *Server) trackGWReply(c *client, acc *Account, reply, routedReply []byte) { + var l sync.Locker + var g *gwReplyMapping + if acc != nil { + acc.mu.Lock() + defer acc.mu.Unlock() + g = &acc.gwReplyMapping + l = &acc.mu } else { - we = len(rm) == 0 + g = &c.gwReplyMapping + l = &c.mu } + ttl := s.gateway.recSubExp + wasEmpty := len(g.mapping) == 0 + if g.mapping == nil { + g.mapping = make(map[string]*gwReplyMap) + } + // The reason we pass both `reply` and `routedReply`, is that in some cases, + // `routedReply` may have a deliver subject appended, something look like: + // "_GR_.xxx.yyy.$JS.ACK.$MQTT_msgs.someid.1.1.1.1620086713306484000.0@$MQTT.msgs.foo" + // but `reply` has already been cleaned up (delivery subject removed from tail): + // "$JS.ACK.$MQTT_msgs.someid.1.1.1.1620086713306484000.0" + // So we will use that knowledge so we don't have to make any cleaning here. + routedReply = routedReply[:gwSubjectOffset+len(reply)] // We need to make a copy so that we don't reference the underlying // read buffer. - ms := string(reply) + ms := string(routedReply) grm := &gwReplyMap{ms: ms, exp: time.Now().Add(ttl).UnixNano()} // If we are here with the same key but different mapped replies // (say $GNR._.A.srv1.bar and then $GNR._.B.srv2.bar), we need to // store it otherwise we would take the risk of the reply not // making it back. - rm[ms[gwSubjectOffset:]] = grm - if we { - atomic.StoreInt32(&c.cgwrt, 1) - s.gwrm.m.Store(c, nil) + g.mapping[ms[gwSubjectOffset:]] = grm + if wasEmpty { + atomic.StoreInt32(&g.check, 1) + s.gwrm.m.Store(g, l) if atomic.CompareAndSwapInt32(&s.gwrm.w, 0, 1) { select { case s.gwrm.ch <- ttl: @@ -3009,19 +3376,20 @@ func (s *Server) startGWReplyMapExpiration() { } now := time.Now().UnixNano() mapEmpty := true - s.gwrm.m.Range(func(k, _ interface{}) bool { - c := k.(*client) - c.mu.Lock() - for k, grm := range c.gwrm { + s.gwrm.m.Range(func(k, v any) bool { + g := k.(*gwReplyMapping) + l := v.(sync.Locker) + l.Lock() + for k, grm := range g.mapping { if grm.exp <= now { - delete(c.gwrm, k) - if len(c.gwrm) == 0 { - atomic.StoreInt32(&c.cgwrt, 0) - s.gwrm.m.Delete(c) + delete(g.mapping, k) + if len(g.mapping) == 0 { + atomic.StoreInt32(&g.check, 0) + s.gwrm.m.Delete(g) } } } - c.mu.Unlock() + l.Unlock() mapEmpty = false return true }) @@ -3033,6 +3401,12 @@ func (s *Server) startGWReplyMapExpiration() { } case cttl := <-s.gwrm.ch: ttl = cttl + if !t.Stop() { + select { + case <-t.C: + default: + } + } t.Reset(ttl) case <-s.quitCh: return diff --git a/vendor/github.com/nats-io/nats-server/v2/server/gsl/gsl.go b/vendor/github.com/nats-io/nats-server/v2/server/gsl/gsl.go new file mode 100644 index 0000000..c16f6ba --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/gsl/gsl.go @@ -0,0 +1,506 @@ +// Copyright 2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gsl + +import ( + "errors" + "strings" + "sync" +) + +// Sublist is a routing mechanism to handle subject distribution and +// provides a facility to match subjects from published messages to +// interested subscribers. Subscribers can have wildcard subjects to +// match multiple published subjects. + +// Common byte variables for wildcards and token separator. +const ( + pwc = '*' + pwcs = "*" + fwc = '>' + fwcs = ">" + tsep = "." + btsep = '.' + _EMPTY_ = "" +) + +// Sublist related errors +var ( + ErrInvalidSubject = errors.New("gsl: invalid subject") + ErrNotFound = errors.New("gsl: no matches found") + ErrNilChan = errors.New("gsl: nil channel") + ErrAlreadyRegistered = errors.New("gsl: notification already registered") +) + +// SimpleSublist is an alias type for GenericSublist that takes +// empty values, useful for tracking interest only without any +// unnecessary allocations. +type SimpleSublist = GenericSublist[struct{}] + +// NewSimpleSublist will create a simple sublist. +func NewSimpleSublist() *SimpleSublist { + return &GenericSublist[struct{}]{root: newLevel[struct{}]()} +} + +// A GenericSublist stores and efficiently retrieves subscriptions. +type GenericSublist[T comparable] struct { + sync.RWMutex + root *level[T] + count uint32 +} + +// A node contains subscriptions and a pointer to the next level. +type node[T comparable] struct { + next *level[T] + subs map[T]string // value -> subject +} + +// A level represents a group of nodes and special pointers to +// wildcard nodes. +type level[T comparable] struct { + nodes map[string]*node[T] + pwc, fwc *node[T] +} + +// Create a new default node. +func newNode[T comparable]() *node[T] { + return &node[T]{subs: make(map[T]string)} +} + +// Create a new default level. +func newLevel[T comparable]() *level[T] { + return &level[T]{nodes: make(map[string]*node[T])} +} + +// NewSublist will create a default sublist with caching enabled per the flag. +func NewSublist[T comparable]() *GenericSublist[T] { + return &GenericSublist[T]{root: newLevel[T]()} +} + +// Insert adds a subscription into the sublist +func (s *GenericSublist[T]) Insert(subject string, value T) error { + s.Lock() + + var sfwc bool + var n *node[T] + l := s.root + + for t := range strings.SplitSeq(subject, tsep) { + lt := len(t) + if lt == 0 || sfwc { + s.Unlock() + return ErrInvalidSubject + } + + if lt > 1 { + n = l.nodes[t] + } else { + switch t[0] { + case pwc: + n = l.pwc + case fwc: + n = l.fwc + sfwc = true + default: + n = l.nodes[t] + } + } + if n == nil { + n = newNode[T]() + if lt > 1 { + l.nodes[t] = n + } else { + switch t[0] { + case pwc: + l.pwc = n + case fwc: + l.fwc = n + default: + l.nodes[t] = n + } + } + } + if n.next == nil { + n.next = newLevel[T]() + } + l = n.next + } + + n.subs[value] = subject + + s.count++ + s.Unlock() + + return nil +} + +// Match will match all entries to the literal subject. +// It will return a set of results for both normal and queue subscribers. +func (s *GenericSublist[T]) Match(subject string, cb func(T)) { + s.match(subject, cb, true) +} + +// MatchBytes will match all entries to the literal subject. +// It will return a set of results for both normal and queue subscribers. +func (s *GenericSublist[T]) MatchBytes(subject []byte, cb func(T)) { + s.match(string(subject), cb, true) +} + +// HasInterest will return whether or not there is any interest in the subject. +// In cases where more detail is not required, this may be faster than Match. +func (s *GenericSublist[T]) HasInterest(subject string) bool { + return s.hasInterest(subject, true, nil) +} + +// NumInterest will return the number of subs interested in the subject. +// In cases where more detail is not required, this may be faster than Match. +func (s *GenericSublist[T]) NumInterest(subject string) (np int) { + s.hasInterest(subject, true, &np) + return +} + +func (s *GenericSublist[T]) match(subject string, cb func(T), doLock bool) { + tsa := [32]string{} + tokens := tsa[:0] + start := 0 + for i := 0; i < len(subject); i++ { + if subject[i] == btsep { + if i-start == 0 { + return + } + tokens = append(tokens, subject[start:i]) + start = i + 1 + } + } + if start >= len(subject) { + return + } + tokens = append(tokens, subject[start:]) + + if doLock { + s.RLock() + defer s.RUnlock() + } + matchLevel(s.root, tokens, cb) +} + +func (s *GenericSublist[T]) hasInterest(subject string, doLock bool, np *int) bool { + tsa := [32]string{} + tokens := tsa[:0] + start := 0 + for i := 0; i < len(subject); i++ { + if subject[i] == btsep { + if i-start == 0 { + return false + } + tokens = append(tokens, subject[start:i]) + start = i + 1 + } + } + if start >= len(subject) { + return false + } + tokens = append(tokens, subject[start:]) + + if doLock { + s.RLock() + defer s.RUnlock() + } + return matchLevelForAny(s.root, tokens, np) +} + +func matchLevelForAny[T comparable](l *level[T], toks []string, np *int) bool { + var pwc, n *node[T] + for i, t := range toks { + if l == nil { + return false + } + if l.fwc != nil { + if np != nil { + *np += len(l.fwc.subs) + } + return true + } + if pwc = l.pwc; pwc != nil { + if match := matchLevelForAny(pwc.next, toks[i+1:], np); match { + return true + } + } + n = l.nodes[t] + if n != nil { + l = n.next + } else { + l = nil + } + } + if n != nil { + if np != nil { + *np += len(n.subs) + } + if len(n.subs) > 0 { + return true + } + } + if pwc != nil { + if np != nil { + *np += len(pwc.subs) + } + return len(pwc.subs) > 0 + } + return false +} + +// callbacksForResults will make the necessary callbacks for each +// result in this node. +func callbacksForResults[T comparable](n *node[T], cb func(T)) { + for sub := range n.subs { + cb(sub) + } +} + +// matchLevel is used to recursively descend into the trie. +func matchLevel[T comparable](l *level[T], toks []string, cb func(T)) { + var pwc, n *node[T] + for i, t := range toks { + if l == nil { + return + } + if l.fwc != nil { + callbacksForResults(l.fwc, cb) + } + if pwc = l.pwc; pwc != nil { + matchLevel(pwc.next, toks[i+1:], cb) + } + n = l.nodes[t] + if n != nil { + l = n.next + } else { + l = nil + } + } + if n != nil { + callbacksForResults(n, cb) + } + if pwc != nil { + callbacksForResults(pwc, cb) + } +} + +// lnt is used to track descent into levels for a removal for pruning. +type lnt[T comparable] struct { + l *level[T] + n *node[T] + t string +} + +// Raw low level remove, can do batches with lock held outside. +func (s *GenericSublist[T]) remove(subject string, value T, shouldLock bool) error { + if shouldLock { + s.Lock() + defer s.Unlock() + } + + var sfwc bool + var n *node[T] + l := s.root + + // Track levels for pruning + var lnts [32]lnt[T] + levels := lnts[:0] + + for t := range strings.SplitSeq(subject, tsep) { + lt := len(t) + if lt == 0 || sfwc { + return ErrInvalidSubject + } + if l == nil { + return ErrNotFound + } + if lt > 1 { + n = l.nodes[t] + } else { + switch t[0] { + case pwc: + n = l.pwc + case fwc: + n = l.fwc + sfwc = true + default: + n = l.nodes[t] + } + } + if n != nil { + levels = append(levels, lnt[T]{l, n, t}) + l = n.next + } else { + l = nil + } + } + + if !s.removeFromNode(n, value) { + return ErrNotFound + } + + s.count-- + + for i := len(levels) - 1; i >= 0; i-- { + l, n, t := levels[i].l, levels[i].n, levels[i].t + if n.isEmpty() { + l.pruneNode(n, t) + } + } + + return nil +} + +// Remove will remove a subscription. +func (s *GenericSublist[T]) Remove(subject string, value T) error { + return s.remove(subject, value, true) +} + +// HasInterestStartingIn is a helper for subject tree intersection. +func (s *GenericSublist[T]) HasInterestStartingIn(subj string) bool { + s.RLock() + defer s.RUnlock() + var _tokens [64]string + tokens := tokenizeSubjectIntoSlice(_tokens[:0], subj) + return hasInterestStartingIn(s.root, tokens) +} + +func hasInterestStartingIn[T comparable](l *level[T], tokens []string) bool { + if l == nil { + return false + } + if len(tokens) == 0 { + return true + } + token := tokens[0] + if l.fwc != nil { + return true + } + found := false + if pwc := l.pwc; pwc != nil { + found = found || hasInterestStartingIn(pwc.next, tokens[1:]) + } + if n := l.nodes[token]; n != nil { + found = found || hasInterestStartingIn(n.next, tokens[1:]) + } + return found +} + +// pruneNode is used to prune an empty node from the tree. +func (l *level[T]) pruneNode(n *node[T], t string) { + if n == nil { + return + } + if n == l.fwc { + l.fwc = nil + } else if n == l.pwc { + l.pwc = nil + } else { + delete(l.nodes, t) + } +} + +// isEmpty will test if the node has any entries. Used +// in pruning. +func (n *node[T]) isEmpty() bool { + return len(n.subs) == 0 && (n.next == nil || n.next.numNodes() == 0) +} + +// Return the number of nodes for the given level. +func (l *level[T]) numNodes() int { + if l == nil { + return 0 + } + num := len(l.nodes) + if l.pwc != nil { + num++ + } + if l.fwc != nil { + num++ + } + return num +} + +// Remove the sub for the given node. +func (s *GenericSublist[T]) removeFromNode(n *node[T], value T) (found bool) { + if n == nil { + return false + } + if _, found = n.subs[value]; found { + delete(n.subs, value) + } + return found +} + +// Count returns the number of subscriptions. +func (s *GenericSublist[T]) Count() uint32 { + s.RLock() + defer s.RUnlock() + return s.count +} + +// numLevels will return the maximum number of levels +// contained in the Sublist tree. +func (s *GenericSublist[T]) numLevels() int { + return visitLevel(s.root, 0) +} + +// visitLevel is used to descend the Sublist tree structure +// recursively. +func visitLevel[T comparable](l *level[T], depth int) int { + if l == nil || l.numNodes() == 0 { + return depth + } + + depth++ + maxDepth := depth + + for _, n := range l.nodes { + if n == nil { + continue + } + newDepth := visitLevel(n.next, depth) + if newDepth > maxDepth { + maxDepth = newDepth + } + } + if l.pwc != nil { + pwcDepth := visitLevel(l.pwc.next, depth) + if pwcDepth > maxDepth { + maxDepth = pwcDepth + } + } + if l.fwc != nil { + fwcDepth := visitLevel(l.fwc.next, depth) + if fwcDepth > maxDepth { + maxDepth = fwcDepth + } + } + return maxDepth +} + +// use similar to append. meaning, the updated slice will be returned +func tokenizeSubjectIntoSlice(tts []string, subject string) []string { + start := 0 + for i := 0; i < len(subject); i++ { + if subject[i] == btsep { + tts = append(tts, subject[start:i]) + start = i + 1 + } + } + tts = append(tts, subject[start:]) + return tts +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ipqueue.go b/vendor/github.com/nats-io/nats-server/v2/server/ipqueue.go new file mode 100644 index 0000000..094c522 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/ipqueue.go @@ -0,0 +1,286 @@ +// Copyright 2021-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "errors" + "sync" + "sync/atomic" +) + +const ipQueueDefaultMaxRecycleSize = 4 * 1024 + +// This is a generic intra-process queue. +type ipQueue[T any] struct { + inprogress int64 + sync.Mutex + ch chan struct{} + elts []T + pos int + pool *sync.Pool + sz uint64 // Calculated size (only if calc != nil) + name string + m *sync.Map + ipQueueOpts[T] +} + +type ipQueueOpts[T any] struct { + mrs int // Max recycle size + calc func(e T) uint64 // Calc function for tracking size + msz uint64 // Limit by total calculated size + mlen int // Limit by number of entries +} + +type ipQueueOpt[T any] func(*ipQueueOpts[T]) + +// This option allows to set the maximum recycle size when attempting +// to put back a slice to the pool. +func ipqMaxRecycleSize[T any](max int) ipQueueOpt[T] { + return func(o *ipQueueOpts[T]) { + o.mrs = max + } +} + +// This option enables total queue size counting by passing in a function +// that evaluates the size of each entry as it is pushed/popped. This option +// enables the size() function. +func ipqSizeCalculation[T any](calc func(e T) uint64) ipQueueOpt[T] { + return func(o *ipQueueOpts[T]) { + o.calc = calc + } +} + +// This option allows setting the maximum queue size. Once the limit is +// reached, then push() will stop returning true and no more entries will +// be stored until some more are popped. The ipQueue_SizeCalculation must +// be provided for this to work. +func ipqLimitBySize[T any](max uint64) ipQueueOpt[T] { + return func(o *ipQueueOpts[T]) { + o.msz = max + } +} + +// This option allows setting the maximum queue length. Once the limit is +// reached, then push() will stop returning true and no more entries will +// be stored until some more are popped. +func ipqLimitByLen[T any](max int) ipQueueOpt[T] { + return func(o *ipQueueOpts[T]) { + o.mlen = max + } +} + +var errIPQLenLimitReached = errors.New("IPQ len limit reached") +var errIPQSizeLimitReached = errors.New("IPQ size limit reached") + +func newIPQueue[T any](s *Server, name string, opts ...ipQueueOpt[T]) *ipQueue[T] { + q := &ipQueue[T]{ + ch: make(chan struct{}, 1), + pool: &sync.Pool{ + New: func() any { + // Reason we use pointer to slice instead of slice is explained + // here: https://staticcheck.io/docs/checks#SA6002 + res := make([]T, 0, 32) + return &res + }, + }, + name: name, + m: &s.ipQueues, + ipQueueOpts: ipQueueOpts[T]{ + mrs: ipQueueDefaultMaxRecycleSize, + }, + } + for _, o := range opts { + o(&q.ipQueueOpts) + } + s.ipQueues.Store(name, q) + return q +} + +// Add the element `e` to the queue, notifying the queue channel's `ch` if the +// entry is the first to be added, and returns the length of the queue after +// this element is added. +func (q *ipQueue[T]) push(e T) (int, error) { + q.Lock() + l := len(q.elts) - q.pos + if q.mlen > 0 && l == q.mlen { + q.Unlock() + return l, errIPQLenLimitReached + } + if q.calc != nil { + sz := q.calc(e) + if q.msz > 0 && q.sz+sz > q.msz { + q.Unlock() + return l, errIPQSizeLimitReached + } + q.sz += sz + } + if q.elts == nil { + // What comes out of the pool is already of size 0, so no need for [:0]. + q.elts = *(q.pool.Get().(*[]T)) + } + q.elts = append(q.elts, e) + q.Unlock() + if l == 0 { + select { + case q.ch <- struct{}{}: + default: + } + } + return l + 1, nil +} + +// Returns the whole list of elements currently present in the queue, +// emptying the queue. This should be called after receiving a notification +// from the queue's `ch` notification channel that indicates that there +// is something in the queue. +// However, in cases where `drain()` may be called from another go +// routine, it is possible that a routine is notified that there is +// something, but by the time it calls `pop()`, the drain() would have +// emptied the queue. So the caller should never assume that pop() will +// return a slice of 1 or more, it could return `nil`. +func (q *ipQueue[T]) pop() []T { + if q == nil { + return nil + } + q.Lock() + if len(q.elts)-q.pos == 0 { + q.Unlock() + return nil + } + var elts []T + if q.pos == 0 { + elts = q.elts + } else { + elts = q.elts[q.pos:] + } + q.elts, q.pos, q.sz = nil, 0, 0 + atomic.AddInt64(&q.inprogress, int64(len(elts))) + q.Unlock() + return elts +} + +// Returns the first element from the queue, if any. See comment above +// regarding calling after being notified that there is something and +// the use of drain(). In short, the caller should always check the +// boolean return value to ensure that the value is genuine and not a +// default empty value. +func (q *ipQueue[T]) popOne() (T, bool) { + q.Lock() + l := len(q.elts) - q.pos + if l == 0 { + q.Unlock() + var empty T + return empty, false + } + e := q.elts[q.pos] + if l--; l > 0 { + q.pos++ + if q.calc != nil { + q.sz -= q.calc(e) + } + // We need to re-signal + select { + case q.ch <- struct{}{}: + default: + } + } else { + // We have just emptied the queue, so we can reuse unless it is too big. + if cap(q.elts) <= q.mrs { + q.elts = q.elts[:0] + } else { + q.elts = nil + } + q.pos, q.sz = 0, 0 + } + q.Unlock() + return e, true +} + +// After a pop(), the slice can be recycled for the next push() when +// a first element is added to the queue. +// This will also decrement the "in progress" count with the length +// of the slice. +// WARNING: The caller MUST never reuse `elts`. +func (q *ipQueue[T]) recycle(elts *[]T) { + // If invoked with a nil list, nothing to do. + if elts == nil || *elts == nil { + return + } + // Update the in progress count. + if len(*elts) > 0 { + atomic.AddInt64(&q.inprogress, int64(-(len(*elts)))) + } + // We also don't want to recycle huge slices, so check against the max. + // q.mrs is normally immutable but can be changed, in a safe way, in some tests. + if cap(*elts) > q.mrs { + return + } + (*elts) = (*elts)[:0] + q.pool.Put(elts) +} + +// Returns the current length of the queue. +func (q *ipQueue[T]) len() int { + q.Lock() + defer q.Unlock() + return len(q.elts) - q.pos +} + +// Returns the calculated size of the queue (if ipQueue_SizeCalculation has been +// passed in), otherwise returns zero. +func (q *ipQueue[T]) size() uint64 { + q.Lock() + defer q.Unlock() + return q.sz +} + +// Empty the queue and consumes the notification signal if present. +// Returns the number of items that were drained from the queue. +// Note that this could cause a reader go routine that has been +// notified that there is something in the queue (reading from queue's `ch`) +// may then get nothing if `drain()` is invoked before the `pop()` or `popOne()`. +func (q *ipQueue[T]) drain() int { + if q == nil { + return 0 + } + q.Lock() + olen := len(q.elts) - q.pos + q.elts, q.pos, q.sz = nil, 0, 0 + // Consume the signal if it was present to reduce the chance of a reader + // routine to be think that there is something in the queue... + select { + case <-q.ch: + default: + } + q.Unlock() + return olen +} + +// Since the length of the queue goes to 0 after a pop(), it is good to +// have an insight on how many elements are yet to be processed after a pop(). +// For that reason, the queue maintains a count of elements returned through +// the pop() API. When the caller will call q.recycle(), this count will +// be reduced by the size of the slice returned by pop(). +func (q *ipQueue[T]) inProgress() int64 { + return atomic.LoadInt64(&q.inprogress) +} + +// Remove this queue from the server's map of ipQueues. +// All ipQueue operations (such as push/pop/etc..) are still possible. +func (q *ipQueue[T]) unregister() { + if q == nil { + return + } + q.m.Delete(q.name) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go index 9a59147..8cf4c6f 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,113 +14,422 @@ package server import ( + "bytes" + "crypto/hmac" "crypto/sha256" + "encoding/binary" "encoding/hex" "encoding/json" "fmt" - "io/ioutil" "math" "os" - "path" "path/filepath" + "runtime/debug" "strconv" "strings" "sync" + "sync/atomic" + "time" "github.com/minio/highwayhash" "github.com/nats-io/nats-server/v2/server/sysmem" + "github.com/nats-io/nats-server/v2/server/tpm" + "github.com/nats-io/nkeys" + "github.com/nats-io/nuid" ) // JetStreamConfig determines this server's configuration. // MaxMemory and MaxStore are in bytes. type JetStreamConfig struct { - MaxMemory int64 - MaxStore int64 - StoreDir string + MaxMemory int64 `json:"max_memory"` // MaxMemory is the maximum size of memory type streams + MaxStore int64 `json:"max_storage"` // MaxStore is the maximum size of file store type streams + StoreDir string `json:"store_dir,omitempty"` // StoreDir is where storage files are stored + SyncInterval time.Duration `json:"sync_interval,omitempty"` // SyncInterval is how frequently we sync to disk in the background by calling fsync + SyncAlways bool `json:"sync_always,omitempty"` // SyncAlways indicates flushes are done after every write + Domain string `json:"domain,omitempty"` // Domain is the JetStream domain + CompressOK bool `json:"compress_ok,omitempty"` // CompressOK indicates if compression is supported + UniqueTag string `json:"unique_tag,omitempty"` // UniqueTag is the unique tag assigned to this instance + Strict bool `json:"strict,omitempty"` // Strict indicates if strict JSON parsing is performed +} + +// Statistics about JetStream for this server. +type JetStreamStats struct { + Memory uint64 `json:"memory"` + Store uint64 `json:"storage"` + ReservedMemory uint64 `json:"reserved_memory"` + ReservedStore uint64 `json:"reserved_storage"` + Accounts int `json:"accounts"` + HAAssets int `json:"ha_assets"` + API JetStreamAPIStats `json:"api"` } -// TODO(dlc) - need to track and rollup against server limits, etc. type JetStreamAccountLimits struct { - MaxMemory int64 `json:"max_memory"` - MaxStore int64 `json:"max_storage"` - MaxStreams int `json:"max_streams"` - MaxConsumers int `json:"max_consumers"` + MaxMemory int64 `json:"max_memory"` + MaxStore int64 `json:"max_storage"` + MaxStreams int `json:"max_streams"` + MaxConsumers int `json:"max_consumers"` + MaxAckPending int `json:"max_ack_pending"` + MemoryMaxStreamBytes int64 `json:"memory_max_stream_bytes"` + StoreMaxStreamBytes int64 `json:"storage_max_stream_bytes"` + MaxBytesRequired bool `json:"max_bytes_required"` +} + +type JetStreamTier struct { + Memory uint64 `json:"memory"` + Store uint64 `json:"storage"` + ReservedMemory uint64 `json:"reserved_memory"` + ReservedStore uint64 `json:"reserved_storage"` + Streams int `json:"streams"` + Consumers int `json:"consumers"` + Limits JetStreamAccountLimits `json:"limits"` } // JetStreamAccountStats returns current statistics about the account's JetStream usage. type JetStreamAccountStats struct { - Memory uint64 `json:"memory"` - Store uint64 `json:"storage"` - Streams int `json:"streams"` - Limits JetStreamAccountLimits `json:"limits"` + JetStreamTier // in case tiers are used, reflects totals with limits not set + Domain string `json:"domain,omitempty"` + API JetStreamAPIStats `json:"api"` + Tiers map[string]JetStreamTier `json:"tiers,omitempty"` // indexed by tier name +} + +// JetStreamAPIStats holds stats about the API usage for this server +type JetStreamAPIStats struct { + Level int `json:"level"` // Level is the active API level this server implements + Total uint64 `json:"total"` // Total is the total API requests received since start + Errors uint64 `json:"errors"` // Errors is the total API requests that resulted in error responses + Inflight uint64 `json:"inflight,omitempty"` // Inflight are the number of API requests currently being served } // This is for internal accounting for JetStream for this server. type jetStream struct { + // These are here first because of atomics on 32bit systems. + apiInflight int64 + apiTotal int64 + apiErrors int64 + memReserved int64 + storeReserved int64 + memUsed int64 + storeUsed int64 + queueLimit int64 + clustered int32 mu sync.RWMutex srv *Server config JetStreamConfig - accounts map[*Account]*jsAccount - memReserved int64 - storeReserved int64 + cluster *jetStreamCluster + accounts map[string]*jsAccount + apiSubs *Sublist + started time.Time + + // System level request to purge a stream move + accountPurge *subscription + + // Some bools regarding general state. + metaRecovering bool + standAlone bool + oos bool + shuttingDown bool + + // Atomic versions + disabled atomic.Bool +} + +type remoteUsage struct { + tiers map[string]*jsaUsage // indexed by tier name + api uint64 + err uint64 +} + +type jsaStorage struct { + total jsaUsage + local jsaUsage } // This represents a jetstream enabled account. -// Worth noting that we include the js ptr, this is because +// Worth noting that we include the jetstream pointer, this is because // in general we want to be very efficient when receiving messages on -// and internal sub for a msgSet, so we will direct link to the msgSet +// an internal sub for a stream, so we will direct link to the stream // and walk backwards as needed vs multiple hash lookups and locks, etc. type jsAccount struct { - mu sync.RWMutex - js *jetStream - account *Account - limits JetStreamAccountLimits - memReserved int64 - memUsed int64 - storeReserved int64 - storeUsed int64 - storeDir string - streams map[string]*Stream - templates map[string]*StreamTemplate - store TemplateStore + mu sync.RWMutex + js *jetStream + account *Account + storeDir string + inflight sync.Map + streams map[string]*stream + templates map[string]*streamTemplate + store TemplateStore + + // From server + sendq *ipQueue[*pubMsg] + + // For limiting only running one checkAndSync at a time. + sync atomic.Bool + + // Usage/limits related fields that will be protected by usageMu + usageMu sync.RWMutex + limits map[string]JetStreamAccountLimits // indexed by tierName + usage map[string]*jsaStorage // indexed by tierName + rusage map[string]*remoteUsage // indexed by node id + apiTotal uint64 + apiErrors uint64 + usageApi uint64 + usageErr uint64 + updatesPub string + updatesSub *subscription + lupdate time.Time + utimer *time.Timer +} + +// Track general usage for this account. +type jsaUsage struct { + mem int64 + store int64 } // EnableJetStream will enable JetStream support on this server with the given configuration. // A nil configuration will dynamically choose the limits and temporary file storage directory. -// If this server is part of a cluster, a system account will need to be defined. func (s *Server) EnableJetStream(config *JetStreamConfig) error { - s.mu.Lock() - if !s.standAloneMode() { - s.mu.Unlock() - return fmt.Errorf("jetstream restricted to single server mode for now") - } - if s.js != nil { - s.mu.Unlock() + if s.JetStreamEnabled() { return fmt.Errorf("jetstream already enabled") } + s.Noticef("Starting JetStream") + start := time.Now() + defer func() { + s.Noticef("Took %s to start JetStream", time.Since(start)) + }() + if config == nil || config.MaxMemory <= 0 || config.MaxStore <= 0 { - var storeDir string - var maxStore int64 + var storeDir, domain, uniqueTag string + var maxStore, maxMem int64 if config != nil { - storeDir = config.StoreDir - maxStore = config.MaxStore + storeDir, domain, uniqueTag = config.StoreDir, config.Domain, config.UniqueTag + maxStore, maxMem = config.MaxStore, config.MaxMemory + } + config = s.dynJetStreamConfig(storeDir, maxStore, maxMem) + if maxMem > 0 { + config.MaxMemory = maxMem + } + if domain != _EMPTY_ { + config.Domain = domain } - config = s.dynJetStreamConfig(storeDir, maxStore) - s.Debugf("JetStream creating dynamic configuration - %s memory, %s disk", FriendlyBytes(config.MaxMemory), FriendlyBytes(config.MaxStore)) + if uniqueTag != _EMPTY_ { + config.UniqueTag = uniqueTag + } + s.Debugf("JetStream creating dynamic configuration - %s memory, %s disk", friendlyBytes(config.MaxMemory), friendlyBytes(config.MaxStore)) + } else if config.StoreDir != _EMPTY_ { + config.StoreDir = filepath.Join(config.StoreDir, JetStreamStoreDir) } - // Copy, don't change callers version. + cfg := *config - if cfg.StoreDir == "" { + if cfg.StoreDir == _EMPTY_ { cfg.StoreDir = filepath.Join(os.TempDir(), JetStreamStoreDir) + s.Warnf("Temporary storage directory used, data could be lost on system reboot") } - s.js = &jetStream{srv: s, config: cfg, accounts: make(map[*Account]*jsAccount)} - s.mu.Unlock() + // We will consistently place the 'jetstream' directory under the storedir that was handed to us. Prior to 2.2.3 though + // we could have a directory on disk without the 'jetstream' directory. This will check and fix if needed. + if err := s.checkStoreDir(&cfg); err != nil { + return err + } + + return s.enableJetStream(cfg) +} + +// Function signature to generate a key encryption key. +type keyGen func(context []byte) ([]byte, error) + +// Return a key generation function or nil if encryption not enabled. +func (s *Server) jsKeyGen(jsKey, info string) keyGen { + if ek := jsKey; ek != _EMPTY_ { + return func(context []byte) ([]byte, error) { + h := hmac.New(sha256.New, []byte(ek)) + if _, err := h.Write([]byte(info)); err != nil { + return nil, err + } + if _, err := h.Write(context); err != nil { + return nil, err + } + return h.Sum(nil), nil + } + } + return nil +} + +// Decode the encrypted metafile. +func (s *Server) decryptMeta(sc StoreCipher, ekey, buf []byte, acc, context string) ([]byte, bool, error) { + if len(ekey) < minMetaKeySize { + return nil, false, errBadKeySize + } + var osc StoreCipher + switch sc { + case AES: + osc = ChaCha + case ChaCha: + osc = AES + } + type prfWithCipher struct { + keyGen + StoreCipher + } + var prfs []prfWithCipher + if prf := s.jsKeyGen(s.getOpts().JetStreamKey, acc); prf == nil { + return nil, false, errNoEncryption + } else { + // First of all, try our current encryption keys with both + // store cipher algorithms. + prfs = append(prfs, prfWithCipher{prf, sc}) + prfs = append(prfs, prfWithCipher{prf, osc}) + } + if prf := s.jsKeyGen(s.getOpts().JetStreamOldKey, acc); prf != nil { + // Then, if we have an old encryption key, try with also with + // both store cipher algorithms. + prfs = append(prfs, prfWithCipher{prf, sc}) + prfs = append(prfs, prfWithCipher{prf, osc}) + } + + for i, prf := range prfs { + rb, err := prf.keyGen([]byte(context)) + if err != nil { + continue + } + kek, err := genEncryptionKey(prf.StoreCipher, rb) + if err != nil { + continue + } + ns := kek.NonceSize() + seed, err := kek.Open(nil, ekey[:ns], ekey[ns:], nil) + if err != nil { + continue + } + aek, err := genEncryptionKey(prf.StoreCipher, seed) + if err != nil { + continue + } + if aek.NonceSize() != kek.NonceSize() { + continue + } + plain, err := aek.Open(nil, buf[:ns], buf[ns:], nil) + if err != nil { + continue + } + return plain, i > 0, nil + } + return nil, false, fmt.Errorf("unable to recover keys") +} + +// Check to make sure directory has the jetstream directory. +// We will have it properly configured here now regardless, so need to look inside. +func (s *Server) checkStoreDir(cfg *JetStreamConfig) error { + fis, _ := os.ReadDir(cfg.StoreDir) + // If we have nothing underneath us, could be just starting new, but if we see this we can check. + if len(fis) != 0 { + return nil + } + // Let's check the directory above. If it has us 'jetstream' but also other stuff that we can + // identify as accounts then we can fix. + fis, _ = os.ReadDir(filepath.Dir(cfg.StoreDir)) + // If just one that is us 'jetstream' and all is ok. + if len(fis) == 1 { + return nil + } + + haveJetstreamDir := false + for _, fi := range fis { + if fi.Name() == JetStreamStoreDir { + haveJetstreamDir = true + break + } + } + + for _, fi := range fis { + // Skip the 'jetstream' directory. + if fi.Name() == JetStreamStoreDir { + continue + } + // Let's see if this is an account. + if accName := fi.Name(); accName != _EMPTY_ { + _, ok := s.accounts.Load(accName) + if !ok && s.AccountResolver() != nil && nkeys.IsValidPublicAccountKey(accName) { + // Account is not local but matches the NKEY account public key, + // this is enough indication to move this directory, no need to + // fetch the account. + ok = true + } + // If this seems to be an account go ahead and move the directory. This will include all assets + // like streams and consumers. + if ok { + if !haveJetstreamDir { + err := os.Mkdir(filepath.Join(filepath.Dir(cfg.StoreDir), JetStreamStoreDir), defaultDirPerms) + if err != nil { + return err + } + haveJetstreamDir = true + } + old := filepath.Join(filepath.Dir(cfg.StoreDir), fi.Name()) + new := filepath.Join(cfg.StoreDir, fi.Name()) + s.Noticef("JetStream relocated account %q to %q", old, new) + if err := os.Rename(old, new); err != nil { + return err + } + } + } + } + + return nil +} + +// This function sets/updates the jetstream encryption key and cipher based +// on options. If the TPM options have been specified, a key is generated +// and sealed by the TPM. +func (s *Server) initJetStreamEncryption() (err error) { + opts := s.getOpts() + + // The TPM settings and other encryption settings are mutually exclusive. + if opts.JetStreamKey != _EMPTY_ && opts.JetStreamTpm.KeysFile != _EMPTY_ { + return fmt.Errorf("JetStream encryption key may not be used with TPM options") + } + // if we are using the standard method to set the encryption key just return and carry on. + if opts.JetStreamKey != _EMPTY_ { + return nil + } + // if the tpm options are not used then no encryption has been configured and return. + if opts.JetStreamTpm.KeysFile == _EMPTY_ { + return nil + } + + if opts.JetStreamTpm.Pcr == 0 { + // Default PCR to use in the TPM. Values can be 0-23, and most platforms + // reserve values 0-12 for the OS, boot locker, disc encryption, etc. + // 16 used for debugging. In sticking to NATS tradition, we'll use 22 + // as the default with the option being configurable. + opts.JetStreamTpm.Pcr = 22 + } + + // Using the TPM to generate or get the encryption key and update the encryption options. + opts.JetStreamKey, err = tpm.LoadJetStreamEncryptionKeyFromTPM(opts.JetStreamTpm.SrkPassword, + opts.JetStreamTpm.KeysFile, opts.JetStreamTpm.KeyPassword, opts.JetStreamTpm.Pcr) + + return err +} + +// enableJetStream will start up the JetStream subsystem. +func (s *Server) enableJetStream(cfg JetStreamConfig) error { + js := &jetStream{srv: s, config: cfg, accounts: make(map[string]*jsAccount), apiSubs: NewSublistNoCache()} + s.gcbMu.Lock() + if s.gcbOutMax = s.getOpts().JetStreamMaxCatchup; s.gcbOutMax == 0 { + s.gcbOutMax = defaultMaxTotalCatchupOutBytes + } + s.gcbMu.Unlock() + + // TODO: Not currently reloadable. + atomic.StoreInt64(&js.queueLimit, s.getOpts().JetStreamRequestQueueLimit) + + s.js.Store(js) // FIXME(dlc) - Allow memory only operation? if stat, err := os.Stat(cfg.StoreDir); os.IsNotExist(err) { - if err := os.MkdirAll(cfg.StoreDir, 0755); err != nil { + if err := os.MkdirAll(cfg.StoreDir, defaultDirPerms); err != nil { return fmt.Errorf("could not create storage directory - %v", err) } } else { @@ -128,68 +437,284 @@ func (s *Server) EnableJetStream(config *JetStreamConfig) error { if stat == nil || !stat.IsDir() { return fmt.Errorf("storage directory is not a directory") } - tmpfile, err := ioutil.TempFile(cfg.StoreDir, "_test_") + tmpfile, err := os.CreateTemp(cfg.StoreDir, "_test_") if err != nil { return fmt.Errorf("storage directory is not writable") } + tmpfile.Close() os.Remove(tmpfile.Name()) } + if err := s.initJetStreamEncryption(); err != nil { + return err + } + // JetStream is an internal service so we need to make sure we have a system account. // This system account will export the JetStream service endpoints. - if sacc := s.SystemAccount(); sacc == nil { + if s.SystemAccount() == nil { s.SetDefaultSystemAccount() } + opts := s.getOpts() + if !opts.DisableJetStreamBanner { + s.Noticef(" _ ___ _____ ___ _____ ___ ___ _ __ __") + s.Noticef(" _ | | __|_ _/ __|_ _| _ \\ __| /_\\ | \\/ |") + s.Noticef("| || | _| | | \\__ \\ | | | / _| / _ \\| |\\/| |") + s.Noticef(" \\__/|___| |_| |___/ |_| |_|_\\___/_/ \\_\\_| |_|") + s.Noticef("") + s.Noticef(" https://docs.nats.io/jetstream") + s.Noticef("") + } + s.Noticef("---------------- JETSTREAM ----------------") + + if cfg.Strict { + s.Noticef(" Strict: %t", cfg.Strict) + } + + s.Noticef(" Max Memory: %s", friendlyBytes(cfg.MaxMemory)) + s.Noticef(" Max Storage: %s", friendlyBytes(cfg.MaxStore)) + s.Noticef(" Store Directory: \"%s\"", cfg.StoreDir) + if cfg.Domain != _EMPTY_ { + s.Noticef(" Domain: %s", cfg.Domain) + } + + if ek := opts.JetStreamKey; ek != _EMPTY_ { + s.Noticef(" Encryption: %s", opts.JetStreamCipher) + } + if opts.JetStreamTpm.KeysFile != _EMPTY_ { + s.Noticef(" TPM File: %q, Pcr: %d", opts.JetStreamTpm.KeysFile, + opts.JetStreamTpm.Pcr) + } + s.Noticef(" API Level: %d", JSApiLevel) + s.Noticef("-------------------------------------------") + // Setup our internal subscriptions. if err := s.setJetStreamExportSubs(); err != nil { - return fmt.Errorf("Error setting up internal jetstream subscriptions: %v", err) - } - - s.Warnf(" _ ___ _____ ___ _____ ___ ___ _ __ __") - s.Warnf(" _ | | __|_ _/ __|_ _| _ \\ __| /_\\ | \\/ |") - s.Warnf("| || | _| | | \\__ \\ | | | / _| / _ \\| |\\/| |") - s.Warnf(" \\__/|___| |_| |___/ |_| |_|_\\___/_/ \\_\\_| |_|") - s.Warnf("") - s.Warnf(" _ _") - s.Warnf(" | |__ ___| |_ __ _") - s.Warnf(" | '_ \\/ -_) _/ _` |") - s.Warnf(" |_.__/\\___|\\__\\__,_|") - s.Warnf("") - s.Warnf(" JetStream is a Beta feature") - s.Warnf(" https://github.com/nats-io/jetstream") - s.Noticef("") - s.Noticef("----------- JETSTREAM -----------") - s.Noticef(" Max Memory: %s", FriendlyBytes(cfg.MaxMemory)) - s.Noticef(" Max Storage: %s", FriendlyBytes(cfg.MaxStore)) - s.Noticef(" Store Directory: %q", cfg.StoreDir) + return fmt.Errorf("setting up internal jetstream subscriptions failed: %v", err) + } // Setup our internal system exports. - sacc := s.SystemAccount() - // FIXME(dlc) - Should we lock these down? s.Debugf(" Exports:") - for _, export := range allJsExports { - s.Debugf(" %s", export) - if err := sacc.AddServiceExport(export, nil); err != nil { - return fmt.Errorf("Error setting up jetstream service exports: %v", err) + s.Debugf(" %s", jsAllAPI) + s.setupJetStreamExports() + + standAlone, canExtend := s.standAloneMode(), s.canExtendOtherDomain() + if standAlone && canExtend && s.getOpts().JetStreamExtHint != jsWillExtend { + canExtend = false + s.Noticef("Standalone server started in clustered mode do not support extending domains") + s.Noticef(`Manually disable standalone mode by setting the JetStream Option "extension_hint: %s"`, jsWillExtend) + } + + // Indicate if we will be standalone for checking resource reservations, etc. + js.setJetStreamStandAlone(standAlone && !canExtend) + + // Enable accounts and restore state before starting clustering. + if err := s.enableJetStreamAccounts(); err != nil { + return err + } + + // If we are in clustered mode go ahead and start the meta controller. + if !standAlone || canExtend { + if err := s.enableJetStreamClustering(); err != nil { + return err } + // Set our atomic bool to clustered. + s.jsClustered.Store(true) } - s.Noticef("----------------------------------------") + + // Mark when we are up and running. + js.setStarted() + + return nil +} + +const jsNoExtend = "no_extend" +const jsWillExtend = "will_extend" + +// This will check if we have a solicited leafnode that shares the system account +// and extension is not manually disabled +func (s *Server) canExtendOtherDomain() bool { + opts := s.getOpts() + sysAcc := s.SystemAccount().GetName() + for _, r := range opts.LeafNode.Remotes { + if r.LocalAccount == sysAcc { + for _, denySub := range r.DenyImports { + if subjectIsSubsetMatch(denySub, raftAllSubj) { + return false + } + } + return true + } + } + return false +} + +func (s *Server) updateJetStreamInfoStatus(enabled bool) { + s.mu.Lock() + s.info.JetStream = enabled + s.mu.Unlock() +} + +// restartJetStream will try to re-enable JetStream during a reload if it had been disabled during runtime. +func (s *Server) restartJetStream() error { + opts := s.getOpts() + cfg := JetStreamConfig{ + StoreDir: opts.StoreDir, + SyncInterval: opts.SyncInterval, + SyncAlways: opts.SyncAlways, + MaxMemory: opts.JetStreamMaxMemory, + MaxStore: opts.JetStreamMaxStore, + Domain: opts.JetStreamDomain, + Strict: opts.JetStreamStrict, + } + s.Noticef("Restarting JetStream") + err := s.EnableJetStream(&cfg) + if err != nil { + s.Warnf("Can't start JetStream: %v", err) + return s.DisableJetStream() + } + s.updateJetStreamInfoStatus(true) + return nil +} + +// checkJetStreamExports will check if we have the JS exports setup +// on the system account, and if not go ahead and set them up. +func (s *Server) checkJetStreamExports() { + if sacc := s.SystemAccount(); sacc != nil { + sacc.mu.RLock() + se := sacc.getServiceExport(jsAllAPI) + sacc.mu.RUnlock() + if se == nil { + s.setupJetStreamExports() + } + } +} + +func (s *Server) setupJetStreamExports() { + // Setup our internal system export. + if err := s.SystemAccount().AddServiceExport(jsAllAPI, nil); err != nil { + s.Warnf("Error setting up jetstream service exports: %v", err) + } +} + +func (s *Server) jetStreamOOSPending() (wasPending bool) { + if js := s.getJetStream(); js != nil { + js.mu.Lock() + wasPending = js.oos + js.oos = true + js.mu.Unlock() + } + return wasPending +} + +func (s *Server) setJetStreamDisabled() { + if js := s.getJetStream(); js != nil { + js.disabled.Store(true) + } +} + +func (s *Server) handleOutOfSpace(mset *stream) { + if s.JetStreamEnabled() && !s.jetStreamOOSPending() { + var stream string + if mset != nil { + stream = mset.name() + s.Errorf("JetStream out of %s resources, will be DISABLED", mset.Store().Type()) + } else { + s.Errorf("JetStream out of resources, will be DISABLED") + } + + go s.DisableJetStream() + + adv := &JSServerOutOfSpaceAdvisory{ + TypedEvent: TypedEvent{ + Type: JSServerOutOfStorageAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Server: s.Name(), + ServerID: s.ID(), + Stream: stream, + Cluster: s.cachedClusterName(), + Domain: s.getOpts().JetStreamDomain, + } + s.publishAdvisory(nil, JSAdvisoryServerOutOfStorage, adv) + } +} + +// DisableJetStream will turn off JetStream and signals in clustered mode +// to have the metacontroller remove us from the peer list. +func (s *Server) DisableJetStream() error { + if !s.JetStreamEnabled() { + return nil + } + + s.setJetStreamDisabled() + + if s.JetStreamIsClustered() { + isLeader := s.JetStreamIsLeader() + js, cc := s.getJetStreamCluster() + if js == nil { + s.shutdownJetStream() + return nil + } + js.mu.RLock() + meta := cc.meta + js.mu.RUnlock() + + if meta != nil { + if isLeader { + s.Warnf("JetStream initiating meta leader transfer") + meta.StepDown() + select { + case <-s.quitCh: + return nil + case <-time.After(2 * time.Second): + } + if !s.JetStreamIsCurrent() { + s.Warnf("JetStream timeout waiting for meta leader transfer") + } + } + meta.Delete() + } + } + + // Update our info status. + s.updateJetStreamInfoStatus(false) + + // Normal shutdown. + s.shutdownJetStream() + + // Shut down the RAFT groups. + s.shutdownRaftNodes() + + return nil +} + +func (s *Server) enableJetStreamAccounts() error { + // Reuse the same task workers across all accounts, so that we don't explode + // with a large number of goroutines on multi-account systems. + tq := parallelTaskQueue(len(dios)) + defer close(tq) // If we have no configured accounts setup then setup imports on global account. if s.globalAccountOnly() { - if err := s.GlobalAccount().EnableJetStream(nil); err != nil { - return fmt.Errorf("Error enabling jetstream on the global account") + gacc := s.GlobalAccount() + gacc.mu.Lock() + if len(gacc.jsLimits) == 0 { + gacc.jsLimits = defaultJSAccountTiers } - } else if err := s.configAllJetStreamAccounts(); err != nil { + gacc.mu.Unlock() + if err := s.configJetStream(gacc, tq); err != nil { + return err + } + } else if err := s.configAllJetStreamAccounts(tq); err != nil { return fmt.Errorf("Error enabling jetstream on configured accounts: %v", err) } - return nil } -// enableAllJetStreamServiceImports turns on all service imports for jetstream for this account. -func (a *Account) enableAllJetStreamServiceImports() error { +// enableAllJetStreamServiceImportsAndMappings turns on all service imports and mappings for jetstream for this account. +func (a *Account) enableAllJetStreamServiceImportsAndMappings() error { a.mu.RLock() s := a.srv a.mu.RUnlock() @@ -198,51 +723,78 @@ func (a *Account) enableAllJetStreamServiceImports() error { return fmt.Errorf("jetstream account not registered") } - // In case the enabled import exists here. - a.removeServiceImport(JSApiAccountInfo) + var dstAccName string + if sacc := s.SystemAccount(); sacc != nil { + dstAccName = sacc.Name + } - sys := s.SystemAccount() - for _, export := range allJsExports { - if !a.serviceImportExists(sys, export) { - if err := a.AddServiceImport(sys, export, _EMPTY_); err != nil { - return fmt.Errorf("Error setting up jetstream service imports for account: %v", err) + if !a.serviceImportExists(dstAccName, jsAllAPI) { + // Capture si so we can turn on implicit sharing with JetStream layer. + // Make sure to set "to" otherwise will incur performance slow down. + si, err := a.addServiceImport(s.SystemAccount(), jsAllAPI, jsAllAPI, nil) + if err != nil { + return fmt.Errorf("Error setting up jetstream service imports for account: %v", err) + } + a.mu.Lock() + si.share = true + a.mu.Unlock() + } + + // Check if we have a Domain specified. + // If so add in a subject mapping that will allow local connected clients to reach us here as well. + if opts := s.getOpts(); opts.JetStreamDomain != _EMPTY_ { + mappings := generateJSMappingTable(opts.JetStreamDomain) + a.mu.RLock() + for _, m := range a.mappings { + delete(mappings, m.src) + } + a.mu.RUnlock() + for src, dest := range mappings { + if err := a.AddMapping(src, dest); err != nil { + s.Errorf("Error adding JetStream domain mapping: %v", err) } } } + return nil } -// enableJetStreamEnabledServiceImportOnly will enable the single service import responder. +// enableJetStreamInfoServiceImportOnly will enable the single service import responder. // Should we do them all regardless? func (a *Account) enableJetStreamInfoServiceImportOnly() error { - a.mu.RLock() - s := a.srv - a.mu.RUnlock() - - if s == nil { - return fmt.Errorf("jetstream account not registered") - } - sys := s.SystemAccount() - if err := a.AddServiceImport(sys, JSApiAccountInfo, _EMPTY_); err != nil { - return fmt.Errorf("Error setting up jetstream service imports for account: %v", err) + // Check if this import would be overshadowed. This can happen when accounts + // are importing from another account for JS access. + if a.serviceImportShadowed(JSApiAccountInfo) { + return nil } - return nil + + return a.enableAllJetStreamServiceImportsAndMappings() } -func (s *Server) configJetStream(acc *Account) error { - if acc.jsLimits != nil { +func (s *Server) configJetStream(acc *Account, tq chan<- func()) error { + if acc == nil { + return nil + } + acc.mu.RLock() + jsLimits := acc.jsLimits + acc.mu.RUnlock() + if jsLimits != nil { // Check if already enabled. This can be during a reload. if acc.JetStreamEnabled() { - if err := acc.enableAllJetStreamServiceImports(); err != nil { + if err := acc.enableAllJetStreamServiceImportsAndMappings(); err != nil { return err } - if err := acc.UpdateJetStreamLimits(acc.jsLimits); err != nil { + if err := acc.UpdateJetStreamLimits(jsLimits); err != nil { return err } - } else if err := acc.EnableJetStream(acc.jsLimits); err != nil { - return err + } else { + if err := acc.EnableJetStream(jsLimits, tq); err != nil { + return err + } + if s.gateway.enabled { + s.switchAccountToInterestMode(acc.GetName()) + } } - acc.jsLimits = nil } else if acc != s.SystemAccount() { if acc.JetStreamEnabled() { acc.DisableJetStream() @@ -257,89 +809,270 @@ func (s *Server) configJetStream(acc *Account) error { } // configAllJetStreamAccounts walk all configured accounts and turn on jetstream if requested. -func (s *Server) configAllJetStreamAccounts() error { +func (s *Server) configAllJetStreamAccounts(tq chan<- func()) error { // Check to see if system account has been enabled. We could arrive here via reload and // a non-default system account. - if sacc := s.SystemAccount(); sacc != nil && !sacc.IsExportService(JSApiAccountInfo) { - for _, export := range allJsExports { - if err := sacc.AddServiceExport(export, nil); err != nil { - return fmt.Errorf("Error setting up jetstream service exports: %v", err) - } - } - } + s.checkJetStreamExports() - // Snapshot into our own list. Might not be needed. - s.mu.Lock() // Bail if server not enabled. If it was enabled and a reload turns it off // that will be handled elsewhere. - if s.js == nil { - s.mu.Unlock() + js := s.getJetStream() + if js == nil { return nil } - var jsAccounts []*Account - - s.accounts.Range(func(k, v interface{}) bool { - jsAccounts = append(jsAccounts, v.(*Account)) - return true - }) - s.mu.Unlock() + // Snapshot into our own list. Might not be needed. + s.mu.RLock() + if s.sys != nil { + // clustered stream removal will perform this cleanup as well + // this is mainly for initial cleanup + saccName := s.sys.account.Name + accStoreDirs, _ := os.ReadDir(js.config.StoreDir) + for _, acc := range accStoreDirs { + if accName := acc.Name(); accName != saccName { + // no op if not empty + accDir := filepath.Join(js.config.StoreDir, accName) + os.Remove(filepath.Join(accDir, streamsDir)) + os.Remove(accDir) + } + } + } + + var jsAccounts []*Account + s.accounts.Range(func(k, v any) bool { + jsAccounts = append(jsAccounts, v.(*Account)) + return true + }) + accounts := &s.accounts + s.mu.RUnlock() + + // Process any jetstream enabled accounts here. These will be accounts we are + // already aware of at startup etc. + for _, acc := range jsAccounts { + if err := s.configJetStream(acc, tq); err != nil { + return err + } + } + + // Now walk all the storage we have and resolve any accounts that we did not process already. + // This is important in resolver/operator models. + fis, _ := os.ReadDir(js.config.StoreDir) + for _, fi := range fis { + if accName := fi.Name(); accName != _EMPTY_ { + // Only load up ones not already loaded since they are processed above. + if _, ok := accounts.Load(accName); !ok { + if acc, err := s.lookupAccount(accName); err != nil && acc != nil { + if err := s.configJetStream(acc, tq); err != nil { + return err + } + } + } + } + } + + return nil +} + +// Mark our started time. +func (js *jetStream) setStarted() { + js.mu.Lock() + defer js.mu.Unlock() + js.started = time.Now() +} + +func (js *jetStream) isEnabled() bool { + if js == nil { + return false + } + return !js.disabled.Load() +} + +// Mark that we will be in standlone mode. +func (js *jetStream) setJetStreamStandAlone(isStandAlone bool) { + if js == nil { + return + } + js.mu.Lock() + defer js.mu.Unlock() + if js.standAlone = isStandAlone; js.standAlone { + // Update our server atomic. + js.srv.isMetaLeader.Store(true) + js.accountPurge, _ = js.srv.systemSubscribe(JSApiAccountPurge, _EMPTY_, false, nil, js.srv.jsLeaderAccountPurgeRequest) + } else if js.accountPurge != nil { + js.srv.sysUnsubscribe(js.accountPurge) + } +} + +// JetStreamEnabled reports if jetstream is enabled for this server. +func (s *Server) JetStreamEnabled() bool { + return s.getJetStream().isEnabled() +} + +// JetStreamEnabledForDomain will report if any servers have JetStream enabled within this domain. +func (s *Server) JetStreamEnabledForDomain() bool { + if s.JetStreamEnabled() { + return true + } + + var jsFound bool + // If we are here we do not have JetStream enabled for ourselves, but we need to check all connected servers. + // TODO(dlc) - Could optimize and memoize this. + s.nodeToInfo.Range(func(k, v any) bool { + // This should not be dependent on online status, so only check js. + if v.(nodeInfo).js { + jsFound = true + return false + } + return true + }) + + return jsFound +} + +// Will signal that all pull requests for consumers on this server are now invalid. +func (s *Server) signalPullConsumers() { + js := s.getJetStream() + if js == nil { + return + } + + js.mu.RLock() + defer js.mu.RUnlock() - // Process any jetstream enabled accounts here. - for _, acc := range jsAccounts { - if err := s.configJetStream(acc); err != nil { - return err + // In case we have stale pending requests. + const hdr = "NATS/1.0 409 Server Shutdown\r\n" + JSPullRequestPendingMsgs + ": %d\r\n" + JSPullRequestPendingBytes + ": %d\r\n\r\n" + var didSend bool + + for _, jsa := range js.accounts { + jsa.mu.RLock() + for _, stream := range jsa.streams { + stream.mu.RLock() + for _, o := range stream.consumers { + o.mu.RLock() + // Only signal on R1. + if o.cfg.Replicas <= 1 { + for reply, wr := range o.pendingRequests() { + shdr := fmt.Sprintf(hdr, wr.n, wr.b) + o.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, []byte(shdr), nil, nil, 0)) + didSend = true + } + } + o.mu.RUnlock() + } + stream.mu.RUnlock() } + jsa.mu.RUnlock() + } + // Give time for migration information to make it out of our server. + if didSend { + time.Sleep(50 * time.Millisecond) } - return nil } -// JetStreamEnabled reports if jetstream is enabled. -func (s *Server) JetStreamEnabled() bool { - s.mu.Lock() - enabled := s.js != nil - s.mu.Unlock() - return enabled +// Helper for determining if we are shutting down. +func (js *jetStream) isShuttingDown() bool { + js.mu.RLock() + defer js.mu.RUnlock() + return js.shuttingDown } // Shutdown jetstream for this server. func (s *Server) shutdownJetStream() { - s.mu.Lock() - if s.js == nil { - s.mu.Unlock() + js := s.getJetStream() + if js == nil { return } - var _jsa [512]*jsAccount - jsas := _jsa[:0] + + s.Noticef("Initiating JetStream Shutdown...") + defer s.Noticef("JetStream Shutdown") + + // If we have folks blocked on sync requests, unblock. + // Send 1 is enough, but use select in case they were all present. + select { + case s.syncOutSem <- struct{}{}: + default: + } + + var _a [512]*Account + accounts := _a[:0] + + js.mu.Lock() // Collect accounts. - for _, jsa := range s.js.accounts { - jsas = append(jsas, jsa) + for _, jsa := range js.accounts { + if a := jsa.acc(); a != nil { + accounts = append(accounts, a) + } } - s.mu.Unlock() + accPurgeSub := js.accountPurge + js.accountPurge = nil + // Signal we are shutting down. + js.shuttingDown = true + js.mu.Unlock() - for _, jsa := range jsas { - s.js.disableJetStream(jsa) + if accPurgeSub != nil { + s.sysUnsubscribe(accPurgeSub) } - s.mu.Lock() - s.js.accounts = nil - s.js = nil - s.mu.Unlock() + for _, a := range accounts { + a.removeJetStream() + } + + s.js.Store(nil) + + js.mu.Lock() + js.accounts = nil + + var qch chan struct{} + var stopped chan struct{} + if cc := js.cluster; cc != nil { + if cc.qch != nil { + qch, stopped = cc.qch, cc.stopped + cc.qch, cc.stopped = nil, nil + } + js.stopUpdatesSub() + if cc.c != nil { + cc.c.closeConnection(ClientClosed) + cc.c = nil + } + cc.meta = nil + // Set our atomic bool to false. + s.jsClustered.Store(false) + } + js.mu.Unlock() + + // If we were clustered signal the monitor cluster go routine. + // We will wait for a bit for it to close. + // Do this without the lock. + if qch != nil { + close(qch) // Must be close() to signal *all* listeners + select { + case <-stopped: + case <-time.After(10 * time.Second): + s.Warnf("Did not receive signal for successful shutdown of cluster routine") + } + } } // JetStreamConfig will return the current config. Useful if the system // created a dynamic configuration. A copy is returned. func (s *Server) JetStreamConfig() *JetStreamConfig { var c *JetStreamConfig - s.mu.Lock() - if s.js != nil { - copy := s.js.config + if js := s.getJetStream(); js != nil { + copy := js.config c = &(copy) } - s.mu.Unlock() return c } +// StoreDir returns the current JetStream directory. +func (s *Server) StoreDir() string { + js := s.getJetStream() + if js == nil { + return _EMPTY_ + } + return js.config.StoreDir +} + // JetStreamNumAccounts returns the number of enabled accounts this server is tracking. func (s *Server) JetStreamNumAccounts() int { js := s.getJetStream() @@ -355,7 +1088,7 @@ func (s *Server) JetStreamNumAccounts() int { func (s *Server) JetStreamReservedResources() (int64, int64, error) { js := s.getJetStream() if js == nil { - return -1, -1, ErrJetStreamNotEnabled + return -1, -1, NewJSNotEnabledForAccountError() } js.mu.RLock() defer js.mu.RUnlock() @@ -363,97 +1096,143 @@ func (s *Server) JetStreamReservedResources() (int64, int64, error) { } func (s *Server) getJetStream() *jetStream { - s.mu.Lock() - js := s.js - s.mu.Unlock() - return js + return s.js.Load() +} + +func (a *Account) assignJetStreamLimits(limits map[string]JetStreamAccountLimits) { + a.mu.Lock() + a.jsLimits = limits + a.mu.Unlock() } // EnableJetStream will enable JetStream on this account with the defined limits. // This is a helper for JetStreamEnableAccount. -func (a *Account) EnableJetStream(limits *JetStreamAccountLimits) error { +func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits, tq chan<- func()) error { a.mu.RLock() s := a.srv a.mu.RUnlock() + if s == nil { return fmt.Errorf("jetstream account not registered") } - // FIXME(dlc) - cluster mode - js := s.getJetStream() - if js == nil { - return ErrJetStreamNotEnabled - } + if s.SystemAccount() == a { return fmt.Errorf("jetstream can not be enabled on the system account") } + s.mu.RLock() + if s.sys == nil { + s.mu.RUnlock() + return ErrServerNotRunning + } + sendq := s.sys.sendq + s.mu.RUnlock() + // No limits means we dynamically set up limits. - if limits == nil { - limits = js.dynamicAccountLimits() + // We also place limits here so we know that the account is configured for JetStream. + if len(limits) == 0 { + limits = defaultJSAccountTiers + } + + a.assignJetStreamLimits(limits) + + js := s.getJetStream() + if js == nil { + return NewJSNotEnabledError() } js.mu.Lock() - // Check the limits against existing reservations. - if _, ok := js.accounts[a]; ok { + // Accounts get reset to nil on shutdown, since we re-acquire the locks here, we need to check again. + if js.accounts == nil { + js.mu.Unlock() + return NewJSNotEnabledError() + } + + if jsa, ok := js.accounts[a.Name]; ok { + a.mu.Lock() + a.js = jsa + a.mu.Unlock() js.mu.Unlock() - return fmt.Errorf("jetstream already enabled for account") + return a.enableAllJetStreamServiceImportsAndMappings() } + + // Check the limits against existing reservations. if err := js.sufficientResources(limits); err != nil { js.mu.Unlock() return err } - jsa := &jsAccount{js: js, account: a, limits: *limits, streams: make(map[string]*Stream)} - jsa.storeDir = path.Join(js.config.StoreDir, a.Name) - js.accounts[a] = jsa - js.reserveResources(limits) - js.mu.Unlock() - // Stamp inside account as well. + sysNode := s.Node() + + jsa := &jsAccount{js: js, account: a, limits: limits, streams: make(map[string]*stream), sendq: sendq, usage: make(map[string]*jsaStorage)} + jsa.storeDir = filepath.Join(js.config.StoreDir, a.Name) + + // A single server does not need to do the account updates at this point. + if js.cluster != nil || !s.standAloneMode() { + jsa.usageMu.Lock() + jsa.utimer = time.AfterFunc(usageTick, jsa.sendClusterUsageUpdateTimer) + // Cluster mode updates to resource usage. System internal prevents echos. + jsa.updatesPub = fmt.Sprintf(jsaUpdatesPubT, a.Name, sysNode) + jsa.updatesSub, _ = s.sysSubscribe(fmt.Sprintf(jsaUpdatesSubT, a.Name), jsa.remoteUpdateUsage) + jsa.usageMu.Unlock() + } + + js.accounts[a.Name] = jsa + // Stamp inside account as well. Needs to be done under js's lock. a.mu.Lock() a.js = jsa a.mu.Unlock() + js.mu.Unlock() // Create the proper imports here. - if err := a.enableAllJetStreamServiceImports(); err != nil { + if err := a.enableAllJetStreamServiceImportsAndMappings(); err != nil { return err } s.Debugf("Enabled JetStream for account %q", a.Name) - s.Debugf(" Max Memory: %s", FriendlyBytes(limits.MaxMemory)) - s.Debugf(" Max Storage: %s", FriendlyBytes(limits.MaxStore)) + if l, ok := limits[_EMPTY_]; ok { + s.Debugf(" Max Memory: %s", friendlyBytes(l.MaxMemory)) + s.Debugf(" Max Storage: %s", friendlyBytes(l.MaxStore)) + } else { + for t, l := range limits { + s.Debugf(" Tier: %s", t) + s.Debugf(" Max Memory: %s", friendlyBytes(l.MaxMemory)) + s.Debugf(" Max Storage: %s", friendlyBytes(l.MaxStore)) + } + } + + // Clean up any old snapshots that were orphaned while staging. + os.RemoveAll(filepath.Join(js.config.StoreDir, snapStagingDir)) - // Do quick fixup here for new directory structure. - // TODO(dlc) - We can remove once we do MVP IMO. - sdir := path.Join(jsa.storeDir, streamsDir) + sdir := filepath.Join(jsa.storeDir, streamsDir) if _, err := os.Stat(sdir); os.IsNotExist(err) { - // If we are here that means this is old school directory, upgrade in place. - s.Noticef(" Upgrading storage directory structure for %q", a.Name) - omdirs, _ := ioutil.ReadDir(jsa.storeDir) - if err := os.MkdirAll(sdir, 0755); err != nil { + if err := os.MkdirAll(sdir, defaultDirPerms); err != nil { return fmt.Errorf("could not create storage streams directory - %v", err) } - for _, fi := range omdirs { - os.Rename(path.Join(jsa.storeDir, fi.Name()), path.Join(sdir, fi.Name())) - } + // Just need to make sure we can write to the directory. + // Remove the directory will create later if needed. + os.RemoveAll(sdir) + // when empty remove parent directory, which may have been created as well + os.Remove(jsa.storeDir) + } else { + // Restore any state here. + s.Debugf("Recovering JetStream state for account %q", a.Name) } - // Restore any state here. - s.Noticef(" Recovering JetStream state for account %q", a.Name) - // Check templates first since messsage sets will need proper ownership. // FIXME(dlc) - Make this consistent. - tdir := path.Join(jsa.storeDir, tmplsDir) + tdir := filepath.Join(jsa.storeDir, tmplsDir) if stat, err := os.Stat(tdir); err == nil && stat.IsDir() { key := sha256.Sum256([]byte("templates")) - hh, err := highwayhash.New64(key[:]) + hh, err := highwayhash.NewDigest64(key[:]) if err != nil { return err } - fis, _ := ioutil.ReadDir(tdir) + fis, _ := os.ReadDir(tdir) for _, fi := range fis { - metafile := path.Join(tdir, fi.Name(), JetStreamMetaFile) - metasum := path.Join(tdir, fi.Name(), JetStreamMetaFileSum) - buf, err := ioutil.ReadFile(metafile) + metafile := filepath.Join(tdir, fi.Name(), JetStreamMetaFile) + metasum := filepath.Join(tdir, fi.Name(), JetStreamMetaFileSum) + buf, err := os.ReadFile(metafile) if err != nil { s.Warnf(" Error reading StreamTemplate metafile %q: %v", metasum, err) continue @@ -462,14 +1241,15 @@ func (a *Account) EnableJetStream(limits *JetStreamAccountLimits) error { s.Warnf(" Missing StreamTemplate checksum for %q", metasum) continue } - sum, err := ioutil.ReadFile(metasum) + sum, err := os.ReadFile(metasum) if err != nil { s.Warnf(" Error reading StreamTemplate checksum %q: %v", metasum, err) continue } hh.Reset() hh.Write(buf) - checksum := hex.EncodeToString(hh.Sum(nil)) + var hb [highwayhash.Size64]byte + checksum := hex.EncodeToString(hh.Sum(hb[:0])) if checksum != string(sum) { s.Warnf(" StreamTemplate checksums do not match %q vs %q", sum, checksum) continue @@ -480,131 +1260,399 @@ func (a *Account) EnableJetStream(limits *JetStreamAccountLimits) error { continue } cfg.Config.Name = _EMPTY_ - if _, err := a.AddStreamTemplate(&cfg); err != nil { + if _, err := a.addStreamTemplate(&cfg); err != nil { s.Warnf(" Error recreating StreamTemplate %q: %v", cfg.Name, err) continue } } } + // Remember if we should be encrypted and what cipher we think we should use. + encrypted := s.getOpts().JetStreamKey != _EMPTY_ + sc := s.getOpts().JetStreamCipher + + doConsumers := func(mset *stream, odir string) { + ofis, _ := os.ReadDir(odir) + if len(ofis) > 0 { + s.Noticef(" Recovering %d consumers for stream - '%s > %s'", len(ofis), mset.accName(), mset.name()) + } + for _, ofi := range ofis { + metafile := filepath.Join(odir, ofi.Name(), JetStreamMetaFile) + metasum := filepath.Join(odir, ofi.Name(), JetStreamMetaFileSum) + if _, err := os.Stat(metafile); os.IsNotExist(err) { + s.Warnf(" Missing consumer metafile %q", metafile) + continue + } + buf, err := os.ReadFile(metafile) + if err != nil { + s.Warnf(" Error reading consumer metafile %q: %v", metafile, err) + continue + } + if _, err := os.Stat(metasum); os.IsNotExist(err) { + s.Warnf(" Missing consumer checksum for %q", metasum) + continue + } + + // Check if we are encrypted. + if key, err := os.ReadFile(filepath.Join(odir, ofi.Name(), JetStreamMetaFileKey)); err == nil { + s.Debugf(" Consumer metafile is encrypted, reading encrypted keyfile") + // Decode the buffer before proceeding. + ctxName := mset.name() + tsep + ofi.Name() + nbuf, _, err := s.decryptMeta(sc, key, buf, a.Name, ctxName) + if err != nil { + s.Warnf(" Error decrypting our consumer metafile: %v", err) + continue + } + buf = nbuf + } + + var cfg FileConsumerInfo + decoder := json.NewDecoder(bytes.NewReader(buf)) + decoder.DisallowUnknownFields() + strictErr := decoder.Decode(&cfg) + if strictErr != nil { + cfg = FileConsumerInfo{} + if err := json.Unmarshal(buf, &cfg); err != nil { + s.Warnf(" Error unmarshalling consumer metafile %q: %v", metafile, err) + continue + } + } + if supported := supportsRequiredApiLevel(cfg.Metadata); !supported || strictErr != nil { + var offlineReason string + if !supported { + apiLevel := getRequiredApiLevel(cfg.Metadata) + if strictErr != nil { + offlineReason = fmt.Sprintf("unsupported - config error: %s", strings.TrimPrefix(strictErr.Error(), "json: ")) + } else { + offlineReason = fmt.Sprintf("unsupported - required API level: %s, current API level: %d", apiLevel, JSApiLevel) + } + s.Warnf(" Detected unsupported consumer '%s > %s > %s': %s", a.Name, mset.name(), cfg.Name, offlineReason) + } else { + offlineReason = fmt.Sprintf("decoding error: %v", strictErr) + s.Warnf(" Error unmarshalling consumer metafile %q: %v", metafile, strictErr) + } + singleServerMode := !s.JetStreamIsClustered() && s.standAloneMode() + if singleServerMode { + if !mset.closed.Load() { + s.Warnf(" Stopping unsupported stream '%s > %s'", a.Name, mset.name()) + mset.mu.Lock() + mset.offlineReason = fmt.Sprintf("stopped - unsupported consumer %q", cfg.Name) + mset.mu.Unlock() + mset.stop(false, false) + } + + // Fake a consumer, so we can respond to API requests as single-server. + o := &consumer{ + mset: mset, + js: s.getJetStream(), + acc: a, + srv: s, + cfg: cfg.ConsumerConfig, + active: false, + stream: mset.name(), + name: cfg.Name, + dseq: 1, + sseq: 1, + created: time.Now().UTC(), + closed: true, + offlineReason: offlineReason, + } + if !cfg.Created.IsZero() { + o.created = cfg.Created + } + + mset.mu.Lock() + mset.setConsumer(o) + mset.mu.Unlock() + } + continue + } + + isEphemeral := !isDurableConsumer(&cfg.ConsumerConfig) + if isEphemeral { + // This is an ephemeral consumer and this could fail on restart until + // the consumer can reconnect. We will create it as a durable and switch it. + cfg.ConsumerConfig.Durable = ofi.Name() + } + obs, err := mset.addConsumerWithAssignment(&cfg.ConsumerConfig, _EMPTY_, nil, true, ActionCreateOrUpdate, false) + if err != nil { + s.Warnf(" Error adding consumer '%s > %s > %s': %v", a.Name, mset.name(), cfg.Name, err) + continue + } + if isEphemeral { + obs.switchToEphemeral() + } + if !cfg.Created.IsZero() { + obs.setCreatedTime(cfg.Created) + } + } + } + // Now recover the streams. - fis, _ := ioutil.ReadDir(sdir) - for _, fi := range fis { - mdir := path.Join(sdir, fi.Name()) + fis, _ := os.ReadDir(sdir) + doStream := func(fi os.DirEntry) error { + plaintext := true + mdir := filepath.Join(sdir, fi.Name()) + // Check for partially deleted streams. They are marked with "." prefix. + if strings.HasPrefix(fi.Name(), tsep) { + go os.RemoveAll(mdir) + return nil + } key := sha256.Sum256([]byte(fi.Name())) - hh, err := highwayhash.New64(key[:]) + hh, err := highwayhash.NewDigest64(key[:]) if err != nil { return err } - metafile := path.Join(mdir, JetStreamMetaFile) - metasum := path.Join(mdir, JetStreamMetaFileSum) + metafile := filepath.Join(mdir, JetStreamMetaFile) + metasum := filepath.Join(mdir, JetStreamMetaFileSum) if _, err := os.Stat(metafile); os.IsNotExist(err) { - s.Warnf(" Missing Stream metafile for %q", metafile) - continue + s.Warnf(" Missing stream metafile for %q", metafile) + return nil } - buf, err := ioutil.ReadFile(metafile) + buf, err := os.ReadFile(metafile) if err != nil { - s.Warnf(" Error reading metafile %q: %v", metasum, err) - continue + s.Warnf(" Error reading metafile %q: %v", metafile, err) + return nil } if _, err := os.Stat(metasum); os.IsNotExist(err) { - s.Warnf(" Missing Stream checksum for %q", metasum) - continue + s.Warnf(" Missing stream checksum file %q", metasum) + return nil } - sum, err := ioutil.ReadFile(metasum) + sum, err := os.ReadFile(metasum) if err != nil { s.Warnf(" Error reading Stream metafile checksum %q: %v", metasum, err) - continue + return nil } hh.Write(buf) - checksum := hex.EncodeToString(hh.Sum(nil)) + var hb [highwayhash.Size64]byte + checksum := hex.EncodeToString(hh.Sum(hb[:0])) if checksum != string(sum) { - s.Warnf(" Stream metafile checksums do not match %q vs %q", sum, checksum) - continue + s.Warnf(" Stream metafile %q: checksums do not match %q vs %q", metafile, sum, checksum) + return nil + } + + // Track if we are converting ciphers. + var convertingCiphers bool + + // Check if we are encrypted. + keyFile := filepath.Join(mdir, JetStreamMetaFileKey) + keyBuf, err := os.ReadFile(keyFile) + if err == nil { + s.Debugf(" Stream metafile is encrypted, reading encrypted keyfile") + if len(keyBuf) < minMetaKeySize { + s.Warnf(" Bad stream encryption key length of %d", len(keyBuf)) + return nil + } + // Decode the buffer before proceeding. + var nbuf []byte + nbuf, convertingCiphers, err = s.decryptMeta(sc, keyBuf, buf, a.Name, fi.Name()) + if err != nil { + s.Warnf(" Error decrypting our stream metafile: %v", err) + return nil + } + buf = nbuf + plaintext = false } var cfg FileStreamInfo - if err := json.Unmarshal(buf, &cfg); err != nil { - s.Warnf(" Error unmarshalling Stream metafile: %v", err) - continue + decoder := json.NewDecoder(bytes.NewReader(buf)) + decoder.DisallowUnknownFields() + strictErr := decoder.Decode(&cfg) + if strictErr != nil { + cfg = FileStreamInfo{} + if err := json.Unmarshal(buf, &cfg); err != nil { + s.Warnf(" Error unmarshalling stream metafile %q: %v", metafile, err) + return nil + } + } + if supported := supportsRequiredApiLevel(cfg.Metadata); !supported || strictErr != nil { + var offlineReason string + if !supported { + apiLevel := getRequiredApiLevel(cfg.Metadata) + if strictErr != nil { + offlineReason = fmt.Sprintf("unsupported - config error: %s", strings.TrimPrefix(strictErr.Error(), "json: ")) + } else { + offlineReason = fmt.Sprintf("unsupported - required API level: %s, current API level: %d", apiLevel, JSApiLevel) + } + s.Warnf(" Detected unsupported stream '%s > %s': %s", a.Name, cfg.StreamConfig.Name, offlineReason) + } else { + offlineReason = fmt.Sprintf("decoding error: %v", strictErr) + s.Warnf(" Error unmarshalling stream metafile %q: %v", metafile, strictErr) + } + singleServerMode := !s.JetStreamIsClustered() && s.standAloneMode() + if singleServerMode { + // Fake a stream, so we can respond to API requests as single-server. + mset := &stream{ + acc: a, + jsa: jsa, + cfg: cfg.StreamConfig, + js: js, + srv: s, + stype: cfg.Storage, + consumers: make(map[string]*consumer), + active: false, + created: time.Now().UTC(), + offlineReason: offlineReason, + } + if !cfg.Created.IsZero() { + mset.created = cfg.Created + } + mset.closed.Store(true) + + jsa.mu.Lock() + jsa.streams[cfg.Name] = mset + jsa.mu.Unlock() + + // Now do the consumers. + odir := filepath.Join(sdir, fi.Name(), consumerDir) + doConsumers(mset, odir) + } + return nil } + if cfg.Template != _EMPTY_ { - if err := jsa.addStreamNameToTemplate(cfg.Template, cfg.Name); err != nil { - s.Warnf(" Error adding Stream %q to Template %q: %v", cfg.Name, cfg.Template, err) + jsa.mu.Lock() + err := jsa.addStreamNameToTemplate(cfg.Template, cfg.Name) + jsa.mu.Unlock() + if err != nil { + s.Warnf(" Error adding stream %q to template %q: %v", cfg.Name, cfg.Template, err) + } + } + + // We had a bug that set a default de dupe window on mirror, despite that being not a valid config + fixCfgMirrorWithDedupWindow(&cfg.StreamConfig) + + // We had a bug that could allow subjects in that had prefix or suffix spaces. We check for that here + // and will patch them on the fly for now. We will warn about them. + var hadSubjErr bool + for i, subj := range cfg.StreamConfig.Subjects { + if !IsValidSubject(subj) { + s.Warnf(" Detected bad subject %q while adding stream %q, will attempt to repair", subj, cfg.Name) + if nsubj := strings.TrimSpace(subj); IsValidSubject(nsubj) { + s.Warnf(" Bad subject %q repaired to %q", subj, nsubj) + cfg.StreamConfig.Subjects[i] = nsubj + } else { + s.Warnf(" Error recreating stream %q: %v", cfg.Name, "invalid subject") + hadSubjErr = true + break + } } } - mset, err := a.AddStream(&cfg.StreamConfig) + if hadSubjErr { + return nil + } + + // The other possible bug is assigning subjects to mirrors, so check for that and patch as well. + if cfg.StreamConfig.Mirror != nil && len(cfg.StreamConfig.Subjects) > 0 { + s.Warnf(" Detected subjects on a mirrored stream %q, will remove", cfg.Name) + cfg.StreamConfig.Subjects = nil + } + + s.Noticef(" Starting restore for stream '%s > %s'", a.Name, cfg.StreamConfig.Name) + rt := time.Now() + + // Log if we are converting from plaintext to encrypted. + if encrypted { + if plaintext { + s.Noticef(" Encrypting stream '%s > %s'", a.Name, cfg.StreamConfig.Name) + } else if convertingCiphers { + s.Noticef(" Converting to %s for stream '%s > %s'", sc, a.Name, cfg.StreamConfig.Name) + // Remove the key file to have system regenerate with the new cipher. + os.Remove(keyFile) + } + } + + // Add in the stream. + mset, err := a.addStream(&cfg.StreamConfig) if err != nil { - s.Warnf(" Error recreating Stream %q: %v", cfg.Name, err) - continue + s.Warnf(" Error recreating stream %q: %v", cfg.Name, err) + // If we removed a keyfile from above make sure to put it back. + if convertingCiphers { + err := os.WriteFile(keyFile, keyBuf, defaultFilePerms) + if err != nil { + s.Warnf(" Error replacing meta keyfile for stream %q: %v", cfg.Name, err) + } + } + return nil } if !cfg.Created.IsZero() { - mset.setCreated(cfg.Created) + mset.setCreatedTime(cfg.Created) } - stats := mset.State() - s.Noticef(" Restored %s messages for Stream %q", comma(int64(stats.Msgs)), fi.Name()) + state := mset.state() + s.Noticef(" Restored %s messages for stream '%s > %s' in %v", + comma(int64(state.Msgs)), mset.accName(), mset.name(), time.Since(rt).Round(time.Millisecond)) // Now do the consumers. - odir := path.Join(sdir, fi.Name(), consumerDir) - ofis, _ := ioutil.ReadDir(odir) - if len(ofis) > 0 { - s.Noticef(" Recovering %d Consumers for Stream - %q", len(ofis), fi.Name()) + odir := filepath.Join(sdir, fi.Name(), consumerDir) + doConsumers(mset, odir) + + // Collect to check for dangling messages. + // TODO(dlc) - Can be removed eventually. + if cfg.StreamConfig.Retention == InterestPolicy { + mset.checkForOrphanMsgs() + mset.checkConsumerReplication() } - for _, ofi := range ofis { - metafile := path.Join(odir, ofi.Name(), JetStreamMetaFile) - metasum := path.Join(odir, ofi.Name(), JetStreamMetaFileSum) - if _, err := os.Stat(metafile); os.IsNotExist(err) { - s.Warnf(" Missing Consumer Metafile %q", metafile) - continue - } - buf, err := ioutil.ReadFile(metafile) - if err != nil { - s.Warnf(" Error reading consumer metafile %q: %v", metasum, err) - continue - } - if _, err := os.Stat(metasum); os.IsNotExist(err) { - s.Warnf(" Missing Consumer checksum for %q", metasum) - continue - } - var cfg FileConsumerInfo - if err := json.Unmarshal(buf, &cfg); err != nil { - s.Warnf(" Error unmarshalling Consumer metafile: %v", err) - continue - } - isEphemeral := !isDurableConsumer(&cfg.ConsumerConfig) - if isEphemeral { - // This is an ephermal consumer and this could fail on restart until - // the consumer can reconnect. We will create it as a durable and switch it. - cfg.ConsumerConfig.Durable = ofi.Name() - } - obs, err := mset.AddConsumer(&cfg.ConsumerConfig) - if err != nil { - s.Warnf(" Error adding Consumer: %v", err) - continue - } - if isEphemeral { - obs.switchToEphemeral() - } - if !cfg.Created.IsZero() { - obs.setCreated(cfg.Created) - } - if err := obs.readStoredState(); err != nil { - s.Warnf(" Error restoring Consumer state: %v", err) + + return nil + } + + if tq != nil { + // If a parallelTaskQueue was provided then use that for concurrency. + var wg sync.WaitGroup + wg.Add(len(fis)) + for _, fi := range fis { + tq <- func() { + doStream(fi) + wg.Done() } } + wg.Wait() + } else { + // No parallelTaskQueue provided, do inline as before. + for _, fi := range fis { + doStream(fi) + } } - // Make sure to cleanup and old remaining snapshots. - os.RemoveAll(path.Join(jsa.storeDir, snapsDir)) + // Make sure to cleanup any old remaining snapshots. + os.RemoveAll(filepath.Join(jsa.storeDir, snapsDir)) - s.Noticef("JetStream state for account %q recovered", a.Name) + s.Debugf("JetStream state for account %q recovered", a.Name) return nil } +// Return whether we require MaxBytes to be set and if > 0 an upper limit for stream size exists +// Both limits are independent of each other. +func (a *Account) maxBytesLimits(cfg *StreamConfig) (bool, int64) { + a.mu.RLock() + jsa := a.js + a.mu.RUnlock() + if jsa == nil { + return false, 0 + } + jsa.usageMu.RLock() + var replicas int + if cfg != nil { + replicas = cfg.Replicas + } + selectedLimits, _, ok := jsa.selectLimits(replicas) + jsa.usageMu.RUnlock() + if !ok { + return false, 0 + } + maxStreamBytes := int64(0) + if cfg.Storage == MemoryStorage { + maxStreamBytes = selectedLimits.MemoryMaxStreamBytes + } else { + maxStreamBytes = selectedLimits.StoreMaxStreamBytes + } + return selectedLimits.MaxBytesRequired, maxStreamBytes +} + // NumStreams will return how many streams we have. -func (a *Account) NumStreams() int { +func (a *Account) numStreams() int { a.mu.RLock() jsa := a.js a.mu.RUnlock() @@ -618,11 +1666,11 @@ func (a *Account) NumStreams() int { } // Streams will return all known streams. -func (a *Account) Streams() []*Stream { +func (a *Account) streams() []*stream { return a.filteredStreams(_EMPTY_) } -func (a *Account) filteredStreams(filter string) []*Stream { +func (a *Account) filteredStreams(filter string) []*stream { a.mu.RLock() jsa := a.js a.mu.RUnlock() @@ -631,18 +1679,20 @@ func (a *Account) filteredStreams(filter string) []*Stream { return nil } - jsa.mu.Lock() - defer jsa.mu.Unlock() + jsa.mu.RLock() + defer jsa.mu.RUnlock() - var msets []*Stream + var msets []*stream for _, mset := range jsa.streams { if filter != _EMPTY_ { - for _, subj := range mset.config.Subjects { + mset.cfgMu.RLock() + for _, subj := range mset.cfg.Subjects { if SubjectsCollide(filter, subj) { msets = append(msets, mset) break } } + mset.cfgMu.RUnlock() } else { msets = append(msets, mset) } @@ -651,29 +1701,29 @@ func (a *Account) filteredStreams(filter string) []*Stream { return msets } -// LookupStream will lookup a stream by name. -func (a *Account) LookupStream(name string) (*Stream, error) { +// lookupStream will lookup a stream by name. +func (a *Account) lookupStream(name string) (*stream, error) { a.mu.RLock() jsa := a.js a.mu.RUnlock() if jsa == nil { - return nil, ErrJetStreamNotEnabled + return nil, NewJSNotEnabledForAccountError() } - jsa.mu.Lock() + jsa.mu.RLock() + defer jsa.mu.RUnlock() + mset, ok := jsa.streams[name] - jsa.mu.Unlock() if !ok { - return nil, ErrJetStreamStreamNotFound + return nil, NewJSStreamNotFoundError() } return mset, nil } // UpdateJetStreamLimits will update the account limits for a JetStream enabled account. -func (a *Account) UpdateJetStreamLimits(limits *JetStreamAccountLimits) error { +func (a *Account) UpdateJetStreamLimits(limits map[string]JetStreamAccountLimits) error { a.mu.RLock() - s := a.srv - jsa := a.js + s, jsa := a.srv, a.js a.mu.RUnlock() if s == nil { @@ -681,68 +1731,227 @@ func (a *Account) UpdateJetStreamLimits(limits *JetStreamAccountLimits) error { } js := s.getJetStream() if js == nil { - return ErrJetStreamNotEnabled + return NewJSNotEnabledError() } if jsa == nil { - return ErrJetStreamNotEnabledForAccount + return NewJSNotEnabledForAccountError() } - if limits == nil { - limits = js.dynamicAccountLimits() + if len(limits) == 0 { + limits = defaultJSAccountTiers } // Calculate the delta between what we have and what we want. - jsa.mu.Lock() - dl := diffCheckedLimits(&jsa.limits, limits) - jsaLimits := jsa.limits - jsa.mu.Unlock() + jsa.usageMu.RLock() + dl := diffCheckedLimits(jsa.limits, limits) + jsa.usageMu.RUnlock() js.mu.Lock() // Check the limits against existing reservations. - if err := js.sufficientResources(&dl); err != nil { + if err := js.sufficientResources(dl); err != nil { js.mu.Unlock() return err } - // FIXME(dlc) - If we drop and are over the max on memory or store, do we delete?? - js.releaseResources(&jsaLimits) - js.reserveResources(limits) js.mu.Unlock() // Update - jsa.mu.Lock() - jsa.limits = *limits - jsa.mu.Unlock() + jsa.usageMu.Lock() + jsa.limits = limits + jsa.usageMu.Unlock() return nil } -func diffCheckedLimits(a, b *JetStreamAccountLimits) JetStreamAccountLimits { - return JetStreamAccountLimits{ - MaxMemory: b.MaxMemory - a.MaxMemory, - MaxStore: b.MaxStore - a.MaxStore, +func diffCheckedLimits(a, b map[string]JetStreamAccountLimits) map[string]JetStreamAccountLimits { + diff := map[string]JetStreamAccountLimits{} + for t, la := range a { + // in a, not in b will return 0 + lb := b[t] + diff[t] = JetStreamAccountLimits{ + MaxMemory: lb.MaxMemory - la.MaxMemory, + MaxStore: lb.MaxStore - la.MaxStore, + } + } + for t, lb := range b { + if la, ok := a[t]; !ok { + // only in b not in a. (in a and b already covered) + diff[t] = JetStreamAccountLimits{ + MaxMemory: lb.MaxMemory - la.MaxMemory, + MaxStore: lb.MaxStore - la.MaxStore, + } + } + } + return diff +} + +// Return reserved bytes for memory and file store streams for this account on this server. +// Lock should be held. +func (jsa *jsAccount) reservedStorage(tier string) (mem, store uint64) { + for _, mset := range jsa.streams { + cfg := &mset.cfg + if (tier == _EMPTY_ || tier == tierName(cfg.Replicas)) && cfg.MaxBytes > 0 { + switch cfg.Storage { + case FileStorage: + store += uint64(cfg.MaxBytes) + case MemoryStorage: + mem += uint64(cfg.MaxBytes) + } + } + } + return mem, store +} + +// Return reserved bytes for memory and file store streams for this account in clustered mode. +// js lock should be held. +func reservedStorage(sas map[string]*streamAssignment, tier string) (mem, store uint64) { + for _, sa := range sas { + cfg := sa.Config + if (tier == _EMPTY_ || tier == tierName(cfg.Replicas)) && cfg.MaxBytes > 0 { + switch cfg.Storage { + case FileStorage: + store += uint64(cfg.MaxBytes) + case MemoryStorage: + mem += uint64(cfg.MaxBytes) + } + } } + return mem, store } // JetStreamUsage reports on JetStream usage and limits for an account. func (a *Account) JetStreamUsage() JetStreamAccountStats { a.mu.RLock() - jsa := a.js + jsa, aname := a.js, a.Name + accJsLimits := a.jsLimits a.mu.RUnlock() var stats JetStreamAccountStats if jsa != nil { - jsa.mu.Lock() - stats.Memory = uint64(jsa.memUsed) - stats.Store = uint64(jsa.storeUsed) - stats.Streams = len(jsa.streams) - stats.Limits = jsa.limits - jsa.mu.Unlock() + js := jsa.js + js.mu.RLock() + cc := js.cluster + singleServer := cc == nil + jsa.mu.RLock() + jsa.usageMu.RLock() + stats.Memory, stats.Store = jsa.storageTotals() + stats.Domain = js.config.Domain + stats.API = JetStreamAPIStats{ + Level: JSApiLevel, + Total: jsa.apiTotal, + Errors: jsa.apiErrors, + } + if singleServer { + stats.ReservedMemory, stats.ReservedStore = jsa.reservedStorage(_EMPTY_) + } else { + stats.ReservedMemory, stats.ReservedStore = reservedStorage(cc.streams[aname], _EMPTY_) + } + l, defaultTier := jsa.limits[_EMPTY_] + if defaultTier { + stats.Limits = l + } else { + skipped := 0 + stats.Tiers = make(map[string]JetStreamTier) + for t, total := range jsa.usage { + if _, ok := jsa.limits[t]; !ok && (*total) == (jsaStorage{}) { + // skip tiers not present that don't contain a count + // In case this shows an empty stream, that tier will be added when iterating over streams + skipped++ + } else { + tier := JetStreamTier{ + Memory: uint64(total.total.mem), + Store: uint64(total.total.store), + Limits: jsa.limits[t], + } + if singleServer { + tier.ReservedMemory, tier.ReservedStore = jsa.reservedStorage(t) + } else { + tier.ReservedMemory, tier.ReservedStore = reservedStorage(cc.streams[aname], t) + } + stats.Tiers[t] = tier + } + } + if len(accJsLimits) != len(jsa.usage)-skipped { + // insert unused limits + for t, lim := range accJsLimits { + if _, ok := stats.Tiers[t]; !ok { + tier := JetStreamTier{Limits: lim} + if singleServer { + tier.ReservedMemory, tier.ReservedStore = jsa.reservedStorage(t) + } else { + tier.ReservedMemory, tier.ReservedStore = reservedStorage(cc.streams[aname], t) + } + stats.Tiers[t] = tier + } + } + } + } + jsa.usageMu.RUnlock() + + // Clustered + if cc := js.cluster; cc != nil { + sas := cc.streams[aname] + if defaultTier { + stats.Streams = len(sas) + stats.ReservedMemory, stats.ReservedStore = reservedStorage(sas, _EMPTY_) + } + for _, sa := range sas { + if defaultTier { + stats.Consumers += len(sa.consumers) + } else { + stats.Streams++ + streamTier := tierName(sa.Config.Replicas) + su, ok := stats.Tiers[streamTier] + if !ok { + su = JetStreamTier{} + } + su.Streams++ + stats.Tiers[streamTier] = su + + // Now consumers, check each since could be different tiers. + for _, ca := range sa.consumers { + stats.Consumers++ + consumerTier := tierName(ca.Config.replicas(sa.Config)) + cu, ok := stats.Tiers[consumerTier] + if !ok { + cu = JetStreamTier{} + } + cu.Consumers++ + stats.Tiers[consumerTier] = cu + } + } + } + } else { + if defaultTier { + stats.Streams = len(jsa.streams) + } + for _, mset := range jsa.streams { + consCount := mset.numConsumers() + stats.Consumers += consCount + if !defaultTier { + u, ok := stats.Tiers[mset.tier] + if !ok { + u = JetStreamTier{} + } + u.Streams++ + stats.Streams++ + u.Consumers += consCount + stats.Tiers[mset.tier] = u + } + } + } + jsa.mu.RUnlock() + js.mu.RUnlock() } return stats } // DisableJetStream will disable JetStream for this account. func (a *Account) DisableJetStream() error { + return a.removeJetStream() +} + +// removeJetStream is called when JetStream has been disabled for this account. +func (a *Account) removeJetStream() error { a.mu.Lock() s := a.srv a.js = nil @@ -754,12 +1963,7 @@ func (a *Account) DisableJetStream() error { js := s.getJetStream() if js == nil { - return ErrJetStreamNotEnabled - } - - // Remove service imports. - for _, export := range allJsExports { - a.removeServiceImport(export) + return NewJSNotEnabledForAccountError() } return js.disableJetStream(js.lookupAccount(a)) @@ -767,13 +1971,12 @@ func (a *Account) DisableJetStream() error { // Disable JetStream for the account. func (js *jetStream) disableJetStream(jsa *jsAccount) error { - if jsa == nil { - return ErrJetStreamNotEnabledForAccount + if jsa == nil || jsa.account == nil { + return NewJSNotEnabledForAccountError() } js.mu.Lock() - delete(js.accounts, jsa.account) - js.releaseResources(&jsa.limits) + delete(js.accounts, jsa.account.Name) js.mu.Unlock() jsa.delete() @@ -781,6 +1984,17 @@ func (js *jetStream) disableJetStream(jsa *jsAccount) error { return nil } +// jetStreamConfigured reports whether the account has JetStream configured, regardless of this +// servers JetStream status. +func (a *Account) jetStreamConfigured() bool { + if a == nil { + return false + } + a.mu.RLock() + defer a.mu.RUnlock() + return len(a.jsLimits) > 0 +} + // JetStreamEnabled is a helper to determine if jetstream is enabled for an account. func (a *Account) JetStreamEnabled() bool { if a == nil { @@ -792,86 +2006,484 @@ func (a *Account) JetStreamEnabled() bool { return enabled } -// Updates accounting on in use memory and storage. -func (jsa *jsAccount) updateUsage(storeType StorageType, delta int64) { - // TODO(dlc) - atomics? snapshot limits? - jsa.mu.Lock() +func (jsa *jsAccount) remoteUpdateUsage(sub *subscription, c *client, _ *Account, subject, _ string, msg []byte) { + // jsa.js.srv is immutable and guaranteed to no be nil, so no lock needed. + s := jsa.js.srv + + jsa.usageMu.Lock() + defer jsa.usageMu.Unlock() + + if len(msg) < minUsageUpdateLen { + s.Warnf("Ignoring remote usage update with size too short") + return + } + var rnode string + if li := strings.LastIndexByte(subject, btsep); li > 0 && li < len(subject) { + rnode = subject[li+1:] + } + if rnode == _EMPTY_ { + s.Warnf("Received remote usage update with no remote node") + return + } + rUsage, ok := jsa.rusage[rnode] + if !ok { + if jsa.rusage == nil { + jsa.rusage = make(map[string]*remoteUsage) + } + rUsage = &remoteUsage{tiers: make(map[string]*jsaUsage)} + jsa.rusage[rnode] = rUsage + } + updateTotal := func(tierName string, memUsed, storeUsed int64) { + total, ok := jsa.usage[tierName] + if !ok { + total = &jsaStorage{} + jsa.usage[tierName] = total + } + // Update the usage for this remote. + if usage := rUsage.tiers[tierName]; usage != nil { + // Decrement our old values. + total.total.mem -= usage.mem + total.total.store -= usage.store + usage.mem, usage.store = memUsed, storeUsed + } else { + rUsage.tiers[tierName] = &jsaUsage{memUsed, storeUsed} + } + total.total.mem += memUsed + total.total.store += storeUsed + } + + var le = binary.LittleEndian + apiTotal, apiErrors := le.Uint64(msg[16:]), le.Uint64(msg[24:]) + memUsed, storeUsed := int64(le.Uint64(msg[0:])), int64(le.Uint64(msg[8:])) + + // We later extended the data structure to support multiple tiers + var excessRecordCnt uint32 + var tierName string + + if len(msg) >= usageMultiTiersLen { + excessRecordCnt = le.Uint32(msg[minUsageUpdateLen:]) + length := le.Uint64(msg[minUsageUpdateLen+4:]) + // Need to protect past this point in case this is wrong. + if uint64(len(msg)) < usageMultiTiersLen+length { + s.Warnf("Received corrupt remote usage update") + return + } + tierName = string(msg[usageMultiTiersLen : usageMultiTiersLen+length]) + msg = msg[usageMultiTiersLen+length:] + } + updateTotal(tierName, memUsed, storeUsed) + for ; excessRecordCnt > 0 && len(msg) >= usageRecordLen; excessRecordCnt-- { + memUsed, storeUsed := int64(le.Uint64(msg[0:])), int64(le.Uint64(msg[8:])) + length := le.Uint64(msg[16:]) + if uint64(len(msg)) < usageRecordLen+length { + s.Warnf("Received corrupt remote usage update on excess record") + return + } + tierName = string(msg[usageRecordLen : usageRecordLen+length]) + msg = msg[usageRecordLen+length:] + updateTotal(tierName, memUsed, storeUsed) + } + jsa.apiTotal -= rUsage.api + jsa.apiErrors -= rUsage.err + rUsage.api = apiTotal + rUsage.err = apiErrors + jsa.apiTotal += apiTotal + jsa.apiErrors += apiErrors +} + +// When we detect a skew of some sort this will verify the usage reporting is correct. +// No locks should be held. +func (jsa *jsAccount) checkAndSyncUsage(tierName string, storeType StorageType) { + // This will run in a separate go routine, so check that we are only running once. + if !jsa.sync.CompareAndSwap(false, true) { + return + } + defer jsa.sync.Store(false) + + // Hold the account read lock and the usage lock while we calculate. + // We scope by tier and storage type, but if R3 File has 200 streams etc. could + // show a pause. I did test with > 100 non-active streams and was 80-200ns or so. + // Should be rare this gets called as well. + jsa.mu.RLock() + defer jsa.mu.RUnlock() + js := jsa.js + if js == nil { + return + } + s := js.srv + + // We need to collect the stream stores before we acquire the usage lock since in storeUpdates the + // stream lock could be held if deletion are inline with storing a new message, e.g. via limits. + var stores []StreamStore + for _, mset := range jsa.streams { + mset.mu.RLock() + if mset.tier == tierName && mset.stype == storeType && mset.store != nil { + stores = append(stores, mset.store) + } + mset.mu.RUnlock() + } + + // Now range and qualify, hold usage lock to prevent updates. + jsa.usageMu.Lock() + defer jsa.usageMu.Unlock() + + usage, ok := jsa.usage[tierName] + if !ok { + return + } + + // Collect current total for all stream stores that matched. + var total int64 + var state StreamState + for _, store := range stores { + store.FastState(&state) + total += int64(state.Bytes) + } + + var needClusterUpdate bool + // If we do not match on our calculations compute delta and adjust. if storeType == MemoryStorage { - jsa.memUsed += delta + if total != usage.local.mem { + s.Warnf("MemStore usage drift of %v vs %v detected for account %q", + friendlyBytes(total), friendlyBytes(usage.local.mem), jsa.account.GetName()) + delta := total - usage.local.mem + usage.local.mem += delta + usage.total.mem += delta + atomic.AddInt64(&js.memUsed, delta) + needClusterUpdate = true + } } else { - jsa.storeUsed += delta + if total != usage.local.store { + s.Warnf("FileStore usage drift of %v vs %v detected for account %q", + friendlyBytes(total), friendlyBytes(usage.local.store), jsa.account.GetName()) + delta := total - usage.local.store + usage.local.store += delta + usage.total.store += delta + atomic.AddInt64(&js.storeUsed, delta) + needClusterUpdate = true + } + } + + // Publish our local updates if in clustered mode. + if needClusterUpdate && js.isClusteredNoLock() { + jsa.sendClusterUsageUpdate() } - jsa.mu.Unlock() } -func (jsa *jsAccount) limitsExceeded(storeType StorageType) bool { - var exceeded bool - jsa.mu.Lock() +// Updates accounting on in use memory and storage. This is called from locally +// by the lower storage layers. +func (jsa *jsAccount) updateUsage(tierName string, storeType StorageType, delta int64) { + // jsa.js is immutable and cannot be nil, so ok w/o lock. + js := jsa.js + // updateUsage() may be invoked under the mset's lock, so we can't get + // the js' lock to check if clustered. So use this function that make + // use of an atomic to do the check without having data race reports. + isClustered := js.isClusteredNoLock() + + var needsCheck bool + jsa.usageMu.Lock() + s, ok := jsa.usage[tierName] + if !ok { + s = &jsaStorage{} + jsa.usage[tierName] = s + } if storeType == MemoryStorage { - if jsa.limits.MaxMemory > 0 && jsa.memUsed > jsa.limits.MaxMemory { - exceeded = true - } + s.local.mem += delta + s.total.mem += delta + atomic.AddInt64(&js.memUsed, delta) + needsCheck = s.local.mem < 0 + } else { + s.local.store += delta + s.total.store += delta + atomic.AddInt64(&js.storeUsed, delta) + needsCheck = s.local.store < 0 + } + // Publish our local updates if in clustered mode. + if isClustered { + jsa.sendClusterUsageUpdate() + } + jsa.usageMu.Unlock() + + if needsCheck { + // We could be holding the stream lock from up in the stack, and this + // will want the jsa lock, which would violate locking order. + // So do this in a Go routine. The function will check if it is already running. + go jsa.checkAndSyncUsage(tierName, storeType) + } +} + +var usageTick = 1500 * time.Millisecond + +func (jsa *jsAccount) sendClusterUsageUpdateTimer() { + jsa.usageMu.Lock() + defer jsa.usageMu.Unlock() + jsa.sendClusterUsageUpdate() + if jsa.utimer != nil { + jsa.utimer.Reset(usageTick) + } +} + +// For usage fields. +const ( + minUsageUpdateLen = 32 + stackUsageUpdate = 72 + usageRecordLen = 24 + usageMultiTiersLen = 44 + apiStatsAndNumTiers = 20 + minUsageUpdateWindow = 250 * time.Millisecond +) + +// Send updates to our account usage for this server. +// jsa.usageMu lock should be held. +func (jsa *jsAccount) sendClusterUsageUpdate() { + // These values are absolute so we can limit send rates. + now := time.Now() + if now.Sub(jsa.lupdate) < minUsageUpdateWindow { + return + } + jsa.lupdate = now + + lenUsage := len(jsa.usage) + if lenUsage == 0 { + return + } + // every base record contains mem/store/len(tier) as well as the tier name + l := usageRecordLen * lenUsage + for tier := range jsa.usage { + l += len(tier) + } + // first record contains api/usage errors as well as count for extra base records + l += apiStatsAndNumTiers + + var raw [stackUsageUpdate]byte + var b []byte + if l > stackUsageUpdate { + b = make([]byte, l) } else { - if jsa.limits.MaxStore > 0 && jsa.storeUsed > jsa.limits.MaxStore { - exceeded = true + b = raw[:l] + } + + var i int + var le = binary.LittleEndian + for tier, usage := range jsa.usage { + le.PutUint64(b[i+0:], uint64(usage.local.mem)) + le.PutUint64(b[i+8:], uint64(usage.local.store)) + if i == 0 { + le.PutUint64(b[16:], jsa.usageApi) + le.PutUint64(b[24:], jsa.usageErr) + le.PutUint32(b[32:], uint32(len(jsa.usage)-1)) + le.PutUint64(b[36:], uint64(len(tier))) + copy(b[usageMultiTiersLen:], tier) + i = usageMultiTiersLen + len(tier) + } else { + le.PutUint64(b[i+16:], uint64(len(tier))) + copy(b[i+usageRecordLen:], tier) + i += usageRecordLen + len(tier) } } - jsa.mu.Unlock() - return exceeded + jsa.sendq.push(newPubMsg(nil, jsa.updatesPub, _EMPTY_, nil, nil, b, noCompression, false, false)) +} + +func (js *jetStream) wouldExceedLimits(storeType StorageType, sz int) bool { + var ( + total *int64 + max int64 + ) + if storeType == MemoryStorage { + total, max = &js.memUsed, js.config.MaxMemory + } else { + total, max = &js.storeUsed, js.config.MaxStore + } + return (atomic.LoadInt64(total) + int64(sz)) > max +} + +func (js *jetStream) limitsExceeded(storeType StorageType) bool { + return js.wouldExceedLimits(storeType, 0) +} + +func tierName(replicas int) string { + // TODO (mh) this is where we could select based off a placement tag as well "qos:tier" + if replicas == 0 { + replicas = 1 + } + return fmt.Sprintf("R%d", replicas) +} + +func isSameTier(cfgA, cfgB *StreamConfig) bool { + // TODO (mh) this is where we could select based off a placement tag as well "qos:tier" + return cfgA.Replicas == cfgB.Replicas +} + +func (jsa *jsAccount) jetStreamAndClustered() (*jetStream, bool) { + jsa.mu.RLock() + js := jsa.js + jsa.mu.RUnlock() + return js, js.isClustered() +} + +// jsa.usageMu read lock should be held. +func (jsa *jsAccount) selectLimits(replicas int) (JetStreamAccountLimits, string, bool) { + if selectedLimits, ok := jsa.limits[_EMPTY_]; ok { + return selectedLimits, _EMPTY_, true + } + tier := tierName(replicas) + if selectedLimits, ok := jsa.limits[tier]; ok { + return selectedLimits, tier, true + } + return JetStreamAccountLimits{}, _EMPTY_, false } -// Check if a new proposed msg set while exceed our account limits. // Lock should be held. -func (jsa *jsAccount) checkLimits(config *StreamConfig) error { - if jsa.limits.MaxStreams > 0 && len(jsa.streams) >= jsa.limits.MaxStreams { - return fmt.Errorf("maximum number of streams reached") +func (jsa *jsAccount) countStreams(tier string, cfg *StreamConfig) (streams int) { + for _, sa := range jsa.streams { + // Don't count the stream toward the limit if it already exists. + if (tier == _EMPTY_ || isSameTier(&sa.cfg, cfg)) && sa.cfg.Name != cfg.Name { + streams++ + } } - // FIXME(dlc) - Add check here for replicas based on clustering. - if config.Replicas != 1 { - return fmt.Errorf("replicas setting of %d not allowed", config.Replicas) + return streams +} + +// jsa.usageMu read lock (at least) should be held. +func (jsa *jsAccount) storageTotals() (uint64, uint64) { + mem := uint64(0) + store := uint64(0) + for _, sa := range jsa.usage { + mem += uint64(sa.total.mem) + store += uint64(sa.total.store) } - // Check MaxConsumers - if config.MaxConsumers > 0 && jsa.limits.MaxConsumers > 0 && config.MaxConsumers > jsa.limits.MaxConsumers { - return fmt.Errorf("maximum consumers exceeds account limit") + return mem, store +} + +func (jsa *jsAccount) limitsExceeded(storeType StorageType, tierName string, replicas int) (bool, *ApiError) { + return jsa.wouldExceedLimits(storeType, tierName, replicas, _EMPTY_, nil, nil) +} + +func (jsa *jsAccount) wouldExceedLimits(storeType StorageType, tierName string, replicas int, subj string, hdr, msg []byte) (bool, *ApiError) { + jsa.usageMu.RLock() + defer jsa.usageMu.RUnlock() + + selectedLimits, ok := jsa.limits[tierName] + if !ok { + return true, NewJSNoLimitsError() + } + inUse := jsa.usage[tierName] + if inUse == nil { + // Imply totals of 0 + return false, nil + } + r := int64(replicas) + // Make sure replicas is correct. + if r < 1 { + r = 1 + } + // This is for limits. If we have no tier, consider all to be flat, vs tiers like R3 where we want to scale limit by replication. + lr := r + if tierName == _EMPTY_ { + lr = 1 } - // Check storage, memory or disk. - if config.MaxBytes > 0 { - return jsa.checkBytesLimits(config.MaxBytes*int64(config.Replicas), config.Storage) + // Since tiers are flat we need to scale limit up by replicas when checking. + if storeType == MemoryStorage { + totalMem := inUse.total.mem + (int64(memStoreMsgSize(subj, hdr, msg)) * r) + if selectedLimits.MemoryMaxStreamBytes > 0 && totalMem > selectedLimits.MemoryMaxStreamBytes*lr { + return true, nil + } + if selectedLimits.MaxMemory >= 0 && totalMem > selectedLimits.MaxMemory*lr { + return true, nil + } + } else { + totalStore := inUse.total.store + (int64(fileStoreMsgSize(subj, hdr, msg)) * r) + if selectedLimits.StoreMaxStreamBytes > 0 && totalStore > selectedLimits.StoreMaxStreamBytes*lr { + return true, nil + } + if selectedLimits.MaxStore >= 0 && totalStore > selectedLimits.MaxStore*lr { + return true, nil + } } - return nil + + return false, nil } -// Check if additional bytes will exceed our account limits. -// This should account for replicas. +// Check account limits. +// Read Lock should be held +func (js *jetStream) checkAccountLimits(selected *JetStreamAccountLimits, config *StreamConfig, currentRes int64) error { + return js.checkLimits(selected, config, false, currentRes, 0) +} + +// Check account and server limits. +// Read Lock should be held +func (js *jetStream) checkAllLimits(selected *JetStreamAccountLimits, config *StreamConfig, currentRes, maxBytesOffset int64) error { + return js.checkLimits(selected, config, true, currentRes, maxBytesOffset) +} + +// Check if a new proposed msg set while exceed our account limits. // Lock should be held. -func (jsa *jsAccount) checkBytesLimits(addBytes int64, storage StorageType) error { +func (js *jetStream) checkLimits(selected *JetStreamAccountLimits, config *StreamConfig, checkServer bool, currentRes, maxBytesOffset int64) error { + // Check MaxConsumers + if config.MaxConsumers > 0 && selected.MaxConsumers > 0 && config.MaxConsumers > selected.MaxConsumers { + return NewJSMaximumConsumersLimitError() + } + // stream limit is checked separately on stream create only! + // Check storage, memory or disk. + return js.checkBytesLimits(selected, config.MaxBytes, config.Storage, checkServer, currentRes, maxBytesOffset) +} + +// Check if additional bytes will exceed our account limits and optionally the server itself. +// Read Lock should be held. +func (js *jetStream) checkBytesLimits(selectedLimits *JetStreamAccountLimits, addBytes int64, storage StorageType, checkServer bool, currentRes, maxBytesOffset int64) error { + if addBytes < 0 { + addBytes = 1 + } + totalBytes := addBytes + maxBytesOffset + switch storage { case MemoryStorage: - if jsa.memReserved+addBytes > jsa.limits.MaxMemory { - return fmt.Errorf("insufficient memory resources available") + // Account limits defined. + if selectedLimits.MaxMemory >= 0 && currentRes+totalBytes > selectedLimits.MaxMemory { + return NewJSMemoryResourcesExceededError() + } + // Check if this server can handle request. + if checkServer && js.memReserved+totalBytes > js.config.MaxMemory { + return NewJSMemoryResourcesExceededError() } case FileStorage: - if jsa.storeReserved+addBytes > jsa.limits.MaxStore { - return fmt.Errorf("insufficient storage resources available") + // Account limits defined. + if selectedLimits.MaxStore >= 0 && currentRes+totalBytes > selectedLimits.MaxStore { + return NewJSStorageResourcesExceededError() + } + // Check if this server can handle request. + if checkServer && js.storeReserved+totalBytes > js.config.MaxStore { + return NewJSStorageResourcesExceededError() } } + return nil } func (jsa *jsAccount) acc() *Account { - jsa.mu.RLock() - acc := jsa.account - jsa.mu.RUnlock() - return acc + return jsa.account } // Delete the JetStream resources. func (jsa *jsAccount) delete() { - var streams []*Stream + var streams []*stream var ts []string jsa.mu.Lock() + // The update timer and subs need to be protected by usageMu lock + jsa.usageMu.Lock() + if jsa.utimer != nil { + jsa.utimer.Stop() + jsa.utimer = nil + } + if jsa.updatesSub != nil && jsa.js.srv != nil { + s := jsa.js.srv + s.sysUnsubscribe(jsa.updatesSub) + jsa.updatesSub = nil + } + jsa.usageMu.Unlock() + for _, ms := range jsa.streams { streams = append(streams, ms) } @@ -882,85 +2494,152 @@ func (jsa *jsAccount) delete() { jsa.templates = nil jsa.mu.Unlock() - for _, ms := range streams { - ms.stop(false) + for _, mset := range streams { + mset.stop(false, false) } for _, t := range ts { - acc.DeleteStreamTemplate(t) + acc.deleteStreamTemplate(t) } } // Lookup the jetstream account for a given account. func (js *jetStream) lookupAccount(a *Account) *jsAccount { + if a == nil { + return nil + } js.mu.RLock() - jsa := js.accounts[a] + jsa := js.accounts[a.Name] js.mu.RUnlock() return jsa } -// Will dynamically create limits for this account. -func (js *jetStream) dynamicAccountLimits() *JetStreamAccountLimits { +// Report on JetStream stats and usage for this server. +func (js *jetStream) usageStats() *JetStreamStats { + var stats JetStreamStats js.mu.RLock() - // For now used all resources. Mostly meant for $G in non-account mode. - limits := &JetStreamAccountLimits{js.config.MaxMemory, js.config.MaxStore, -1, -1} + stats.Accounts = len(js.accounts) + stats.ReservedMemory = uint64(js.memReserved) + stats.ReservedStore = uint64(js.storeReserved) + s := js.srv js.mu.RUnlock() - return limits + stats.API.Level = JSApiLevel + stats.API.Total = uint64(atomic.LoadInt64(&js.apiTotal)) + stats.API.Errors = uint64(atomic.LoadInt64(&js.apiErrors)) + stats.API.Inflight = uint64(atomic.LoadInt64(&js.apiInflight)) + // Make sure we do not report negative. + used := atomic.LoadInt64(&js.memUsed) + if used < 0 { + used = 0 + } + stats.Memory = uint64(used) + used = atomic.LoadInt64(&js.storeUsed) + if used < 0 { + used = 0 + } + stats.Store = uint64(used) + stats.HAAssets = s.numRaftNodes() + return &stats } // Check to see if we have enough system resources for this account. // Lock should be held. -func (js *jetStream) sufficientResources(limits *JetStreamAccountLimits) error { - if limits == nil { +func (js *jetStream) sufficientResources(limits map[string]JetStreamAccountLimits) error { + // If we are clustered we do not really know how many resources will be ultimately available. + // This needs to be handled out of band. + // If we are a single server, we can make decisions here. + if limits == nil || !js.standAlone { return nil } - if js.memReserved+limits.MaxMemory > js.config.MaxMemory { - return fmt.Errorf("insufficient memory resources available") + + totalMaxBytes := func(limits map[string]JetStreamAccountLimits) (int64, int64) { + totalMaxMemory := int64(0) + totalMaxStore := int64(0) + for _, l := range limits { + if l.MaxMemory > 0 { + totalMaxMemory += l.MaxMemory + } + if l.MaxStore > 0 { + totalMaxStore += l.MaxStore + } + } + return totalMaxMemory, totalMaxStore } - if js.storeReserved+limits.MaxStore > js.config.MaxStore { - return fmt.Errorf("insufficient storage resources available") + + totalMaxMemory, totalMaxStore := totalMaxBytes(limits) + + // Reserved is now specific to the MaxBytes for streams. + if js.memReserved+totalMaxMemory > js.config.MaxMemory { + return NewJSMemoryResourcesExceededError() + } + if js.storeReserved+totalMaxStore > js.config.MaxStore { + return NewJSStorageResourcesExceededError() } - return nil -} -// This will (blindly) reserve the respources requested. -// Lock should be held. -func (js *jetStream) reserveResources(limits *JetStreamAccountLimits) error { - if limits == nil { - return nil + // Since we know if we are here we are single server mode, check the account reservations. + var storeReserved, memReserved int64 + for _, jsa := range js.accounts { + if jsa.account.IsExpired() { + continue + } + jsa.usageMu.RLock() + maxMemory, maxStore := totalMaxBytes(jsa.limits) + jsa.usageMu.RUnlock() + memReserved += maxMemory + storeReserved += maxStore } - if limits.MaxMemory > 0 { - js.memReserved += limits.MaxMemory + + if memReserved+totalMaxMemory > js.config.MaxMemory { + return NewJSMemoryResourcesExceededError() } - if limits.MaxStore > 0 { - js.storeReserved += limits.MaxStore + if storeReserved+totalMaxStore > js.config.MaxStore { + return NewJSStorageResourcesExceededError() } + return nil } -// Lock should be held. -func (js *jetStream) releaseResources(limits *JetStreamAccountLimits) error { - if limits == nil { - return nil +// This will reserve the stream resources requested. +// This will spin off off of MaxBytes. +func (js *jetStream) reserveStreamResources(cfg *StreamConfig) { + if cfg == nil || cfg.MaxBytes <= 0 { + return } - if limits.MaxMemory > 0 { - js.memReserved -= limits.MaxMemory + + js.mu.Lock() + switch cfg.Storage { + case MemoryStorage: + js.memReserved += cfg.MaxBytes + case FileStorage: + js.storeReserved += cfg.MaxBytes } - if limits.MaxStore > 0 { - js.storeReserved -= limits.MaxStore + s, clustered := js.srv, !js.standAlone + js.mu.Unlock() + // If clustered send an update to the system immediately. + if clustered { + s.sendStatszUpdate() } - return nil } -// Will clear the resource reservations. Mostly for reload of a config. -func (js *jetStream) clearResources() { - if js == nil { +// Release reserved resources held by a stream. +func (js *jetStream) releaseStreamResources(cfg *StreamConfig) { + if cfg == nil || cfg.MaxBytes <= 0 { return } + js.mu.Lock() - js.memReserved = 0 - js.storeReserved = 0 + switch cfg.Storage { + case MemoryStorage: + js.memReserved -= cfg.MaxBytes + case FileStorage: + js.storeReserved -= cfg.MaxBytes + } + s, clustered := js.srv, !js.standAlone js.mu.Unlock() + // If clustered send an update to the system immediately. + if clustered { + s.sendStatszUpdate() + } } const ( @@ -970,29 +2649,52 @@ const ( JetStreamMaxStoreDefault = 1024 * 1024 * 1024 * 1024 // JetStreamMaxMemDefault is only used when we can't determine system memory. 256MB JetStreamMaxMemDefault = 1024 * 1024 * 256 + // snapshot staging for restores. + snapStagingDir = ".snap-staging" ) // Dynamically create a config with a tmp based directory (repeatable) and 75% of system memory. -func (s *Server) dynJetStreamConfig(storeDir string, maxStore int64) *JetStreamConfig { +func (s *Server) dynJetStreamConfig(storeDir string, maxStore, maxMem int64) *JetStreamConfig { jsc := &JetStreamConfig{} - if storeDir != "" { + if storeDir != _EMPTY_ { jsc.StoreDir = filepath.Join(storeDir, JetStreamStoreDir) } else { - tdir, _ := ioutil.TempDir(os.TempDir(), "nats-jetstream-storedir-") - jsc.StoreDir = filepath.Join(tdir, JetStreamStoreDir) + // Create one in tmp directory, but make it consistent for restarts. + jsc.StoreDir = filepath.Join(os.TempDir(), "nats", JetStreamStoreDir) + s.Warnf("Temporary storage directory used, data could be lost on system reboot") } - if maxStore > 0 { + opts := s.getOpts() + + // Strict mode. + jsc.Strict = opts.JetStreamStrict + + // Sync options. + jsc.SyncInterval = opts.SyncInterval + jsc.SyncAlways = opts.SyncAlways + + if opts.maxStoreSet && maxStore >= 0 { jsc.MaxStore = maxStore } else { jsc.MaxStore = diskAvailable(jsc.StoreDir) } - // Estimate to 75% of total memory if we can determine system memory. - if sysMem := sysmem.Memory(); sysMem > 0 { - jsc.MaxMemory = sysMem / 4 * 3 + + if opts.maxMemSet && maxMem >= 0 { + jsc.MaxMemory = maxMem } else { - jsc.MaxMemory = JetStreamMaxMemDefault + // Estimate to 75% of total memory if we can determine system memory. + if sysMem := sysmem.Memory(); sysMem > 0 { + // Check if we have been limited with GOMEMLIMIT and if lower use that value. + if gml := debug.SetMemoryLimit(-1); gml != math.MaxInt64 && gml < sysMem { + s.Debugf("JetStream detected GOMEMLIMIT of %v", friendlyBytes(gml)) + sysMem = gml + } + jsc.MaxMemory = sysMem / 4 * 3 + } else { + jsc.MaxMemory = JetStreamMaxMemDefault + } } + return jsc } @@ -1003,12 +2705,8 @@ func (a *Account) checkForJetStream() (*Server, *jsAccount, error) { jsa := a.js a.mu.RUnlock() - if s == nil { - return nil, nil, fmt.Errorf("jetstream account not registered") - } - - if jsa == nil { - return nil, nil, ErrJetStreamNotEnabledForAccount + if s == nil || jsa == nil { + return nil, nil, NewJSNotEnabledForAccountError() } return s, jsa, nil @@ -1028,8 +2726,8 @@ type StreamTemplateInfo struct { Streams []string `json:"streams"` } -// StreamTemplate -type StreamTemplate struct { +// streamTemplate +type streamTemplate struct { mu sync.Mutex tc *client jsa *jsAccount @@ -1044,8 +2742,8 @@ func (t *StreamTemplateConfig) deepCopy() *StreamTemplateConfig { return © } -// AddStreamTemplate will add a stream template to this account that allows auto-creation of streams. -func (a *Account) AddStreamTemplate(tc *StreamTemplateConfig) (*StreamTemplate, error) { +// addStreamTemplate will add a stream template to this account that allows auto-creation of streams. +func (a *Account) addStreamTemplate(tc *StreamTemplateConfig) (*streamTemplate, error) { s, jsa, err := a.checkForJetStream() if err != nil { return nil, err @@ -1060,12 +2758,12 @@ func (a *Account) AddStreamTemplate(tc *StreamTemplateConfig) (*StreamTemplate, // FIXME(dlc) - Hacky tcopy := tc.deepCopy() tcopy.Config.Name = "_" - cfg, err := checkStreamCfg(tcopy.Config) - if err != nil { - return nil, err + cfg, apiErr := s.checkStreamCfg(tcopy.Config, a, false) + if apiErr != nil { + return nil, apiErr } tcopy.Config = &cfg - t := &StreamTemplate{ + t := &streamTemplate{ StreamTemplateConfig: tcopy, tc: s.createInternalJetStreamClient(), jsa: jsa, @@ -1074,7 +2772,7 @@ func (a *Account) AddStreamTemplate(tc *StreamTemplateConfig) (*StreamTemplate, jsa.mu.Lock() if jsa.templates == nil { - jsa.templates = make(map[string]*StreamTemplate) + jsa.templates = make(map[string]*streamTemplate) // Create the appropriate store if cfg.Storage == FileStorage { jsa.store = newTemplateFileStore(jsa.storeDir) @@ -1095,13 +2793,13 @@ func (a *Account) AddStreamTemplate(tc *StreamTemplateConfig) (*StreamTemplate, return nil, err } if err := jsa.store.Store(t); err != nil { - t.Delete() + t.delete() return nil, err } return t, nil } -func (t *StreamTemplate) createTemplateSubscriptions() error { +func (t *streamTemplate) createTemplateSubscriptions() error { if t == nil { return fmt.Errorf("no template") } @@ -1109,14 +2807,14 @@ func (t *StreamTemplate) createTemplateSubscriptions() error { return fmt.Errorf("template not enabled") } c := t.tc - if !c.srv.eventsEnabled() { + if !c.srv.EventsEnabled() { return ErrNoSysAccount } sid := 1 for _, subject := range t.Config.Subjects { // Now create the subscription if _, err := c.processSub([]byte(subject), nil, []byte(strconv.Itoa(sid)), t.processInboundTemplateMsg, false); err != nil { - c.acc.DeleteStreamTemplate(t.Name) + c.acc.deleteStreamTemplate(t.Name) return err } sid++ @@ -1124,12 +2822,12 @@ func (t *StreamTemplate) createTemplateSubscriptions() error { return nil } -func (t *StreamTemplate) processInboundTemplateMsg(_ *subscription, _ *client, subject, reply string, msg []byte) { +func (t *streamTemplate) processInboundTemplateMsg(_ *subscription, pc *client, acc *Account, subject, reply string, msg []byte) { if t == nil || t.jsa == nil { return } jsa := t.jsa - cn := CanonicalName(subject) + cn := canonicalName(subject) jsa.mu.Lock() // If we already are registered then we can just return here. @@ -1137,7 +2835,6 @@ func (t *StreamTemplate) processInboundTemplateMsg(_ *subscription, _ *client, s jsa.mu.Unlock() return } - acc := jsa.account jsa.mu.Unlock() // Check if we are at the maximum and grab some variables. @@ -1152,7 +2849,7 @@ func (t *StreamTemplate) processInboundTemplateMsg(_ *subscription, _ *client, s t.mu.Unlock() if atLimit { - c.Warnf("JetStream could not create stream for account %q on subject %q, at limit", acc.Name, subject) + c.RateLimitWarnf("JetStream could not create stream for account %q on subject %q, at limit", acc.Name, subject) return } @@ -1160,19 +2857,19 @@ func (t *StreamTemplate) processInboundTemplateMsg(_ *subscription, _ *client, s // Change the config from the template and only use literal subject. cfg.Name = cn cfg.Subjects = []string{subject} - mset, err := acc.AddStream(&cfg) + mset, err := acc.addStream(&cfg) if err != nil { acc.validateStreams(t) - c.Warnf("JetStream could not create stream for account %q on subject %q", acc.Name, subject) + c.RateLimitWarnf("JetStream could not create stream for account %q on subject %q: %v", acc.Name, subject, err) return } // Process this message directly by invoking mset. - mset.processInboundJetStreamMsg(nil, nil, subject, reply, msg) + mset.processInboundJetStreamMsg(nil, pc, acc, subject, reply, msg) } -// LookupStreamTemplate looks up the names stream template. -func (a *Account) LookupStreamTemplate(name string) (*StreamTemplate, error) { +// lookupStreamTemplate looks up the names stream template. +func (a *Account) lookupStreamTemplate(name string) (*streamTemplate, error) { _, jsa, err := a.checkForJetStream() if err != nil { return nil, err @@ -1190,11 +2887,11 @@ func (a *Account) LookupStreamTemplate(name string) (*StreamTemplate, error) { } // This function will check all named streams and make sure they are valid. -func (a *Account) validateStreams(t *StreamTemplate) { +func (a *Account) validateStreams(t *streamTemplate) { t.mu.Lock() var vstreams []string for _, sname := range t.streams { - if _, err := a.LookupStream(sname); err == nil { + if _, err := a.lookupStream(sname); err == nil { vstreams = append(vstreams, sname) } } @@ -1202,7 +2899,7 @@ func (a *Account) validateStreams(t *StreamTemplate) { t.mu.Unlock() } -func (t *StreamTemplate) Delete() error { +func (t *streamTemplate) delete() error { if t == nil { return fmt.Errorf("nil stream template") } @@ -1219,7 +2916,7 @@ func (t *StreamTemplate) Delete() error { t.mu.Unlock() if jsa == nil { - return ErrJetStreamNotEnabled + return NewJSNotEnabledForAccountError() } jsa.mu.Lock() @@ -1236,10 +2933,10 @@ func (t *StreamTemplate) Delete() error { jsa.mu.Unlock() // Remove streams associated with this template. - var streams []*Stream + var streams []*stream t.mu.Lock() for _, name := range t.streams { - if mset, err := acc.LookupStream(name); err == nil { + if mset, err := acc.lookupStream(name); err == nil { streams = append(streams, mset) } } @@ -1253,23 +2950,23 @@ func (t *StreamTemplate) Delete() error { var lastErr error for _, mset := range streams { - if err := mset.Delete(); err != nil { + if err := mset.delete(); err != nil { lastErr = err } } return lastErr } -func (a *Account) DeleteStreamTemplate(name string) error { - t, err := a.LookupStreamTemplate(name) +func (a *Account) deleteStreamTemplate(name string) error { + t, err := a.lookupStreamTemplate(name) if err != nil { - return err + return NewJSStreamTemplateNotFoundError() } - return t.Delete() + return t.delete() } -func (a *Account) Templates() []*StreamTemplate { - var ts []*StreamTemplate +func (a *Account) templates() []*streamTemplate { + var ts []*streamTemplate _, jsa, err := a.checkForJetStream() if err != nil { return nil @@ -1320,9 +3017,13 @@ func (jsa *jsAccount) checkTemplateOwnership(tname, sname string) bool { return false } -// FriendlyBytes returns a string with the given bytes int64 +type Number interface { + int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 +} + +// friendlyBytes returns a string with the given bytes int64 // represented as a size, such as 1KB, 10MB, etc... -func FriendlyBytes(bytes int64) string { +func friendlyBytes[T Number](bytes T) string { fbytes := float64(bytes) base := 1024 pre := []string{"K", "M", "G", "T", "P", "E"} @@ -1335,14 +3036,140 @@ func FriendlyBytes(bytes int64) string { } func isValidName(name string) bool { - if name == "" { + if name == _EMPTY_ { return false } - return !strings.ContainsAny(name, ".*>") + return !strings.ContainsAny(name, " \t\r\n\f.*>") } // CanonicalName will replace all token separators '.' with '_'. // This can be used when naming streams or consumers with multi-token subjects. -func CanonicalName(name string) string { +func canonicalName(name string) string { return strings.ReplaceAll(name, ".", "_") } + +// To throttle the out of resources errors. +func (s *Server) resourcesExceededError() { + var didAlert bool + + s.rerrMu.Lock() + if now := time.Now(); now.Sub(s.rerrLast) > 10*time.Second { + s.Errorf("JetStream resource limits exceeded for server") + s.rerrLast = now + didAlert = true + } + s.rerrMu.Unlock() + + // If we are meta leader we should relinquish that here. + if didAlert { + if js := s.getJetStream(); js != nil { + js.mu.RLock() + if cc := js.cluster; cc != nil && cc.meta != nil { + cc.meta.StepDown() + } + js.mu.RUnlock() + } + } +} + +// For validating options. +func validateJetStreamOptions(o *Options) error { + // in non operator mode, the account names need to be configured + if len(o.JsAccDefaultDomain) > 0 { + if len(o.TrustedOperators) == 0 { + for a, domain := range o.JsAccDefaultDomain { + found := false + if isReservedAccount(a) { + found = true + } else { + for _, acc := range o.Accounts { + if a == acc.GetName() { + if len(acc.jsLimits) > 0 && domain != _EMPTY_ { + return fmt.Errorf("default_js_domain contains account name %q with enabled JetStream", a) + } + found = true + break + } + } + } + if !found { + return fmt.Errorf("in non operator mode, `default_js_domain` references non existing account %q", a) + } + } + } else { + for a := range o.JsAccDefaultDomain { + if !nkeys.IsValidPublicAccountKey(a) { + return fmt.Errorf("default_js_domain contains account name %q, which is not a valid public account nkey", a) + } + } + } + for a, d := range o.JsAccDefaultDomain { + sacc := DEFAULT_SYSTEM_ACCOUNT + if o.SystemAccount != _EMPTY_ { + sacc = o.SystemAccount + } + if a == sacc { + return fmt.Errorf("system account %q can not be in default_js_domain", a) + } + if d == _EMPTY_ { + continue + } + if sub := fmt.Sprintf(jsDomainAPI, d); !IsValidSubject(sub) { + return fmt.Errorf("default_js_domain contains account %q with invalid domain name %q", a, d) + } + } + } + if o.JetStreamDomain != _EMPTY_ { + if subj := fmt.Sprintf(jsDomainAPI, o.JetStreamDomain); !IsValidSubject(subj) { + return fmt.Errorf("invalid domain name: derived %q is not a valid subject", subj) + } + + if !isValidName(o.JetStreamDomain) { + return fmt.Errorf("invalid domain name: may not contain ., * or >") + } + } + // If not clustered no checks needed past here. + if !o.JetStream || o.Cluster.Port == 0 { + return nil + } + if o.ServerName == _EMPTY_ { + return fmt.Errorf("jetstream cluster requires `server_name` to be set") + } + if o.Cluster.Name == _EMPTY_ { + return fmt.Errorf("jetstream cluster requires `cluster.name` to be set") + } + + h := strings.ToLower(o.JetStreamExtHint) + switch h { + case jsWillExtend, jsNoExtend, _EMPTY_: + o.JetStreamExtHint = h + default: + return fmt.Errorf("expected 'no_extend' for string value, got '%s'", h) + } + + if o.JetStreamMaxCatchup < 0 { + return fmt.Errorf("jetstream max catchup cannot be negative") + } + return nil +} + +// We had a bug that set a default de dupe window on mirror, despite that being not a valid config +func fixCfgMirrorWithDedupWindow(cfg *StreamConfig) { + if cfg == nil || cfg.Mirror == nil { + return + } + if cfg.Duplicates != 0 { + cfg.Duplicates = 0 + } +} + +func (s *Server) handleWritePermissionError() { + //TODO Check if we should add s.jetStreamOOSPending in condition + if s.JetStreamEnabled() { + s.Errorf("File system permission denied while writing, disabling JetStream") + + go s.DisableJetStream() + + //TODO Send respective advisory if needed, same as in handleOutOfSpace + } +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go index 7d27c69..1ae1db0 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2020-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,23 +15,35 @@ package server import ( "bytes" + "cmp" "encoding/json" + "errors" "fmt" - "io/ioutil" - "net" + "io" "os" - "sort" + "path/filepath" + "runtime" + "slices" "strconv" "strings" "sync/atomic" "time" + "unicode" "github.com/nats-io/nuid" ) // Request API subjects for JetStream. const ( - // JSApiInfo is for obtaining general information about JetStream for this account. + // All API endpoints. + jsAllAPI = "$JS.API.>" + + // For constructing JetStream domain prefixes. + jsDomainAPI = "$JS.%s.API.>" + + JSApiPrefix = "$JS.API" + + // JSApiAccountInfo is for obtaining general information about JetStream for this account. // Will return JSON response. JSApiAccountInfo = "$JS.API.INFO" @@ -80,7 +92,7 @@ const ( JSApiStreamDelete = "$JS.API.STREAM.DELETE.*" JSApiStreamDeleteT = "$JS.API.STREAM.DELETE.%s" - // JSApiPurgeStream is the endpoint to purge streams. + // JSApiStreamPurge is the endpoint to purge streams. // Will return JSON response. JSApiStreamPurge = "$JS.API.STREAM.PURGE.*" JSApiStreamPurgeT = "$JS.API.STREAM.PURGE.%s" @@ -93,11 +105,11 @@ const ( JSApiStreamSnapshotT = "$JS.API.STREAM.SNAPSHOT.%s" // JSApiStreamRestore is the endpoint to restore a stream from a snapshot. - // Caller should resond to each chunk with a nil body response. + // Caller should respond to each chunk with a nil body response. JSApiStreamRestore = "$JS.API.STREAM.RESTORE.*" JSApiStreamRestoreT = "$JS.API.STREAM.RESTORE.%s" - // JSApiDeleteMsg is the endpoint to delete messages from a stream. + // JSApiMsgDelete is the endpoint to delete messages from a stream. // Will return JSON response. JSApiMsgDelete = "$JS.API.STREAM.MSG.DELETE.*" JSApiMsgDeleteT = "$JS.API.STREAM.MSG.DELETE.%s" @@ -107,10 +119,28 @@ const ( JSApiMsgGet = "$JS.API.STREAM.MSG.GET.*" JSApiMsgGetT = "$JS.API.STREAM.MSG.GET.%s" - // JSApiConsumerCreate is the endpoint to create ephemeral consumers for streams. + // JSDirectMsgGet is the template for non-api layer direct requests for a message by its stream sequence number or last by subject. + // Will return the message similar to how a consumer receives the message, no JSON processing. + // If the message can not be found we will use a status header of 404. If the stream does not exist the client will get a no-responders or timeout. + JSDirectMsgGet = "$JS.API.DIRECT.GET.*" + JSDirectMsgGetT = "$JS.API.DIRECT.GET.%s" + + // This is a direct version of get last by subject, which will be the dominant pattern for KV access once 2.9 is released. + // The stream and the key will be part of the subject to allow for no-marshal payloads and subject based security permissions. + JSDirectGetLastBySubject = "$JS.API.DIRECT.GET.*.>" + JSDirectGetLastBySubjectT = "$JS.API.DIRECT.GET.%s.%s" + + // jsDirectGetPre + jsDirectGetPre = "$JS.API.DIRECT.GET" + + // JSApiConsumerCreate is the endpoint to create consumers for streams. + // This was also the legacy endpoint for ephemeral consumers. + // It now can take consumer name and optional filter subject, which when part of the subject controls access. // Will return JSON response. - JSApiConsumerCreate = "$JS.API.CONSUMER.CREATE.*" - JSApiConsumerCreateT = "$JS.API.CONSUMER.CREATE.%s" + JSApiConsumerCreate = "$JS.API.CONSUMER.CREATE.*" + JSApiConsumerCreateT = "$JS.API.CONSUMER.CREATE.%s" + JSApiConsumerCreateEx = "$JS.API.CONSUMER.CREATE.*.>" + JSApiConsumerCreateExT = "$JS.API.CONSUMER.CREATE.%s.%s.%s" // JSApiDurableCreate is the endpoint to create durable consumers for streams. // You need to include the stream and consumer name in the subject. @@ -131,22 +161,86 @@ const ( JSApiConsumerInfo = "$JS.API.CONSUMER.INFO.*.*" JSApiConsumerInfoT = "$JS.API.CONSUMER.INFO.%s.%s" - // JSApiDeleteConsumer is the endpoint to delete consumers. + // JSApiConsumerDelete is the endpoint to delete consumers. // Will return JSON response. JSApiConsumerDelete = "$JS.API.CONSUMER.DELETE.*.*" JSApiConsumerDeleteT = "$JS.API.CONSUMER.DELETE.%s.%s" + // JSApiConsumerPause is the endpoint to pause or unpause consumers. + // Will return JSON response. + JSApiConsumerPause = "$JS.API.CONSUMER.PAUSE.*.*" + JSApiConsumerPauseT = "$JS.API.CONSUMER.PAUSE.%s.%s" + // JSApiRequestNextT is the prefix for the request next message(s) for a consumer in worker/pull mode. JSApiRequestNextT = "$JS.API.CONSUMER.MSG.NEXT.%s.%s" + // JSApiConsumerUnpinT is the prefix for unpinning subscription for a given consumer. + JSApiConsumerUnpin = "$JS.API.CONSUMER.UNPIN.*.*" + JSApiConsumerUnpinT = "$JS.API.CONSUMER.UNPIN.%s.%s" + + // jsRequestNextPre + jsRequestNextPre = "$JS.API.CONSUMER.MSG.NEXT." + // For snapshots and restores. The ack will have additional tokens. jsSnapshotAckT = "$JS.SNAPSHOT.ACK.%s.%s" jsRestoreDeliverT = "$JS.SNAPSHOT.RESTORE.%s.%s" + // JSApiStreamRemovePeer is the endpoint to remove a peer from a clustered stream and its consumers. + // Will return JSON response. + JSApiStreamRemovePeer = "$JS.API.STREAM.PEER.REMOVE.*" + JSApiStreamRemovePeerT = "$JS.API.STREAM.PEER.REMOVE.%s" + + // JSApiStreamLeaderStepDown is the endpoint to have stream leader stepdown. + // Will return JSON response. + JSApiStreamLeaderStepDown = "$JS.API.STREAM.LEADER.STEPDOWN.*" + JSApiStreamLeaderStepDownT = "$JS.API.STREAM.LEADER.STEPDOWN.%s" + + // JSApiConsumerLeaderStepDown is the endpoint to have consumer leader stepdown. + // Will return JSON response. + JSApiConsumerLeaderStepDown = "$JS.API.CONSUMER.LEADER.STEPDOWN.*.*" + JSApiConsumerLeaderStepDownT = "$JS.API.CONSUMER.LEADER.STEPDOWN.%s.%s" + + // JSApiLeaderStepDown is the endpoint to have our metaleader stepdown. + // Only works from system account. + // Will return JSON response. + JSApiLeaderStepDown = "$JS.API.META.LEADER.STEPDOWN" + + // JSApiRemoveServer is the endpoint to remove a peer server from the cluster. + // Only works from system account. + // Will return JSON response. + JSApiRemoveServer = "$JS.API.SERVER.REMOVE" + + // JSApiAccountPurge is the endpoint to purge the js content of an account + // Only works from system account. + // Will return JSON response. + JSApiAccountPurge = "$JS.API.ACCOUNT.PURGE.*" + JSApiAccountPurgeT = "$JS.API.ACCOUNT.PURGE.%s" + + // JSApiServerStreamMove is the endpoint to move streams off a server + // Only works from system account. + // Will return JSON response. + JSApiServerStreamMove = "$JS.API.ACCOUNT.STREAM.MOVE.*.*" + JSApiServerStreamMoveT = "$JS.API.ACCOUNT.STREAM.MOVE.%s.%s" + + // JSApiServerStreamCancelMove is the endpoint to cancel a stream move + // Only works from system account. + // Will return JSON response. + JSApiServerStreamCancelMove = "$JS.API.ACCOUNT.STREAM.CANCEL_MOVE.*.*" + JSApiServerStreamCancelMoveT = "$JS.API.ACCOUNT.STREAM.CANCEL_MOVE.%s.%s" + + // The prefix for system level account API. + jsAPIAccountPre = "$JS.API.ACCOUNT." + // jsAckT is the template for the ack message stream coming back from a consumer // when they ACK/NAK, etc a message. - jsAckT = "$JS.ACK.%s.%s" - jsAckPre = "$JS.ACK." + jsAckT = "$JS.ACK.%s.%s" + jsAckPre = "$JS.ACK." + jsAckPreLen = len(jsAckPre) + + // jsFlowControl is for flow control subjects. + jsFlowControlPre = "$JS.FC." + // jsFlowControl is for FC responses. + jsFlowControl = "$JS.FC.%s.%s.*" // JSAdvisoryPrefix is a prefix for all JetStream advisories. JSAdvisoryPrefix = "$JS.EVENT.ADVISORY" @@ -160,52 +254,124 @@ const ( // JSAdvisoryConsumerMaxDeliveryExceedPre is a notification published when a message exceeds its delivery threshold. JSAdvisoryConsumerMaxDeliveryExceedPre = "$JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES" + // JSAdvisoryConsumerMsgNakPre is a notification published when a message has been naked + JSAdvisoryConsumerMsgNakPre = "$JS.EVENT.ADVISORY.CONSUMER.MSG_NAKED" + // JSAdvisoryConsumerMsgTerminatedPre is a notification published when a message has been terminated. JSAdvisoryConsumerMsgTerminatedPre = "$JS.EVENT.ADVISORY.CONSUMER.MSG_TERMINATED" - // JSAdvisoryStreamCreatedPre notification that a stream was created + // JSAdvisoryStreamCreatedPre notification that a stream was created. JSAdvisoryStreamCreatedPre = "$JS.EVENT.ADVISORY.STREAM.CREATED" - // JSAdvisoryStreamDeletedPre notification that a stream was deleted + // JSAdvisoryStreamDeletedPre notification that a stream was deleted. JSAdvisoryStreamDeletedPre = "$JS.EVENT.ADVISORY.STREAM.DELETED" - // JSAdvisoryStreamUpdatedPre notification that a stream was updated + // JSAdvisoryStreamUpdatedPre notification that a stream was updated. JSAdvisoryStreamUpdatedPre = "$JS.EVENT.ADVISORY.STREAM.UPDATED" - // JSAdvisoryConsumerCreatedPre notification that a template created + // JSAdvisoryConsumerCreatedPre notification that a consumer was created. JSAdvisoryConsumerCreatedPre = "$JS.EVENT.ADVISORY.CONSUMER.CREATED" - // JSAdvisoryConsumerDeletedPre notification that a template deleted + // JSAdvisoryConsumerDeletedPre notification that a consumer was deleted. JSAdvisoryConsumerDeletedPre = "$JS.EVENT.ADVISORY.CONSUMER.DELETED" - // JSAdvisoryStreamSnapshotCreatePre notification that a snapshot was created + // JSAdvisoryConsumerPausePre notification that a consumer paused/unpaused. + JSAdvisoryConsumerPausePre = "$JS.EVENT.ADVISORY.CONSUMER.PAUSE" + + // JSAdvisoryConsumerPinnedPre notification that a consumer was pinned. + JSAdvisoryConsumerPinnedPre = "$JS.EVENT.ADVISORY.CONSUMER.PINNED" + + // JSAdvisoryConsumerUnpinnedPre notification that a consumer was unpinned. + JSAdvisoryConsumerUnpinnedPre = "$JS.EVENT.ADVISORY.CONSUMER.UNPINNED" + + // JSAdvisoryStreamSnapshotCreatePre notification that a snapshot was created. JSAdvisoryStreamSnapshotCreatePre = "$JS.EVENT.ADVISORY.STREAM.SNAPSHOT_CREATE" - // JSAdvisoryStreamSnapshotCompletePre notification that a snapshot was completed + // JSAdvisoryStreamSnapshotCompletePre notification that a snapshot was completed. JSAdvisoryStreamSnapshotCompletePre = "$JS.EVENT.ADVISORY.STREAM.SNAPSHOT_COMPLETE" - // JSAdvisoryStreamRestoreCreatePre notification that a restore was start + // JSAdvisoryStreamRestoreCreatePre notification that a restore was start. JSAdvisoryStreamRestoreCreatePre = "$JS.EVENT.ADVISORY.STREAM.RESTORE_CREATE" - // JSAdvisoryStreamRestoreCompletePre notification that a restore was completed + // JSAdvisoryStreamRestoreCompletePre notification that a restore was completed. JSAdvisoryStreamRestoreCompletePre = "$JS.EVENT.ADVISORY.STREAM.RESTORE_COMPLETE" + // JSAdvisoryDomainLeaderElectedPre notification that a jetstream domain has elected a leader. + JSAdvisoryDomainLeaderElected = "$JS.EVENT.ADVISORY.DOMAIN.LEADER_ELECTED" + + // JSAdvisoryStreamLeaderElectedPre notification that a replicated stream has elected a leader. + JSAdvisoryStreamLeaderElectedPre = "$JS.EVENT.ADVISORY.STREAM.LEADER_ELECTED" + + // JSAdvisoryStreamQuorumLostPre notification that a stream and its consumers are stalled. + JSAdvisoryStreamQuorumLostPre = "$JS.EVENT.ADVISORY.STREAM.QUORUM_LOST" + + // JSAdvisoryConsumerLeaderElectedPre notification that a replicated consumer has elected a leader. + JSAdvisoryConsumerLeaderElectedPre = "$JS.EVENT.ADVISORY.CONSUMER.LEADER_ELECTED" + + // JSAdvisoryConsumerQuorumLostPre notification that a consumer is stalled. + JSAdvisoryConsumerQuorumLostPre = "$JS.EVENT.ADVISORY.CONSUMER.QUORUM_LOST" + + // JSAdvisoryServerOutOfStorage notification that a server has no more storage. + JSAdvisoryServerOutOfStorage = "$JS.EVENT.ADVISORY.SERVER.OUT_OF_STORAGE" + + // JSAdvisoryServerRemoved notification that a server has been removed from the system. + JSAdvisoryServerRemoved = "$JS.EVENT.ADVISORY.SERVER.REMOVED" + + // JSAdvisoryAPILimitReached notification that a server has reached the JS API hard limit. + JSAdvisoryAPILimitReached = "$JS.EVENT.ADVISORY.API.LIMIT_REACHED" + // JSAuditAdvisory is a notification about JetStream API access. // FIXME - Add in details about who.. JSAuditAdvisory = "$JS.EVENT.ADVISORY.API" ) -// Maximum name lengths for streams, consumers and templates. -const JSMaxNameLen = 256 +var denyAllClientJs = []string{jsAllAPI, "$KV.>", "$OBJ.>"} +var denyAllJs = []string{jscAllSubj, raftAllSubj, jsAllAPI, "$KV.>", "$OBJ.>"} + +func generateJSMappingTable(domain string) map[string]string { + mappings := map[string]string{} + // This set of mappings is very very very ugly. + // It is a consequence of what we defined the domain prefix to be "$JS.domain.API" and it's mapping to "$JS.API" + // For optics $KV and $OBJ where made to be independent subject spaces. + // As materialized views of JS, they did not simply extend that subject space to say "$JS.API.KV" "$JS.API.OBJ" + // This is very unfortunate!!! + // Furthermore, it seemed bad to require different domain prefixes for JS/KV/OBJ. + // Especially since the actual API for say KV, does use stream create from JS. + // To avoid overlaps KV and OBJ views append the prefix to their API. + // (Replacing $KV with the prefix allows users to create collisions with say the bucket name) + // This mapping therefore needs to have extra token so that the mapping can properly discern between $JS, $KV, $OBJ + for srcMappingSuffix, to := range map[string]string{ + "INFO": JSApiAccountInfo, + "STREAM.>": "$JS.API.STREAM.>", + "CONSUMER.>": "$JS.API.CONSUMER.>", + "DIRECT.>": "$JS.API.DIRECT.>", + "META.>": "$JS.API.META.>", + "SERVER.>": "$JS.API.SERVER.>", + "ACCOUNT.>": "$JS.API.ACCOUNT.>", + "$KV.>": "$KV.>", + "$OBJ.>": "$OBJ.>", + } { + mappings[fmt.Sprintf("$JS.%s.API.%s", domain, srcMappingSuffix)] = to + } + return mappings +} -// Responses for API calls. +// JSMaxDescription is the maximum description length for streams and consumers. +const JSMaxDescriptionLen = 4 * 1024 -// ApiError is included in all responses if there was an error. -// TODO(dlc) - Move to more generic location. -type ApiError struct { - Code int `json:"code"` - Description string `json:"description,omitempty"` -} +// JSMaxMetadataLen is the maximum length for streams and consumers metadata map. +// It's calculated by summing length of all keys and values. +const JSMaxMetadataLen = 128 * 1024 + +// JSMaxNameLen is the maximum name lengths for streams, consumers and templates. +// Picked 255 as it seems to be a widely used file name limit +const JSMaxNameLen = 255 + +// JSDefaultRequestQueueLimit is the default number of entries that we will +// put on the global request queue before we react. +const JSDefaultRequestQueueLimit = 10_000 + +// Responses for API calls. // ApiResponse is a standard response from the JetStream JSON API type ApiResponse struct { @@ -213,6 +379,26 @@ type ApiResponse struct { Error *ApiError `json:"error,omitempty"` } +const JSApiSystemResponseType = "io.nats.jetstream.api.v1.system_response" + +// When passing back to the clients generalize store failures. +var ( + errStreamStoreFailed = errors.New("error creating store for stream") + errConsumerStoreFailed = errors.New("error creating store for consumer") +) + +// ToError checks if the response has a error and if it does converts it to an error avoiding +// the pitfalls described by https://yourbasic.org/golang/gotcha-why-nil-error-not-equal-nil/ +func (r *ApiResponse) ToError() error { + if r.Error == nil { + return nil + } + + return r.Error +} + +const JSApiOverloadedType = "io.nats.jetstream.api.v1.system_overloaded" + // ApiPaged includes variables used to create paged responses from the JSON API type ApiPaged struct { Total int `json:"total"` @@ -237,6 +423,7 @@ const JSApiAccountInfoResponseType = "io.nats.jetstream.api.v1.account_info_resp type JSApiStreamCreateResponse struct { ApiResponse *StreamInfo + DidCreate bool `json:"did_create,omitempty"` } const JSApiStreamCreateResponseType = "io.nats.jetstream.api.v1.stream_create_response" @@ -249,15 +436,24 @@ type JSApiStreamDeleteResponse struct { const JSApiStreamDeleteResponseType = "io.nats.jetstream.api.v1.stream_delete_response" -// JSApiStreamInfoResponse. +// JSMaxSubjectDetails The limit of the number of subject details we will send in a stream info response. +const JSMaxSubjectDetails = 100_000 + +type JSApiStreamInfoRequest struct { + ApiPagedRequest + DeletedDetails bool `json:"deleted_details,omitempty"` + SubjectsFilter string `json:"subjects_filter,omitempty"` +} + type JSApiStreamInfoResponse struct { ApiResponse + ApiPaged *StreamInfo } const JSApiStreamInfoResponseType = "io.nats.jetstream.api.v1.stream_info_response" -// Maximum entries we will return for streams or consumers lists. +// JSApiNamesLimit is the maximum entries we will return for streams or consumers lists. // TODO(dlc) - with header or request support could request chunked response. const JSApiNamesLimit = 1024 const JSApiListLimit = 256 @@ -278,17 +474,38 @@ type JSApiStreamNamesResponse struct { const JSApiStreamNamesResponseType = "io.nats.jetstream.api.v1.stream_names_response" +type JSApiStreamListRequest struct { + ApiPagedRequest + // These are filters that can be applied to the list. + Subject string `json:"subject,omitempty"` +} + // JSApiStreamListResponse list of detailed stream information. // A nil request is valid and means all streams. type JSApiStreamListResponse struct { ApiResponse ApiPaged - Streams []*StreamInfo `json:"streams"` + Streams []*StreamInfo `json:"streams"` + Missing []string `json:"missing,omitempty"` + Offline map[string]string `json:"offline,omitempty"` } const JSApiStreamListResponseType = "io.nats.jetstream.api.v1.stream_list_response" -// JSApiStreamPurgeResponse. +// JSApiStreamPurgeRequest is optional request information to the purge API. +// Subject will filter the purge request to only messages that match the subject, which can have wildcards. +// Sequence will purge up to but not including this sequence and can be combined with subject filtering. +// Keep will specify how many messages to keep. This can also be combined with subject filtering. +// Note that Sequence and Keep are mutually exclusive, so both can not be set at the same time. +type JSApiStreamPurgeRequest struct { + // Purge up to but not including sequence. + Sequence uint64 `json:"seq,omitempty"` + // Subject to match against messages for the purge command. + Subject string `json:"filter,omitempty"` + // Number of messages to keep. + Keep uint64 `json:"keep,omitempty"` +} + type JSApiStreamPurgeResponse struct { ApiResponse Success bool `json:"success,omitempty"` @@ -297,6 +514,16 @@ type JSApiStreamPurgeResponse struct { const JSApiStreamPurgeResponseType = "io.nats.jetstream.api.v1.stream_purge_response" +type JSApiConsumerUnpinRequest struct { + Group string `json:"group"` +} + +type JSApiConsumerUnpinResponse struct { + ApiResponse +} + +const JSApiConsumerUnpinResponseType = "io.nats.jetstream.api.v1.consumer_unpin_response" + // JSApiStreamUpdateResponse for updating a stream. type JSApiStreamUpdateResponse struct { ApiResponse @@ -307,10 +534,10 @@ const JSApiStreamUpdateResponseType = "io.nats.jetstream.api.v1.stream_update_re // JSApiMsgDeleteRequest delete message request. type JSApiMsgDeleteRequest struct { - Seq uint64 `json:"seq"` + Seq uint64 `json:"seq"` + NoErase bool `json:"no_erase,omitempty"` } -// JSApiMsgDeleteResponse. type JSApiMsgDeleteResponse struct { ApiResponse Success bool `json:"success,omitempty"` @@ -333,14 +560,22 @@ type JSApiStreamSnapshotRequest struct { // JSApiStreamSnapshotResponse is the direct response to the snapshot request. type JSApiStreamSnapshotResponse struct { ApiResponse - // Estimate of number of blocks for the messages. - NumBlks int `json:"num_blks"` - // Block size limit as specified by the stream. - BlkSize int `json:"blk_size"` + // Configuration of the given stream. + Config *StreamConfig `json:"config,omitempty"` + // Current State for the given stream. + State *StreamState `json:"state,omitempty"` } const JSApiStreamSnapshotResponseType = "io.nats.jetstream.api.v1.stream_snapshot_response" +// JSApiStreamRestoreRequest is the required restore request. +type JSApiStreamRestoreRequest struct { + // Configuration of the given stream. + Config StreamConfig `json:"config"` + // Current State for the given stream. + State StreamState `json:"state"` +} + // JSApiStreamRestoreResponse is the direct response to the restore request. type JSApiStreamRestoreResponse struct { ApiResponse @@ -350,12 +585,110 @@ type JSApiStreamRestoreResponse struct { const JSApiStreamRestoreResponseType = "io.nats.jetstream.api.v1.stream_restore_response" +// JSApiStreamRemovePeerRequest is the required remove peer request. +type JSApiStreamRemovePeerRequest struct { + // Server name of the peer to be removed. + Peer string `json:"peer"` +} + +// JSApiStreamRemovePeerResponse is the response to a remove peer request. +type JSApiStreamRemovePeerResponse struct { + ApiResponse + Success bool `json:"success,omitempty"` +} + +const JSApiStreamRemovePeerResponseType = "io.nats.jetstream.api.v1.stream_remove_peer_response" + +// JSApiStreamLeaderStepDownResponse is the response to a leader stepdown request. +type JSApiStreamLeaderStepDownResponse struct { + ApiResponse + Success bool `json:"success,omitempty"` +} + +const JSApiStreamLeaderStepDownResponseType = "io.nats.jetstream.api.v1.stream_leader_stepdown_response" + +// JSApiConsumerLeaderStepDownResponse is the response to a consumer leader stepdown request. +type JSApiConsumerLeaderStepDownResponse struct { + ApiResponse + Success bool `json:"success,omitempty"` +} + +const JSApiConsumerLeaderStepDownResponseType = "io.nats.jetstream.api.v1.consumer_leader_stepdown_response" + +// JSApiLeaderStepdownRequest allows placement control over the meta leader placement. +type JSApiLeaderStepdownRequest struct { + Placement *Placement `json:"placement,omitempty"` +} + +// JSApiLeaderStepDownResponse is the response to a meta leader stepdown request. +type JSApiLeaderStepDownResponse struct { + ApiResponse + Success bool `json:"success,omitempty"` +} + +const JSApiLeaderStepDownResponseType = "io.nats.jetstream.api.v1.meta_leader_stepdown_response" + +// JSApiMetaServerRemoveRequest will remove a peer from the meta group. +type JSApiMetaServerRemoveRequest struct { + // Server name of the peer to be removed. + Server string `json:"peer"` + // Peer ID of the peer to be removed. If specified this is used + // instead of the server name. + Peer string `json:"peer_id,omitempty"` +} + +// JSApiMetaServerRemoveResponse is the response to a peer removal request in the meta group. +type JSApiMetaServerRemoveResponse struct { + ApiResponse + Success bool `json:"success,omitempty"` +} + +const JSApiMetaServerRemoveResponseType = "io.nats.jetstream.api.v1.meta_server_remove_response" + +// JSApiMetaServerStreamMoveRequest will move a stream on a server to another +// response to this will come as JSApiStreamUpdateResponse/JSApiStreamUpdateResponseType +type JSApiMetaServerStreamMoveRequest struct { + // Server name of the peer to be evacuated. + Server string `json:"server,omitempty"` + // Cluster the server is in + Cluster string `json:"cluster,omitempty"` + // Domain the sever is in + Domain string `json:"domain,omitempty"` + // Ephemeral placement tags for the move + Tags []string `json:"tags,omitempty"` +} + +const JSApiAccountPurgeResponseType = "io.nats.jetstream.api.v1.account_purge_response" + +// JSApiAccountPurgeResponse is the response to a purge request in the meta group. +type JSApiAccountPurgeResponse struct { + ApiResponse + Initiated bool `json:"initiated,omitempty"` +} + // JSApiMsgGetRequest get a message request. type JSApiMsgGetRequest struct { - Seq uint64 `json:"seq"` + Seq uint64 `json:"seq,omitempty"` + LastFor string `json:"last_by_subj,omitempty"` + NextFor string `json:"next_by_subj,omitempty"` + + // Batch support. Used to request more then one msg at a time. + // Can be used with simple starting seq, but also NextFor with wildcards. + Batch int `json:"batch,omitempty"` + // This will make sure we limit how much data we blast out. If not set we will + // inherit the slow consumer default max setting of the server. Default is MAX_PENDING_SIZE. + MaxBytes int `json:"max_bytes,omitempty"` + // Return messages as of this start time. + StartTime *time.Time `json:"start_time,omitempty"` + + // Multiple response support. Will get the last msgs matching the subjects. These can include wildcards. + MultiLastFor []string `json:"multi_last,omitempty"` + // Only return messages up to this sequence. If not set, will be last sequence for the stream. + UpToSeq uint64 `json:"up_to_seq,omitempty"` + // Only return messages up to this time. + UpToTime *time.Time `json:"up_to_time,omitempty"` } -// JSApiMsgGetResponse. type JSApiMsgGetResponse struct { ApiResponse Message *StoredMsg `json:"message,omitempty"` @@ -366,7 +699,6 @@ const JSApiMsgGetResponseType = "io.nats.jetstream.api.v1.stream_msg_get_respons // JSWaitQueueDefaultMax is the default max number of outstanding requests for pull consumers. const JSWaitQueueDefaultMax = 512 -// JSApiConsumerCreateResponse. type JSApiConsumerCreateResponse struct { ApiResponse *ConsumerInfo @@ -374,7 +706,6 @@ type JSApiConsumerCreateResponse struct { const JSApiConsumerCreateResponseType = "io.nats.jetstream.api.v1.consumer_create_response" -// JSApiConsumerDeleteResponse. type JSApiConsumerDeleteResponse struct { ApiResponse Success bool `json:"success,omitempty"` @@ -382,7 +713,19 @@ type JSApiConsumerDeleteResponse struct { const JSApiConsumerDeleteResponseType = "io.nats.jetstream.api.v1.consumer_delete_response" -// JSApiConsumerInfoResponse. +type JSApiConsumerPauseRequest struct { + PauseUntil time.Time `json:"pause_until,omitempty"` +} + +const JSApiConsumerPauseResponseType = "io.nats.jetstream.api.v1.consumer_pause_response" + +type JSApiConsumerPauseResponse struct { + ApiResponse + Paused bool `json:"paused"` + PauseUntil time.Time `json:"pause_until"` + PauseRemaining time.Duration `json:"pause_remaining,omitempty"` +} + type JSApiConsumerInfoResponse struct { ApiResponse *ConsumerInfo @@ -390,12 +733,10 @@ type JSApiConsumerInfoResponse struct { const JSApiConsumerInfoResponseType = "io.nats.jetstream.api.v1.consumer_info_response" -// JSApiConsumersRequest type JSApiConsumersRequest struct { ApiPagedRequest } -// JSApiConsumerNamesResponse. type JSApiConsumerNamesResponse struct { ApiResponse ApiPaged @@ -404,20 +745,24 @@ type JSApiConsumerNamesResponse struct { const JSApiConsumerNamesResponseType = "io.nats.jetstream.api.v1.consumer_names_response" -// JSApiConsumerListResponse. type JSApiConsumerListResponse struct { ApiResponse ApiPaged - Consumers []*ConsumerInfo `json:"consumers"` + Consumers []*ConsumerInfo `json:"consumers"` + Missing []string `json:"missing,omitempty"` + Offline map[string]string `json:"offline,omitempty"` } const JSApiConsumerListResponseType = "io.nats.jetstream.api.v1.consumer_list_response" // JSApiConsumerGetNextRequest is for getting next messages for pull based consumers. type JSApiConsumerGetNextRequest struct { - Expires time.Time `json:"expires,omitempty"` - Batch int `json:"batch,omitempty"` - NoWait bool `json:"no_wait,omitempty"` + Expires time.Duration `json:"expires,omitempty"` + Batch int `json:"batch,omitempty"` + MaxBytes int `json:"max_bytes,omitempty"` + NoWait bool `json:"no_wait,omitempty"` + Heartbeat time.Duration `json:"idle_heartbeat,omitempty"` + PriorityGroup } // JSApiStreamTemplateCreateResponse for creating templates. @@ -428,7 +773,6 @@ type JSApiStreamTemplateCreateResponse struct { const JSApiStreamTemplateCreateResponseType = "io.nats.jetstream.api.v1.stream_template_create_response" -// JSApiStreamTemplateDeleteResponse type JSApiStreamTemplateDeleteResponse struct { ApiResponse Success bool `json:"success,omitempty"` @@ -444,7 +788,6 @@ type JSApiStreamTemplateInfoResponse struct { const JSApiStreamTemplateInfoResponseType = "io.nats.jetstream.api.v1.stream_template_info_response" -// JSApiStreamTemplatesRequest type JSApiStreamTemplatesRequest struct { ApiPagedRequest } @@ -458,40 +801,166 @@ type JSApiStreamTemplateNamesResponse struct { const JSApiStreamTemplateNamesResponseType = "io.nats.jetstream.api.v1.stream_template_names_response" -var ( - jsNotEnabledErr = &ApiError{Code: 503, Description: "jetstream not enabled for account"} - jsBadRequestErr = &ApiError{Code: 400, Description: "bad request"} - jsNotEmptyRequestErr = &ApiError{Code: 400, Description: "expected an empty request payload"} - jsInvalidJSONErr = &ApiError{Code: 400, Description: "invalid JSON received in request"} -) +// Structure that holds state for a JetStream API request that is processed +// in a separate long-lived go routine. This is to avoid blocking connections. +type jsAPIRoutedReq struct { + jsub *subscription + sub *subscription + acc *Account + subject string + reply string + msg []byte + pa pubArg +} + +func (js *jetStream) apiDispatch(sub *subscription, c *client, acc *Account, subject, reply string, rmsg []byte) { + // Ignore system level directives meta stepdown and peer remove requests here. + if subject == JSApiLeaderStepDown || + subject == JSApiRemoveServer || + strings.HasPrefix(subject, jsAPIAccountPre) { + return + } + // No lock needed, those are immutable. + s, rr := js.srv, js.apiSubs.Match(subject) + + hdr, msg := c.msgParts(rmsg) + if len(sliceHeader(ClientInfoHdr, hdr)) == 0 { + // Check if this is the system account. We will let these through for the account info only. + sacc := s.SystemAccount() + if sacc != acc { + return + } + if subject != JSApiAccountInfo { + // Only respond from the initial server entry to the NATS system. + if c.kind == CLIENT || c.kind == LEAF { + var resp = ApiResponse{ + Type: JSApiSystemResponseType, + Error: NewJSNotEnabledForAccountError(), + } + s.sendAPIErrResponse(nil, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + } + + // Short circuit for no interest. + if len(rr.psubs)+len(rr.qsubs) == 0 { + if (c.kind == CLIENT || c.kind == LEAF) && acc != s.SystemAccount() { + ci, acc, _, _, _ := s.getRequestInfo(c, rmsg) + var resp = ApiResponse{ + Type: JSApiSystemResponseType, + Error: NewJSBadRequestError(), + } + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + + // We should only have psubs and only 1 per result. + if len(rr.psubs) != 1 { + s.Warnf("Malformed JetStream API Request: [%s] %q", subject, rmsg) + if c.kind == CLIENT || c.kind == LEAF { + ci, acc, _, _, _ := s.getRequestInfo(c, rmsg) + var resp = ApiResponse{ + Type: JSApiSystemResponseType, + Error: NewJSBadRequestError(), + } + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + jsub := rr.psubs[0] + + // We need to make sure not to block. We will send the request to a long-lived + // pool of go routines. + + // Increment inflight. Do this before queueing. + atomic.AddInt64(&js.apiInflight, 1) + + // Copy the state. Note the JSAPI only uses the hdr index to piece apart the + // header from the msg body. No other references are needed. + // Check pending and warn if getting backed up. + pending, _ := s.jsAPIRoutedReqs.push(&jsAPIRoutedReq{jsub, sub, acc, subject, reply, copyBytes(rmsg), c.pa}) + limit := atomic.LoadInt64(&js.queueLimit) + if pending >= int(limit) { + s.rateLimitFormatWarnf("JetStream API queue limit reached, dropping %d requests", pending) + drained := int64(s.jsAPIRoutedReqs.drain()) + atomic.AddInt64(&js.apiInflight, -drained) -// For easier handling of exports and imports. -var allJsExports = []string{ - JSApiAccountInfo, - JSApiTemplateCreate, - JSApiTemplates, - JSApiTemplateInfo, - JSApiTemplateDelete, - JSApiStreamCreate, - JSApiStreamUpdate, - JSApiStreams, - JSApiStreamList, - JSApiStreamInfo, - JSApiStreamDelete, - JSApiStreamPurge, - JSApiStreamSnapshot, - JSApiStreamRestore, - JSApiMsgDelete, - JSApiMsgGet, - JSApiConsumerCreate, - JSApiDurableCreate, - JSApiConsumers, - JSApiConsumerList, - JSApiConsumerInfo, - JSApiConsumerDelete, + s.publishAdvisory(nil, JSAdvisoryAPILimitReached, JSAPILimitReachedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSAPILimitReachedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Server: s.Name(), + Domain: js.config.Domain, + Dropped: drained, + }) + } +} + +func (s *Server) processJSAPIRoutedRequests() { + defer s.grWG.Done() + + s.mu.RLock() + queue := s.jsAPIRoutedReqs + client := &client{srv: s, kind: JETSTREAM} + s.mu.RUnlock() + + js := s.getJetStream() + + for { + select { + case <-queue.ch: + // Only pop one item at a time here, otherwise if the system is recovering + // from queue buildup, then one worker will pull off all the tasks and the + // others will be starved of work. + for r, ok := queue.popOne(); ok && r != nil; r, ok = queue.popOne() { + client.pa = r.pa + start := time.Now() + r.jsub.icb(r.sub, client, r.acc, r.subject, r.reply, r.msg) + if dur := time.Since(start); dur >= readLoopReportThreshold { + s.Warnf("Internal subscription on %q took too long: %v", r.subject, dur) + } + atomic.AddInt64(&js.apiInflight, -1) + } + case <-s.quitCh: + return + } + } } func (s *Server) setJetStreamExportSubs() error { + js := s.getJetStream() + if js == nil { + return NewJSNotEnabledError() + } + + // Start the go routine that will process API requests received by the + // subscription below when they are coming from routes, etc.. + const maxProcs = 16 + mp := runtime.GOMAXPROCS(0) + // Cap at 16 max for now on larger core setups. + if mp > maxProcs { + mp = maxProcs + } + s.jsAPIRoutedReqs = newIPQueue[*jsAPIRoutedReq](s, "Routed JS API Requests") + for i := 0; i < mp; i++ { + s.startGoRoutine(s.processJSAPIRoutedRequests) + } + + // This is the catch all now for all JetStream API calls. + if _, err := s.sysSubscribe(jsAllAPI, js.apiDispatch); err != nil { + return err + } + + if err := s.SystemAccount().AddServiceExport(jsAllAPI, nil); err != nil { + s.Warnf("Error setting up jetstream service exports: %v", err) + return err + } + + // API handles themselves. pairs := []struct { subject string handler msgHandler @@ -510,130 +979,441 @@ func (s *Server) setJetStreamExportSubs() error { {JSApiStreamPurge, s.jsStreamPurgeRequest}, {JSApiStreamSnapshot, s.jsStreamSnapshotRequest}, {JSApiStreamRestore, s.jsStreamRestoreRequest}, + {JSApiStreamRemovePeer, s.jsStreamRemovePeerRequest}, + {JSApiStreamLeaderStepDown, s.jsStreamLeaderStepDownRequest}, + {JSApiConsumerLeaderStepDown, s.jsConsumerLeaderStepDownRequest}, {JSApiMsgDelete, s.jsMsgDeleteRequest}, {JSApiMsgGet, s.jsMsgGetRequest}, + {JSApiConsumerCreateEx, s.jsConsumerCreateRequest}, {JSApiConsumerCreate, s.jsConsumerCreateRequest}, - {JSApiDurableCreate, s.jsDurableCreateRequest}, + {JSApiDurableCreate, s.jsConsumerCreateRequest}, {JSApiConsumers, s.jsConsumerNamesRequest}, {JSApiConsumerList, s.jsConsumerListRequest}, {JSApiConsumerInfo, s.jsConsumerInfoRequest}, {JSApiConsumerDelete, s.jsConsumerDeleteRequest}, + {JSApiConsumerPause, s.jsConsumerPauseRequest}, + {JSApiConsumerUnpin, s.jsConsumerUnpinRequest}, } + js.mu.Lock() + defer js.mu.Unlock() + for _, p := range pairs { - if _, err := s.sysSubscribe(p.subject, p.handler); err != nil { + sub := &subscription{subject: []byte(p.subject), icb: p.handler} + if err := js.apiSubs.Insert(sub); err != nil { return err } } + return nil } -func (s *Server) sendAPIResponse(c *client, subject, reply, request, response string) { - s.sendInternalAccountMsg(nil, reply, response) - s.sendJetStreamAPIAuditAdvisory(c, subject, request, response) +func (s *Server) sendAPIResponse(ci *ClientInfo, acc *Account, subject, reply, request, response string) { + acc.trackAPI() + if reply != _EMPTY_ { + s.sendInternalAccountMsg(nil, reply, response) + } + s.sendJetStreamAPIAuditAdvisory(ci, acc, subject, request, response) } -// Request for current usage and limits for this account. -func (s *Server) jsAccountInfoRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { - return +func (s *Server) sendAPIErrResponse(ci *ClientInfo, acc *Account, subject, reply, request, response string) { + acc.trackAPIErr() + if reply != _EMPTY_ { + s.sendInternalAccountMsg(nil, reply, response) } + s.sendJetStreamAPIAuditAdvisory(ci, acc, subject, request, response) +} - var resp = JSApiAccountInfoResponse{ApiResponse: ApiResponse{Type: JSApiAccountInfoResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - } else { - stats := c.acc.JetStreamUsage() - resp.JetStreamAccountStats = &stats +const errRespDelay = 500 * time.Millisecond + +type delayedAPIResponse struct { + ci *ClientInfo + acc *Account + subject string + reply string + request string + hdr []byte + response string + rg *raftGroup + deadline time.Time + noJs bool + next *delayedAPIResponse +} + +// Add `r` in the list that is maintained ordered by the `delayedAPIResponse.deadline` time. +func addDelayedResponse(head, tail **delayedAPIResponse, r *delayedAPIResponse) { + // Check if list empty. + if *head == nil { + *head, *tail = r, r + return } - b, err := json.MarshalIndent(resp, "", " ") - if err != nil { + // Check if it should be added at the end, which is if after or equal to the tail. + if r.deadline.After((*tail).deadline) || r.deadline.Equal((*tail).deadline) { + (*tail).next, *tail = r, r return } - s.sendAPIResponse(c, subject, reply, string(msg), string(b)) + // Find its spot in the list. + var prev *delayedAPIResponse + for c := *head; c != nil; c = c.next { + // We insert only if we are stricly before the current `c`. + if r.deadline.Before(c.deadline) { + r.next = c + if prev != nil { + prev.next = r + } else { + *head = r + } + return + } + prev = c + } } -// Helpers for token extraction. -func templateNameFromSubject(subject string) string { - return tokenAt(subject, 6) +func (s *Server) delayedAPIResponder() { + defer s.grWG.Done() + var ( + head, tail *delayedAPIResponse // Linked list. + r *delayedAPIResponse // Updated by calling next(). + rqch <-chan struct{} // Quit channel of the Raft group (if present). + tm = time.NewTimer(time.Hour) + ) + next := func() { + r, rqch = nil, nil + // Check that JetStream is still on. Do not exit the go routine + // since JS can be enabled/disabled. The go routine will exit + // only if server is shutdown. + js := s.getJetStream() + if js == nil { + // Reset head and tail here. Also drain the ipQueue. + head, tail = nil, nil + s.delayedAPIResponses.drain() + // Fall back into next "if" that resets timer. + } + // If there are no delayed messages then delay the timer for + // a while. + if head == nil { + tm.Reset(time.Hour) + return + } + // Get the first expected message and then reset the timer. + r = head + js.mu.RLock() + if r.rg != nil && r.rg.node != nil { + // If there's an attached Raft group to the delayed response + // then pull out the quit channel, so that we don't bother + // sending responses for entities which are now no longer + // running. + rqch = r.rg.node.QuitC() + } + js.mu.RUnlock() + tm.Reset(time.Until(r.deadline)) + } + pop := func() { + if head == nil { + return + } + head = head.next + if head == nil { + tail = nil + } + } + for { + select { + case <-s.delayedAPIResponses.ch: + v, ok := s.delayedAPIResponses.popOne() + if !ok { + continue + } + // Add it to the list, and if ends up being the head, set things up. + addDelayedResponse(&head, &tail, v) + if v == head { + next() + } + case <-s.quitCh: + return + case <-rqch: + // If we were the head, drop and setup things for next. + if r != nil && r == head { + pop() + } + next() + case <-tm.C: + if r != nil { + // If it's not a JS API error, send it as a raw response without additional API/audit tracking. + if r.noJs { + s.sendInternalAccountMsgWithReply(r.acc, r.subject, _EMPTY_, r.hdr, r.response, false) + } else { + s.sendAPIErrResponse(r.ci, r.acc, r.subject, r.reply, r.request, r.response) + } + pop() + } + next() + } + } } -func streamNameFromSubject(subject string) string { - return tokenAt(subject, 5) +func (s *Server) sendDelayedAPIErrResponse(ci *ClientInfo, acc *Account, subject, reply, request, response string, rg *raftGroup, duration time.Duration) { + s.delayedAPIResponses.push(&delayedAPIResponse{ + ci, acc, subject, reply, request, nil, response, rg, time.Now().Add(duration), false, nil, + }) } -func consumerNameFromSubject(subject string) string { - return tokenAt(subject, 6) +func (s *Server) sendDelayedErrResponse(acc *Account, subject string, hdr []byte, response string, duration time.Duration) { + s.delayedAPIResponses.push(&delayedAPIResponse{ + nil, acc, subject, _EMPTY_, _EMPTY_, hdr, response, nil, time.Now().Add(duration), true, nil, + }) } -// Request to create a new template. -func (s *Server) jsTemplateCreateRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { - return +func (s *Server) getRequestInfo(c *client, raw []byte) (pci *ClientInfo, acc *Account, hdr, msg []byte, err error) { + hdr, msg = c.msgParts(raw) + var ci ClientInfo + + if len(hdr) > 0 { + if err := json.Unmarshal(sliceHeader(ClientInfoHdr, hdr), &ci); err != nil { + return nil, nil, nil, nil, err + } } - var resp = JSApiStreamTemplateCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateCreateResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + if ci.Service != _EMPTY_ { + acc, _ = s.LookupAccount(ci.Service) + } else if ci.Account != _EMPTY_ { + acc, _ = s.LookupAccount(ci.Account) + } else { + // Direct $SYS access. + acc = c.acc + if acc == nil { + acc = s.SystemAccount() + } } - var cfg StreamTemplateConfig - if err := json.Unmarshal(msg, &cfg); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + if acc == nil { + return nil, nil, nil, nil, ErrMissingAccount } - templateName := templateNameFromSubject(subject) - if templateName != cfg.Name { - resp.Error = &ApiError{Code: 400, Description: "template name in subject does not match request"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + return &ci, acc, hdr, msg, nil +} + +func (s *Server) unmarshalRequest(c *client, acc *Account, subject string, msg []byte, v any) error { + decoder := json.NewDecoder(bytes.NewReader(msg)) + decoder.DisallowUnknownFields() + + for { + if err := decoder.Decode(v); err != nil { + if err == io.EOF { + return nil + } + + var syntaxErr *json.SyntaxError + if errors.As(err, &syntaxErr) { + err = fmt.Errorf("%w at offset %d", err, syntaxErr.Offset) + } + + c.RateLimitWarnf("Invalid JetStream request '%s > %s': %s", acc, subject, err) + + if s.JetStreamConfig().Strict { + return err + } + + return json.Unmarshal(msg, v) + } } +} - t, err := c.acc.AddStreamTemplate(&cfg) - if err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return +func (a *Account) trackAPI() { + a.mu.RLock() + jsa := a.js + a.mu.RUnlock() + if jsa != nil { + jsa.usageMu.Lock() + jsa.usageApi++ + jsa.apiTotal++ + jsa.sendClusterUsageUpdate() + atomic.AddInt64(&jsa.js.apiTotal, 1) + jsa.usageMu.Unlock() } - t.mu.Lock() - tcfg := t.StreamTemplateConfig.deepCopy() - streams := t.streams - if streams == nil { - streams = []string{} +} + +func (a *Account) trackAPIErr() { + a.mu.RLock() + jsa := a.js + a.mu.RUnlock() + if jsa != nil { + jsa.usageMu.Lock() + jsa.usageApi++ + jsa.apiTotal++ + jsa.usageErr++ + jsa.apiErrors++ + jsa.sendClusterUsageUpdate() + atomic.AddInt64(&jsa.js.apiTotal, 1) + atomic.AddInt64(&jsa.js.apiErrors, 1) + jsa.usageMu.Unlock() } - t.mu.Unlock() - resp.StreamTemplateInfo = &StreamTemplateInfo{Config: tcfg, Streams: streams} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) } -// Request for the list of all template names. -func (s *Server) jsTemplateNamesRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +const badAPIRequestT = "Malformed JetStream API Request: %q" + +// Helper function to check on JetStream being enabled but also on status of leafnodes +// If the local account is not enabled but does have leafnode connectivity we will not +// want to error immediately and let the other side decide. +func (a *Account) checkJetStream() (enabled, shouldError bool) { + a.mu.RLock() + defer a.mu.RUnlock() + return a.js != nil, a.nleafs+a.nrleafs == 0 +} + +// Request for current usage and limits for this account. +func (s *Server) jsAccountInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { return } - var resp = JSApiStreamTemplateNamesResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateNamesResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } + + var resp = JSApiAccountInfoResponse{ApiResponse: ApiResponse{Type: JSApiAccountInfoResponseType}} + + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if !doErr { + return + } + resp.Error = NewJSNotEnabledForAccountError() + } else { + stats := acc.JetStreamUsage() + resp.JetStreamAccountStats = &stats + } + b, err := json.Marshal(resp) + if err != nil { + return + } + + s.sendAPIResponse(ci, acc, subject, reply, string(msg), string(b)) +} + +// Helpers for token extraction. +func templateNameFromSubject(subject string) string { + return tokenAt(subject, 6) +} + +func streamNameFromSubject(subject string) string { + return tokenAt(subject, 5) +} + +func consumerNameFromSubject(subject string) string { + return tokenAt(subject, 6) +} + +// Request to create a new template. +func (s *Server) jsTemplateCreateRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + var resp = JSApiStreamTemplateCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateCreateResponseType}} + if !acc.JetStreamEnabled() { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Not supported for now. + if s.JetStreamIsClustered() { + resp.Error = NewJSClusterUnSupportFeatureError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var cfg StreamTemplateConfig + if err := s.unmarshalRequest(c, acc, subject, msg, &cfg); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + templateName := templateNameFromSubject(subject) + if templateName != cfg.Name { + resp.Error = NewJSTemplateNameNotMatchSubjectError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + t, err := acc.addStreamTemplate(&cfg) + if err != nil { + resp.Error = NewJSStreamTemplateCreateError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + t.mu.Lock() + tcfg := t.StreamTemplateConfig.deepCopy() + streams := t.streams + if streams == nil { + streams = []string{} + } + t.mu.Unlock() + resp.StreamTemplateInfo = &StreamTemplateInfo{Config: tcfg, Streams: streams} + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request for the list of all template names. +func (s *Server) jsTemplateNamesRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + var resp = JSApiStreamTemplateNamesResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateNamesResponseType}} + if !acc.JetStreamEnabled() { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Not supported for now. + if s.JetStreamIsClustered() { + resp.Error = NewJSClusterUnSupportFeatureError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + var offset int - if !isEmptyRequest(msg) { + if isJSONObjectOrArray(msg) { var req JSApiStreamTemplatesRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } offset = req.Offset } - ts := c.acc.Templates() - sort.Slice(ts, func(i, j int) bool { - return strings.Compare(ts[i].StreamTemplateConfig.Name, ts[j].StreamTemplateConfig.Name) < 0 + ts := acc.templates() + slices.SortFunc(ts, func(i, j *streamTemplate) int { + return cmp.Compare(i.StreamTemplateConfig.Name, j.StreamTemplateConfig.Name) }) tcnt := len(ts) @@ -656,31 +1436,36 @@ func (s *Server) jsTemplateNamesRequest(sub *subscription, c *client, subject, r if resp.Templates == nil { resp.Templates = []string{} } - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request for information about a stream template. -func (s *Server) jsTemplateInfoRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsTemplateInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiStreamTemplateInfoResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateInfoResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if !acc.JetStreamEnabled() { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSNotEmptyRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } name := templateNameFromSubject(subject) - t, err := c.acc.LookupStreamTemplate(name) + t, err := acc.lookupStreamTemplate(name) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamTemplateNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } t.mu.Lock() @@ -692,39 +1477,44 @@ func (s *Server) jsTemplateInfoRequest(sub *subscription, c *client, subject, re t.mu.Unlock() resp.StreamTemplateInfo = &StreamTemplateInfo{Config: cfg, Streams: streams} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request to delete a stream template. -func (s *Server) jsTemplateDeleteRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsTemplateDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiStreamTemplateDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamTemplateDeleteResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if !acc.JetStreamEnabled() { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSNotEmptyRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } name := templateNameFromSubject(subject) - err := c.acc.DeleteStreamTemplate(name) + err = acc.deleteStreamTemplate(name) if err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamTemplateDeleteError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } resp.Success = true - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } -func (s *Server) jsonResponse(v interface{}) string { - b, err := json.MarshalIndent(v, "", " ") +func (s *Server) jsonResponse(v any) string { + b, err := json.Marshal(v) if err != nil { s.Warnf("Problem marshaling JSON for JetStream API:", err) return "" @@ -732,116 +1522,287 @@ func (s *Server) jsonResponse(v interface{}) string { return string(b) } -func jsError(err error) *ApiError { - return &ApiError{ - Code: 500, - Description: err.Error(), - } -} - -func jsNotFoundError(err error) *ApiError { - return &ApiError{ - Code: 404, - Description: err.Error(), +// Read lock must be held +func (jsa *jsAccount) tieredReservation(tier string, cfg *StreamConfig) int64 { + reservation := int64(0) + if tier == _EMPTY_ { + for _, sa := range jsa.streams { + if sa.cfg.MaxBytes > 0 { + if sa.cfg.Storage == cfg.Storage && sa.cfg.Name != cfg.Name { + reservation += (int64(sa.cfg.Replicas) * sa.cfg.MaxBytes) + } + } + } + } else { + for _, sa := range jsa.streams { + if sa.cfg.Replicas == cfg.Replicas { + if sa.cfg.MaxBytes > 0 { + if isSameTier(&sa.cfg, cfg) && sa.cfg.Name != cfg.Name { + reservation += (int64(sa.cfg.Replicas) * sa.cfg.MaxBytes) + } + } + } + } } + return reservation } // Request to create a stream. -func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsStreamCreateRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } - var cfg StreamConfig - if err := json.Unmarshal(msg, &cfg); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + var cfg StreamConfigRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &cfg); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } + + // Initialize asset version metadata. + setStaticStreamMetadata(&cfg.StreamConfig) + streamName := streamNameFromSubject(subject) if streamName != cfg.Name { - resp.Error = &ApiError{Code: 400, Description: "stream name in subject does not match request"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamMismatchError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Check for path like separators in the name. + if strings.ContainsAny(streamName, `\/`) { + resp.Error = NewJSStreamNameContainsPathSeparatorsError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Can't create a stream with a sealed state. + if cfg.Sealed { + resp.Error = NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for create can not be sealed")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // If we are told to do mirror direct but are not mirroring, error. + if cfg.MirrorDirect && cfg.Mirror == nil { + resp.Error = NewJSStreamInvalidConfigError(fmt.Errorf("stream has no mirror but does have mirror direct")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - mset, err := c.acc.AddStream(&cfg) + // Hand off to cluster for processing. + if s.JetStreamIsClustered() { + s.jsClusteredStreamRequest(ci, acc, subject, reply, rmsg, &cfg) + return + } + + if err := acc.jsNonClusteredStreamLimitsCheck(&cfg.StreamConfig); err != nil { + resp.Error = err + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + mset, err := acc.addStreamPedantic(&cfg.StreamConfig, cfg.Pedantic) if err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if IsNatsErr(err, JSStreamStoreFailedF) { + s.Warnf("Stream create failed for '%s > %s': %v", acc, streamName, err) + err = errStreamStoreFailed + } + resp.Error = NewJSStreamCreateError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - resp.StreamInfo = &StreamInfo{Created: mset.Created(), State: mset.State(), Config: mset.Config()} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + msetCfg := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: *setDynamicStreamMetadata(&msetCfg), + TimeStamp: time.Now().UTC(), + Mirror: mset.mirrorInfo(), + Sources: mset.sourcesInfo(), + } + resp.DidCreate = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request to update a stream. -func (s *Server) jsStreamUpdateRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsStreamUpdateRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + var ncfg StreamConfigRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &ncfg); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - var cfg StreamConfig - if err := json.Unmarshal(msg, &cfg); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + cfg, apiErr := s.checkStreamCfg(&ncfg.StreamConfig, acc, ncfg.Pedantic) + if apiErr != nil { + resp.Error = apiErr + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } + streamName := streamNameFromSubject(subject) if streamName != cfg.Name { - resp.Error = &ApiError{Code: 400, Description: "stream name in subject does not match request"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamMismatchError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Handle clustered version here. + if s.JetStreamIsClustered() { + s.jsClusteredStreamUpdateRequest(ci, acc, subject, reply, copyBytes(rmsg), &cfg, nil, ncfg.Pedantic) return } - mset, err := c.acc.LookupStream(streamName) + + mset, err := acc.lookupStream(streamName) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if mset.offlineReason != _EMPTY_ { + resp.Error = NewJSStreamOfflineReasonError(errors.New(mset.offlineReason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + return } - if err := mset.Update(&cfg); err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // Update asset version metadata. + setStaticStreamMetadata(&cfg) + + if err := mset.updatePedantic(&cfg, ncfg.Pedantic); err != nil { + resp.Error = NewJSStreamUpdateError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - resp.StreamInfo = &StreamInfo{Created: mset.Created(), State: mset.State(), Config: mset.Config()} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + msetCfg := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: *setDynamicStreamMetadata(&msetCfg), + Domain: s.getOpts().JetStreamDomain, + Mirror: mset.mirrorInfo(), + Sources: mset.sourcesInfo(), + TimeStamp: time.Now().UTC(), + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request for the list of all stream names. -func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiStreamNamesResponse{ApiResponse: ApiResponse{Type: JSApiStreamNamesResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } var offset int var filter string - if !isEmptyRequest(msg) { + if isJSONObjectOrArray(msg) { var req JSApiStreamNamesRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } offset = req.Offset @@ -852,33 +1813,85 @@ func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, subject, rep // TODO(dlc) - Maybe hold these results for large results that we expect to be paged. // TODO(dlc) - If this list is long maybe do this in a Go routine? - msets := c.acc.filteredStreams(filter) - // Since we page results order matters. - sort.Slice(msets, func(i, j int) bool { - return strings.Compare(msets[i].config.Name, msets[j].config.Name) < 0 - }) + var numStreams int + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + // TODO(dlc) - Debug or Warn? + return + } + js.mu.RLock() + for stream, sa := range cc.streams[acc.Name] { + if IsNatsErr(sa.err, JSClusterNotAssignedErr) { + continue + } + if filter != _EMPTY_ { + // These could not have subjects auto-filled in since they are raw and unprocessed. + if len(sa.Config.Subjects) == 0 { + if SubjectsCollide(filter, sa.Config.Name) { + resp.Streams = append(resp.Streams, stream) + } + } else { + for _, subj := range sa.Config.Subjects { + if SubjectsCollide(filter, subj) { + resp.Streams = append(resp.Streams, stream) + break + } + } + } + } else { + resp.Streams = append(resp.Streams, stream) + } + } + js.mu.RUnlock() + if len(resp.Streams) > 1 { + slices.Sort(resp.Streams) + } + numStreams = len(resp.Streams) + if offset > numStreams { + offset = numStreams + } + if offset > 0 { + resp.Streams = resp.Streams[offset:] + } + if len(resp.Streams) > JSApiNamesLimit { + resp.Streams = resp.Streams[:JSApiNamesLimit] + } + } else { + msets := acc.filteredStreams(filter) + // Since we page results order matters. + if len(msets) > 1 { + slices.SortFunc(msets, func(i, j *stream) int { return cmp.Compare(i.cfg.Name, j.cfg.Name) }) + } - scnt := len(msets) - if offset > scnt { - offset = scnt - } + numStreams = len(msets) + if offset > numStreams { + offset = numStreams + } - for _, mset := range msets[offset:] { - resp.Streams = append(resp.Streams, mset.config.Name) - if len(resp.Streams) >= JSApiNamesLimit { - break + for _, mset := range msets[offset:] { + resp.Streams = append(resp.Streams, mset.cfg.Name) + if len(resp.Streams) >= JSApiNamesLimit { + break + } } } - resp.Total = scnt + resp.Total = numStreams resp.Limit = JSApiNamesLimit resp.Offset = offset - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request for the list of all detailed stream info. // TODO(dlc) - combine with above long term -func (s *Server) jsStreamListRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsStreamListRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } @@ -887,37 +1900,92 @@ func (s *Server) jsStreamListRequest(sub *subscription, c *client, subject, repl Streams: []*StreamInfo{}, } - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } var offset int - if !isEmptyRequest(msg) { - var req JSApiStreamNamesRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + var filter string + + if isJSONObjectOrArray(msg) { + var req JSApiStreamListRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } offset = req.Offset + if req.Subject != _EMPTY_ { + filter = req.Subject + } + } + + // Clustered mode will invoke a scatter and gather. + if s.JetStreamIsClustered() { + // Need to copy these off before sending.. don't move this inside startGoRoutine!!! + msg = copyBytes(msg) + s.startGoRoutine(func() { s.jsClusteredStreamListRequest(acc, ci, filter, offset, subject, reply, msg) }) + return } // TODO(dlc) - Maybe hold these results for large results that we expect to be paged. // TODO(dlc) - If this list is long maybe do this in a Go routine? - msets := c.acc.Streams() - sort.Slice(msets, func(i, j int) bool { - return strings.Compare(msets[i].config.Name, msets[j].config.Name) < 0 - }) + var msets []*stream + if filter == _EMPTY_ { + msets = acc.streams() + } else { + msets = acc.filteredStreams(filter) + } + + slices.SortFunc(msets, func(i, j *stream) int { return cmp.Compare(i.cfg.Name, j.cfg.Name) }) scnt := len(msets) if offset > scnt { offset = scnt } + var missingNames []string for _, mset := range msets[offset:] { - resp.Streams = append(resp.Streams, &StreamInfo{Created: mset.Created(), State: mset.State(), Config: mset.Config()}) + if mset.offlineReason != _EMPTY_ { + if resp.Offline == nil { + resp.Offline = make(map[string]string, 1) + } + resp.Offline[mset.getCfgName()] = mset.offlineReason + missingNames = append(missingNames, mset.getCfgName()) + continue + } + + config := mset.config() + resp.Streams = append(resp.Streams, &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: config, + Domain: s.getOpts().JetStreamDomain, + Mirror: mset.mirrorInfo(), + Sources: mset.sourcesInfo(), + TimeStamp: time.Now().UTC(), + }) if len(resp.Streams) >= JSApiListLimit { break } @@ -925,393 +1993,2168 @@ func (s *Server) jsStreamListRequest(sub *subscription, c *client, subject, repl resp.Total = scnt resp.Limit = JSApiListLimit resp.Offset = offset - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + resp.Missing = missingNames + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request for information about a stream. -func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { - return - } - - var resp = JSApiStreamInfoResponse{ApiResponse: ApiResponse{Type: JSApiStreamInfoResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return - } - if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) +func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, a *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { return } - name := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(name) + ci, acc, hdr, msg, err := s.getRequestInfo(c, rmsg) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + s.Warnf(badAPIRequestT, msg) return } - config := mset.Config() - // Some streams are created without subject (for instance MQTT streams), - // but "nats" tooling would then fail to display them since it uses - // validation and expect the config's Subjects to not be empty. - if config.allowNoSubject && len(config.Subjects) == 0 { - config.Subjects = []string{">"} - } - resp.StreamInfo = &StreamInfo{Created: mset.Created(), State: mset.State(), Config: config} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) -} -func isEmptyRequest(req []byte) bool { - if len(req) == 0 { - return true - } - if bytes.Equal(req, []byte("{}")) { - return true + streamName := streamNameFromSubject(subject) + + var resp = JSApiStreamInfoResponse{ApiResponse: ApiResponse{Type: JSApiStreamInfoResponseType}} + + // If someone creates a duplicate stream that is identical we will get this request forwarded to us. + // Make sure the response type is for a create call. + if rt := getHeader(JSResponseType, hdr); len(rt) > 0 && string(rt) == jsCreateResponse { + resp.ApiResponse.Type = JSApiStreamCreateResponseType } - // If we are here we didn't get our simple match, but still could be valid. - var v interface{} - if err := json.Unmarshal(req, &v); err != nil { - return false + + var clusterWideConsCount int + + js, cc := s.getJetStreamCluster() + if js == nil { + return } - vm, ok := v.(map[string]interface{}) - if !ok { - return false + // If we are in clustered mode we need to be the stream leader to proceed. + if cc != nil { + // Check to make sure the stream is assigned. + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, streamName) + var offline bool + if sa != nil { + clusterWideConsCount = len(sa.consumers) + offline = s.allPeersOffline(sa.Group) + if sa.unsupported != nil && sa.Group != nil && cc.meta != nil && sa.Group.isMember(cc.meta.ID()) { + // If we're a member for this stream, and it's not supported, report it as offline. + resp.Error = NewJSStreamOfflineReasonError(errors.New(sa.unsupported.reason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + js.mu.RUnlock() + return + } + } + js.mu.RUnlock() + + if isLeader && sa == nil { + // We can't find the stream, so mimic what would be the errors below. + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + // No stream present. + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if sa == nil { + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + // Delaying an error response gives the leader a chance to respond before us + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + } + return + } else if isLeader && offline { + resp.Error = NewJSStreamOfflineError() + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + + // Check to see if we are a member of the group and if the group has no leader. + isLeaderless := js.isGroupLeaderless(sa.Group) + + // We have the stream assigned and a leader, so only the stream leader should answer. + if !acc.JetStreamIsStreamLeader(streamName) && !isLeaderless { + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + // Delaying an error response gives the leader a chance to respond before us + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), sa.Group, errRespDelay) + return + } + + // We may be in process of electing a leader, but if this is a scale up from 1 we will still be the state leader + // while the new members work through the election and catchup process. + // Double check for that instead of exiting here and being silent. e.g. nats stream update test --replicas=3 + js.mu.RLock() + rg := sa.Group + var ourID string + if cc.meta != nil { + ourID = cc.meta.ID() + } + // We have seen cases where rg is nil at this point, + // so check explicitly and bail if that is the case. + bail := rg == nil || !rg.isMember(ourID) + if !bail { + // We know we are a member here, if this group is new and we are preferred allow us to answer. + // Also, we have seen cases where rg.node is nil at this point, + // so check explicitly and bail if that is the case. + bail = rg.Preferred != ourID || (rg.node != nil && time.Since(rg.node.Created()) > lostQuorumIntervalDefault) + } + js.mu.RUnlock() + if bail { + return + } + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + + var details bool + var subjects string + var offset int + if isJSONObjectOrArray(msg) { + var req JSApiStreamInfoRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + details, subjects = req.DeletedDetails, req.SubjectsFilter + offset = req.Offset + } + + mset, err := acc.lookupStream(streamName) + // Error is not to be expected at this point, but could happen if same stream trying to be created. + if err != nil { + if cc != nil { + // This could be inflight, pause for a short bit and try again. + // This will not be inline, so ok. + time.Sleep(10 * time.Millisecond) + mset, err = acc.lookupStream(streamName) + } + // Check again. + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + if mset.offlineReason != _EMPTY_ { + resp.Error = NewJSStreamOfflineReasonError(errors.New(mset.offlineReason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + + config := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.stateWithDetail(details), + Config: *setDynamicStreamMetadata(&config), + Domain: s.getOpts().JetStreamDomain, + Cluster: js.clusterInfo(mset.raftGroup()), + Mirror: mset.mirrorInfo(), + Sources: mset.sourcesInfo(), + Alternates: js.streamAlternates(ci, config.Name), + TimeStamp: time.Now().UTC(), + } + if clusterWideConsCount > 0 { + resp.StreamInfo.State.Consumers = clusterWideConsCount + } + + // Check if they have asked for subject details. + if subjects != _EMPTY_ { + st := mset.store.SubjectsTotals(subjects) + if lst := len(st); lst > 0 { + // Common for both cases. + resp.Offset = offset + resp.Limit = JSMaxSubjectDetails + resp.Total = lst + + if offset == 0 && lst <= JSMaxSubjectDetails { + resp.StreamInfo.State.Subjects = st + } else { + // Here we have to filter list due to offset or maximum constraints. + subjs := make([]string, 0, len(st)) + for subj := range st { + subjs = append(subjs, subj) + } + // Sort it + slices.Sort(subjs) + + if offset > len(subjs) { + offset = len(subjs) + } + + end := offset + JSMaxSubjectDetails + if end > len(subjs) { + end = len(subjs) + } + actualSize := end - offset + var sd map[string]uint64 + + if actualSize > 0 { + sd = make(map[string]uint64, actualSize) + for _, ss := range subjs[offset:end] { + sd[ss] = st[ss] + } + } + resp.StreamInfo.State.Subjects = sd + } + } + } + // Check for out of band catchups. + if mset.hasCatchupPeers() { + mset.checkClusterInfo(resp.StreamInfo.Cluster) + } + + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to have a stream leader stepdown. +func (s *Server) jsStreamLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + // Have extra token for this one. + name := tokenAt(subject, 6) + + var resp = JSApiStreamLeaderStepDownResponse{ApiResponse: ApiResponse{Type: JSApiStreamLeaderStepDownResponseType}} + + // If we are not in clustered mode this is a failed request. + if !s.JetStreamIsClustered() { + resp.Error = NewJSClusterRequiredError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // If we are here we are clustered. See if we are the stream leader in order to proceed. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, name) + js.mu.RUnlock() + + if isLeader && sa == nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if sa == nil { + return + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + + // Check to see if we are a member of the group and if the group has no leader. + if js.isGroupLeaderless(sa.Group) { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // We have the stream assigned and a leader, so only the stream leader should answer. + if !acc.JetStreamIsStreamLeader(name) { + return + } + + mset, err := acc.lookupStream(name) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if mset == nil { + resp.Success = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) + return + } + + node := mset.raftNode() + if node == nil { + resp.Success = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) + return + } + + var preferredLeader string + if isJSONObjectOrArray(msg) { + var req JSApiLeaderStepdownRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if preferredLeader, resp.Error = s.getStepDownPreferredPlacement(node, req.Placement); resp.Error != nil { + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + // Call actual stepdown. + err = node.StepDown(preferredLeader) + if err != nil { + resp.Error = NewJSRaftGeneralError(err, Unless(err)) + } else { + resp.Success = true + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to have a consumer leader stepdown. +func (s *Server) jsConsumerLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + var resp = JSApiConsumerLeaderStepDownResponse{ApiResponse: ApiResponse{Type: JSApiConsumerLeaderStepDownResponseType}} + + // If we are not in clustered mode this is a failed request. + if !s.JetStreamIsClustered() { + resp.Error = NewJSClusterRequiredError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // If we are here we are clustered. See if we are the stream leader in order to proceed. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Have extra token for this one. + stream := tokenAt(subject, 6) + consumer := tokenAt(subject, 7) + + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream) + js.mu.RUnlock() + + if isLeader && sa == nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if sa == nil { + return + } + var ca *consumerAssignment + if sa.consumers != nil { + ca = sa.consumers[consumer] + } + if ca == nil { + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Check to see if we are a member of the group and if the group has no leader. + if js.isGroupLeaderless(ca.Group) { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if !acc.JetStreamIsConsumerLeader(stream, consumer) { + return + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + + mset, err := acc.lookupStream(stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + o := mset.lookupConsumer(consumer) + if o == nil { + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + n := o.raftNode() + if n == nil { + resp.Success = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) + return + } + + var preferredLeader string + if isJSONObjectOrArray(msg) { + var req JSApiLeaderStepdownRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if preferredLeader, resp.Error = s.getStepDownPreferredPlacement(n, req.Placement); resp.Error != nil { + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + // Call actual stepdown. + err = n.StepDown(preferredLeader) + if err != nil { + resp.Error = NewJSRaftGeneralError(err, Unless(err)) + } else { + resp.Success = true + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to remove a peer from a clustered stream. +func (s *Server) jsStreamRemovePeerRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + // Have extra token for this one. + name := tokenAt(subject, 6) + + var resp = JSApiStreamRemovePeerResponse{ApiResponse: ApiResponse{Type: JSApiStreamRemovePeerResponseType}} + + // If we are not in clustered mode this is a failed request. + if !s.JetStreamIsClustered() { + resp.Error = NewJSClusterRequiredError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // If we are here we are clustered. See if we are the stream leader in order to proceed. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, name) + js.mu.RUnlock() + + // Make sure we are meta leader. + if !isLeader { + return + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + if isEmptyRequest(msg) { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var req JSApiStreamRemovePeerRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if req.Peer == _EMPTY_ { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if sa == nil { + // No stream present. + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Check to see if we are a member of the group and if the group has no leader. + // Peers here is a server name, convert to node name. + nodeName := getHash(req.Peer) + + js.mu.RLock() + rg := sa.Group + isMember := rg.isMember(nodeName) + js.mu.RUnlock() + + // Make sure we are a member. + if !isMember { + resp.Error = NewJSClusterPeerNotMemberError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // If we are here we have a valid peer member set for removal. + if !js.removePeerFromStream(sa, nodeName) { + resp.Error = NewJSPeerRemapError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + resp.Success = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to have the metaleader remove a peer from the system. +func (s *Server) jsLeaderServerRemoveRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + if acc != s.SystemAccount() { + return + } + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.RLock() + isLeader := cc.isLeader() + meta := cc.meta + js.mu.RUnlock() + + // Extra checks here but only leader is listening. + if !isLeader { + return + } + + var resp = JSApiMetaServerRemoveResponse{ApiResponse: ApiResponse{Type: JSApiMetaServerRemoveResponseType}} + + if isEmptyRequest(msg) { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var req JSApiMetaServerRemoveRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + // Another peer-remove is already in progress, don't allow multiple concurrent changes. + if cc.peerRemoveReply != nil { + resp.Error = NewJSClusterServerMemberChangeInflightError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var found string + for _, p := range meta.Peers() { + // If Peer is specified, it takes precedence + if req.Peer != _EMPTY_ { + if p.ID == req.Peer { + found = req.Peer + break + } + continue + } + si, ok := s.nodeToInfo.Load(p.ID) + if ok && si.(nodeInfo).name == req.Server { + found = p.ID + break + } + } + + if found == _EMPTY_ { + resp.Error = NewJSClusterServerNotMemberError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if err := meta.ProposeRemovePeer(found); err != nil { + if err == errMembershipChange { + resp.Error = NewJSClusterServerMemberChangeInflightError() + } else { + resp.Error = NewJSRaftGeneralError(err) + } + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if cc.peerRemoveReply == nil { + cc.peerRemoveReply = make(map[string]peerRemoveInfo, 1) + } + // Only copy the request, the subject and reply are already copied. + cc.peerRemoveReply[found] = peerRemoveInfo{ci: ci, subject: subject, reply: reply, request: string(msg)} +} + +func (s *Server) peerSetToNames(ps []string) []string { + names := make([]string, len(ps)) + for i := 0; i < len(ps); i++ { + if si, ok := s.nodeToInfo.Load(ps[i]); !ok { + names[i] = ps[i] + } else { + names[i] = si.(nodeInfo).name + } + } + return names +} + +// looks up the peer id for a given server name. Cluster and domain name are optional filter criteria +func (s *Server) nameToPeer(js *jetStream, serverName, clusterName, domainName string) string { + js.mu.RLock() + defer js.mu.RUnlock() + if cc := js.cluster; cc != nil { + for _, p := range cc.meta.Peers() { + si, ok := s.nodeToInfo.Load(p.ID) + if ok && si.(nodeInfo).name == serverName { + if clusterName == _EMPTY_ || clusterName == si.(nodeInfo).cluster { + if domainName == _EMPTY_ || domainName == si.(nodeInfo).domain { + return p.ID + } + } + } + } + } + return _EMPTY_ +} + +// Request to have the metaleader move a stream on a peer to another +func (s *Server) jsLeaderServerStreamMoveRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + // Extra checks here but only leader is listening. + js.mu.RLock() + isLeader := cc.isLeader() + js.mu.RUnlock() + + if !isLeader { + return + } + + accName := tokenAt(subject, 6) + streamName := tokenAt(subject, 7) + + if acc.GetName() != accName && acc != s.SystemAccount() { + return + } + + var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}} + + var req JSApiMetaServerStreamMoveRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + srcPeer := _EMPTY_ + if req.Server != _EMPTY_ { + srcPeer = s.nameToPeer(js, req.Server, req.Cluster, req.Domain) + } + + targetAcc, ok := s.accounts.Load(accName) + if !ok { + resp.Error = NewJSNoAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var streamFound bool + cfg := StreamConfig{} + currPeers := []string{} + currCluster := _EMPTY_ + js.mu.Lock() + streams, ok := cc.streams[accName] + if ok { + sa, ok := streams[streamName] + if ok { + cfg = *sa.Config.clone() + streamFound = true + currPeers = sa.Group.Peers + currCluster = sa.Group.Cluster + } + } + js.mu.Unlock() + + if !streamFound { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // if server was picked, make sure src peer exists and move it to first position. + // removal will drop peers from the left + if req.Server != _EMPTY_ { + if srcPeer == _EMPTY_ { + resp.Error = NewJSClusterServerNotMemberError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + var peerFound bool + for i := 0; i < len(currPeers); i++ { + if currPeers[i] == srcPeer { + copy(currPeers[1:], currPeers[:i]) + currPeers[0] = srcPeer + peerFound = true + break + } + } + if !peerFound { + resp.Error = NewJSClusterPeerNotMemberError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + // make sure client is scoped to requested account + ciNew := *(ci) + ciNew.Account = accName + + // backup placement such that peers can be looked up with modified tag list + var origPlacement *Placement + if cfg.Placement != nil { + tmp := *cfg.Placement + origPlacement = &tmp + } + + if len(req.Tags) > 0 { + if cfg.Placement == nil { + cfg.Placement = &Placement{} + } + cfg.Placement.Tags = append(cfg.Placement.Tags, req.Tags...) + } + + peers, e := cc.selectPeerGroup(cfg.Replicas+1, currCluster, &cfg, currPeers, 1, nil) + if len(peers) <= cfg.Replicas { + // since expanding in the same cluster did not yield a result, try in different cluster + peers = nil + + clusters := map[string]struct{}{} + s.nodeToInfo.Range(func(_, ni any) bool { + if currCluster != ni.(nodeInfo).cluster { + clusters[ni.(nodeInfo).cluster] = struct{}{} + } + return true + }) + errs := &selectPeerError{} + errs.accumulate(e) + for cluster := range clusters { + newPeers, e := cc.selectPeerGroup(cfg.Replicas, cluster, &cfg, nil, 0, nil) + if len(newPeers) >= cfg.Replicas { + peers = append([]string{}, currPeers...) + peers = append(peers, newPeers[:cfg.Replicas]...) + break + } + errs.accumulate(e) + } + if peers == nil { + resp.Error = NewJSClusterNoPeersError(errs) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + cfg.Placement = origPlacement + + s.Noticef("Requested move for stream '%s > %s' R=%d from %+v to %+v", + accName, streamName, cfg.Replicas, s.peerSetToNames(currPeers), s.peerSetToNames(peers)) + + // We will always have peers and therefore never do a callout, therefore it is safe to call inline + // We should be fine ignoring pedantic mode here. as we do not touch configuration. + s.jsClusteredStreamUpdateRequest(&ciNew, targetAcc.(*Account), subject, reply, rmsg, &cfg, peers, false) +} + +// Request to have the metaleader move a stream on a peer to another +func (s *Server) jsLeaderServerStreamCancelMoveRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + // Extra checks here but only leader is listening. + js.mu.RLock() + isLeader := cc.isLeader() + js.mu.RUnlock() + + if !isLeader { + return + } + + var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}} + + accName := tokenAt(subject, 6) + streamName := tokenAt(subject, 7) + + if acc.GetName() != accName && acc != s.SystemAccount() { + return + } + + targetAcc, ok := s.accounts.Load(accName) + if !ok { + resp.Error = NewJSNoAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + streamFound := false + cfg := StreamConfig{} + currPeers := []string{} + js.mu.Lock() + streams, ok := cc.streams[accName] + if ok { + sa, ok := streams[streamName] + if ok { + cfg = *sa.Config.clone() + streamFound = true + currPeers = sa.Group.Peers + } + } + js.mu.Unlock() + + if !streamFound { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if len(currPeers) <= cfg.Replicas { + resp.Error = NewJSStreamMoveNotInProgressError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // make sure client is scoped to requested account + ciNew := *(ci) + ciNew.Account = accName + + peers := currPeers[:cfg.Replicas] + + // Remove placement in case tags don't match + // This can happen if the move was initiated by modifying the tags. + // This is an account operation. + // This can NOT happen when the move was initiated by the system account. + // There move honors the original tag list. + if cfg.Placement != nil && len(cfg.Placement.Tags) != 0 { + FOR_TAGCHECK: + for _, peer := range peers { + si, ok := s.nodeToInfo.Load(peer) + if !ok { + // can't verify tags, do the safe thing and error + resp.Error = NewJSStreamGeneralError( + fmt.Errorf("peer %s not present for tag validation", peer)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + nodeTags := si.(nodeInfo).tags + for _, tag := range cfg.Placement.Tags { + if !nodeTags.Contains(tag) { + // clear placement as tags don't match + cfg.Placement = nil + break FOR_TAGCHECK + } + } + + } + } + + s.Noticef("Requested cancel of move: R=%d '%s > %s' to peer set %+v and restore previous peer set %+v", + cfg.Replicas, accName, streamName, s.peerSetToNames(currPeers), s.peerSetToNames(peers)) + + // We will always have peers and therefore never do a callout, therefore it is safe to call inline + s.jsClusteredStreamUpdateRequest(&ciNew, targetAcc.(*Account), subject, reply, rmsg, &cfg, peers, false) +} + +// Request to have an account purged +func (s *Server) jsLeaderAccountPurgeRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + if acc != s.SystemAccount() { + return + } + + js := s.getJetStream() + if js == nil { + return + } + + accName := tokenAt(subject, 5) + + var resp = JSApiAccountPurgeResponse{ApiResponse: ApiResponse{Type: JSApiAccountPurgeResponseType}} + + if !s.JetStreamIsClustered() { + var streams []*stream + var ac *Account + if ac, err = s.lookupAccount(accName); err == nil && ac != nil { + streams = ac.streams() + } + + s.Noticef("Purge request for account %s (streams: %d, hasAccount: %t)", + accName, len(streams), ac != nil) + + for _, mset := range streams { + err := mset.delete() + if err != nil { + resp.Error = NewJSStreamDeleteError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + if err := os.RemoveAll(filepath.Join(js.config.StoreDir, accName)); err != nil { + resp.Error = NewJSStreamGeneralError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + resp.Initiated = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + _, cc := s.getJetStreamCluster() + + js.mu.RLock() + isLeader := cc.isLeader() + meta := cc.meta + js.mu.RUnlock() + + if !isLeader { + return + } + + if js.isMetaRecovering() { + // While in recovery mode, the data structures are not fully initialized + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + js.mu.RLock() + ns, nc := 0, 0 + streams, hasAccount := cc.streams[accName] + for _, osa := range streams { + for _, oca := range osa.consumers { + oca.deleted = true + ca := &consumerAssignment{Group: oca.Group, Stream: oca.Stream, Name: oca.Name, Config: oca.Config, Subject: subject, Client: oca.Client} + meta.Propose(encodeDeleteConsumerAssignment(ca)) + nc++ + } + sa := &streamAssignment{Group: osa.Group, Config: osa.Config, Subject: subject, Client: osa.Client} + meta.Propose(encodeDeleteStreamAssignment(sa)) + ns++ + } + js.mu.RUnlock() + + s.Noticef("Purge request for account %s (streams: %d, consumer: %d, hasAccount: %t)", accName, ns, nc, hasAccount) + + resp.Initiated = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) +} + +// Request to have the meta leader stepdown. +// These will only be received by the meta leader, so less checking needed. +func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + // This should only be coming from the System Account. + if acc != s.SystemAccount() { + s.RateLimitWarnf("JetStream API stepdown request from non-system account: %q user: %q", ci.serviceAccount(), ci.User) + return + } + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + // Extra checks here but only leader is listening. + js.mu.RLock() + isLeader := cc.isLeader() + meta := cc.meta + js.mu.RUnlock() + + if !isLeader { + return + } + + var preferredLeader string + var resp = JSApiLeaderStepDownResponse{ApiResponse: ApiResponse{Type: JSApiLeaderStepDownResponseType}} + + if isJSONObjectOrArray(msg) { + var req JSApiLeaderStepdownRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if preferredLeader, resp.Error = s.getStepDownPreferredPlacement(meta, req.Placement); resp.Error != nil { + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + // Call actual stepdown. + err = meta.StepDown(preferredLeader) + if err != nil { + resp.Error = NewJSRaftGeneralError(err, Unless(err)) + } else { + resp.Success = true + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Check if given []bytes is a JSON Object or Array. +// Technically, valid JSON can also be a plain string or number, but for our use case, +// we care only for JSON objects or arrays which starts with `[` or `{`. +// This function does not have to ensure valid JSON in its entirety. It is used merely +// to hint the codepath if it should attempt to parse the request as JSON or not. +func isJSONObjectOrArray(req []byte) bool { + // Skip leading JSON whitespace (space, tab, newline, carriage return) + i := 0 + for i < len(req) && (req[i] == ' ' || req[i] == '\t' || req[i] == '\n' || req[i] == '\r') { + i++ + } + // Check for empty input after trimming + if i >= len(req) { + return false + } + // Check if the first non-whitespace character is '{' or '[' + return req[i] == '{' || req[i] == '[' +} + +func isEmptyRequest(req []byte) bool { + if len(req) == 0 { + return true + } + if bytes.Equal(req, []byte("{}")) { + return true + } + // If we are here we didn't get our simple match, but still could be valid. + var v any + if err := json.Unmarshal(req, &v); err != nil { + return false + } + vm, ok := v.(map[string]any) + if !ok { + return false + } + return len(vm) == 0 +} + +// getStepDownPreferredPlacement attempts to work out what the best placement is +// for a stepdown request. The preferred server name always takes precedence, but +// if not specified, the placement will be used to filter by cluster. The caller +// should check for return API errors and return those to the requestor if needed. +func (s *Server) getStepDownPreferredPlacement(group RaftNode, placement *Placement) (string, *ApiError) { + if placement == nil { + return _EMPTY_, nil + } + var preferredLeader string + if placement.Preferred != _EMPTY_ { + for _, p := range group.Peers() { + si, ok := s.nodeToInfo.Load(p.ID) + if !ok || si == nil { + continue + } + if si.(nodeInfo).name == placement.Preferred { + preferredLeader = p.ID + break + } + } + if preferredLeader == group.ID() { + return _EMPTY_, NewJSClusterNoPeersError(fmt.Errorf("preferred server %q is already leader", placement.Preferred)) + } + if preferredLeader == _EMPTY_ { + return _EMPTY_, NewJSClusterNoPeersError(fmt.Errorf("preferred server %q not known", placement.Preferred)) + } + } else { + possiblePeers := make(map[*Peer]nodeInfo, len(group.Peers())) + ourID := group.ID() + for _, p := range group.Peers() { + if p == nil { + continue // ... shouldn't happen. + } + si, ok := s.nodeToInfo.Load(p.ID) + if !ok || si == nil { + continue + } + ni := si.(nodeInfo) + if ni.offline || p.ID == ourID { + continue + } + possiblePeers[p] = ni + } + // If cluster is specified, filter out anything not matching the cluster name. + if placement.Cluster != _EMPTY_ { + for p, si := range possiblePeers { + if si.cluster != placement.Cluster { + delete(possiblePeers, p) + } + } + } + // If tags are specified, filter out anything not matching all supplied tags. + if len(placement.Tags) > 0 { + for p, si := range possiblePeers { + matchesAll := true + for _, tag := range placement.Tags { + if matchesAll = matchesAll && si.tags.Contains(tag); !matchesAll { + break + } + } + if !matchesAll { + delete(possiblePeers, p) + } + } + } + // If there are no possible peers, return an error. + if len(possiblePeers) == 0 { + return _EMPTY_, NewJSClusterNoPeersError(fmt.Errorf("no replacement peer connected")) + } + // Take advantage of random map iteration order to select the preferred. + for p := range possiblePeers { + preferredLeader = p.ID + break + } + } + return preferredLeader, nil +} + +// Request to delete a stream. +func (s *Server) jsStreamDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}} + + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + + if !isEmptyRequest(msg) { + resp.Error = NewJSNotEmptyRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + stream := streamNameFromSubject(subject) + + // Clustered. + if s.JetStreamIsClustered() { + s.jsClusteredStreamDeleteRequest(ci, acc, stream, subject, reply, msg) + return + } + + mset, err := acc.lookupStream(stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if err := mset.delete(); err != nil { + resp.Error = NewJSStreamDeleteError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + resp.Success = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to delete a message. +// This expects a stream sequence number as the msg body. +func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + stream := tokenAt(subject, 6) + + var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}} + + // If we are in clustered mode we need to be the stream leader to proceed. + if s.JetStreamIsClustered() { + // Check to make sure the stream is assigned. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream) + js.mu.RUnlock() + + if isLeader && sa == nil { + // We can't find the stream, so mimic what would be the errors below. + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + // No stream present. + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if sa == nil { + return + } + + // Check to see if we are a member of the group and if the group has no leader. + if js.isGroupLeaderless(sa.Group) { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // We have the stream assigned and a leader, so only the stream leader should answer. + if !acc.JetStreamIsStreamLeader(stream) { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + if isEmptyRequest(msg) { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + var req JSApiMsgDeleteRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + mset, err := acc.lookupStream(stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if mset.cfg.Sealed { + resp.Error = NewJSStreamSealedError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if mset.cfg.DenyDelete { + resp.Error = NewJSStreamMsgDeleteFailedError(errors.New("message delete not permitted")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if s.JetStreamIsClustered() { + s.jsClusteredMsgDeleteRequest(ci, acc, mset, stream, subject, reply, &req, rmsg) + return + } + + var removed bool + if req.NoErase { + removed, err = mset.removeMsg(req.Seq) + } else { + removed, err = mset.eraseMsg(req.Seq) + } + if err != nil { + resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err)) + } else if !removed { + resp.Error = NewJSSequenceNotFoundError(req.Seq) + } else { + resp.Success = true + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to get a raw stream message. +func (s *Server) jsMsgGetRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) + return + } + + stream := tokenAt(subject, 6) + + var resp = JSApiMsgGetResponse{ApiResponse: ApiResponse{Type: JSApiMsgGetResponseType}} + + // If we are in clustered mode we need to be the stream leader to proceed. + if s.JetStreamIsClustered() { + // Check to make sure the stream is assigned. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream) + js.mu.RUnlock() + + if isLeader && sa == nil { + // We can't find the stream, so mimic what would be the errors below. + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + // No stream present. + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if sa == nil { + return + } + + // Check to see if we are a member of the group and if the group has no leader. + if js.isGroupLeaderless(sa.Group) { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // We have the stream assigned and a leader, so only the stream leader should answer. + if !acc.JetStreamIsStreamLeader(stream) { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + if isEmptyRequest(msg) { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return } - return len(vm) == 0 -} - -// Request to delete a stream. -func (s *Server) jsStreamDeleteRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { + var req JSApiMsgGetRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // This version does not support batch. + if req.Batch > 0 || req.MaxBytes > 0 { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + // Validate non-conflicting options. Seq, LastFor, and AsOfTime are mutually exclusive. + // NextFor can be paired with Seq or AsOfTime indicating a filter subject. + if (req.Seq > 0 && req.LastFor != _EMPTY_) || + (req.Seq == 0 && req.LastFor == _EMPTY_ && req.NextFor == _EMPTY_ && req.StartTime == nil) || + (req.Seq > 0 && req.StartTime != nil) || + (req.StartTime != nil && req.LastFor != _EMPTY_) || + (req.LastFor != _EMPTY_ && req.NextFor != _EMPTY_) { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - stream := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(stream) + + mset, err := acc.lookupStream(stream) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if mset.Config().internal { - resp.Error = &ApiError{Code: 403, Description: "not allowed to delete internal stream"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if mset.offlineReason != _EMPTY_ { + // Just let the request time out. return } - if err := mset.Delete(); err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + + var svp StoreMsg + var sm *StoreMsg + + // If AsOfTime is set, perform this first to get the sequence. + var seq uint64 + if req.StartTime != nil { + seq = mset.store.GetSeqFromTime(*req.StartTime) + } else { + seq = req.Seq } - resp.Success = true - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) -} -// Request to delete a message. -// This expects a stream sequence number as the msg body. -func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { + if seq > 0 && req.NextFor == _EMPTY_ { + sm, err = mset.store.LoadMsg(seq, &svp) + } else if req.NextFor != _EMPTY_ { + sm, _, err = mset.store.LoadNextMsg(req.NextFor, subjectHasWildcard(req.NextFor), seq, &svp) + } else { + sm, err = mset.store.LoadLastMsg(req.LastFor, &svp) + } + if err != nil { + resp.Error = NewJSNoMessageFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } + resp.Message = &StoredMsg{ + Subject: sm.subj, + Sequence: sm.seq, + Header: sm.hdr, + Data: sm.msg, + Time: time.Unix(0, sm.ts).UTC(), + } - var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // Don't send response through API layer for this call. + s.sendInternalAccountMsg(nil, reply, s.jsonResponse(resp)) +} + +func (s *Server) jsConsumerUnpinRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { return } - if isEmptyRequest(msg) { - resp.Error = jsBadRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } - var req JSApiMsgDeleteRequest + + stream := streamNameFromSubject(subject) + consumer := consumerNameFromSubject(subject) + + var req JSApiConsumerUnpinRequest + var resp = JSApiConsumerUnpinResponse{ApiResponse: ApiResponse{Type: JSApiConsumerUnpinResponseType}} + if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - stream := tokenAt(subject, 6) - mset, err := c.acc.LookupStream(stream) - if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if req.Group == _EMPTY_ { + resp.Error = NewJSInvalidJSONError(errors.New("consumer group not specified")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - removed, err := mset.EraseMsg(req.Seq) - if err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return - } else if !removed { - resp.Error = &ApiError{Code: 400, Description: fmt.Sprintf("sequence [%d] not found", req.Seq)} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if !validGroupName.MatchString(req.Group) { + resp.Error = NewJSConsumerInvalidGroupNameError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - resp.Success = true - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) -} + if s.JetStreamIsClustered() { + // Check to make sure the stream is assigned. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } -// Request to get a raw stream message. -func (s *Server) jsMsgGetRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { + // First check if the stream and consumer is there. + js.mu.RLock() + sa := js.streamAssignment(acc.Name, stream) + if sa == nil { + js.mu.RUnlock() + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if sa.unsupported != nil { + js.mu.RUnlock() + // Just let the request time out. + return + } + + ca, ok := sa.consumers[consumer] + if !ok || ca == nil { + js.mu.RUnlock() + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if ca.unsupported != nil { + js.mu.RUnlock() + // Just let the request time out. + return + } + js.mu.RUnlock() + + // Then check if we are the leader. + mset, err := acc.lookupStream(stream) + if err != nil { + return + } + + o := mset.lookupConsumer(consumer) + if o == nil { + return + } + if !o.isLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } - var resp = JSApiMsgGetResponse{ApiResponse: ApiResponse{Type: JSApiMsgGetResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + mset, err := acc.lookupStream(stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if isEmptyRequest(msg) { - resp.Error = jsBadRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if mset.offlineReason != _EMPTY_ { + // Just let the request time out. return } - var req JSApiMsgGetRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + o := mset.lookupConsumer(consumer) + if o == nil { + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - - stream := tokenAt(subject, 6) - mset, err := c.acc.LookupStream(stream) - if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if o.offlineReason != _EMPTY_ { + // Just let the request time out. return } - subj, hdr, msg, ts, err := mset.store.LoadMsg(req.Seq) - if err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + var foundPriority bool + for _, group := range o.config().PriorityGroups { + if group == req.Group { + foundPriority = true + break + } } - resp.Message = &StoredMsg{ - Subject: subj, - Sequence: req.Seq, - Header: hdr, - Data: msg, - Time: time.Unix(0, ts), + if !foundPriority { + resp.Error = NewJSConsumerInvalidPriorityGroupError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return } - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + + o.mu.Lock() + o.currentPinId = _EMPTY_ + o.sendUnpinnedAdvisoryLocked(req.Group, "admin") + o.mu.Unlock() + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request to purge a stream. -func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } + stream := streamNameFromSubject(subject) + var resp = JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + + // If we are in clustered mode we need to be the stream leader to proceed. + if s.JetStreamIsClustered() { + // Check to make sure the stream is assigned. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.RLock() + isLeader, sa := cc.isLeader(), js.streamAssignment(acc.Name, stream) + js.mu.RUnlock() + + if isLeader && sa == nil { + // We can't find the stream, so mimic what would be the errors below. + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + // No stream present. + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if sa == nil { + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + + // Check to see if we are a member of the group and if the group has no leader. + if js.isGroupLeaderless(sa.Group) { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // We have the stream assigned and a leader, so only the stream leader should answer. + if !acc.JetStreamIsStreamLeader(stream) { + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } } - if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } - stream := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(stream) + + var purgeRequest *JSApiStreamPurgeRequest + if isJSONObjectOrArray(msg) { + var req JSApiStreamPurgeRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if req.Sequence > 0 && req.Keep > 0 { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + purgeRequest = &req + } + + mset, err := acc.lookupStream(stream) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if mset.cfg.Sealed { + resp.Error = NewJSStreamSealedError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if mset.cfg.DenyPurge { + resp.Error = NewJSStreamPurgeFailedError(errors.New("stream purge not permitted")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if s.JetStreamIsClustered() { + s.jsClusteredStreamPurgeRequest(ci, acc, mset, stream, subject, reply, rmsg, purgeRequest) return } - purged, err := mset.Purge() + + purged, err := mset.purge(purgeRequest) if err != nil { - resp.Error = jsError(err) + resp.Error = NewJSStreamGeneralError(err, Unless(err)) } else { resp.Purged = purged resp.Success = true } - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +func (acc *Account) jsNonClusteredStreamLimitsCheck(cfg *StreamConfig) *ApiError { + var replicas int + if cfg != nil { + replicas = cfg.Replicas + } + selectedLimits, tier, jsa, apiErr := acc.selectLimits(replicas) + if apiErr != nil { + return apiErr + } + jsa.js.mu.RLock() + defer jsa.js.mu.RUnlock() + jsa.mu.RLock() + defer jsa.mu.RUnlock() + if selectedLimits.MaxStreams > 0 && jsa.countStreams(tier, cfg) >= selectedLimits.MaxStreams { + return NewJSMaximumStreamsLimitError() + } + reserved := jsa.tieredReservation(tier, cfg) + if err := jsa.js.checkAllLimits(selectedLimits, cfg, reserved, 0); err != nil { + return NewJSStreamLimitsError(err, Unless(err)) + } + return nil } // Request to restore a stream. -func (s *Server) jsStreamRestoreRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c.acc == nil { +func (s *Server) jsStreamRestoreRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamIsLeader() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } - acc := c.acc var resp = JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}} if !acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if isEmptyRequest(msg) { + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var req JSApiStreamRestoreRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } + stream := streamNameFromSubject(subject) - if _, err := acc.LookupStream(stream); err == nil { - resp.Error = &ApiError{Code: 400, Description: fmt.Sprintf("stream [%q] already exists", stream)} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + if stream != req.Config.Name && req.Config.Name == _EMPTY_ { + req.Config.Name = stream + } + + // check stream config at the start of the restore process, not at the end + cfg, apiErr := s.checkStreamCfg(&req.Config, acc, false) + if apiErr != nil { + resp.Error = apiErr + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - // FIXME(dlc) - Need to close these up if we fail for some reason. - // TODO(dlc) - Might need to make configurable or stream direct to storage dir. - tfile, err := ioutil.TempFile("", "jetstream-restore-") - if err != nil { - resp.Error = &ApiError{Code: 500, Description: "jetstream unable to open temp storage for restore"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if s.JetStreamIsClustered() { + s.jsClusteredStreamRestoreRequest(ci, acc, &req, subject, reply, rmsg) + return + } + + if err := acc.jsNonClusteredStreamLimitsCheck(&cfg); err != nil { + resp.Error = err + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if _, err := acc.lookupStream(stream); err == nil { + resp.Error = NewJSStreamNameExistRestoreFailedError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } - s.Noticef("Starting restore for stream %q in account %q", stream, c.acc.Name) - start := time.Now() - received := 0 + s.processStreamRestore(ci, acc, &req.Config, subject, reply, string(msg)) +} + +func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamConfig, subject, reply, msg string) <-chan error { + js := s.getJetStream() + + var resp = JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}} + + snapDir := filepath.Join(js.config.StoreDir, snapStagingDir) + if _, err := os.Stat(snapDir); os.IsNotExist(err) { + if err := os.MkdirAll(snapDir, defaultDirPerms); err != nil { + resp.Error = &ApiError{Code: 503, Description: "JetStream unable to create temp storage for restore"} + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return nil + } + } + + tfile, err := os.CreateTemp(snapDir, "js-restore-") + if err != nil { + resp.Error = NewJSTempStorageFailedError() + s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp)) + return nil + } - caudit := c.apiAuditClient() - s.publishAdvisory(c.acc, JSAdvisoryStreamRestoreCreatePre+"."+stream, &JSRestoreCreateAdvisory{ + streamName := cfg.Name + s.Noticef("Starting restore for stream '%s > %s'", acc.Name, streamName) + + start := time.Now().UTC() + domain := s.getOpts().JetStreamDomain + s.publishAdvisory(acc, JSAdvisoryStreamRestoreCreatePre+"."+streamName, &JSRestoreCreateAdvisory{ TypedEvent: TypedEvent{ Type: JSRestoreCreateAdvisoryType, ID: nuid.Next(), - Time: time.Now().UTC(), + Time: start, }, - Stream: stream, - Client: caudit, + Stream: streamName, + Client: ci.forAdvisory(), + Domain: domain, }) // Create our internal subscription to accept the snapshot. - restoreSubj := fmt.Sprintf(jsRestoreDeliverT, stream, nuid.Next()) + restoreSubj := fmt.Sprintf(jsRestoreDeliverT, streamName, nuid.Next()) + + type result struct { + err error + reply string + } + + // For signaling to upper layers. + resultCh := make(chan result, 1) + activeQ := newIPQueue[int](s, fmt.Sprintf("[ACC:%s] stream '%s' restore", acc.Name, streamName)) // of int + + var total int - // FIXME(dlc) - Can't recover well here if something goes wrong. Could use channels and at least time - // things out. Note that this is tied to the requesting client, so if it is a tool this goes away when - // the client does. Only thing leaking here is the sub on strange failure. - acc.subscribeInternal(restoreSubj, func(sub *subscription, c *client, subject, reply string, msg []byte) { + // FIXME(dlc) - Probably take out of network path eventually due to disk I/O? + processChunk := func(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { // We require reply subjects to communicate back failures, flow etc. If they do not have one log and cancel. if reply == _EMPTY_ { - tfile.Close() - os.Remove(tfile.Name()) sub.client.processUnsub(sub.sid) - s.Warnf("Restore for stream %q in account %q requires reply subject for each chunk", stream, c.acc.Name) + resultCh <- result{ + fmt.Errorf("restore for stream '%s > %s' requires reply subject for each chunk", acc.Name, streamName), + reply, + } return } - // Account client messages have \r\n on end. + // Account client messages have \r\n on end. This is an error. if len(msg) < LEN_CR_LF { + sub.client.processUnsub(sub.sid) + resultCh <- result{ + fmt.Errorf("restore for stream '%s > %s' received short chunk", acc.Name, streamName), + reply, + } return } + // Adjust. msg = msg[:len(msg)-LEN_CR_LF] + // This means we are complete with our transfer from the client. if len(msg) == 0 { - tfile.Seek(0, 0) - mset, err := acc.RestoreStream(stream, tfile) - tfile.Close() - os.Remove(tfile.Name()) - sub.client.processUnsub(sub.sid) - - end := time.Now() - - // TODO(rip) - Should this have the error code in it?? - s.publishAdvisory(c.acc, JSAdvisoryStreamRestoreCompletePre+"."+stream, &JSRestoreCompleteAdvisory{ - TypedEvent: TypedEvent{ - Type: JSRestoreCompleteAdvisoryType, - ID: nuid.Next(), - Time: time.Now().UTC(), - }, - Stream: stream, - Start: start.UTC(), - End: end.UTC(), - Bytes: int64(received), - Client: caudit, - }) - - s.Noticef("Completed %s restore for stream %q in account %q in %v", - FriendlyBytes(int64(received)), stream, c.acc.Name, end.Sub(start)) - - // On the last EOF, send back the stream info or error status. - var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}} - if err != nil { - resp.Error = jsError(err) - } else { - resp.StreamInfo = &StreamInfo{Created: mset.Created(), State: mset.State(), Config: mset.Config()} - } - s.sendInternalAccountMsg(acc, reply, s.jsonResponse(&resp)) + s.Debugf("Finished staging restore for stream '%s > %s'", acc.Name, streamName) + resultCh <- result{err, reply} + return + } + // We track total and check on server limits. + // TODO(dlc) - We could check apriori and cancel initial request if we know it won't fit. + total += len(msg) + if js.wouldExceedLimits(FileStorage, total) { + s.resourcesExceededError() + resultCh <- result{NewJSInsufficientResourcesError(), reply} return } + // Append chunk to temp file. Mark as issue if we encounter an error. if n, err := tfile.Write(msg); n != len(msg) || err != nil { - s.Warnf("Storage failure for restore at %s for stream in account %q: %v", - FriendlyBytes(int64(received)), stream, c.acc.Name, err) - tfile.Close() - os.Remove(tfile.Name()) - sub.client.processUnsub(sub.sid) + resultCh <- result{err, reply} if reply != _EMPTY_ { s.sendInternalAccountMsg(acc, reply, "-ERR 'storage failure during restore'") } return } - received += len(msg) + + activeQ.push(len(msg)) + s.sendInternalAccountMsg(acc, reply, nil) - }) + } + + sub, err := acc.subscribeInternal(restoreSubj, processChunk) + if err != nil { + tfile.Close() + os.Remove(tfile.Name()) + resp.Error = NewJSRestoreSubscribeFailedError(err, restoreSubj) + s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp)) + return nil + } + // Mark the subject so the end user knows where to send the snapshot chunks. resp.DeliverSubject = restoreSubj - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, msg, s.jsonResponse(resp)) + + doneCh := make(chan error, 1) + + // Monitor the progress from another Go routine. + s.startGoRoutine(func() { + defer s.grWG.Done() + defer func() { + tfile.Close() + os.Remove(tfile.Name()) + sub.client.processUnsub(sub.sid) + activeQ.unregister() + }() + + const activityInterval = 5 * time.Second + notActive := time.NewTimer(activityInterval) + defer notActive.Stop() + + total := 0 + for { + select { + case result := <-resultCh: + err := result.err + var mset *stream + + // If we staged properly go ahead and do restore now. + if err == nil { + s.Debugf("Finalizing restore for stream '%s > %s'", acc.Name, streamName) + tfile.Seek(0, 0) + mset, err = acc.RestoreStream(cfg, tfile) + } else { + errStr := err.Error() + tmp := []rune(errStr) + tmp[0] = unicode.ToUpper(tmp[0]) + s.Warnf(errStr) + } + + end := time.Now().UTC() + + // TODO(rip) - Should this have the error code in it?? + s.publishAdvisory(acc, JSAdvisoryStreamRestoreCompletePre+"."+streamName, &JSRestoreCompleteAdvisory{ + TypedEvent: TypedEvent{ + Type: JSRestoreCompleteAdvisoryType, + ID: nuid.Next(), + Time: end, + }, + Stream: streamName, + Start: start, + End: end, + Bytes: int64(total), + Client: ci.forAdvisory(), + Domain: domain, + }) + + var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}} + + if err != nil { + resp.Error = NewJSStreamRestoreError(err, Unless(err)) + s.Warnf("Restore failed for %s for stream '%s > %s' in %v", + friendlyBytes(int64(total)), acc.Name, streamName, end.Sub(start)) + } else { + msetCfg := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: *setDynamicStreamMetadata(&msetCfg), + TimeStamp: time.Now().UTC(), + } + s.Noticef("Completed restore of %s for stream '%s > %s' in %v", + friendlyBytes(int64(total)), acc.Name, streamName, end.Sub(start).Round(time.Millisecond)) + } + + // On the last EOF, send back the stream info or error status. + s.sendInternalAccountMsg(acc, result.reply, s.jsonResponse(&resp)) + // Signal to the upper layers. + doneCh <- err + return + case <-activeQ.ch: + if n, ok := activeQ.popOne(); ok { + total += n + notActive.Reset(activityInterval) + } + case <-notActive.C: + err := fmt.Errorf("restore for stream '%s > %s' is stalled", acc, streamName) + doneCh <- err + return + } + } + }) + + return doneCh } // Process a snapshot request. -func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c.acc == nil { +func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } - acc := c.acc + smsg := string(msg) + stream := streamNameFromSubject(subject) + + // If we are in clustered mode we need to be the stream leader to proceed. + if s.JetStreamIsClustered() && !acc.JetStreamIsStreamLeader(stream) { + return + } var resp = JSApiStreamSnapshotResponse{ApiResponse: ApiResponse{Type: JSApiStreamSnapshotResponseType}} if !acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(&resp)) + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) return } if isEmptyRequest(msg) { - resp.Error = jsBadRequestErr - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(&resp)) + resp.Error = NewJSBadRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) return } - stream := streamNameFromSubject(subject) - mset, err := acc.LookupStream(stream) + + mset, err := acc.lookupStream(stream) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(&resp)) + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) + return + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) + } return } var req JSApiStreamSnapshotRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(&resp)) + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) return } if !IsValidSubject(req.DeliverSubject) { - resp.Error = &ApiError{Code: 400, Description: "deliver subject not valid"} - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(&resp)) + resp.Error = NewJSSnapshotDeliverSubjectInvalidError() + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) return } @@ -1319,76 +4162,76 @@ func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, subject, // stall this go routine. go func() { if req.CheckMsgs { - s.Noticef("Starting health check and snapshot for stream %q in account %q", mset.Name(), mset.jsa.account.Name) + s.Noticef("Starting health check and snapshot for stream '%s > %s'", mset.jsa.account.Name, mset.name()) } else { - s.Noticef("Starting snapshot for stream %q in account %q", mset.Name(), mset.jsa.account.Name) + s.Noticef("Starting snapshot for stream '%s > %s'", mset.jsa.account.Name, mset.name()) } - start := time.Now() + start := time.Now().UTC() - sr, err := mset.Snapshot(0, req.CheckMsgs, !req.NoConsumers) + sr, err := mset.snapshot(0, req.CheckMsgs, !req.NoConsumers) if err != nil { - s.Noticef("Snapshot of %q in account %q failed: %s", mset.Name(), mset.jsa.account.Name, err) - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(&resp)) + s.Warnf("Snapshot of stream '%s > %s' failed: %v", mset.jsa.account.Name, mset.name(), err) + resp.Error = NewJSStreamSnapshotError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, smsg, s.jsonResponse(&resp)) return } - resp.NumBlks = sr.NumBlks - resp.BlkSize = sr.BlkSize + config := mset.config() + resp.State = &sr.State + resp.Config = &config - s.sendAPIResponse(c, subject, reply, smsg, s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, smsg, s.jsonResponse(resp)) - caudit := c.apiAuditClient() - s.publishAdvisory(c.acc, JSAdvisoryStreamSnapshotCreatePre+"."+mset.Name(), &JSSnapshotCreateAdvisory{ + s.publishAdvisory(acc, JSAdvisoryStreamSnapshotCreatePre+"."+mset.name(), &JSSnapshotCreateAdvisory{ TypedEvent: TypedEvent{ Type: JSSnapshotCreatedAdvisoryType, ID: nuid.Next(), Time: time.Now().UTC(), }, - Stream: mset.Name(), - NumBlks: sr.NumBlks, - BlkSize: sr.BlkSize, - Client: caudit, + Stream: mset.name(), + State: sr.State, + Client: ci.forAdvisory(), + Domain: s.getOpts().JetStreamDomain, }) // Now do the real streaming. - s.streamSnapshot(c, mset, sr, &req) + s.streamSnapshot(acc, mset, sr, &req) - end := time.Now() + end := time.Now().UTC() - s.publishAdvisory(c.acc, JSAdvisoryStreamSnapshotCompletePre+"."+mset.Name(), &JSSnapshotCompleteAdvisory{ + s.publishAdvisory(acc, JSAdvisoryStreamSnapshotCompletePre+"."+mset.name(), &JSSnapshotCompleteAdvisory{ TypedEvent: TypedEvent{ Type: JSSnapshotCompleteAdvisoryType, ID: nuid.Next(), - Time: time.Now().UTC(), + Time: end, }, - Stream: mset.Name(), - Start: start.UTC(), - End: end.UTC(), - Client: caudit, + Stream: mset.name(), + Start: start, + End: end, + Client: ci.forAdvisory(), + Domain: s.getOpts().JetStreamDomain, }) - s.Noticef("Completed %s snapshot for stream %q in account %q in %v", - FriendlyBytes(int64(resp.NumBlks*resp.BlkSize)), - mset.Name(), + s.Noticef("Completed snapshot of %s for stream '%s > %s' in %v", + friendlyBytes(int64(sr.State.Bytes)), mset.jsa.account.Name, + mset.name(), end.Sub(start)) }() } // Default chunk size for now. const defaultSnapshotChunkSize = 128 * 1024 -const defaultSnapshotWindowSize = 16 * 1024 * 1024 // 16MB +const defaultSnapshotWindowSize = 8 * 1024 * 1024 // 8MB // streamSnapshot will stream out our snapshot to the reply subject. -func (s *Server) streamSnapshot(c *client, mset *Stream, sr *SnapshotResult, req *JSApiStreamSnapshotRequest) { +func (s *Server) streamSnapshot(acc *Account, mset *stream, sr *SnapshotResult, req *JSApiStreamSnapshotRequest) { chunkSize := req.ChunkSize if chunkSize == 0 { chunkSize = defaultSnapshotChunkSize } // Setup for the chunk stream. - acc := c.acc reply := req.DeliverSubject r := sr.Reader defer r.Close() @@ -1408,148 +4251,316 @@ func (s *Server) streamSnapshot(c *client, mset *Stream, sr *SnapshotResult, req // Create our ack flow handler. // This is very simple for now. - acks := make(chan struct{}, 1) + ackSize := defaultSnapshotWindowSize / chunkSize + if ackSize < 8 { + ackSize = 8 + } else if ackSize > 8*1024 { + ackSize = 8 * 1024 + } + acks := make(chan struct{}, ackSize) acks <- struct{}{} // Track bytes outstanding. var out int32 // We will place sequence number and size of chunk sent in the reply. - ackSubj := fmt.Sprintf(jsSnapshotAckT, mset.Name(), nuid.Next()) - ackSub, _ := mset.subscribeInternalUnlocked(ackSubj+".>", func(_ *subscription, _ *client, subject, _ string, _ []byte) { + ackSubj := fmt.Sprintf(jsSnapshotAckT, mset.name(), nuid.Next()) + ackSub, _ := mset.subscribeInternal(ackSubj+".>", func(_ *subscription, _ *client, _ *Account, subject, _ string, _ []byte) { + cs, _ := strconv.Atoi(tokenAt(subject, 6)) // This is very crude and simple, but ok for now. // This only matters when sending multiple chunks. - if atomic.LoadInt32(&out) > defaultSnapshotWindowSize { - acks <- struct{}{} + if atomic.AddInt32(&out, int32(-cs)) < defaultSnapshotWindowSize { + select { + case acks <- struct{}{}: + default: + } } - cs, _ := strconv.Atoi(tokenAt(subject, 6)) - atomic.AddInt32(&out, int32(-cs)) }) - defer mset.unsubscribeUnlocked(ackSub) + defer mset.unsubscribe(ackSub) // TODO(dlc) - Add in NATS-Chunked-Sequence header - + var hdr []byte for index := 1; ; index++ { chunk := make([]byte, chunkSize) n, err := r.Read(chunk) chunk = chunk[:n] if err != nil { if n > 0 { - mset.sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, chunk, nil, 0} + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, chunk, nil, 0)) } break } // Wait on acks for flow control if past our window size. - // Wait up to 1ms for now if no acks received. + // Wait up to 10ms for now if no acks received. if atomic.LoadInt32(&out) > defaultSnapshotWindowSize { select { case <-acks: - case <-inch: // Lost interest + // ok to proceed. + case <-inch: + // Lost interest + hdr = []byte("NATS/1.0 408 No Interest\r\n\r\n") + goto done + case <-time.After(2 * time.Second): + hdr = []byte("NATS/1.0 408 No Flow Response\r\n\r\n") goto done - case <-time.After(time.Millisecond): } } - // TODO(dlc) - Might want these moved off sendq if we have contention. ackReply := fmt.Sprintf("%s.%d.%d", ackSubj, len(chunk), index) - mset.sendq <- &jsPubMsg{reply, _EMPTY_, ackReply, nil, chunk, nil, 0} + if hdr == nil { + hdr = []byte("NATS/1.0 204\r\n\r\n") + } + mset.outq.send(newJSPubMsg(reply, _EMPTY_, ackReply, nil, chunk, nil, 0)) atomic.AddInt32(&out, int32(len(chunk))) } + + if err := <-sr.errCh; err != _EMPTY_ { + hdr = []byte(fmt.Sprintf("NATS/1.0 500 %s\r\n\r\n", err)) + } + done: // Send last EOF // TODO(dlc) - place hash in header - mset.sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, nil, nil, 0} + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) } -// Request to create a durable consumer. -func (s *Server) jsDurableCreateRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - s.jsConsumerCreate(sub, c, subject, reply, msg, true) -} +// For determining consumer request type. +type ccReqType uint8 -// Request to create a consumer. -func (s *Server) jsConsumerCreateRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - s.jsConsumerCreate(sub, c, subject, reply, msg, false) -} +const ( + ccNew = iota + ccLegacyEphemeral + ccLegacyDurable +) + +// Request to create a consumer where stream and optional consumer name are part of the subject, and optional +// filtered subjects can be at the tail end. +// Assumes stream and consumer names are single tokens. +func (s *Server) jsConsumerCreateRequest(sub *subscription, c *client, a *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } -func (s *Server) jsConsumerCreate(sub *subscription, c *client, subject, reply string, msg []byte, expectDurable bool) { - if c == nil || c.acc == nil { + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + var req CreateConsumerRequest + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + var js *jetStream + isClustered := s.JetStreamIsClustered() + + // Determine if we should proceed here when we are in clustered mode. + if isClustered { + if req.Config.Direct { + // Check to see if we have this stream and are the stream leader. + if !acc.JetStreamIsStreamLeader(streamNameFromSubject(subject)) { + return + } + } else { + var cc *jetStreamCluster + js, cc = s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + } + + var streamName, consumerName, filteredSubject string + var rt ccReqType + + if n := numTokens(subject); n < 5 { + s.Warnf(badAPIRequestT, msg) return + } else if n == 5 { + // Legacy ephemeral. + rt = ccLegacyEphemeral + streamName = streamNameFromSubject(subject) + } else { + // New style and durable legacy. + if tokenAt(subject, 4) == "DURABLE" { + rt = ccLegacyDurable + if n != 7 { + resp.Error = NewJSConsumerDurableNameNotInSubjectError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + streamName = tokenAt(subject, 6) + consumerName = tokenAt(subject, 7) + } else { + streamName = streamNameFromSubject(subject) + consumerName = consumerNameFromSubject(subject) + // New has optional filtered subject as part of main subject.. + if n > 6 { + tokens := strings.Split(subject, tsep) + filteredSubject = strings.Join(tokens[6:], tsep) + } + } } - var req CreateConsumerRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } - var streamName string - if expectDurable { - streamName = tokenAt(subject, 6) - } else { - streamName = tokenAt(subject, 5) - } + if streamName != req.Stream { - resp.Error = &ApiError{Code: 400, Description: "stream name in subject does not match request"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamMismatchError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - stream, err := c.acc.LookupStream(req.Stream) - if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return + + if consumerName != _EMPTY_ { + // Check for path like separators in the name. + if strings.ContainsAny(consumerName, `\/`) { + resp.Error = NewJSConsumerNameContainsPathSeparatorsError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } } - if expectDurable { - if numTokens(subject) != 7 { - resp.Error = &ApiError{Code: 400, Description: "consumer expected to be durable but no durable name set in subject"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // Should we expect a durable name + if rt == ccLegacyDurable { + if numTokens(subject) < 7 { + resp.Error = NewJSConsumerDurableNameNotInSubjectError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } // Now check on requirements for durable request. if req.Config.Durable == _EMPTY_ { - resp.Error = &ApiError{Code: 400, Description: "consumer expected to be durable but a durable name was not set"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSConsumerDurableNameNotSetError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - consumerName := tokenAt(subject, 7) if consumerName != req.Config.Durable { - resp.Error = &ApiError{Code: 400, Description: "consumer name in subject does not match durable name in request"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return - } - } else { - if numTokens(subject) != 5 { - resp.Error = &ApiError{Code: 400, Description: "consumer expected to be ephemeral but detected a durable name set in subject"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSConsumerDurableNameNotMatchSubjectError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } + } + // If new style and durable set make sure they match. + if rt == ccNew { if req.Config.Durable != _EMPTY_ { - resp.Error = &ApiError{Code: 400, Description: "consumer expected to be ephemeral but a durable name was set in request"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if consumerName != req.Config.Durable { + resp.Error = NewJSConsumerDurableNameNotMatchSubjectError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + // New style ephemeral so we need to honor the name. + req.Config.Name = consumerName + } + // Check for legacy ephemeral mis-configuration. + if rt == ccLegacyEphemeral && req.Config.Durable != _EMPTY_ { + resp.Error = NewJSConsumerEphemeralWithDurableNameError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // in case of multiple filters provided, error if new API is used. + if filteredSubject != _EMPTY_ && len(req.Config.FilterSubjects) != 0 { + resp.Error = NewJSConsumerMultipleFiltersNotAllowedError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // Check for a filter subject. + if filteredSubject != _EMPTY_ && req.Config.FilterSubject != filteredSubject { + resp.Error = NewJSConsumerCreateFilterSubjectMismatchError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if isClustered && !req.Config.Direct { + s.jsClusteredConsumerRequest(ci, acc, subject, reply, rmsg, req.Stream, &req.Config, req.Action, req.Pedantic) + return + } + + // If we are here we are single server mode. + if req.Config.Replicas > 1 { + resp.Error = NewJSStreamReplicasNotSupportedError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + stream, err := acc.lookupStream(req.Stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if stream.offlineReason != _EMPTY_ { + resp.Error = NewJSStreamOfflineReasonError(errors.New(stream.offlineReason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + + if o := stream.lookupConsumer(consumerName); o != nil { + if o.offlineReason != _EMPTY_ { + resp.Error = NewJSConsumerOfflineReasonError(errors.New(o.offlineReason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) return } + // If the consumer already exists then don't allow updating the PauseUntil, just set + // it back to whatever the current configured value is. + o.mu.RLock() + req.Config.PauseUntil = o.cfg.PauseUntil + o.mu.RUnlock() } - o, err := stream.AddConsumer(&req.Config) + // Initialize/update asset version metadata. + setStaticConsumerMetadata(&req.Config) + + o, err := stream.addConsumerWithAction(&req.Config, req.Action, req.Pedantic) + if err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if IsNatsErr(err, JSConsumerStoreFailedErrF) { + cname := req.Config.Durable // Will be empty if ephemeral. + s.Warnf("Consumer create failed for '%s > %s > %s': %v", acc, req.Stream, cname, err) + err = errConsumerStoreFailed + } + resp.Error = NewJSConsumerCreateError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - resp.ConsumerInfo = o.Info() - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + resp.ConsumerInfo = setDynamicConsumerInfoMetadata(o.initialInfo()) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) + + o.mu.RLock() + if o.cfg.PauseUntil != nil && !o.cfg.PauseUntil.IsZero() && time.Now().Before(*o.cfg.PauseUntil) { + o.sendPauseAdvisoryLocked(&o.cfg) + } + o.mu.RUnlock() } // Request for the list of all consumer names. -func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } @@ -1558,56 +4569,120 @@ func (s *Server) jsConsumerNamesRequest(sub *subscription, c *client, subject, r Consumers: []string{}, } - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } var offset int - if !isEmptyRequest(msg) { + if isJSONObjectOrArray(msg) { var req JSApiConsumersRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } offset = req.Offset } streamName := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(streamName) - if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) - return - } + var numConsumers int - obs := mset.Consumers() - sort.Slice(obs, func(i, j int) bool { - return strings.Compare(obs[i].name, obs[j].name) < 0 - }) + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + // TODO(dlc) - Debug or Warn? + return + } + js.mu.RLock() + sas := cc.streams[acc.Name] + if sas == nil { + js.mu.RUnlock() + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + sa := sas[streamName] + if sa == nil || sa.err != nil { + js.mu.RUnlock() + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + for consumer := range sa.consumers { + resp.Consumers = append(resp.Consumers, consumer) + } + if len(resp.Consumers) > 1 { + slices.Sort(resp.Consumers) + } + numConsumers = len(resp.Consumers) + if offset > numConsumers { + offset = numConsumers + } + resp.Consumers = resp.Consumers[offset:] + if len(resp.Consumers) > JSApiNamesLimit { + resp.Consumers = resp.Consumers[:JSApiNamesLimit] + } + js.mu.RUnlock() - ocnt := len(obs) - if offset > ocnt { - offset = ocnt - } + } else { + mset, err := acc.lookupStream(streamName) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } - for _, o := range obs[offset:] { - resp.Consumers = append(resp.Consumers, o.Name()) - if len(resp.Consumers) >= JSApiNamesLimit { - break + obs := mset.getPublicConsumers() + slices.SortFunc(obs, func(i, j *consumer) int { return cmp.Compare(i.name, j.name) }) + + numConsumers = len(obs) + if offset > numConsumers { + offset = numConsumers + } + + for _, o := range obs[offset:] { + resp.Consumers = append(resp.Consumers, o.String()) + if len(resp.Consumers) >= JSApiNamesLimit { + break + } } } - resp.Total = ocnt + resp.Total = numConsumers resp.Limit = JSApiNamesLimit resp.Offset = offset - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request for the list of all detailed consumer information. -func (s *Server) jsConsumerListRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsConsumerListRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } @@ -1616,43 +4691,82 @@ func (s *Server) jsConsumerListRequest(sub *subscription, c *client, subject, re Consumers: []*ConsumerInfo{}, } - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } var offset int - if !isEmptyRequest(msg) { + if isJSONObjectOrArray(msg) { var req JSApiConsumersRequest - if err := json.Unmarshal(msg, &req); err != nil { - resp.Error = jsInvalidJSONErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } offset = req.Offset } streamName := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(streamName) + + // Clustered mode will invoke a scatter and gather. + if s.JetStreamIsClustered() { + // Need to copy these off before sending.. don't move this inside startGoRoutine!!! + msg = copyBytes(msg) + s.startGoRoutine(func() { + s.jsClusteredConsumerListRequest(acc, ci, offset, streamName, subject, reply, msg) + }) + return + } + + mset, err := acc.lookupStream(streamName) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - obs := mset.Consumers() - sort.Slice(obs, func(i, j int) bool { - return strings.Compare(obs[i].name, obs[j].name) < 0 - }) + obs := mset.getPublicConsumers() + slices.SortFunc(obs, func(i, j *consumer) int { return cmp.Compare(i.name, j.name) }) ocnt := len(obs) if offset > ocnt { offset = ocnt } + var missingNames []string for _, o := range obs[offset:] { - resp.Consumers = append(resp.Consumers, o.Info()) + if o.offlineReason != _EMPTY_ { + if resp.Offline == nil { + resp.Offline = make(map[string]string, 1) + } + resp.Offline[o.name] = o.offlineReason + missingNames = append(missingNames, o.name) + continue + } + if cinfo := o.info(); cinfo != nil { + resp.Consumers = append(resp.Consumers, cinfo) + } if len(resp.Consumers) >= JSApiListLimit { break } @@ -1660,144 +4774,449 @@ func (s *Server) jsConsumerListRequest(sub *subscription, c *client, subject, re resp.Total = ocnt resp.Limit = JSApiListLimit resp.Offset = offset - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + resp.Missing = missingNames + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request for information about an consumer. -func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } + streamName := streamNameFromSubject(subject) + consumerName := consumerNameFromSubject(subject) + var resp = JSApiConsumerInfoResponse{ApiResponse: ApiResponse{Type: JSApiConsumerInfoResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + if !isEmptyRequest(msg) { + resp.Error = NewJSNotEmptyRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + // If we are in clustered mode we need to be the consumer leader to proceed. + if s.JetStreamIsClustered() { + // Check to make sure the consumer is assigned. + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.RLock() + meta := cc.meta + js.mu.RUnlock() + + if meta == nil { + return + } + + // Since these could wait on the Raft group lock, don't do so under the JS lock. + ourID := meta.ID() + groupLeaderless := meta.Leaderless() + groupCreated := meta.Created() + + js.mu.RLock() + isLeader, sa, ca := cc.isLeader(), js.streamAssignment(acc.Name, streamName), js.consumerAssignment(acc.Name, streamName, consumerName) + var rg *raftGroup + var offline, isMember bool + if ca != nil { + if rg = ca.Group; rg != nil { + offline = s.allPeersOffline(rg) + isMember = rg.isMember(ourID) + } + if ca.unsupported != nil && isMember { + // If we're a member for this consumer, and it's not supported, report it as offline. + resp.Error = NewJSConsumerOfflineReasonError(errors.New(ca.unsupported.reason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + js.mu.RUnlock() + return + } + } + // Capture consumer leader here. + isConsumerLeader := cc.isConsumerLeader(acc.Name, streamName, consumerName) + // Also capture if we think there is no meta leader. + var isLeaderLess bool + if !isLeader { + isLeaderLess = groupLeaderless && time.Since(groupCreated) > lostQuorumIntervalDefault + } + js.mu.RUnlock() + + if isLeader && ca == nil { + // We can't find the consumer, so mimic what would be the errors below. + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } + return + } + if sa == nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // If we are here the consumer is not present. + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } else if ca == nil { + if isLeaderLess { + resp.Error = NewJSClusterNotAvailError() + // Delaying an error response gives the leader a chance to respond before us + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + } + return + } else if isLeader && offline { + resp.Error = NewJSConsumerOfflineError() + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + + // Check to see if we are a member of the group and if the group has no leader. + if isMember && js.isGroupLeaderless(ca.Group) { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + // We have the consumer assigned and a leader, so only the consumer leader should answer. + if !isConsumerLeader { + if isLeaderLess { + resp.Error = NewJSClusterNotAvailError() + // Delaying an error response gives the leader a chance to respond before us + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), ca.Group, errRespDelay) + return + } + + var node RaftNode + var leaderNotPartOfGroup bool + + // We have a consumer assignment. + if isMember { + js.mu.RLock() + if rg != nil && rg.node != nil { + node = rg.node + if gl := node.GroupLeader(); gl != _EMPTY_ && !rg.isMember(gl) { + leaderNotPartOfGroup = true + } + } + js.mu.RUnlock() + } + + // Check if we should ignore all together. + if node == nil { + // We have been assigned but have not created a node yet. If we are a member return + // our config and defaults for state and no cluster info. + if isMember { + // Since we access consumerAssignment, need js lock. + js.mu.RLock() + resp.ConsumerInfo = &ConsumerInfo{ + Stream: ca.Stream, + Name: ca.Name, + Created: ca.Created, + Config: setDynamicConsumerMetadata(ca.Config), + TimeStamp: time.Now().UTC(), + } + b := s.jsonResponse(resp) + js.mu.RUnlock() + s.sendAPIResponse(ci, acc, subject, reply, string(msg), b) + } + return + } + // If we are a member and we have a group leader or we had a previous leader consider bailing out. + if !node.Leaderless() || node.HadPreviousLeader() || (rg != nil && rg.Preferred != _EMPTY_ && rg.Preferred != ourID) { + if leaderNotPartOfGroup { + resp.Error = NewJSConsumerOfflineError() + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + } + return + } + // If we are here we are a member and this is just a new consumer that does not have a (preferred) leader yet. + // Will fall through and return what we have. All consumers can respond but this should be very rare + // but makes more sense to clients when they try to create, get a consumer exists, and then do consumer info. + } + } + + if !acc.JetStreamEnabled() { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - stream := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(stream) + mset, err := acc.lookupStream(streamName) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - consumer := consumerNameFromSubject(subject) - obs := mset.LookupConsumer(consumer) + + obs := mset.lookupConsumer(consumerName) if obs == nil { - resp.Error = &ApiError{Code: 404, Description: "consumer not found"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + if obs.offlineReason != _EMPTY_ { + resp.Error = NewJSConsumerOfflineReasonError(errors.New(obs.offlineReason)) + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + + if resp.ConsumerInfo = setDynamicConsumerInfoMetadata(obs.info()); resp.ConsumerInfo == nil { + // This consumer returned nil which means it's closed. Respond with not found. + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - resp.ConsumerInfo = obs.Info() - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } // Request to delete an Consumer. -func (s *Server) jsConsumerDeleteRequest(sub *subscription, c *client, subject, reply string, msg []byte) { - if c == nil || c.acc == nil { +func (s *Server) jsConsumerDeleteRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) + if err != nil { + s.Warnf(badAPIRequestT, msg) return } var resp = JSApiConsumerDeleteResponse{ApiResponse: ApiResponse{Type: JSApiConsumerDeleteResponseType}} - if !c.acc.JetStreamEnabled() { - resp.Error = jsNotEnabledErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + // Determine if we should proceed here when we are in clustered mode. + if s.JetStreamIsClustered() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } if !isEmptyRequest(msg) { - resp.Error = jsNotEmptyRequestErr - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSNotEmptyRequestError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } stream := streamNameFromSubject(subject) - mset, err := c.acc.LookupStream(stream) + consumer := consumerNameFromSubject(subject) + + if s.JetStreamIsClustered() { + s.jsClusteredConsumerDeleteRequest(ci, acc, stream, consumer, subject, reply, rmsg) + return + } + + mset, err := acc.lookupStream(stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + obs := mset.lookupConsumer(consumer) + if obs == nil { + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if err := obs.delete(); err != nil { + resp.Error = NewJSStreamGeneralError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + resp.Success = true + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) +} + +// Request to pause or unpause a Consumer. +func (s *Server) jsConsumerPauseRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if c == nil || !s.JetStreamEnabled() { + return + } + ci, acc, _, msg, err := s.getRequestInfo(c, rmsg) if err != nil { - resp.Error = jsNotFoundError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + s.Warnf(badAPIRequestT, msg) return } - if mset.Config().internal { - resp.Error = &ApiError{Code: 403, Description: "not allowed to delete consumer of internal stream"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + + var req JSApiConsumerPauseRequest + var resp = JSApiConsumerPauseResponse{ApiResponse: ApiResponse{Type: JSApiConsumerPauseResponseType}} + + if isJSONObjectOrArray(msg) { + if err := s.unmarshalRequest(c, acc, subject, msg, &req); err != nil { + resp.Error = NewJSInvalidJSONError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + } + + // Determine if we should proceed here when we are in clustered mode. + isClustered := s.JetStreamIsClustered() + js, cc := s.getJetStreamCluster() + if isClustered { + if js == nil || cc == nil { + return + } + if js.isLeaderless() { + resp.Error = NewJSClusterNotAvailError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + // Make sure we are meta leader. + if !s.JetStreamIsLeader() { + return + } + } + + if hasJS, doErr := acc.checkJetStream(); !hasJS { + if doErr { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + } return } + + stream := streamNameFromSubject(subject) consumer := consumerNameFromSubject(subject) - obs := mset.LookupConsumer(consumer) + + if isClustered { + js.mu.RLock() + sa := js.streamAssignment(acc.Name, stream) + if sa == nil { + js.mu.RUnlock() + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if sa.unsupported != nil { + js.mu.RUnlock() + // Just let the request time out. + return + } + + ca, ok := sa.consumers[consumer] + if !ok || ca == nil { + js.mu.RUnlock() + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if ca.unsupported != nil { + js.mu.RUnlock() + // Just let the request time out. + return + } + + nca := *ca + ncfg := *ca.Config + nca.Config = &ncfg + meta := cc.meta + js.mu.RUnlock() + pauseUTC := req.PauseUntil.UTC() + if !pauseUTC.IsZero() { + nca.Config.PauseUntil = &pauseUTC + } else { + nca.Config.PauseUntil = nil + } + + // Update asset version metadata due to updating pause/resume. + // Only PauseUntil is updated above, so reuse config for both. + setStaticConsumerMetadata(nca.Config) + + eca := encodeAddConsumerAssignment(&nca) + meta.Propose(eca) + + resp.PauseUntil = pauseUTC + if resp.Paused = time.Now().Before(pauseUTC); resp.Paused { + resp.PauseRemaining = time.Until(pauseUTC) + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) + return + } + + mset, err := acc.lookupStream(stream) + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + if mset.offlineReason != _EMPTY_ { + // Just let the request time out. + return + } + + obs := mset.lookupConsumer(consumer) if obs == nil { - resp.Error = &ApiError{Code: 404, Description: "consumer not found"} - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if err := obs.Delete(); err != nil { - resp.Error = jsError(err) - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp)) + if obs.offlineReason != _EMPTY_ { + // Just let the request time out. return } - resp.Success = true - s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp)) + + ncfg := obs.cfg + pauseUTC := req.PauseUntil.UTC() + if !pauseUTC.IsZero() { + ncfg.PauseUntil = &pauseUTC + } else { + ncfg.PauseUntil = nil + } + + // Update asset version metadata due to updating pause/resume. + setStaticConsumerMetadata(&ncfg) + + if err := obs.updateConfig(&ncfg); err != nil { + // The only type of error that should be returned here is from o.store, + // so use a store failed error type. + resp.Error = NewJSConsumerStoreFailedError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) + return + } + + resp.PauseUntil = pauseUTC + if resp.Paused = time.Now().Before(pauseUTC); resp.Paused { + resp.PauseRemaining = time.Until(pauseUTC) + } + s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp)) } -// sendJetStreamAPIAuditAdvisor will send the audit event for a given event. -func (s *Server) sendJetStreamAPIAuditAdvisory(c *client, subject, request, response string) { - s.publishAdvisory(c.acc, JSAuditAdvisory, JSAPIAudit{ +// sendJetStreamAPIAuditAdvisory will send the audit event for a given event. +func (s *Server) sendJetStreamAPIAuditAdvisory(ci *ClientInfo, acc *Account, subject, request, response string) { + s.publishAdvisory(acc, JSAuditAdvisory, JSAPIAudit{ TypedEvent: TypedEvent{ Type: JSAPIAuditType, ID: nuid.Next(), Time: time.Now().UTC(), }, Server: s.Name(), - Client: *c.apiAuditClient(), + Client: ci.forAdvisory(), Subject: subject, Request: request, Response: response, + Domain: s.getOpts().JetStreamDomain, }) } - -func (c *client) apiAuditClient() *ClientAPIAudit { - c.mu.Lock() - auditUser := c.auditUser() - h, p := c.auditClient() - appName := c.opts.Name - lang := c.opts.Lang - version := c.opts.Version - cid := c.cid - c.mu.Unlock() - - return &ClientAPIAudit{ - Host: h, - Port: p, - CID: cid, - Account: c.Account().Name, - User: auditUser, - Name: appName, - Language: lang, - Version: version, - } -} - -// Returns a string identifying the user for an audit event. Returns empty string when no user is present. -func (c *client) auditUser() string { - switch { - case c.opts.Nkey != "": - return c.opts.Nkey - case c.opts.Username != "": - return c.opts.Username - default: - return "" - } -} - -// Returns the audit client name, which will just be IP:Port -func (c *client) auditClient() (string, int) { - parts := strings.Split(c.String(), " ") - h, p, _ := net.SplitHostPort(parts[0]) - port, _ := strconv.Atoi(p) - return h, port -} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go new file mode 100644 index 0000000..22dbbf4 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go @@ -0,0 +1,9948 @@ +// Copyright 2020-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "cmp" + crand "crypto/rand" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "math" + "math/rand" + "os" + "path/filepath" + "reflect" + "slices" + "strconv" + "strings" + "sync/atomic" + "time" + + "github.com/antithesishq/antithesis-sdk-go/assert" + "github.com/klauspost/compress/s2" + "github.com/minio/highwayhash" + "github.com/nats-io/nuid" +) + +// jetStreamCluster holds information about the meta group and stream assignments. +type jetStreamCluster struct { + // The metacontroller raftNode. + meta RaftNode + // For stream and consumer assignments. All servers will have this be the same. + // ACCOUNT -> STREAM -> Stream Assignment -> Consumers + streams map[string]map[string]*streamAssignment + // These are inflight proposals and used to apply limits when there are + // concurrent requests that would otherwise be accepted. + // We also record the group for the stream. This is needed since if we have + // concurrent requests for same account and stream we need to let it process to get + // a response but they need to be same group, peers etc. and sync subjects. + inflight map[string]map[string]*inflightInfo + // Holds a map of a peer ID to the reply subject, to only respond after gaining + // quorum on the peer-remove action. + peerRemoveReply map[string]peerRemoveInfo + // Signals meta-leader should check the stream assignments. + streamsCheck bool + // Server. + s *Server + // Internal client. + c *client + // Processing assignment results. + streamResults *subscription + consumerResults *subscription + // System level request to have the leader stepdown. + stepdown *subscription + // System level requests to remove a peer. + peerRemove *subscription + // System level request to move a stream + peerStreamMove *subscription + // System level request to cancel a stream move + peerStreamCancelMove *subscription + // To pop out the monitorCluster before the raft layer. + qch chan struct{} + // To notify others that monitorCluster has actually stopped. + stopped chan struct{} + // Track last meta snapshot time and duration for monitoring. + lastMetaSnapTime int64 // Unix nanoseconds + lastMetaSnapDuration int64 // Duration in nanoseconds +} + +// Used to track inflight stream add requests to properly re-use same group and sync subject. +type inflightInfo struct { + rg *raftGroup + sync string + cfg *StreamConfig +} + +// Used to track inflight peer-remove info to respond 'success' after quorum. +type peerRemoveInfo struct { + ci *ClientInfo + subject string + reply string + request string +} + +// Used to guide placement of streams and meta controllers in clustered JetStream. +type Placement struct { + Cluster string `json:"cluster,omitempty"` + Tags []string `json:"tags,omitempty"` + Preferred string `json:"preferred,omitempty"` +} + +// Define types of the entry. +type entryOp uint8 + +// ONLY ADD TO THE END, DO NOT INSERT IN BETWEEN WILL BREAK SERVER INTEROP. +const ( + // Meta ops. + assignStreamOp entryOp = iota + assignConsumerOp + removeStreamOp + removeConsumerOp + // Stream ops. + streamMsgOp + purgeStreamOp + deleteMsgOp + // Consumer ops. + updateDeliveredOp + updateAcksOp + // Compressed consumer assignments. + assignCompressedConsumerOp + // Filtered Consumer skip. + updateSkipOp + // Update Stream. + updateStreamOp + // For updating information on pending pull requests. + addPendingRequest + removePendingRequest + // For sending compressed streams, either through RAFT or catchup. + compressedStreamMsgOp + // For sending deleted gaps on catchups for replicas. + deleteRangeOp +) + +// raftGroups are controlled by the metagroup controller. +// The raftGroups will house streams and consumers. +type raftGroup struct { + Name string `json:"name"` + Peers []string `json:"peers"` + Storage StorageType `json:"store"` + Cluster string `json:"cluster,omitempty"` + Preferred string `json:"preferred,omitempty"` + // Internal + node RaftNode +} + +// streamAssignment is what the meta controller uses to assign streams to peers. +type streamAssignment struct { + Client *ClientInfo `json:"client,omitempty"` + Created time.Time `json:"created"` + ConfigJSON json.RawMessage `json:"stream"` + Config *StreamConfig `json:"-"` + Group *raftGroup `json:"group"` + Sync string `json:"sync"` + Subject string `json:"subject,omitempty"` + Reply string `json:"reply,omitempty"` + Restore *StreamState `json:"restore_state,omitempty"` + // Internal + consumers map[string]*consumerAssignment + responded bool + recovering bool + reassigning bool // i.e. due to placement issues, lack of resources, etc. + resetting bool // i.e. there was an error, and we're stopping and starting the stream + err error + unsupported *unsupportedStreamAssignment +} + +type unsupportedStreamAssignment struct { + reason string + info StreamInfo + sysc *client + infoSub *subscription +} + +func newUnsupportedStreamAssignment(s *Server, sa *streamAssignment, err error) *unsupportedStreamAssignment { + reason := "stopped" + if err != nil { + if errstr := err.Error(); strings.HasPrefix(errstr, "json:") { + reason = fmt.Sprintf("unsupported - config error: %s", strings.TrimPrefix(err.Error(), "json: ")) + } else { + reason = fmt.Sprintf("stopped - %s", errstr) + } + } else if sa.Config != nil && !supportsRequiredApiLevel(sa.Config.Metadata) { + if req := getRequiredApiLevel(sa.Config.Metadata); req != _EMPTY_ { + reason = fmt.Sprintf("unsupported - required API level: %s, current API level: %d", req, JSApiLevel) + } + } + return &unsupportedStreamAssignment{ + reason: reason, + info: StreamInfo{ + Created: sa.Created, + Config: *setDynamicStreamMetadata(sa.Config), + Domain: s.getOpts().JetStreamDomain, + TimeStamp: time.Now().UTC(), + }, + } +} + +func (usa *unsupportedStreamAssignment) setupInfoSub(s *Server, sa *streamAssignment) { + if usa.infoSub != nil { + return + } + + // Bind to the system account. + ic := s.createInternalJetStreamClient() + ic.registerWithAccount(s.SystemAccount()) + usa.sysc = ic + + // Note below the way we subscribe here is so that we can send requests to ourselves. + isubj := fmt.Sprintf(clusterStreamInfoT, sa.Client.serviceAccount(), sa.Config.Name) + usa.infoSub, _ = s.systemSubscribe(isubj, _EMPTY_, false, ic, usa.handleClusterStreamInfoRequest) +} + +func (usa *unsupportedStreamAssignment) handleClusterStreamInfoRequest(_ *subscription, c *client, _ *Account, _, reply string, _ []byte) { + s, acc := c.srv, c.acc + info := streamInfoClusterResponse{OfflineReason: usa.reason, StreamInfo: usa.info} + s.sendDelayedErrResponse(acc, reply, nil, s.jsonResponse(&info), errRespDelay) +} + +func (usa *unsupportedStreamAssignment) closeInfoSub(s *Server) { + if usa.infoSub != nil { + s.sysUnsubscribe(usa.infoSub) + usa.infoSub = nil + } + if usa.sysc != nil { + usa.sysc.closeConnection(ClientClosed) + usa.sysc = nil + } +} + +// consumerAssignment is what the meta controller uses to assign consumers to streams. +type consumerAssignment struct { + Client *ClientInfo `json:"client,omitempty"` + Created time.Time `json:"created"` + Name string `json:"name"` + Stream string `json:"stream"` + ConfigJSON json.RawMessage `json:"consumer"` + Config *ConsumerConfig `json:"-"` + Group *raftGroup `json:"group"` + Subject string `json:"subject,omitempty"` + Reply string `json:"reply,omitempty"` + State *ConsumerState `json:"state,omitempty"` + // Internal + responded bool + recovering bool + pending bool + deleted bool + err error + unsupported *unsupportedConsumerAssignment +} + +type unsupportedConsumerAssignment struct { + reason string + info ConsumerInfo + sysc *client + infoSub *subscription +} + +func newUnsupportedConsumerAssignment(ca *consumerAssignment, err error) *unsupportedConsumerAssignment { + reason := "stopped" + if err != nil { + if errstr := err.Error(); strings.HasPrefix(errstr, "json:") { + reason = fmt.Sprintf("unsupported - config error: %s", strings.TrimPrefix(err.Error(), "json: ")) + } else { + reason = fmt.Sprintf("stopped - %s", errstr) + } + } else if ca.Config != nil && !supportsRequiredApiLevel(ca.Config.Metadata) { + if req := getRequiredApiLevel(ca.Config.Metadata); req != _EMPTY_ { + reason = fmt.Sprintf("unsupported - required API level: %s, current API level: %d", getRequiredApiLevel(ca.Config.Metadata), JSApiLevel) + } + } + return &unsupportedConsumerAssignment{ + reason: reason, + info: ConsumerInfo{ + Stream: ca.Stream, + Name: ca.Name, + Created: ca.Created, + Config: setDynamicConsumerMetadata(ca.Config), + TimeStamp: time.Now().UTC(), + }, + } +} + +func (uca *unsupportedConsumerAssignment) setupInfoSub(s *Server, ca *consumerAssignment) { + if uca.infoSub != nil { + return + } + + // Bind to the system account. + ic := s.createInternalJetStreamClient() + ic.registerWithAccount(s.SystemAccount()) + uca.sysc = ic + + // Note below the way we subscribe here is so that we can send requests to ourselves. + isubj := fmt.Sprintf(clusterConsumerInfoT, ca.Client.serviceAccount(), ca.Stream, ca.Name) + uca.infoSub, _ = s.systemSubscribe(isubj, _EMPTY_, false, ic, uca.handleClusterConsumerInfoRequest) +} + +func (uca *unsupportedConsumerAssignment) handleClusterConsumerInfoRequest(_ *subscription, c *client, _ *Account, _, reply string, _ []byte) { + s, acc := c.srv, c.acc + info := consumerInfoClusterResponse{OfflineReason: uca.reason, ConsumerInfo: uca.info} + s.sendDelayedErrResponse(acc, reply, nil, s.jsonResponse(&info), errRespDelay) +} + +func (uca *unsupportedConsumerAssignment) closeInfoSub(s *Server) { + if uca.infoSub != nil { + s.sysUnsubscribe(uca.infoSub) + uca.infoSub = nil + } + if uca.sysc != nil { + uca.sysc.closeConnection(ClientClosed) + uca.sysc = nil + } +} + +type writeableConsumerAssignment struct { + Client *ClientInfo `json:"client,omitempty"` + Created time.Time `json:"created"` + Name string `json:"name"` + Stream string `json:"stream"` + ConfigJSON json.RawMessage `json:"consumer"` + Group *raftGroup `json:"group"` + State *ConsumerState `json:"state,omitempty"` +} + +// streamPurge is what the stream leader will replicate when purging a stream. +type streamPurge struct { + Client *ClientInfo `json:"client,omitempty"` + Stream string `json:"stream"` + LastSeq uint64 `json:"last_seq"` + Subject string `json:"subject"` + Reply string `json:"reply"` + Request *JSApiStreamPurgeRequest `json:"request,omitempty"` +} + +// streamMsgDelete is what the stream leader will replicate when deleting a message. +type streamMsgDelete struct { + Client *ClientInfo `json:"client,omitempty"` + Stream string `json:"stream"` + Seq uint64 `json:"seq"` + NoErase bool `json:"no_erase,omitempty"` + Subject string `json:"subject"` + Reply string `json:"reply"` +} + +const ( + defaultStoreDirName = "_js_" + defaultMetaGroupName = "_meta_" + defaultMetaFSBlkSize = 1024 * 1024 + jsExcludePlacement = "!jetstream" +) + +// Returns information useful in mixed mode. +func (s *Server) trackedJetStreamServers() (js, total int) { + s.mu.RLock() + defer s.mu.RUnlock() + if !s.isRunning() || !s.eventsEnabled() { + return -1, -1 + } + s.nodeToInfo.Range(func(k, v any) bool { + si := v.(nodeInfo) + if si.js { + js++ + } + total++ + return true + }) + return js, total +} + +func (s *Server) getJetStreamCluster() (*jetStream, *jetStreamCluster) { + if s.isShuttingDown() { + return nil, nil + } + + js := s.getJetStream() + if js == nil { + return nil, nil + } + + // Only set once, do not need a lock. + return js, js.cluster +} + +func (s *Server) JetStreamIsClustered() bool { + return s.jsClustered.Load() +} + +func (s *Server) JetStreamIsLeader() bool { + return s.isMetaLeader.Load() +} + +func (s *Server) JetStreamIsCurrent() bool { + js := s.getJetStream() + if js == nil { + return false + } + // Grab what we need and release js lock. + js.mu.RLock() + var meta RaftNode + cc := js.cluster + if cc != nil { + meta = cc.meta + } + js.mu.RUnlock() + + if cc == nil { + // Non-clustered mode + return true + } + return meta.Current() +} + +func (s *Server) JetStreamSnapshotMeta() error { + js := s.getJetStream() + if js == nil { + return NewJSNotEnabledError() + } + js.mu.RLock() + cc := js.cluster + isLeader := cc.isLeader() + meta := cc.meta + js.mu.RUnlock() + + if !isLeader { + return errNotLeader + } + + snap, err := js.metaSnapshot() + if err != nil { + return err + } + + return meta.InstallSnapshot(snap) +} + +func (s *Server) JetStreamStepdownStream(account, stream string) error { + js, cc := s.getJetStreamCluster() + if js == nil { + return NewJSNotEnabledError() + } + if cc == nil { + return NewJSClusterNotActiveError() + } + // Grab account + acc, err := s.LookupAccount(account) + if err != nil { + return err + } + // Grab stream + mset, err := acc.lookupStream(stream) + if err != nil { + return err + } + + if node := mset.raftNode(); node != nil { + node.StepDown() + } + + return nil +} + +func (s *Server) JetStreamStepdownConsumer(account, stream, consumer string) error { + js, cc := s.getJetStreamCluster() + if js == nil { + return NewJSNotEnabledError() + } + if cc == nil { + return NewJSClusterNotActiveError() + } + // Grab account + acc, err := s.LookupAccount(account) + if err != nil { + return err + } + // Grab stream + mset, err := acc.lookupStream(stream) + if err != nil { + return err + } + + o := mset.lookupConsumer(consumer) + if o == nil { + return NewJSConsumerNotFoundError() + } + + if node := o.raftNode(); node != nil { + node.StepDown() + } + + return nil +} + +func (s *Server) JetStreamSnapshotStream(account, stream string) error { + js, cc := s.getJetStreamCluster() + if js == nil { + return NewJSNotEnabledForAccountError() + } + if cc == nil { + return NewJSClusterNotActiveError() + } + // Grab account + acc, err := s.LookupAccount(account) + if err != nil { + return err + } + // Grab stream + mset, err := acc.lookupStream(stream) + if err != nil { + return err + } + + // Hold lock when installing snapshot. + mset.mu.Lock() + if mset.node == nil { + mset.mu.Unlock() + return nil + } + err = mset.node.InstallSnapshot(mset.stateSnapshotLocked()) + mset.mu.Unlock() + + return err +} + +func (s *Server) JetStreamClusterPeers() []string { + js := s.getJetStream() + if js == nil { + return nil + } + js.mu.RLock() + defer js.mu.RUnlock() + + cc := js.cluster + if !cc.isLeader() || cc.meta == nil { + return nil + } + peers := cc.meta.Peers() + var nodes []string + for _, p := range peers { + si, ok := s.nodeToInfo.Load(p.ID) + if !ok || si == nil { + continue + } + ni := si.(nodeInfo) + // Ignore if offline, no JS, or no current stats have been received. + if ni.offline || !ni.js || ni.stats == nil { + continue + } + nodes = append(nodes, si.(nodeInfo).name) + } + return nodes +} + +// Read lock should be held. +func (cc *jetStreamCluster) isLeader() bool { + if cc == nil { + // Non-clustered mode + return true + } + return cc.meta != nil && cc.meta.Leader() +} + +// isStreamCurrent will determine if the stream is up to date. +// For R1 it will make sure the stream is present on this server. +// Read lock should be held. +func (cc *jetStreamCluster) isStreamCurrent(account, stream string) bool { + if cc == nil { + // Non-clustered mode + return true + } + as := cc.streams[account] + if as == nil { + return false + } + sa := as[stream] + if sa == nil { + return false + } + rg := sa.Group + if rg == nil { + return false + } + + if rg.node == nil || rg.node.Current() { + // Check if we are processing a snapshot and are catching up. + acc, err := cc.s.LookupAccount(account) + if err != nil { + return false + } + mset, err := acc.lookupStream(stream) + if err != nil { + return false + } + if mset.isCatchingUp() { + return false + } + // Success. + return true + } + + return false +} + +// isStreamHealthy will determine if the stream is up to date or very close. +// For R1 it will make sure the stream is present on this server. +func (js *jetStream) isStreamHealthy(acc *Account, sa *streamAssignment) error { + js.mu.RLock() + if sa != nil && sa.unsupported != nil { + js.mu.RUnlock() + return nil + } + s, cc := js.srv, js.cluster + if cc == nil { + // Non-clustered mode + js.mu.RUnlock() + return nil + } + if sa == nil || sa.Group == nil { + js.mu.RUnlock() + return errors.New("stream assignment or group missing") + } + streamName := sa.Config.Name + node := sa.Group.node + js.mu.RUnlock() + + // First lookup stream and make sure its there. + mset, err := acc.lookupStream(streamName) + if err != nil { + return errors.New("stream not found") + } + + msetNode := mset.raftNode() + mset.cfgMu.RLock() + replicas := mset.cfg.Replicas + mset.cfgMu.RUnlock() + switch { + case replicas <= 1: + return nil // No further checks for R=1 streams + + case node == nil: + return errors.New("group node missing") + + case msetNode == nil: + // Can happen when the stream's node is not yet initialized. + return errors.New("stream node missing") + + case node != msetNode: + s.Warnf("Detected stream cluster node skew '%s > %s'", acc.GetName(), streamName) + return errors.New("cluster node skew detected") + + case !mset.isMonitorRunning(): + return errors.New("monitor goroutine not running") + + case mset.isCatchingUp(): + return errors.New("stream catching up") + + case !node.Healthy(): + return errors.New("group node unhealthy") + + default: + return nil + } +} + +// isConsumerHealthy will determine if the consumer is up to date. +// For R1 it will make sure the consunmer is present on this server. +func (js *jetStream) isConsumerHealthy(mset *stream, consumer string, ca *consumerAssignment) error { + js.mu.RLock() + if ca != nil && ca.unsupported != nil { + js.mu.RUnlock() + return nil + } + if mset == nil { + return errors.New("stream missing") + } + s, cc := js.srv, js.cluster + if cc == nil { + // Non-clustered mode + js.mu.RUnlock() + return nil + } + if ca == nil || ca.Group == nil { + js.mu.RUnlock() + return errors.New("consumer assignment or group missing") + } + if ca.deleted { + js.mu.RUnlock() + return nil // No further checks, consumer was deleted in the meantime. + } + created := ca.Created + node := ca.Group.node + js.mu.RUnlock() + + // Check if not running at all. + o := mset.lookupConsumer(consumer) + if o == nil { + if time.Since(created) < 5*time.Second { + // No further checks, consumer is not available yet but should be soon. + // We'll start erroring once we're sure this consumer is actually broken. + return nil + } + return errors.New("consumer not found") + } + + oNode := o.raftNode() + rc, _ := o.replica() + switch { + case rc <= 1: + return nil // No further checks for R=1 consumers + + case node == nil: + return errors.New("group node missing") + + case oNode == nil: + // Can happen when the consumer's node is not yet initialized. + return errors.New("consumer node missing") + + case node != oNode: + mset.mu.RLock() + accName, streamName := mset.acc.GetName(), mset.cfg.Name + mset.mu.RUnlock() + s.Warnf("Detected consumer cluster node skew '%s > %s > %s'", accName, streamName, consumer) + return errors.New("cluster node skew detected") + + case !o.isMonitorRunning(): + return errors.New("monitor goroutine not running") + + case !node.Healthy(): + return errors.New("group node unhealthy") + + default: + return nil + } +} + +// subjectsOverlap checks all existing stream assignments for the account cross-cluster for subject overlap +// Use only for clustered JetStream +// Read lock should be held. +func (jsc *jetStreamCluster) subjectsOverlap(acc string, subjects []string, osa *streamAssignment) bool { + asa := jsc.streams[acc] + for _, sa := range asa { + // can't overlap yourself, assume osa pre-checked for deep equal if passed + if osa != nil && sa == osa { + continue + } + for _, subj := range sa.Config.Subjects { + for _, tsubj := range subjects { + if SubjectsCollide(tsubj, subj) { + return true + } + } + } + } + return false +} + +func (a *Account) getJetStreamFromAccount() (*Server, *jetStream, *jsAccount) { + a.mu.RLock() + jsa := a.js + a.mu.RUnlock() + if jsa == nil { + return nil, nil, nil + } + jsa.mu.RLock() + js := jsa.js + jsa.mu.RUnlock() + if js == nil { + return nil, nil, nil + } + // Lock not needed, set on creation. + s := js.srv + return s, js, jsa +} + +func (s *Server) JetStreamIsStreamLeader(account, stream string) bool { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return false + } + js.mu.RLock() + defer js.mu.RUnlock() + return cc.isStreamLeader(account, stream) +} + +func (a *Account) JetStreamIsStreamLeader(stream string) bool { + s, js, jsa := a.getJetStreamFromAccount() + if s == nil || js == nil || jsa == nil { + return false + } + js.mu.RLock() + defer js.mu.RUnlock() + return js.cluster.isStreamLeader(a.Name, stream) +} + +func (s *Server) JetStreamIsStreamCurrent(account, stream string) bool { + js, cc := s.getJetStreamCluster() + if js == nil { + return false + } + js.mu.RLock() + defer js.mu.RUnlock() + return cc.isStreamCurrent(account, stream) +} + +func (a *Account) JetStreamIsConsumerLeader(stream, consumer string) bool { + s, js, jsa := a.getJetStreamFromAccount() + if s == nil || js == nil || jsa == nil { + return false + } + js.mu.RLock() + defer js.mu.RUnlock() + return js.cluster.isConsumerLeader(a.Name, stream, consumer) +} + +func (s *Server) JetStreamIsConsumerLeader(account, stream, consumer string) bool { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return false + } + js.mu.RLock() + defer js.mu.RUnlock() + return cc.isConsumerLeader(account, stream, consumer) +} + +func (s *Server) enableJetStreamClustering() error { + if !s.isRunning() { + return nil + } + js := s.getJetStream() + if js == nil { + return NewJSNotEnabledForAccountError() + } + // Already set. + if js.cluster != nil { + return nil + } + + s.Noticef("Starting JetStream cluster") + // We need to determine if we have a stable cluster name and expected number of servers. + s.Debugf("JetStream cluster checking for stable cluster name and peers") + + hasLeafNodeSystemShare := s.canExtendOtherDomain() + if s.isClusterNameDynamic() && !hasLeafNodeSystemShare { + return errors.New("JetStream cluster requires cluster name") + } + if s.configuredRoutes() == 0 && !hasLeafNodeSystemShare { + return errors.New("JetStream cluster requires configured routes or solicited leafnode for the system account") + } + + return js.setupMetaGroup() +} + +// isClustered returns if we are clustered. +// Lock should not be held. +func (js *jetStream) isClustered() bool { + // This is only ever set, no need for lock here. + return js.cluster != nil +} + +// isClusteredNoLock returns if we are clustered, but unlike isClustered() does +// not use the jetstream's lock, instead, uses an atomic operation. +// There are situations where some code wants to know if we are clustered but +// can't use js.isClustered() without causing a lock inversion. +func (js *jetStream) isClusteredNoLock() bool { + return atomic.LoadInt32(&js.clustered) == 1 +} + +func (js *jetStream) setupMetaGroup() error { + s := js.srv + s.Noticef("Creating JetStream metadata controller") + + // Setup our WAL for the metagroup. + sysAcc := s.SystemAccount() + if sysAcc == nil { + return ErrNoSysAccount + } + storeDir := filepath.Join(js.config.StoreDir, sysAcc.Name, defaultStoreDirName, defaultMetaGroupName) + + js.srv.optsMu.RLock() + syncAlways := js.srv.opts.SyncAlways + syncInterval := js.srv.opts.SyncInterval + js.srv.optsMu.RUnlock() + fs, err := newFileStoreWithCreated( + FileStoreConfig{StoreDir: storeDir, BlockSize: defaultMetaFSBlkSize, AsyncFlush: false, SyncAlways: syncAlways, SyncInterval: syncInterval, srv: s}, + StreamConfig{Name: defaultMetaGroupName, Storage: FileStorage}, + time.Now().UTC(), + s.jsKeyGen(s.getOpts().JetStreamKey, defaultMetaGroupName), + s.jsKeyGen(s.getOpts().JetStreamOldKey, defaultMetaGroupName), + ) + if err != nil { + s.Errorf("Error creating filestore: %v", err) + return err + } + + cfg := &RaftConfig{Name: defaultMetaGroupName, Store: storeDir, Log: fs} + + // If we are soliciting leafnode connections and we are sharing a system account and do not disable it with a hint, + // we want to move to observer mode so that we extend the solicited cluster or supercluster but do not form our own. + cfg.Observer = s.canExtendOtherDomain() && s.getOpts().JetStreamExtHint != jsNoExtend + + var bootstrap bool + if ps, err := readPeerState(storeDir); err != nil { + s.Noticef("JetStream cluster bootstrapping") + bootstrap = true + peers := s.ActivePeers() + s.Debugf("JetStream cluster initial peers: %+v", peers) + if err := s.bootstrapRaftNode(cfg, peers, false); err != nil { + return err + } + if cfg.Observer { + s.Noticef("Turning JetStream metadata controller Observer Mode on") + s.Noticef("In cases where the JetStream domain is not intended to be extended through a SYS account leaf node connection") + s.Noticef("and waiting for leader election until first contact is not acceptable,") + s.Noticef(`manually disable Observer Mode by setting the JetStream Option "extension_hint: %s"`, jsNoExtend) + } + } else { + s.Noticef("JetStream cluster recovering state") + // correlate the value of observer with observations from a previous run. + if cfg.Observer { + switch ps.domainExt { + case extExtended: + s.Noticef("Keeping JetStream metadata controller Observer Mode on - due to previous contact") + case extNotExtended: + s.Noticef("Turning JetStream metadata controller Observer Mode off - due to previous contact") + cfg.Observer = false + case extUndetermined: + s.Noticef("Turning JetStream metadata controller Observer Mode on - no previous contact") + s.Noticef("In cases where the JetStream domain is not intended to be extended through a SYS account leaf node connection") + s.Noticef("and waiting for leader election until first contact is not acceptable,") + s.Noticef(`manually disable Observer Mode by setting the JetStream Option "extension_hint: %s"`, jsNoExtend) + } + } else { + // To track possible configuration changes, responsible for an altered value of cfg.Observer, + // set extension state to undetermined. + ps.domainExt = extUndetermined + if err := writePeerState(storeDir, ps); err != nil { + return err + } + } + } + + // Start up our meta node. + n, err := s.startRaftNode(sysAcc.GetName(), cfg, pprofLabels{ + "type": "metaleader", + "account": sysAcc.Name, + }) + if err != nil { + s.Warnf("Could not start metadata controller: %v", err) + return err + } + + // If we are bootstrapped with no state, start campaign early. + if bootstrap { + n.Campaign() + } + + c := s.createInternalJetStreamClient() + + js.mu.Lock() + defer js.mu.Unlock() + js.cluster = &jetStreamCluster{ + meta: n, + streams: make(map[string]map[string]*streamAssignment), + s: s, + c: c, + qch: make(chan struct{}), + stopped: make(chan struct{}), + } + atomic.StoreInt32(&js.clustered, 1) + c.registerWithAccount(sysAcc) + + // Set to true before we start. + js.metaRecovering = true + js.srv.startGoRoutine( + js.monitorCluster, + pprofLabels{ + "type": "metaleader", + "account": sysAcc.Name, + }, + ) + return nil +} + +func (js *jetStream) getMetaGroup() RaftNode { + js.mu.RLock() + defer js.mu.RUnlock() + if js.cluster == nil { + return nil + } + return js.cluster.meta +} + +func (js *jetStream) server() *Server { + // Lock not needed, only set once on creation. + return js.srv +} + +// Will respond if we do not think we have a metacontroller leader. +func (js *jetStream) isLeaderless() bool { + js.mu.RLock() + cc := js.cluster + if cc == nil || cc.meta == nil { + js.mu.RUnlock() + return false + } + meta := cc.meta + js.mu.RUnlock() + + // If we don't have a leader. + // Make sure we have been running for enough time. + if meta.Leaderless() && time.Since(meta.Created()) > lostQuorumIntervalDefault { + return true + } + return false +} + +// Will respond iff we are a member and we know we have no leader. +func (js *jetStream) isGroupLeaderless(rg *raftGroup) bool { + if rg == nil || js == nil { + return false + } + js.mu.RLock() + cc := js.cluster + started := js.started + + // If we are not a member we can not say.. + if cc.meta == nil { + js.mu.RUnlock() + return false + } + if !rg.isMember(cc.meta.ID()) { + js.mu.RUnlock() + return false + } + // Single peer groups always have a leader if we are here. + if rg.node == nil { + js.mu.RUnlock() + return false + } + node := rg.node + js.mu.RUnlock() + // If we don't have a leader. + if node.Leaderless() { + // Threshold for jetstream startup. + const startupThreshold = 10 * time.Second + + if node.HadPreviousLeader() { + // Make sure we have been running long enough to intelligently determine this. + if time.Since(started) > startupThreshold { + return true + } + } + // Make sure we have been running for enough time. + if time.Since(node.Created()) > lostQuorumIntervalDefault { + return true + } + } + + return false +} + +func (s *Server) JetStreamIsStreamAssigned(account, stream string) bool { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return false + } + acc, _ := s.LookupAccount(account) + if acc == nil { + return false + } + js.mu.RLock() + assigned := cc.isStreamAssigned(acc, stream) + js.mu.RUnlock() + return assigned +} + +// streamAssigned informs us if this server has this stream assigned. +func (jsa *jsAccount) streamAssigned(stream string) bool { + jsa.mu.RLock() + js, acc := jsa.js, jsa.account + jsa.mu.RUnlock() + + if js == nil { + return false + } + js.mu.RLock() + assigned := js.cluster.isStreamAssigned(acc, stream) + js.mu.RUnlock() + return assigned +} + +// Read lock should be held. +func (cc *jetStreamCluster) isStreamAssigned(a *Account, stream string) bool { + // Non-clustered mode always return true. + if cc == nil { + return true + } + if cc.meta == nil { + return false + } + as := cc.streams[a.Name] + if as == nil { + return false + } + sa := as[stream] + if sa == nil { + return false + } + return sa.Group.isMember(cc.meta.ID()) +} + +// Read lock should be held. +func (cc *jetStreamCluster) isStreamLeader(account, stream string) bool { + // Non-clustered mode always return true. + if cc == nil { + return true + } + if cc.meta == nil { + return false + } + + var sa *streamAssignment + if as := cc.streams[account]; as != nil { + sa = as[stream] + } + if sa == nil { + return false + } + rg := sa.Group + if rg == nil { + return false + } + // Check if we are the leader of this raftGroup assigned to the stream. + ourID := cc.meta.ID() + for _, peer := range rg.Peers { + if peer == ourID { + if len(rg.Peers) == 1 || (rg.node != nil && rg.node.Leader()) { + return true + } + } + } + return false +} + +// Read lock should be held. +func (cc *jetStreamCluster) isConsumerLeader(account, stream, consumer string) bool { + // Non-clustered mode always return true. + if cc == nil { + return true + } + if cc.meta == nil { + return false + } + + var sa *streamAssignment + if as := cc.streams[account]; as != nil { + sa = as[stream] + } + if sa == nil { + return false + } + // Check if we are the leader of this raftGroup assigned to this consumer. + ca := sa.consumers[consumer] + if ca == nil { + return false + } + rg := ca.Group + ourID := cc.meta.ID() + for _, peer := range rg.Peers { + if peer == ourID { + if len(rg.Peers) == 1 || (rg.node != nil && rg.node.Leader()) { + return true + } + } + } + return false +} + +// Remove the stream `streamName` for the account `accName` from the inflight +// proposals map. This is done on success (processStreamAssignment) or on +// failure (processStreamAssignmentResults). +// (Write) Lock held on entry. +func (cc *jetStreamCluster) removeInflightProposal(accName, streamName string) { + streams, ok := cc.inflight[accName] + if !ok { + return + } + delete(streams, streamName) + if len(streams) == 0 { + delete(cc.inflight, accName) + } +} + +// Return the cluster quit chan. +func (js *jetStream) clusterQuitC() chan struct{} { + js.mu.RLock() + defer js.mu.RUnlock() + if js.cluster != nil { + return js.cluster.qch + } + return nil +} + +// Return the cluster stopped chan. +func (js *jetStream) clusterStoppedC() chan struct{} { + js.mu.RLock() + defer js.mu.RUnlock() + if js.cluster != nil { + return js.cluster.stopped + } + return nil +} + +// Mark that the meta layer is recovering. +func (js *jetStream) setMetaRecovering() { + js.mu.Lock() + defer js.mu.Unlock() + if js.cluster != nil { + // metaRecovering + js.metaRecovering = true + } +} + +// Mark that the meta layer is no longer recovering. +func (js *jetStream) clearMetaRecovering() { + js.mu.Lock() + defer js.mu.Unlock() + js.metaRecovering = false +} + +// Return whether the meta layer is recovering. +func (js *jetStream) isMetaRecovering() bool { + js.mu.RLock() + defer js.mu.RUnlock() + return js.metaRecovering +} + +// During recovery track any stream and consumer delete and update operations. +type recoveryUpdates struct { + removeStreams map[string]*streamAssignment + removeConsumers map[string]map[string]*consumerAssignment + addStreams map[string]*streamAssignment + updateStreams map[string]*streamAssignment + updateConsumers map[string]map[string]*consumerAssignment +} + +func (ru *recoveryUpdates) removeStream(sa *streamAssignment) { + key := sa.recoveryKey() + ru.removeStreams[key] = sa + delete(ru.addStreams, key) + delete(ru.updateStreams, key) + delete(ru.updateConsumers, key) + delete(ru.removeConsumers, key) +} + +func (ru *recoveryUpdates) addStream(sa *streamAssignment) { + key := sa.recoveryKey() + ru.addStreams[key] = sa + delete(ru.removeStreams, key) +} + +func (ru *recoveryUpdates) updateStream(sa *streamAssignment) { + key := sa.recoveryKey() + ru.updateStreams[key] = sa + delete(ru.addStreams, key) + delete(ru.removeStreams, key) +} + +func (ru *recoveryUpdates) removeConsumer(ca *consumerAssignment) { + key := ca.recoveryKey() + skey := ca.streamRecoveryKey() + if _, ok := ru.removeConsumers[skey]; !ok { + ru.removeConsumers[skey] = map[string]*consumerAssignment{} + } + ru.removeConsumers[skey][key] = ca + if consumers, ok := ru.updateConsumers[skey]; ok { + delete(consumers, key) + } +} + +func (ru *recoveryUpdates) addOrUpdateConsumer(ca *consumerAssignment) { + key := ca.recoveryKey() + skey := ca.streamRecoveryKey() + if consumers, ok := ru.removeConsumers[skey]; ok { + delete(consumers, key) + } + if _, ok := ru.updateConsumers[skey]; !ok { + ru.updateConsumers[skey] = map[string]*consumerAssignment{} + } + ru.updateConsumers[skey][key] = ca +} + +// Called after recovery of the cluster on startup to check for any orphans. +// Streams and consumers are recovered from disk, and the meta layer's mappings +// should clean them up, but under crash scenarios there could be orphans. +func (js *jetStream) checkForOrphans() { + // Can not hold jetstream lock while trying to delete streams or consumers. + js.mu.Lock() + s, cc := js.srv, js.cluster + s.Debugf("JetStream cluster checking for orphans") + + // We only want to cleanup any orphans if we know we are current with the meta-leader. + meta := cc.meta + if meta == nil || meta.Leaderless() { + js.mu.Unlock() + s.Debugf("JetStream cluster skipping check for orphans, no meta-leader") + return + } + if !meta.Healthy() { + js.mu.Unlock() + s.Debugf("JetStream cluster skipping check for orphans, not current with the meta-leader") + return + } + + var streams []*stream + var consumers []*consumer + + for accName, jsa := range js.accounts { + asa := cc.streams[accName] + jsa.mu.RLock() + for stream, mset := range jsa.streams { + if sa := asa[stream]; sa == nil { + streams = append(streams, mset) + } else { + // This one is good, check consumers now. + for _, o := range mset.getConsumers() { + if sa.consumers[o.String()] == nil { + consumers = append(consumers, o) + } + } + } + } + jsa.mu.RUnlock() + } + js.mu.Unlock() + + for _, mset := range streams { + mset.mu.RLock() + accName, stream := mset.acc.Name, mset.cfg.Name + mset.mu.RUnlock() + s.Warnf("Detected orphaned stream '%s > %s', will cleanup", accName, stream) + if err := mset.delete(); err != nil { + s.Warnf("Deleting stream encountered an error: %v", err) + } + } + for _, o := range consumers { + o.mu.RLock() + accName, mset, consumer := o.acc.Name, o.mset, o.name + o.mu.RUnlock() + stream := "N/A" + if mset != nil { + mset.mu.RLock() + stream = mset.cfg.Name + mset.mu.RUnlock() + } + if o.isDurable() { + s.Warnf("Detected orphaned durable consumer '%s > %s > %s', will cleanup", accName, stream, consumer) + } else { + s.Debugf("Detected orphaned consumer '%s > %s > %s', will cleanup", accName, stream, consumer) + } + + if err := o.delete(); err != nil { + s.Warnf("Deleting consumer encountered an error: %v", err) + } + } +} + +func (js *jetStream) monitorCluster() { + s, n := js.server(), js.getMetaGroup() + qch, stopped, rqch, lch, aq := js.clusterQuitC(), js.clusterStoppedC(), n.QuitC(), n.LeadChangeC(), n.ApplyQ() + + defer s.grWG.Done() + defer close(stopped) + + s.Debugf("Starting metadata monitor") + defer s.Debugf("Exiting metadata monitor") + + // Make sure to stop the raft group on exit to prevent accidental memory bloat. + defer n.Stop() + defer s.isMetaLeader.Store(false) + + const compactInterval = time.Minute + t := time.NewTicker(compactInterval) + defer t.Stop() + + // Used to check cold boot cluster when possibly in mixed mode. + const leaderCheckInterval = time.Second + lt := time.NewTicker(leaderCheckInterval) + defer lt.Stop() + + // Check the general health once an hour. + const healthCheckInterval = 1 * time.Hour + ht := time.NewTicker(healthCheckInterval) + defer ht.Stop() + + // Utility to check health. + checkHealth := func() { + if hs := s.healthz(nil); hs.Error != _EMPTY_ { + s.Warnf("%v", hs.Error) + } + } + + var ( + isLeader bool + lastSnapTime time.Time + compactSizeMin = uint64(8 * 1024 * 1024) // 8MB + minSnapDelta = 30 * time.Second + ) + + // Highwayhash key for generating hashes. + key := make([]byte, 32) + crand.Read(key) + + // Set to true to start. + js.setMetaRecovering() + + // Snapshotting function. + doSnapshot := func(force bool) { + // Suppress during recovery. + if js.isMetaRecovering() { + return + } + // Look up what the threshold is for compaction. Re-reading from config here as it is reloadable. + js.srv.optsMu.RLock() + ethresh := js.srv.opts.JetStreamMetaCompact + szthresh := js.srv.opts.JetStreamMetaCompactSize + js.srv.optsMu.RUnlock() + // Work out our criteria for snapshotting. + byEntries, bySize := ethresh > 0, szthresh > 0 + byNeither := !byEntries && !bySize + // For the meta layer we want to snapshot when over the above threshold (which could be 0 by default). + if ne, nsz := n.Size(); force || byNeither || (byEntries && ne > ethresh) || (bySize && nsz > szthresh) || n.NeedSnapshot() { + snap, err := js.metaSnapshot() + if err != nil { + s.Warnf("Error generating JetStream cluster snapshot: %v", err) + } else if err = n.InstallSnapshot(snap); err == nil { + lastSnapTime = time.Now() + } else if err != errNoSnapAvailable && err != errNodeClosed { + s.Warnf("Error snapshotting JetStream cluster state: %v", err) + } + } + } + + ru := &recoveryUpdates{ + removeStreams: make(map[string]*streamAssignment), + removeConsumers: make(map[string]map[string]*consumerAssignment), + addStreams: make(map[string]*streamAssignment), + updateStreams: make(map[string]*streamAssignment), + updateConsumers: make(map[string]map[string]*consumerAssignment), + } + + // Make sure to cancel any pending checkForOrphans calls if the + // monitor goroutine exits. + var oc *time.Timer + defer stopAndClearTimer(&oc) + + for { + select { + case <-s.quitCh: + // Server shutting down, but we might receive this before qch, so try to snapshot. + doSnapshot(false) + return + case <-rqch: + // Clean signal from shutdown routine so do best effort attempt to snapshot meta layer. + doSnapshot(false) + return + case <-qch: + // Clean signal from shutdown routine so do best effort attempt to snapshot meta layer. + doSnapshot(false) + return + case <-aq.ch: + ces := aq.pop() + for _, ce := range ces { + if ce == nil { + // Process any removes that are still valid after recovery. + for _, cas := range ru.removeConsumers { + for _, ca := range cas { + js.processConsumerRemoval(ca) + } + } + for _, sa := range ru.removeStreams { + js.processStreamRemoval(sa) + } + // Process stream additions. + for _, sa := range ru.addStreams { + js.processStreamAssignment(sa) + } + // Process pending updates. + for _, sa := range ru.updateStreams { + js.processUpdateStreamAssignment(sa) + } + // Now consumers. + for _, cas := range ru.updateConsumers { + for _, ca := range cas { + js.processConsumerAssignment(ca) + } + } + // Signals we have replayed all of our metadata. + js.clearMetaRecovering() + // Clear. + ru = nil + s.Debugf("Recovered JetStream cluster metadata") + // Snapshot now so we start with freshly compacted log. + doSnapshot(true) + oc = time.AfterFunc(30*time.Second, js.checkForOrphans) + // Do a health check here as well. + go checkHealth() + continue + } + if didSnap, err := js.applyMetaEntries(ce.Entries, ru); err == nil { + var nb uint64 + // Some entries can fail without an error when shutting down, don't move applied forward. + if !js.isShuttingDown() { + _, nb = n.Applied(ce.Index) + } + if js.hasPeerEntries(ce.Entries) || (didSnap && !isLeader) { + doSnapshot(true) + } else if nb > compactSizeMin && time.Since(lastSnapTime) > minSnapDelta { + doSnapshot(false) + } + } else { + s.Warnf("Error applying JetStream cluster entries: %v", err) + } + ce.ReturnToPool() + } + aq.recycle(&ces) + + case isLeader = <-lch: + // Process the change. + js.processLeaderChange(isLeader) + if isLeader { + s.sendInternalMsgLocked(serverStatsPingReqSubj, _EMPTY_, nil, nil) + // Install a snapshot as we become leader. + js.checkClusterSize() + doSnapshot(false) + } + + case <-t.C: + doSnapshot(false) + // Periodically check the cluster size. + if n.Leader() { + js.checkClusterSize() + } + case <-ht.C: + // Do this in a separate go routine. + go checkHealth() + + case <-lt.C: + s.Debugf("Checking JetStream cluster state") + // If we have a current leader or had one in the past we can cancel this here since the metaleader + // will be in charge of all peer state changes. + // For cold boot only. + if !n.Leaderless() || n.HadPreviousLeader() { + lt.Stop() + continue + } + // If we are here we do not have a leader and we did not have a previous one, so cold start. + // Check to see if we can adjust our cluster size down iff we are in mixed mode and we have + // seen a total that is what our original estimate was. + cs := n.ClusterSize() + if js, total := s.trackedJetStreamServers(); js < total && total >= cs && js != cs { + s.Noticef("Adjusting JetStream expected peer set size to %d from original %d", js, cs) + n.AdjustBootClusterSize(js) + } + } + } +} + +// This is called on first leader transition to double check the peers and cluster set size. +func (js *jetStream) checkClusterSize() { + s, n := js.server(), js.getMetaGroup() + if n == nil { + return + } + // We will check that we have a correct cluster set size by checking for any non-js servers + // which can happen in mixed mode. + ps := n.(*raft).currentPeerState() + if len(ps.knownPeers) >= ps.clusterSize { + return + } + + // Grab our active peers. + peers := s.ActivePeers() + + // If we have not registered all of our peers yet we can't do + // any adjustments based on a mixed mode. We will periodically check back. + if len(peers) < ps.clusterSize { + return + } + + s.Debugf("Checking JetStream cluster size") + + // If we are here our known set as the leader is not the same as the cluster size. + // Check to see if we have a mixed mode setup. + var totalJS int + for _, p := range peers { + if si, ok := s.nodeToInfo.Load(p); ok && si != nil { + if si.(nodeInfo).js { + totalJS++ + } + } + } + // If we have less then our cluster size adjust that here. Can not do individual peer removals since + // they will not be in the tracked peers. + if totalJS < ps.clusterSize { + s.Debugf("Adjusting JetStream cluster size from %d to %d", ps.clusterSize, totalJS) + if err := n.AdjustClusterSize(totalJS); err != nil { + s.Warnf("Error adjusting JetStream cluster size: %v", err) + } + } +} + +// Represents our stable meta state that we can write out. +type writeableStreamAssignment struct { + Client *ClientInfo `json:"client,omitempty"` + Created time.Time `json:"created"` + ConfigJSON json.RawMessage `json:"stream"` + Group *raftGroup `json:"group"` + Sync string `json:"sync"` + Consumers []*writeableConsumerAssignment +} + +func (js *jetStream) clusterStreamConfig(accName, streamName string) (StreamConfig, bool) { + js.mu.RLock() + defer js.mu.RUnlock() + if sa, ok := js.cluster.streams[accName][streamName]; ok { + return *sa.Config, true + } + return StreamConfig{}, false +} + +func (js *jetStream) metaSnapshot() ([]byte, error) { + start := time.Now() + js.mu.RLock() + s := js.srv + cc := js.cluster + nsa := 0 + nca := 0 + for _, asa := range cc.streams { + nsa += len(asa) + } + streams := make([]writeableStreamAssignment, 0, nsa) + for _, asa := range cc.streams { + for _, sa := range asa { + wsa := writeableStreamAssignment{ + Client: sa.Client.forAssignmentSnap(), + Created: sa.Created, + ConfigJSON: sa.ConfigJSON, + Group: sa.Group, + Sync: sa.Sync, + Consumers: make([]*writeableConsumerAssignment, 0, len(sa.consumers)), + } + for _, ca := range sa.consumers { + // Skip if the consumer is pending, we can't include it in our snapshot. + // If the proposal fails after we marked it pending, it would result in a ghost consumer. + if ca.pending { + continue + } + wca := writeableConsumerAssignment{ + Client: ca.Client.forAssignmentSnap(), + Created: ca.Created, + Name: ca.Name, + Stream: ca.Stream, + ConfigJSON: ca.ConfigJSON, + Group: ca.Group, + State: ca.State, + } + wsa.Consumers = append(wsa.Consumers, &wca) + nca++ + } + streams = append(streams, wsa) + } + } + + if len(streams) == 0 { + js.mu.RUnlock() + return nil, nil + } + + // Track how long it took to marshal the JSON + mstart := time.Now() + b, err := json.Marshal(streams) + mend := time.Since(mstart) + + js.mu.RUnlock() + + // Must not be possible for a JSON marshaling error to result + // in an empty snapshot. + if err != nil { + return nil, err + } + + // Track how long it took to compress the JSON. + cstart := time.Now() + snap := s2.Encode(nil, b) + cend := time.Since(cstart) + took := time.Since(start) + + if took > time.Second { + s.rateLimitFormatWarnf("Metalayer snapshot took %.3fs (streams: %d, consumers: %d, marshal: %.3fs, s2: %.3fs, uncompressed: %d, compressed: %d)", + took.Seconds(), nsa, nca, mend.Seconds(), cend.Seconds(), len(b), len(snap)) + } + + // Track in jsz monitoring as well. + if cc != nil { + atomic.StoreInt64(&cc.lastMetaSnapTime, start.UnixNano()) + atomic.StoreInt64(&cc.lastMetaSnapDuration, int64(took)) + } + + return snap, nil +} + +func (js *jetStream) applyMetaSnapshot(buf []byte, ru *recoveryUpdates, isRecovering bool) error { + var wsas []writeableStreamAssignment + if len(buf) > 0 { + jse, err := s2.Decode(nil, buf) + if err != nil { + return err + } + if err = json.Unmarshal(jse, &wsas); err != nil { + return err + } + } + + // Build our new version here outside of js. + streams := make(map[string]map[string]*streamAssignment) + for _, wsa := range wsas { + as := streams[wsa.Client.serviceAccount()] + if as == nil { + as = make(map[string]*streamAssignment) + streams[wsa.Client.serviceAccount()] = as + } + sa := &streamAssignment{Client: wsa.Client, Created: wsa.Created, ConfigJSON: wsa.ConfigJSON, Group: wsa.Group, Sync: wsa.Sync} + decodeStreamAssignmentConfig(js.srv, sa) + if len(wsa.Consumers) > 0 { + sa.consumers = make(map[string]*consumerAssignment) + for _, wca := range wsa.Consumers { + if wca.Stream == _EMPTY_ { + wca.Stream = sa.Config.Name // Rehydrate from the stream name. + } + ca := &consumerAssignment{Client: wca.Client, Created: wca.Created, Name: wca.Name, Stream: wca.Stream, ConfigJSON: wca.ConfigJSON, Group: wca.Group, State: wca.State} + decodeConsumerAssignmentConfig(ca) + sa.consumers[ca.Name] = ca + } + } + as[sa.Config.Name] = sa + } + + js.mu.Lock() + cc := js.cluster + + var saAdd, saDel, saChk []*streamAssignment + // Walk through the old list to generate the delete list. + for account, asa := range cc.streams { + nasa := streams[account] + for sn, sa := range asa { + if nsa := nasa[sn]; nsa == nil { + saDel = append(saDel, sa) + } else { + saChk = append(saChk, nsa) + } + } + } + // Walk through the new list to generate the add list. + for account, nasa := range streams { + asa := cc.streams[account] + for sn, sa := range nasa { + if asa[sn] == nil { + saAdd = append(saAdd, sa) + } + } + } + + // Now walk the ones to check and process consumers. + var caAdd, caDel []*consumerAssignment + for _, sa := range saChk { + // Make sure to add in all the new ones from sa. + for _, ca := range sa.consumers { + caAdd = append(caAdd, ca) + } + if osa := js.streamAssignment(sa.Client.serviceAccount(), sa.Config.Name); osa != nil { + for _, ca := range osa.consumers { + // Consumer was either removed, or recreated with a different raft group. + if nca := sa.consumers[ca.Name]; nca == nil { + caDel = append(caDel, ca) + } else if nca.Group != nil && ca.Group != nil && nca.Group.Name != ca.Group.Name { + caDel = append(caDel, ca) + } + } + } + } + js.mu.Unlock() + + // Do removals first. + for _, sa := range saDel { + js.setStreamAssignmentRecovering(sa) + if isRecovering { + ru.removeStream(sa) + } else { + js.processStreamRemoval(sa) + } + } + // Now do add for the streams. Also add in all consumers. + for _, sa := range saAdd { + consumers := sa.consumers + js.setStreamAssignmentRecovering(sa) + if isRecovering { + // Since we're recovering and storing up changes, we'll need to clear out these consumers. + // Some might be removed, and we'll recover those later, must not be able to remember them. + sa.consumers = nil + ru.addStream(sa) + } else { + js.processStreamAssignment(sa) + } + + // We can simply process the consumers. + for _, ca := range consumers { + js.setConsumerAssignmentRecovering(ca) + if isRecovering { + ru.addOrUpdateConsumer(ca) + } else { + js.processConsumerAssignment(ca) + } + } + } + + // Perform updates on those in saChk. These were existing so make + // sure to process any changes. + for _, sa := range saChk { + js.setStreamAssignmentRecovering(sa) + if isRecovering { + ru.updateStream(sa) + } else { + js.processUpdateStreamAssignment(sa) + } + } + + // Now do the deltas for existing stream's consumers. + for _, ca := range caDel { + js.setConsumerAssignmentRecovering(ca) + if isRecovering { + ru.removeConsumer(ca) + } else { + js.processConsumerRemoval(ca) + } + } + for _, ca := range caAdd { + js.setConsumerAssignmentRecovering(ca) + if isRecovering { + ru.addOrUpdateConsumer(ca) + } else { + js.processConsumerAssignment(ca) + } + } + + return nil +} + +// Called on recovery to make sure we do not process like original. +func (js *jetStream) setStreamAssignmentRecovering(sa *streamAssignment) { + js.mu.Lock() + defer js.mu.Unlock() + sa.responded = true + sa.recovering = true + sa.Restore = nil + if sa.Group != nil { + sa.Group.Preferred = _EMPTY_ + } +} + +// Called on recovery to make sure we do not process like original. +func (js *jetStream) setConsumerAssignmentRecovering(ca *consumerAssignment) { + js.mu.Lock() + defer js.mu.Unlock() + ca.responded = true + ca.recovering = true + if ca.Group != nil { + ca.Group.Preferred = _EMPTY_ + } +} + +// Just copies over and changes out the group so it can be encoded. +// Lock should be held. +func (sa *streamAssignment) copyGroup() *streamAssignment { + csa, cg := *sa, *sa.Group + csa.Group = &cg + csa.Group.Peers = copyStrings(sa.Group.Peers) + return &csa +} + +// Just copies over and changes out the group so it can be encoded. +// Lock should be held. +func (ca *consumerAssignment) copyGroup() *consumerAssignment { + cca, cg := *ca, *ca.Group + cca.Group = &cg + cca.Group.Peers = copyStrings(ca.Group.Peers) + return &cca +} + +// Lock should be held. +func (sa *streamAssignment) missingPeers() bool { + return len(sa.Group.Peers) < sa.Config.Replicas +} + +// Called when we detect a new peer. Only the leader will process checking +// for any streams, and consequently any consumers. +func (js *jetStream) processAddPeer(peer string) { + js.mu.Lock() + defer js.mu.Unlock() + + s, cc := js.srv, js.cluster + if cc == nil || cc.meta == nil { + return + } + isLeader := cc.isLeader() + + // Now check if we are meta-leader. We will check for any re-assignments. + if !isLeader { + return + } + + sir, ok := s.nodeToInfo.Load(peer) + if !ok || sir == nil { + return + } + si := sir.(nodeInfo) + + for _, asa := range cc.streams { + for _, sa := range asa { + if sa.unsupported != nil { + continue + } + if sa.missingPeers() { + // Make sure the right cluster etc. + if si.cluster != sa.Client.Cluster { + continue + } + // If we are here we can add in this peer. + csa := sa.copyGroup() + csa.Group.Peers = append(csa.Group.Peers, peer) + // Send our proposal for this csa. Also use same group definition for all the consumers as well. + cc.meta.Propose(encodeAddStreamAssignment(csa)) + for _, ca := range sa.consumers { + if ca.unsupported != nil { + continue + } + // Ephemerals are R=1, so only auto-remap durables, or R>1. + if ca.Config.Durable != _EMPTY_ || len(ca.Group.Peers) > 1 { + cca := ca.copyGroup() + cca.Group.Peers = csa.Group.Peers + cc.meta.Propose(encodeAddConsumerAssignment(cca)) + } + } + } + } + } +} + +func (js *jetStream) processRemovePeer(peer string) { + // We may be already disabled. + if js == nil || js.disabled.Load() { + return + } + + js.mu.Lock() + s, cc := js.srv, js.cluster + if cc == nil || cc.meta == nil { + js.mu.Unlock() + return + } + isLeader := cc.isLeader() + // All nodes will check if this is them. + isUs := cc.meta.ID() == peer + js.mu.Unlock() + + if isUs { + s.Errorf("JetStream being DISABLED, our server was removed from the cluster") + adv := &JSServerRemovedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSServerRemovedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Server: s.Name(), + ServerID: s.ID(), + Cluster: s.cachedClusterName(), + Domain: s.getOpts().JetStreamDomain, + } + s.publishAdvisory(nil, JSAdvisoryServerRemoved, adv) + + go s.DisableJetStream() + } + + // Now check if we are meta-leader. We will attempt re-assignment. + if !isLeader { + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + for _, asa := range cc.streams { + for _, sa := range asa { + if sa.unsupported != nil { + continue + } + if rg := sa.Group; rg.isMember(peer) { + js.removePeerFromStreamLocked(sa, peer) + } + } + } +} + +// Assumes all checks have already been done. +func (js *jetStream) removePeerFromStream(sa *streamAssignment, peer string) bool { + js.mu.Lock() + defer js.mu.Unlock() + return js.removePeerFromStreamLocked(sa, peer) +} + +// Lock should be held. +func (js *jetStream) removePeerFromStreamLocked(sa *streamAssignment, peer string) bool { + if rg := sa.Group; !rg.isMember(peer) { + return false + } + + s, cc, csa := js.srv, js.cluster, sa.copyGroup() + if cc == nil || cc.meta == nil { + return false + } + replaced := cc.remapStreamAssignment(csa, peer) + if !replaced { + s.Warnf("JetStream cluster could not replace peer for stream '%s > %s'", sa.Client.serviceAccount(), sa.Config.Name) + } + + // Send our proposal for this csa. Also use same group definition for all the consumers as well. + cc.meta.Propose(encodeAddStreamAssignment(csa)) + rg := csa.Group + for _, ca := range sa.consumers { + if ca.unsupported != nil { + continue + } + // Ephemerals are R=1, so only auto-remap durables, or R>1. + if ca.Config.Durable != _EMPTY_ { + cca := ca.copyGroup() + cca.Group.Peers, cca.Group.Preferred = rg.Peers, _EMPTY_ + cc.meta.Propose(encodeAddConsumerAssignment(cca)) + } else if ca.Group.isMember(peer) { + // These are ephemerals. Check to see if we deleted this peer. + cc.meta.Propose(encodeDeleteConsumerAssignment(ca)) + } + } + return replaced +} + +// Check if we have peer related entries. +func (js *jetStream) hasPeerEntries(entries []*Entry) bool { + for _, e := range entries { + if e.Type == EntryRemovePeer || e.Type == EntryAddPeer { + return true + } + } + return false +} + +const ksep = ":" + +func (sa *streamAssignment) recoveryKey() string { + if sa == nil { + return _EMPTY_ + } + return sa.Client.serviceAccount() + ksep + sa.Config.Name +} + +func (ca *consumerAssignment) streamRecoveryKey() string { + if ca == nil { + return _EMPTY_ + } + return ca.Client.serviceAccount() + ksep + ca.Stream +} + +func (ca *consumerAssignment) recoveryKey() string { + if ca == nil { + return _EMPTY_ + } + return ca.Client.serviceAccount() + ksep + ca.Stream + ksep + ca.Name +} + +func (js *jetStream) applyMetaEntries(entries []*Entry, ru *recoveryUpdates) (bool, error) { + var didSnap bool + isRecovering := js.isMetaRecovering() + + for _, e := range entries { + if e.Type == EntrySnapshot { + js.applyMetaSnapshot(e.Data, ru, isRecovering) + didSnap = true + } else if e.Type == EntryRemovePeer { + if !js.isMetaRecovering() { + peer := string(e.Data) + js.processRemovePeer(peer) + + // The meta leader can now respond to the peer-removal, + // since a quorum of nodes has this in their log. + s := js.srv + if s.JetStreamIsLeader() { + var ( + info peerRemoveInfo + ok bool + ) + js.mu.Lock() + if cc := js.cluster; cc != nil && cc.peerRemoveReply != nil { + if info, ok = cc.peerRemoveReply[peer]; ok { + delete(cc.peerRemoveReply, peer) + } + if len(cc.peerRemoveReply) == 0 { + cc.peerRemoveReply = nil + } + } + js.mu.Unlock() + + if info.reply != _EMPTY_ { + sysAcc := s.SystemAccount() + var resp = JSApiMetaServerRemoveResponse{ApiResponse: ApiResponse{Type: JSApiMetaServerRemoveResponseType}} + resp.Success = true + s.sendAPIResponse(info.ci, sysAcc, info.subject, info.reply, info.request, s.jsonResponse(&resp)) + } + } + } + } else if e.Type == EntryAddPeer { + if !isRecovering { + js.processAddPeer(string(e.Data)) + } + } else { + buf := e.Data + switch entryOp(buf[0]) { + case assignStreamOp: + sa, err := decodeStreamAssignment(js.srv, buf[1:]) + if err != nil { + js.srv.Errorf("JetStream cluster failed to decode stream assignment: %q", buf[1:]) + return didSnap, err + } + if isRecovering { + js.setStreamAssignmentRecovering(sa) + ru.addStream(sa) + } else { + js.processStreamAssignment(sa) + } + case removeStreamOp: + sa, err := decodeStreamAssignment(js.srv, buf[1:]) + if err != nil { + js.srv.Errorf("JetStream cluster failed to decode stream assignment: %q", buf[1:]) + return didSnap, err + } + if isRecovering { + js.setStreamAssignmentRecovering(sa) + ru.removeStream(sa) + } else { + js.processStreamRemoval(sa) + } + case assignConsumerOp: + ca, err := decodeConsumerAssignment(buf[1:]) + if err != nil { + js.srv.Errorf("JetStream cluster failed to decode consumer assignment: %q", buf[1:]) + return didSnap, err + } + if isRecovering { + js.setConsumerAssignmentRecovering(ca) + ru.addOrUpdateConsumer(ca) + } else { + js.processConsumerAssignment(ca) + } + case assignCompressedConsumerOp: + ca, err := decodeConsumerAssignmentCompressed(buf[1:]) + if err != nil { + js.srv.Errorf("JetStream cluster failed to decode compressed consumer assignment: %q", buf[1:]) + return didSnap, err + } + if isRecovering { + js.setConsumerAssignmentRecovering(ca) + key := ca.recoveryKey() + skey := ca.streamRecoveryKey() + if consumers, ok := ru.removeConsumers[skey]; ok { + delete(consumers, key) + } + if _, ok := ru.updateConsumers[skey]; !ok { + ru.updateConsumers[skey] = map[string]*consumerAssignment{} + } + ru.updateConsumers[skey][key] = ca + } else { + js.processConsumerAssignment(ca) + } + case removeConsumerOp: + ca, err := decodeConsumerAssignment(buf[1:]) + if err != nil { + js.srv.Errorf("JetStream cluster failed to decode consumer assignment: %q", buf[1:]) + return didSnap, err + } + if isRecovering { + js.setConsumerAssignmentRecovering(ca) + ru.removeConsumer(ca) + } else { + js.processConsumerRemoval(ca) + } + case updateStreamOp: + sa, err := decodeStreamAssignment(js.srv, buf[1:]) + if err != nil { + js.srv.Errorf("JetStream cluster failed to decode stream assignment: %q", buf[1:]) + return didSnap, err + } + if isRecovering { + js.setStreamAssignmentRecovering(sa) + ru.updateStream(sa) + } else { + js.processUpdateStreamAssignment(sa) + } + default: + panic(fmt.Sprintf("JetStream Cluster Unknown meta entry op type: %v", entryOp(buf[0]))) + } + } + } + return didSnap, nil +} + +func (rg *raftGroup) isMember(id string) bool { + if rg == nil { + return false + } + for _, peer := range rg.Peers { + if peer == id { + return true + } + } + return false +} + +func (rg *raftGroup) setPreferred() { + if rg == nil || len(rg.Peers) == 0 { + return + } + if len(rg.Peers) == 1 { + rg.Preferred = rg.Peers[0] + } else { + // For now just randomly select a peer for the preferred. + pi := rand.Int31n(int32(len(rg.Peers))) + rg.Preferred = rg.Peers[pi] + } +} + +// createRaftGroup is called to spin up this raft group if needed. +func (js *jetStream) createRaftGroup(accName string, rg *raftGroup, storage StorageType, labels pprofLabels) (RaftNode, error) { + // Must hold JS lock throughout, otherwise two parallel calls for the same raft group could result + // in duplicate instances for the same identifier, if the current Raft node is shutting down. + // We can release the lock temporarily while waiting for the Raft node to shut down. + js.mu.Lock() + defer js.mu.Unlock() + + s, cc := js.srv, js.cluster + if cc == nil || cc.meta == nil { + return nil, NewJSClusterNotActiveError() + } + + // If this is a single peer raft group or we are not a member return. + if len(rg.Peers) <= 1 || !rg.isMember(cc.meta.ID()) { + // Nothing to do here. + return nil, nil + } + + // Check if we already have this assigned. +retry: + if node := s.lookupRaftNode(rg.Name); node != nil { + if node.State() == Closed { + // We're waiting for this node to finish shutting down before we replace it. + js.mu.Unlock() + node.WaitForStop() + js.mu.Lock() + goto retry + } + s.Debugf("JetStream cluster already has raft group %q assigned", rg.Name) + // Check and see if the group has the same peers. If not then we + // will update the known peers, which will send a peerstate if leader. + groupPeerIDs := append([]string{}, rg.Peers...) + var samePeers bool + if nodePeers := node.Peers(); len(rg.Peers) == len(nodePeers) { + nodePeerIDs := make([]string, 0, len(nodePeers)) + for _, n := range nodePeers { + nodePeerIDs = append(nodePeerIDs, n.ID) + } + slices.Sort(groupPeerIDs) + slices.Sort(nodePeerIDs) + samePeers = slices.Equal(groupPeerIDs, nodePeerIDs) + } + if !samePeers { + // At this point we have no way of knowing: + // 1. Whether the group has lost enough nodes to cause a quorum + // loss, in which case a proposal may fail, therefore we will + // force a peerstate write; + // 2. Whether nodes in the group have other applies queued up + // that could change the peerstate again, therefore the leader + // should send out a new proposal anyway too just to make sure + // that this change gets captured in the log. + node.UpdateKnownPeers(groupPeerIDs) + + // If the peers changed as a result of an update by the meta layer, we must reflect that in the log of + // this group. Otherwise, a new peer would come up and instantly reset the peer state back to whatever is + // in the log at that time, overwriting what the meta layer told it. + // Will need to address this properly later on, by for example having the meta layer decide the new + // placement, but have the leader of this group propose it through its own log instead. + if node.Leader() { + node.ProposeKnownPeers(groupPeerIDs) + } + } + rg.node = node + return node, nil + } + + s.Debugf("JetStream cluster creating raft group:%+v", rg) + + sysAcc := s.SystemAccount() + if sysAcc == nil { + s.Debugf("JetStream cluster detected shutdown processing raft group: %+v", rg) + return nil, errors.New("shutting down") + } + + // Check here to see if we have a max HA Assets limit set. + if maxHaAssets := s.getOpts().JetStreamLimits.MaxHAAssets; maxHaAssets > 0 { + if s.numRaftNodes() > maxHaAssets { + s.Warnf("Maximum HA Assets limit reached: %d", maxHaAssets) + // Since the meta leader assigned this, send a statsz update to them to get them up to date. + go s.sendStatszUpdate() + return nil, errors.New("system limit reached") + } + } + + storeDir := filepath.Join(js.config.StoreDir, sysAcc.Name, defaultStoreDirName, rg.Name) + var store StreamStore + if storage == FileStorage { + // If the server is set to sync always, do the same for the Raft log. + js.srv.optsMu.RLock() + syncAlways := js.srv.opts.SyncAlways + syncInterval := js.srv.opts.SyncInterval + js.srv.optsMu.RUnlock() + fs, err := newFileStoreWithCreated( + FileStoreConfig{StoreDir: storeDir, BlockSize: defaultMediumBlockSize, AsyncFlush: false, SyncAlways: syncAlways, SyncInterval: syncInterval, srv: s}, + StreamConfig{Name: rg.Name, Storage: FileStorage, Metadata: labels}, + time.Now().UTC(), + s.jsKeyGen(s.getOpts().JetStreamKey, rg.Name), + s.jsKeyGen(s.getOpts().JetStreamOldKey, rg.Name), + ) + if err != nil { + s.Errorf("Error creating filestore WAL: %v", err) + return nil, err + } + store = fs + } else { + ms, err := newMemStore(&StreamConfig{Name: rg.Name, Storage: MemoryStorage}) + if err != nil { + s.Errorf("Error creating memstore WAL: %v", err) + return nil, err + } + store = ms + } + + cfg := &RaftConfig{Name: rg.Name, Store: storeDir, Log: store, Track: true} + + if _, err := readPeerState(storeDir); err != nil { + s.bootstrapRaftNode(cfg, rg.Peers, true) + } + + n, err := s.startRaftNode(accName, cfg, labels) + if err != nil || n == nil { + s.Debugf("Error creating raft group: %v", err) + return nil, err + } + // Need JS lock to be held for the assignment to avoid data-race reports + rg.node = n + // See if we are preferred and should start campaign immediately. + if n.ID() == rg.Preferred && n.Term() == 0 { + n.CampaignImmediately() + } + return n, nil +} + +func (mset *stream) raftGroup() *raftGroup { + if mset == nil { + return nil + } + mset.mu.RLock() + defer mset.mu.RUnlock() + if mset.sa == nil { + return nil + } + return mset.sa.Group +} + +func (mset *stream) raftNode() RaftNode { + if mset == nil { + return nil + } + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.node +} + +func (mset *stream) removeNode() { + mset.mu.Lock() + defer mset.mu.Unlock() + if n := mset.node; n != nil { + n.Delete() + mset.node = nil + } +} + +// Helper function to generate peer info. +// lists and sets for old and new. +func genPeerInfo(peers []string, split int) (newPeers, oldPeers []string, newPeerSet, oldPeerSet map[string]bool) { + newPeers = peers[split:] + oldPeers = peers[:split] + newPeerSet = make(map[string]bool, len(newPeers)) + oldPeerSet = make(map[string]bool, len(oldPeers)) + for i, peer := range peers { + if i < split { + oldPeerSet[peer] = true + } else { + newPeerSet[peer] = true + } + } + return +} + +// This will wait for a period of time until all consumers are registered and have +// their consumer assignments assigned. +// Should only be called from monitorStream. +func (mset *stream) waitOnConsumerAssignments() { + mset.mu.RLock() + s, js, acc, sa, name, replicas := mset.srv, mset.js, mset.acc, mset.sa, mset.cfg.Name, mset.cfg.Replicas + mset.mu.RUnlock() + + if s == nil || js == nil || acc == nil || sa == nil { + return + } + + js.mu.RLock() + numExpectedConsumers := len(sa.consumers) + js.mu.RUnlock() + + // Max to wait. + const maxWaitTime = 10 * time.Second + const sleepTime = 500 * time.Millisecond + + // Wait up to 10s + timeout := time.Now().Add(maxWaitTime) + for time.Now().Before(timeout) { + var numReady int + for _, o := range mset.getConsumers() { + // Make sure we are registered with our consumer assignment. + if ca := o.consumerAssignment(); ca != nil { + if replicas > 1 && !o.isMonitorRunning() { + break + } + numReady++ + } else { + break + } + } + // Check if we are good. + if numReady >= numExpectedConsumers { + break + } + + s.Debugf("Waiting for consumers for interest based stream '%s > %s'", acc.Name, name) + select { + case <-s.quitCh: + return + case <-mset.monitorQuitC(): + return + case <-time.After(sleepTime): + } + } + + if actual := mset.numConsumers(); actual < numExpectedConsumers { + s.Warnf("All consumers not online for '%s > %s': expected %d but only have %d", acc.Name, name, numExpectedConsumers, actual) + } +} + +// Monitor our stream node for this stream. +func (js *jetStream) monitorStream(mset *stream, sa *streamAssignment, sendSnapshot bool) { + s, cc := js.server(), js.cluster + defer s.grWG.Done() + if mset != nil { + defer mset.monitorWg.Done() + } + js.mu.RLock() + n := sa.Group.node + meta := cc.meta + js.mu.RUnlock() + + if n == nil || meta == nil { + s.Warnf("No RAFT group for '%s > %s'", sa.Client.serviceAccount(), sa.Config.Name) + return + } + + // Make sure only one is running. + if mset != nil { + if mset.checkInMonitor() { + return + } + defer mset.clearMonitorRunning() + } + + // Make sure to stop the raft group on exit to prevent accidental memory bloat. + // This should be below the checkInMonitor call though to avoid stopping it out + // from underneath the one that is running since it will be the same raft node. + defer func() { + // We might be closing during shutdown, don't pre-emptively stop here since we'll still want to install snapshots. + if mset != nil && !mset.closed.Load() { + n.Stop() + } + }() + + qch, mqch, lch, aq, uch, ourPeerId := n.QuitC(), mset.monitorQuitC(), n.LeadChangeC(), n.ApplyQ(), mset.updateC(), meta.ID() + + s.Debugf("Starting stream monitor for '%s > %s' [%s]", sa.Client.serviceAccount(), sa.Config.Name, n.Group()) + defer s.Debugf("Exiting stream monitor for '%s > %s' [%s]", sa.Client.serviceAccount(), sa.Config.Name, n.Group()) + + // Make sure we do not leave the apply channel to fill up and block the raft layer. + defer func() { + if n.State() == Closed { + return + } + n.StepDown() + // Drain the commit queue... + aq.drain() + }() + + const ( + compactInterval = 2 * time.Minute + compactSizeMin = 8 * 1024 * 1024 + compactNumMin = 65536 + ) + + // Spread these out for large numbers on server restart. + rci := time.Duration(rand.Int63n(int64(time.Minute))) + t := time.NewTicker(compactInterval + rci) + defer t.Stop() + + js.mu.RLock() + isLeader := cc.isStreamLeader(sa.Client.serviceAccount(), sa.Config.Name) + isRestore := sa.Restore != nil + js.mu.RUnlock() + + acc, err := s.LookupAccount(sa.Client.serviceAccount()) + if err != nil { + s.Warnf("Could not retrieve account for stream '%s > %s'", sa.Client.serviceAccount(), sa.Config.Name) + return + } + accName := acc.GetName() + + // Used to represent how we can detect a changed state quickly and without representing + // a complete and detailed state which could be costly in terms of memory, cpu and GC. + // This only entails how many messages, and the first and last sequence of the stream. + // This is all that is needed to detect a change, and we can get this from FilteredState() + // with an empty filter. + var lastState SimpleState + + // Don't allow the upper layer to install snapshots until we have + // fully recovered from disk. + isRecovering := true + + doSnapshot := func() { + if mset == nil || isRecovering || isRestore { + return + } + + // Before we actually calculate the detailed state and encode it, let's check the + // simple state to detect any changes. + curState := mset.store.FilteredState(0, _EMPTY_) + + // If the state hasn't changed but the log has gone way over + // the compaction size then we will want to compact anyway. + // This shouldn't happen for streams like it can for pull + // consumers on idle streams but better to be safe than sorry! + ne, nb := n.Size() + if curState == lastState && ne < compactNumMin && nb < compactSizeMin { + return + } + + if err := n.InstallSnapshot(mset.stateSnapshot()); err == nil { + lastState = curState + } else if err != errNoSnapAvailable && err != errNodeClosed && err != errCatchupsRunning { + s.RateLimitWarnf("Failed to install snapshot for '%s > %s' [%s]: %v", mset.acc.Name, mset.name(), n.Group(), err) + } + } + + // We will establish a restoreDoneCh no matter what. Will never be triggered unless + // we replace with the restore chan. + restoreDoneCh := make(<-chan error) + + // For migration tracking. + var mmt *time.Ticker + var mmtc <-chan time.Time + + startMigrationMonitoring := func() { + if mmt == nil { + mmt = time.NewTicker(500 * time.Millisecond) + mmtc = mmt.C + } + } + + stopMigrationMonitoring := func() { + if mmt != nil { + mmt.Stop() + mmt, mmtc = nil, nil + } + } + defer stopMigrationMonitoring() + + // This is to optionally track when we are ready as a non-leader for direct access participation. + // Either direct or if we are a direct mirror, or both. + var dat *time.Ticker + var datc <-chan time.Time + + startDirectAccessMonitoring := func() { + if dat == nil { + dat = time.NewTicker(2 * time.Second) + datc = dat.C + } + } + + stopDirectMonitoring := func() { + if dat != nil { + dat.Stop() + dat, datc = nil, nil + } + } + defer stopDirectMonitoring() + + // For checking interest state if applicable. + var cist *time.Ticker + var cistc <-chan time.Time + + checkInterestInterval := checkInterestStateT + time.Duration(rand.Intn(checkInterestStateJ))*time.Second + + if mset != nil && mset.isInterestRetention() { + // Wait on our consumers to be assigned and running before proceeding. + // This can become important when a server has lots of assets + // since we process streams first then consumers as an asset class. + mset.waitOnConsumerAssignments() + // Setup our periodic check here. We will check once we have restored right away. + cist = time.NewTicker(checkInterestInterval) + cistc = cist.C + } + + // This is triggered during a scale up from R1 to clustered mode. We need the new followers to catchup, + // similar to how we trigger the catchup mechanism post a backup/restore. + // We can arrive here NOT being the leader, so we send the snapshot only if we are, and in this case + // reset the notion that we need to send the snapshot. If we are not, then the first time the server + // will switch to leader (in the loop below), we will send the snapshot. + if sendSnapshot && isLeader && mset != nil && n != nil && !isRecovering { + n.SendSnapshot(mset.stateSnapshot()) + sendSnapshot = false + } + + for { + select { + case <-s.quitCh: + // Server shutting down, but we might receive this before qch, so try to snapshot. + doSnapshot() + return + case <-mqch: + // Clean signal from shutdown routine so do best effort attempt to snapshot. + // Don't snapshot if not shutting down, monitor goroutine could be going away + // on a scale down or a remove for example. + if s.isShuttingDown() { + doSnapshot() + } + return + case <-qch: + // Clean signal from shutdown routine so do best effort attempt to snapshot. + // Don't snapshot if not shutting down, Raft node could be going away on a + // scale down or remove for example. + if s.isShuttingDown() { + doSnapshot() + } + return + case <-aq.ch: + var ne, nb uint64 + // If we bump clfs we will want to write out snapshot if within our time window. + pclfs := mset.getCLFS() + + ces := aq.pop() + for _, ce := range ces { + // No special processing needed for when we are caught up on restart. + if ce == nil { + isRecovering = false + // If we are interest based make sure to check consumers if interest retention policy. + // This is to make sure we process any outstanding acks from all consumers. + if mset != nil && mset.isInterestRetention() { + fire := time.Duration(rand.Intn(5)+5) * time.Second + time.AfterFunc(fire, mset.checkInterestState) + } + // If we became leader during this time and we need to send a snapshot to our + // followers, i.e. as a result of a scale-up from R1, do it now. + if sendSnapshot && isLeader && mset != nil && n != nil { + n.SendSnapshot(mset.stateSnapshot()) + sendSnapshot = false + } + continue + } + + // Apply our entries. + if err := js.applyStreamEntries(mset, ce, isRecovering); err == nil { + // Update our applied. + ne, nb = n.Applied(ce.Index) + ce.ReturnToPool() + } else { + // Make sure to clean up. + ce.ReturnToPool() + // Our stream was closed out from underneath of us, simply return here. + if err == errStreamClosed || err == errCatchupStreamStopped || err == ErrServerNotRunning { + aq.recycle(&ces) + return + } + s.Warnf("Error applying entries to '%s > %s': %v", accName, sa.Config.Name, err) + if isClusterResetErr(err) { + if mset.isMirror() && mset.IsLeader() { + mset.retryMirrorConsumer() + continue + } + // If the error signals we timed out of a snapshot, we should try to replay the snapshot + // instead of fully resetting the state. Resetting the clustered state may result in + // race conditions and should only be used as a last effort attempt. + if errors.Is(err, errCatchupAbortedNoLeader) || err == errCatchupTooManyRetries { + if node := mset.raftNode(); node != nil && node.DrainAndReplaySnapshot() { + break + } + } + // We will attempt to reset our cluster state. + if mset.resetClusteredState(err) { + aq.recycle(&ces) + return + } + } else if isOutOfSpaceErr(err) { + // If applicable this will tear all of this down, but don't assume so and return. + s.handleOutOfSpace(mset) + } + } + } + aq.recycle(&ces) + + // Check about snapshotting + // If we have at least min entries to compact, go ahead and try to snapshot/compact. + if ne >= compactNumMin || nb > compactSizeMin || mset.getCLFS() > pclfs { + doSnapshot() + } + + case isLeader = <-lch: + // Process our leader change. + js.processStreamLeaderChange(mset, isLeader) + + if isLeader { + if mset != nil && n != nil && sendSnapshot && !isRecovering { + // If we *are* recovering at the time then this will get done when the apply queue + // handles the nil guard to show the catchup ended. + n.SendSnapshot(mset.stateSnapshot()) + sendSnapshot = false + } + if isRestore { + acc, _ := s.LookupAccount(sa.Client.serviceAccount()) + restoreDoneCh = s.processStreamRestore(sa.Client, acc, sa.Config, _EMPTY_, sa.Reply, _EMPTY_) + continue + } else if n != nil && n.NeedSnapshot() { + doSnapshot() + } + // Always cancel if this was running. + stopDirectMonitoring() + } else if !n.Leaderless() { + js.setStreamAssignmentRecovering(sa) + } + + // We may receive a leader change after the stream assignment which would cancel us + // monitoring for this closely. So re-assess our state here as well. + // Or the old leader is no longer part of the set and transferred leadership + // for this leader to resume with removal + migrating := mset.isMigrating() + + // Check for migrations here. We set the state on the stream assignment update below. + if isLeader && migrating { + startMigrationMonitoring() + } + + // Here we are checking if we are not the leader but we have been asked to allow + // direct access. We now allow non-leaders to participate in the queue group. + if !isLeader && mset != nil { + mset.mu.RLock() + ad, md := mset.cfg.AllowDirect, mset.cfg.MirrorDirect + mset.mu.RUnlock() + if ad || md { + startDirectAccessMonitoring() + } + } + + case <-cistc: + cist.Reset(checkInterestInterval) + // We may be adjusting some things with consumers so do this in its own go routine. + go mset.checkInterestState() + + case <-datc: + if mset == nil || isRecovering { + continue + } + // If we are leader we can stop, we know this is setup now. + if isLeader { + stopDirectMonitoring() + continue + } + + mset.mu.Lock() + ad, md, current := mset.cfg.AllowDirect, mset.cfg.MirrorDirect, mset.isCurrent() + if !current { + const syncThreshold = 90.0 + // We are not current, but current means exactly caught up. Under heavy publish + // loads we may never reach this, so check if we are within 90% caught up. + _, c, a := mset.node.Progress() + if c == 0 { + mset.mu.Unlock() + continue + } + if p := float64(a) / float64(c) * 100.0; p < syncThreshold { + mset.mu.Unlock() + continue + } else { + s.Debugf("Stream '%s > %s' enabling direct gets at %.0f%% synchronized", + sa.Client.serviceAccount(), sa.Config.Name, p) + } + } + // We are current, cancel monitoring and create the direct subs as needed. + if ad { + mset.subscribeToDirect() + } + if md { + mset.subscribeToMirrorDirect() + } + mset.mu.Unlock() + // Stop direct monitoring. + stopDirectMonitoring() + + case <-t.C: + doSnapshot() + + case <-uch: + // keep stream assignment current + sa = mset.streamAssignment() + + // We get this when we have a new stream assignment caused by an update. + // We want to know if we are migrating. + if migrating := mset.isMigrating(); migrating { + if isLeader && mmtc == nil { + startMigrationMonitoring() + } + } else { + stopMigrationMonitoring() + } + case <-mmtc: + if !isLeader { + // We are no longer leader, so not our job. + stopMigrationMonitoring() + continue + } + + // Check to see where we are.. + rg := mset.raftGroup() + + // Track the new peers and check the ones that are current. + mset.mu.RLock() + replicas := mset.cfg.Replicas + mset.mu.RUnlock() + if len(rg.Peers) <= replicas { + // Migration no longer happening, so not our job anymore + stopMigrationMonitoring() + continue + } + + // Make sure we have correct cluster information on the other peers. + ci := js.clusterInfo(rg) + mset.checkClusterInfo(ci) + + newPeers, oldPeers, newPeerSet, oldPeerSet := genPeerInfo(rg.Peers, len(rg.Peers)-replicas) + + // If we are part of the new peerset and we have been passed the baton. + // We will handle scale down. + if newPeerSet[ourPeerId] { + // First need to check on any consumers and make sure they have moved properly before scaling down ourselves. + js.mu.RLock() + var needToWait bool + for name, c := range sa.consumers { + if c.unsupported != nil { + continue + } + for _, peer := range c.Group.Peers { + // If we have peers still in the old set block. + if oldPeerSet[peer] { + s.Debugf("Scale down of '%s > %s' blocked by consumer '%s'", accName, sa.Config.Name, name) + needToWait = true + break + } + } + if needToWait { + break + } + } + js.mu.RUnlock() + if needToWait { + continue + } + + // We are good to go, can scale down here. + for _, p := range oldPeers { + n.ProposeRemovePeer(p) + } + + csa := sa.copyGroup() + csa.Group.Peers = newPeers + csa.Group.Preferred = ourPeerId + csa.Group.Cluster = s.cachedClusterName() + cc.meta.ForwardProposal(encodeUpdateStreamAssignment(csa)) + s.Noticef("Scaling down '%s > %s' to %+v", accName, sa.Config.Name, s.peerSetToNames(newPeers)) + } else { + // We are the old leader here, from the original peer set. + // We are simply waiting on the new peerset to be caught up so we can transfer leadership. + var newLeaderPeer, newLeader string + neededCurrent, current := replicas/2+1, 0 + + for _, r := range ci.Replicas { + if r.Current && newPeerSet[r.Peer] { + current++ + if newLeader == _EMPTY_ { + newLeaderPeer, newLeader = r.Peer, r.Name + } + } + } + // Check if we have a quorom. + if current >= neededCurrent { + s.Noticef("Transfer of stream leader for '%s > %s' to '%s'", accName, sa.Config.Name, newLeader) + n.ProposeKnownPeers(newPeers) + n.StepDown(newLeaderPeer) + } + } + + case err := <-restoreDoneCh: + // We have completed a restore from snapshot on this server. The stream assignment has + // already been assigned but the replicas will need to catch up out of band. Consumers + // will need to be assigned by forwarding the proposal and stamping the initial state. + s.Debugf("Stream restore for '%s > %s' completed", sa.Client.serviceAccount(), sa.Config.Name) + if err != nil { + s.Debugf("Stream restore failed: %v", err) + } + isRestore = false + sa.Restore = nil + // If we were successful lookup up our stream now. + if err == nil { + if mset, err = acc.lookupStream(sa.Config.Name); mset != nil { + mset.monitorWg.Add(1) + defer mset.monitorWg.Done() + mset.checkInMonitor() + mset.setStreamAssignment(sa) + // Make sure to update our updateC which would have been nil. + uch = mset.updateC() + // Also update our mqch + mqch = mset.monitorQuitC() + // Setup a periodic check here if we are interest based as well. + if mset.isInterestRetention() { + cist = time.NewTicker(checkInterestInterval) + cistc = cist.C + } + } + } + if err != nil { + if mset != nil { + mset.delete() + } + js.mu.Lock() + sa.err = err + if n != nil { + n.Delete() + } + result := &streamAssignmentResult{ + Account: sa.Client.serviceAccount(), + Stream: sa.Config.Name, + Restore: &JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}}, + } + result.Restore.Error = NewJSStreamAssignmentError(err, Unless(err)) + js.mu.Unlock() + // Send response to the metadata leader. They will forward to the user as needed. + s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result) + return + } + + if !isLeader { + panic("Finished restore but not leader") + } + // Trigger the stream followers to catchup. + if n = mset.raftNode(); n != nil { + n.SendSnapshot(mset.stateSnapshot()) + } + js.processStreamLeaderChange(mset, isLeader) + + // Check to see if we have restored consumers here. + // These are not currently assigned so we will need to do so here. + if consumers := mset.getPublicConsumers(); len(consumers) > 0 { + for _, o := range consumers { + name, cfg := o.String(), o.config() + rg := cc.createGroupForConsumer(&cfg, sa) + // Pick a preferred leader. + rg.setPreferred() + + // Place our initial state here as well for assignment distribution. + state, _ := o.store.State() + ca := &consumerAssignment{ + Group: rg, + Stream: sa.Config.Name, + Name: name, + Config: &cfg, + Client: sa.Client, + Created: o.createdTime(), + State: state, + } + + // We make these compressed in case state is complex. + addEntry := encodeAddConsumerAssignmentCompressed(ca) + cc.meta.ForwardProposal(addEntry) + + // Check to make sure we see the assignment. + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for range ticker.C { + js.mu.RLock() + ca, meta := js.consumerAssignment(ca.Client.serviceAccount(), sa.Config.Name, name), cc.meta + js.mu.RUnlock() + if ca == nil { + s.Warnf("Consumer assignment has not been assigned, retrying") + if meta != nil { + meta.ForwardProposal(addEntry) + } else { + return + } + } else { + return + } + } + }() + } + } + } + } +} + +// Determine if we are migrating +func (mset *stream) isMigrating() bool { + if mset == nil { + return false + } + + mset.mu.RLock() + js, sa := mset.js, mset.sa + mset.mu.RUnlock() + + js.mu.RLock() + defer js.mu.RUnlock() + + // During migration we will always be R>1, even when we start R1. + // So if we do not have a group or node we no we are not migrating. + if sa == nil || sa.Group == nil || sa.Group.node == nil { + return false + } + // The sign of migration is if our group peer count != configured replica count. + if sa.Config.Replicas == len(sa.Group.Peers) { + return false + } + return true +} + +// resetClusteredState is called when a clustered stream had an error (e.g sequence mismatch, bad snapshot) and needs to be reset. +func (mset *stream) resetClusteredState(err error) bool { + mset.mu.RLock() + s, js, jsa, sa, acc, node, name := mset.srv, mset.js, mset.jsa, mset.sa, mset.acc, mset.node, mset.nameLocked(false) + stype, tierName, replicas := mset.cfg.Storage, mset.tier, mset.cfg.Replicas + mset.mu.RUnlock() + + // The stream might already be deleted and not assigned to us anymore. + // In any case, don't revive the stream if it's already closed. + if mset.closed.Load() || (node != nil && node.IsDeleted()) { + s.Warnf("Will not reset stream '%s > %s', stream is closed", acc, mset.name()) + // Explicitly returning true here, we want the outside to break out of the monitoring loop as well. + return true + } + + assert.Unreachable("Reset clustered state", map[string]any{ + "stream": name, + "account": acc.Name, + "err": err, + }) + + // Stepdown regardless if we are the leader here. + if node != nil { + node.StepDown() + } + + // If we detect we are shutting down just return. + if js != nil && js.isShuttingDown() { + s.Debugf("Will not reset stream '%s > %s', JetStream shutting down", acc, mset.name()) + return false + } + + // Server + if js.limitsExceeded(stype) { + s.Warnf("Will not reset stream '%s > %s', server resources exceeded", acc, mset.name()) + return false + } + + // Account + if exceeded, _ := jsa.limitsExceeded(stype, tierName, replicas); exceeded { + s.Warnf("Stream '%s > %s' errored, account resources exceeded", acc, mset.name()) + return false + } + + if node != nil { + if errors.Is(err, errCatchupAbortedNoLeader) || err == errCatchupTooManyRetries { + // Don't delete all state, could've just been temporarily unable to reach the leader. + node.Stop() + } else { + // We delete our raft state. Will recreate. + node.Delete() + } + } + + // Preserve our current state and messages unless we have a first sequence mismatch. + shouldDelete := err == errFirstSequenceMismatch + + // Need to do the rest in a separate Go routine. + go func() { + mset.signalMonitorQuit() + mset.monitorWg.Wait() + mset.resetAndWaitOnConsumers() + // Stop our stream. + mset.stop(shouldDelete, false) + + if sa != nil { + js.mu.Lock() + if js.shuttingDown { + js.mu.Unlock() + return + } + + s.Warnf("Resetting stream cluster state for '%s > %s'", sa.Client.serviceAccount(), sa.Config.Name) + // Mark stream assignment as resetting, so we don't double-account reserved resources. + // But only if we're not also releasing the resources as part of the delete. + sa.resetting = !shouldDelete + // Now wipe groups from assignments. + sa.Group.node = nil + var consumers []*consumerAssignment + if cc := js.cluster; cc != nil && cc.meta != nil { + ourID := cc.meta.ID() + for _, ca := range sa.consumers { + if ca.unsupported != nil { + continue + } + if rg := ca.Group; rg != nil && rg.isMember(ourID) { + rg.node = nil // Erase group raft/node state. + consumers = append(consumers, ca) + } + } + } + js.mu.Unlock() + + // This will reset the stream and consumers. + // Reset stream. + js.processClusterCreateStream(acc, sa) + // Reset consumers. + for _, ca := range consumers { + js.processClusterCreateConsumer(ca, nil, false) + } + } + }() + + return true +} + +func isControlHdr(hdr []byte) bool { + return bytes.HasPrefix(hdr, []byte("NATS/1.0 100 ")) +} + +// Apply our stream entries. +func (js *jetStream) applyStreamEntries(mset *stream, ce *CommittedEntry, isRecovering bool) error { + for _, e := range ce.Entries { + if e.Type == EntryNormal { + buf, op := e.Data, entryOp(e.Data[0]) + switch op { + case streamMsgOp, compressedStreamMsgOp: + if mset == nil { + continue + } + s := js.srv + + mbuf := buf[1:] + if op == compressedStreamMsgOp { + var err error + mbuf, err = s2.Decode(nil, mbuf) + if err != nil { + panic(err.Error()) + } + } + + subject, reply, hdr, msg, lseq, ts, sourced, err := decodeStreamMsg(mbuf) + if err != nil { + if node := mset.raftNode(); node != nil { + s.Errorf("JetStream cluster could not decode stream msg for '%s > %s' [%s]", + mset.account(), mset.name(), node.Group()) + } + panic(err.Error()) + } + + // Check for flowcontrol here. + if len(msg) == 0 && len(hdr) > 0 && reply != _EMPTY_ && isControlHdr(hdr) { + if !isRecovering { + mset.sendFlowControlReply(reply) + } + continue + } + + // Grab last sequence and CLFS. + last, clfs := mset.lastSeqAndCLFS() + + // We can skip if we know this is less than what we already have. + if lseq-clfs < last { + s.Debugf("Apply stream entries for '%s > %s' skipping message with sequence %d with last of %d", + mset.account(), mset.name(), lseq+1-clfs, last) + mset.mu.Lock() + // Check for any preAcks in case we are interest based. + mset.clearAllPreAcks(lseq + 1 - clfs) + mset.mu.Unlock() + continue + } + + // Skip by hand here since first msg special case. + // Reason is sequence is unsigned and for lseq being 0 + // the lseq under stream would have to be -1. + if lseq == 0 && last != 0 { + continue + } + + // Messages to be skipped have no subject or timestamp or msg or hdr. + if subject == _EMPTY_ && ts == 0 && len(msg) == 0 && len(hdr) == 0 { + // Skip and update our lseq. + last, _ := mset.store.SkipMsg(0) + mset.mu.Lock() + mset.setLastSeq(last) + mset.clearAllPreAcks(last) + mset.mu.Unlock() + continue + } + + var mt *msgTrace + // If not recovering, see if we find a message trace object for this + // sequence. Only the leader that has proposed this entry will have + // stored the trace info. + if !isRecovering { + mt = mset.getAndDeleteMsgTrace(lseq) + } + // Process the actual message here. + err = mset.processJetStreamMsg(subject, reply, hdr, msg, lseq, ts, mt, sourced) + + // If we have inflight make sure to clear after processing. + // TODO(dlc) - technically check on inflight != nil could cause datarace. + // But do not want to acquire lock since tracking this will be rare. + if mset.inflight != nil { + mset.clMu.Lock() + delete(mset.inflight, lseq) + mset.clMu.Unlock() + } + + // Clear expected per subject state after processing. + if mset.expectedPerSubjectSequence != nil { + mset.clMu.Lock() + if subj, found := mset.expectedPerSubjectSequence[lseq]; found { + delete(mset.expectedPerSubjectSequence, lseq) + delete(mset.expectedPerSubjectInProcess, subj) + } + mset.clMu.Unlock() + } + + if err != nil { + if err == errLastSeqMismatch { + + var state StreamState + mset.store.FastState(&state) + + // If we have no msgs and the other side is delivering us a sequence past where we + // should be reset. This is possible if the other side has a stale snapshot and no longer + // has those messages. So compact and retry to reset. + if state.Msgs == 0 { + mset.store.Compact(lseq + 1) + // Retry + err = mset.processJetStreamMsg(subject, reply, hdr, msg, lseq, ts, mt, sourced) + } + // FIXME(dlc) - We could just run a catchup with a request defining the span between what we expected + // and what we got. + } + + // Only return in place if we are going to reset our stream or we are out of space, or we are closed. + if isClusterResetErr(err) || isOutOfSpaceErr(err) || err == errStreamClosed { + return err + } + s.Debugf("Apply stream entries for '%s > %s' got error processing message: %v", + mset.account(), mset.name(), err) + } + + case deleteMsgOp: + md, err := decodeMsgDelete(buf[1:]) + if err != nil { + if node := mset.raftNode(); node != nil { + s := js.srv + s.Errorf("JetStream cluster could not decode delete msg for '%s > %s' [%s]", + mset.account(), mset.name(), node.Group()) + } + panic(err.Error()) + } + s := js.server() + + var removed bool + if md.NoErase { + removed, err = mset.removeMsg(md.Seq) + } else { + removed, err = mset.eraseMsg(md.Seq) + } + + var isLeader bool + if node := mset.raftNode(); node != nil && node.Leader() { + isLeader = true + } + + if err == ErrStoreEOF { + if isLeader && !isRecovering { + var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}} + resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err)) + s.sendAPIErrResponse(md.Client, mset.account(), md.Subject, md.Reply, _EMPTY_, s.jsonResponse(resp)) + } + continue + } + + if err != nil && !isRecovering { + s.Debugf("JetStream cluster failed to delete stream msg %d from '%s > %s': %v", + md.Seq, md.Client.serviceAccount(), md.Stream, err) + } + + if isLeader && !isRecovering { + var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}} + if err != nil { + resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err)) + s.sendAPIErrResponse(md.Client, mset.account(), md.Subject, md.Reply, _EMPTY_, s.jsonResponse(resp)) + } else if !removed { + resp.Error = NewJSSequenceNotFoundError(md.Seq) + s.sendAPIErrResponse(md.Client, mset.account(), md.Subject, md.Reply, _EMPTY_, s.jsonResponse(resp)) + } else { + resp.Success = true + s.sendAPIResponse(md.Client, mset.account(), md.Subject, md.Reply, _EMPTY_, s.jsonResponse(resp)) + } + } + case purgeStreamOp: + sp, err := decodeStreamPurge(buf[1:]) + if err != nil { + if node := mset.raftNode(); node != nil { + s := js.srv + s.Errorf("JetStream cluster could not decode purge msg for '%s > %s' [%s]", + mset.account(), mset.name(), node.Group()) + } + panic(err.Error()) + } + // If no explicit request, fill in with leader stamped last sequence to protect ourselves on replay during server start. + if sp.Request == nil || sp.Request.Sequence == 0 { + purgeSeq := sp.LastSeq + 1 + if sp.Request == nil { + sp.Request = &JSApiStreamPurgeRequest{Sequence: purgeSeq} + } else if sp.Request.Keep == 0 { + sp.Request.Sequence = purgeSeq + } else if isRecovering { + continue + } + } + + s := js.server() + purged, err := mset.purge(sp.Request) + if err != nil { + s.Warnf("JetStream cluster failed to purge stream %q for account %q: %v", sp.Stream, sp.Client.serviceAccount(), err) + } + + js.mu.RLock() + isLeader := js.cluster.isStreamLeader(sp.Client.serviceAccount(), sp.Stream) + js.mu.RUnlock() + + if isLeader && !isRecovering { + var resp = JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}} + if err != nil { + resp.Error = NewJSStreamGeneralError(err, Unless(err)) + s.sendAPIErrResponse(sp.Client, mset.account(), sp.Subject, sp.Reply, _EMPTY_, s.jsonResponse(resp)) + } else { + resp.Purged = purged + resp.Success = true + s.sendAPIResponse(sp.Client, mset.account(), sp.Subject, sp.Reply, _EMPTY_, s.jsonResponse(resp)) + } + } + default: + panic(fmt.Sprintf("JetStream Cluster Unknown group entry op type: %v", op)) + } + } else if e.Type == EntrySnapshot { + if mset == nil { + continue + } + + // Everything operates on new replicated state. Will convert legacy snapshots to this for processing. + var ss *StreamReplicatedState + + onBadState := func(err error) { + // If we are the leader or recovering, meaning we own the snapshot, + // we should stepdown and clear our raft state since our snapshot is bad. + if isRecovering || mset.IsLeader() { + mset.mu.RLock() + s, accName, streamName := mset.srv, mset.acc.GetName(), mset.cfg.Name + mset.mu.RUnlock() + s.Warnf("Detected bad stream state, resetting '%s > %s'", accName, streamName) + mset.resetClusteredState(err) + } + } + + // Check if we are the new binary encoding. + if IsEncodedStreamState(e.Data) { + var err error + ss, err = DecodeStreamState(e.Data) + if err != nil { + onBadState(err) + return err + } + } else { + var snap streamSnapshot + if err := json.Unmarshal(e.Data, &snap); err != nil { + onBadState(err) + return err + } + // Convert over to StreamReplicatedState + ss = &StreamReplicatedState{ + Msgs: snap.Msgs, + Bytes: snap.Bytes, + FirstSeq: snap.FirstSeq, + LastSeq: snap.LastSeq, + Failed: snap.Failed, + } + if len(snap.Deleted) > 0 { + ss.Deleted = append(ss.Deleted, DeleteSlice(snap.Deleted)) + } + } + + if isRecovering || !mset.IsLeader() { + if err := mset.processSnapshot(ss, ce.Index); err != nil { + return err + } + } + } else if e.Type == EntryRemovePeer { + js.mu.RLock() + var ourID string + if js.cluster != nil && js.cluster.meta != nil { + ourID = js.cluster.meta.ID() + } + js.mu.RUnlock() + // We only need to do processing if this is us. + if peer := string(e.Data); peer == ourID && mset != nil { + // Double check here with the registered stream assignment. + shouldRemove := true + if sa := mset.streamAssignment(); sa != nil && sa.Group != nil { + js.mu.RLock() + shouldRemove = !sa.Group.isMember(ourID) + js.mu.RUnlock() + } + if shouldRemove { + mset.stop(true, false) + } + } + } + } + return nil +} + +// Returns the PeerInfo for all replicas of a raft node. This is different than node.Peers() +// and is used for external facing advisories. +func (s *Server) replicas(node RaftNode) []*PeerInfo { + var replicas []*PeerInfo + for _, rp := range node.Peers() { + if sir, ok := s.nodeToInfo.Load(rp.ID); ok && sir != nil { + si := sir.(nodeInfo) + pi := &PeerInfo{Peer: rp.ID, Name: si.name, Current: rp.Current, Offline: si.offline, Lag: rp.Lag} + if !rp.Last.IsZero() { + pi.Active = time.Since(rp.Last) + } + replicas = append(replicas, pi) + } + } + return replicas +} + +// Process a leader change for the clustered stream. +func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) { + if mset == nil { + return + } + sa := mset.streamAssignment() + if sa == nil { + return + } + + // Clear inflight dedupe IDs, where seq=0. + mset.mu.Lock() + var removed int + for i := len(mset.ddarr) - 1; i >= mset.ddindex; i-- { + dde := mset.ddarr[i] + if dde.seq != 0 { + break + } + removed++ + delete(mset.ddmap, dde.id) + } + if removed > 0 { + if len(mset.ddmap) > 0 { + mset.ddarr = mset.ddarr[:len(mset.ddarr)-removed] + } else { + mset.ddmap = nil + mset.ddarr = nil + mset.ddindex = 0 + } + } + mset.mu.Unlock() + + mset.clMu.Lock() + // Clear inflight if we have it. + mset.inflight = nil + // Clear expected per subject state. + mset.expectedPerSubjectSequence = nil + mset.expectedPerSubjectInProcess = nil + mset.clMu.Unlock() + + js.mu.Lock() + s, account, err := js.srv, sa.Client.serviceAccount(), sa.err + client, subject, reply := sa.Client, sa.Subject, sa.Reply + hasResponded := sa.responded + sa.responded = true + js.mu.Unlock() + + streamName := mset.name() + + if isLeader { + s.Noticef("JetStream cluster new stream leader for '%s > %s'", account, streamName) + s.sendStreamLeaderElectAdvisory(mset) + } else { + // We are stepping down. + // Make sure if we are doing so because we have lost quorum that we send the appropriate advisories. + if node := mset.raftNode(); node != nil && !node.Quorum() && time.Since(node.Created()) > 5*time.Second { + s.sendStreamLostQuorumAdvisory(mset) + } + + // Clear clseq. If we become leader again, it will be fixed up + // automatically on the next processClusteredInboundMsg call. + mset.clMu.Lock() + if mset.clseq > 0 { + mset.clseq = 0 + } + mset.clMu.Unlock() + } + + // Tell stream to switch leader status. + mset.setLeader(isLeader) + + if !isLeader || hasResponded { + return + } + + acc, _ := s.LookupAccount(account) + if acc == nil { + return + } + + // Send our response. + var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}} + if err != nil { + resp.Error = NewJSStreamCreateError(err, Unless(err)) + s.sendAPIErrResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + } else { + msetCfg := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: *setDynamicStreamMetadata(&msetCfg), + Cluster: js.clusterInfo(mset.raftGroup()), + Sources: mset.sourcesInfo(), + Mirror: mset.mirrorInfo(), + TimeStamp: time.Now().UTC(), + } + resp.DidCreate = true + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + if node := mset.raftNode(); node != nil { + mset.sendCreateAdvisory() + } + } +} + +// Fixed value ok for now. +const lostQuorumAdvInterval = 10 * time.Second + +// Determines if we should send lost quorum advisory. We throttle these after first one. +func (mset *stream) shouldSendLostQuorum() bool { + mset.mu.Lock() + defer mset.mu.Unlock() + if time.Since(mset.lqsent) >= lostQuorumAdvInterval { + mset.lqsent = time.Now() + return true + } + return false +} + +func (s *Server) sendStreamLostQuorumAdvisory(mset *stream) { + if mset == nil { + return + } + node, stream, acc := mset.raftNode(), mset.name(), mset.account() + if node == nil { + return + } + if !mset.shouldSendLostQuorum() { + return + } + + s.Warnf("JetStream cluster stream '%s > %s' has NO quorum, stalled", acc.GetName(), stream) + + subj := JSAdvisoryStreamQuorumLostPre + "." + stream + adv := &JSStreamQuorumLostAdvisory{ + TypedEvent: TypedEvent{ + Type: JSStreamQuorumLostAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Stream: stream, + Replicas: s.replicas(node), + Domain: s.getOpts().JetStreamDomain, + } + + // Send to the user's account if not the system account. + if acc != s.SystemAccount() { + s.publishAdvisory(acc, subj, adv) + } + // Now do system level one. Place account info in adv, and nil account means system. + adv.Account = acc.GetName() + s.publishAdvisory(nil, subj, adv) +} + +func (s *Server) sendStreamLeaderElectAdvisory(mset *stream) { + if mset == nil { + return + } + node, stream, acc := mset.raftNode(), mset.name(), mset.account() + if node == nil { + return + } + subj := JSAdvisoryStreamLeaderElectedPre + "." + stream + adv := &JSStreamLeaderElectedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSStreamLeaderElectedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Stream: stream, + Leader: s.serverNameForNode(node.GroupLeader()), + Replicas: s.replicas(node), + Domain: s.getOpts().JetStreamDomain, + } + + // Send to the user's account if not the system account. + if acc != s.SystemAccount() { + s.publishAdvisory(acc, subj, adv) + } + // Now do system level one. Place account info in adv, and nil account means system. + adv.Account = acc.GetName() + s.publishAdvisory(nil, subj, adv) +} + +// Will lookup a stream assignment. +// Lock should be held. +func (js *jetStream) streamAssignment(account, stream string) (sa *streamAssignment) { + cc := js.cluster + if cc == nil { + return nil + } + + if as := cc.streams[account]; as != nil { + sa = as[stream] + } + return sa +} + +// processStreamAssignment is called when followers have replicated an assignment. +func (js *jetStream) processStreamAssignment(sa *streamAssignment) { + js.mu.Lock() + s, cc := js.srv, js.cluster + accName, stream := sa.Client.serviceAccount(), sa.Config.Name + noMeta := cc == nil || cc.meta == nil + var ourID string + if !noMeta { + ourID = cc.meta.ID() + } + var isMember bool + if sa.Group != nil && ourID != _EMPTY_ { + isMember = sa.Group.isMember(ourID) + } + + // Remove this stream from the inflight proposals + cc.removeInflightProposal(accName, sa.Config.Name) + + if s == nil || noMeta { + js.mu.Unlock() + return + } + + accStreams := cc.streams[accName] + if accStreams == nil { + accStreams = make(map[string]*streamAssignment) + } else if osa := accStreams[stream]; osa != nil { + if osa != sa { + // Copy over private existing state from former SA. + if sa.Group != nil { + sa.Group.node = osa.Group.node + } + sa.consumers = osa.consumers + sa.responded = osa.responded + sa.err = osa.err + } + // Unsubscribe if it was previously unsupported. + if osa.unsupported != nil { + osa.unsupported.closeInfoSub(js.srv) + // If we've seen unsupported once, it remains for the lifetime of this server process. + if sa.unsupported == nil { + sa.unsupported = osa.unsupported + } + } + } + + // Update our state. + accStreams[stream] = sa + cc.streams[accName] = accStreams + hasResponded := sa.responded + + // If unsupported, we can't register any further. + if sa.unsupported != nil { + sa.unsupported.setupInfoSub(s, sa) + s.Warnf("Detected unsupported stream '%s > %s': %s", accName, stream, sa.unsupported.reason) + js.mu.Unlock() + + // Need to stop the stream, we can't keep running with an old config. + acc, err := s.LookupAccount(accName) + if err != nil { + return + } + mset, err := acc.lookupStream(stream) + if err != nil || mset.closed.Load() { + return + } + s.Warnf("Stopping unsupported stream '%s > %s'", accName, stream) + mset.stop(false, false) + return + } + js.mu.Unlock() + + acc, err := s.LookupAccount(accName) + if err != nil { + ll := fmt.Sprintf("Account [%s] lookup for stream create failed: %v", accName, err) + if isMember { + if !hasResponded { + // If we can not lookup the account and we are a member, send this result back to the metacontroller leader. + result := &streamAssignmentResult{ + Account: accName, + Stream: stream, + Response: &JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}, + } + result.Response.Error = NewJSNoAccountError() + s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result) + } + s.Warnf(ll) + } else { + s.Debugf(ll) + } + return + } + + // Check if this is for us.. + if isMember { + js.processClusterCreateStream(acc, sa) + } else if mset, _ := acc.lookupStream(sa.Config.Name); mset != nil { + // We have one here even though we are not a member. This can happen on re-assignment. + s.removeStream(mset, sa) + } + + // If this stream assignment does not have a sync subject (bug) set that the meta-leader should check when elected. + if sa.Sync == _EMPTY_ { + js.mu.Lock() + cc.streamsCheck = true + js.mu.Unlock() + } +} + +// processUpdateStreamAssignment is called when followers have replicated an updated assignment. +func (js *jetStream) processUpdateStreamAssignment(sa *streamAssignment) { + js.mu.RLock() + s, cc := js.srv, js.cluster + js.mu.RUnlock() + if s == nil || cc == nil { + // TODO(dlc) - debug at least + return + } + + accName := sa.Client.serviceAccount() + stream := sa.Config.Name + + js.mu.Lock() + if cc.meta == nil { + js.mu.Unlock() + return + } + ourID := cc.meta.ID() + + var isMember bool + if sa.Group != nil { + isMember = sa.Group.isMember(ourID) + } + + accStreams := cc.streams[accName] + if accStreams == nil { + js.mu.Unlock() + return + } + osa := accStreams[stream] + if osa == nil { + js.mu.Unlock() + return + } + + // Copy over private existing state from former SA. + if sa.Group != nil { + sa.Group.node = osa.Group.node + } + sa.consumers = osa.consumers + sa.err = osa.err + + // If we detect we are scaling down to 1, non-clustered, and we had a previous node, clear it here. + if sa.Config.Replicas == 1 && sa.Group.node != nil { + sa.Group.node = nil + } + + // Update our state. + accStreams[stream] = sa + cc.streams[accName] = accStreams + + // Make sure we respond if we are a member. + if isMember { + sa.responded = false + } else { + // Make sure to clean up any old node in case this stream moves back here. + if sa.Group != nil { + sa.Group.node = nil + } + } + + // Unsubscribe if it was previously unsupported. + if osa.unsupported != nil { + osa.unsupported.closeInfoSub(js.srv) + // If we've seen unsupported once, it remains for the lifetime of this server process. + if sa.unsupported == nil { + sa.unsupported = osa.unsupported + } + } + + // If unsupported, we can't register any further. + if sa.unsupported != nil { + sa.unsupported.setupInfoSub(s, sa) + s.Warnf("Detected unsupported stream '%s > %s': %s", accName, stream, sa.unsupported.reason) + js.mu.Unlock() + + // Need to stop the stream, we can't keep running with an old config. + acc, err := s.LookupAccount(accName) + if err != nil { + return + } + mset, err := acc.lookupStream(stream) + if err != nil || mset.closed.Load() { + return + } + s.Warnf("Stopping unsupported stream '%s > %s'", accName, stream) + mset.stop(false, false) + return + } + js.mu.Unlock() + + acc, err := s.LookupAccount(accName) + if err != nil { + s.Warnf("Update Stream Account %s, error on lookup: %v", accName, err) + return + } + + // Check if this is for us.. + if isMember { + js.processClusterUpdateStream(acc, osa, sa) + } else if mset, _ := acc.lookupStream(sa.Config.Name); mset != nil { + // We have one here even though we are not a member. This can happen on re-assignment. + s.removeStream(mset, sa) + } +} + +// Common function to remove ourselves from this server. +// This can happen on re-assignment, move, etc +func (s *Server) removeStream(mset *stream, nsa *streamAssignment) { + if mset == nil { + return + } + // Make sure to use the new stream assignment, not our own. + s.Debugf("JetStream removing stream '%s > %s' from this server", nsa.Client.serviceAccount(), nsa.Config.Name) + if node := mset.raftNode(); node != nil { + node.StepDown(nsa.Group.Preferred) + // shutdown monitor by shutting down raft. + node.Delete() + } + + var isShuttingDown bool + // Make sure this node is no longer attached to our stream assignment. + if js, _ := s.getJetStreamCluster(); js != nil { + js.mu.Lock() + nsa.Group.node = nil + isShuttingDown = js.shuttingDown + js.mu.Unlock() + } + + if !isShuttingDown { + // wait for monitor to be shutdown. + mset.signalMonitorQuit() + mset.monitorWg.Wait() + } + mset.stop(true, false) +} + +// processClusterUpdateStream is called when we have a stream assignment that +// has been updated for an existing assignment and we are a member. +func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAssignment) { + if sa == nil { + return + } + + js.mu.Lock() + s, rg := js.srv, sa.Group + client, subject, reply := sa.Client, sa.Subject, sa.Reply + alreadyRunning, numReplicas := osa.Group.node != nil, len(rg.Peers) + needsNode := rg.node == nil + storage, cfg := sa.Config.Storage, sa.Config + hasResponded := sa.responded + sa.responded = true + recovering := sa.recovering + js.mu.Unlock() + + mset, err := acc.lookupStream(cfg.Name) + if err == nil && mset != nil { + // Make sure we have not had a new group assigned to us. + if osa.Group.Name != sa.Group.Name { + s.Warnf("JetStream cluster detected stream remapping for '%s > %s' from %q to %q", + acc, cfg.Name, osa.Group.Name, sa.Group.Name) + mset.removeNode() + alreadyRunning, needsNode = false, true + // Make sure to clear from original. + js.mu.Lock() + osa.Group.node = nil + js.mu.Unlock() + } + + if !alreadyRunning && numReplicas > 1 { + if needsNode { + // Since we are scaling up we want to make sure our sync subject + // is registered before we start our raft node. + mset.mu.Lock() + mset.startClusterSubs() + mset.mu.Unlock() + + js.createRaftGroup(acc.GetName(), rg, storage, pprofLabels{ + "type": "stream", + "account": mset.accName(), + "stream": mset.name(), + }) + } + mset.monitorWg.Add(1) + // Start monitoring.. + started := s.startGoRoutine( + func() { js.monitorStream(mset, sa, needsNode) }, + pprofLabels{ + "type": "stream", + "account": mset.accName(), + "stream": mset.name(), + }, + ) + if !started { + mset.monitorWg.Done() + } + } else if numReplicas == 1 && alreadyRunning { + // We downgraded to R1. Make sure we cleanup the raft node and the stream monitor. + mset.removeNode() + // In case we need to shutdown the cluster specific subs, etc. + mset.mu.Lock() + // Stop responding to sync requests. + mset.stopClusterSubs() + // Clear catchup state + mset.clearAllCatchupPeers() + mset.mu.Unlock() + // Remove from meta layer. + js.mu.Lock() + rg.node = nil + js.mu.Unlock() + } + // Set the new stream assignment. + mset.setStreamAssignment(sa) + + // Call update. + if err = mset.updateWithAdvisory(cfg, !recovering, false); err != nil { + s.Warnf("JetStream cluster error updating stream %q for account %q: %v", cfg.Name, acc.Name, err) + } + } + + // If not found we must be expanding into this node since if we are here we know we are a member. + if err == ErrJetStreamStreamNotFound { + js.processStreamAssignment(sa) + return + } + + if err != nil { + js.mu.Lock() + sa.err = err + result := &streamAssignmentResult{ + Account: sa.Client.serviceAccount(), + Stream: sa.Config.Name, + Response: &JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}, + Update: true, + } + result.Response.Error = NewJSStreamGeneralError(err, Unless(err)) + js.mu.Unlock() + + // Send response to the metadata leader. They will forward to the user as needed. + s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result) + return + } + + isLeader := mset.IsLeader() + + // Check for missing syncSubject bug. + if isLeader && osa != nil && osa.Sync == _EMPTY_ { + if node := mset.raftNode(); node != nil { + node.StepDown() + } + return + } + + // If we were a single node being promoted assume leadership role for purpose of responding. + if !hasResponded && !isLeader && !alreadyRunning { + isLeader = true + } + + // Check if we should bail. + if !isLeader || hasResponded || recovering { + return + } + + // Send our response. + var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}} + msetCfg := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: *setDynamicStreamMetadata(&msetCfg), + Cluster: js.clusterInfo(mset.raftGroup()), + Mirror: mset.mirrorInfo(), + Sources: mset.sourcesInfo(), + TimeStamp: time.Now().UTC(), + } + + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) +} + +// processClusterCreateStream is called when we have a stream assignment that +// has been committed and this server is a member of the peer group. +func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignment) { + if sa == nil { + return + } + + js.mu.RLock() + s, rg, created := js.srv, sa.Group, sa.Created + alreadyRunning := rg.node != nil + storage := sa.Config.Storage + restore := sa.Restore + js.mu.RUnlock() + + // Process the raft group and make sure it's running if needed. + _, err := js.createRaftGroup(acc.GetName(), rg, storage, pprofLabels{ + "type": "stream", + "account": acc.Name, + "stream": sa.Config.Name, + }) + + // If we are restoring, create the stream if we are R>1 and not the preferred who handles the + // receipt of the snapshot itself. + shouldCreate := true + if restore != nil { + if len(rg.Peers) == 1 || rg.node != nil && rg.node.ID() == rg.Preferred { + shouldCreate = false + } else { + js.mu.Lock() + sa.Restore = nil + js.mu.Unlock() + } + } + + // Our stream. + var mset *stream + + // Process here if not restoring or not the leader. + if shouldCreate && err == nil { + // Go ahead and create or update the stream. + mset, err = acc.lookupStream(sa.Config.Name) + if err == nil && mset != nil { + osa := mset.streamAssignment() + // If we already have a stream assignment and they are the same exact config, short circuit here. + if osa != nil { + if reflect.DeepEqual(osa.Config, sa.Config) { + if sa.Group.Name == osa.Group.Name && reflect.DeepEqual(sa.Group.Peers, osa.Group.Peers) { + // Since this already exists we know it succeeded, just respond to this caller. + js.mu.RLock() + client, subject, reply, recovering := sa.Client, sa.Subject, sa.Reply, sa.recovering + js.mu.RUnlock() + + if !recovering { + var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}} + msetCfg := mset.config() + resp.StreamInfo = &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: *setDynamicStreamMetadata(&msetCfg), + Cluster: js.clusterInfo(mset.raftGroup()), + Sources: mset.sourcesInfo(), + Mirror: mset.mirrorInfo(), + TimeStamp: time.Now().UTC(), + } + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + } + return + } else { + // We had a bug where we could have multiple assignments for the same + // stream but with different group assignments, including multiple raft + // groups. So check for that here. We can only bet on the last one being + // consistent in the long run, so let it continue if we see this condition. + s.Warnf("JetStream cluster detected duplicate assignment for stream %q for account %q", sa.Config.Name, acc.Name) + if osa.Group.node != nil && osa.Group.node != sa.Group.node { + osa.Group.node.Delete() + osa.Group.node = nil + } + } + } + } + mset.setStreamAssignment(sa) + // Check if our config has really been updated. + cfg := mset.config() + if !reflect.DeepEqual(&cfg, sa.Config) { + if err = mset.updateWithAdvisory(sa.Config, false, false); err != nil { + s.Warnf("JetStream cluster error updating stream %q for account %q: %v", sa.Config.Name, acc.Name, err) + if osa != nil { + // Process the raft group and make sure it's running if needed. + js.createRaftGroup(acc.GetName(), osa.Group, storage, pprofLabels{ + "type": "stream", + "account": mset.accName(), + "stream": mset.name(), + }) + mset.setStreamAssignment(osa) + } + if rg.node != nil { + rg.node.Delete() + rg.node = nil + } + } + } + } else if err == NewJSStreamNotFoundError() { + // Add in the stream here. + mset, err = acc.addStreamWithAssignment(sa.Config, nil, sa, false) + } + if mset != nil { + mset.setCreatedTime(created) + } + } + + // This is an error condition. + if err != nil { + // If we're shutting down we could get a variety of errors, for example: + // 'JetStream not enabled for account' when looking up the stream. + // Normally we can continue and delete state, but need to be careful when shutting down. + if js.isShuttingDown() { + s.Debugf("Could not create stream, JetStream shutting down") + return + } + + if IsNatsErr(err, JSStreamStoreFailedF) { + s.Warnf("Stream create failed for '%s > %s': %v", sa.Client.serviceAccount(), sa.Config.Name, err) + err = errStreamStoreFailed + } + js.mu.Lock() + + sa.err = err + hasResponded := sa.responded + + // If out of space do nothing for now. + if isOutOfSpaceErr(err) { + hasResponded = true + } + + if rg.node != nil { + rg.node.Delete() + } + + var result *streamAssignmentResult + if !hasResponded { + result = &streamAssignmentResult{ + Account: sa.Client.serviceAccount(), + Stream: sa.Config.Name, + Response: &JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}}, + } + result.Response.Error = NewJSStreamCreateError(err, Unless(err)) + } + js.mu.Unlock() + + // Send response to the metadata leader. They will forward to the user as needed. + if result != nil { + s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result) + } + return + } + + // Re-capture node. + js.mu.RLock() + node := rg.node + js.mu.RUnlock() + + // Start our monitoring routine. + if node != nil { + if !alreadyRunning { + if mset != nil { + mset.monitorWg.Add(1) + } + started := s.startGoRoutine( + func() { js.monitorStream(mset, sa, false) }, + pprofLabels{ + "type": "stream", + "account": mset.accName(), + "stream": mset.name(), + }, + ) + if !started && mset != nil { + mset.monitorWg.Done() + } + } + } else { + // Single replica stream, process manually here. + // If we are restoring, process that first. + if sa.Restore != nil { + // We are restoring a stream here. + restoreDoneCh := s.processStreamRestore(sa.Client, acc, sa.Config, _EMPTY_, sa.Reply, _EMPTY_) + s.startGoRoutine(func() { + defer s.grWG.Done() + select { + case err := <-restoreDoneCh: + if err == nil { + mset, err = acc.lookupStream(sa.Config.Name) + if mset != nil { + mset.setStreamAssignment(sa) + mset.setCreatedTime(created) + } + } + if err != nil { + if mset != nil { + mset.delete() + } + js.mu.Lock() + sa.err = err + result := &streamAssignmentResult{ + Account: sa.Client.serviceAccount(), + Stream: sa.Config.Name, + Restore: &JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}}, + } + result.Restore.Error = NewJSStreamRestoreError(err, Unless(err)) + js.mu.Unlock() + // Send response to the metadata leader. They will forward to the user as needed. + b, _ := json.Marshal(result) // Avoids auto-processing and doing fancy json with newlines. + s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, b) + return + } + js.processStreamLeaderChange(mset, true) + + // Check to see if we have restored consumers here. + // These are not currently assigned so we will need to do so here. + if consumers := mset.getPublicConsumers(); len(consumers) > 0 { + js.mu.RLock() + cc := js.cluster + js.mu.RUnlock() + + for _, o := range consumers { + name, cfg := o.String(), o.config() + rg := cc.createGroupForConsumer(&cfg, sa) + + // Place our initial state here as well for assignment distribution. + ca := &consumerAssignment{ + Group: rg, + Stream: sa.Config.Name, + Name: name, + Config: &cfg, + Client: sa.Client, + Created: o.createdTime(), + } + + addEntry := encodeAddConsumerAssignment(ca) + cc.meta.ForwardProposal(addEntry) + + // Check to make sure we see the assignment. + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for range ticker.C { + js.mu.RLock() + ca, meta := js.consumerAssignment(ca.Client.serviceAccount(), sa.Config.Name, name), cc.meta + js.mu.RUnlock() + if ca == nil { + s.Warnf("Consumer assignment has not been assigned, retrying") + if meta != nil { + meta.ForwardProposal(addEntry) + } else { + return + } + } else { + return + } + } + }() + } + } + case <-s.quitCh: + return + } + }) + } else { + js.processStreamLeaderChange(mset, true) + } + } +} + +// processStreamRemoval is called when followers have replicated an assignment. +func (js *jetStream) processStreamRemoval(sa *streamAssignment) { + js.mu.Lock() + s, cc := js.srv, js.cluster + if s == nil || cc == nil || cc.meta == nil { + // TODO(dlc) - debug at least + js.mu.Unlock() + return + } + stream := sa.Config.Name + isMember := sa.Group.isMember(cc.meta.ID()) + wasLeader := cc.isStreamLeader(sa.Client.serviceAccount(), stream) + + // Check if we already have this assigned. + accStreams := cc.streams[sa.Client.serviceAccount()] + needDelete := accStreams != nil && accStreams[stream] != nil + if needDelete { + if osa := accStreams[stream]; osa != nil && osa.unsupported != nil { + osa.unsupported.closeInfoSub(js.srv) + // Remember we used to be unsupported, just so we can send a successful delete response. + if sa.unsupported == nil { + sa.unsupported = osa.unsupported + } + } + delete(accStreams, stream) + if len(accStreams) == 0 { + delete(cc.streams, sa.Client.serviceAccount()) + } + } + js.mu.Unlock() + + if needDelete { + js.processClusterDeleteStream(sa, isMember, wasLeader) + } +} + +func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember, wasLeader bool) { + if sa == nil { + return + } + js.mu.RLock() + s := js.srv + node := sa.Group.node + hadLeader := node == nil || !node.Leaderless() + offline := s.allPeersOffline(sa.Group) || sa.unsupported != nil + var isMetaLeader bool + if cc := js.cluster; cc != nil { + isMetaLeader = cc.isLeader() + } + recovering := sa.recovering + js.mu.RUnlock() + + stopped := false + var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}} + var err error + var acc *Account + + // Go ahead and delete the stream if we have it and the account here. + if acc, _ = s.LookupAccount(sa.Client.serviceAccount()); acc != nil { + if mset, _ := acc.lookupStream(sa.Config.Name); mset != nil { + // shut down monitor by shutting down raft + if n := mset.raftNode(); n != nil { + n.Delete() + } + // wait for monitor to be shut down + mset.signalMonitorQuit() + mset.monitorWg.Wait() + err = mset.stop(true, wasLeader) + stopped = true + } else if isMember { + s.Warnf("JetStream failed to lookup running stream while removing stream '%s > %s' from this server", + sa.Client.serviceAccount(), sa.Config.Name) + } + } else if isMember { + s.Warnf("JetStream failed to lookup account while removing stream '%s > %s' from this server", sa.Client.serviceAccount(), sa.Config.Name) + } + + // Always delete the node if present. + if node != nil { + node.Delete() + } + + // This is a stop gap cleanup in case + // 1) the account or mset does not exist and/or + // 2) node was nil (and couldn't be deleted) + if !stopped || node == nil { + if sacc := s.SystemAccount(); sacc != nil { + saccName := sacc.GetName() + os.RemoveAll(filepath.Join(js.config.StoreDir, saccName, defaultStoreDirName, sa.Group.Name)) + // cleanup dependent consumer groups + if !stopped { + for _, ca := range sa.consumers { + // Make sure we cleanup any possible running nodes for the consumers. + if isMember && ca.Group != nil && ca.Group.node != nil { + ca.Group.node.Delete() + } + os.RemoveAll(filepath.Join(js.config.StoreDir, saccName, defaultStoreDirName, ca.Group.Name)) + } + } + } + } + accDir := filepath.Join(js.config.StoreDir, sa.Client.serviceAccount()) + streamDir := filepath.Join(accDir, streamsDir) + os.RemoveAll(filepath.Join(streamDir, sa.Config.Name)) + + // no op if not empty + os.Remove(streamDir) + os.Remove(accDir) + + // Normally we want only the leader to respond here, but if we had no leader then all members will respond to make + // sure we get feedback to the user. + if !isMember || (hadLeader && !wasLeader) { + // If all the peers are offline and we are the meta leader we will also respond, so suppress returning here. + if !(offline && isMetaLeader) { + return + } + } + + // Do not respond if the account does not exist any longer + if acc == nil || recovering { + return + } + + if err != nil { + resp.Error = NewJSStreamGeneralError(err, Unless(err)) + s.sendAPIErrResponse(sa.Client, acc, sa.Subject, sa.Reply, _EMPTY_, s.jsonResponse(resp)) + } else { + resp.Success = true + s.sendAPIResponse(sa.Client, acc, sa.Subject, sa.Reply, _EMPTY_, s.jsonResponse(resp)) + } +} + +// processConsumerAssignment is called when followers have replicated an assignment for a consumer. +func (js *jetStream) processConsumerAssignment(ca *consumerAssignment) { + js.mu.RLock() + s, cc := js.srv, js.cluster + accName, stream, consumerName := ca.Client.serviceAccount(), ca.Stream, ca.Name + noMeta := cc == nil || cc.meta == nil + shuttingDown := js.shuttingDown + var ourID string + if !noMeta { + ourID = cc.meta.ID() + } + var isMember bool + if ca.Group != nil && ourID != _EMPTY_ { + isMember = ca.Group.isMember(ourID) + } + js.mu.RUnlock() + + if s == nil || noMeta || shuttingDown { + return + } + + js.mu.Lock() + sa := js.streamAssignment(accName, stream) + if sa == nil { + js.mu.Unlock() + s.Debugf("Consumer create failed, could not locate stream '%s > %s'", accName, stream) + return + } + + // Might need this below. + numReplicas := sa.Config.Replicas + + // Track if this existed already. + var wasExisting bool + + // Check if we have an existing consumer assignment. + if sa.consumers == nil { + sa.consumers = make(map[string]*consumerAssignment) + } else if oca := sa.consumers[ca.Name]; oca != nil { + wasExisting = true + // Copy over private existing state from former CA. + if ca.Group != nil { + ca.Group.node = oca.Group.node + } + ca.responded = oca.responded + ca.err = oca.err + + // Unsubscribe if it was previously unsupported. + if oca.unsupported != nil { + oca.unsupported.closeInfoSub(s) + // If we've seen unsupported once, it remains for the lifetime of this server process. + if ca.unsupported == nil { + ca.unsupported = oca.unsupported + } + } + } + + // Capture the optional state. We will pass it along if we are a member to apply. + // This is only applicable when restoring a stream with consumers. + state := ca.State + ca.State = nil + + // Place into our internal map under the stream assignment. + // Ok to replace an existing one, we check on process call below. + sa.consumers[ca.Name] = ca + ca.pending = false + + // If unsupported, we can't register any further. + if ca.unsupported != nil { + ca.unsupported.setupInfoSub(s, ca) + s.Warnf("Detected unsupported consumer '%s > %s > %s': %s", accName, stream, ca.Name, ca.unsupported.reason) + + // Mark stream as unsupported as well + if sa.unsupported == nil { + sa.unsupported = newUnsupportedStreamAssignment(s, sa, fmt.Errorf("unsupported consumer %q", ca.Name)) + } + sa.unsupported.setupInfoSub(s, sa) + js.mu.Unlock() + + // Be conservative by protecting the whole stream, even if just one consumer is unsupported. + // This ensures it's safe, even with Interest-based retention where it would otherwise + // continue accepting but dropping messages. + acc, err := s.LookupAccount(accName) + if err != nil { + return + } + mset, err := acc.lookupStream(stream) + if err != nil || mset.closed.Load() { + return + } + s.Warnf("Stopping unsupported stream '%s > %s'", accName, stream) + mset.stop(false, false) + return + } + js.mu.Unlock() + + acc, err := s.LookupAccount(accName) + if err != nil { + ll := fmt.Sprintf("Account [%s] lookup for consumer create failed: %v", accName, err) + if isMember { + if !js.isMetaRecovering() { + // If we can not lookup the account and we are a member, send this result back to the metacontroller leader. + result := &consumerAssignmentResult{ + Account: accName, + Stream: stream, + Consumer: consumerName, + Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}}, + } + result.Response.Error = NewJSNoAccountError() + s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result) + } + s.Warnf(ll) + } else { + s.Debugf(ll) + } + return + } + + // Check if this is for us.. + if isMember { + js.processClusterCreateConsumer(ca, state, wasExisting) + } else { + // We need to be removed here, we are no longer assigned. + // Grab consumer if we have it. + var o *consumer + if mset, _ := acc.lookupStream(sa.Config.Name); mset != nil { + o = mset.lookupConsumer(ca.Name) + } + + // Check if we have a raft node running, meaning we are no longer part of the group but were. + js.mu.Lock() + if node := ca.Group.node; node != nil { + // We have one here even though we are not a member. This can happen on re-assignment. + s.Debugf("JetStream removing consumer '%s > %s > %s' from this server", sa.Client.serviceAccount(), sa.Config.Name, ca.Name) + if node.Leader() { + s.Debugf("JetStream consumer '%s > %s > %s' is being removed and was the leader, will perform stepdown", + sa.Client.serviceAccount(), sa.Config.Name, ca.Name) + + peers, cn := node.Peers(), s.cachedClusterName() + migrating := numReplicas != len(peers) + + // Select a new peer to transfer to. If we are a migrating make sure its from the new cluster. + var npeer string + for _, r := range peers { + if !r.Current { + continue + } + if !migrating { + npeer = r.ID + break + } else if sir, ok := s.nodeToInfo.Load(r.ID); ok && sir != nil { + si := sir.(nodeInfo) + if si.cluster != cn { + npeer = r.ID + break + } + } + } + // Clear the raftnode from our consumer so that a subsequent o.delete will not also issue a stepdown. + if o != nil { + o.clearRaftNode() + } + // Manually handle the stepdown and deletion of the node. + node.UpdateKnownPeers(ca.Group.Peers) + node.StepDown(npeer) + node.Delete() + } else { + node.UpdateKnownPeers(ca.Group.Peers) + } + } + // Always clear the old node. + ca.Group.node = nil + ca.err = nil + js.mu.Unlock() + + if o != nil { + o.deleteWithoutAdvisory() + } + } +} + +func (js *jetStream) processConsumerRemoval(ca *consumerAssignment) { + js.mu.Lock() + s, cc := js.srv, js.cluster + if s == nil || cc == nil || cc.meta == nil { + // TODO(dlc) - debug at least + js.mu.Unlock() + return + } + + wasLeader := cc.isConsumerLeader(ca.Client.serviceAccount(), ca.Stream, ca.Name) + + // Delete from our state. + var needDelete bool + if accStreams := cc.streams[ca.Client.serviceAccount()]; accStreams != nil { + if sa := accStreams[ca.Stream]; sa != nil && sa.consumers != nil && sa.consumers[ca.Name] != nil { + oca := sa.consumers[ca.Name] + // Make sure this removal is for what we have, otherwise ignore. + if ca.Group != nil && oca.Group != nil && ca.Group.Name == oca.Group.Name { + needDelete = true + oca.deleted = true + delete(sa.consumers, ca.Name) + // Remember we used to be unsupported, just so we can send a successful delete response. + if ca.unsupported == nil { + ca.unsupported = oca.unsupported + } + } + } + } + js.mu.Unlock() + + if needDelete { + js.processClusterDeleteConsumer(ca, wasLeader) + } +} + +type consumerAssignmentResult struct { + Account string `json:"account"` + Stream string `json:"stream"` + Consumer string `json:"consumer"` + Response *JSApiConsumerCreateResponse `json:"response,omitempty"` +} + +// processClusterCreateConsumer is when we are a member of the group and need to create the consumer. +func (js *jetStream) processClusterCreateConsumer(ca *consumerAssignment, state *ConsumerState, wasExisting bool) { + if ca == nil { + return + } + js.mu.RLock() + s := js.srv + rg := ca.Group + alreadyRunning := rg != nil && rg.node != nil + accName, stream, consumer := ca.Client.serviceAccount(), ca.Stream, ca.Name + js.mu.RUnlock() + + acc, err := s.LookupAccount(accName) + if err != nil { + s.Warnf("JetStream cluster failed to lookup axccount %q: %v", accName, err) + return + } + + // Go ahead and create or update the consumer. + mset, err := acc.lookupStream(stream) + if err != nil { + if !js.isMetaRecovering() { + js.mu.Lock() + s.Warnf("Consumer create failed, could not locate stream '%s > %s > %s'", ca.Client.serviceAccount(), ca.Stream, ca.Name) + ca.err = NewJSStreamNotFoundError() + result := &consumerAssignmentResult{ + Account: ca.Client.serviceAccount(), + Stream: ca.Stream, + Consumer: ca.Name, + Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}}, + } + result.Response.Error = NewJSStreamNotFoundError() + s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result) + js.mu.Unlock() + } + return + } + + // Check if we already have this consumer running. + o := mset.lookupConsumer(consumer) + + // Process the raft group and make sure it's running if needed. + storage := mset.config().Storage + if ca.Config.MemoryStorage { + storage = MemoryStorage + } + // No-op if R1. + js.createRaftGroup(accName, rg, storage, pprofLabels{ + "type": "consumer", + "account": mset.accName(), + "stream": ca.Stream, + "consumer": ca.Name, + }) + + // Check if we already have this consumer running. + var didCreate, isConfigUpdate, needsLocalResponse bool + if o == nil { + // Add in the consumer if needed. + if o, err = mset.addConsumerWithAssignment(ca.Config, ca.Name, ca, js.isMetaRecovering(), ActionCreateOrUpdate, false); err == nil { + didCreate = true + } + } else { + // This consumer exists. + // Only update if config is really different. + cfg := o.config() + if isConfigUpdate = !reflect.DeepEqual(&cfg, ca.Config); isConfigUpdate { + // Call into update, ignore consumer exists error here since this means an old deliver subject is bound + // which can happen on restart etc. + // JS lock needed as this can mutate the consumer assignments and race with updateInactivityThreshold. + js.mu.Lock() + err := o.updateConfig(ca.Config) + js.mu.Unlock() + if err != nil && err != NewJSConsumerNameExistError() { + // This is essentially an update that has failed. Respond back to metaleader if we are not recovering. + js.mu.RLock() + if !js.metaRecovering { + result := &consumerAssignmentResult{ + Account: accName, + Stream: stream, + Consumer: consumer, + Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}}, + } + result.Response.Error = NewJSConsumerNameExistError() + s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result) + } + s.Warnf("Consumer create failed during update for '%s > %s > %s': %v", ca.Client.serviceAccount(), ca.Stream, ca.Name, err) + js.mu.RUnlock() + return + } + } + + var sendState bool + js.mu.RLock() + n := rg.node + // Check if we already had a consumer assignment and its still pending. + cca, oca := ca, o.consumerAssignment() + if oca != nil { + if !oca.responded { + // We can't override info for replying here otherwise leader once elected can not respond. + // So copy over original client and the reply from the old ca. + cac := *ca + cac.Client = oca.Client + cac.Reply = oca.Reply + cca = &cac + needsLocalResponse = true + } + // If we look like we are scaling up, let's send our current state to the group. + sendState = len(ca.Group.Peers) > len(oca.Group.Peers) && o.IsLeader() && n != nil + // Signal that this is an update + if ca.Reply != _EMPTY_ { + isConfigUpdate = true + } + } + js.mu.RUnlock() + + if sendState { + if snap, err := o.store.EncodedState(); err == nil { + n.SendSnapshot(snap) + } + } + + // Set CA for our consumer. + o.setConsumerAssignment(cca) + s.Debugf("JetStream cluster, consumer '%s > %s > %s' was already running", ca.Client.serviceAccount(), ca.Stream, ca.Name) + } + + // If we have an initial state set apply that now. + if state != nil && o != nil { + o.mu.Lock() + err = o.setStoreState(state) + o.mu.Unlock() + } + + if err != nil { + // If we're shutting down we could get a variety of errors. + // Normally we can continue and delete state, but need to be careful when shutting down. + if js.isShuttingDown() { + s.Debugf("Could not create consumer, JetStream shutting down") + return + } + + if IsNatsErr(err, JSConsumerStoreFailedErrF) { + s.Warnf("Consumer create failed for '%s > %s > %s': %v", ca.Client.serviceAccount(), ca.Stream, ca.Name, err) + err = errConsumerStoreFailed + } + + js.mu.Lock() + + ca.err = err + hasResponded := ca.responded + + // If out of space do nothing for now. + if isOutOfSpaceErr(err) { + hasResponded = true + } + + if rg.node != nil { + rg.node.Delete() + // Clear the node here. + rg.node = nil + } + + // If we did seem to create a consumer make sure to stop it. + if o != nil { + o.stop() + } + + var result *consumerAssignmentResult + if !hasResponded && !js.metaRecovering { + result = &consumerAssignmentResult{ + Account: ca.Client.serviceAccount(), + Stream: ca.Stream, + Consumer: ca.Name, + Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}}, + } + result.Response.Error = NewJSConsumerCreateError(err, Unless(err)) + } else if err == errNoInterest { + // This is a stranded ephemeral, let's clean this one up. + subject := fmt.Sprintf(JSApiConsumerDeleteT, ca.Stream, ca.Name) + mset.outq.send(newJSPubMsg(subject, _EMPTY_, _EMPTY_, nil, nil, nil, 0)) + } + js.mu.Unlock() + + if result != nil { + // Send response to the metadata leader. They will forward to the user as needed. + b, _ := json.Marshal(result) // Avoids auto-processing and doing fancy json with newlines. + s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, b) + } + } else { + js.mu.RLock() + node := rg.node + js.mu.RUnlock() + + if didCreate { + o.setCreatedTime(ca.Created) + } else { + // Check for scale down to 1.. + if node != nil && len(rg.Peers) == 1 { + o.clearNode() + o.setLeader(true) + // Need to clear from rg too. + js.mu.Lock() + rg.node = nil + client, subject, reply := ca.Client, ca.Subject, ca.Reply + js.mu.Unlock() + var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}} + resp.ConsumerInfo = setDynamicConsumerInfoMetadata(o.info()) + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + return + } + } + + if node == nil { + // Single replica consumer, process manually here. + js.mu.Lock() + // Force response in case we think this is an update. + if !js.metaRecovering && isConfigUpdate { + ca.responded = false + } + js.mu.Unlock() + js.processConsumerLeaderChange(o, true) + } else { + // Clustered consumer. + // Start our monitoring routine if needed. + if !alreadyRunning && o.shouldStartMonitor() { + started := s.startGoRoutine( + func() { js.monitorConsumer(o, ca) }, + pprofLabels{ + "type": "consumer", + "account": mset.accName(), + "stream": mset.name(), + "consumer": ca.Name, + }, + ) + if !started { + o.clearMonitorRunning() + } + } + // For existing consumer, only send response if not recovering. + if wasExisting && !js.isMetaRecovering() { + if o.IsLeader() || (!didCreate && needsLocalResponse) { + // Process if existing as an update. Double check that this is not recovered. + js.mu.RLock() + client, subject, reply, recovering := ca.Client, ca.Subject, ca.Reply, ca.recovering + js.mu.RUnlock() + if !recovering { + var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}} + resp.ConsumerInfo = setDynamicConsumerInfoMetadata(o.info()) + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + } + } + } + } + } +} + +func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, wasLeader bool) { + if ca == nil { + return + } + js.mu.RLock() + s := js.srv + node := ca.Group.node + offline := s.allPeersOffline(ca.Group) || ca.unsupported != nil + var isMetaLeader bool + if cc := js.cluster; cc != nil { + isMetaLeader = cc.isLeader() + } + recovering := ca.recovering + js.mu.RUnlock() + + stopped := false + var resp = JSApiConsumerDeleteResponse{ApiResponse: ApiResponse{Type: JSApiConsumerDeleteResponseType}} + var err error + var acc *Account + + // Go ahead and delete the consumer if we have it and the account. + if acc, _ = s.LookupAccount(ca.Client.serviceAccount()); acc != nil { + if mset, _ := acc.lookupStream(ca.Stream); mset != nil { + if o := mset.lookupConsumer(ca.Name); o != nil { + err = o.stopWithFlags(true, false, true, wasLeader) + stopped = true + } + } + } + + // Always delete the node if present. + if node != nil { + node.Delete() + } + + // This is a stop gap cleanup in case + // 1) the account, mset, or consumer does not exist and/or + // 2) node was nil (and couldn't be deleted) + if !stopped || node == nil { + if sacc := s.SystemAccount(); sacc != nil { + os.RemoveAll(filepath.Join(js.config.StoreDir, sacc.GetName(), defaultStoreDirName, ca.Group.Name)) + } + } + + accDir := filepath.Join(js.config.StoreDir, ca.Client.serviceAccount()) + consumersDir := filepath.Join(accDir, streamsDir, ca.Stream, consumerDir) + os.RemoveAll(filepath.Join(consumersDir, ca.Name)) + + if !wasLeader || ca.Reply == _EMPTY_ { + if !(offline && isMetaLeader) { + return + } + } + + // Do not respond if the account does not exist any longer or this is during recovery. + if acc == nil || recovering { + return + } + + if err != nil { + resp.Error = NewJSStreamNotFoundError(Unless(err)) + s.sendAPIErrResponse(ca.Client, acc, ca.Subject, ca.Reply, _EMPTY_, s.jsonResponse(resp)) + } else { + resp.Success = true + s.sendAPIResponse(ca.Client, acc, ca.Subject, ca.Reply, _EMPTY_, s.jsonResponse(resp)) + } +} + +// Returns the consumer assignment, or nil if not present. +// Lock should be held. +func (js *jetStream) consumerAssignment(account, stream, consumer string) *consumerAssignment { + if sa := js.streamAssignment(account, stream); sa != nil { + return sa.consumers[consumer] + } + return nil +} + +// consumerAssigned informs us if this server has this consumer assigned. +func (jsa *jsAccount) consumerAssigned(stream, consumer string) bool { + jsa.mu.RLock() + js, acc := jsa.js, jsa.account + jsa.mu.RUnlock() + + if js == nil { + return false + } + js.mu.RLock() + defer js.mu.RUnlock() + return js.cluster.isConsumerAssigned(acc, stream, consumer) +} + +// Read lock should be held. +func (cc *jetStreamCluster) isConsumerAssigned(a *Account, stream, consumer string) bool { + // Non-clustered mode always return true. + if cc == nil { + return true + } + if cc.meta == nil { + return false + } + var sa *streamAssignment + accStreams := cc.streams[a.Name] + if accStreams != nil { + sa = accStreams[stream] + } + if sa == nil { + // TODO(dlc) - This should not happen. + return false + } + ca := sa.consumers[consumer] + if ca == nil { + return false + } + return ca.Group.isMember(cc.meta.ID()) +} + +// Returns our stream and underlying raft node. +func (o *consumer) streamAndNode() (*stream, RaftNode) { + if o == nil { + return nil, nil + } + o.mu.RLock() + defer o.mu.RUnlock() + return o.mset, o.node +} + +// Return the replica count for this consumer. If the consumer has been +// stopped, this will return an error. +func (o *consumer) replica() (int, error) { + o.mu.RLock() + oCfg := o.cfg + mset := o.mset + o.mu.RUnlock() + if mset == nil { + return 0, errBadConsumer + } + sCfg := mset.config() + return oCfg.replicas(&sCfg), nil +} + +func (o *consumer) raftGroup() *raftGroup { + if o == nil { + return nil + } + o.mu.RLock() + defer o.mu.RUnlock() + if o.ca == nil { + return nil + } + return o.ca.Group +} + +func (o *consumer) clearRaftNode() { + if o == nil { + return + } + o.mu.Lock() + defer o.mu.Unlock() + o.node = nil +} + +func (o *consumer) raftNode() RaftNode { + if o == nil { + return nil + } + o.mu.RLock() + defer o.mu.RUnlock() + return o.node +} + +func (js *jetStream) monitorConsumer(o *consumer, ca *consumerAssignment) { + s, n, meta := js.server(), o.raftNode(), js.getMetaGroup() + defer s.grWG.Done() + + defer o.clearMonitorRunning() + + if n == nil || meta == nil { + s.Warnf("No RAFT group for '%s > %s > %s'", o.acc.Name, ca.Stream, ca.Name) + return + } + + // Make sure to stop the raft group on exit to prevent accidental memory bloat. + // This should be below the checkInMonitor call though to avoid stopping it out + // from underneath the one that is running since it will be the same raft node. + defer n.Stop() + + qch, mqch, lch, aq, uch, ourPeerId := n.QuitC(), o.monitorQuitC(), n.LeadChangeC(), n.ApplyQ(), o.updateC(), meta.ID() + + s.Debugf("Starting consumer monitor for '%s > %s > %s' [%s]", o.acc.Name, ca.Stream, ca.Name, n.Group()) + defer s.Debugf("Exiting consumer monitor for '%s > %s > %s' [%s]", o.acc.Name, ca.Stream, ca.Name, n.Group()) + + const ( + compactInterval = 2 * time.Minute + compactSizeMin = 64 * 1024 // What is stored here is always small for consumers. + compactNumMin = 1024 + minSnapDelta = 10 * time.Second + ) + + // Spread these out for large numbers on server restart. + rci := time.Duration(rand.Int63n(int64(time.Minute))) + t := time.NewTicker(compactInterval + rci) + defer t.Stop() + + // Highwayhash key for generating hashes. + key := make([]byte, 32) + crand.Read(key) + + // Hash of the last snapshot (fixed size in memory). + var lastSnap []byte + var lastSnapTime time.Time + + // Don't allow the upper layer to install snapshots until we have + // fully recovered from disk. + recovering := true + + doSnapshot := func(force bool) { + // Bail if trying too fast and not in a forced situation. + if recovering || (!force && time.Since(lastSnapTime) < minSnapDelta) { + return + } + + // Check several things to see if we need a snapshot. + ne, nb := n.Size() + if !n.NeedSnapshot() { + // Check if we should compact etc. based on size of log. + if !force && ne < compactNumMin && nb < compactSizeMin { + return + } + } + + if snap, err := o.store.EncodedState(); err == nil { + hash := highwayhash.Sum(snap, key) + // If the state hasn't changed but the log has gone way over + // the compaction size then we will want to compact anyway. + // This can happen for example when a pull consumer fetches a + // lot on an idle stream, log entries get distributed but the + // state never changes, therefore the log never gets compacted. + if !bytes.Equal(hash[:], lastSnap) || ne >= compactNumMin || nb >= compactSizeMin { + if err := n.InstallSnapshot(snap); err == nil { + lastSnap, lastSnapTime = hash[:], time.Now() + } else if err != errNoSnapAvailable && err != errNodeClosed && err != errCatchupsRunning { + s.RateLimitWarnf("Failed to install snapshot for '%s > %s > %s' [%s]: %v", o.acc.Name, ca.Stream, ca.Name, n.Group(), err) + } + } + } + } + + // For migration tracking. + var mmt *time.Ticker + var mmtc <-chan time.Time + + startMigrationMonitoring := func() { + if mmt == nil { + mmt = time.NewTicker(500 * time.Millisecond) + mmtc = mmt.C + } + } + + stopMigrationMonitoring := func() { + if mmt != nil { + mmt.Stop() + mmt, mmtc = nil, nil + } + } + defer stopMigrationMonitoring() + + // Track if we are leader. + var isLeader bool + + for { + select { + case <-s.quitCh: + // Server shutting down, but we might receive this before qch, so try to snapshot. + doSnapshot(false) + return + case <-mqch: + // Clean signal from shutdown routine so do best effort attempt to snapshot. + // Don't snapshot if not shutting down, monitor goroutine could be going away + // on a scale down or a remove for example. + if s.isShuttingDown() { + doSnapshot(false) + } + return + case <-qch: + // Clean signal from shutdown routine so do best effort attempt to snapshot. + // Don't snapshot if not shutting down, Raft node could be going away on a + // scale down or remove for example. + if s.isShuttingDown() { + doSnapshot(false) + } + return + case <-aq.ch: + ces := aq.pop() + for _, ce := range ces { + // No special processing needed for when we are caught up on restart. + if ce == nil { + recovering = false + if n.NeedSnapshot() { + doSnapshot(true) + } + continue + } + if err := js.applyConsumerEntries(o, ce, isLeader); err == nil { + var ne, nb uint64 + // We can't guarantee writes are flushed while we're shutting down. Just rely on replay during recovery. + if !js.isShuttingDown() { + ne, nb = n.Applied(ce.Index) + } + // If we have at least min entries to compact, go ahead and snapshot/compact. + if nb > 0 && ne >= compactNumMin || nb > compactSizeMin { + doSnapshot(false) + } + } else if err != errConsumerClosed { + s.Warnf("Error applying consumer entries to '%s > %s'", ca.Client.serviceAccount(), ca.Name) + } + ce.ReturnToPool() + } + aq.recycle(&ces) + + case isLeader = <-lch: + if recovering && !isLeader { + js.setConsumerAssignmentRecovering(ca) + } + + // Process the change. + if err := js.processConsumerLeaderChange(o, isLeader); err == nil { + // Check our state if we are under an interest based stream. + if mset := o.getStream(); mset != nil { + var ss StreamState + mset.store.FastState(&ss) + o.checkStateForInterestStream(&ss) + } + } + + // We may receive a leader change after the consumer assignment which would cancel us + // monitoring for this closely. So re-assess our state here as well. + // Or the old leader is no longer part of the set and transferred leadership + // for this leader to resume with removal + rg := o.raftGroup() + + // Check for migrations (peer count and replica count differ) here. + // We set the state on the stream assignment update below. + replicas, err := o.replica() + if err != nil { + continue + } + if isLeader && len(rg.Peers) != replicas { + startMigrationMonitoring() + } else { + stopMigrationMonitoring() + } + case <-uch: + // keep consumer assignment current + ca = o.consumerAssignment() + // We get this when we have a new consumer assignment caused by an update. + // We want to know if we are migrating. + rg := o.raftGroup() + // If we are migrating, monitor for the new peers to be caught up. + replicas, err := o.replica() + if err != nil { + continue + } + if isLeader && len(rg.Peers) != replicas { + startMigrationMonitoring() + } else { + stopMigrationMonitoring() + } + case <-mmtc: + if !isLeader { + // We are no longer leader, so not our job. + stopMigrationMonitoring() + continue + } + rg := o.raftGroup() + ci := js.clusterInfo(rg) + replicas, err := o.replica() + if err != nil { + continue + } + if len(rg.Peers) <= replicas { + // Migration no longer happening, so not our job anymore + stopMigrationMonitoring() + continue + } + newPeers, oldPeers, newPeerSet, _ := genPeerInfo(rg.Peers, len(rg.Peers)-replicas) + + // If we are part of the new peerset and we have been passed the baton. + // We will handle scale down. + if newPeerSet[ourPeerId] { + for _, p := range oldPeers { + n.ProposeRemovePeer(p) + } + cca := ca.copyGroup() + cca.Group.Peers = newPeers + cca.Group.Cluster = s.cachedClusterName() + meta.ForwardProposal(encodeAddConsumerAssignment(cca)) + s.Noticef("Scaling down '%s > %s > %s' to %+v", ca.Client.serviceAccount(), ca.Stream, ca.Name, s.peerSetToNames(newPeers)) + + } else { + var newLeaderPeer, newLeader, newCluster string + neededCurrent, current := replicas/2+1, 0 + for _, r := range ci.Replicas { + if r.Current && newPeerSet[r.Peer] { + current++ + if newCluster == _EMPTY_ { + newLeaderPeer, newLeader, newCluster = r.Peer, r.Name, r.cluster + } + } + } + + // Check if we have a quorom + if current >= neededCurrent { + s.Noticef("Transfer of consumer leader for '%s > %s > %s' to '%s'", ca.Client.serviceAccount(), ca.Stream, ca.Name, newLeader) + n.StepDown(newLeaderPeer) + } + } + + case <-t.C: + doSnapshot(false) + } + } +} + +func (js *jetStream) applyConsumerEntries(o *consumer, ce *CommittedEntry, isLeader bool) error { + for _, e := range ce.Entries { + if e.Type == EntrySnapshot { + if !isLeader { + // No-op needed? + state, err := decodeConsumerState(e.Data) + if err != nil { + if mset, node := o.streamAndNode(); mset != nil && node != nil { + s := js.srv + s.Errorf("JetStream cluster could not decode consumer snapshot for '%s > %s > %s' [%s]", + mset.account(), mset.name(), o, node.Group()) + } + panic(err.Error()) + } + + if err = o.store.Update(state); err != nil { + o.mu.RLock() + s, acc, mset, name := o.srv, o.acc, o.mset, o.name + o.mu.RUnlock() + if s != nil && mset != nil { + s.Warnf("Consumer '%s > %s > %s' error on store update from snapshot entry: %v", acc, mset.name(), name, err) + } + } + // Check our interest state if applicable. + if mset := o.getStream(); mset != nil { + var ss StreamState + mset.store.FastState(&ss) + // We used to register preacks here if our ack floor was higher than the last sequence. + // Now when streams catch up they properly call checkInterestState() and periodically run this as well. + // If our states drift this could have allocated lots of pre-acks. + o.checkStateForInterestStream(&ss) + } + } + + } else if e.Type == EntryRemovePeer { + js.mu.RLock() + var ourID string + if js.cluster != nil && js.cluster.meta != nil { + ourID = js.cluster.meta.ID() + } + js.mu.RUnlock() + if peer := string(e.Data); peer == ourID { + shouldRemove := true + if mset := o.getStream(); mset != nil { + if sa := mset.streamAssignment(); sa != nil && sa.Group != nil { + js.mu.RLock() + shouldRemove = !sa.Group.isMember(ourID) + js.mu.RUnlock() + } + } + if shouldRemove { + o.stopWithFlags(true, false, false, false) + } + } + } else if e.Type == EntryAddPeer { + // Ignore for now. + } else { + buf := e.Data + switch entryOp(buf[0]) { + case updateDeliveredOp: + dseq, sseq, dc, ts, err := decodeDeliveredUpdate(buf[1:]) + if err != nil { + if mset, node := o.streamAndNode(); mset != nil && node != nil { + s := js.srv + s.Errorf("JetStream cluster could not decode consumer delivered update for '%s > %s > %s' [%s]", + mset.account(), mset.name(), o, node.Group()) + } + panic(err.Error()) + } + // Make sure to update delivered under the lock. + o.mu.Lock() + err = o.store.UpdateDelivered(dseq, sseq, dc, ts) + o.ldt = time.Now() + // Need to send message to the client, since we have quorum to do so now. + if pmsg, ok := o.pendingDeliveries[sseq]; ok { + // Copy delivery subject and sequence first, as the send returns it to the pool and clears it. + dsubj, seq := pmsg.dsubj, pmsg.seq + o.outq.send(pmsg) + delete(o.pendingDeliveries, sseq) + + // Might need to send a request timeout after sending the last replicated delivery. + if wd, ok := o.waitingDeliveries[dsubj]; ok && wd.seq == seq { + if wd.pn > 0 || wd.pb > 0 { + hdr := fmt.Appendf(nil, "NATS/1.0 408 Request Timeout\r\n%s: %d\r\n%s: %d\r\n\r\n", JSPullRequestPendingMsgs, wd.pn, JSPullRequestPendingBytes, wd.pb) + o.outq.send(newJSPubMsg(dsubj, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + } + wd.recycle() + delete(o.waitingDeliveries, dsubj) + } + } + o.mu.Unlock() + if err != nil { + panic(err.Error()) + } + case updateAcksOp: + dseq, sseq, err := decodeAckUpdate(buf[1:]) + if err != nil { + if mset, node := o.streamAndNode(); mset != nil && node != nil { + s := js.srv + s.Errorf("JetStream cluster could not decode consumer ack update for '%s > %s > %s' [%s]", + mset.account(), mset.name(), o, node.Group()) + } + panic(err.Error()) + } + if err := o.processReplicatedAck(dseq, sseq); err == errConsumerClosed { + return err + } + case updateSkipOp: + o.mu.Lock() + var le = binary.LittleEndian + sseq := le.Uint64(buf[1:]) + if !o.isLeader() && sseq > o.sseq { + o.sseq = sseq + } + if o.store != nil { + o.store.UpdateStarting(sseq - 1) + } + o.mu.Unlock() + case addPendingRequest: + o.mu.Lock() + if !o.isLeader() { + if o.prm == nil { + o.prm = make(map[string]struct{}) + } + o.prm[string(buf[1:])] = struct{}{} + } + o.mu.Unlock() + case removePendingRequest: + o.mu.Lock() + if !o.isLeader() { + if o.prm != nil { + delete(o.prm, string(buf[1:])) + } + } + o.mu.Unlock() + default: + panic(fmt.Sprintf("JetStream Cluster Unknown group entry op type: %v", entryOp(buf[0]))) + } + } + } + return nil +} + +var errConsumerClosed = errors.New("consumer closed") + +func (o *consumer) processReplicatedAck(dseq, sseq uint64) error { + o.mu.Lock() + // Update activity. + o.lat = time.Now() + + var sagap uint64 + if o.cfg.AckPolicy == AckAll { + // Always use the store state, as o.asflr is skipped ahead already. + // Capture before updating store. + state, err := o.store.BorrowState() + if err == nil { + sagap = sseq - state.AckFloor.Stream + } + } + + // Do actual ack update to store. + // Always do this to have it recorded. + o.store.UpdateAcks(dseq, sseq) + + mset := o.mset + if o.closed || mset == nil { + o.mu.Unlock() + return errConsumerClosed + } + if mset.closed.Load() { + o.mu.Unlock() + return errStreamClosed + } + + // Check if we have a reply that was requested. + if reply := o.replies[sseq]; reply != _EMPTY_ { + o.outq.sendMsg(reply, nil) + delete(o.replies, sseq) + } + + if o.retention == LimitsPolicy { + o.mu.Unlock() + return nil + } + o.mu.Unlock() + + if sagap > 1 { + // FIXME(dlc) - This is very inefficient, will need to fix. + for seq := sseq; seq > sseq-sagap; seq-- { + mset.ackMsg(o, seq) + } + } else { + mset.ackMsg(o, sseq) + } + return nil +} + +var errBadAckUpdate = errors.New("jetstream cluster bad replicated ack update") +var errBadDeliveredUpdate = errors.New("jetstream cluster bad replicated delivered update") + +func decodeAckUpdate(buf []byte) (dseq, sseq uint64, err error) { + var bi, n int + if dseq, n = binary.Uvarint(buf); n < 0 { + return 0, 0, errBadAckUpdate + } + bi += n + if sseq, n = binary.Uvarint(buf[bi:]); n < 0 { + return 0, 0, errBadAckUpdate + } + return dseq, sseq, nil +} + +func decodeDeliveredUpdate(buf []byte) (dseq, sseq, dc uint64, ts int64, err error) { + var bi, n int + if dseq, n = binary.Uvarint(buf); n < 0 { + return 0, 0, 0, 0, errBadDeliveredUpdate + } + bi += n + if sseq, n = binary.Uvarint(buf[bi:]); n < 0 { + return 0, 0, 0, 0, errBadDeliveredUpdate + } + bi += n + if dc, n = binary.Uvarint(buf[bi:]); n < 0 { + return 0, 0, 0, 0, errBadDeliveredUpdate + } + bi += n + if ts, n = binary.Varint(buf[bi:]); n < 0 { + return 0, 0, 0, 0, errBadDeliveredUpdate + } + return dseq, sseq, dc, ts, nil +} + +func (js *jetStream) processConsumerLeaderChange(o *consumer, isLeader bool) error { + stepDownIfLeader := func() error { + if node := o.raftNode(); node != nil && isLeader { + node.StepDown() + } + return errors.New("failed to update consumer leader status") + } + + if o == nil || o.isClosed() { + return stepDownIfLeader() + } + + ca := o.consumerAssignment() + if ca == nil { + return stepDownIfLeader() + } + js.mu.Lock() + s, account, err := js.srv, ca.Client.serviceAccount(), ca.err + client, subject, reply, streamName, consumerName := ca.Client, ca.Subject, ca.Reply, ca.Stream, ca.Name + hasResponded := ca.responded + ca.responded = true + js.mu.Unlock() + + acc, _ := s.LookupAccount(account) + if acc == nil { + return stepDownIfLeader() + } + + if isLeader { + // Only log if the consumer is replicated and/or durable. + // Logging about R1 ephemerals, like KV watchers, is mostly noise since the leader will always be known. + o.mu.RLock() + isReplicated, durable := o.node != nil, o.isDurable() + o.mu.RUnlock() + if isReplicated || durable { + s.Noticef("JetStream cluster new consumer leader for '%s > %s > %s'", ca.Client.serviceAccount(), streamName, consumerName) + } + s.sendConsumerLeaderElectAdvisory(o) + } else { + // We are stepping down. + // Make sure if we are doing so because we have lost quorum that we send the appropriate advisories. + if node := o.raftNode(); node != nil && !node.Quorum() && time.Since(node.Created()) > 5*time.Second { + s.sendConsumerLostQuorumAdvisory(o) + } + } + + // Tell consumer to switch leader status. + o.setLeader(isLeader) + + if !isLeader || hasResponded { + if isLeader { + o.clearInitialInfo() + } + return nil + } + + var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}} + if err != nil { + resp.Error = NewJSConsumerCreateError(err, Unless(err)) + s.sendAPIErrResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + } else { + resp.ConsumerInfo = setDynamicConsumerInfoMetadata(o.initialInfo()) + s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp)) + o.sendCreateAdvisory() + } + + // Only send a pause advisory on consumer create if we're + // actually paused. The timer would have been kicked by now + // by the call to o.setLeader() above. + o.mu.RLock() + if isLeader && o.cfg.PauseUntil != nil && !o.cfg.PauseUntil.IsZero() && time.Now().Before(*o.cfg.PauseUntil) { + o.sendPauseAdvisoryLocked(&o.cfg) + } + o.mu.RUnlock() + + return nil +} + +// Determines if we should send lost quorum advisory. We throttle these after first one. +func (o *consumer) shouldSendLostQuorum() bool { + o.mu.Lock() + defer o.mu.Unlock() + if time.Since(o.lqsent) >= lostQuorumAdvInterval { + o.lqsent = time.Now() + return true + } + return false +} + +func (s *Server) sendConsumerLostQuorumAdvisory(o *consumer) { + if o == nil { + return + } + node, stream, consumer, acc := o.raftNode(), o.streamName(), o.String(), o.account() + if node == nil { + return + } + if !o.shouldSendLostQuorum() { + return + } + + s.Warnf("JetStream cluster consumer '%s > %s > %s' has NO quorum, stalled.", acc.GetName(), stream, consumer) + + subj := JSAdvisoryConsumerQuorumLostPre + "." + stream + "." + consumer + adv := &JSConsumerQuorumLostAdvisory{ + TypedEvent: TypedEvent{ + Type: JSConsumerQuorumLostAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Stream: stream, + Consumer: consumer, + Replicas: s.replicas(node), + Domain: s.getOpts().JetStreamDomain, + } + + // Send to the user's account if not the system account. + if acc != s.SystemAccount() { + s.publishAdvisory(acc, subj, adv) + } + // Now do system level one. Place account info in adv, and nil account means system. + adv.Account = acc.GetName() + s.publishAdvisory(nil, subj, adv) +} + +func (s *Server) sendConsumerLeaderElectAdvisory(o *consumer) { + if o == nil { + return + } + node, stream, consumer, acc := o.raftNode(), o.streamName(), o.String(), o.account() + if node == nil { + return + } + + subj := JSAdvisoryConsumerLeaderElectedPre + "." + stream + "." + consumer + adv := &JSConsumerLeaderElectedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSConsumerLeaderElectedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Stream: stream, + Consumer: consumer, + Leader: s.serverNameForNode(node.GroupLeader()), + Replicas: s.replicas(node), + Domain: s.getOpts().JetStreamDomain, + } + + // Send to the user's account if not the system account. + if acc != s.SystemAccount() { + s.publishAdvisory(acc, subj, adv) + } + // Now do system level one. Place account info in adv, and nil account means system. + adv.Account = acc.GetName() + s.publishAdvisory(nil, subj, adv) +} + +type streamAssignmentResult struct { + Account string `json:"account"` + Stream string `json:"stream"` + Response *JSApiStreamCreateResponse `json:"create_response,omitempty"` + Restore *JSApiStreamRestoreResponse `json:"restore_response,omitempty"` + Update bool `json:"is_update,omitempty"` +} + +// Determine if this is an insufficient resources' error type. +func isInsufficientResourcesErr(resp *JSApiStreamCreateResponse) bool { + return resp != nil && resp.Error != nil && IsNatsErr(resp.Error, JSInsufficientResourcesErr, JSMemoryResourcesExceededErr, JSStorageResourcesExceededErr) +} + +// Process error results of stream and consumer assignments. +// Success will be handled by stream leader. +func (js *jetStream) processStreamAssignmentResults(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + var result streamAssignmentResult + if err := json.Unmarshal(msg, &result); err != nil { + // TODO(dlc) - log + return + } + acc, _ := js.srv.LookupAccount(result.Account) + if acc == nil { + // TODO(dlc) - log + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + s, cc := js.srv, js.cluster + if cc == nil || cc.meta == nil { + return + } + + // This should have been done already in processStreamAssignment, but in + // case we have a code path that gets here with no processStreamAssignment, + // then we will do the proper thing. Otherwise will be a no-op. + cc.removeInflightProposal(result.Account, result.Stream) + + if sa := js.streamAssignment(result.Account, result.Stream); sa != nil && !sa.reassigning { + canDelete := !result.Update && time.Since(sa.Created) < 5*time.Second + + // See if we should retry in case this cluster is full but there are others. + if cfg, ci := sa.Config, sa.Client; cfg != nil && ci != nil && isInsufficientResourcesErr(result.Response) && canDelete { + // If cluster is defined we can not retry. + if cfg.Placement == nil || cfg.Placement.Cluster == _EMPTY_ { + // If we have additional clusters to try we can retry. + // We have already verified that ci != nil. + if len(ci.Alternates) > 0 { + if rg, err := js.createGroupForStream(ci, cfg); err != nil { + s.Warnf("Retrying cluster placement for stream '%s > %s' failed due to placement error: %+v", result.Account, result.Stream, err) + } else { + if org := sa.Group; org != nil && len(org.Peers) > 0 { + s.Warnf("Retrying cluster placement for stream '%s > %s' due to insufficient resources in cluster %q", + result.Account, result.Stream, s.clusterNameForNode(org.Peers[0])) + } else { + s.Warnf("Retrying cluster placement for stream '%s > %s' due to insufficient resources", result.Account, result.Stream) + } + // Pick a new preferred leader. + rg.setPreferred() + // Get rid of previous attempt. + cc.meta.Propose(encodeDeleteStreamAssignment(sa)) + // Propose new. + sa.Group, sa.err = rg, nil + cc.meta.Propose(encodeAddStreamAssignment(sa)) + // When the new stream assignment is processed, sa.reassigning will be + // automatically set back to false. Until then, don't process any more + // assignment results. + sa.reassigning = true + return + } + } + } + } + + // Respond to the user here. + var resp string + if result.Response != nil { + resp = s.jsonResponse(result.Response) + } else if result.Restore != nil { + resp = s.jsonResponse(result.Restore) + } + if !sa.responded || result.Update { + sa.responded = true + js.srv.sendAPIErrResponse(sa.Client, acc, sa.Subject, sa.Reply, _EMPTY_, resp) + } + // Remove this assignment if possible. + if canDelete { + sa.err = NewJSClusterNotAssignedError() + cc.meta.Propose(encodeDeleteStreamAssignment(sa)) + } + } +} + +func (js *jetStream) processConsumerAssignmentResults(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + var result consumerAssignmentResult + if err := json.Unmarshal(msg, &result); err != nil { + // TODO(dlc) - log + return + } + acc, _ := js.srv.LookupAccount(result.Account) + if acc == nil { + // TODO(dlc) - log + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + s, cc := js.srv, js.cluster + if cc == nil || cc.meta == nil { + return + } + + if sa := js.streamAssignment(result.Account, result.Stream); sa != nil && sa.consumers != nil { + if ca := sa.consumers[result.Consumer]; ca != nil && !ca.responded { + js.srv.sendAPIErrResponse(ca.Client, acc, ca.Subject, ca.Reply, _EMPTY_, s.jsonResponse(result.Response)) + ca.responded = true + + // Check if this failed. + // TODO(dlc) - Could have mixed results, should track per peer. + // Make sure this is recent response, do not delete existing consumers. + if result.Response.Error != nil && result.Response.Error != NewJSConsumerNameExistError() && time.Since(ca.Created) < 2*time.Second { + // So while we are deleting we will not respond to list/names requests. + ca.err = NewJSClusterNotAssignedError() + cc.meta.Propose(encodeDeleteConsumerAssignment(ca)) + s.Warnf("Proposing to delete consumer `%s > %s > %s' due to assignment response error: %v", + result.Account, result.Stream, result.Consumer, result.Response.Error) + } + } + } +} + +const ( + streamAssignmentSubj = "$SYS.JSC.STREAM.ASSIGNMENT.RESULT" + consumerAssignmentSubj = "$SYS.JSC.CONSUMER.ASSIGNMENT.RESULT" +) + +// Lock should be held. +func (js *jetStream) startUpdatesSub() { + cc, s, c := js.cluster, js.srv, js.cluster.c + if cc.streamResults == nil { + cc.streamResults, _ = s.systemSubscribe(streamAssignmentSubj, _EMPTY_, false, c, js.processStreamAssignmentResults) + } + if cc.consumerResults == nil { + cc.consumerResults, _ = s.systemSubscribe(consumerAssignmentSubj, _EMPTY_, false, c, js.processConsumerAssignmentResults) + } + if cc.stepdown == nil { + cc.stepdown, _ = s.systemSubscribe(JSApiLeaderStepDown, _EMPTY_, false, c, s.jsLeaderStepDownRequest) + } + if cc.peerRemove == nil { + cc.peerRemove, _ = s.systemSubscribe(JSApiRemoveServer, _EMPTY_, false, c, s.jsLeaderServerRemoveRequest) + } + if cc.peerStreamMove == nil { + cc.peerStreamMove, _ = s.systemSubscribe(JSApiServerStreamMove, _EMPTY_, false, c, s.jsLeaderServerStreamMoveRequest) + } + if cc.peerStreamCancelMove == nil { + cc.peerStreamCancelMove, _ = s.systemSubscribe(JSApiServerStreamCancelMove, _EMPTY_, false, c, s.jsLeaderServerStreamCancelMoveRequest) + } + if js.accountPurge == nil { + js.accountPurge, _ = s.systemSubscribe(JSApiAccountPurge, _EMPTY_, false, c, s.jsLeaderAccountPurgeRequest) + } +} + +// Lock should be held. +func (js *jetStream) stopUpdatesSub() { + cc := js.cluster + if cc.streamResults != nil { + cc.s.sysUnsubscribe(cc.streamResults) + cc.streamResults = nil + } + if cc.consumerResults != nil { + cc.s.sysUnsubscribe(cc.consumerResults) + cc.consumerResults = nil + } + if cc.stepdown != nil { + cc.s.sysUnsubscribe(cc.stepdown) + cc.stepdown = nil + } + if cc.peerRemove != nil { + cc.s.sysUnsubscribe(cc.peerRemove) + cc.peerRemove = nil + } + if cc.peerStreamMove != nil { + cc.s.sysUnsubscribe(cc.peerStreamMove) + cc.peerStreamMove = nil + } + if cc.peerStreamCancelMove != nil { + cc.s.sysUnsubscribe(cc.peerStreamCancelMove) + cc.peerStreamCancelMove = nil + } + if js.accountPurge != nil { + cc.s.sysUnsubscribe(js.accountPurge) + js.accountPurge = nil + } +} + +func (s *Server) sendDomainLeaderElectAdvisory() { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.RLock() + node := cc.meta + js.mu.RUnlock() + + if node == nil { + return + } + + adv := &JSDomainLeaderElectedAdvisory{ + TypedEvent: TypedEvent{ + Type: JSDomainLeaderElectedAdvisoryType, + ID: nuid.Next(), + Time: time.Now().UTC(), + }, + Leader: node.GroupLeader(), + Replicas: s.replicas(node), + Cluster: s.cachedClusterName(), + Domain: s.getOpts().JetStreamDomain, + } + + s.publishAdvisory(nil, JSAdvisoryDomainLeaderElected, adv) +} + +func (js *jetStream) processLeaderChange(isLeader bool) { + if js == nil { + return + } + s := js.srv + if s == nil { + return + } + // Update our server atomic. + s.isMetaLeader.Store(isLeader) + + if isLeader { + s.Noticef("Self is new JetStream cluster metadata leader") + s.sendDomainLeaderElectAdvisory() + } else { + var node string + if meta := js.getMetaGroup(); meta != nil { + node = meta.GroupLeader() + } + if node == _EMPTY_ { + s.Noticef("JetStream cluster no metadata leader") + } else if srv := js.srv.serverNameForNode(node); srv == _EMPTY_ { + s.Noticef("JetStream cluster new remote metadata leader") + } else if clst := js.srv.clusterNameForNode(node); clst == _EMPTY_ { + s.Noticef("JetStream cluster new metadata leader: %s", srv) + } else { + s.Noticef("JetStream cluster new metadata leader: %s/%s", srv, clst) + } + } + + js.mu.Lock() + defer js.mu.Unlock() + + // Clear replies for peer-removes. + js.cluster.peerRemoveReply = nil + + if isLeader { + if meta := js.cluster.meta; meta != nil && meta.IsObserver() { + meta.StepDown() + return + } + } + + if isLeader { + js.startUpdatesSub() + } else { + js.stopUpdatesSub() + // TODO(dlc) - stepdown. + } + + // If we have been signaled to check the streams, this is for a bug that left stream + // assignments with no sync subject after an update and no way to sync/catchup outside of the RAFT layer. + if isLeader && js.cluster.streamsCheck { + cc := js.cluster + for acc, asa := range cc.streams { + for _, sa := range asa { + if sa.unsupported != nil { + continue + } + if sa.Sync == _EMPTY_ { + s.Warnf("Stream assignment corrupt for stream '%s > %s'", acc, sa.Config.Name) + nsa := &streamAssignment{Group: sa.Group, Config: sa.Config, Subject: sa.Subject, Reply: sa.Reply, Client: sa.Client} + nsa.Sync = syncSubjForStream() + cc.meta.Propose(encodeUpdateStreamAssignment(nsa)) + } + } + } + // Clear check. + cc.streamsCheck = false + } +} + +// Lock should be held. +func (cc *jetStreamCluster) remapStreamAssignment(sa *streamAssignment, removePeer string) bool { + // Invoke placement algo passing RG peers that stay (existing) and the peer that is being removed (ignore) + var retain, ignore []string + for _, v := range sa.Group.Peers { + if v == removePeer { + ignore = append(ignore, v) + } else { + retain = append(retain, v) + } + } + + newPeers, placementError := cc.selectPeerGroup(len(sa.Group.Peers), sa.Group.Cluster, sa.Config, retain, 0, ignore) + + if placementError == nil { + sa.Group.Peers = newPeers + // Don't influence preferred leader. + sa.Group.Preferred = _EMPTY_ + return true + } + + // If R1 just return to avoid bricking the stream. + if sa.Group.node == nil || len(sa.Group.Peers) == 1 { + return false + } + + // If we are here let's remove the peer at least, as long as we are R>1 + for i, peer := range sa.Group.Peers { + if peer == removePeer { + sa.Group.Peers[i] = sa.Group.Peers[len(sa.Group.Peers)-1] + sa.Group.Peers = sa.Group.Peers[:len(sa.Group.Peers)-1] + break + } + } + return false +} + +type selectPeerError struct { + excludeTag bool + offline bool + noStorage bool + uniqueTag bool + misc bool + noJsClust bool + noMatchTags map[string]struct{} +} + +func (e *selectPeerError) Error() string { + b := strings.Builder{} + writeBoolErrReason := func(hasErr bool, errMsg string) { + if !hasErr { + return + } + b.WriteString(", ") + b.WriteString(errMsg) + } + b.WriteString("no suitable peers for placement") + writeBoolErrReason(e.offline, "peer offline") + writeBoolErrReason(e.excludeTag, "exclude tag set") + writeBoolErrReason(e.noStorage, "insufficient storage") + writeBoolErrReason(e.uniqueTag, "server tag not unique") + writeBoolErrReason(e.misc, "miscellaneous issue") + writeBoolErrReason(e.noJsClust, "jetstream not enabled in cluster") + if len(e.noMatchTags) != 0 { + b.WriteString(", tags not matched [") + var firstTagWritten bool + for tag := range e.noMatchTags { + if firstTagWritten { + b.WriteString(", ") + } + firstTagWritten = true + b.WriteRune('\'') + b.WriteString(tag) + b.WriteRune('\'') + } + b.WriteString("]") + } + return b.String() +} + +func (e *selectPeerError) addMissingTag(t string) { + if e.noMatchTags == nil { + e.noMatchTags = map[string]struct{}{} + } + e.noMatchTags[t] = struct{}{} +} + +func (e *selectPeerError) accumulate(eAdd *selectPeerError) { + if eAdd == nil { + return + } + acc := func(val *bool, valAdd bool) { + if valAdd { + *val = valAdd + } + } + acc(&e.offline, eAdd.offline) + acc(&e.excludeTag, eAdd.excludeTag) + acc(&e.noStorage, eAdd.noStorage) + acc(&e.uniqueTag, eAdd.uniqueTag) + acc(&e.misc, eAdd.misc) + acc(&e.noJsClust, eAdd.noJsClust) + for tag := range eAdd.noMatchTags { + e.addMissingTag(tag) + } +} + +// selectPeerGroup will select a group of peers to start a raft group. +// when peers exist already the unique tag prefix check for the replaceFirstExisting will be skipped +// js lock should be held. +func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamConfig, existing []string, replaceFirstExisting int, ignore []string) ([]string, *selectPeerError) { + if cluster == _EMPTY_ || cfg == nil { + return nil, &selectPeerError{misc: true} + } + + var maxBytes uint64 + if cfg.MaxBytes > 0 { + maxBytes = uint64(cfg.MaxBytes) + } + + // Check for tags. + var tags []string + if cfg.Placement != nil && len(cfg.Placement.Tags) > 0 { + tags = cfg.Placement.Tags + } + + // Used for weighted sorting based on availability. + type wn struct { + id string + avail uint64 + ha int + ns int + } + + var nodes []wn + // peers is a randomized list + s, peers := cc.s, cc.meta.Peers() + + uniqueTagPrefix := s.getOpts().JetStreamUniqueTag + if uniqueTagPrefix != _EMPTY_ { + for _, tag := range tags { + if strings.HasPrefix(tag, uniqueTagPrefix) { + // disable uniqueness check if explicitly listed in tags + uniqueTagPrefix = _EMPTY_ + break + } + } + } + var uniqueTags = make(map[string]*nodeInfo) + + checkUniqueTag := func(ni *nodeInfo) (bool, *nodeInfo) { + for _, t := range ni.tags { + if strings.HasPrefix(t, uniqueTagPrefix) { + if n, ok := uniqueTags[t]; !ok { + uniqueTags[t] = ni + return true, ni + } else { + return false, n + } + } + } + // default requires the unique prefix to be present + return false, nil + } + + // Map existing. + var ep map[string]struct{} + if le := len(existing); le > 0 { + if le >= r { + return existing[:r], nil + } + ep = make(map[string]struct{}) + for i, p := range existing { + ep[p] = struct{}{} + if uniqueTagPrefix == _EMPTY_ { + continue + } + si, ok := s.nodeToInfo.Load(p) + if !ok || si == nil || i < replaceFirstExisting { + continue + } + ni := si.(nodeInfo) + // collect unique tags, but do not require them as this node is already part of the peerset + checkUniqueTag(&ni) + } + } + + // Map ignore + var ip map[string]struct{} + if li := len(ignore); li > 0 { + ip = make(map[string]struct{}) + for _, p := range ignore { + ip[p] = struct{}{} + } + } + + // Grab the number of streams and HA assets currently assigned to each peer. + // HAAssets under usage is async, so calculate here in realtime based on assignments. + peerStreams := make(map[string]int, len(peers)) + peerHA := make(map[string]int, len(peers)) + for _, asa := range cc.streams { + for _, sa := range asa { + if sa.unsupported != nil { + continue + } + isHA := len(sa.Group.Peers) > 1 + for _, peer := range sa.Group.Peers { + peerStreams[peer]++ + if isHA { + peerHA[peer]++ + } + } + } + } + + maxHaAssets := s.getOpts().JetStreamLimits.MaxHAAssets + + // An error is a result of multiple individual placement decisions. + // Which is why we keep taps on how often which one happened. + err := selectPeerError{} + + // Shuffle them up. + rand.Shuffle(len(peers), func(i, j int) { peers[i], peers[j] = peers[j], peers[i] }) + for _, p := range peers { + si, ok := s.nodeToInfo.Load(p.ID) + if !ok || si == nil { + err.misc = true + continue + } + ni := si.(nodeInfo) + // Only select from the designated named cluster. + if ni.cluster != cluster { + s.Debugf("Peer selection: discard %s@%s reason: not target cluster %s", ni.name, ni.cluster, cluster) + continue + } + + // If we know its offline or we do not have config or err don't consider. + if ni.offline || ni.cfg == nil || ni.stats == nil { + s.Debugf("Peer selection: discard %s@%s reason: offline", ni.name, ni.cluster) + err.offline = true + continue + } + + // If ignore skip + if _, ok := ip[p.ID]; ok { + continue + } + + // If existing also skip, we will add back in to front of the list when done. + if _, ok := ep[p.ID]; ok { + continue + } + + if ni.tags.Contains(jsExcludePlacement) { + s.Debugf("Peer selection: discard %s@%s tags: %v reason: %s present", + ni.name, ni.cluster, ni.tags, jsExcludePlacement) + err.excludeTag = true + continue + } + + if len(tags) > 0 { + matched := true + for _, t := range tags { + if !ni.tags.Contains(t) { + matched = false + s.Debugf("Peer selection: discard %s@%s tags: %v reason: mandatory tag %s not present", + ni.name, ni.cluster, ni.tags, t) + err.addMissingTag(t) + break + } + } + if !matched { + continue + } + } + + var available uint64 + if ni.stats != nil { + switch cfg.Storage { + case MemoryStorage: + used := ni.stats.ReservedMemory + if ni.stats.Memory > used { + used = ni.stats.Memory + } + if ni.cfg.MaxMemory > int64(used) { + available = uint64(ni.cfg.MaxMemory) - used + } + case FileStorage: + used := ni.stats.ReservedStore + if ni.stats.Store > used { + used = ni.stats.Store + } + if ni.cfg.MaxStore > int64(used) { + available = uint64(ni.cfg.MaxStore) - used + } + } + } + + // Otherwise check if we have enough room if maxBytes set. + if maxBytes > 0 && maxBytes > available { + s.Warnf("Peer selection: discard %s@%s (Max Bytes: %d) exceeds available %s storage of %d bytes", + ni.name, ni.cluster, maxBytes, cfg.Storage.String(), available) + err.noStorage = true + continue + } + // HAAssets contain _meta_ which we want to ignore, hence > and not >=. + if maxHaAssets > 0 && ni.stats != nil && ni.stats.HAAssets > maxHaAssets { + s.Warnf("Peer selection: discard %s@%s (HA Asset Count: %d) exceeds max ha asset limit of %d for stream placement", + ni.name, ni.cluster, ni.stats.HAAssets, maxHaAssets) + err.misc = true + continue + } + + if uniqueTagPrefix != _EMPTY_ { + if unique, owner := checkUniqueTag(&ni); !unique { + if owner != nil { + s.Debugf("Peer selection: discard %s@%s tags:%v reason: unique prefix %s owned by %s@%s", + ni.name, ni.cluster, ni.tags, owner.name, owner.cluster) + } else { + s.Debugf("Peer selection: discard %s@%s tags:%v reason: unique prefix %s not present", + ni.name, ni.cluster, ni.tags) + } + err.uniqueTag = true + continue + } + } + // Add to our list of potential nodes. + nodes = append(nodes, wn{p.ID, available, peerHA[p.ID], peerStreams[p.ID]}) + } + + // If we could not select enough peers, fail. + if len(nodes) < (r - len(existing)) { + s.Debugf("Peer selection: required %d nodes but found %d (cluster: %s replica: %d existing: %v/%d peers: %d result-peers: %d err: %+v)", + (r - len(existing)), len(nodes), cluster, r, existing, replaceFirstExisting, len(peers), len(nodes), err) + if len(peers) == 0 { + err.noJsClust = true + } + return nil, &err + } + // Sort based on available from most to least, breaking ties by number of total streams assigned to the peer. + slices.SortFunc(nodes, func(i, j wn) int { + if i.avail == j.avail { + return cmp.Compare(i.ns, j.ns) + } + return -cmp.Compare(i.avail, j.avail) // reverse + }) + // If we are placing a replicated stream, let's sort based on HAAssets, as that is more important to balance. + if cfg.Replicas > 1 { + slices.SortStableFunc(nodes, func(i, j wn) int { return cmp.Compare(i.ha, j.ha) }) + } + + var results []string + if len(existing) > 0 { + results = append(results, existing...) + r -= len(existing) + } + for _, r := range nodes[:r] { + results = append(results, r.id) + } + return results, nil +} + +func groupNameForStream(peers []string, storage StorageType) string { + return groupName("S", peers, storage) +} + +func groupNameForConsumer(peers []string, storage StorageType) string { + return groupName("C", peers, storage) +} + +func groupName(prefix string, peers []string, storage StorageType) string { + gns := getHash(nuid.Next()) + return fmt.Sprintf("%s-R%d%s-%s", prefix, len(peers), storage.String()[:1], gns) +} + +// returns stream count for this tier as well as applicable reservation size (not including cfg) +// jetStream read lock should be held +func tieredStreamAndReservationCount(asa map[string]*streamAssignment, tier string, cfg *StreamConfig) (int, int64) { + var numStreams int + var reservation int64 + for _, sa := range asa { + // Don't count the stream toward the limit if it already exists. + if (tier == _EMPTY_ || isSameTier(sa.Config, cfg)) && sa.Config.Name != cfg.Name { + numStreams++ + if sa.Config.MaxBytes > 0 && sa.Config.Storage == cfg.Storage { + // If tier is empty, all storage is flat and we should adjust for replicas. + // Otherwise if tiered, storage replication already taken into consideration. + if tier == _EMPTY_ && cfg.Replicas > 1 { + reservation += sa.Config.MaxBytes * int64(cfg.Replicas) + } else { + reservation += sa.Config.MaxBytes + } + } + } + } + return numStreams, reservation +} + +// createGroupForStream will create a group for assignment for the stream. +// Lock should be held. +func (js *jetStream) createGroupForStream(ci *ClientInfo, cfg *StreamConfig) (*raftGroup, *selectPeerError) { + replicas := cfg.Replicas + if replicas == 0 { + replicas = 1 + } + + // Default connected cluster from the request origin. + cc, cluster := js.cluster, ci.Cluster + // If specified, override the default. + clusterDefined := cfg.Placement != nil && cfg.Placement.Cluster != _EMPTY_ + if clusterDefined { + cluster = cfg.Placement.Cluster + } + clusters := []string{cluster} + if !clusterDefined { + clusters = append(clusters, ci.Alternates...) + } + + // Need to create a group here. + errs := &selectPeerError{} + for _, cn := range clusters { + peers, err := cc.selectPeerGroup(replicas, cn, cfg, nil, 0, nil) + if len(peers) < replicas { + errs.accumulate(err) + continue + } + return &raftGroup{Name: groupNameForStream(peers, cfg.Storage), Storage: cfg.Storage, Peers: peers, Cluster: cn}, nil + } + return nil, errs +} + +func (acc *Account) selectLimits(replicas int) (*JetStreamAccountLimits, string, *jsAccount, *ApiError) { + // Grab our jetstream account info. + acc.mu.RLock() + jsa := acc.js + acc.mu.RUnlock() + + if jsa == nil { + return nil, _EMPTY_, nil, NewJSNotEnabledForAccountError() + } + + jsa.usageMu.RLock() + selectedLimits, tierName, ok := jsa.selectLimits(replicas) + jsa.usageMu.RUnlock() + + if !ok { + return nil, _EMPTY_, nil, NewJSNoLimitsError() + } + return &selectedLimits, tierName, jsa, nil +} + +// Read lock needs to be held +func (js *jetStream) jsClusteredStreamLimitsCheck(acc *Account, cfg *StreamConfig) *ApiError { + var replicas int + if cfg != nil { + replicas = cfg.Replicas + } + selectedLimits, tier, _, apiErr := acc.selectLimits(replicas) + if apiErr != nil { + return apiErr + } + + asa := js.cluster.streams[acc.Name] + numStreams, reservations := tieredStreamAndReservationCount(asa, tier, cfg) + // Check for inflight proposals... + if cc := js.cluster; cc != nil && cc.inflight != nil { + streams := cc.inflight[acc.Name] + numStreams += len(streams) + // If inflight contains the same stream, don't count toward exceeding maximum. + if cfg != nil { + if _, ok := streams[cfg.Name]; ok { + numStreams-- + } + } + } + if selectedLimits.MaxStreams > 0 && numStreams >= selectedLimits.MaxStreams { + return NewJSMaximumStreamsLimitError() + } + // Check for account limits here before proposing. + if err := js.checkAccountLimits(selectedLimits, cfg, reservations); err != nil { + return NewJSStreamLimitsError(err, Unless(err)) + } + return nil +} + +func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject, reply string, rmsg []byte, config *StreamConfigRequest) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + var resp = JSApiStreamCreateResponse{ApiResponse: ApiResponse{Type: JSApiStreamCreateResponseType}} + + ccfg, apiErr := s.checkStreamCfg(&config.StreamConfig, acc, config.Pedantic) + if apiErr != nil { + resp.Error = apiErr + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + cfg := &ccfg + + // Now process the request and proposal. + js.mu.Lock() + defer js.mu.Unlock() + + var self *streamAssignment + var rg *raftGroup + var syncSubject string + + // Capture if we have existing assignment first. + if osa := js.streamAssignment(acc.Name, cfg.Name); osa != nil { + copyStreamMetadata(cfg, osa.Config) + if !reflect.DeepEqual(osa.Config, cfg) { + resp.Error = NewJSStreamNameExistError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // This is an equal assignment. + self, rg, syncSubject = osa, osa.Group, osa.Sync + } + + if cfg.Sealed { + resp.Error = NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for create can not be sealed")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Check for subject collisions here. + if cc.subjectsOverlap(acc.Name, cfg.Subjects, self) { + resp.Error = NewJSStreamSubjectOverlapError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + apiErr = js.jsClusteredStreamLimitsCheck(acc, cfg) + // Check for stream limits here before proposing. These need to be tracked from meta layer, not jsa. + if apiErr != nil { + resp.Error = apiErr + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Make sure inflight is setup properly. + if cc.inflight == nil { + cc.inflight = make(map[string]map[string]*inflightInfo) + } + streams, ok := cc.inflight[acc.Name] + if !ok { + streams = make(map[string]*inflightInfo) + cc.inflight[acc.Name] = streams + } + + // Raft group selection and placement. + if rg == nil { + // Check inflight before proposing in case we have an existing inflight proposal. + if existing, ok := streams[cfg.Name]; ok { + if !reflect.DeepEqual(existing.cfg, cfg) { + resp.Error = NewJSStreamNameExistError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // We have existing for same stream. Re-use same group and syncSubject. + rg, syncSubject = existing.rg, existing.sync + } + } + // Create a new one here if needed. + if rg == nil { + nrg, err := js.createGroupForStream(ci, cfg) + if err != nil { + resp.Error = NewJSClusterNoPeersError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + rg = nrg + // Pick a preferred leader. + rg.setPreferred() + } + + if syncSubject == _EMPTY_ { + syncSubject = syncSubjForStream() + } + // Sync subject for post snapshot sync. + sa := &streamAssignment{Group: rg, Sync: syncSubject, Config: cfg, Subject: subject, Reply: reply, Client: ci, Created: time.Now().UTC()} + if err := cc.meta.Propose(encodeAddStreamAssignment(sa)); err == nil { + // On success, add this as an inflight proposal so we can apply limits + // on concurrent create requests while this stream assignment has + // possibly not been processed yet. + if streams, ok := cc.inflight[acc.Name]; ok && self == nil { + streams[cfg.Name] = &inflightInfo{rg, syncSubject, cfg} + } + } +} + +var ( + errReqTimeout = errors.New("timeout while waiting for response") + errReqSrvExit = errors.New("server shutdown while waiting for response") +) + +// blocking utility call to perform requests on the system account +// returns (synchronized) v or error +func sysRequest[T any](s *Server, subjFormat string, args ...any) (*T, error) { + isubj := fmt.Sprintf(subjFormat, args...) + + s.mu.Lock() + if s.sys == nil { + s.mu.Unlock() + return nil, ErrNoSysAccount + } + inbox := s.newRespInbox() + results := make(chan *T, 1) + s.sys.replies[inbox] = func(_ *subscription, _ *client, _ *Account, _, _ string, msg []byte) { + var v T + if err := json.Unmarshal(msg, &v); err != nil { + s.Warnf("Error unmarshalling response for request '%s':%v", isubj, err) + return + } + select { + case results <- &v: + default: + s.Warnf("Failed placing request response on internal channel") + } + } + s.mu.Unlock() + + s.sendInternalMsgLocked(isubj, inbox, nil, nil) + + defer func() { + s.mu.Lock() + defer s.mu.Unlock() + if s.sys != nil && s.sys.replies != nil { + delete(s.sys.replies, inbox) + } + }() + + ttl := time.NewTimer(2 * time.Second) + defer ttl.Stop() + + select { + case <-s.quitCh: + return nil, errReqSrvExit + case <-ttl.C: + return nil, errReqTimeout + case data := <-results: + return data, nil + } +} + +func (s *Server) jsClusteredStreamUpdateRequest(ci *ClientInfo, acc *Account, subject, reply string, rmsg []byte, cfg *StreamConfig, peerSet []string, pedantic bool) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + // Now process the request and proposal. + js.mu.Lock() + defer js.mu.Unlock() + meta := cc.meta + if meta == nil { + return + } + + var resp = JSApiStreamUpdateResponse{ApiResponse: ApiResponse{Type: JSApiStreamUpdateResponseType}} + + osa := js.streamAssignment(acc.Name, cfg.Name) + if osa == nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Don't allow updating if all peers are offline. + if s.allPeersOffline(osa.Group) { + resp.Error = NewJSStreamOfflineError() + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + + // Update asset version metadata. + setStaticStreamMetadata(cfg) + + var newCfg *StreamConfig + if jsa := js.accounts[acc.Name]; jsa != nil { + js.mu.Unlock() + ncfg, err := jsa.configUpdateCheck(osa.Config, cfg, s, pedantic) + js.mu.Lock() + if err != nil { + resp.Error = NewJSStreamUpdateError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } else { + newCfg = ncfg + } + } else { + resp.Error = NewJSNotEnabledForAccountError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Check for mirror changes which are not allowed. + if !reflect.DeepEqual(newCfg.Mirror, osa.Config.Mirror) { + resp.Error = NewJSStreamMirrorNotUpdatableError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Check for subject collisions here. + if cc.subjectsOverlap(acc.Name, cfg.Subjects, osa) { + resp.Error = NewJSStreamSubjectOverlapError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Make copy so to not change original. + rg := osa.copyGroup().Group + + // Check for a move request. + var isMoveRequest, isMoveCancel bool + if lPeerSet := len(peerSet); lPeerSet > 0 { + isMoveRequest = true + // check if this is a cancellation + if lPeerSet == osa.Config.Replicas && lPeerSet <= len(rg.Peers) { + isMoveCancel = true + // can only be a cancellation if the peer sets overlap as expected + for i := 0; i < lPeerSet; i++ { + if peerSet[i] != rg.Peers[i] { + isMoveCancel = false + break + } + } + } + } else { + isMoveRequest = newCfg.Placement != nil && !reflect.DeepEqual(osa.Config.Placement, newCfg.Placement) + } + + // Check for replica changes. + isReplicaChange := newCfg.Replicas != osa.Config.Replicas + + // We stage consumer updates and do them after the stream update. + var consumers []*consumerAssignment + + // Check if this is a move request, but no cancellation, and we are already moving this stream. + if isMoveRequest && !isMoveCancel && osa.Config.Replicas != len(rg.Peers) { + // obtain stats to include in error message + msg := _EMPTY_ + if s.allPeersOffline(rg) { + msg = fmt.Sprintf("all %d peers offline", len(rg.Peers)) + } else { + // Need to release js lock. + js.mu.Unlock() + if si, err := sysRequest[StreamInfo](s, clusterStreamInfoT, ci.serviceAccount(), cfg.Name); err != nil { + msg = fmt.Sprintf("error retrieving info: %s", err.Error()) + } else if si != nil { + currentCount := 0 + if si.Cluster.Leader != _EMPTY_ { + currentCount++ + } + combinedLag := uint64(0) + for _, r := range si.Cluster.Replicas { + if r.Current { + currentCount++ + } + combinedLag += r.Lag + } + msg = fmt.Sprintf("total peers: %d, current peers: %d, combined lag: %d", + len(rg.Peers), currentCount, combinedLag) + } + // Re-acquire here. + js.mu.Lock() + } + resp.Error = NewJSStreamMoveInProgressError(msg) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Can not move and scale at same time. + if isMoveRequest && isReplicaChange { + resp.Error = NewJSStreamMoveAndScaleError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + if isReplicaChange { + isScaleUp := newCfg.Replicas > len(rg.Peers) + // We are adding new peers here. + if isScaleUp { + // Check that we have the allocation available. + if err := js.jsClusteredStreamLimitsCheck(acc, newCfg); err != nil { + resp.Error = err + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Check if we do not have a cluster assigned, and if we do not make sure we + // try to pick one. This could happen with older streams that were assigned by + // previous servers. + if rg.Cluster == _EMPTY_ { + // Prefer placement directives if we have them. + if newCfg.Placement != nil && newCfg.Placement.Cluster != _EMPTY_ { + rg.Cluster = newCfg.Placement.Cluster + } else { + // Fall back to the cluster assignment from the client. + rg.Cluster = ci.Cluster + } + } + peers, err := cc.selectPeerGroup(newCfg.Replicas, rg.Cluster, newCfg, rg.Peers, 0, nil) + if err != nil { + resp.Error = NewJSClusterNoPeersError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Single nodes are not recorded by the NRG layer so we can rename. + if len(peers) == 1 { + rg.Name = groupNameForStream(peers, rg.Storage) + } else if len(rg.Peers) == 1 { + // This is scale up from being a singelton, set preferred to that singelton. + rg.Preferred = rg.Peers[0] + } + rg.Peers = peers + } else { + // We are deleting nodes here. We want to do our best to preserve the current leader. + // We have support now from above that guarantees we are in our own Go routine, so can + // ask for stream info from the stream leader to make sure we keep the leader in the new list. + var curLeader string + if !s.allPeersOffline(rg) { + // Need to release js lock. + js.mu.Unlock() + if si, err := sysRequest[StreamInfo](s, clusterStreamInfoT, ci.serviceAccount(), cfg.Name); err != nil { + s.Warnf("Did not receive stream info results for '%s > %s' due to: %s", acc, cfg.Name, err) + } else if si != nil { + if cl := si.Cluster; cl != nil && cl.Leader != _EMPTY_ { + curLeader = getHash(cl.Leader) + } + } + // Re-acquire here. + js.mu.Lock() + } + // If we identified a leader make sure its part of the new group. + selected := make([]string, 0, newCfg.Replicas) + + if curLeader != _EMPTY_ { + selected = append(selected, curLeader) + } + for _, peer := range rg.Peers { + if len(selected) == newCfg.Replicas { + break + } + if peer == curLeader { + continue + } + if si, ok := s.nodeToInfo.Load(peer); ok && si != nil { + if si.(nodeInfo).offline { + continue + } + selected = append(selected, peer) + } + } + rg.Peers = selected + } + + // Need to remap any consumers. + for _, ca := range osa.consumers { + // Legacy ephemerals are R=1 but present as R=0, so only auto-remap named consumers, or if we are downsizing the consumer peers. + // If stream is interest or workqueue policy always remaps since they require peer parity with stream. + numPeers := len(ca.Group.Peers) + isAutoScale := ca.Config.Replicas == 0 && (ca.Config.Durable != _EMPTY_ || ca.Config.Name != _EMPTY_) + if isAutoScale || numPeers > len(rg.Peers) || cfg.Retention != LimitsPolicy { + cca := ca.copyGroup() + // Adjust preferred as needed. + if numPeers == 1 && isScaleUp { + cca.Group.Preferred = ca.Group.Peers[0] + } else { + cca.Group.Preferred = _EMPTY_ + } + // Assign new peers. + cca.Group.Peers = rg.Peers + // If the replicas was not 0 make sure it matches here. + if cca.Config.Replicas != 0 { + cca.Config.Replicas = len(rg.Peers) + } + // We can not propose here before the stream itself so we collect them. + consumers = append(consumers, cca) + + } else if !isScaleUp { + // We decided to leave this consumer's peer group alone but we are also scaling down. + // We need to make sure we do not have any peers that are no longer part of the stream. + // Note we handle down scaling of a consumer above if its number of peers were > new stream peers. + var needReplace []string + for _, rp := range ca.Group.Peers { + // Check if we have an orphaned peer now for this consumer. + if !rg.isMember(rp) { + needReplace = append(needReplace, rp) + } + } + if len(needReplace) > 0 { + newPeers := copyStrings(rg.Peers) + rand.Shuffle(len(newPeers), func(i, j int) { newPeers[i], newPeers[j] = newPeers[j], newPeers[i] }) + // If we had a small size then the peer set, restrict to the same number. + if lp := len(ca.Group.Peers); lp < len(newPeers) { + newPeers = newPeers[:lp] + } + cca := ca.copyGroup() + // Assign new peers. + cca.Group.Peers = newPeers + // If the replicas was not 0 make sure it matches here. + if cca.Config.Replicas != 0 { + cca.Config.Replicas = len(newPeers) + } + // Check if all peers are invalid. This can happen with R1 under replicated streams that are being scaled down. + if len(needReplace) == len(ca.Group.Peers) { + // We have to transfer state to new peers. + // we will grab our state and attach to the new assignment. + // TODO(dlc) - In practice we would want to make sure the consumer is paused. + // Need to release js lock. + js.mu.Unlock() + if ci, err := sysRequest[ConsumerInfo](s, clusterConsumerInfoT, acc, osa.Config.Name, ca.Name); err != nil { + s.Warnf("Did not receive consumer info results for '%s > %s > %s' due to: %s", acc, osa.Config.Name, ca.Name, err) + } else if ci != nil { + cca.State = &ConsumerState{ + Delivered: SequencePair{ + Consumer: ci.Delivered.Consumer, + Stream: ci.Delivered.Stream, + }, + AckFloor: SequencePair{ + Consumer: ci.AckFloor.Consumer, + Stream: ci.AckFloor.Stream, + }, + } + } + // Re-acquire here. + js.mu.Lock() + } + // We can not propose here before the stream itself so we collect them. + consumers = append(consumers, cca) + } + } + } + + } else if isMoveRequest { + if len(peerSet) == 0 { + nrg, err := js.createGroupForStream(ci, newCfg) + if err != nil { + resp.Error = NewJSClusterNoPeersError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // filter peers present in both sets + for _, peer := range rg.Peers { + found := false + for _, newPeer := range nrg.Peers { + if peer == newPeer { + found = true + break + } + } + if !found { + peerSet = append(peerSet, peer) + } + } + peerSet = append(peerSet, nrg.Peers...) + } + if len(rg.Peers) == 1 { + rg.Preferred = peerSet[0] + } + rg.Peers = peerSet + + for _, ca := range osa.consumers { + cca := ca.copyGroup() + r := cca.Config.replicas(osa.Config) + // shuffle part of cluster peer set we will be keeping + randPeerSet := copyStrings(peerSet[len(peerSet)-newCfg.Replicas:]) + rand.Shuffle(newCfg.Replicas, func(i, j int) { randPeerSet[i], randPeerSet[j] = randPeerSet[j], randPeerSet[i] }) + // move overlapping peers at the end of randPeerSet and keep a tally of non overlapping peers + dropPeerSet := make([]string, 0, len(cca.Group.Peers)) + for _, p := range cca.Group.Peers { + found := false + for i, rp := range randPeerSet { + if p == rp { + randPeerSet[i] = randPeerSet[newCfg.Replicas-1] + randPeerSet[newCfg.Replicas-1] = p + found = true + break + } + } + if !found { + dropPeerSet = append(dropPeerSet, p) + } + } + cPeerSet := randPeerSet[newCfg.Replicas-r:] + // In case of a set or cancel simply assign + if len(peerSet) == newCfg.Replicas { + cca.Group.Peers = cPeerSet + } else { + cca.Group.Peers = append(dropPeerSet, cPeerSet...) + } + // make sure it overlaps with peers and remove if not + if cca.Group.Preferred != _EMPTY_ { + found := false + for _, p := range cca.Group.Peers { + if p == cca.Group.Preferred { + found = true + break + } + } + if !found { + cca.Group.Preferred = _EMPTY_ + } + } + // We can not propose here before the stream itself so we collect them. + consumers = append(consumers, cca) + } + } else { + // All other updates make sure no preferred is set. + rg.Preferred = _EMPTY_ + } + + sa := &streamAssignment{Group: rg, Sync: osa.Sync, Created: osa.Created, Config: newCfg, Subject: subject, Reply: reply, Client: ci} + meta.Propose(encodeUpdateStreamAssignment(sa)) + + // Process any staged consumers. + for _, ca := range consumers { + meta.Propose(encodeAddConsumerAssignment(ca)) + } +} + +func (s *Server) jsClusteredStreamDeleteRequest(ci *ClientInfo, acc *Account, stream, subject, reply string, rmsg []byte) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + if cc.meta == nil { + return + } + + osa := js.streamAssignment(acc.Name, stream) + if osa == nil { + var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}} + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + sa := &streamAssignment{Group: osa.Group, Config: osa.Config, Subject: subject, Reply: reply, Client: ci} + cc.meta.Propose(encodeDeleteStreamAssignment(sa)) +} + +// Process a clustered purge request. +func (s *Server) jsClusteredStreamPurgeRequest( + ci *ClientInfo, + acc *Account, + mset *stream, + stream, subject, reply string, + rmsg []byte, + preq *JSApiStreamPurgeRequest, +) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.Lock() + sa := js.streamAssignment(acc.Name, stream) + if sa == nil { + resp := JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}} + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + js.mu.Unlock() + return + } + + if n := sa.Group.node; n != nil { + sp := &streamPurge{Stream: stream, LastSeq: mset.state().LastSeq, Subject: subject, Reply: reply, Client: ci, Request: preq} + n.Propose(encodeStreamPurge(sp)) + js.mu.Unlock() + return + } + js.mu.Unlock() + + if mset == nil { + return + } + + var resp = JSApiStreamPurgeResponse{ApiResponse: ApiResponse{Type: JSApiStreamPurgeResponseType}} + purged, err := mset.purge(preq) + if err != nil { + resp.Error = NewJSStreamGeneralError(err, Unless(err)) + } else { + resp.Purged = purged + resp.Success = true + } + s.sendAPIResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(resp)) +} + +func (s *Server) jsClusteredStreamRestoreRequest( + ci *ClientInfo, + acc *Account, + req *JSApiStreamRestoreRequest, + subject, reply string, rmsg []byte) { + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + if cc.meta == nil { + return + } + + cfg := &req.Config + resp := JSApiStreamRestoreResponse{ApiResponse: ApiResponse{Type: JSApiStreamRestoreResponseType}} + + if err := js.jsClusteredStreamLimitsCheck(acc, cfg); err != nil { + resp.Error = err + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + if sa := js.streamAssignment(ci.serviceAccount(), cfg.Name); sa != nil { + resp.Error = NewJSStreamNameExistRestoreFailedError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Raft group selection and placement. + rg, err := js.createGroupForStream(ci, cfg) + if err != nil { + resp.Error = NewJSClusterNoPeersError(err) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Pick a preferred leader. + rg.setPreferred() + sa := &streamAssignment{Group: rg, Sync: syncSubjForStream(), Config: cfg, Subject: subject, Reply: reply, Client: ci, Created: time.Now().UTC()} + // Now add in our restore state and pre-select a peer to handle the actual receipt of the snapshot. + sa.Restore = &req.State + cc.meta.Propose(encodeAddStreamAssignment(sa)) +} + +// Determine if all peers for this group are offline. +func (s *Server) allPeersOffline(rg *raftGroup) bool { + if rg == nil { + return false + } + // Check to see if this stream has any servers online to respond. + for _, peer := range rg.Peers { + if si, ok := s.nodeToInfo.Load(peer); ok && si != nil { + if !si.(nodeInfo).offline { + return false + } + } + } + return true +} + +// This will do a scatter and gather operation for all streams for this account. This is only called from metadata leader. +// This will be running in a separate Go routine. +func (s *Server) jsClusteredStreamListRequest(acc *Account, ci *ClientInfo, filter string, offset int, subject, reply string, rmsg []byte) { + defer s.grWG.Done() + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.RLock() + + var streams []*streamAssignment + for _, sa := range cc.streams[acc.Name] { + if IsNatsErr(sa.err, JSClusterNotAssignedErr) { + continue + } + + if filter != _EMPTY_ { + // These could not have subjects auto-filled in since they are raw and unprocessed. + if len(sa.Config.Subjects) == 0 { + if SubjectsCollide(filter, sa.Config.Name) { + streams = append(streams, sa) + } + } else { + for _, subj := range sa.Config.Subjects { + if SubjectsCollide(filter, subj) { + streams = append(streams, sa) + break + } + } + } + } else { + streams = append(streams, sa) + } + } + + // Needs to be sorted for offsets etc. + if len(streams) > 1 { + slices.SortFunc(streams, func(i, j *streamAssignment) int { return cmp.Compare(i.Config.Name, j.Config.Name) }) + } + + scnt := len(streams) + if offset > scnt { + offset = scnt + } + if offset > 0 { + streams = streams[offset:] + } + if len(streams) > JSApiListLimit { + streams = streams[:JSApiListLimit] + } + + var resp = JSApiStreamListResponse{ + ApiResponse: ApiResponse{Type: JSApiStreamListResponseType}, + Streams: make([]*StreamInfo, 0, len(streams)), + } + + js.mu.RUnlock() + + if len(streams) == 0 { + resp.Limit = JSApiListLimit + resp.Offset = offset + s.sendAPIResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(resp)) + return + } + + // Create an inbox for our responses and send out our requests. + s.mu.Lock() + inbox := s.newRespInbox() + rc := make(chan *streamInfoClusterResponse, len(streams)) + + // Store our handler. + s.sys.replies[inbox] = func(sub *subscription, _ *client, _ *Account, subject, _ string, msg []byte) { + var si streamInfoClusterResponse + if err := json.Unmarshal(msg, &si); err != nil { + s.Warnf("Error unmarshalling clustered stream info response:%v", err) + return + } + select { + case rc <- &si: + default: + s.Warnf("Failed placing remote stream info result on internal channel") + } + } + s.mu.Unlock() + + // Cleanup after. + defer func() { + s.mu.Lock() + if s.sys != nil && s.sys.replies != nil { + delete(s.sys.replies, inbox) + } + s.mu.Unlock() + }() + + var missingNames []string + sent := map[string]int{} + + // Send out our requests here. + js.mu.RLock() + for _, sa := range streams { + if s.allPeersOffline(sa.Group) { + // Place offline onto our results by hand here. + si := &StreamInfo{ + Config: *sa.Config, + Created: sa.Created, + Cluster: js.offlineClusterInfo(sa.Group), + TimeStamp: time.Now().UTC(), + } + resp.Streams = append(resp.Streams, si) + missingNames = append(missingNames, sa.Config.Name) + } else { + isubj := fmt.Sprintf(clusterStreamInfoT, sa.Client.serviceAccount(), sa.Config.Name) + s.sendInternalMsgLocked(isubj, inbox, nil, nil) + sent[sa.Config.Name] = len(sa.consumers) + } + } + // Don't hold lock. + js.mu.RUnlock() + + const timeout = 4 * time.Second + notActive := time.NewTimer(timeout) + defer notActive.Stop() + +LOOP: + for len(sent) > 0 { + select { + case <-s.quitCh: + return + case <-notActive.C: + s.Warnf("Did not receive all stream info results for %q", acc) + for sName := range sent { + missingNames = append(missingNames, sName) + } + break LOOP + case si := <-rc: + consCount := sent[si.Config.Name] + if consCount > 0 { + si.State.Consumers = consCount + } + delete(sent, si.Config.Name) + if si.OfflineReason == _EMPTY_ { + resp.Streams = append(resp.Streams, &si.StreamInfo) + } else if _, ok := resp.Offline[si.Config.Name]; !ok { + if resp.Offline == nil { + resp.Offline = make(map[string]string, 1) + } + resp.Offline[si.Config.Name] = si.OfflineReason + missingNames = append(missingNames, si.Config.Name) + } + } + } + + // Needs to be sorted as well. + if len(resp.Streams) > 1 { + slices.SortFunc(resp.Streams, func(i, j *StreamInfo) int { return cmp.Compare(i.Config.Name, j.Config.Name) }) + } + + resp.Total = scnt + resp.Limit = JSApiListLimit + resp.Offset = offset + resp.Missing = missingNames + s.sendAPIResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(resp)) +} + +// This will do a scatter and gather operation for all consumers for this stream and account. +// This will be running in a separate Go routine. +func (s *Server) jsClusteredConsumerListRequest(acc *Account, ci *ClientInfo, offset int, stream, subject, reply string, rmsg []byte) { + defer s.grWG.Done() + + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.RLock() + + var consumers []*consumerAssignment + if sas := cc.streams[acc.Name]; sas != nil { + if sa := sas[stream]; sa != nil { + // Copy over since we need to sort etc. + for _, ca := range sa.consumers { + consumers = append(consumers, ca) + } + } + } + // Needs to be sorted. + if len(consumers) > 1 { + slices.SortFunc(consumers, func(i, j *consumerAssignment) int { return cmp.Compare(i.Config.Name, j.Config.Name) }) + } + + ocnt := len(consumers) + if offset > ocnt { + offset = ocnt + } + if offset > 0 { + consumers = consumers[offset:] + } + if len(consumers) > JSApiListLimit { + consumers = consumers[:JSApiListLimit] + } + + // Send out our requests here. + var resp = JSApiConsumerListResponse{ + ApiResponse: ApiResponse{Type: JSApiConsumerListResponseType}, + Consumers: []*ConsumerInfo{}, + } + + js.mu.RUnlock() + + if len(consumers) == 0 { + resp.Limit = JSApiListLimit + resp.Offset = offset + s.sendAPIResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(resp)) + return + } + + // Create an inbox for our responses and send out requests. + s.mu.Lock() + inbox := s.newRespInbox() + rc := make(chan *consumerInfoClusterResponse, len(consumers)) + + // Store our handler. + s.sys.replies[inbox] = func(sub *subscription, _ *client, _ *Account, subject, _ string, msg []byte) { + var ci consumerInfoClusterResponse + if err := json.Unmarshal(msg, &ci); err != nil { + s.Warnf("Error unmarshaling clustered consumer info response:%v", err) + return + } + select { + case rc <- &ci: + default: + s.Warnf("Failed placing consumer info result on internal chan") + } + } + s.mu.Unlock() + + // Cleanup after. + defer func() { + s.mu.Lock() + if s.sys != nil && s.sys.replies != nil { + delete(s.sys.replies, inbox) + } + s.mu.Unlock() + }() + + var missingNames []string + sent := map[string]struct{}{} + + // Send out our requests here. + js.mu.RLock() + for _, ca := range consumers { + if s.allPeersOffline(ca.Group) { + // Place offline onto our results by hand here. + ci := &ConsumerInfo{ + Config: ca.Config, + Created: ca.Created, + Cluster: js.offlineClusterInfo(ca.Group), + TimeStamp: time.Now().UTC(), + } + resp.Consumers = append(resp.Consumers, ci) + missingNames = append(missingNames, ca.Name) + } else { + isubj := fmt.Sprintf(clusterConsumerInfoT, ca.Client.serviceAccount(), stream, ca.Name) + s.sendInternalMsgLocked(isubj, inbox, nil, nil) + sent[ca.Name] = struct{}{} + } + } + // Don't hold lock. + js.mu.RUnlock() + + const timeout = 4 * time.Second + notActive := time.NewTimer(timeout) + defer notActive.Stop() + +LOOP: + for len(sent) > 0 { + select { + case <-s.quitCh: + return + case <-notActive.C: + s.Warnf("Did not receive all consumer info results for '%s > %s'", acc, stream) + for cName := range sent { + missingNames = append(missingNames, cName) + } + break LOOP + case ci := <-rc: + delete(sent, ci.Name) + if ci.OfflineReason == _EMPTY_ { + resp.Consumers = append(resp.Consumers, &ci.ConsumerInfo) + } else if _, ok := resp.Offline[ci.Name]; !ok { + if resp.Offline == nil { + resp.Offline = make(map[string]string, 1) + } + resp.Offline[ci.Name] = ci.OfflineReason + missingNames = append(missingNames, ci.Name) + } + } + } + + // Needs to be sorted as well. + if len(resp.Consumers) > 1 { + slices.SortFunc(resp.Consumers, func(i, j *ConsumerInfo) int { return cmp.Compare(i.Name, j.Name) }) + } + + resp.Total = ocnt + resp.Limit = JSApiListLimit + resp.Offset = offset + resp.Missing = missingNames + s.sendAPIResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(resp)) +} + +func encodeStreamPurge(sp *streamPurge) []byte { + var bb bytes.Buffer + bb.WriteByte(byte(purgeStreamOp)) + json.NewEncoder(&bb).Encode(sp) + return bb.Bytes() +} + +func decodeStreamPurge(buf []byte) (*streamPurge, error) { + var sp streamPurge + err := json.Unmarshal(buf, &sp) + return &sp, err +} + +func (s *Server) jsClusteredConsumerDeleteRequest(ci *ClientInfo, acc *Account, stream, consumer, subject, reply string, rmsg []byte) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + if cc.meta == nil { + return + } + + var resp = JSApiConsumerDeleteResponse{ApiResponse: ApiResponse{Type: JSApiConsumerDeleteResponseType}} + + sa := js.streamAssignment(acc.Name, stream) + if sa == nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + + } + if sa.consumers == nil { + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + oca := sa.consumers[consumer] + if oca == nil { + resp.Error = NewJSConsumerNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + oca.deleted = true + ca := &consumerAssignment{Group: oca.Group, Stream: stream, Name: consumer, Config: oca.Config, Subject: subject, Reply: reply, Client: ci} + cc.meta.Propose(encodeDeleteConsumerAssignment(ca)) +} + +func encodeMsgDelete(md *streamMsgDelete) []byte { + var bb bytes.Buffer + bb.WriteByte(byte(deleteMsgOp)) + json.NewEncoder(&bb).Encode(md) + return bb.Bytes() +} + +func decodeMsgDelete(buf []byte) (*streamMsgDelete, error) { + var md streamMsgDelete + err := json.Unmarshal(buf, &md) + return &md, err +} + +func (s *Server) jsClusteredMsgDeleteRequest(ci *ClientInfo, acc *Account, mset *stream, stream, subject, reply string, req *JSApiMsgDeleteRequest, rmsg []byte) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + js.mu.Lock() + sa := js.streamAssignment(acc.Name, stream) + if sa == nil { + s.Debugf("Message delete failed, could not locate stream '%s > %s'", acc.Name, stream) + js.mu.Unlock() + return + } + + // Check for single replica items. + if n := sa.Group.node; n != nil { + md := streamMsgDelete{Seq: req.Seq, NoErase: req.NoErase, Stream: stream, Subject: subject, Reply: reply, Client: ci} + n.Propose(encodeMsgDelete(&md)) + js.mu.Unlock() + return + } + js.mu.Unlock() + + if mset == nil { + return + } + + var err error + var removed bool + if req.NoErase { + removed, err = mset.removeMsg(req.Seq) + } else { + removed, err = mset.eraseMsg(req.Seq) + } + var resp = JSApiMsgDeleteResponse{ApiResponse: ApiResponse{Type: JSApiMsgDeleteResponseType}} + if err != nil { + resp.Error = NewJSStreamMsgDeleteFailedError(err, Unless(err)) + } else if !removed { + resp.Error = NewJSSequenceNotFoundError(req.Seq) + } else { + resp.Success = true + } + s.sendAPIResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(resp)) +} + +func encodeAddStreamAssignment(sa *streamAssignment) []byte { + csa := *sa + csa.Client = csa.Client.forProposal() + csa.ConfigJSON, _ = json.Marshal(sa.Config) + var bb bytes.Buffer + bb.WriteByte(byte(assignStreamOp)) + json.NewEncoder(&bb).Encode(csa) + return bb.Bytes() +} + +func encodeUpdateStreamAssignment(sa *streamAssignment) []byte { + csa := *sa + csa.Client = csa.Client.forProposal() + csa.ConfigJSON, _ = json.Marshal(sa.Config) + var bb bytes.Buffer + bb.WriteByte(byte(updateStreamOp)) + json.NewEncoder(&bb).Encode(csa) + return bb.Bytes() +} + +func encodeDeleteStreamAssignment(sa *streamAssignment) []byte { + csa := *sa + csa.Client = csa.Client.forProposal() + csa.ConfigJSON, _ = json.Marshal(sa.Config) + var bb bytes.Buffer + bb.WriteByte(byte(removeStreamOp)) + json.NewEncoder(&bb).Encode(csa) + return bb.Bytes() +} + +func decodeStreamAssignment(s *Server, buf []byte) (*streamAssignment, error) { + var sa streamAssignment + if err := json.Unmarshal(buf, &sa); err != nil { + return nil, err + } + if err := decodeStreamAssignmentConfig(s, &sa); err != nil { + return nil, err + } + return &sa, nil +} + +func decodeStreamAssignmentConfig(s *Server, sa *streamAssignment) error { + var unsupported bool + var cfg StreamConfig + var err error + decoder := json.NewDecoder(bytes.NewReader(sa.ConfigJSON)) + decoder.DisallowUnknownFields() + if err = decoder.Decode(&cfg); err != nil { + unsupported = true + cfg = StreamConfig{} + if err2 := json.Unmarshal(sa.ConfigJSON, &cfg); err2 != nil { + return err2 + } + } + sa.Config = &cfg + fixCfgMirrorWithDedupWindow(sa.Config) + + if unsupported || err != nil || (sa.Config != nil && !supportsRequiredApiLevel(sa.Config.Metadata)) { + sa.unsupported = newUnsupportedStreamAssignment(s, sa, err) + } + return nil +} + +func encodeDeleteRange(dr *DeleteRange) []byte { + var bb bytes.Buffer + bb.WriteByte(byte(deleteRangeOp)) + json.NewEncoder(&bb).Encode(dr) + return bb.Bytes() +} + +func decodeDeleteRange(buf []byte) (*DeleteRange, error) { + var dr DeleteRange + err := json.Unmarshal(buf, &dr) + if err != nil { + return nil, err + } + return &dr, err +} + +// createGroupForConsumer will create a new group from same peer set as the stream. +func (cc *jetStreamCluster) createGroupForConsumer(cfg *ConsumerConfig, sa *streamAssignment) *raftGroup { + if len(sa.Group.Peers) == 0 || cfg.Replicas > len(sa.Group.Peers) { + return nil + } + + replicas := cfg.replicas(sa.Config) + peers := copyStrings(sa.Group.Peers) + var _ss [5]string + active := _ss[:0] + + // Calculate all active peers. + for _, peer := range peers { + if sir, ok := cc.s.nodeToInfo.Load(peer); ok && sir != nil { + if !sir.(nodeInfo).offline { + active = append(active, peer) + } + } + } + if quorum := replicas/2 + 1; quorum > len(active) { + // Not enough active to satisfy the request. + return nil + } + + // If we want less then our parent stream, select from active. + if replicas > 0 && replicas < len(peers) { + // Pedantic in case stream is say R5 and consumer is R3 and 3 or more offline, etc. + if len(active) < replicas { + return nil + } + // First shuffle the active peers and then select to account for replica = 1. + rand.Shuffle(len(active), func(i, j int) { active[i], active[j] = active[j], active[i] }) + peers = active[:replicas] + } + storage := sa.Config.Storage + if cfg.MemoryStorage { + storage = MemoryStorage + } + return &raftGroup{Name: groupNameForConsumer(peers, storage), Storage: storage, Peers: peers} +} + +// jsClusteredConsumerRequest is first point of entry to create a consumer in clustered mode. +func (s *Server) jsClusteredConsumerRequest(ci *ClientInfo, acc *Account, subject, reply string, rmsg []byte, stream string, cfg *ConsumerConfig, action ConsumerAction, pedantic bool) { + js, cc := s.getJetStreamCluster() + if js == nil || cc == nil { + return + } + + var resp = JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}} + + streamCfg, ok := js.clusterStreamConfig(acc.Name, stream) + if !ok { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + selectedLimits, _, _, apiErr := acc.selectLimits(cfg.replicas(&streamCfg)) + if apiErr != nil { + resp.Error = apiErr + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + srvLim := &s.getOpts().JetStreamLimits + // Make sure we have sane defaults + if err := setConsumerConfigDefaults(cfg, &streamCfg, srvLim, selectedLimits, pedantic); err != nil { + resp.Error = err + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + if err := checkConsumerCfg(cfg, srvLim, &streamCfg, acc, selectedLimits, false); err != nil { + resp.Error = err + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + js.mu.Lock() + defer js.mu.Unlock() + + if cc.meta == nil { + return + } + + // Lookup the stream assignment. + sa := js.streamAssignment(acc.Name, stream) + if sa == nil { + resp.Error = NewJSStreamNotFoundError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + + // Was a consumer name provided? + var oname string + if isDurableConsumer(cfg) || cfg.Name != _EMPTY_ { + if cfg.Name != _EMPTY_ { + oname = cfg.Name + } else { + oname = cfg.Durable + } + } + + // Check for max consumers here to short circuit if possible. + // Start with limit on a stream, but if one is defined at the level of the account + // and is lower, use that limit. + if action == ActionCreate || action == ActionCreateOrUpdate { + maxc := sa.Config.MaxConsumers + if maxc <= 0 || (selectedLimits.MaxConsumers > 0 && selectedLimits.MaxConsumers < maxc) { + maxc = selectedLimits.MaxConsumers + } + if maxc > 0 { + // Don't count DIRECTS. + total := 0 + for cn, ca := range sa.consumers { + if ca.unsupported != nil { + continue + } + // If the consumer name is specified and we think it already exists, then + // we're likely updating an existing consumer, so don't count it. Otherwise + // we will incorrectly return NewJSMaximumConsumersLimitError for an update. + if oname != _EMPTY_ && cn == oname && sa.consumers[oname] != nil { + continue + } + if ca.Config != nil && !ca.Config.Direct { + total++ + } + } + if total >= maxc { + resp.Error = NewJSMaximumConsumersLimitError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + } + } + + // Also short circuit if DeliverLastPerSubject is set with no FilterSubject. + if cfg.DeliverPolicy == DeliverLastPerSubject { + if cfg.FilterSubject == _EMPTY_ && len(cfg.FilterSubjects) == 0 { + resp.Error = NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last per subject, but FilterSubject is not set")) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + } + + // Setup proper default for ack wait if we are in explicit ack mode. + if cfg.AckWait == 0 && (cfg.AckPolicy == AckExplicit || cfg.AckPolicy == AckAll) { + cfg.AckWait = JsAckWaitDefault + } + // Setup default of -1, meaning no limit for MaxDeliver. + if cfg.MaxDeliver == 0 { + cfg.MaxDeliver = -1 + } + // Set proper default for max ack pending if we are ack explicit and none has been set. + if cfg.AckPolicy == AckExplicit && cfg.MaxAckPending == 0 { + cfg.MaxAckPending = JsDefaultMaxAckPending + } + + if cfg.PriorityPolicy == PriorityPinnedClient && cfg.PinnedTTL == 0 { + cfg.PinnedTTL = JsDefaultPinnedTTL + } + + var ca *consumerAssignment + + // See if we have an existing one already under same durable name or + // if name was set by the user. + if oname != _EMPTY_ { + if ca = sa.consumers[oname]; ca != nil && !ca.deleted { + // Provided config might miss metadata, copy from existing config. + copyConsumerMetadata(cfg, ca.Config) + + if action == ActionCreate && !reflect.DeepEqual(cfg, ca.Config) { + resp.Error = NewJSConsumerAlreadyExistsError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Do quick sanity check on new cfg to prevent here if possible. + if err := acc.checkNewConsumerConfig(ca.Config, cfg); err != nil { + resp.Error = NewJSConsumerCreateError(err, Unless(err)) + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Don't allow updating if all peers are offline. + if s.allPeersOffline(ca.Group) { + resp.Error = NewJSConsumerOfflineError() + s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp), nil, errRespDelay) + return + } + } else { + // Initialize/update asset version metadata. + // First time creating this consumer, or updating. + setStaticConsumerMetadata(cfg) + } + } + + // Initialize/update asset version metadata. + // But only if we're not creating, should only update it the first time + // to be idempotent with versions where there's no versioning metadata. + if action != ActionCreate { + setStaticConsumerMetadata(cfg) + } + + // If this is new consumer. + if ca == nil { + if action == ActionUpdate { + resp.Error = NewJSConsumerDoesNotExistError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + rg := cc.createGroupForConsumer(cfg, sa) + if rg == nil { + resp.Error = NewJSInsufficientResourcesError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Pick a preferred leader. + rg.setPreferred() + + // Inherit cluster from stream. + rg.Cluster = sa.Group.Cluster + + // We need to set the ephemeral here before replicating. + if !isDurableConsumer(cfg) { + if cfg.Name != _EMPTY_ { + oname = cfg.Name + } else { + // Make sure name is unique. + for { + oname = createConsumerName() + if sa.consumers != nil { + if sa.consumers[oname] != nil { + continue + } + } + break + } + } + } + if len(rg.Peers) > 1 { + if maxHaAssets := s.getOpts().JetStreamLimits.MaxHAAssets; maxHaAssets != 0 { + for _, peer := range rg.Peers { + if ni, ok := s.nodeToInfo.Load(peer); ok { + ni := ni.(nodeInfo) + if stats := ni.stats; stats != nil && stats.HAAssets > maxHaAssets { + resp.Error = NewJSInsufficientResourcesError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + s.Warnf("%s@%s (HA Asset Count: %d) exceeds max ha asset limit of %d"+ + " for (durable) consumer %s placement on stream %s", + ni.name, ni.cluster, ni.stats.HAAssets, maxHaAssets, oname, stream) + return + } + } + } + } + } + + // Check if we are work queue policy. + // We will do pre-checks here to avoid thrashing meta layer. + if sa.Config.Retention == WorkQueuePolicy && !cfg.Direct { + if cfg.AckPolicy != AckExplicit { + resp.Error = NewJSConsumerWQRequiresExplicitAckError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + subjects := gatherSubjectFilters(cfg.FilterSubject, cfg.FilterSubjects) + if len(subjects) == 0 && len(sa.consumers) > 0 { + resp.Error = NewJSConsumerWQMultipleUnfilteredError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + // Check here to make sure we have not collided with another. + if len(sa.consumers) > 0 { + for _, oca := range sa.consumers { + if oca.Name == oname { + continue + } + for _, psubj := range gatherSubjectFilters(oca.Config.FilterSubject, oca.Config.FilterSubjects) { + for _, subj := range subjects { + if SubjectsCollide(subj, psubj) { + resp.Error = NewJSConsumerWQConsumerNotUniqueError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + } + } + } + } + } + + ca = &consumerAssignment{ + Group: rg, + Stream: stream, + Name: oname, + Config: cfg, + Subject: subject, + Reply: reply, + Client: ci, + Created: time.Now().UTC(), + } + } else { + // If the consumer already exists then don't allow updating the PauseUntil, just set + // it back to whatever the current configured value is. + cfg.PauseUntil = ca.Config.PauseUntil + + nca := ca.copyGroup() + + rBefore := nca.Config.replicas(sa.Config) + rAfter := cfg.replicas(sa.Config) + + var curLeader string + if rBefore != rAfter { + // We are modifying nodes here. We want to do our best to preserve the current leader. + // We have support now from above that guarantees we are in our own Go routine, so can + // ask for stream info from the stream leader to make sure we keep the leader in the new list. + if !s.allPeersOffline(ca.Group) { + // Need to release js lock. + js.mu.Unlock() + if ci, err := sysRequest[ConsumerInfo](s, clusterConsumerInfoT, ci.serviceAccount(), sa.Config.Name, cfg.Durable); err != nil { + s.Warnf("Did not receive consumer info results for '%s > %s > %s' due to: %s", acc, sa.Config.Name, cfg.Durable, err) + } else if ci != nil { + if cl := ci.Cluster; cl != nil { + curLeader = getHash(cl.Leader) + } + } + // Re-acquire here. + js.mu.Lock() + } + } + + if rBefore < rAfter { + newPeerSet := nca.Group.Peers + // Scale up by adding new members from the stream peer set that are not yet in the consumer peer set. + streamPeerSet := copyStrings(sa.Group.Peers) + + // Respond with error when there is a config mismatch between the intended config and expected peer size. + if len(streamPeerSet) < rAfter { + resp.Error = NewJSConsumerReplicasExceedsStreamError() + s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) + return + } + rand.Shuffle(rAfter, func(i, j int) { streamPeerSet[i], streamPeerSet[j] = streamPeerSet[j], streamPeerSet[i] }) + for _, p := range streamPeerSet { + found := false + for _, sp := range newPeerSet { + if sp == p { + found = true + break + } + } + if !found { + newPeerSet = append(newPeerSet, p) + if len(newPeerSet) == rAfter { + break + } + } + } + nca.Group.Peers = newPeerSet + nca.Group.Preferred = curLeader + } else if rBefore > rAfter { + newPeerSet := nca.Group.Peers + // mark leader preferred and move it to end + nca.Group.Preferred = curLeader + if nca.Group.Preferred != _EMPTY_ { + for i, p := range newPeerSet { + if nca.Group.Preferred == p { + newPeerSet[i] = newPeerSet[len(newPeerSet)-1] + newPeerSet[len(newPeerSet)-1] = p + } + } + } + // scale down by removing peers from the end + newPeerSet = newPeerSet[len(newPeerSet)-rAfter:] + nca.Group.Peers = newPeerSet + } + + // Update config and client info on copy of existing. + nca.Config = cfg + nca.Client = ci + nca.Subject = subject + nca.Reply = reply + ca = nca + } + + // Do formal proposal. + if err := cc.meta.Propose(encodeAddConsumerAssignment(ca)); err == nil { + // Mark this as pending. + if sa.consumers == nil { + sa.consumers = make(map[string]*consumerAssignment) + } + ca.pending = true + sa.consumers[ca.Name] = ca + } +} + +func encodeAddConsumerAssignment(ca *consumerAssignment) []byte { + cca := *ca + cca.Client = cca.Client.forProposal() + cca.ConfigJSON, _ = json.Marshal(ca.Config) + var bb bytes.Buffer + bb.WriteByte(byte(assignConsumerOp)) + json.NewEncoder(&bb).Encode(cca) + return bb.Bytes() +} + +func encodeDeleteConsumerAssignment(ca *consumerAssignment) []byte { + cca := *ca + cca.Client = cca.Client.forProposal() + cca.ConfigJSON, _ = json.Marshal(ca.Config) + var bb bytes.Buffer + bb.WriteByte(byte(removeConsumerOp)) + json.NewEncoder(&bb).Encode(cca) + return bb.Bytes() +} + +func decodeConsumerAssignment(buf []byte) (*consumerAssignment, error) { + var ca consumerAssignment + if err := json.Unmarshal(buf, &ca); err != nil { + return nil, err + } + if err := decodeConsumerAssignmentConfig(&ca); err != nil { + return nil, err + } + return &ca, nil +} + +func decodeConsumerAssignmentConfig(ca *consumerAssignment) error { + var unsupported bool + var cfg ConsumerConfig + var err error + decoder := json.NewDecoder(bytes.NewReader(ca.ConfigJSON)) + decoder.DisallowUnknownFields() + if err = decoder.Decode(&cfg); err != nil { + unsupported = true + cfg = ConsumerConfig{} + if err2 := json.Unmarshal(ca.ConfigJSON, &cfg); err2 != nil { + return err2 + } + } + ca.Config = &cfg + if unsupported || err != nil || (ca.Config != nil && !supportsRequiredApiLevel(ca.Config.Metadata)) { + ca.unsupported = newUnsupportedConsumerAssignment(ca, err) + } + return nil +} + +func encodeAddConsumerAssignmentCompressed(ca *consumerAssignment) []byte { + cca := *ca + cca.Client = cca.Client.forProposal() + cca.ConfigJSON, _ = json.Marshal(ca.Config) + var bb bytes.Buffer + bb.WriteByte(byte(assignCompressedConsumerOp)) + s2e := s2.NewWriter(&bb) + json.NewEncoder(s2e).Encode(cca) + s2e.Close() + return bb.Bytes() +} + +func decodeConsumerAssignmentCompressed(buf []byte) (*consumerAssignment, error) { + var ca consumerAssignment + bb := bytes.NewBuffer(buf) + s2d := s2.NewReader(bb) + decoder := json.NewDecoder(s2d) + if err := decoder.Decode(&ca); err != nil { + return nil, err + } + if err := decodeConsumerAssignmentConfig(&ca); err != nil { + return nil, err + } + return &ca, nil +} + +var errBadStreamMsg = errors.New("jetstream cluster bad replicated stream msg") + +func decodeStreamMsg(buf []byte) (subject, reply string, hdr, msg []byte, lseq uint64, ts int64, sourced bool, err error) { + var le = binary.LittleEndian + if len(buf) < 26 { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + lseq = le.Uint64(buf) + buf = buf[8:] + ts = int64(le.Uint64(buf)) + buf = buf[8:] + sl := int(le.Uint16(buf)) + buf = buf[2:] + if len(buf) < sl { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + subject = string(buf[:sl]) + buf = buf[sl:] + if len(buf) < 2 { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + rl := int(le.Uint16(buf)) + buf = buf[2:] + if len(buf) < rl { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + reply = string(buf[:rl]) + buf = buf[rl:] + if len(buf) < 2 { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + hl := int(le.Uint16(buf)) + buf = buf[2:] + if len(buf) < hl { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + if hdr = buf[:hl]; len(hdr) == 0 { + hdr = nil + } + buf = buf[hl:] + if len(buf) < 4 { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + ml := int(le.Uint32(buf)) + buf = buf[4:] + if len(buf) < ml { + return _EMPTY_, _EMPTY_, nil, nil, 0, 0, false, errBadStreamMsg + } + if msg = buf[:ml]; len(msg) == 0 { + msg = nil + } + buf = buf[ml:] + if len(buf) > 0 { + flags, _ := binary.Uvarint(buf) + sourced = flags&msgFlagFromSourceOrMirror != 0 + } + return subject, reply, hdr, msg, lseq, ts, sourced, nil +} + +// Flags for encodeStreamMsg/decodeStreamMsg. +const ( + msgFlagFromSourceOrMirror uint64 = 1 << iota +) + +func encodeStreamMsg(subject, reply string, hdr, msg []byte, lseq uint64, ts int64, sourced bool) []byte { + return encodeStreamMsgAllowCompress(subject, reply, hdr, msg, lseq, ts, sourced) +} + +// Threshold for compression. +// TODO(dlc) - Eventually make configurable. +const compressThreshold = 8192 // 8k + +// If allowed and contents over the threshold we will compress. +func encodeStreamMsgAllowCompress(subject, reply string, hdr, msg []byte, lseq uint64, ts int64, sourced bool) []byte { + // Clip the subject, reply, header and msgs down. Operate on + // uint64 lengths to avoid overflowing. + slen := min(uint64(len(subject)), math.MaxUint16) + rlen := min(uint64(len(reply)), math.MaxUint16) + hlen := min(uint64(len(hdr)), math.MaxUint16) + mlen := min(uint64(len(msg)), math.MaxUint32) + total := slen + rlen + hlen + mlen + + shouldCompress := total > compressThreshold + elen := int(1 + 8 + 8 + total) + elen += (2 + 2 + 2 + 4 + 8) // Encoded lengths, 4bytes, flags are up to 8 bytes + + var flags uint64 + if sourced { + flags |= msgFlagFromSourceOrMirror + } + + buf := make([]byte, 1, elen) + buf[0] = byte(streamMsgOp) + + var le = binary.LittleEndian + buf = le.AppendUint64(buf, lseq) + buf = le.AppendUint64(buf, uint64(ts)) + buf = le.AppendUint16(buf, uint16(slen)) + buf = append(buf, subject[:slen]...) + buf = le.AppendUint16(buf, uint16(rlen)) + buf = append(buf, reply[:rlen]...) + buf = le.AppendUint16(buf, uint16(hlen)) + buf = append(buf, hdr[:hlen]...) + buf = le.AppendUint32(buf, uint32(mlen)) + buf = append(buf, msg[:mlen]...) + buf = binary.AppendUvarint(buf, flags) + + // Check if we should compress. + if shouldCompress { + nbuf := make([]byte, s2.MaxEncodedLen(elen)) + nbuf[0] = byte(compressedStreamMsgOp) + ebuf := s2.Encode(nbuf[1:], buf[1:]) + // Only pay the cost of decode on the other side if we compressed. + // S2 will allow us to try without major penalty for non-compressable data. + if len(ebuf) < len(buf) { + buf = nbuf[:len(ebuf)+1] + } + } + + return buf +} + +// Determine if all peers in our set support the binary snapshot. +func (mset *stream) supportsBinarySnapshot() bool { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.supportsBinarySnapshotLocked() +} + +// Determine if all peers in our set support the binary snapshot. +// Lock should be held. +func (mset *stream) supportsBinarySnapshotLocked() bool { + s, n := mset.srv, mset.node + if s == nil || n == nil { + return false + } + // Grab our peers and walk them to make sure we can all support binary stream snapshots. + id, peers := n.ID(), n.Peers() + for _, p := range peers { + if p.ID == id { + // We know we support ourselves. + continue + } + // Since release 2.10.16 only deny if we know the other node does not support. + if sir, ok := s.nodeToInfo.Load(p.ID); ok && sir != nil && !sir.(nodeInfo).binarySnapshots { + return false + } + } + return true +} + +// StreamSnapshot is used for snapshotting and out of band catch up in clustered mode. +// Legacy, replace with binary stream snapshots. +type streamSnapshot struct { + Msgs uint64 `json:"messages"` + Bytes uint64 `json:"bytes"` + FirstSeq uint64 `json:"first_seq"` + LastSeq uint64 `json:"last_seq"` + Failed uint64 `json:"clfs"` + Deleted []uint64 `json:"deleted,omitempty"` +} + +// Grab a snapshot of a stream for clustered mode. +func (mset *stream) stateSnapshot() []byte { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.stateSnapshotLocked() +} + +// Grab a snapshot of a stream for clustered mode. +// Lock should be held. +func (mset *stream) stateSnapshotLocked() []byte { + // Decide if we can support the new style of stream snapshots. + if mset.supportsBinarySnapshotLocked() { + snap, err := mset.store.EncodedStreamState(mset.getCLFS()) + if err != nil { + return nil + } + return snap + } + + // Older v1 version with deleted as a sorted []uint64. + // For a stream with millions or billions of interior deletes, this will be huge. + // Now that all server versions 2.10.+ support binary snapshots, we should never fall back. + assert.Unreachable("Legacy JSON stream snapshot used", map[string]any{ + "stream": mset.cfg.Name, + "account": mset.acc.Name, + }) + + state := mset.store.State() + snap := &streamSnapshot{ + Msgs: state.Msgs, + Bytes: state.Bytes, + FirstSeq: state.FirstSeq, + LastSeq: state.LastSeq, + Failed: mset.getCLFS(), + Deleted: state.Deleted, + } + b, _ := json.Marshal(snap) + return b +} + +// To warn when we are getting too far behind from what has been proposed vs what has been committed. +const streamLagWarnThreshold = 10_000 + +// processClusteredInboundMsg will propose the inbound message to the underlying raft group. +func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg []byte, mt *msgTrace, sourced bool) (retErr error) { + // For possible error response. + var response []byte + + mset.mu.RLock() + canRespond := !mset.cfg.NoAck && len(reply) > 0 + name, stype, store := mset.cfg.Name, mset.cfg.Storage, mset.store + s, js, jsa, st, r, tierName, outq, node := mset.srv, mset.js, mset.jsa, mset.cfg.Storage, mset.cfg.Replicas, mset.tier, mset.outq, mset.node + maxMsgSize, lseq := int(mset.cfg.MaxMsgSize), mset.lseq + interestPolicy, discard, maxMsgs, maxBytes := mset.cfg.Retention != LimitsPolicy, mset.cfg.Discard, mset.cfg.MaxMsgs, mset.cfg.MaxBytes + isLeader, isSealed, allowTTL := mset.isLeader(), mset.cfg.Sealed, mset.cfg.AllowMsgTTL + mset.mu.RUnlock() + + // This should not happen but possible now that we allow scale up, and scale down where this could trigger. + // + // We also invoke this in clustering mode for message tracing when not + // performing message delivery. + if node == nil || mt.traceOnly() { + return mset.processJetStreamMsg(subject, reply, hdr, msg, 0, 0, mt, sourced) + } + + // If message tracing (with message delivery), we will need to send the + // event on exit in case there was an error (if message was not proposed). + // Otherwise, the event will be sent from processJetStreamMsg when + // invoked by the leader (from applyStreamEntries). + if mt != nil { + defer func() { + if retErr != nil { + mt.sendEventFromJetStream(retErr) + } + }() + } + + // Check that we are the leader. This can be false if we have scaled up from an R1 that had inbound queued messages. + if !isLeader { + return NewJSClusterNotLeaderError() + } + + // Bail here if sealed. + if isSealed { + var resp = JSPubAckResponse{PubAck: &PubAck{Stream: mset.name()}, Error: NewJSStreamSealedError()} + b, _ := json.Marshal(resp) + mset.outq.sendMsg(reply, b) + return NewJSStreamSealedError() + } + + // Check here pre-emptively if we have exceeded this server limits. + if js.limitsExceeded(stype) { + s.resourcesExceededError() + if canRespond { + b, _ := json.Marshal(&JSPubAckResponse{PubAck: &PubAck{Stream: name}, Error: NewJSInsufficientResourcesError()}) + outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, b, nil, 0)) + } + // Stepdown regardless. + if node := mset.raftNode(); node != nil { + node.StepDown() + } + return NewJSInsufficientResourcesError() + } + + // Check here pre-emptively if we have exceeded our account limits. + if exceeded, err := jsa.wouldExceedLimits(st, tierName, r, subject, hdr, msg); exceeded { + if err == nil { + err = NewJSAccountResourcesExceededError() + } + s.RateLimitWarnf("JetStream account limits exceeded for '%s': %s", jsa.acc().GetName(), err.Error()) + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = err + response, _ = json.Marshal(resp) + outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + return err + } + + // Check msgSize if we have a limit set there. Again this works if it goes through but better to be pre-emptive. + if maxMsgSize >= 0 && (len(hdr)+len(msg)) > maxMsgSize { + err := fmt.Errorf("JetStream message size exceeds limits for '%s > %s'", jsa.acc().Name, mset.cfg.Name) + s.RateLimitWarnf("%s", err.Error()) + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = NewJSStreamMessageExceedsMaximumError() + response, _ = json.Marshal(resp) + outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + return err + } + + // Some header checks can be checked pre proposal. Most can not. + var msgId string + if len(hdr) > 0 { + // Since we encode header len as u16 make sure we do not exceed. + // Again this works if it goes through but better to be pre-emptive. + if len(hdr) > math.MaxUint16 { + err := fmt.Errorf("JetStream header size exceeds limits for '%s > %s'", jsa.acc().Name, mset.cfg.Name) + s.RateLimitWarnf("%s", err.Error()) + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = NewJSStreamHeaderExceedsMaximumError() + response, _ = json.Marshal(resp) + outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + return err + } + // Expected stream name can also be pre-checked. + if sname := getExpectedStream(hdr); sname != _EMPTY_ && sname != name { + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamNotMatchError() + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return errStreamMismatch + } + // TTL'd messages are rejected entirely if TTLs are not enabled on the stream, or if the TTL is invalid. + if ttl, err := getMessageTTL(hdr); !sourced && (ttl != 0 || err != nil) { + if !allowTTL { + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = NewJSMessageTTLDisabledError() + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return errMsgTTLDisabled + } else if err != nil { + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = NewJSMessageTTLInvalidError() + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return err + } + } + // Check for MsgIds here at the cluster level to avoid excessive CLFS accounting. + // Will help during restarts. + if msgId = getMsgId(hdr); msgId != _EMPTY_ { + mset.mu.Lock() + if dde := mset.checkMsgId(msgId); dde != nil { + var buf [256]byte + pubAck := append(buf[:0], mset.pubAck...) + seq := dde.seq + mset.mu.Unlock() + // Should not return an invalid sequence, in that case error. + if canRespond { + if seq > 0 { + response := append(pubAck, strconv.FormatUint(seq, 10)...) + response = append(response, ",\"duplicate\": true}"...) + outq.sendMsg(reply, response) + } else { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = ApiErrors[JSStreamDuplicateMessageConflict] + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + } + return errMsgIdDuplicate + } + // FIXME(dlc) - locking conflict with accessing mset.clseq + // For now we stage with zero, and will update in processStreamMsg. + mset.storeMsgIdLocked(&ddentry{msgId, 0, time.Now().UnixNano()}) + mset.mu.Unlock() + } + } + + // Proceed with proposing this message. + + // We only use mset.clseq for clustering and in case we run ahead of actual commits. + // Check if we need to set initial value here + mset.clMu.Lock() + if mset.clseq == 0 || mset.clseq < lseq+mset.clfs { + // Re-capture + lseq = mset.lastSeq() + mset.clseq = lseq + mset.clfs + } + + // Check if we have an interest policy and discard new with max msgs or bytes. + // We need to deny here otherwise it could succeed on some peers and not others + // depending on consumer ack state. So we deny here, if we allow that means we know + // it would succeed on every peer. + if interestPolicy && discard == DiscardNew && (maxMsgs > 0 || maxBytes > 0) { + // Track inflight. + if mset.inflight == nil { + mset.inflight = make(map[uint64]uint64) + } + if stype == FileStorage { + mset.inflight[mset.clseq] = fileStoreMsgSize(subject, hdr, msg) + } else { + mset.inflight[mset.clseq] = memStoreMsgSize(subject, hdr, msg) + } + + var state StreamState + mset.store.FastState(&state) + + var err error + if maxMsgs > 0 && state.Msgs+uint64(len(mset.inflight)) > uint64(maxMsgs) { + err = ErrMaxMsgs + } else if maxBytes > 0 { + // TODO(dlc) - Could track this rollup independently. + var bytesPending uint64 + for _, nb := range mset.inflight { + bytesPending += nb + } + if state.Bytes+bytesPending > uint64(maxBytes) { + err = ErrMaxBytes + } + } + if err != nil { + delete(mset.inflight, mset.clseq) + mset.clMu.Unlock() + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.Error = NewJSStreamStoreFailedError(err, Unless(err)) + response, _ = json.Marshal(resp) + outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + return err + } + } + + if len(hdr) > 0 { + // Expected last sequence per subject. + if seq, exists := getExpectedLastSeqPerSubject(hdr); exists && store != nil { + // Allow override of the subject used for the check. + seqSubj := subject + if optSubj := getExpectedLastSeqPerSubjectForSubject(hdr); optSubj != _EMPTY_ { + seqSubj = optSubj + } + + // If subject is already in process, block as otherwise we could have multiple messages inflight with same subject. + if _, found := mset.expectedPerSubjectInProcess[seqSubj]; found { + // Could have set inflight above, cleanup here. + delete(mset.inflight, mset.clseq) + mset.clMu.Unlock() + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamWrongLastSequenceConstantError() + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return fmt.Errorf("last sequence by subject mismatch") + } + + var smv StoreMsg + var fseq uint64 + sm, err := store.LoadLastMsg(seqSubj, &smv) + if sm != nil { + fseq = sm.seq + } + if err == ErrStoreMsgNotFound && seq == 0 { + fseq, err = 0, nil + } + if err != nil || fseq != seq { + // Could have set inflight above, cleanup here. + delete(mset.inflight, mset.clseq) + mset.clMu.Unlock() + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamWrongLastSequenceError(fseq) + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return fmt.Errorf("last sequence by subject mismatch: %d vs %d", seq, fseq) + } + + // Track sequence and subject. + if mset.expectedPerSubjectSequence == nil { + mset.expectedPerSubjectSequence = make(map[uint64]string) + } + if mset.expectedPerSubjectInProcess == nil { + mset.expectedPerSubjectInProcess = make(map[string]struct{}) + } + mset.expectedPerSubjectSequence[mset.clseq] = seqSubj + mset.expectedPerSubjectInProcess[seqSubj] = struct{}{} + } + } + + esm := encodeStreamMsgAllowCompress(subject, reply, hdr, msg, mset.clseq, time.Now().UnixNano(), sourced) + var mtKey uint64 + if mt != nil { + mtKey = mset.clseq + if mset.mt == nil { + mset.mt = make(map[uint64]*msgTrace) + } + mset.mt[mtKey] = mt + } + + // Do proposal. + err := node.Propose(esm) + if err == nil { + mset.clseq++ + // If we are using the system account for NRG, add in the extra sent msgs and bytes to our account + // so that the end user / account owner has visibility. + if node.IsSystemAccount() && mset.acc != nil && r > 1 { + outMsgs := int64(r - 1) + outBytes := int64(len(esm) * (r - 1)) + + mset.acc.stats.Lock() + mset.acc.stats.outMsgs += outMsgs + mset.acc.stats.outBytes += outBytes + mset.acc.stats.rt.outMsgs += outMsgs + mset.acc.stats.rt.outBytes += outBytes + mset.acc.stats.Unlock() + } + } + + // Check to see if we are being overrun. + // TODO(dlc) - Make this a limit where we drop messages to protect ourselves, but allow to be configured. + if mset.clseq-(lseq+mset.clfs) > streamLagWarnThreshold { + lerr := fmt.Errorf("JetStream stream '%s > %s' has high message lag", jsa.acc().Name, name) + s.RateLimitWarnf("%s", lerr.Error()) + } + mset.clMu.Unlock() + + if err != nil { + if mt != nil { + mset.getAndDeleteMsgTrace(mtKey) + } + if canRespond { + var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: mset.cfg.Name}} + resp.Error = &ApiError{Code: 503, Description: err.Error()} + response, _ = json.Marshal(resp) + // If we errored out respond here. + outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + if isOutOfSpaceErr(err) { + s.handleOutOfSpace(mset) + } + } + + return err +} + +func (mset *stream) getAndDeleteMsgTrace(lseq uint64) *msgTrace { + if mset == nil { + return nil + } + mset.clMu.Lock() + mt, ok := mset.mt[lseq] + if ok { + delete(mset.mt, lseq) + } + mset.clMu.Unlock() + return mt +} + +// For requesting messages post raft snapshot to catch up streams post server restart. +// Any deleted msgs etc will be handled inline on catchup. +type streamSyncRequest struct { + Peer string `json:"peer,omitempty"` + FirstSeq uint64 `json:"first_seq"` + LastSeq uint64 `json:"last_seq"` + DeleteRangesOk bool `json:"delete_ranges"` + MinApplied uint64 `json:"min_applied"` +} + +// Given a stream state that represents a snapshot, calculate the sync request based on our current state. +// Stream lock must be held. +func (mset *stream) calculateSyncRequest(state *StreamState, snap *StreamReplicatedState, index uint64) *streamSyncRequest { + // Shouldn't happen, but consequences are pretty bad if we have the lock held and + // our caller tries to take the lock again on panic defer, as in processSnapshot. + if state == nil || snap == nil || mset.node == nil { + return nil + } + // Quick check if we are already caught up. + if state.LastSeq >= snap.LastSeq { + return nil + } + return &streamSyncRequest{FirstSeq: state.LastSeq + 1, LastSeq: snap.LastSeq, Peer: mset.node.ID(), DeleteRangesOk: true, MinApplied: index} +} + +// processSnapshotDeletes will update our current store based on the snapshot +// but only processing deletes and new FirstSeq / purges. +func (mset *stream) processSnapshotDeletes(snap *StreamReplicatedState) { + mset.mu.Lock() + var state StreamState + mset.store.FastState(&state) + // Always adjust if FirstSeq has moved beyond our state. + var didReset bool + if snap.FirstSeq > state.FirstSeq { + mset.store.Compact(snap.FirstSeq) + mset.store.FastState(&state) + mset.lseq = state.LastSeq + mset.clearAllPreAcksBelowFloor(state.FirstSeq) + didReset = true + } + s := mset.srv + mset.mu.Unlock() + + if didReset { + s.Warnf("Catchup for stream '%s > %s' resetting first sequence: %d on catchup request", + mset.account(), mset.name(), snap.FirstSeq) + } + + if len(snap.Deleted) > 0 { + mset.store.SyncDeleted(snap.Deleted) + } +} + +func (mset *stream) setCatchupPeer(peer string, lag uint64) { + if peer == _EMPTY_ { + return + } + mset.mu.Lock() + if mset.catchups == nil { + mset.catchups = make(map[string]uint64) + } + mset.catchups[peer] = lag + mset.mu.Unlock() +} + +// Will decrement by one. +func (mset *stream) updateCatchupPeer(peer string) { + if peer == _EMPTY_ { + return + } + mset.mu.Lock() + if lag := mset.catchups[peer]; lag > 0 { + mset.catchups[peer] = lag - 1 + } + mset.mu.Unlock() +} + +func (mset *stream) decrementCatchupPeer(peer string, num uint64) { + if peer == _EMPTY_ { + return + } + mset.mu.Lock() + if lag := mset.catchups[peer]; lag > 0 { + if lag >= num { + lag -= num + } else { + lag = 0 + } + mset.catchups[peer] = lag + } + mset.mu.Unlock() +} + +func (mset *stream) clearCatchupPeer(peer string) { + mset.mu.Lock() + if mset.catchups != nil { + delete(mset.catchups, peer) + } + mset.mu.Unlock() +} + +// Lock should be held. +func (mset *stream) clearAllCatchupPeers() { + if mset.catchups != nil { + mset.catchups = nil + } +} + +func (mset *stream) lagForCatchupPeer(peer string) uint64 { + mset.mu.RLock() + defer mset.mu.RUnlock() + if mset.catchups == nil { + return 0 + } + return mset.catchups[peer] +} + +func (mset *stream) hasCatchupPeers() bool { + mset.mu.RLock() + defer mset.mu.RUnlock() + return len(mset.catchups) > 0 +} + +func (mset *stream) setCatchingUp() { + mset.catchup.Store(true) +} + +func (mset *stream) clearCatchingUp() { + mset.catchup.Store(false) +} + +func (mset *stream) isCatchingUp() bool { + return mset.catchup.Load() +} + +// Determine if a non-leader is current. +// Lock should be held. +func (mset *stream) isCurrent() bool { + if mset.node == nil { + return true + } + return mset.node.Current() && !mset.catchup.Load() +} + +// Maximum requests for the whole server that can be in flight at the same time. +const maxConcurrentSyncRequests = 32 + +var ( + errCatchupCorruptSnapshot = errors.New("corrupt stream snapshot detected") + errCatchupStalled = errors.New("catchup stalled") + errCatchupStreamStopped = errors.New("stream has been stopped") // when a catchup is terminated due to the stream going away. + errCatchupBadMsg = errors.New("bad catchup msg") + errCatchupWrongSeqForSkip = errors.New("wrong sequence for skipped msg") + errCatchupAbortedNoLeader = errors.New("catchup aborted, no leader") + errCatchupTooManyRetries = errors.New("catchup failed, too many retries") +) + +// Process a stream snapshot. +func (mset *stream) processSnapshot(snap *StreamReplicatedState, index uint64) (e error) { + // Update any deletes, etc. + mset.processSnapshotDeletes(snap) + mset.setCLFS(snap.Failed) + + mset.mu.Lock() + var state StreamState + mset.store.FastState(&state) + sreq := mset.calculateSyncRequest(&state, snap, index) + + if mset.sa == nil || mset.node == nil { + mset.mu.Unlock() + return errCatchupStreamStopped + } + s, js, subject, n, st := mset.srv, mset.js, mset.sa.Sync, mset.node, mset.cfg.Storage + qname := fmt.Sprintf("[ACC:%s] stream '%s' snapshot", mset.acc.Name, mset.cfg.Name) + mset.mu.Unlock() + + // Always try to resume applies, we might be paused already if we timed out of processing the snapshot previously. + defer func() { + // Don't bother resuming if server or stream is gone. + if e != errCatchupStreamStopped && e != ErrServerNotRunning { + n.ResumeApply() + } + }() + + // Bug that would cause this to be empty on stream update. + if subject == _EMPTY_ { + return errCatchupCorruptSnapshot + } + + // Just return if up to date or already exceeded limits. + if sreq == nil || js.limitsExceeded(st) { + return nil + } + + // Pause the apply channel for our raft group while we catch up. + if err := n.PauseApply(); err != nil { + return err + } + + // Set our catchup state. + mset.setCatchingUp() + defer mset.clearCatchingUp() + + var sub *subscription + var err error + + const ( + startInterval = 5 * time.Second + activityInterval = 30 * time.Second + ) + notActive := time.NewTimer(startInterval) + defer notActive.Stop() + + defer func() { + if sub != nil { + s.sysUnsubscribe(sub) + } + // Make sure any consumers are updated for the pending amounts. + mset.mu.Lock() + for _, o := range mset.consumers { + o.mu.Lock() + if o.isLeader() { + o.streamNumPending() + } + o.mu.Unlock() + } + mset.mu.Unlock() + + // If we are interest based make sure to check our ack floor state. + // We will delay a bit to allow consumer states to also catchup. + if mset.isInterestRetention() { + fire := time.Duration(rand.Intn(10)+5) * time.Second + time.AfterFunc(fire, mset.checkInterestState) + } + }() + + var releaseSem bool + releaseSyncOutSem := func() { + if !releaseSem { + return + } + // Need to use select for the server shutdown case. + select { + case s.syncOutSem <- struct{}{}: + default: + } + releaseSem = false + } + // On exit, we will release our semaphore if we acquired it. + defer releaseSyncOutSem() + + // Do not let this go on forever. + const maxRetries = 3 + var numRetries int + +RETRY: + // On retry, we need to release the semaphore we got. Call will be no-op + // if releaseSem boolean has not been set to true on successfully getting + // the semaphore. + releaseSyncOutSem() + + if n.Leaderless() { + // Prevent us from spinning if we've installed a snapshot from a leader but there's no leader online. + // We wait a bit to check if a leader has come online in the meantime, if so we can continue. + var canContinue bool + if numRetries == 0 { + time.Sleep(startInterval) + canContinue = !n.Leaderless() + } + if !canContinue { + return fmt.Errorf("%w for stream '%s > %s'", errCatchupAbortedNoLeader, mset.account(), mset.name()) + } + } + + // If we have a sub clear that here. + if sub != nil { + s.sysUnsubscribe(sub) + sub = nil + } + + if !s.isRunning() { + return ErrServerNotRunning + } + + numRetries++ + if numRetries > maxRetries { + // Force a hard reset here. + return errCatchupTooManyRetries + } + + // Block here if we have too many requests in flight. + <-s.syncOutSem + releaseSem = true + + // We may have been blocked for a bit, so the reset needs to ensure that we + // consume the already fired timer. + if !notActive.Stop() { + select { + case <-notActive.C: + default: + } + } + notActive.Reset(startInterval) + + // Grab sync request again on failures. + if sreq == nil { + mset.mu.RLock() + var state StreamState + mset.store.FastState(&state) + sreq = mset.calculateSyncRequest(&state, snap, index) + mset.mu.RUnlock() + if sreq == nil { + return nil + } + } + + // Used to transfer message from the wire to another Go routine internally. + type im struct { + msg []byte + reply string + } + // This is used to notify the leader that it should stop the runCatchup + // because we are either bailing out or going to retry due to an error. + notifyLeaderStopCatchup := func(mrec *im, err error) { + if mrec.reply == _EMPTY_ { + return + } + s.sendInternalMsgLocked(mrec.reply, _EMPTY_, nil, err.Error()) + } + + msgsQ := newIPQueue[*im](s, qname) + defer msgsQ.unregister() + + // Send our catchup request here. + reply := syncReplySubject() + sub, err = s.sysSubscribe(reply, func(_ *subscription, _ *client, _ *Account, _, reply string, msg []byte) { + // Make copy since we are using a buffer from the inbound client/route. + msgsQ.push(&im{copyBytes(msg), reply}) + }) + if err != nil { + s.Errorf("Could not subscribe to stream catchup: %v", err) + goto RETRY + } + + // Send our sync request. + b, _ := json.Marshal(sreq) + s.sendInternalMsgLocked(subject, reply, nil, b) + + // Remember when we sent this out to avoid loop spins on errors below. + reqSendTime := time.Now() + + // Clear our sync request. + sreq = nil + + // Run our own select loop here. + for qch, lch := n.QuitC(), n.LeadChangeC(); ; { + select { + case <-msgsQ.ch: + notActive.Reset(activityInterval) + + mrecs := msgsQ.pop() + for _, mrec := range mrecs { + msg := mrec.msg + // Check for eof signaling. + if len(msg) == 0 { + msgsQ.recycle(&mrecs) + + // Sanity check that we've received all data expected by the snapshot. + mset.mu.RLock() + lseq := mset.lseq + mset.mu.RUnlock() + if lseq >= snap.LastSeq { + return nil + } + + // Make sure we do not spin and make things worse. + const minRetryWait = 2 * time.Second + elapsed := time.Since(reqSendTime) + if elapsed < minRetryWait { + select { + case <-s.quitCh: + return ErrServerNotRunning + case <-qch: + return errCatchupStreamStopped + case <-time.After(minRetryWait - elapsed): + } + } + goto RETRY + } + if _, err := mset.processCatchupMsg(msg); err == nil { + if mrec.reply != _EMPTY_ { + s.sendInternalMsgLocked(mrec.reply, _EMPTY_, nil, nil) + } + } else if isOutOfSpaceErr(err) { + notifyLeaderStopCatchup(mrec, err) + msgsQ.recycle(&mrecs) + return err + } else if err == NewJSInsufficientResourcesError() { + notifyLeaderStopCatchup(mrec, err) + if mset.js.limitsExceeded(mset.cfg.Storage) { + s.resourcesExceededError() + } else { + s.Warnf("Catchup for stream '%s > %s' errored, account resources exceeded: %v", mset.account(), mset.name(), err) + } + msgsQ.recycle(&mrecs) + return err + } else { + notifyLeaderStopCatchup(mrec, err) + s.Warnf("Catchup for stream '%s > %s' errored, will retry: %v", mset.account(), mset.name(), err) + msgsQ.recycle(&mrecs) + + // Make sure we do not spin and make things worse. + const minRetryWait = 2 * time.Second + elapsed := time.Since(reqSendTime) + if elapsed < minRetryWait { + select { + case <-s.quitCh: + return ErrServerNotRunning + case <-qch: + return errCatchupStreamStopped + case <-time.After(minRetryWait - elapsed): + } + } + goto RETRY + } + } + notActive.Reset(activityInterval) + msgsQ.recycle(&mrecs) + case <-notActive.C: + if mrecs := msgsQ.pop(); len(mrecs) > 0 { + mrec := mrecs[0] + notifyLeaderStopCatchup(mrec, errCatchupStalled) + msgsQ.recycle(&mrecs) + } + s.Warnf("Catchup for stream '%s > %s' stalled", mset.account(), mset.name()) + goto RETRY + case <-s.quitCh: + return ErrServerNotRunning + case <-qch: + return errCatchupStreamStopped + case isLeader := <-lch: + if isLeader { + n.StepDown() + goto RETRY + } + } + } +} + +// processCatchupMsg will be called to process out of band catchup msgs from a sync request. +func (mset *stream) processCatchupMsg(msg []byte) (uint64, error) { + if len(msg) == 0 { + return 0, errCatchupBadMsg + } + op := entryOp(msg[0]) + if op != streamMsgOp && op != compressedStreamMsgOp && op != deleteRangeOp { + return 0, errCatchupBadMsg + } + + mbuf := msg[1:] + if op == deleteRangeOp { + dr, err := decodeDeleteRange(mbuf) + if err != nil { + return 0, errCatchupBadMsg + } + // Handle the delete range. + // Make sure the sequences match up properly. + mset.mu.Lock() + if len(mset.preAcks) > 0 { + for seq := dr.First; seq < dr.First+dr.Num; seq++ { + mset.clearAllPreAcks(seq) + } + } + if err = mset.store.SkipMsgs(dr.First, dr.Num); err != nil { + mset.mu.Unlock() + return 0, errCatchupWrongSeqForSkip + } + mset.lseq = dr.First + dr.Num - 1 + lseq := mset.lseq + mset.mu.Unlock() + return lseq, nil + } + + if op == compressedStreamMsgOp { + var err error + mbuf, err = s2.Decode(nil, mbuf) + if err != nil { + panic(err.Error()) + } + } + + subj, _, hdr, msg, seq, ts, _, err := decodeStreamMsg(mbuf) + if err != nil { + return 0, errCatchupBadMsg + } + + mset.mu.Lock() + st := mset.cfg.Storage + ddloaded := mset.ddloaded + if mset.hasAllPreAcks(seq, subj) { + mset.clearAllPreAcks(seq) + // Mark this to be skipped + subj, ts = _EMPTY_, 0 + } + mset.mu.Unlock() + + // Since we're clustered we do not want to check limits based on tier here and possibly introduce skew. + if mset.js.limitsExceeded(st) { + return 0, NewJSInsufficientResourcesError() + } + + // Find the message TTL if any. + // TODO(nat): If the TTL isn't valid by this stage then there isn't really a + // lot we can do about it, as we'd break the catchup if we reject the message. + ttl, _ := getMessageTTL(hdr) + + // Put into our store + // Messages to be skipped have no subject or timestamp. + // TODO(dlc) - formalize with skipMsgOp + if subj == _EMPTY_ && ts == 0 { + if _, err = mset.store.SkipMsg(seq); err != nil { + return 0, errCatchupWrongSeqForSkip + } + } else if err := mset.store.StoreRawMsg(subj, hdr, msg, seq, ts, ttl); err != nil { + return 0, err + } + + mset.mu.Lock() + defer mset.mu.Unlock() + // Update our lseq. + mset.setLastSeq(seq) + + // Check for MsgId and if we have one here make sure to update our internal map. + if len(hdr) > 0 { + if msgId := getMsgId(hdr); msgId != _EMPTY_ { + if !ddloaded { + mset.rebuildDedupe() + } + mset.storeMsgIdLocked(&ddentry{msgId, seq, ts}) + } + } + + return seq, nil +} + +func (mset *stream) handleClusterSyncRequest(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + var sreq streamSyncRequest + if err := json.Unmarshal(msg, &sreq); err != nil { + // Log error. + return + } + mset.srv.startGoRoutine(func() { mset.runCatchup(reply, &sreq) }) +} + +// Lock should be held. +func (js *jetStream) offlineClusterInfo(rg *raftGroup) *ClusterInfo { + s := js.srv + + ci := &ClusterInfo{Name: s.ClusterName(), RaftGroup: rg.Name} + for _, peer := range rg.Peers { + if sir, ok := s.nodeToInfo.Load(peer); ok && sir != nil { + si := sir.(nodeInfo) + pi := &PeerInfo{Peer: peer, Name: si.name, Current: false, Offline: true} + ci.Replicas = append(ci.Replicas, pi) + } + } + return ci +} + +// clusterInfo will report on the status of the raft group. +func (js *jetStream) clusterInfo(rg *raftGroup) *ClusterInfo { + if js == nil { + return nil + } + js.mu.RLock() + defer js.mu.RUnlock() + + s := js.srv + if rg == nil || rg.node == nil { + return &ClusterInfo{ + Name: s.cachedClusterName(), + Leader: s.Name(), + } + } + + n := rg.node + ci := &ClusterInfo{ + Name: s.cachedClusterName(), + Leader: s.serverNameForNode(n.GroupLeader()), + LeaderSince: n.LeaderSince(), + SystemAcc: n.IsSystemAccount(), + TrafficAcc: n.GetTrafficAccountName(), + RaftGroup: rg.Name, + } + + now := time.Now() + id, peers := n.ID(), n.Peers() + + // If we are leaderless, do not suppress putting us in the peer list. + if ci.Leader == _EMPTY_ { + id = _EMPTY_ + } + + for _, rp := range peers { + if rp.ID != id && rg.isMember(rp.ID) { + var lastSeen time.Duration + if now.After(rp.Last) && !rp.Last.IsZero() { + lastSeen = now.Sub(rp.Last) + } + current := rp.Current + if current && lastSeen > lostQuorumInterval { + current = false + } + // Create a peer info with common settings if the peer has not been seen + // yet (which can happen after the whole cluster is stopped and only some + // of the nodes are restarted). + pi := &PeerInfo{ + Current: current, + Offline: true, + Active: lastSeen, + Lag: rp.Lag, + Peer: rp.ID, + } + // If node is found, complete/update the settings. + if sir, ok := s.nodeToInfo.Load(rp.ID); ok && sir != nil { + si := sir.(nodeInfo) + pi.Name, pi.Offline, pi.cluster = si.name, si.offline, si.cluster + } else { + // If not, then add a name that indicates that the server name + // is unknown at this time, and clear the lag since it is misleading + // (the node may not have that much lag). + // Note: We return now the Peer ID in PeerInfo, so the "(peerID: %s)" + // would technically not be required, but keeping it for now. + pi.Name, pi.Lag = fmt.Sprintf("Server name unknown at this time (peerID: %s)", rp.ID), 0 + } + ci.Replicas = append(ci.Replicas, pi) + } + } + // Order the result based on the name so that we get something consistent + // when doing repeated stream info in the CLI, etc... + slices.SortFunc(ci.Replicas, func(i, j *PeerInfo) int { return cmp.Compare(i.Name, j.Name) }) + return ci +} + +func (mset *stream) checkClusterInfo(ci *ClusterInfo) { + for _, r := range ci.Replicas { + peer := getHash(r.Name) + if lag := mset.lagForCatchupPeer(peer); lag > 0 { + r.Current = false + r.Lag = lag + } + } +} + +// Return a list of alternates, ranked by preference order to the request, of stream mirrors. +// This allows clients to select or get more information about read replicas that could be a +// better option to connect to versus the original source. +func (js *jetStream) streamAlternates(ci *ClientInfo, stream string) []StreamAlternate { + if js == nil { + return nil + } + + js.mu.RLock() + defer js.mu.RUnlock() + + s, cc := js.srv, js.cluster + // Track our domain. + domain := s.getOpts().JetStreamDomain + + // No clustering just return nil. + if cc == nil { + return nil + } + acc, _ := s.LookupAccount(ci.serviceAccount()) + if acc == nil { + return nil + } + + // Collect our ordering first for clusters. + weights := make(map[string]int) + all := []string{ci.Cluster} + all = append(all, ci.Alternates...) + + for i := 0; i < len(all); i++ { + weights[all[i]] = len(all) - i + } + + var alts []StreamAlternate + for _, sa := range cc.streams[acc.Name] { + if sa.unsupported != nil { + continue + } + // Add in ourselves and any mirrors. + if sa.Config.Name == stream || (sa.Config.Mirror != nil && sa.Config.Mirror.Name == stream) { + alts = append(alts, StreamAlternate{Name: sa.Config.Name, Domain: domain, Cluster: sa.Group.Cluster}) + } + } + // If just us don't fill in. + if len(alts) == 1 { + return nil + } + + // Sort based on our weights that originate from the request itself. + // reverse sort + slices.SortFunc(alts, func(i, j StreamAlternate) int { return -cmp.Compare(weights[i.Cluster], weights[j.Cluster]) }) + + return alts +} + +// Internal request for stream info, this is coming on the wire so do not block here. +func (mset *stream) handleClusterStreamInfoRequest(_ *subscription, c *client, _ *Account, subject, reply string, _ []byte) { + go mset.processClusterStreamInfoRequest(reply) +} + +func (mset *stream) processClusterStreamInfoRequest(reply string) { + mset.mu.RLock() + sysc, js, sa, config := mset.sysc, mset.srv.js.Load(), mset.sa, mset.cfg + isLeader := mset.isLeader() + mset.mu.RUnlock() + + // By design all members will receive this. Normally we only want the leader answering. + // But if we have stalled and lost quorom all can respond. + if sa != nil && !js.isGroupLeaderless(sa.Group) && !isLeader { + return + } + + // If we are not the leader let someone else possibly respond first. + if !isLeader { + time.Sleep(500 * time.Millisecond) + } + + si := &StreamInfo{ + Created: mset.createdTime(), + State: mset.state(), + Config: config, + Cluster: js.clusterInfo(mset.raftGroup()), + Sources: mset.sourcesInfo(), + Mirror: mset.mirrorInfo(), + TimeStamp: time.Now().UTC(), + } + + // Check for out of band catchups. + if mset.hasCatchupPeers() { + mset.checkClusterInfo(si.Cluster) + } + + sysc.sendInternalMsg(reply, _EMPTY_, nil, si) +} + +// 64MB for now, for the total server. This is max we will blast out if asked to +// do so to another server for purposes of catchups. +// This number should be ok on 1Gbit interface. +const defaultMaxTotalCatchupOutBytes = int64(64 * 1024 * 1024) + +// Current total outstanding catchup bytes. +func (s *Server) gcbTotal() int64 { + s.gcbMu.RLock() + defer s.gcbMu.RUnlock() + return s.gcbOut +} + +// Returns true if Current total outstanding catchup bytes is below +// the maximum configured. +func (s *Server) gcbBelowMax() bool { + s.gcbMu.RLock() + defer s.gcbMu.RUnlock() + return s.gcbOut <= s.gcbOutMax +} + +// Adds `sz` to the server's total outstanding catchup bytes and to `localsz` +// under the gcbMu lock. The `localsz` points to the local outstanding catchup +// bytes of the runCatchup go routine of a given stream. +func (s *Server) gcbAdd(localsz *int64, sz int64) { + s.gcbMu.Lock() + atomic.AddInt64(localsz, sz) + s.gcbOut += sz + if s.gcbOut >= s.gcbOutMax && s.gcbKick == nil { + s.gcbKick = make(chan struct{}) + } + s.gcbMu.Unlock() +} + +// Removes `sz` from the server's total outstanding catchup bytes and from +// `localsz`, but only if `localsz` is non 0, which would signal that gcSubLast +// has already been invoked. See that function for details. +// Must be invoked under the gcbMu lock. +func (s *Server) gcbSubLocked(localsz *int64, sz int64) { + if atomic.LoadInt64(localsz) == 0 { + return + } + atomic.AddInt64(localsz, -sz) + s.gcbOut -= sz + if s.gcbKick != nil && s.gcbOut < s.gcbOutMax { + close(s.gcbKick) + s.gcbKick = nil + } +} + +// Locked version of gcbSubLocked() +func (s *Server) gcbSub(localsz *int64, sz int64) { + s.gcbMu.Lock() + s.gcbSubLocked(localsz, sz) + s.gcbMu.Unlock() +} + +// Similar to gcbSub() but reset `localsz` to 0 at the end under the gcbMu lock. +// This will signal further calls to gcbSub() for this `localsz` pointer that +// nothing should be done because runCatchup() has exited and any remaining +// outstanding bytes value has already been decremented. +func (s *Server) gcbSubLast(localsz *int64) { + s.gcbMu.Lock() + s.gcbSubLocked(localsz, *localsz) + *localsz = 0 + s.gcbMu.Unlock() +} + +// Returns our kick chan, or nil if it does not exist. +func (s *Server) cbKickChan() <-chan struct{} { + s.gcbMu.RLock() + defer s.gcbMu.RUnlock() + return s.gcbKick +} + +func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) { + s := mset.srv + defer s.grWG.Done() + + const maxOutBytes = int64(64 * 1024 * 1024) // 64MB for now, these are all internal, from server to server + const maxOutMsgs = int32(256 * 1024) // 256k in case we have lots of small messages or skip msgs. + outb := int64(0) + outm := int32(0) + + // On abnormal exit make sure to update global total. + defer s.gcbSubLast(&outb) + + // Flow control processing. + ackReplySize := func(subj string) int64 { + if li := strings.LastIndexByte(subj, btsep); li > 0 && li < len(subj) { + return parseAckReplyNum(subj[li+1:]) + } + return 0 + } + + nextBatchC := make(chan struct{}, 4) + nextBatchC <- struct{}{} + remoteQuitCh := make(chan struct{}) + + const activityInterval = 30 * time.Second + notActive := time.NewTimer(activityInterval) + defer notActive.Stop() + + // Setup ackReply for flow control. + ackReply := syncAckSubject() + ackSub, _ := s.sysSubscribe(ackReply, func(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + if len(msg) > 0 { + s.Warnf("Catchup for stream '%s > %s' was aborted on the remote due to: %q", + mset.account(), mset.name(), msg) + s.sysUnsubscribe(sub) + close(remoteQuitCh) + return + } + sz := ackReplySize(subject) + s.gcbSub(&outb, sz) + atomic.AddInt32(&outm, -1) + mset.updateCatchupPeer(sreq.Peer) + // Kick ourselves and anyone else who might have stalled on global state. + select { + case nextBatchC <- struct{}{}: + default: + } + // Reset our activity + notActive.Reset(activityInterval) + }) + defer s.sysUnsubscribe(ackSub) + ackReplyT := strings.ReplaceAll(ackReply, ".*", ".%d") + + // Grab our state. + var state StreamState + // mset.store never changes after being set, don't need lock. + mset.store.FastState(&state) + + // Setup sequences to walk through. + seq, last := sreq.FirstSeq, sreq.LastSeq + + // The follower received a snapshot from another leader, and we've become leader since. + // We have an up-to-date log but could be behind on applies. We must wait until we've reached the minimum required. + // The follower will automatically retry after a timeout, so we can safely return here. + if node := mset.raftNode(); node != nil { + index, _, applied := node.Progress() + // Only skip if our log has enough entries, and they could be applied in the future. + if index >= sreq.MinApplied && applied < sreq.MinApplied { + return + } + // We know here we've either applied enough entries, or our log doesn't have enough entries. + // In the latter case the request expects us to have more. Just continue and value availability here. + // This should only be possible if the logs have already desynced, and we shouldn't have become leader + // in the first place. Not much we can do here in this (hypothetical) scenario. + + // Do another quick sanity check that we actually have enough data to satisfy the request. + // If not, let's step down and hope a new leader can correct this. + if state.LastSeq < last { + s.Warnf("Catchup for stream '%s > %s' skipped, requested sequence %d was larger than current state: %+v", + mset.account(), mset.name(), seq, state) + node.StepDown() + return + } + } + + start := time.Now() + mset.setCatchupPeer(sreq.Peer, last-seq) + + var spb int + const minWait = 5 * time.Second + + sendNextBatchAndContinue := func(qch chan struct{}) bool { + // Check if we know we will not enter the loop because we are done. + if seq > last { + s.Noticef("Catchup for stream '%s > %s' complete (took %v)", mset.account(), mset.name(), time.Since(start)) + // EOF + s.sendInternalMsgLocked(sendSubject, _EMPTY_, nil, nil) + return false + } + + // If we already sent a batch, we will try to make sure we can at least send a minimum + // batch before sending the next batch. + if spb > 0 { + // Wait til we can send at least 4k + const minBatchWait = int32(4 * 1024) + mw := time.NewTimer(minWait) + for done := maxOutMsgs-atomic.LoadInt32(&outm) > minBatchWait; !done; { + select { + case <-nextBatchC: + done = maxOutMsgs-atomic.LoadInt32(&outm) > minBatchWait + if !done { + // Wait for a small bit. + time.Sleep(100 * time.Millisecond) + } else { + // GC friendly. + mw.Stop() + } + case <-mw.C: + done = true + case <-s.quitCh: + return false + case <-qch: + return false + case <-remoteQuitCh: + return false + } + } + spb = 0 + } + + // Send an encoded msg. + sendEM := func(em []byte) { + // Place size in reply subject for flow control. + l := int64(len(em)) + reply := fmt.Sprintf(ackReplyT, l) + s.gcbAdd(&outb, l) + atomic.AddInt32(&outm, 1) + s.sendInternalMsgLocked(sendSubject, reply, nil, em) + spb++ + } + + // If we support gap markers. + var dr DeleteRange + drOk := sreq.DeleteRangesOk + + // Will send our delete range. + // Should already be checked for being valid. + sendDR := func() { + if dr.Num == 1 { + // Send like a normal skip msg. + sendEM(encodeStreamMsg(_EMPTY_, _EMPTY_, nil, nil, dr.First, 0, false)) + } else { + // We have a run, send a gap record. We send these without reply or tracking. + s.sendInternalMsgLocked(sendSubject, _EMPTY_, nil, encodeDeleteRange(&dr)) + // Clear out the pending for catchup. + mset.decrementCatchupPeer(sreq.Peer, dr.Num) + } + // Reset always. + dr.First, dr.Num = 0, 0 + } + + // See if we should use LoadNextMsg instead of walking sequence by sequence if we have an order magnitude more interior deletes. + // Only makes sense with delete range capabilities. + useLoadNext := drOk && (uint64(state.NumDeleted) > 2*state.Msgs || state.NumDeleted > 1_000_000) + + var smv StoreMsg + for ; seq <= last && atomic.LoadInt64(&outb) <= maxOutBytes && atomic.LoadInt32(&outm) <= maxOutMsgs && s.gcbBelowMax(); seq++ { + var sm *StoreMsg + var err error + // If we should use load next do so here. + if useLoadNext { + var nseq uint64 + sm, nseq, err = mset.store.LoadNextMsg(fwcs, true, seq, &smv) + if err == nil && nseq > seq { + // If we jumped over the requested last sequence, clamp it down. + // Otherwise, we would send too much to the follower. + if nseq > last { + nseq = last + sm = nil + } + dr.First, dr.Num = seq, nseq-seq + // Jump ahead + seq = nseq + } else if err == ErrStoreEOF { + dr.First, dr.Num = seq, last-seq + // Clear EOF here for normal processing. + err = nil + // Jump ahead + seq = last + } + } else { + sm, err = mset.store.LoadMsg(seq, &smv) + } + + // if this is not a deleted msg, bail out. + if err != nil && err != ErrStoreMsgNotFound && err != errDeletedMsg { + if err == ErrStoreEOF { + var state StreamState + mset.store.FastState(&state) + if seq > state.LastSeq { + // The snapshot has a larger last sequence then we have. This could be due to a truncation + // when trying to recover after corruption, still not 100% sure. Could be off by 1 too somehow, + // but tested a ton of those with no success. + s.Warnf("Catchup for stream '%s > %s' completed (took %v), but requested sequence %d was larger than current state: %+v", + mset.account(), mset.name(), time.Since(start), seq, state) + // Try our best to redo our invalidated snapshot as well. + if n := mset.raftNode(); n != nil { + if snap := mset.stateSnapshot(); snap != nil { + n.InstallSnapshot(snap) + } + } + // If we allow gap markers check if we have one pending. + if drOk && dr.First > 0 { + sendDR() + } + // Signal EOF + s.sendInternalMsgLocked(sendSubject, _EMPTY_, nil, nil) + return false + } + } + s.Warnf("Error loading message for catchup '%s > %s': %v", mset.account(), mset.name(), err) + return false + } + + if sm != nil { + // If we allow gap markers check if we have one pending. + if drOk && dr.First > 0 { + sendDR() + } + // Send the normal message now. + sendEM(encodeStreamMsgAllowCompress(sm.subj, _EMPTY_, sm.hdr, sm.msg, sm.seq, sm.ts, false)) + } else { + if drOk { + if dr.First == 0 { + dr.First, dr.Num = seq, 1 + } else { + dr.Num++ + } + } else { + // Skip record for deleted msg. + sendEM(encodeStreamMsg(_EMPTY_, _EMPTY_, nil, nil, seq, 0, false)) + } + } + + // Check if we are done. + if seq == last { + // Need to see if we have a pending delete range. + if drOk && dr.First > 0 { + sendDR() + } + s.Noticef("Catchup for stream '%s > %s' complete (took %v)", mset.account(), mset.name(), time.Since(start)) + // EOF + s.sendInternalMsgLocked(sendSubject, _EMPTY_, nil, nil) + return false + } + select { + case <-remoteQuitCh: + return false + default: + } + } + if drOk && dr.First > 0 { + sendDR() + } + return true + } + + // Check is this stream got closed. + mset.mu.RLock() + qch := mset.qch + mset.mu.RUnlock() + if qch == nil { + return + } + + // Run as long as we are still active and need catchup. + // FIXME(dlc) - Purge event? Stream delete? + for { + // Get this each time, will be non-nil if globally blocked and we will close to wake everyone up. + cbKick := s.cbKickChan() + + select { + case <-s.quitCh: + return + case <-qch: + return + case <-remoteQuitCh: + mset.clearCatchupPeer(sreq.Peer) + return + case <-notActive.C: + s.Warnf("Catchup for stream '%s > %s' stalled", mset.account(), mset.name()) + mset.clearCatchupPeer(sreq.Peer) + return + case <-nextBatchC: + if !sendNextBatchAndContinue(qch) { + mset.clearCatchupPeer(sreq.Peer) + return + } + case <-cbKick: + if !sendNextBatchAndContinue(qch) { + mset.clearCatchupPeer(sreq.Peer) + return + } + case <-time.After(500 * time.Millisecond): + if !sendNextBatchAndContinue(qch) { + mset.clearCatchupPeer(sreq.Peer) + return + } + } + } +} + +const jscAllSubj = "$JSC.>" + +func syncSubjForStream() string { + return syncSubject("$JSC.SYNC") +} + +func syncReplySubject() string { + return syncSubject("$JSC.R") +} + +func infoReplySubject() string { + return syncSubject("$JSC.R") +} + +func syncAckSubject() string { + return syncSubject("$JSC.ACK") + ".*" +} + +func syncSubject(pre string) string { + var sb strings.Builder + sb.WriteString(pre) + sb.WriteByte(btsep) + + var b [replySuffixLen]byte + rn := rand.Int63() + for i, l := 0, rn; i < len(b); i++ { + b[i] = digits[l%base] + l /= base + } + + sb.Write(b[:]) + return sb.String() +} + +const ( + clusterStreamInfoT = "$JSC.SI.%s.%s" + clusterConsumerInfoT = "$JSC.CI.%s.%s.%s" + jsaUpdatesSubT = "$JSC.ARU.%s.*" + jsaUpdatesPubT = "$JSC.ARU.%s.%s" +) diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_errors.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_errors.go new file mode 100644 index 0000000..5a81aa6 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_errors.go @@ -0,0 +1,102 @@ +package server + +import ( + "fmt" +) + +type errOpts struct { + err error +} + +// ErrorOption configures a NATS Error helper +type ErrorOption func(*errOpts) + +// Unless ensures that if err is a ApiErr that err will be returned rather than the one being created via the helper +func Unless(err error) ErrorOption { + return func(opts *errOpts) { + opts.err = err + } +} + +func parseOpts(opts []ErrorOption) *errOpts { + eopts := &errOpts{} + for _, opt := range opts { + opt(eopts) + } + return eopts +} + +type ErrorIdentifier uint16 + +// IsNatsErr determines if an error matches ID, if multiple IDs are given if the error matches any of these the function will be true +func IsNatsErr(err error, ids ...ErrorIdentifier) bool { + if err == nil { + return false + } + + ce, ok := err.(*ApiError) + if !ok || ce == nil { + return false + } + + for _, id := range ids { + ae, ok := ApiErrors[id] + if !ok || ae == nil { + continue + } + + if ce.ErrCode == ae.ErrCode { + return true + } + } + + return false +} + +// ApiError is included in all responses if there was an error. +type ApiError struct { + Code int `json:"code"` + ErrCode uint16 `json:"err_code,omitempty"` + Description string `json:"description,omitempty"` +} + +// ErrorsData is the source data for generated errors as found in errors.json +type ErrorsData struct { + Constant string `json:"constant"` + Code int `json:"code"` + ErrCode uint16 `json:"error_code"` + Description string `json:"description"` + Comment string `json:"comment"` + Help string `json:"help"` + URL string `json:"url"` + Deprecates string `json:"deprecates"` +} + +func (e *ApiError) Error() string { + return fmt.Sprintf("%s (%d)", e.Description, e.ErrCode) +} + +func (e *ApiError) toReplacerArgs(replacements []any) []string { + var ( + ra []string + key string + ) + + for i, replacement := range replacements { + if i%2 == 0 { + key = replacement.(string) + continue + } + + switch v := replacement.(type) { + case string: + ra = append(ra, key, v) + case error: + ra = append(ra, key, v.Error()) + default: + ra = append(ra, key, fmt.Sprintf("%v", v)) + } + } + + return ra +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_errors_generated.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_errors_generated.go new file mode 100644 index 0000000..7980efc --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_errors_generated.go @@ -0,0 +1,2696 @@ +// Generated code, do not edit. See errors.json and run go generate to update + +package server + +import "strings" + +const ( + // JSAccountResourcesExceededErr resource limits exceeded for account + JSAccountResourcesExceededErr ErrorIdentifier = 10002 + + // JSBadRequestErr bad request + JSBadRequestErr ErrorIdentifier = 10003 + + // JSClusterIncompleteErr incomplete results + JSClusterIncompleteErr ErrorIdentifier = 10004 + + // JSClusterNoPeersErrF Error causing no peers to be available ({err}) + JSClusterNoPeersErrF ErrorIdentifier = 10005 + + // JSClusterNotActiveErr JetStream not in clustered mode + JSClusterNotActiveErr ErrorIdentifier = 10006 + + // JSClusterNotAssignedErr JetStream cluster not assigned to this server + JSClusterNotAssignedErr ErrorIdentifier = 10007 + + // JSClusterNotAvailErr JetStream system temporarily unavailable + JSClusterNotAvailErr ErrorIdentifier = 10008 + + // JSClusterNotLeaderErr JetStream cluster can not handle request + JSClusterNotLeaderErr ErrorIdentifier = 10009 + + // JSClusterPeerNotMemberErr peer not a member + JSClusterPeerNotMemberErr ErrorIdentifier = 10040 + + // JSClusterRequiredErr JetStream clustering support required + JSClusterRequiredErr ErrorIdentifier = 10010 + + // JSClusterServerMemberChangeInflightErr cluster member change is in progress + JSClusterServerMemberChangeInflightErr ErrorIdentifier = 10202 + + // JSClusterServerNotMemberErr server is not a member of the cluster + JSClusterServerNotMemberErr ErrorIdentifier = 10044 + + // JSClusterTagsErr tags placement not supported for operation + JSClusterTagsErr ErrorIdentifier = 10011 + + // JSClusterUnSupportFeatureErr not currently supported in clustered mode + JSClusterUnSupportFeatureErr ErrorIdentifier = 10036 + + // JSConsumerAlreadyExists action CREATE is used for a existing consumer with a different config (consumer already exists) + JSConsumerAlreadyExists ErrorIdentifier = 10148 + + // JSConsumerBadDurableNameErr durable name can not contain '.', '*', '>' + JSConsumerBadDurableNameErr ErrorIdentifier = 10103 + + // JSConsumerConfigRequiredErr consumer config required + JSConsumerConfigRequiredErr ErrorIdentifier = 10078 + + // JSConsumerCreateDurableAndNameMismatch Consumer Durable and Name have to be equal if both are provided + JSConsumerCreateDurableAndNameMismatch ErrorIdentifier = 10132 + + // JSConsumerCreateErrF General consumer creation failure string ({err}) + JSConsumerCreateErrF ErrorIdentifier = 10012 + + // JSConsumerCreateFilterSubjectMismatchErr Consumer create request did not match filtered subject from create subject + JSConsumerCreateFilterSubjectMismatchErr ErrorIdentifier = 10131 + + // JSConsumerDeliverCycleErr consumer deliver subject forms a cycle + JSConsumerDeliverCycleErr ErrorIdentifier = 10081 + + // JSConsumerDeliverToWildcardsErr consumer deliver subject has wildcards + JSConsumerDeliverToWildcardsErr ErrorIdentifier = 10079 + + // JSConsumerDescriptionTooLongErrF consumer description is too long, maximum allowed is {max} + JSConsumerDescriptionTooLongErrF ErrorIdentifier = 10107 + + // JSConsumerDirectRequiresEphemeralErr consumer direct requires an ephemeral consumer + JSConsumerDirectRequiresEphemeralErr ErrorIdentifier = 10091 + + // JSConsumerDirectRequiresPushErr consumer direct requires a push based consumer + JSConsumerDirectRequiresPushErr ErrorIdentifier = 10090 + + // JSConsumerDoesNotExist action UPDATE is used for a nonexisting consumer (consumer does not exist) + JSConsumerDoesNotExist ErrorIdentifier = 10149 + + // JSConsumerDuplicateFilterSubjects consumer cannot have both FilterSubject and FilterSubjects specified + JSConsumerDuplicateFilterSubjects ErrorIdentifier = 10136 + + // JSConsumerDurableNameNotInSubjectErr consumer expected to be durable but no durable name set in subject + JSConsumerDurableNameNotInSubjectErr ErrorIdentifier = 10016 + + // JSConsumerDurableNameNotMatchSubjectErr consumer name in subject does not match durable name in request + JSConsumerDurableNameNotMatchSubjectErr ErrorIdentifier = 10017 + + // JSConsumerDurableNameNotSetErr consumer expected to be durable but a durable name was not set + JSConsumerDurableNameNotSetErr ErrorIdentifier = 10018 + + // JSConsumerEmptyFilter consumer filter in FilterSubjects cannot be empty + JSConsumerEmptyFilter ErrorIdentifier = 10139 + + // JSConsumerEmptyGroupName Group name cannot be an empty string + JSConsumerEmptyGroupName ErrorIdentifier = 10161 + + // JSConsumerEphemeralWithDurableInSubjectErr consumer expected to be ephemeral but detected a durable name set in subject + JSConsumerEphemeralWithDurableInSubjectErr ErrorIdentifier = 10019 + + // JSConsumerEphemeralWithDurableNameErr consumer expected to be ephemeral but a durable name was set in request + JSConsumerEphemeralWithDurableNameErr ErrorIdentifier = 10020 + + // JSConsumerExistingActiveErr consumer already exists and is still active + JSConsumerExistingActiveErr ErrorIdentifier = 10105 + + // JSConsumerFCRequiresPushErr consumer flow control requires a push based consumer + JSConsumerFCRequiresPushErr ErrorIdentifier = 10089 + + // JSConsumerFilterNotSubsetErr consumer filter subject is not a valid subset of the interest subjects + JSConsumerFilterNotSubsetErr ErrorIdentifier = 10093 + + // JSConsumerHBRequiresPushErr consumer idle heartbeat requires a push based consumer + JSConsumerHBRequiresPushErr ErrorIdentifier = 10088 + + // JSConsumerInactiveThresholdExcess consumer inactive threshold exceeds system limit of {limit} + JSConsumerInactiveThresholdExcess ErrorIdentifier = 10153 + + // JSConsumerInvalidDeliverSubject invalid push consumer deliver subject + JSConsumerInvalidDeliverSubject ErrorIdentifier = 10112 + + // JSConsumerInvalidGroupNameErr Valid priority group name must match A-Z, a-z, 0-9, -_/=)+ and may not exceed 16 characters + JSConsumerInvalidGroupNameErr ErrorIdentifier = 10162 + + // JSConsumerInvalidPolicyErrF Generic delivery policy error ({err}) + JSConsumerInvalidPolicyErrF ErrorIdentifier = 10094 + + // JSConsumerInvalidPriorityGroupErr Provided priority group does not exist for this consumer + JSConsumerInvalidPriorityGroupErr ErrorIdentifier = 10160 + + // JSConsumerInvalidSamplingErrF failed to parse consumer sampling configuration: {err} + JSConsumerInvalidSamplingErrF ErrorIdentifier = 10095 + + // JSConsumerMaxDeliverBackoffErr max deliver is required to be > length of backoff values + JSConsumerMaxDeliverBackoffErr ErrorIdentifier = 10116 + + // JSConsumerMaxPendingAckExcessErrF consumer max ack pending exceeds system limit of {limit} + JSConsumerMaxPendingAckExcessErrF ErrorIdentifier = 10121 + + // JSConsumerMaxPendingAckPolicyRequiredErr consumer requires ack policy for max ack pending + JSConsumerMaxPendingAckPolicyRequiredErr ErrorIdentifier = 10082 + + // JSConsumerMaxRequestBatchExceededF consumer max request batch exceeds server limit of {limit} + JSConsumerMaxRequestBatchExceededF ErrorIdentifier = 10125 + + // JSConsumerMaxRequestBatchNegativeErr consumer max request batch needs to be > 0 + JSConsumerMaxRequestBatchNegativeErr ErrorIdentifier = 10114 + + // JSConsumerMaxRequestExpiresToSmall consumer max request expires needs to be >= 1ms + JSConsumerMaxRequestExpiresToSmall ErrorIdentifier = 10115 + + // JSConsumerMaxWaitingNegativeErr consumer max waiting needs to be positive + JSConsumerMaxWaitingNegativeErr ErrorIdentifier = 10087 + + // JSConsumerMetadataLengthErrF consumer metadata exceeds maximum size of {limit} + JSConsumerMetadataLengthErrF ErrorIdentifier = 10135 + + // JSConsumerMultipleFiltersNotAllowed consumer with multiple subject filters cannot use subject based API + JSConsumerMultipleFiltersNotAllowed ErrorIdentifier = 10137 + + // JSConsumerNameContainsPathSeparatorsErr Consumer name can not contain path separators + JSConsumerNameContainsPathSeparatorsErr ErrorIdentifier = 10127 + + // JSConsumerNameExistErr consumer name already in use + JSConsumerNameExistErr ErrorIdentifier = 10013 + + // JSConsumerNameTooLongErrF consumer name is too long, maximum allowed is {max} + JSConsumerNameTooLongErrF ErrorIdentifier = 10102 + + // JSConsumerNotFoundErr consumer not found + JSConsumerNotFoundErr ErrorIdentifier = 10014 + + // JSConsumerOfflineErr consumer is offline + JSConsumerOfflineErr ErrorIdentifier = 10119 + + // JSConsumerOfflineReasonErrF consumer is offline: {err} + JSConsumerOfflineReasonErrF ErrorIdentifier = 10195 + + // JSConsumerOnMappedErr consumer direct on a mapped consumer + JSConsumerOnMappedErr ErrorIdentifier = 10092 + + // JSConsumerOverlappingSubjectFilters consumer subject filters cannot overlap + JSConsumerOverlappingSubjectFilters ErrorIdentifier = 10138 + + // JSConsumerPriorityPolicyWithoutGroup Setting PriorityPolicy requires at least one PriorityGroup to be set + JSConsumerPriorityPolicyWithoutGroup ErrorIdentifier = 10159 + + // JSConsumerPullNotDurableErr consumer in pull mode requires a durable name + JSConsumerPullNotDurableErr ErrorIdentifier = 10085 + + // JSConsumerPullRequiresAckErr consumer in pull mode requires explicit ack policy on workqueue stream + JSConsumerPullRequiresAckErr ErrorIdentifier = 10084 + + // JSConsumerPullWithRateLimitErr consumer in pull mode can not have rate limit set + JSConsumerPullWithRateLimitErr ErrorIdentifier = 10086 + + // JSConsumerPushMaxWaitingErr consumer in push mode can not set max waiting + JSConsumerPushMaxWaitingErr ErrorIdentifier = 10080 + + // JSConsumerPushWithPriorityGroupErr priority groups can not be used with push consumers + JSConsumerPushWithPriorityGroupErr ErrorIdentifier = 10178 + + // JSConsumerReplacementWithDifferentNameErr consumer replacement durable config not the same + JSConsumerReplacementWithDifferentNameErr ErrorIdentifier = 10106 + + // JSConsumerReplicasExceedsStream consumer config replica count exceeds parent stream + JSConsumerReplicasExceedsStream ErrorIdentifier = 10126 + + // JSConsumerReplicasShouldMatchStream consumer config replicas must match interest retention stream's replicas + JSConsumerReplicasShouldMatchStream ErrorIdentifier = 10134 + + // JSConsumerSmallHeartbeatErr consumer idle heartbeat needs to be >= 100ms + JSConsumerSmallHeartbeatErr ErrorIdentifier = 10083 + + // JSConsumerStoreFailedErrF error creating store for consumer: {err} + JSConsumerStoreFailedErrF ErrorIdentifier = 10104 + + // JSConsumerWQConsumerNotDeliverAllErr consumer must be deliver all on workqueue stream + JSConsumerWQConsumerNotDeliverAllErr ErrorIdentifier = 10101 + + // JSConsumerWQConsumerNotUniqueErr filtered consumer not unique on workqueue stream + JSConsumerWQConsumerNotUniqueErr ErrorIdentifier = 10100 + + // JSConsumerWQMultipleUnfilteredErr multiple non-filtered consumers not allowed on workqueue stream + JSConsumerWQMultipleUnfilteredErr ErrorIdentifier = 10099 + + // JSConsumerWQRequiresExplicitAckErr workqueue stream requires explicit ack + JSConsumerWQRequiresExplicitAckErr ErrorIdentifier = 10098 + + // JSConsumerWithFlowControlNeedsHeartbeats consumer with flow control also needs heartbeats + JSConsumerWithFlowControlNeedsHeartbeats ErrorIdentifier = 10108 + + // JSInsufficientResourcesErr insufficient resources + JSInsufficientResourcesErr ErrorIdentifier = 10023 + + // JSInvalidJSONErr invalid JSON: {err} + JSInvalidJSONErr ErrorIdentifier = 10025 + + // JSMaximumConsumersLimitErr maximum consumers limit reached + JSMaximumConsumersLimitErr ErrorIdentifier = 10026 + + // JSMaximumStreamsLimitErr maximum number of streams reached + JSMaximumStreamsLimitErr ErrorIdentifier = 10027 + + // JSMemoryResourcesExceededErr insufficient memory resources available + JSMemoryResourcesExceededErr ErrorIdentifier = 10028 + + // JSMessageTTLDisabledErr per-message TTL is disabled + JSMessageTTLDisabledErr ErrorIdentifier = 10166 + + // JSMessageTTLInvalidErr invalid per-message TTL + JSMessageTTLInvalidErr ErrorIdentifier = 10165 + + // JSMirrorConsumerSetupFailedErrF generic mirror consumer setup failure string ({err}) + JSMirrorConsumerSetupFailedErrF ErrorIdentifier = 10029 + + // JSMirrorInvalidStreamName mirrored stream name is invalid + JSMirrorInvalidStreamName ErrorIdentifier = 10142 + + // JSMirrorInvalidSubjectFilter mirror transform source: {err} + JSMirrorInvalidSubjectFilter ErrorIdentifier = 10151 + + // JSMirrorInvalidTransformDestination mirror transform: {err} + JSMirrorInvalidTransformDestination ErrorIdentifier = 10154 + + // JSMirrorMaxMessageSizeTooBigErr stream mirror must have max message size >= source + JSMirrorMaxMessageSizeTooBigErr ErrorIdentifier = 10030 + + // JSMirrorMultipleFiltersNotAllowed mirror with multiple subject transforms cannot also have a single subject filter + JSMirrorMultipleFiltersNotAllowed ErrorIdentifier = 10150 + + // JSMirrorOverlappingSubjectFilters mirror subject filters can not overlap + JSMirrorOverlappingSubjectFilters ErrorIdentifier = 10152 + + // JSMirrorWithFirstSeqErr stream mirrors can not have first sequence configured + JSMirrorWithFirstSeqErr ErrorIdentifier = 10143 + + // JSMirrorWithSourcesErr stream mirrors can not also contain other sources + JSMirrorWithSourcesErr ErrorIdentifier = 10031 + + // JSMirrorWithStartSeqAndTimeErr stream mirrors can not have both start seq and start time configured + JSMirrorWithStartSeqAndTimeErr ErrorIdentifier = 10032 + + // JSMirrorWithSubjectFiltersErr stream mirrors can not contain filtered subjects + JSMirrorWithSubjectFiltersErr ErrorIdentifier = 10033 + + // JSMirrorWithSubjectsErr stream mirrors can not contain subjects + JSMirrorWithSubjectsErr ErrorIdentifier = 10034 + + // JSNoAccountErr account not found + JSNoAccountErr ErrorIdentifier = 10035 + + // JSNoLimitsErr no JetStream default or applicable tiered limit present + JSNoLimitsErr ErrorIdentifier = 10120 + + // JSNoMessageFoundErr no message found + JSNoMessageFoundErr ErrorIdentifier = 10037 + + // JSNotEmptyRequestErr expected an empty request payload + JSNotEmptyRequestErr ErrorIdentifier = 10038 + + // JSNotEnabledErr JetStream not enabled + JSNotEnabledErr ErrorIdentifier = 10076 + + // JSNotEnabledForAccountErr JetStream not enabled for account + JSNotEnabledForAccountErr ErrorIdentifier = 10039 + + // JSPedanticErrF pedantic mode: {err} + JSPedanticErrF ErrorIdentifier = 10157 + + // JSPeerRemapErr peer remap failed + JSPeerRemapErr ErrorIdentifier = 10075 + + // JSRaftGeneralErrF General RAFT error string ({err}) + JSRaftGeneralErrF ErrorIdentifier = 10041 + + // JSReplicasCountCannotBeNegative replicas count cannot be negative + JSReplicasCountCannotBeNegative ErrorIdentifier = 10133 + + // JSRestoreSubscribeFailedErrF JetStream unable to subscribe to restore snapshot {subject}: {err} + JSRestoreSubscribeFailedErrF ErrorIdentifier = 10042 + + // JSSequenceNotFoundErrF sequence {seq} not found + JSSequenceNotFoundErrF ErrorIdentifier = 10043 + + // JSSnapshotDeliverSubjectInvalidErr deliver subject not valid + JSSnapshotDeliverSubjectInvalidErr ErrorIdentifier = 10015 + + // JSSourceConsumerSetupFailedErrF General source consumer setup failure string ({err}) + JSSourceConsumerSetupFailedErrF ErrorIdentifier = 10045 + + // JSSourceDuplicateDetected source stream, filter and transform (plus external if present) must form a unique combination (duplicate source configuration detected) + JSSourceDuplicateDetected ErrorIdentifier = 10140 + + // JSSourceInvalidStreamName sourced stream name is invalid + JSSourceInvalidStreamName ErrorIdentifier = 10141 + + // JSSourceInvalidSubjectFilter source transform source: {err} + JSSourceInvalidSubjectFilter ErrorIdentifier = 10145 + + // JSSourceInvalidTransformDestination source transform: {err} + JSSourceInvalidTransformDestination ErrorIdentifier = 10146 + + // JSSourceMaxMessageSizeTooBigErr stream source must have max message size >= target + JSSourceMaxMessageSizeTooBigErr ErrorIdentifier = 10046 + + // JSSourceMultipleFiltersNotAllowed source with multiple subject transforms cannot also have a single subject filter + JSSourceMultipleFiltersNotAllowed ErrorIdentifier = 10144 + + // JSSourceOverlappingSubjectFilters source filters can not overlap + JSSourceOverlappingSubjectFilters ErrorIdentifier = 10147 + + // JSStorageResourcesExceededErr insufficient storage resources available + JSStorageResourcesExceededErr ErrorIdentifier = 10047 + + // JSStreamAssignmentErrF Generic stream assignment error string ({err}) + JSStreamAssignmentErrF ErrorIdentifier = 10048 + + // JSStreamCreateErrF Generic stream creation error string ({err}) + JSStreamCreateErrF ErrorIdentifier = 10049 + + // JSStreamDeleteErrF General stream deletion error string ({err}) + JSStreamDeleteErrF ErrorIdentifier = 10050 + + // JSStreamDuplicateMessageConflict duplicate message id is in process + JSStreamDuplicateMessageConflict ErrorIdentifier = 10158 + + // JSStreamExpectedLastSeqPerSubjectNotReady expected last sequence per subject temporarily unavailable + JSStreamExpectedLastSeqPerSubjectNotReady ErrorIdentifier = 10163 + + // JSStreamExternalApiOverlapErrF stream external api prefix {prefix} must not overlap with {subject} + JSStreamExternalApiOverlapErrF ErrorIdentifier = 10021 + + // JSStreamExternalDelPrefixOverlapsErrF stream external delivery prefix {prefix} overlaps with stream subject {subject} + JSStreamExternalDelPrefixOverlapsErrF ErrorIdentifier = 10022 + + // JSStreamGeneralErrorF General stream failure string ({err}) + JSStreamGeneralErrorF ErrorIdentifier = 10051 + + // JSStreamHeaderExceedsMaximumErr header size exceeds maximum allowed of 64k + JSStreamHeaderExceedsMaximumErr ErrorIdentifier = 10097 + + // JSStreamInfoMaxSubjectsErr subject details would exceed maximum allowed + JSStreamInfoMaxSubjectsErr ErrorIdentifier = 10117 + + // JSStreamInvalidConfigF Stream configuration validation error string ({err}) + JSStreamInvalidConfigF ErrorIdentifier = 10052 + + // JSStreamInvalidErr stream not valid + JSStreamInvalidErr ErrorIdentifier = 10096 + + // JSStreamInvalidExternalDeliverySubjErrF stream external delivery prefix {prefix} must not contain wildcards + JSStreamInvalidExternalDeliverySubjErrF ErrorIdentifier = 10024 + + // JSStreamLimitsErrF General stream limits exceeded error string ({err}) + JSStreamLimitsErrF ErrorIdentifier = 10053 + + // JSStreamMaxBytesRequired account requires a stream config to have max bytes set + JSStreamMaxBytesRequired ErrorIdentifier = 10113 + + // JSStreamMaxStreamBytesExceeded stream max bytes exceeds account limit max stream bytes + JSStreamMaxStreamBytesExceeded ErrorIdentifier = 10122 + + // JSStreamMessageExceedsMaximumErr message size exceeds maximum allowed + JSStreamMessageExceedsMaximumErr ErrorIdentifier = 10054 + + // JSStreamMirrorNotUpdatableErr stream mirror configuration can not be updated + JSStreamMirrorNotUpdatableErr ErrorIdentifier = 10055 + + // JSStreamMismatchErr stream name in subject does not match request + JSStreamMismatchErr ErrorIdentifier = 10056 + + // JSStreamMoveAndScaleErr can not move and scale a stream in a single update + JSStreamMoveAndScaleErr ErrorIdentifier = 10123 + + // JSStreamMoveInProgressF stream move already in progress: {msg} + JSStreamMoveInProgressF ErrorIdentifier = 10124 + + // JSStreamMoveNotInProgress stream move not in progress + JSStreamMoveNotInProgress ErrorIdentifier = 10129 + + // JSStreamMsgDeleteFailedF Generic message deletion failure error string ({err}) + JSStreamMsgDeleteFailedF ErrorIdentifier = 10057 + + // JSStreamNameContainsPathSeparatorsErr Stream name can not contain path separators + JSStreamNameContainsPathSeparatorsErr ErrorIdentifier = 10128 + + // JSStreamNameExistErr stream name already in use with a different configuration + JSStreamNameExistErr ErrorIdentifier = 10058 + + // JSStreamNameExistRestoreFailedErr stream name already in use, cannot restore + JSStreamNameExistRestoreFailedErr ErrorIdentifier = 10130 + + // JSStreamNotFoundErr stream not found + JSStreamNotFoundErr ErrorIdentifier = 10059 + + // JSStreamNotMatchErr expected stream does not match + JSStreamNotMatchErr ErrorIdentifier = 10060 + + // JSStreamOfflineErr stream is offline + JSStreamOfflineErr ErrorIdentifier = 10118 + + // JSStreamOfflineReasonErrF stream is offline: {err} + JSStreamOfflineReasonErrF ErrorIdentifier = 10194 + + // JSStreamPurgeFailedF Generic stream purge failure error string ({err}) + JSStreamPurgeFailedF ErrorIdentifier = 10110 + + // JSStreamReplicasNotSupportedErr replicas > 1 not supported in non-clustered mode + JSStreamReplicasNotSupportedErr ErrorIdentifier = 10074 + + // JSStreamReplicasNotUpdatableErr Replicas configuration can not be updated + JSStreamReplicasNotUpdatableErr ErrorIdentifier = 10061 + + // JSStreamRestoreErrF restore failed: {err} + JSStreamRestoreErrF ErrorIdentifier = 10062 + + // JSStreamRollupFailedF Generic stream rollup failure error string ({err}) + JSStreamRollupFailedF ErrorIdentifier = 10111 + + // JSStreamSealedErr invalid operation on sealed stream + JSStreamSealedErr ErrorIdentifier = 10109 + + // JSStreamSequenceNotMatchErr expected stream sequence does not match + JSStreamSequenceNotMatchErr ErrorIdentifier = 10063 + + // JSStreamSnapshotErrF snapshot failed: {err} + JSStreamSnapshotErrF ErrorIdentifier = 10064 + + // JSStreamStoreFailedF Generic error when storing a message failed ({err}) + JSStreamStoreFailedF ErrorIdentifier = 10077 + + // JSStreamSubjectOverlapErr subjects overlap with an existing stream + JSStreamSubjectOverlapErr ErrorIdentifier = 10065 + + // JSStreamTemplateCreateErrF Generic template creation failed string ({err}) + JSStreamTemplateCreateErrF ErrorIdentifier = 10066 + + // JSStreamTemplateDeleteErrF Generic stream template deletion failed error string ({err}) + JSStreamTemplateDeleteErrF ErrorIdentifier = 10067 + + // JSStreamTemplateNotFoundErr template not found + JSStreamTemplateNotFoundErr ErrorIdentifier = 10068 + + // JSStreamTooManyRequests too many requests + JSStreamTooManyRequests ErrorIdentifier = 10167 + + // JSStreamTransformInvalidDestination stream transform: {err} + JSStreamTransformInvalidDestination ErrorIdentifier = 10156 + + // JSStreamTransformInvalidSource stream transform source: {err} + JSStreamTransformInvalidSource ErrorIdentifier = 10155 + + // JSStreamUpdateErrF Generic stream update error string ({err}) + JSStreamUpdateErrF ErrorIdentifier = 10069 + + // JSStreamWrongLastMsgIDErrF wrong last msg ID: {id} + JSStreamWrongLastMsgIDErrF ErrorIdentifier = 10070 + + // JSStreamWrongLastSequenceConstantErr wrong last sequence + JSStreamWrongLastSequenceConstantErr ErrorIdentifier = 10164 + + // JSStreamWrongLastSequenceErrF wrong last sequence: {seq} + JSStreamWrongLastSequenceErrF ErrorIdentifier = 10071 + + // JSTempStorageFailedErr JetStream unable to open temp storage for restore + JSTempStorageFailedErr ErrorIdentifier = 10072 + + // JSTemplateNameNotMatchSubjectErr template name in subject does not match request + JSTemplateNameNotMatchSubjectErr ErrorIdentifier = 10073 +) + +var ( + ApiErrors = map[ErrorIdentifier]*ApiError{ + JSAccountResourcesExceededErr: {Code: 400, ErrCode: 10002, Description: "resource limits exceeded for account"}, + JSBadRequestErr: {Code: 400, ErrCode: 10003, Description: "bad request"}, + JSClusterIncompleteErr: {Code: 503, ErrCode: 10004, Description: "incomplete results"}, + JSClusterNoPeersErrF: {Code: 400, ErrCode: 10005, Description: "{err}"}, + JSClusterNotActiveErr: {Code: 500, ErrCode: 10006, Description: "JetStream not in clustered mode"}, + JSClusterNotAssignedErr: {Code: 500, ErrCode: 10007, Description: "JetStream cluster not assigned to this server"}, + JSClusterNotAvailErr: {Code: 503, ErrCode: 10008, Description: "JetStream system temporarily unavailable"}, + JSClusterNotLeaderErr: {Code: 500, ErrCode: 10009, Description: "JetStream cluster can not handle request"}, + JSClusterPeerNotMemberErr: {Code: 400, ErrCode: 10040, Description: "peer not a member"}, + JSClusterRequiredErr: {Code: 503, ErrCode: 10010, Description: "JetStream clustering support required"}, + JSClusterServerMemberChangeInflightErr: {Code: 400, ErrCode: 10202, Description: "cluster member change is in progress"}, + JSClusterServerNotMemberErr: {Code: 400, ErrCode: 10044, Description: "server is not a member of the cluster"}, + JSClusterTagsErr: {Code: 400, ErrCode: 10011, Description: "tags placement not supported for operation"}, + JSClusterUnSupportFeatureErr: {Code: 503, ErrCode: 10036, Description: "not currently supported in clustered mode"}, + JSConsumerAlreadyExists: {Code: 400, ErrCode: 10148, Description: "consumer already exists"}, + JSConsumerBadDurableNameErr: {Code: 400, ErrCode: 10103, Description: "durable name can not contain '.', '*', '>'"}, + JSConsumerConfigRequiredErr: {Code: 400, ErrCode: 10078, Description: "consumer config required"}, + JSConsumerCreateDurableAndNameMismatch: {Code: 400, ErrCode: 10132, Description: "Consumer Durable and Name have to be equal if both are provided"}, + JSConsumerCreateErrF: {Code: 500, ErrCode: 10012, Description: "{err}"}, + JSConsumerCreateFilterSubjectMismatchErr: {Code: 400, ErrCode: 10131, Description: "Consumer create request did not match filtered subject from create subject"}, + JSConsumerDeliverCycleErr: {Code: 400, ErrCode: 10081, Description: "consumer deliver subject forms a cycle"}, + JSConsumerDeliverToWildcardsErr: {Code: 400, ErrCode: 10079, Description: "consumer deliver subject has wildcards"}, + JSConsumerDescriptionTooLongErrF: {Code: 400, ErrCode: 10107, Description: "consumer description is too long, maximum allowed is {max}"}, + JSConsumerDirectRequiresEphemeralErr: {Code: 400, ErrCode: 10091, Description: "consumer direct requires an ephemeral consumer"}, + JSConsumerDirectRequiresPushErr: {Code: 400, ErrCode: 10090, Description: "consumer direct requires a push based consumer"}, + JSConsumerDoesNotExist: {Code: 400, ErrCode: 10149, Description: "consumer does not exist"}, + JSConsumerDuplicateFilterSubjects: {Code: 400, ErrCode: 10136, Description: "consumer cannot have both FilterSubject and FilterSubjects specified"}, + JSConsumerDurableNameNotInSubjectErr: {Code: 400, ErrCode: 10016, Description: "consumer expected to be durable but no durable name set in subject"}, + JSConsumerDurableNameNotMatchSubjectErr: {Code: 400, ErrCode: 10017, Description: "consumer name in subject does not match durable name in request"}, + JSConsumerDurableNameNotSetErr: {Code: 400, ErrCode: 10018, Description: "consumer expected to be durable but a durable name was not set"}, + JSConsumerEmptyFilter: {Code: 400, ErrCode: 10139, Description: "consumer filter in FilterSubjects cannot be empty"}, + JSConsumerEmptyGroupName: {Code: 400, ErrCode: 10161, Description: "Group name cannot be an empty string"}, + JSConsumerEphemeralWithDurableInSubjectErr: {Code: 400, ErrCode: 10019, Description: "consumer expected to be ephemeral but detected a durable name set in subject"}, + JSConsumerEphemeralWithDurableNameErr: {Code: 400, ErrCode: 10020, Description: "consumer expected to be ephemeral but a durable name was set in request"}, + JSConsumerExistingActiveErr: {Code: 400, ErrCode: 10105, Description: "consumer already exists and is still active"}, + JSConsumerFCRequiresPushErr: {Code: 400, ErrCode: 10089, Description: "consumer flow control requires a push based consumer"}, + JSConsumerFilterNotSubsetErr: {Code: 400, ErrCode: 10093, Description: "consumer filter subject is not a valid subset of the interest subjects"}, + JSConsumerHBRequiresPushErr: {Code: 400, ErrCode: 10088, Description: "consumer idle heartbeat requires a push based consumer"}, + JSConsumerInactiveThresholdExcess: {Code: 400, ErrCode: 10153, Description: "consumer inactive threshold exceeds system limit of {limit}"}, + JSConsumerInvalidDeliverSubject: {Code: 400, ErrCode: 10112, Description: "invalid push consumer deliver subject"}, + JSConsumerInvalidGroupNameErr: {Code: 400, ErrCode: 10162, Description: "Valid priority group name must match A-Z, a-z, 0-9, -_/=)+ and may not exceed 16 characters"}, + JSConsumerInvalidPolicyErrF: {Code: 400, ErrCode: 10094, Description: "{err}"}, + JSConsumerInvalidPriorityGroupErr: {Code: 400, ErrCode: 10160, Description: "Provided priority group does not exist for this consumer"}, + JSConsumerInvalidSamplingErrF: {Code: 400, ErrCode: 10095, Description: "failed to parse consumer sampling configuration: {err}"}, + JSConsumerMaxDeliverBackoffErr: {Code: 400, ErrCode: 10116, Description: "max deliver is required to be > length of backoff values"}, + JSConsumerMaxPendingAckExcessErrF: {Code: 400, ErrCode: 10121, Description: "consumer max ack pending exceeds system limit of {limit}"}, + JSConsumerMaxPendingAckPolicyRequiredErr: {Code: 400, ErrCode: 10082, Description: "consumer requires ack policy for max ack pending"}, + JSConsumerMaxRequestBatchExceededF: {Code: 400, ErrCode: 10125, Description: "consumer max request batch exceeds server limit of {limit}"}, + JSConsumerMaxRequestBatchNegativeErr: {Code: 400, ErrCode: 10114, Description: "consumer max request batch needs to be > 0"}, + JSConsumerMaxRequestExpiresToSmall: {Code: 400, ErrCode: 10115, Description: "consumer max request expires needs to be >= 1ms"}, + JSConsumerMaxWaitingNegativeErr: {Code: 400, ErrCode: 10087, Description: "consumer max waiting needs to be positive"}, + JSConsumerMetadataLengthErrF: {Code: 400, ErrCode: 10135, Description: "consumer metadata exceeds maximum size of {limit}"}, + JSConsumerMultipleFiltersNotAllowed: {Code: 400, ErrCode: 10137, Description: "consumer with multiple subject filters cannot use subject based API"}, + JSConsumerNameContainsPathSeparatorsErr: {Code: 400, ErrCode: 10127, Description: "Consumer name can not contain path separators"}, + JSConsumerNameExistErr: {Code: 400, ErrCode: 10013, Description: "consumer name already in use"}, + JSConsumerNameTooLongErrF: {Code: 400, ErrCode: 10102, Description: "consumer name is too long, maximum allowed is {max}"}, + JSConsumerNotFoundErr: {Code: 404, ErrCode: 10014, Description: "consumer not found"}, + JSConsumerOfflineErr: {Code: 500, ErrCode: 10119, Description: "consumer is offline"}, + JSConsumerOfflineReasonErrF: {Code: 500, ErrCode: 10195, Description: "consumer is offline: {err}"}, + JSConsumerOnMappedErr: {Code: 400, ErrCode: 10092, Description: "consumer direct on a mapped consumer"}, + JSConsumerOverlappingSubjectFilters: {Code: 400, ErrCode: 10138, Description: "consumer subject filters cannot overlap"}, + JSConsumerPriorityPolicyWithoutGroup: {Code: 400, ErrCode: 10159, Description: "Setting PriorityPolicy requires at least one PriorityGroup to be set"}, + JSConsumerPullNotDurableErr: {Code: 400, ErrCode: 10085, Description: "consumer in pull mode requires a durable name"}, + JSConsumerPullRequiresAckErr: {Code: 400, ErrCode: 10084, Description: "consumer in pull mode requires explicit ack policy on workqueue stream"}, + JSConsumerPullWithRateLimitErr: {Code: 400, ErrCode: 10086, Description: "consumer in pull mode can not have rate limit set"}, + JSConsumerPushMaxWaitingErr: {Code: 400, ErrCode: 10080, Description: "consumer in push mode can not set max waiting"}, + JSConsumerPushWithPriorityGroupErr: {Code: 400, ErrCode: 10178, Description: "priority groups can not be used with push consumers"}, + JSConsumerReplacementWithDifferentNameErr: {Code: 400, ErrCode: 10106, Description: "consumer replacement durable config not the same"}, + JSConsumerReplicasExceedsStream: {Code: 400, ErrCode: 10126, Description: "consumer config replica count exceeds parent stream"}, + JSConsumerReplicasShouldMatchStream: {Code: 400, ErrCode: 10134, Description: "consumer config replicas must match interest retention stream's replicas"}, + JSConsumerSmallHeartbeatErr: {Code: 400, ErrCode: 10083, Description: "consumer idle heartbeat needs to be >= 100ms"}, + JSConsumerStoreFailedErrF: {Code: 500, ErrCode: 10104, Description: "error creating store for consumer: {err}"}, + JSConsumerWQConsumerNotDeliverAllErr: {Code: 400, ErrCode: 10101, Description: "consumer must be deliver all on workqueue stream"}, + JSConsumerWQConsumerNotUniqueErr: {Code: 400, ErrCode: 10100, Description: "filtered consumer not unique on workqueue stream"}, + JSConsumerWQMultipleUnfilteredErr: {Code: 400, ErrCode: 10099, Description: "multiple non-filtered consumers not allowed on workqueue stream"}, + JSConsumerWQRequiresExplicitAckErr: {Code: 400, ErrCode: 10098, Description: "workqueue stream requires explicit ack"}, + JSConsumerWithFlowControlNeedsHeartbeats: {Code: 400, ErrCode: 10108, Description: "consumer with flow control also needs heartbeats"}, + JSInsufficientResourcesErr: {Code: 503, ErrCode: 10023, Description: "insufficient resources"}, + JSInvalidJSONErr: {Code: 400, ErrCode: 10025, Description: "invalid JSON: {err}"}, + JSMaximumConsumersLimitErr: {Code: 400, ErrCode: 10026, Description: "maximum consumers limit reached"}, + JSMaximumStreamsLimitErr: {Code: 400, ErrCode: 10027, Description: "maximum number of streams reached"}, + JSMemoryResourcesExceededErr: {Code: 500, ErrCode: 10028, Description: "insufficient memory resources available"}, + JSMessageTTLDisabledErr: {Code: 400, ErrCode: 10166, Description: "per-message TTL is disabled"}, + JSMessageTTLInvalidErr: {Code: 400, ErrCode: 10165, Description: "invalid per-message TTL"}, + JSMirrorConsumerSetupFailedErrF: {Code: 500, ErrCode: 10029, Description: "{err}"}, + JSMirrorInvalidStreamName: {Code: 400, ErrCode: 10142, Description: "mirrored stream name is invalid"}, + JSMirrorInvalidSubjectFilter: {Code: 400, ErrCode: 10151, Description: "mirror transform source: {err}"}, + JSMirrorInvalidTransformDestination: {Code: 400, ErrCode: 10154, Description: "mirror transform: {err}"}, + JSMirrorMaxMessageSizeTooBigErr: {Code: 400, ErrCode: 10030, Description: "stream mirror must have max message size >= source"}, + JSMirrorMultipleFiltersNotAllowed: {Code: 400, ErrCode: 10150, Description: "mirror with multiple subject transforms cannot also have a single subject filter"}, + JSMirrorOverlappingSubjectFilters: {Code: 400, ErrCode: 10152, Description: "mirror subject filters can not overlap"}, + JSMirrorWithFirstSeqErr: {Code: 400, ErrCode: 10143, Description: "stream mirrors can not have first sequence configured"}, + JSMirrorWithSourcesErr: {Code: 400, ErrCode: 10031, Description: "stream mirrors can not also contain other sources"}, + JSMirrorWithStartSeqAndTimeErr: {Code: 400, ErrCode: 10032, Description: "stream mirrors can not have both start seq and start time configured"}, + JSMirrorWithSubjectFiltersErr: {Code: 400, ErrCode: 10033, Description: "stream mirrors can not contain filtered subjects"}, + JSMirrorWithSubjectsErr: {Code: 400, ErrCode: 10034, Description: "stream mirrors can not contain subjects"}, + JSNoAccountErr: {Code: 503, ErrCode: 10035, Description: "account not found"}, + JSNoLimitsErr: {Code: 400, ErrCode: 10120, Description: "no JetStream default or applicable tiered limit present"}, + JSNoMessageFoundErr: {Code: 404, ErrCode: 10037, Description: "no message found"}, + JSNotEmptyRequestErr: {Code: 400, ErrCode: 10038, Description: "expected an empty request payload"}, + JSNotEnabledErr: {Code: 503, ErrCode: 10076, Description: "JetStream not enabled"}, + JSNotEnabledForAccountErr: {Code: 503, ErrCode: 10039, Description: "JetStream not enabled for account"}, + JSPedanticErrF: {Code: 400, ErrCode: 10157, Description: "pedantic mode: {err}"}, + JSPeerRemapErr: {Code: 503, ErrCode: 10075, Description: "peer remap failed"}, + JSRaftGeneralErrF: {Code: 500, ErrCode: 10041, Description: "{err}"}, + JSReplicasCountCannotBeNegative: {Code: 400, ErrCode: 10133, Description: "replicas count cannot be negative"}, + JSRestoreSubscribeFailedErrF: {Code: 500, ErrCode: 10042, Description: "JetStream unable to subscribe to restore snapshot {subject}: {err}"}, + JSSequenceNotFoundErrF: {Code: 400, ErrCode: 10043, Description: "sequence {seq} not found"}, + JSSnapshotDeliverSubjectInvalidErr: {Code: 400, ErrCode: 10015, Description: "deliver subject not valid"}, + JSSourceConsumerSetupFailedErrF: {Code: 500, ErrCode: 10045, Description: "{err}"}, + JSSourceDuplicateDetected: {Code: 400, ErrCode: 10140, Description: "duplicate source configuration detected"}, + JSSourceInvalidStreamName: {Code: 400, ErrCode: 10141, Description: "sourced stream name is invalid"}, + JSSourceInvalidSubjectFilter: {Code: 400, ErrCode: 10145, Description: "source transform source: {err}"}, + JSSourceInvalidTransformDestination: {Code: 400, ErrCode: 10146, Description: "source transform: {err}"}, + JSSourceMaxMessageSizeTooBigErr: {Code: 400, ErrCode: 10046, Description: "stream source must have max message size >= target"}, + JSSourceMultipleFiltersNotAllowed: {Code: 400, ErrCode: 10144, Description: "source with multiple subject transforms cannot also have a single subject filter"}, + JSSourceOverlappingSubjectFilters: {Code: 400, ErrCode: 10147, Description: "source filters can not overlap"}, + JSStorageResourcesExceededErr: {Code: 500, ErrCode: 10047, Description: "insufficient storage resources available"}, + JSStreamAssignmentErrF: {Code: 500, ErrCode: 10048, Description: "{err}"}, + JSStreamCreateErrF: {Code: 500, ErrCode: 10049, Description: "{err}"}, + JSStreamDeleteErrF: {Code: 500, ErrCode: 10050, Description: "{err}"}, + JSStreamDuplicateMessageConflict: {Code: 409, ErrCode: 10158, Description: "duplicate message id is in process"}, + JSStreamExpectedLastSeqPerSubjectNotReady: {Code: 503, ErrCode: 10163, Description: "expected last sequence per subject temporarily unavailable"}, + JSStreamExternalApiOverlapErrF: {Code: 400, ErrCode: 10021, Description: "stream external api prefix {prefix} must not overlap with {subject}"}, + JSStreamExternalDelPrefixOverlapsErrF: {Code: 400, ErrCode: 10022, Description: "stream external delivery prefix {prefix} overlaps with stream subject {subject}"}, + JSStreamGeneralErrorF: {Code: 500, ErrCode: 10051, Description: "{err}"}, + JSStreamHeaderExceedsMaximumErr: {Code: 400, ErrCode: 10097, Description: "header size exceeds maximum allowed of 64k"}, + JSStreamInfoMaxSubjectsErr: {Code: 500, ErrCode: 10117, Description: "subject details would exceed maximum allowed"}, + JSStreamInvalidConfigF: {Code: 500, ErrCode: 10052, Description: "{err}"}, + JSStreamInvalidErr: {Code: 500, ErrCode: 10096, Description: "stream not valid"}, + JSStreamInvalidExternalDeliverySubjErrF: {Code: 400, ErrCode: 10024, Description: "stream external delivery prefix {prefix} must not contain wildcards"}, + JSStreamLimitsErrF: {Code: 500, ErrCode: 10053, Description: "{err}"}, + JSStreamMaxBytesRequired: {Code: 400, ErrCode: 10113, Description: "account requires a stream config to have max bytes set"}, + JSStreamMaxStreamBytesExceeded: {Code: 400, ErrCode: 10122, Description: "stream max bytes exceeds account limit max stream bytes"}, + JSStreamMessageExceedsMaximumErr: {Code: 400, ErrCode: 10054, Description: "message size exceeds maximum allowed"}, + JSStreamMirrorNotUpdatableErr: {Code: 400, ErrCode: 10055, Description: "stream mirror configuration can not be updated"}, + JSStreamMismatchErr: {Code: 400, ErrCode: 10056, Description: "stream name in subject does not match request"}, + JSStreamMoveAndScaleErr: {Code: 400, ErrCode: 10123, Description: "can not move and scale a stream in a single update"}, + JSStreamMoveInProgressF: {Code: 400, ErrCode: 10124, Description: "stream move already in progress: {msg}"}, + JSStreamMoveNotInProgress: {Code: 400, ErrCode: 10129, Description: "stream move not in progress"}, + JSStreamMsgDeleteFailedF: {Code: 500, ErrCode: 10057, Description: "{err}"}, + JSStreamNameContainsPathSeparatorsErr: {Code: 400, ErrCode: 10128, Description: "Stream name can not contain path separators"}, + JSStreamNameExistErr: {Code: 400, ErrCode: 10058, Description: "stream name already in use with a different configuration"}, + JSStreamNameExistRestoreFailedErr: {Code: 400, ErrCode: 10130, Description: "stream name already in use, cannot restore"}, + JSStreamNotFoundErr: {Code: 404, ErrCode: 10059, Description: "stream not found"}, + JSStreamNotMatchErr: {Code: 400, ErrCode: 10060, Description: "expected stream does not match"}, + JSStreamOfflineErr: {Code: 500, ErrCode: 10118, Description: "stream is offline"}, + JSStreamOfflineReasonErrF: {Code: 500, ErrCode: 10194, Description: "stream is offline: {err}"}, + JSStreamPurgeFailedF: {Code: 500, ErrCode: 10110, Description: "{err}"}, + JSStreamReplicasNotSupportedErr: {Code: 500, ErrCode: 10074, Description: "replicas > 1 not supported in non-clustered mode"}, + JSStreamReplicasNotUpdatableErr: {Code: 400, ErrCode: 10061, Description: "Replicas configuration can not be updated"}, + JSStreamRestoreErrF: {Code: 500, ErrCode: 10062, Description: "restore failed: {err}"}, + JSStreamRollupFailedF: {Code: 500, ErrCode: 10111, Description: "{err}"}, + JSStreamSealedErr: {Code: 400, ErrCode: 10109, Description: "invalid operation on sealed stream"}, + JSStreamSequenceNotMatchErr: {Code: 503, ErrCode: 10063, Description: "expected stream sequence does not match"}, + JSStreamSnapshotErrF: {Code: 500, ErrCode: 10064, Description: "snapshot failed: {err}"}, + JSStreamStoreFailedF: {Code: 503, ErrCode: 10077, Description: "{err}"}, + JSStreamSubjectOverlapErr: {Code: 400, ErrCode: 10065, Description: "subjects overlap with an existing stream"}, + JSStreamTemplateCreateErrF: {Code: 500, ErrCode: 10066, Description: "{err}"}, + JSStreamTemplateDeleteErrF: {Code: 500, ErrCode: 10067, Description: "{err}"}, + JSStreamTemplateNotFoundErr: {Code: 404, ErrCode: 10068, Description: "template not found"}, + JSStreamTooManyRequests: {Code: 429, ErrCode: 10167, Description: "too many requests"}, + JSStreamTransformInvalidDestination: {Code: 400, ErrCode: 10156, Description: "stream transform: {err}"}, + JSStreamTransformInvalidSource: {Code: 400, ErrCode: 10155, Description: "stream transform source: {err}"}, + JSStreamUpdateErrF: {Code: 500, ErrCode: 10069, Description: "{err}"}, + JSStreamWrongLastMsgIDErrF: {Code: 400, ErrCode: 10070, Description: "wrong last msg ID: {id}"}, + JSStreamWrongLastSequenceConstantErr: {Code: 400, ErrCode: 10164, Description: "wrong last sequence"}, + JSStreamWrongLastSequenceErrF: {Code: 400, ErrCode: 10071, Description: "wrong last sequence: {seq}"}, + JSTempStorageFailedErr: {Code: 500, ErrCode: 10072, Description: "JetStream unable to open temp storage for restore"}, + JSTemplateNameNotMatchSubjectErr: {Code: 400, ErrCode: 10073, Description: "template name in subject does not match request"}, + } + // ErrJetStreamNotClustered Deprecated by JSClusterNotActiveErr ApiError, use IsNatsError() for comparisons + ErrJetStreamNotClustered = ApiErrors[JSClusterNotActiveErr] + // ErrJetStreamNotAssigned Deprecated by JSClusterNotAssignedErr ApiError, use IsNatsError() for comparisons + ErrJetStreamNotAssigned = ApiErrors[JSClusterNotAssignedErr] + // ErrJetStreamNotLeader Deprecated by JSClusterNotLeaderErr ApiError, use IsNatsError() for comparisons + ErrJetStreamNotLeader = ApiErrors[JSClusterNotLeaderErr] + // ErrJetStreamConsumerAlreadyUsed Deprecated by JSConsumerNameExistErr ApiError, use IsNatsError() for comparisons + ErrJetStreamConsumerAlreadyUsed = ApiErrors[JSConsumerNameExistErr] + // ErrJetStreamResourcesExceeded Deprecated by JSInsufficientResourcesErr ApiError, use IsNatsError() for comparisons + ErrJetStreamResourcesExceeded = ApiErrors[JSInsufficientResourcesErr] + // ErrMemoryResourcesExceeded Deprecated by JSMemoryResourcesExceededErr ApiError, use IsNatsError() for comparisons + ErrMemoryResourcesExceeded = ApiErrors[JSMemoryResourcesExceededErr] + // ErrJetStreamNotEnabled Deprecated by JSNotEnabledErr ApiError, use IsNatsError() for comparisons + ErrJetStreamNotEnabled = ApiErrors[JSNotEnabledErr] + // ErrStorageResourcesExceeded Deprecated by JSStorageResourcesExceededErr ApiError, use IsNatsError() for comparisons + ErrStorageResourcesExceeded = ApiErrors[JSStorageResourcesExceededErr] + // ErrJetStreamStreamAlreadyUsed Deprecated by JSStreamNameExistErr ApiError, use IsNatsError() for comparisons + ErrJetStreamStreamAlreadyUsed = ApiErrors[JSStreamNameExistErr] + // ErrJetStreamStreamNotFound Deprecated by JSStreamNotFoundErr ApiError, use IsNatsError() for comparisons + ErrJetStreamStreamNotFound = ApiErrors[JSStreamNotFoundErr] + // ErrReplicasNotSupported Deprecated by JSStreamReplicasNotSupportedErr ApiError, use IsNatsError() for comparisons + ErrReplicasNotSupported = ApiErrors[JSStreamReplicasNotSupportedErr] +) + +// NewJSAccountResourcesExceededError creates a new JSAccountResourcesExceededErr error: "resource limits exceeded for account" +func NewJSAccountResourcesExceededError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSAccountResourcesExceededErr] +} + +// NewJSBadRequestError creates a new JSBadRequestErr error: "bad request" +func NewJSBadRequestError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSBadRequestErr] +} + +// NewJSClusterIncompleteError creates a new JSClusterIncompleteErr error: "incomplete results" +func NewJSClusterIncompleteError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterIncompleteErr] +} + +// NewJSClusterNoPeersError creates a new JSClusterNoPeersErrF error: "{err}" +func NewJSClusterNoPeersError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSClusterNoPeersErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSClusterNotActiveError creates a new JSClusterNotActiveErr error: "JetStream not in clustered mode" +func NewJSClusterNotActiveError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterNotActiveErr] +} + +// NewJSClusterNotAssignedError creates a new JSClusterNotAssignedErr error: "JetStream cluster not assigned to this server" +func NewJSClusterNotAssignedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterNotAssignedErr] +} + +// NewJSClusterNotAvailError creates a new JSClusterNotAvailErr error: "JetStream system temporarily unavailable" +func NewJSClusterNotAvailError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterNotAvailErr] +} + +// NewJSClusterNotLeaderError creates a new JSClusterNotLeaderErr error: "JetStream cluster can not handle request" +func NewJSClusterNotLeaderError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterNotLeaderErr] +} + +// NewJSClusterPeerNotMemberError creates a new JSClusterPeerNotMemberErr error: "peer not a member" +func NewJSClusterPeerNotMemberError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterPeerNotMemberErr] +} + +// NewJSClusterRequiredError creates a new JSClusterRequiredErr error: "JetStream clustering support required" +func NewJSClusterRequiredError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterRequiredErr] +} + +// NewJSClusterServerMemberChangeInflightError creates a new JSClusterServerMemberChangeInflightErr error: "cluster member change is in progress" +func NewJSClusterServerMemberChangeInflightError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterServerMemberChangeInflightErr] +} + +// NewJSClusterServerNotMemberError creates a new JSClusterServerNotMemberErr error: "server is not a member of the cluster" +func NewJSClusterServerNotMemberError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterServerNotMemberErr] +} + +// NewJSClusterTagsError creates a new JSClusterTagsErr error: "tags placement not supported for operation" +func NewJSClusterTagsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterTagsErr] +} + +// NewJSClusterUnSupportFeatureError creates a new JSClusterUnSupportFeatureErr error: "not currently supported in clustered mode" +func NewJSClusterUnSupportFeatureError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSClusterUnSupportFeatureErr] +} + +// NewJSConsumerAlreadyExistsError creates a new JSConsumerAlreadyExists error: "consumer already exists" +func NewJSConsumerAlreadyExistsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerAlreadyExists] +} + +// NewJSConsumerBadDurableNameError creates a new JSConsumerBadDurableNameErr error: "durable name can not contain '.', '*', '>'" +func NewJSConsumerBadDurableNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerBadDurableNameErr] +} + +// NewJSConsumerConfigRequiredError creates a new JSConsumerConfigRequiredErr error: "consumer config required" +func NewJSConsumerConfigRequiredError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerConfigRequiredErr] +} + +// NewJSConsumerCreateDurableAndNameMismatchError creates a new JSConsumerCreateDurableAndNameMismatch error: "Consumer Durable and Name have to be equal if both are provided" +func NewJSConsumerCreateDurableAndNameMismatchError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerCreateDurableAndNameMismatch] +} + +// NewJSConsumerCreateError creates a new JSConsumerCreateErrF error: "{err}" +func NewJSConsumerCreateError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerCreateErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerCreateFilterSubjectMismatchError creates a new JSConsumerCreateFilterSubjectMismatchErr error: "Consumer create request did not match filtered subject from create subject" +func NewJSConsumerCreateFilterSubjectMismatchError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerCreateFilterSubjectMismatchErr] +} + +// NewJSConsumerDeliverCycleError creates a new JSConsumerDeliverCycleErr error: "consumer deliver subject forms a cycle" +func NewJSConsumerDeliverCycleError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDeliverCycleErr] +} + +// NewJSConsumerDeliverToWildcardsError creates a new JSConsumerDeliverToWildcardsErr error: "consumer deliver subject has wildcards" +func NewJSConsumerDeliverToWildcardsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDeliverToWildcardsErr] +} + +// NewJSConsumerDescriptionTooLongError creates a new JSConsumerDescriptionTooLongErrF error: "consumer description is too long, maximum allowed is {max}" +func NewJSConsumerDescriptionTooLongError(max interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerDescriptionTooLongErrF] + args := e.toReplacerArgs([]interface{}{"{max}", max}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerDirectRequiresEphemeralError creates a new JSConsumerDirectRequiresEphemeralErr error: "consumer direct requires an ephemeral consumer" +func NewJSConsumerDirectRequiresEphemeralError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDirectRequiresEphemeralErr] +} + +// NewJSConsumerDirectRequiresPushError creates a new JSConsumerDirectRequiresPushErr error: "consumer direct requires a push based consumer" +func NewJSConsumerDirectRequiresPushError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDirectRequiresPushErr] +} + +// NewJSConsumerDoesNotExistError creates a new JSConsumerDoesNotExist error: "consumer does not exist" +func NewJSConsumerDoesNotExistError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDoesNotExist] +} + +// NewJSConsumerDuplicateFilterSubjectsError creates a new JSConsumerDuplicateFilterSubjects error: "consumer cannot have both FilterSubject and FilterSubjects specified" +func NewJSConsumerDuplicateFilterSubjectsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDuplicateFilterSubjects] +} + +// NewJSConsumerDurableNameNotInSubjectError creates a new JSConsumerDurableNameNotInSubjectErr error: "consumer expected to be durable but no durable name set in subject" +func NewJSConsumerDurableNameNotInSubjectError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDurableNameNotInSubjectErr] +} + +// NewJSConsumerDurableNameNotMatchSubjectError creates a new JSConsumerDurableNameNotMatchSubjectErr error: "consumer name in subject does not match durable name in request" +func NewJSConsumerDurableNameNotMatchSubjectError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDurableNameNotMatchSubjectErr] +} + +// NewJSConsumerDurableNameNotSetError creates a new JSConsumerDurableNameNotSetErr error: "consumer expected to be durable but a durable name was not set" +func NewJSConsumerDurableNameNotSetError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerDurableNameNotSetErr] +} + +// NewJSConsumerEmptyFilterError creates a new JSConsumerEmptyFilter error: "consumer filter in FilterSubjects cannot be empty" +func NewJSConsumerEmptyFilterError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerEmptyFilter] +} + +// NewJSConsumerEmptyGroupNameError creates a new JSConsumerEmptyGroupName error: "Group name cannot be an empty string" +func NewJSConsumerEmptyGroupNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerEmptyGroupName] +} + +// NewJSConsumerEphemeralWithDurableInSubjectError creates a new JSConsumerEphemeralWithDurableInSubjectErr error: "consumer expected to be ephemeral but detected a durable name set in subject" +func NewJSConsumerEphemeralWithDurableInSubjectError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerEphemeralWithDurableInSubjectErr] +} + +// NewJSConsumerEphemeralWithDurableNameError creates a new JSConsumerEphemeralWithDurableNameErr error: "consumer expected to be ephemeral but a durable name was set in request" +func NewJSConsumerEphemeralWithDurableNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerEphemeralWithDurableNameErr] +} + +// NewJSConsumerExistingActiveError creates a new JSConsumerExistingActiveErr error: "consumer already exists and is still active" +func NewJSConsumerExistingActiveError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerExistingActiveErr] +} + +// NewJSConsumerFCRequiresPushError creates a new JSConsumerFCRequiresPushErr error: "consumer flow control requires a push based consumer" +func NewJSConsumerFCRequiresPushError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerFCRequiresPushErr] +} + +// NewJSConsumerFilterNotSubsetError creates a new JSConsumerFilterNotSubsetErr error: "consumer filter subject is not a valid subset of the interest subjects" +func NewJSConsumerFilterNotSubsetError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerFilterNotSubsetErr] +} + +// NewJSConsumerHBRequiresPushError creates a new JSConsumerHBRequiresPushErr error: "consumer idle heartbeat requires a push based consumer" +func NewJSConsumerHBRequiresPushError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerHBRequiresPushErr] +} + +// NewJSConsumerInactiveThresholdExcessError creates a new JSConsumerInactiveThresholdExcess error: "consumer inactive threshold exceeds system limit of {limit}" +func NewJSConsumerInactiveThresholdExcessError(limit interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerInactiveThresholdExcess] + args := e.toReplacerArgs([]interface{}{"{limit}", limit}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerInvalidDeliverSubjectError creates a new JSConsumerInvalidDeliverSubject error: "invalid push consumer deliver subject" +func NewJSConsumerInvalidDeliverSubjectError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerInvalidDeliverSubject] +} + +// NewJSConsumerInvalidGroupNameError creates a new JSConsumerInvalidGroupNameErr error: "Valid priority group name must match A-Z, a-z, 0-9, -_/=)+ and may not exceed 16 characters" +func NewJSConsumerInvalidGroupNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerInvalidGroupNameErr] +} + +// NewJSConsumerInvalidPolicyError creates a new JSConsumerInvalidPolicyErrF error: "{err}" +func NewJSConsumerInvalidPolicyError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerInvalidPolicyErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerInvalidPriorityGroupError creates a new JSConsumerInvalidPriorityGroupErr error: "Provided priority group does not exist for this consumer" +func NewJSConsumerInvalidPriorityGroupError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerInvalidPriorityGroupErr] +} + +// NewJSConsumerInvalidSamplingError creates a new JSConsumerInvalidSamplingErrF error: "failed to parse consumer sampling configuration: {err}" +func NewJSConsumerInvalidSamplingError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerInvalidSamplingErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerMaxDeliverBackoffError creates a new JSConsumerMaxDeliverBackoffErr error: "max deliver is required to be > length of backoff values" +func NewJSConsumerMaxDeliverBackoffError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerMaxDeliverBackoffErr] +} + +// NewJSConsumerMaxPendingAckExcessError creates a new JSConsumerMaxPendingAckExcessErrF error: "consumer max ack pending exceeds system limit of {limit}" +func NewJSConsumerMaxPendingAckExcessError(limit interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerMaxPendingAckExcessErrF] + args := e.toReplacerArgs([]interface{}{"{limit}", limit}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerMaxPendingAckPolicyRequiredError creates a new JSConsumerMaxPendingAckPolicyRequiredErr error: "consumer requires ack policy for max ack pending" +func NewJSConsumerMaxPendingAckPolicyRequiredError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerMaxPendingAckPolicyRequiredErr] +} + +// NewJSConsumerMaxRequestBatchExceededError creates a new JSConsumerMaxRequestBatchExceededF error: "consumer max request batch exceeds server limit of {limit}" +func NewJSConsumerMaxRequestBatchExceededError(limit interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerMaxRequestBatchExceededF] + args := e.toReplacerArgs([]interface{}{"{limit}", limit}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerMaxRequestBatchNegativeError creates a new JSConsumerMaxRequestBatchNegativeErr error: "consumer max request batch needs to be > 0" +func NewJSConsumerMaxRequestBatchNegativeError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerMaxRequestBatchNegativeErr] +} + +// NewJSConsumerMaxRequestExpiresToSmallError creates a new JSConsumerMaxRequestExpiresToSmall error: "consumer max request expires needs to be >= 1ms" +func NewJSConsumerMaxRequestExpiresToSmallError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerMaxRequestExpiresToSmall] +} + +// NewJSConsumerMaxWaitingNegativeError creates a new JSConsumerMaxWaitingNegativeErr error: "consumer max waiting needs to be positive" +func NewJSConsumerMaxWaitingNegativeError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerMaxWaitingNegativeErr] +} + +// NewJSConsumerMetadataLengthError creates a new JSConsumerMetadataLengthErrF error: "consumer metadata exceeds maximum size of {limit}" +func NewJSConsumerMetadataLengthError(limit interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerMetadataLengthErrF] + args := e.toReplacerArgs([]interface{}{"{limit}", limit}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerMultipleFiltersNotAllowedError creates a new JSConsumerMultipleFiltersNotAllowed error: "consumer with multiple subject filters cannot use subject based API" +func NewJSConsumerMultipleFiltersNotAllowedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerMultipleFiltersNotAllowed] +} + +// NewJSConsumerNameContainsPathSeparatorsError creates a new JSConsumerNameContainsPathSeparatorsErr error: "Consumer name can not contain path separators" +func NewJSConsumerNameContainsPathSeparatorsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerNameContainsPathSeparatorsErr] +} + +// NewJSConsumerNameExistError creates a new JSConsumerNameExistErr error: "consumer name already in use" +func NewJSConsumerNameExistError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerNameExistErr] +} + +// NewJSConsumerNameTooLongError creates a new JSConsumerNameTooLongErrF error: "consumer name is too long, maximum allowed is {max}" +func NewJSConsumerNameTooLongError(max interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerNameTooLongErrF] + args := e.toReplacerArgs([]interface{}{"{max}", max}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerNotFoundError creates a new JSConsumerNotFoundErr error: "consumer not found" +func NewJSConsumerNotFoundError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerNotFoundErr] +} + +// NewJSConsumerOfflineError creates a new JSConsumerOfflineErr error: "consumer is offline" +func NewJSConsumerOfflineError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerOfflineErr] +} + +// NewJSConsumerOfflineReasonError creates a new JSConsumerOfflineReasonErrF error: "consumer is offline: {err}" +func NewJSConsumerOfflineReasonError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerOfflineReasonErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerOnMappedError creates a new JSConsumerOnMappedErr error: "consumer direct on a mapped consumer" +func NewJSConsumerOnMappedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerOnMappedErr] +} + +// NewJSConsumerOverlappingSubjectFiltersError creates a new JSConsumerOverlappingSubjectFilters error: "consumer subject filters cannot overlap" +func NewJSConsumerOverlappingSubjectFiltersError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerOverlappingSubjectFilters] +} + +// NewJSConsumerPriorityPolicyWithoutGroupError creates a new JSConsumerPriorityPolicyWithoutGroup error: "Setting PriorityPolicy requires at least one PriorityGroup to be set" +func NewJSConsumerPriorityPolicyWithoutGroupError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerPriorityPolicyWithoutGroup] +} + +// NewJSConsumerPullNotDurableError creates a new JSConsumerPullNotDurableErr error: "consumer in pull mode requires a durable name" +func NewJSConsumerPullNotDurableError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerPullNotDurableErr] +} + +// NewJSConsumerPullRequiresAckError creates a new JSConsumerPullRequiresAckErr error: "consumer in pull mode requires explicit ack policy on workqueue stream" +func NewJSConsumerPullRequiresAckError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerPullRequiresAckErr] +} + +// NewJSConsumerPullWithRateLimitError creates a new JSConsumerPullWithRateLimitErr error: "consumer in pull mode can not have rate limit set" +func NewJSConsumerPullWithRateLimitError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerPullWithRateLimitErr] +} + +// NewJSConsumerPushMaxWaitingError creates a new JSConsumerPushMaxWaitingErr error: "consumer in push mode can not set max waiting" +func NewJSConsumerPushMaxWaitingError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerPushMaxWaitingErr] +} + +// NewJSConsumerPushWithPriorityGroupError creates a new JSConsumerPushWithPriorityGroupErr error: "priority groups can not be used with push consumers" +func NewJSConsumerPushWithPriorityGroupError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerPushWithPriorityGroupErr] +} + +// NewJSConsumerReplacementWithDifferentNameError creates a new JSConsumerReplacementWithDifferentNameErr error: "consumer replacement durable config not the same" +func NewJSConsumerReplacementWithDifferentNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerReplacementWithDifferentNameErr] +} + +// NewJSConsumerReplicasExceedsStreamError creates a new JSConsumerReplicasExceedsStream error: "consumer config replica count exceeds parent stream" +func NewJSConsumerReplicasExceedsStreamError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerReplicasExceedsStream] +} + +// NewJSConsumerReplicasShouldMatchStreamError creates a new JSConsumerReplicasShouldMatchStream error: "consumer config replicas must match interest retention stream's replicas" +func NewJSConsumerReplicasShouldMatchStreamError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerReplicasShouldMatchStream] +} + +// NewJSConsumerSmallHeartbeatError creates a new JSConsumerSmallHeartbeatErr error: "consumer idle heartbeat needs to be >= 100ms" +func NewJSConsumerSmallHeartbeatError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerSmallHeartbeatErr] +} + +// NewJSConsumerStoreFailedError creates a new JSConsumerStoreFailedErrF error: "error creating store for consumer: {err}" +func NewJSConsumerStoreFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSConsumerStoreFailedErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSConsumerWQConsumerNotDeliverAllError creates a new JSConsumerWQConsumerNotDeliverAllErr error: "consumer must be deliver all on workqueue stream" +func NewJSConsumerWQConsumerNotDeliverAllError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerWQConsumerNotDeliverAllErr] +} + +// NewJSConsumerWQConsumerNotUniqueError creates a new JSConsumerWQConsumerNotUniqueErr error: "filtered consumer not unique on workqueue stream" +func NewJSConsumerWQConsumerNotUniqueError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerWQConsumerNotUniqueErr] +} + +// NewJSConsumerWQMultipleUnfilteredError creates a new JSConsumerWQMultipleUnfilteredErr error: "multiple non-filtered consumers not allowed on workqueue stream" +func NewJSConsumerWQMultipleUnfilteredError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerWQMultipleUnfilteredErr] +} + +// NewJSConsumerWQRequiresExplicitAckError creates a new JSConsumerWQRequiresExplicitAckErr error: "workqueue stream requires explicit ack" +func NewJSConsumerWQRequiresExplicitAckError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerWQRequiresExplicitAckErr] +} + +// NewJSConsumerWithFlowControlNeedsHeartbeatsError creates a new JSConsumerWithFlowControlNeedsHeartbeats error: "consumer with flow control also needs heartbeats" +func NewJSConsumerWithFlowControlNeedsHeartbeatsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSConsumerWithFlowControlNeedsHeartbeats] +} + +// NewJSInsufficientResourcesError creates a new JSInsufficientResourcesErr error: "insufficient resources" +func NewJSInsufficientResourcesError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSInsufficientResourcesErr] +} + +// NewJSInvalidJSONError creates a new JSInvalidJSONErr error: "invalid JSON: {err}" +func NewJSInvalidJSONError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSInvalidJSONErr] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSMaximumConsumersLimitError creates a new JSMaximumConsumersLimitErr error: "maximum consumers limit reached" +func NewJSMaximumConsumersLimitError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMaximumConsumersLimitErr] +} + +// NewJSMaximumStreamsLimitError creates a new JSMaximumStreamsLimitErr error: "maximum number of streams reached" +func NewJSMaximumStreamsLimitError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMaximumStreamsLimitErr] +} + +// NewJSMemoryResourcesExceededError creates a new JSMemoryResourcesExceededErr error: "insufficient memory resources available" +func NewJSMemoryResourcesExceededError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMemoryResourcesExceededErr] +} + +// NewJSMessageTTLDisabledError creates a new JSMessageTTLDisabledErr error: "per-message TTL is disabled" +func NewJSMessageTTLDisabledError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMessageTTLDisabledErr] +} + +// NewJSMessageTTLInvalidError creates a new JSMessageTTLInvalidErr error: "invalid per-message TTL" +func NewJSMessageTTLInvalidError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMessageTTLInvalidErr] +} + +// NewJSMirrorConsumerSetupFailedError creates a new JSMirrorConsumerSetupFailedErrF error: "{err}" +func NewJSMirrorConsumerSetupFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSMirrorConsumerSetupFailedErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSMirrorInvalidStreamNameError creates a new JSMirrorInvalidStreamName error: "mirrored stream name is invalid" +func NewJSMirrorInvalidStreamNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorInvalidStreamName] +} + +// NewJSMirrorInvalidSubjectFilterError creates a new JSMirrorInvalidSubjectFilter error: "mirror transform source: {err}" +func NewJSMirrorInvalidSubjectFilterError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSMirrorInvalidSubjectFilter] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSMirrorInvalidTransformDestinationError creates a new JSMirrorInvalidTransformDestination error: "mirror transform: {err}" +func NewJSMirrorInvalidTransformDestinationError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSMirrorInvalidTransformDestination] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSMirrorMaxMessageSizeTooBigError creates a new JSMirrorMaxMessageSizeTooBigErr error: "stream mirror must have max message size >= source" +func NewJSMirrorMaxMessageSizeTooBigError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorMaxMessageSizeTooBigErr] +} + +// NewJSMirrorMultipleFiltersNotAllowedError creates a new JSMirrorMultipleFiltersNotAllowed error: "mirror with multiple subject transforms cannot also have a single subject filter" +func NewJSMirrorMultipleFiltersNotAllowedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorMultipleFiltersNotAllowed] +} + +// NewJSMirrorOverlappingSubjectFiltersError creates a new JSMirrorOverlappingSubjectFilters error: "mirror subject filters can not overlap" +func NewJSMirrorOverlappingSubjectFiltersError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorOverlappingSubjectFilters] +} + +// NewJSMirrorWithFirstSeqError creates a new JSMirrorWithFirstSeqErr error: "stream mirrors can not have first sequence configured" +func NewJSMirrorWithFirstSeqError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorWithFirstSeqErr] +} + +// NewJSMirrorWithSourcesError creates a new JSMirrorWithSourcesErr error: "stream mirrors can not also contain other sources" +func NewJSMirrorWithSourcesError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorWithSourcesErr] +} + +// NewJSMirrorWithStartSeqAndTimeError creates a new JSMirrorWithStartSeqAndTimeErr error: "stream mirrors can not have both start seq and start time configured" +func NewJSMirrorWithStartSeqAndTimeError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorWithStartSeqAndTimeErr] +} + +// NewJSMirrorWithSubjectFiltersError creates a new JSMirrorWithSubjectFiltersErr error: "stream mirrors can not contain filtered subjects" +func NewJSMirrorWithSubjectFiltersError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorWithSubjectFiltersErr] +} + +// NewJSMirrorWithSubjectsError creates a new JSMirrorWithSubjectsErr error: "stream mirrors can not contain subjects" +func NewJSMirrorWithSubjectsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSMirrorWithSubjectsErr] +} + +// NewJSNoAccountError creates a new JSNoAccountErr error: "account not found" +func NewJSNoAccountError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSNoAccountErr] +} + +// NewJSNoLimitsError creates a new JSNoLimitsErr error: "no JetStream default or applicable tiered limit present" +func NewJSNoLimitsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSNoLimitsErr] +} + +// NewJSNoMessageFoundError creates a new JSNoMessageFoundErr error: "no message found" +func NewJSNoMessageFoundError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSNoMessageFoundErr] +} + +// NewJSNotEmptyRequestError creates a new JSNotEmptyRequestErr error: "expected an empty request payload" +func NewJSNotEmptyRequestError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSNotEmptyRequestErr] +} + +// NewJSNotEnabledError creates a new JSNotEnabledErr error: "JetStream not enabled" +func NewJSNotEnabledError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSNotEnabledErr] +} + +// NewJSNotEnabledForAccountError creates a new JSNotEnabledForAccountErr error: "JetStream not enabled for account" +func NewJSNotEnabledForAccountError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSNotEnabledForAccountErr] +} + +// NewJSPedanticError creates a new JSPedanticErrF error: "pedantic mode: {err}" +func NewJSPedanticError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSPedanticErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSPeerRemapError creates a new JSPeerRemapErr error: "peer remap failed" +func NewJSPeerRemapError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSPeerRemapErr] +} + +// NewJSRaftGeneralError creates a new JSRaftGeneralErrF error: "{err}" +func NewJSRaftGeneralError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSRaftGeneralErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSReplicasCountCannotBeNegativeError creates a new JSReplicasCountCannotBeNegative error: "replicas count cannot be negative" +func NewJSReplicasCountCannotBeNegativeError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSReplicasCountCannotBeNegative] +} + +// NewJSRestoreSubscribeFailedError creates a new JSRestoreSubscribeFailedErrF error: "JetStream unable to subscribe to restore snapshot {subject}: {err}" +func NewJSRestoreSubscribeFailedError(err error, subject interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSRestoreSubscribeFailedErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err, "{subject}", subject}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSSequenceNotFoundError creates a new JSSequenceNotFoundErrF error: "sequence {seq} not found" +func NewJSSequenceNotFoundError(seq uint64, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSSequenceNotFoundErrF] + args := e.toReplacerArgs([]interface{}{"{seq}", seq}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSSnapshotDeliverSubjectInvalidError creates a new JSSnapshotDeliverSubjectInvalidErr error: "deliver subject not valid" +func NewJSSnapshotDeliverSubjectInvalidError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSSnapshotDeliverSubjectInvalidErr] +} + +// NewJSSourceConsumerSetupFailedError creates a new JSSourceConsumerSetupFailedErrF error: "{err}" +func NewJSSourceConsumerSetupFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSSourceConsumerSetupFailedErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSSourceDuplicateDetectedError creates a new JSSourceDuplicateDetected error: "duplicate source configuration detected" +func NewJSSourceDuplicateDetectedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSSourceDuplicateDetected] +} + +// NewJSSourceInvalidStreamNameError creates a new JSSourceInvalidStreamName error: "sourced stream name is invalid" +func NewJSSourceInvalidStreamNameError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSSourceInvalidStreamName] +} + +// NewJSSourceInvalidSubjectFilterError creates a new JSSourceInvalidSubjectFilter error: "source transform source: {err}" +func NewJSSourceInvalidSubjectFilterError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSSourceInvalidSubjectFilter] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSSourceInvalidTransformDestinationError creates a new JSSourceInvalidTransformDestination error: "source transform: {err}" +func NewJSSourceInvalidTransformDestinationError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSSourceInvalidTransformDestination] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSSourceMaxMessageSizeTooBigError creates a new JSSourceMaxMessageSizeTooBigErr error: "stream source must have max message size >= target" +func NewJSSourceMaxMessageSizeTooBigError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSSourceMaxMessageSizeTooBigErr] +} + +// NewJSSourceMultipleFiltersNotAllowedError creates a new JSSourceMultipleFiltersNotAllowed error: "source with multiple subject transforms cannot also have a single subject filter" +func NewJSSourceMultipleFiltersNotAllowedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSSourceMultipleFiltersNotAllowed] +} + +// NewJSSourceOverlappingSubjectFiltersError creates a new JSSourceOverlappingSubjectFilters error: "source filters can not overlap" +func NewJSSourceOverlappingSubjectFiltersError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSSourceOverlappingSubjectFilters] +} + +// NewJSStorageResourcesExceededError creates a new JSStorageResourcesExceededErr error: "insufficient storage resources available" +func NewJSStorageResourcesExceededError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStorageResourcesExceededErr] +} + +// NewJSStreamAssignmentError creates a new JSStreamAssignmentErrF error: "{err}" +func NewJSStreamAssignmentError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamAssignmentErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamCreateError creates a new JSStreamCreateErrF error: "{err}" +func NewJSStreamCreateError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamCreateErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamDeleteError creates a new JSStreamDeleteErrF error: "{err}" +func NewJSStreamDeleteError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamDeleteErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamDuplicateMessageConflictError creates a new JSStreamDuplicateMessageConflict error: "duplicate message id is in process" +func NewJSStreamDuplicateMessageConflictError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamDuplicateMessageConflict] +} + +// NewJSStreamExpectedLastSeqPerSubjectNotReadyError creates a new JSStreamExpectedLastSeqPerSubjectNotReady error: "expected last sequence per subject temporarily unavailable" +func NewJSStreamExpectedLastSeqPerSubjectNotReadyError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamExpectedLastSeqPerSubjectNotReady] +} + +// NewJSStreamExternalApiOverlapError creates a new JSStreamExternalApiOverlapErrF error: "stream external api prefix {prefix} must not overlap with {subject}" +func NewJSStreamExternalApiOverlapError(prefix interface{}, subject interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamExternalApiOverlapErrF] + args := e.toReplacerArgs([]interface{}{"{prefix}", prefix, "{subject}", subject}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamExternalDelPrefixOverlapsError creates a new JSStreamExternalDelPrefixOverlapsErrF error: "stream external delivery prefix {prefix} overlaps with stream subject {subject}" +func NewJSStreamExternalDelPrefixOverlapsError(prefix interface{}, subject interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamExternalDelPrefixOverlapsErrF] + args := e.toReplacerArgs([]interface{}{"{prefix}", prefix, "{subject}", subject}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamGeneralError creates a new JSStreamGeneralErrorF error: "{err}" +func NewJSStreamGeneralError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamGeneralErrorF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamHeaderExceedsMaximumError creates a new JSStreamHeaderExceedsMaximumErr error: "header size exceeds maximum allowed of 64k" +func NewJSStreamHeaderExceedsMaximumError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamHeaderExceedsMaximumErr] +} + +// NewJSStreamInfoMaxSubjectsError creates a new JSStreamInfoMaxSubjectsErr error: "subject details would exceed maximum allowed" +func NewJSStreamInfoMaxSubjectsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamInfoMaxSubjectsErr] +} + +// NewJSStreamInvalidConfigError creates a new JSStreamInvalidConfigF error: "{err}" +func NewJSStreamInvalidConfigError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamInvalidConfigF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamInvalidError creates a new JSStreamInvalidErr error: "stream not valid" +func NewJSStreamInvalidError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamInvalidErr] +} + +// NewJSStreamInvalidExternalDeliverySubjError creates a new JSStreamInvalidExternalDeliverySubjErrF error: "stream external delivery prefix {prefix} must not contain wildcards" +func NewJSStreamInvalidExternalDeliverySubjError(prefix interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamInvalidExternalDeliverySubjErrF] + args := e.toReplacerArgs([]interface{}{"{prefix}", prefix}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamLimitsError creates a new JSStreamLimitsErrF error: "{err}" +func NewJSStreamLimitsError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamLimitsErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamMaxBytesRequiredError creates a new JSStreamMaxBytesRequired error: "account requires a stream config to have max bytes set" +func NewJSStreamMaxBytesRequiredError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMaxBytesRequired] +} + +// NewJSStreamMaxStreamBytesExceededError creates a new JSStreamMaxStreamBytesExceeded error: "stream max bytes exceeds account limit max stream bytes" +func NewJSStreamMaxStreamBytesExceededError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMaxStreamBytesExceeded] +} + +// NewJSStreamMessageExceedsMaximumError creates a new JSStreamMessageExceedsMaximumErr error: "message size exceeds maximum allowed" +func NewJSStreamMessageExceedsMaximumError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMessageExceedsMaximumErr] +} + +// NewJSStreamMirrorNotUpdatableError creates a new JSStreamMirrorNotUpdatableErr error: "stream mirror configuration can not be updated" +func NewJSStreamMirrorNotUpdatableError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMirrorNotUpdatableErr] +} + +// NewJSStreamMismatchError creates a new JSStreamMismatchErr error: "stream name in subject does not match request" +func NewJSStreamMismatchError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMismatchErr] +} + +// NewJSStreamMoveAndScaleError creates a new JSStreamMoveAndScaleErr error: "can not move and scale a stream in a single update" +func NewJSStreamMoveAndScaleError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMoveAndScaleErr] +} + +// NewJSStreamMoveInProgressError creates a new JSStreamMoveInProgressF error: "stream move already in progress: {msg}" +func NewJSStreamMoveInProgressError(msg interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamMoveInProgressF] + args := e.toReplacerArgs([]interface{}{"{msg}", msg}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamMoveNotInProgressError creates a new JSStreamMoveNotInProgress error: "stream move not in progress" +func NewJSStreamMoveNotInProgressError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamMoveNotInProgress] +} + +// NewJSStreamMsgDeleteFailedError creates a new JSStreamMsgDeleteFailedF error: "{err}" +func NewJSStreamMsgDeleteFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamMsgDeleteFailedF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamNameContainsPathSeparatorsError creates a new JSStreamNameContainsPathSeparatorsErr error: "Stream name can not contain path separators" +func NewJSStreamNameContainsPathSeparatorsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamNameContainsPathSeparatorsErr] +} + +// NewJSStreamNameExistError creates a new JSStreamNameExistErr error: "stream name already in use with a different configuration" +func NewJSStreamNameExistError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamNameExistErr] +} + +// NewJSStreamNameExistRestoreFailedError creates a new JSStreamNameExistRestoreFailedErr error: "stream name already in use, cannot restore" +func NewJSStreamNameExistRestoreFailedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamNameExistRestoreFailedErr] +} + +// NewJSStreamNotFoundError creates a new JSStreamNotFoundErr error: "stream not found" +func NewJSStreamNotFoundError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamNotFoundErr] +} + +// NewJSStreamNotMatchError creates a new JSStreamNotMatchErr error: "expected stream does not match" +func NewJSStreamNotMatchError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamNotMatchErr] +} + +// NewJSStreamOfflineError creates a new JSStreamOfflineErr error: "stream is offline" +func NewJSStreamOfflineError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamOfflineErr] +} + +// NewJSStreamOfflineReasonError creates a new JSStreamOfflineReasonErrF error: "stream is offline: {err}" +func NewJSStreamOfflineReasonError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamOfflineReasonErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamPurgeFailedError creates a new JSStreamPurgeFailedF error: "{err}" +func NewJSStreamPurgeFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamPurgeFailedF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamReplicasNotSupportedError creates a new JSStreamReplicasNotSupportedErr error: "replicas > 1 not supported in non-clustered mode" +func NewJSStreamReplicasNotSupportedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamReplicasNotSupportedErr] +} + +// NewJSStreamReplicasNotUpdatableError creates a new JSStreamReplicasNotUpdatableErr error: "Replicas configuration can not be updated" +func NewJSStreamReplicasNotUpdatableError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamReplicasNotUpdatableErr] +} + +// NewJSStreamRestoreError creates a new JSStreamRestoreErrF error: "restore failed: {err}" +func NewJSStreamRestoreError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamRestoreErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamRollupFailedError creates a new JSStreamRollupFailedF error: "{err}" +func NewJSStreamRollupFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamRollupFailedF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamSealedError creates a new JSStreamSealedErr error: "invalid operation on sealed stream" +func NewJSStreamSealedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamSealedErr] +} + +// NewJSStreamSequenceNotMatchError creates a new JSStreamSequenceNotMatchErr error: "expected stream sequence does not match" +func NewJSStreamSequenceNotMatchError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamSequenceNotMatchErr] +} + +// NewJSStreamSnapshotError creates a new JSStreamSnapshotErrF error: "snapshot failed: {err}" +func NewJSStreamSnapshotError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamSnapshotErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamStoreFailedError creates a new JSStreamStoreFailedF error: "{err}" +func NewJSStreamStoreFailedError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamStoreFailedF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamSubjectOverlapError creates a new JSStreamSubjectOverlapErr error: "subjects overlap with an existing stream" +func NewJSStreamSubjectOverlapError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamSubjectOverlapErr] +} + +// NewJSStreamTemplateCreateError creates a new JSStreamTemplateCreateErrF error: "{err}" +func NewJSStreamTemplateCreateError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamTemplateCreateErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamTemplateDeleteError creates a new JSStreamTemplateDeleteErrF error: "{err}" +func NewJSStreamTemplateDeleteError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamTemplateDeleteErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamTemplateNotFoundError creates a new JSStreamTemplateNotFoundErr error: "template not found" +func NewJSStreamTemplateNotFoundError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamTemplateNotFoundErr] +} + +// NewJSStreamTooManyRequestsError creates a new JSStreamTooManyRequests error: "too many requests" +func NewJSStreamTooManyRequestsError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamTooManyRequests] +} + +// NewJSStreamTransformInvalidDestinationError creates a new JSStreamTransformInvalidDestination error: "stream transform: {err}" +func NewJSStreamTransformInvalidDestinationError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamTransformInvalidDestination] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamTransformInvalidSourceError creates a new JSStreamTransformInvalidSource error: "stream transform source: {err}" +func NewJSStreamTransformInvalidSourceError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamTransformInvalidSource] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamUpdateError creates a new JSStreamUpdateErrF error: "{err}" +func NewJSStreamUpdateError(err error, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamUpdateErrF] + args := e.toReplacerArgs([]interface{}{"{err}", err}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamWrongLastMsgIDError creates a new JSStreamWrongLastMsgIDErrF error: "wrong last msg ID: {id}" +func NewJSStreamWrongLastMsgIDError(id interface{}, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamWrongLastMsgIDErrF] + args := e.toReplacerArgs([]interface{}{"{id}", id}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSStreamWrongLastSequenceConstantError creates a new JSStreamWrongLastSequenceConstantErr error: "wrong last sequence" +func NewJSStreamWrongLastSequenceConstantError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSStreamWrongLastSequenceConstantErr] +} + +// NewJSStreamWrongLastSequenceError creates a new JSStreamWrongLastSequenceErrF error: "wrong last sequence: {seq}" +func NewJSStreamWrongLastSequenceError(seq uint64, opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + e := ApiErrors[JSStreamWrongLastSequenceErrF] + args := e.toReplacerArgs([]interface{}{"{seq}", seq}) + return &ApiError{ + Code: e.Code, + ErrCode: e.ErrCode, + Description: strings.NewReplacer(args...).Replace(e.Description), + } +} + +// NewJSTempStorageFailedError creates a new JSTempStorageFailedErr error: "JetStream unable to open temp storage for restore" +func NewJSTempStorageFailedError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSTempStorageFailedErr] +} + +// NewJSTemplateNameNotMatchSubjectError creates a new JSTemplateNameNotMatchSubjectErr error: "template name in subject does not match request" +func NewJSTemplateNameNotMatchSubjectError(opts ...ErrorOption) *ApiError { + eopts := parseOpts(opts) + if ae, ok := eopts.err.(*ApiError); ok { + return ae + } + + return ApiErrors[JSTemplateNameNotMatchSubjectErr] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_events.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_events.go index f72f5d9..6b4ac9d 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_events.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_events.go @@ -1,3 +1,16 @@ +// Copyright 2020-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package server import ( @@ -5,8 +18,23 @@ import ( "time" ) -func (s *Server) publishAdvisory(acc *Account, subject string, adv interface{}) { - ej, err := json.MarshalIndent(adv, "", " ") +// publishAdvisory sends the given advisory into the account. Returns true if +// it was sent, false if not (i.e. due to lack of interest or a marshal error). +func (s *Server) publishAdvisory(acc *Account, subject string, adv any) bool { + if acc == nil { + acc = s.SystemAccount() + if acc == nil { + return false + } + } + + // If there is no one listening for this advisory then save ourselves the effort + // and don't bother encoding the JSON or sending it. + if sl := acc.sl; (sl != nil && !sl.HasInterest(subject)) && !s.hasGatewayInterest(acc.Name, subject) { + return false + } + + ej, err := json.Marshal(adv) if err == nil { err = s.sendInternalAccountMsg(acc, subject, ej) if err != nil { @@ -15,28 +43,18 @@ func (s *Server) publishAdvisory(acc *Account, subject string, adv interface{}) } else { s.Warnf("Advisory could not be serialized for account %q: %v", acc.Name, err) } -} - -// ClientAPIAudit is for identifying a client who initiated an API call to the system. -type ClientAPIAudit struct { - Host string `json:"host"` - Port int `json:"port"` - CID uint64 `json:"cid"` - Account string `json:"account"` - User string `json:"user,omitempty"` - Name string `json:"name,omitempty"` - Language string `json:"lang,omitempty"` - Version string `json:"version,omitempty"` + return err == nil } // JSAPIAudit is an advisory about administrative actions taken on JetStream type JSAPIAudit struct { TypedEvent - Server string `json:"server"` - Client ClientAPIAudit `json:"client"` - Subject string `json:"subject"` - Request string `json:"request,omitempty"` - Response string `json:"response"` + Server string `json:"server"` + Client *ClientInfo `json:"client"` + Subject string `json:"subject"` + Request string `json:"request,omitempty"` + Response string `json:"response"` + Domain string `json:"domain,omitempty"` } const JSAPIAuditType = "io.nats.jetstream.advisory.v1.api_audit" @@ -56,6 +74,7 @@ type JSStreamActionAdvisory struct { Stream string `json:"stream"` Action ActionAdvisoryType `json:"action"` Template string `json:"template,omitempty"` + Domain string `json:"domain,omitempty"` } const JSStreamActionAdvisoryType = "io.nats.jetstream.advisory.v1.stream_action" @@ -66,10 +85,23 @@ type JSConsumerActionAdvisory struct { Stream string `json:"stream"` Consumer string `json:"consumer"` Action ActionAdvisoryType `json:"action"` + Domain string `json:"domain,omitempty"` } const JSConsumerActionAdvisoryType = "io.nats.jetstream.advisory.v1.consumer_action" +// JSConsumerPauseAdvisory indicates that a consumer was paused or unpaused +type JSConsumerPauseAdvisory struct { + TypedEvent + Stream string `json:"stream"` + Consumer string `json:"consumer"` + Paused bool `json:"paused"` + PauseUntil time.Time `json:"pause_until,omitempty"` + Domain string `json:"domain,omitempty"` +} + +const JSConsumerPauseAdvisoryType = "io.nats.jetstream.advisory.v1.consumer_pause" + // JSConsumerAckMetric is a metric published when a user acknowledges a message, the // number of these that will be published is dependent on SampleFrequency type JSConsumerAckMetric struct { @@ -80,6 +112,7 @@ type JSConsumerAckMetric struct { StreamSeq uint64 `json:"stream_seq"` Delay int64 `json:"ack_time"` Deliveries uint64 `json:"deliveries"` + Domain string `json:"domain,omitempty"` } // JSConsumerAckMetricType is the schema type for JSConsumerAckMetricType @@ -93,11 +126,27 @@ type JSConsumerDeliveryExceededAdvisory struct { Consumer string `json:"consumer"` StreamSeq uint64 `json:"stream_seq"` Deliveries uint64 `json:"deliveries"` + Domain string `json:"domain,omitempty"` } // JSConsumerDeliveryExceededAdvisoryType is the schema type for JSConsumerDeliveryExceededAdvisory const JSConsumerDeliveryExceededAdvisoryType = "io.nats.jetstream.advisory.v1.max_deliver" +// JSConsumerDeliveryNakAdvisory is an advisory informing that a message was +// naked by the consumer +type JSConsumerDeliveryNakAdvisory struct { + TypedEvent + Stream string `json:"stream"` + Consumer string `json:"consumer"` + ConsumerSeq uint64 `json:"consumer_seq"` + StreamSeq uint64 `json:"stream_seq"` + Deliveries uint64 `json:"deliveries"` + Domain string `json:"domain,omitempty"` +} + +// JSConsumerDeliveryNakAdvisoryType is the schema type for JSConsumerDeliveryNakAdvisory +const JSConsumerDeliveryNakAdvisoryType = "io.nats.jetstream.advisory.v1.nak" + // JSConsumerDeliveryTerminatedAdvisory is an advisory informing that a message was // terminated by the consumer, so might be a candidate for DLQ handling type JSConsumerDeliveryTerminatedAdvisory struct { @@ -107,6 +156,8 @@ type JSConsumerDeliveryTerminatedAdvisory struct { ConsumerSeq uint64 `json:"consumer_seq"` StreamSeq uint64 `json:"stream_seq"` Deliveries uint64 `json:"deliveries"` + Reason string `json:"reason,omitempty"` + Domain string `json:"domain,omitempty"` } // JSConsumerDeliveryTerminatedAdvisoryType is the schema type for JSConsumerDeliveryTerminatedAdvisory @@ -115,10 +166,10 @@ const JSConsumerDeliveryTerminatedAdvisoryType = "io.nats.jetstream.advisory.v1. // JSSnapshotCreateAdvisory is an advisory sent after a snapshot is successfully started type JSSnapshotCreateAdvisory struct { TypedEvent - Stream string `json:"stream"` - NumBlks int `json:"blocks"` - BlkSize int `json:"block_size"` - Client *ClientAPIAudit `json:"client"` + Stream string `json:"stream"` + State StreamState `json:"state"` + Client *ClientInfo `json:"client"` + Domain string `json:"domain,omitempty"` } // JSSnapshotCreatedAdvisoryType is the schema type for JSSnapshotCreateAdvisory @@ -127,10 +178,11 @@ const JSSnapshotCreatedAdvisoryType = "io.nats.jetstream.advisory.v1.snapshot_cr // JSSnapshotCompleteAdvisory is an advisory sent after a snapshot is successfully started type JSSnapshotCompleteAdvisory struct { TypedEvent - Stream string `json:"stream"` - Start time.Time `json:"start"` - End time.Time `json:"end"` - Client *ClientAPIAudit `json:"client"` + Stream string `json:"stream"` + Start time.Time `json:"start"` + End time.Time `json:"end"` + Client *ClientInfo `json:"client"` + Domain string `json:"domain,omitempty"` } // JSSnapshotCompleteAdvisoryType is the schema type for JSSnapshotCreateAdvisory @@ -139,22 +191,155 @@ const JSSnapshotCompleteAdvisoryType = "io.nats.jetstream.advisory.v1.snapshot_c // JSRestoreCreateAdvisory is an advisory sent after a snapshot is successfully started type JSRestoreCreateAdvisory struct { TypedEvent - Stream string `json:"stream"` - Client *ClientAPIAudit `json:"client"` + Stream string `json:"stream"` + Client *ClientInfo `json:"client"` + Domain string `json:"domain,omitempty"` } -// JSRestoreCreateAdvisory is the schema type for JSSnapshotCreateAdvisory +// JSRestoreCreateAdvisoryType is the schema type for JSSnapshotCreateAdvisory const JSRestoreCreateAdvisoryType = "io.nats.jetstream.advisory.v1.restore_create" // JSRestoreCompleteAdvisory is an advisory sent after a snapshot is successfully started type JSRestoreCompleteAdvisory struct { TypedEvent - Stream string `json:"stream"` - Start time.Time `json:"start"` - End time.Time `json:"end"` - Bytes int64 `json:"bytes"` - Client *ClientAPIAudit `json:"client"` + Stream string `json:"stream"` + Start time.Time `json:"start"` + End time.Time `json:"end"` + Bytes int64 `json:"bytes"` + Client *ClientInfo `json:"client"` + Domain string `json:"domain,omitempty"` } // JSRestoreCompleteAdvisoryType is the schema type for JSSnapshotCreateAdvisory const JSRestoreCompleteAdvisoryType = "io.nats.jetstream.advisory.v1.restore_complete" + +// Clustering specific. + +// JSClusterLeaderElectedAdvisoryType is sent when the system elects a new meta leader. +const JSDomainLeaderElectedAdvisoryType = "io.nats.jetstream.advisory.v1.domain_leader_elected" + +// JSClusterLeaderElectedAdvisory indicates that a domain has elected a new leader. +type JSDomainLeaderElectedAdvisory struct { + TypedEvent + Leader string `json:"leader"` + Replicas []*PeerInfo `json:"replicas"` + Cluster string `json:"cluster"` + Domain string `json:"domain,omitempty"` +} + +// JSStreamLeaderElectedAdvisoryType is sent when the system elects a new leader for a stream. +const JSStreamLeaderElectedAdvisoryType = "io.nats.jetstream.advisory.v1.stream_leader_elected" + +// JSStreamLeaderElectedAdvisory indicates that a stream has elected a new leader. +type JSStreamLeaderElectedAdvisory struct { + TypedEvent + Account string `json:"account,omitempty"` + Stream string `json:"stream"` + Leader string `json:"leader"` + Replicas []*PeerInfo `json:"replicas"` + Domain string `json:"domain,omitempty"` +} + +// JSStreamQuorumLostAdvisoryType is sent when the system detects a clustered stream and +// its consumers are stalled and unable to make progress. +const JSStreamQuorumLostAdvisoryType = "io.nats.jetstream.advisory.v1.stream_quorum_lost" + +// JSStreamQuorumLostAdvisory indicates that a stream has lost quorum and is stalled. +type JSStreamQuorumLostAdvisory struct { + TypedEvent + Account string `json:"account,omitempty"` + Stream string `json:"stream"` + Replicas []*PeerInfo `json:"replicas"` + Domain string `json:"domain,omitempty"` +} + +// JSConsumerLeaderElectedAdvisoryType is sent when the system elects a leader for a consumer. +const JSConsumerLeaderElectedAdvisoryType = "io.nats.jetstream.advisory.v1.consumer_leader_elected" + +// JSConsumerLeaderElectedAdvisory indicates that a consumer has elected a new leader. +type JSConsumerLeaderElectedAdvisory struct { + TypedEvent + Account string `json:"account,omitempty"` + Stream string `json:"stream"` + Consumer string `json:"consumer"` + Leader string `json:"leader"` + Replicas []*PeerInfo `json:"replicas"` + Domain string `json:"domain,omitempty"` +} + +// JSConsumerQuorumLostAdvisoryType is sent when the system detects a clustered consumer and +// is stalled and unable to make progress. +const JSConsumerQuorumLostAdvisoryType = "io.nats.jetstream.advisory.v1.consumer_quorum_lost" + +// JSConsumerQuorumLostAdvisory indicates that a consumer has lost quorum and is stalled. +type JSConsumerQuorumLostAdvisory struct { + TypedEvent + Account string `json:"account,omitempty"` + Stream string `json:"stream"` + Consumer string `json:"consumer"` + Replicas []*PeerInfo `json:"replicas"` + Domain string `json:"domain,omitempty"` +} + +const JSConsumerGroupPinnedAdvisoryType = "io.nats.jetstream.advisory.v1.consumer_group_pinned" + +// JSConsumerGroupPinnedAdvisory that a group switched to a new pinned client +type JSConsumerGroupPinnedAdvisory struct { + TypedEvent + Account string `json:"account,omitempty"` + Stream string `json:"stream"` + Consumer string `json:"consumer"` + Domain string `json:"domain,omitempty"` + Group string `json:"group"` + PinnedClientId string `json:"pinned_id"` +} + +const JSConsumerGroupUnpinnedAdvisoryType = "io.nats.jetstream.advisory.v1.consumer_group_unpinned" + +// JSConsumerGroupUnpinnedAdvisory indicates that a pin was lost +type JSConsumerGroupUnpinnedAdvisory struct { + TypedEvent + Account string `json:"account,omitempty"` + Stream string `json:"stream"` + Consumer string `json:"consumer"` + Domain string `json:"domain,omitempty"` + Group string `json:"group"` + // one of "admin" or "timeout", could be an enum up to the implementor to decide + Reason string `json:"reason"` +} + +// JSServerOutOfStorageAdvisoryType is sent when the server is out of storage space. +const JSServerOutOfStorageAdvisoryType = "io.nats.jetstream.advisory.v1.server_out_of_space" + +// JSServerOutOfSpaceAdvisory indicates that a stream has lost quorum and is stalled. +type JSServerOutOfSpaceAdvisory struct { + TypedEvent + Server string `json:"server"` + ServerID string `json:"server_id"` + Stream string `json:"stream,omitempty"` + Cluster string `json:"cluster"` + Domain string `json:"domain,omitempty"` +} + +// JSServerRemovedAdvisoryType is sent when the server has been removed and JS disabled. +const JSServerRemovedAdvisoryType = "io.nats.jetstream.advisory.v1.server_removed" + +// JSServerRemovedAdvisory indicates that a stream has lost quorum and is stalled. +type JSServerRemovedAdvisory struct { + TypedEvent + Server string `json:"server"` + ServerID string `json:"server_id"` + Cluster string `json:"cluster"` + Domain string `json:"domain,omitempty"` +} + +// JSAPILimitReachedAdvisoryType is sent when the JS API request queue limit is reached. +const JSAPILimitReachedAdvisoryType = "io.nats.jetstream.advisory.v1.api_limit_reached" + +// JSAPILimitReachedAdvisory is a advisory published when JetStream hits the queue length limit. +type JSAPILimitReachedAdvisory struct { + TypedEvent + Server string `json:"server"` // Server that created the event, name or ID + Domain string `json:"domain,omitempty"` // Domain the server belongs to + Dropped int64 `json:"dropped"` // How many messages did we drop from the queue +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jetstream_versioning.go b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_versioning.go new file mode 100644 index 0000000..41ecf04 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/jetstream_versioning.go @@ -0,0 +1,206 @@ +// Copyright 2024-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import "strconv" + +const ( + // JSApiLevel is the maximum supported JetStream API level for this server. + JSApiLevel int = 1 + + JSRequiredLevelMetadataKey = "_nats.req.level" + JSServerVersionMetadataKey = "_nats.ver" + JSServerLevelMetadataKey = "_nats.level" +) + +// getRequiredApiLevel returns the required API level for the JetStream asset. +func getRequiredApiLevel(metadata map[string]string) string { + if l, ok := metadata[JSRequiredLevelMetadataKey]; ok && l != _EMPTY_ { + return l + } + return _EMPTY_ +} + +// supportsRequiredApiLevel returns whether the required API level for the JetStream asset is supported. +func supportsRequiredApiLevel(metadata map[string]string) bool { + if l := getRequiredApiLevel(metadata); l != _EMPTY_ { + li, err := strconv.Atoi(l) + return err == nil && li <= JSApiLevel + } + return true +} + +// setStaticStreamMetadata sets JetStream stream metadata, like the server version and API level. +// Any dynamic metadata is removed, it must not be stored and only be added for responses. +func setStaticStreamMetadata(cfg *StreamConfig) { + if cfg.Metadata == nil { + cfg.Metadata = make(map[string]string) + } else { + deleteDynamicMetadata(cfg.Metadata) + } + + var requiredApiLevel int + requires := func(level int) { + if level > requiredApiLevel { + requiredApiLevel = level + } + } + + // TTLs were added in v2.11 and require API level 1. + if cfg.AllowMsgTTL || cfg.SubjectDeleteMarkerTTL > 0 { + requires(1) + } + + cfg.Metadata[JSRequiredLevelMetadataKey] = strconv.Itoa(requiredApiLevel) +} + +// setDynamicStreamMetadata adds dynamic fields into the (copied) metadata. +func setDynamicStreamMetadata(cfg *StreamConfig) *StreamConfig { + var newCfg StreamConfig + if cfg != nil { + newCfg = *cfg + } + newCfg.Metadata = make(map[string]string) + if cfg != nil { + for key, value := range cfg.Metadata { + newCfg.Metadata[key] = value + } + } + newCfg.Metadata[JSServerVersionMetadataKey] = VERSION + newCfg.Metadata[JSServerLevelMetadataKey] = strconv.Itoa(JSApiLevel) + return &newCfg +} + +// copyConsumerMetadata copies versioning fields from metadata of prevCfg into cfg. +// Removes versioning fields if no previous metadata, updates if set, and removes fields if it doesn't exist in prevCfg. +// Any dynamic metadata is removed, it must not be stored and only be added for responses. +// +// Note: useful when doing equality checks on cfg and prevCfg, but ignoring any versioning metadata differences. +func copyStreamMetadata(cfg *StreamConfig, prevCfg *StreamConfig) { + if cfg.Metadata != nil { + deleteDynamicMetadata(cfg.Metadata) + } + setOrDeleteInStreamMetadata(cfg, prevCfg, JSRequiredLevelMetadataKey) +} + +// setOrDeleteInConsumerMetadata sets field with key/value in metadata of cfg if set, deletes otherwise. +func setOrDeleteInStreamMetadata(cfg *StreamConfig, prevCfg *StreamConfig, key string) { + if prevCfg != nil && prevCfg.Metadata != nil { + if value, ok := prevCfg.Metadata[key]; ok { + if cfg.Metadata == nil { + cfg.Metadata = make(map[string]string) + } + cfg.Metadata[key] = value + return + } + } + delete(cfg.Metadata, key) + if len(cfg.Metadata) == 0 { + cfg.Metadata = nil + } +} + +// setStaticConsumerMetadata sets JetStream consumer metadata, like the server version and API level. +// Any dynamic metadata is removed, it must not be stored and only be added for responses. +func setStaticConsumerMetadata(cfg *ConsumerConfig) { + if cfg.Metadata == nil { + cfg.Metadata = make(map[string]string) + } else { + deleteDynamicMetadata(cfg.Metadata) + } + + var requiredApiLevel int + requires := func(level int) { + if level > requiredApiLevel { + requiredApiLevel = level + } + } + + // Added in 2.11, absent | zero is the feature is not used. + // one could be stricter and say even if its set but the time + // has already passed it is also not needed to restore the consumer + if cfg.PauseUntil != nil && !cfg.PauseUntil.IsZero() { + requires(1) + } + + if cfg.PriorityPolicy != PriorityNone || cfg.PinnedTTL != 0 || len(cfg.PriorityGroups) > 0 { + requires(1) + } + + cfg.Metadata[JSRequiredLevelMetadataKey] = strconv.Itoa(requiredApiLevel) +} + +// setDynamicConsumerMetadata adds dynamic fields into the (copied) metadata. +func setDynamicConsumerMetadata(cfg *ConsumerConfig) *ConsumerConfig { + var newCfg ConsumerConfig + if cfg != nil { + newCfg = *cfg + } + newCfg.Metadata = make(map[string]string) + if cfg != nil { + for key, value := range cfg.Metadata { + newCfg.Metadata[key] = value + } + } + newCfg.Metadata[JSServerVersionMetadataKey] = VERSION + newCfg.Metadata[JSServerLevelMetadataKey] = strconv.Itoa(JSApiLevel) + return &newCfg +} + +// setDynamicConsumerInfoMetadata adds dynamic fields into the (copied) metadata. +func setDynamicConsumerInfoMetadata(info *ConsumerInfo) *ConsumerInfo { + if info == nil { + return nil + } + + newInfo := *info + cfg := setDynamicConsumerMetadata(info.Config) + newInfo.Config = cfg + return &newInfo +} + +// copyConsumerMetadata copies versioning fields from metadata of prevCfg into cfg. +// Removes versioning fields if no previous metadata, updates if set, and removes fields if it doesn't exist in prevCfg. +// Any dynamic metadata is removed, it must not be stored and only be added for responses. +// +// Note: useful when doing equality checks on cfg and prevCfg, but ignoring any versioning metadata differences. +func copyConsumerMetadata(cfg *ConsumerConfig, prevCfg *ConsumerConfig) { + if cfg.Metadata != nil { + deleteDynamicMetadata(cfg.Metadata) + } + setOrDeleteInConsumerMetadata(cfg, prevCfg, JSRequiredLevelMetadataKey) +} + +// setOrDeleteInConsumerMetadata sets field with key/value in metadata of cfg if set, deletes otherwise. +func setOrDeleteInConsumerMetadata(cfg *ConsumerConfig, prevCfg *ConsumerConfig, key string) { + if prevCfg != nil && prevCfg.Metadata != nil { + if value, ok := prevCfg.Metadata[key]; ok { + if cfg.Metadata == nil { + cfg.Metadata = make(map[string]string) + } + cfg.Metadata[key] = value + return + } + } + delete(cfg.Metadata, key) + if len(cfg.Metadata) == 0 { + cfg.Metadata = nil + } +} + +// deleteDynamicMetadata deletes dynamic fields from the metadata. +func deleteDynamicMetadata(metadata map[string]string) { + delete(metadata, JSServerVersionMetadataKey) + delete(metadata, JSServerLevelMetadataKey) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/jwt.go b/vendor/github.com/nats-io/nats-server/v2/server/jwt.go index f7e76ba..82d65d9 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/jwt.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/jwt.go @@ -1,4 +1,4 @@ -// Copyright 2018-2019 The NATS Authors +// Copyright 2018-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,10 +14,10 @@ package server import ( + "errors" "fmt" - "io/ioutil" "net" - "regexp" + "os" "strings" "time" @@ -25,41 +25,36 @@ import ( "github.com/nats-io/nkeys" ) -var nscDecoratedRe = regexp.MustCompile(`\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}[\n]*))`) - // All JWTs once encoded start with this const jwtPrefix = "eyJ" // ReadOperatorJWT will read a jwt file for an operator claim. This can be a decorated file. func ReadOperatorJWT(jwtfile string) (*jwt.OperatorClaims, error) { - contents, err := ioutil.ReadFile(jwtfile) + _, claim, err := readOperatorJWT(jwtfile) + return claim, err +} + +func readOperatorJWT(jwtfile string) (string, *jwt.OperatorClaims, error) { + contents, err := os.ReadFile(jwtfile) if err != nil { // Check to see if the JWT has been inlined. if !strings.HasPrefix(jwtfile, jwtPrefix) { - return nil, err + return "", nil, err } // We may have an inline jwt here. contents = []byte(jwtfile) } defer wipeSlice(contents) - var claim string - items := nscDecoratedRe.FindAllSubmatch(contents, -1) - if len(items) == 0 { - claim = string(contents) - } else { - // First result should be the JWT. - // We copy here so that if the file contained a seed file too we wipe appropriately. - raw := items[0][1] - tmp := make([]byte, len(raw)) - copy(tmp, raw) - claim = string(tmp) - } - opc, err := jwt.DecodeOperatorClaims(claim) + theJWT, err := jwt.ParseDecoratedJWT(contents) + if err != nil { + return "", nil, err + } + opc, err := jwt.DecodeOperatorClaims(theJWT) if err != nil { - return nil, err + return "", nil, err } - return opc, nil + return theJWT, opc, nil } // Just wipe slice with 'x', for clearing contents of nkey seed file. @@ -74,10 +69,24 @@ func wipeSlice(buf []byte) { // will expand the trusted keys in options. func validateTrustedOperators(o *Options) error { if len(o.TrustedOperators) == 0 { + // if we have no operator, default sentinel shouldn't be set + if o.DefaultSentinel != _EMPTY_ { + return fmt.Errorf("default sentinel requires operators and accounts") + } return nil } - if o.AllowNewAccounts { - return fmt.Errorf("operators do not allow dynamic creation of new accounts") + if o.DefaultSentinel != _EMPTY_ { + juc, err := jwt.DecodeUserClaims(o.DefaultSentinel) + if err != nil { + return fmt.Errorf("default sentinel JWT not valid") + } + + if !juc.BearerToken && juc.IssuerAccount != "" && juc.HasEmptyPermissions() { + // we cannot resolve the account yet - but this looks like a scoped user + // it will be rejected at runtime if not valid + } else if !juc.BearerToken { + return fmt.Errorf("default sentinel must be a bearer token") + } } if o.AccountResolver == nil { return fmt.Errorf("operators require an account resolver to be configured") @@ -91,11 +100,11 @@ func validateTrustedOperators(o *Options) error { if len(o.TrustedOperators) > 0 && len(o.TrustedKeys) > 0 { return fmt.Errorf("conflicting options for 'TrustedKeys' and 'TrustedOperators'") } - if o.SystemAccount != "" { + if o.SystemAccount != _EMPTY_ { foundSys := false foundNonEmpty := false for _, op := range o.TrustedOperators { - if op.SystemAccount != "" { + if op.SystemAccount != _EMPTY_ { foundNonEmpty = true } if op.SystemAccount == o.SystemAccount { @@ -106,8 +115,16 @@ func validateTrustedOperators(o *Options) error { if foundNonEmpty && !foundSys { return fmt.Errorf("system_account in config and operator JWT must be identical") } + } else if o.TrustedOperators[0].SystemAccount == _EMPTY_ { + // In case the system account is neither defined in config nor in the first operator. + // If it would be needed due to the nats account resolver, raise an error. + switch o.AccountResolver.(type) { + case *DirAccResolver, *CacheDirAccResolver: + return fmt.Errorf("using nats based account resolver - the system account needs to be specified in configuration or the operator jwt") + } } - srvMajor, srvMinor, srvUpdate, _ := jwt.ParseServerVersion(strings.Split(VERSION, "-")[0]) + + srvMajor, srvMinor, srvUpdate, _ := versionComponents(VERSION) for _, opc := range o.TrustedOperators { if major, minor, update, err := jwt.ParseServerVersion(opc.AssertServerVersion); err != nil { return fmt.Errorf("operator %s expects version %s got error instead: %s", @@ -132,7 +149,9 @@ func validateTrustedOperators(o *Options) error { if o.TrustedKeys == nil { o.TrustedKeys = make([]string, 0, 4) } - o.TrustedKeys = append(o.TrustedKeys, opc.Issuer) + if !opc.StrictSigningKeyUsage { + o.TrustedKeys = append(o.TrustedKeys, opc.Subject) + } o.TrustedKeys = append(o.TrustedKeys, opc.SigningKeys...) } for _, key := range o.TrustedKeys { @@ -140,6 +159,23 @@ func validateTrustedOperators(o *Options) error { return fmt.Errorf("trusted Keys %q are required to be a valid public operator nkey", key) } } + if len(o.resolverPinnedAccounts) > 0 { + for key := range o.resolverPinnedAccounts { + if !nkeys.IsValidPublicAccountKey(key) { + return fmt.Errorf("pinned account key %q is not a valid public account nkey", key) + } + } + // ensure the system account (belonging to the operator can always connect) + if o.SystemAccount != _EMPTY_ { + o.resolverPinnedAccounts[o.SystemAccount] = struct{}{} + } + } + + // If we have an auth callout defined make sure we are not in operator mode. + if o.AuthCallout != nil { + return errors.New("operators do not allow authorization callouts to be configured directly") + } + return nil } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go b/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go index 61264f7..bf97f2d 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,14 +17,16 @@ import ( "bufio" "bytes" "crypto/tls" - "crypto/x509" "encoding/base64" "encoding/json" "fmt" "io" - "io/ioutil" + "math/rand" "net" + "net/http" "net/url" + "os" + "path" "reflect" "regexp" "runtime" @@ -34,22 +36,37 @@ import ( "sync/atomic" "time" + "github.com/klauspost/compress/s2" + "github.com/nats-io/jwt/v2" "github.com/nats-io/nkeys" "github.com/nats-io/nuid" ) -// Warning when user configures leafnode TLS insecure -const leafnodeTLSInsecureWarning = "TLS certificate chain and hostname of solicited leafnodes will not be verified. DO NOT USE IN PRODUCTION!" +const ( + // Warning when user configures leafnode TLS insecure + leafnodeTLSInsecureWarning = "TLS certificate chain and hostname of solicited leafnodes will not be verified. DO NOT USE IN PRODUCTION!" -// When a loop is detected, delay the reconnect of solicited connection. -const leafNodeReconnectDelayAfterLoopDetected = 30 * time.Second + // When a loop is detected, delay the reconnect of solicited connection. + leafNodeReconnectDelayAfterLoopDetected = 30 * time.Second -// When a server receives a message causing a permission violation, the -// connection is closed and it won't attempt to reconnect for that long. -const leafNodeReconnectAfterPermViolation = 30 * time.Second + // When a server receives a message causing a permission violation, the + // connection is closed and it won't attempt to reconnect for that long. + leafNodeReconnectAfterPermViolation = 30 * time.Second -// Prefix for loop detection subject -const leafNodeLoopDetectionSubjectPrefix = "$LDS." + // When we have the same cluster name as the hub. + leafNodeReconnectDelayAfterClusterNameSame = 30 * time.Second + + // Prefix for loop detection subject + leafNodeLoopDetectionSubjectPrefix = "$LDS." + + // Path added to URL to indicate to WS server that the connection is a + // LEAF connection as opposed to a CLIENT. + leafNodeWSPath = "/leafnode" + + // This is the time the server will wait, when receiving a CONNECT, + // before closing the connection if the required minimum version is not met. + leafNodeWaitBeforeClose = 5 * time.Second +) type leaf struct { // We have any auth stuff here for solicited connections. @@ -59,6 +76,12 @@ type leaf struct { isSpoke bool // remoteCluster is when we are a hub but the spoke leafnode is part of a cluster. remoteCluster string + // remoteServer holds onto the remote server's name or ID. + remoteServer string + // domain name of remote server + remoteDomain string + // account name of remote server + remoteAccName string // Used to suppress sub and unsub interest. Same as routes but our audience // here is tied to this leaf node. This will hold all subscriptions except this // leaf nodes. This represents all the interest we want to send to the other side. @@ -72,19 +95,24 @@ type leaf struct { // we would add it a second time in the smap causing later unsub to suppress the LS-. tsub map[*subscription]struct{} tsubt *time.Timer + // Selected compression mode, which may be different from the server configured mode. + compression string + // This is for GW map replies. + gwSub *subscription } // Used for remote (solicited) leafnodes. type leafNodeCfg struct { sync.RWMutex *RemoteLeafOpts - urls []*url.URL - curURL *url.URL - tlsName string - username string - password string - perms *Permissions - connDelay time.Duration // Delay before a connect, could be used while detecting loop condition, etc.. + urls []*url.URL + curURL *url.URL + tlsName string + username string + password string + perms *Permissions + connDelay time.Duration // Delay before a connect, could be used while detecting loop condition, etc.. + jsMigrateTimer *time.Timer } // Check to see if this is a solicited leafnode. We do special processing for solicited. @@ -104,8 +132,52 @@ func (c *client) isHubLeafNode() bool { // This will spin up go routines to solicit the remote leaf node connections. func (s *Server) solicitLeafNodeRemotes(remotes []*RemoteLeafOpts) { - for _, r := range remotes { + sysAccName := _EMPTY_ + sAcc := s.SystemAccount() + if sAcc != nil { + sysAccName = sAcc.Name + } + addRemote := func(r *RemoteLeafOpts, isSysAccRemote bool) *leafNodeCfg { + s.mu.Lock() remote := newLeafNodeCfg(r) + creds := remote.Credentials + accName := remote.LocalAccount + s.leafRemoteCfgs = append(s.leafRemoteCfgs, remote) + // Print notice if + if isSysAccRemote { + if len(remote.DenyExports) > 0 { + s.Noticef("Remote for System Account uses restricted export permissions") + } + if len(remote.DenyImports) > 0 { + s.Noticef("Remote for System Account uses restricted import permissions") + } + } + s.mu.Unlock() + if creds != _EMPTY_ { + contents, err := os.ReadFile(creds) + defer wipeSlice(contents) + if err != nil { + s.Errorf("Error reading LeafNode Remote Credentials file %q: %v", creds, err) + } else if items := credsRe.FindAllSubmatch(contents, -1); len(items) < 2 { + s.Errorf("LeafNode Remote Credentials file %q malformed", creds) + } else if _, err := nkeys.FromSeed(items[1][1]); err != nil { + s.Errorf("LeafNode Remote Credentials file %q has malformed seed", creds) + } else if uc, err := jwt.DecodeUserClaims(string(items[0][1])); err != nil { + s.Errorf("LeafNode Remote Credentials file %q has malformed user jwt", creds) + } else if isSysAccRemote { + if !uc.Permissions.Pub.Empty() || !uc.Permissions.Sub.Empty() || uc.Permissions.Resp != nil { + s.Noticef("LeafNode Remote for System Account uses credentials file %q with restricted permissions", creds) + } + } else { + if !uc.Permissions.Pub.Empty() || !uc.Permissions.Sub.Empty() || uc.Permissions.Resp != nil { + s.Noticef("LeafNode Remote for Account %s uses credentials file %q with restricted permissions", accName, creds) + } + } + } + return remote + } + for _, r := range remotes { + remote := addRemote(r, r.LocalAccount == sysAccName) s.startGoRoutine(func() { s.connectToRemoteLeafNode(remote, true) }) } } @@ -125,6 +197,14 @@ func validateLeafNode(o *Options) error { if err := validateLeafNodeAuthOptions(o); err != nil { return err } + + // Users can bind to any local account, if its empty we will assume the $G account. + for _, r := range o.LeafNode.Remotes { + if r.LocalAccount == _EMPTY_ { + r.LocalAccount = globalAccountName + } + } + // In local config mode, check that leafnode configuration refers to accounts that exist. if len(o.TrustedOperators) == 0 { accNames := map[string]struct{}{} @@ -163,11 +243,14 @@ func validateLeafNode(o *Options) error { } } else { if len(o.LeafNode.Users) != 0 { - return fmt.Errorf("operator mode does not allow specifying user in leafnode config") + return fmt.Errorf("operator mode does not allow specifying users in leafnode config") } for _, r := range o.LeafNode.Remotes { if !nkeys.IsValidPublicAccountKey(r.LocalAccount) { - return fmt.Errorf("operator mode requires account nkeys in remotes") + return fmt.Errorf( + "operator mode requires account nkeys in remotes. " + + "Please add an `account` key to each remote in your `leafnodes` section, to assign it to an account. " + + "Each account value should be a 56 character public key, starting with the letter 'A'") } } if o.LeafNode.Port != 0 && o.LeafNode.Account != "" && !nkeys.IsValidPublicAccountKey(o.LeafNode.Account) { @@ -175,17 +258,73 @@ func validateLeafNode(o *Options) error { } } + // Validate compression settings + if o.LeafNode.Compression.Mode != _EMPTY_ { + if err := validateAndNormalizeCompressionOption(&o.LeafNode.Compression, CompressionS2Auto); err != nil { + return err + } + } + + // If a remote has a websocket scheme, all need to have it. + for _, rcfg := range o.LeafNode.Remotes { + if len(rcfg.URLs) >= 2 { + firstIsWS, ok := isWSURL(rcfg.URLs[0]), true + for i := 1; i < len(rcfg.URLs); i++ { + u := rcfg.URLs[i] + if isWS := isWSURL(u); isWS && !firstIsWS || !isWS && firstIsWS { + ok = false + break + } + } + if !ok { + return fmt.Errorf("remote leaf node configuration cannot have a mix of websocket and non-websocket urls: %q", redactURLList(rcfg.URLs)) + } + } + // Validate compression settings + if rcfg.Compression.Mode != _EMPTY_ { + if err := validateAndNormalizeCompressionOption(&rcfg.Compression, CompressionS2Auto); err != nil { + return err + } + } + } + if o.LeafNode.Port == 0 { return nil } - if o.Gateway.Name == "" && o.Gateway.Port == 0 { + + // If MinVersion is defined, check that it is valid. + if mv := o.LeafNode.MinVersion; mv != _EMPTY_ { + if err := checkLeafMinVersionConfig(mv); err != nil { + return err + } + } + + // The checks below will be done only when detecting that we are configured + // with gateways. So if an option validation needs to be done regardless, + // it MUST be done before this point! + + if o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 { return nil } // If we are here we have both leaf nodes and gateways defined, make sure there // is a system account defined. - if o.SystemAccount == "" { + if o.SystemAccount == _EMPTY_ { return fmt.Errorf("leaf nodes and gateways (both being defined) require a system account to also be configured") } + if err := validatePinnedCerts(o.LeafNode.TLSPinnedCerts); err != nil { + return fmt.Errorf("leafnode: %v", err) + } + return nil +} + +func checkLeafMinVersionConfig(mv string) error { + if ok, err := versionAtLeastCheckError(mv, 2, 8, 0); !ok || err != nil { + if err != nil { + return fmt.Errorf("invalid leafnode's minimum version: %v", err) + } else { + return fmt.Errorf("the minimum version should be at least 2.8.0") + } + } return nil } @@ -199,6 +338,9 @@ func validateLeafNodeAuthOptions(o *Options) error { if o.LeafNode.Username != _EMPTY_ { return fmt.Errorf("can not have a single user/pass and a users array") } + if o.LeafNode.Nkey != _EMPTY_ { + return fmt.Errorf("can not have a single nkey and a users array") + } users := map[string]struct{}{} for _, u := range o.LeafNode.Users { if _, exists := users[u.Username]; exists { @@ -209,6 +351,33 @@ func validateLeafNodeAuthOptions(o *Options) error { return nil } +// Update remote LeafNode TLS configurations after a config reload. +func (s *Server) updateRemoteLeafNodesTLSConfig(opts *Options) { + max := len(opts.LeafNode.Remotes) + if max == 0 { + return + } + + s.mu.RLock() + defer s.mu.RUnlock() + + // Changes in the list of remote leaf nodes is not supported. + // However, make sure that we don't go over the arrays. + if len(s.leafRemoteCfgs) < max { + max = len(s.leafRemoteCfgs) + } + for i := 0; i < max; i++ { + ro := opts.LeafNode.Remotes[i] + cfg := s.leafRemoteCfgs[i] + if ro.TLSConfig != nil { + cfg.Lock() + cfg.TLSConfig = ro.TLSConfig.Clone() + cfg.TLSHandshakeFirst = ro.TLSHandshakeFirst + cfg.Unlock() + } + } +} + func (s *Server) reConnectToRemoteLeafNode(remote *leafNodeCfg) { delay := s.getOpts().LeafNode.ReconnectInterval select { @@ -239,12 +408,23 @@ func newLeafNodeCfg(remote *RemoteLeafOpts) *leafNodeCfg { // Start with the one that is configured. We will add to this // array when receiving async leafnode INFOs. cfg.urls = append(cfg.urls, cfg.URLs...) + // If allowed to randomize, do it on our copy of URLs + if !remote.NoRandomize { + rand.Shuffle(len(cfg.urls), func(i, j int) { + cfg.urls[i], cfg.urls[j] = cfg.urls[j], cfg.urls[i] + }) + } // If we are TLS make sure we save off a proper servername if possible. // Do same for user/password since we may need them to connect to // a bare URL that we get from INFO protocol. for _, u := range cfg.urls { cfg.saveTLSHostname(u) cfg.saveUserPassword(u) + // If the url(s) have the "wss://" scheme, and we don't have a TLS + // config, mark that we should be using TLS anyway. + if !cfg.TLS && isWSSURL(u) { + cfg.TLS = true + } } return cfg } @@ -302,6 +482,8 @@ func (s *Server) setLeafNodeNonExportedOptions() { } } +const sharedSysAccDelay = 250 * time.Millisecond + func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool) { defer s.grWG.Done() @@ -312,10 +494,21 @@ func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool) opts := s.getOpts() reconnectDelay := opts.LeafNode.ReconnectInterval - s.mu.Lock() + s.mu.RLock() dialTimeout := s.leafNodeOpts.dialTimeout resolver := s.leafNodeOpts.resolver - s.mu.Unlock() + var isSysAcc bool + if s.eventsEnabled() { + isSysAcc = remote.LocalAccount == s.sys.account.Name + } + jetstreamMigrateDelay := remote.JetStreamClusterMigrateDelay + s.mu.RUnlock() + + // If we are sharing a system account and we are not standalone delay to gather some info prior. + if firstConnect && isSysAcc && !s.standAloneMode() { + s.Debugf("Will delay first leafnode connect to shared system account due to clustering") + remote.setConnectDelay(sharedSysAccDelay) + } if connDelay := remote.getConnectDelay(); connDelay > 0 { select { @@ -331,6 +524,7 @@ func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool) const connErrFmt = "Error trying to connect as leafnode to remote server %q (attempt %v): %v" attempts := 0 + for s.isRunning() && s.remoteLeafNodeStillValid(remote) { rURL := remote.pickNextURL() url, err := s.getRandomIP(resolver, rURL.Host, nil) @@ -339,23 +533,46 @@ func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool) if url != rURL.Host { ipStr = fmt.Sprintf(" (%s)", url) } - s.Debugf("Trying to connect as leafnode to remote server on %q%s", rURL.Host, ipStr) - conn, err = natsDialTimeout("tcp", url, dialTimeout) + // Some test may want to disable remotes from connecting + if s.isLeafConnectDisabled() { + s.Debugf("Will not attempt to connect to remote server on %q%s, leafnodes currently disabled", rURL.Host, ipStr) + err = ErrLeafNodeDisabled + } else { + s.Debugf("Trying to connect as leafnode to remote server on %q%s", rURL.Host, ipStr) + conn, err = natsDialTimeout("tcp", url, dialTimeout) + } } if err != nil { + jitter := time.Duration(rand.Int63n(int64(reconnectDelay))) + delay := reconnectDelay + jitter attempts++ if s.shouldReportConnectErr(firstConnect, attempts) { s.Errorf(connErrFmt, rURL.Host, attempts, err) } else { s.Debugf(connErrFmt, rURL.Host, attempts, err) } + remote.Lock() + // if we are using a delay to start migrating assets, kick off a migrate timer. + if remote.jsMigrateTimer == nil && jetstreamMigrateDelay > 0 { + remote.jsMigrateTimer = time.AfterFunc(jetstreamMigrateDelay, func() { + s.checkJetStreamMigrate(remote) + }) + } + remote.Unlock() select { case <-s.quitCh: + remote.cancelMigrateTimer() return - case <-time.After(reconnectDelay): + case <-time.After(delay): + // Check if we should migrate any JetStream assets immediately while this remote is down. + // This will be used if JetStreamClusterMigrateDelay was not set + if jetstreamMigrateDelay == 0 { + s.checkJetStreamMigrate(remote) + } continue } } + remote.cancelMigrateTimer() if !s.remoteLeafNodeStillValid(remote) { conn.Close() return @@ -363,22 +580,114 @@ func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool) // We have a connection here to a remote server. // Go ahead and create our leaf node and return. - s.createLeafNode(conn, remote) + s.createLeafNode(conn, rURL, remote, nil) + + // Clear any observer states if we had them. + s.clearObserverState(remote) + + return + } +} + +func (cfg *leafNodeCfg) cancelMigrateTimer() { + cfg.Lock() + stopAndClearTimer(&cfg.jsMigrateTimer) + cfg.Unlock() +} + +// This will clear any observer state such that stream or consumer assets on this server can become leaders again. +func (s *Server) clearObserverState(remote *leafNodeCfg) { + s.mu.RLock() + accName := remote.LocalAccount + s.mu.RUnlock() + + acc, err := s.LookupAccount(accName) + if err != nil { + s.Warnf("Error looking up account [%s] checking for JetStream clear observer state on a leafnode", accName) + return + } - // We will put this in the normal log if first connect, does not force -DV mode to know - // that the connect worked. - if firstConnect { - s.Noticef("Connected leafnode to %q", rURL.Host) + acc.jscmMu.Lock() + defer acc.jscmMu.Unlock() + + // Walk all streams looking for any clustered stream, skip otherwise. + for _, mset := range acc.streams() { + node := mset.raftNode() + if node == nil { + // Not R>1 + continue + } + // Check consumers + for _, o := range mset.getConsumers() { + if n := o.raftNode(); n != nil { + // Ensure we can become a leader again. + n.SetObserver(false) + } } + // Ensure we can not become a leader again. + node.SetObserver(false) + } +} + +// Check to see if we should migrate any assets from this account. +func (s *Server) checkJetStreamMigrate(remote *leafNodeCfg) { + s.mu.RLock() + accName, shouldMigrate := remote.LocalAccount, remote.JetStreamClusterMigrate + s.mu.RUnlock() + + if !shouldMigrate { return } + + acc, err := s.LookupAccount(accName) + if err != nil { + s.Warnf("Error looking up account [%s] checking for JetStream migration on a leafnode", accName) + return + } + + acc.jscmMu.Lock() + defer acc.jscmMu.Unlock() + + // Walk all streams looking for any clustered stream, skip otherwise. + // If we are the leader force stepdown. + for _, mset := range acc.streams() { + node := mset.raftNode() + if node == nil { + // Not R>1 + continue + } + // Collect any consumers + for _, o := range mset.getConsumers() { + if n := o.raftNode(); n != nil { + n.StepDown() + // Ensure we can not become a leader while in this state. + n.SetObserver(true) + } + } + // Stepdown if this stream was leader. + node.StepDown() + // Ensure we can not become a leader while in this state. + node.SetObserver(true) + } +} + +// Helper for checking. +func (s *Server) isLeafConnectDisabled() bool { + s.mu.RLock() + defer s.mu.RUnlock() + return s.leafDisableConnect } // Save off the tlsName for when we use TLS and mix hostnames and IPs. IPs usually // come from the server we connect to. +// +// We used to save the name only if there was a TLSConfig or scheme equal to "tls". +// However, this was causing failures for users that did not set the scheme (and +// their remote connections did not have a tls{} block). +// We now save the host name regardless in case the remote returns an INFO indicating +// that TLS is required. func (cfg *leafNodeCfg) saveTLSHostname(u *url.URL) { - isTLS := cfg.TLSConfig != nil || u.Scheme == "tls" - if isTLS && cfg.tlsName == "" && net.ParseIP(u.Hostname()) == nil { + if cfg.tlsName == _EMPTY_ && net.ParseIP(u.Hostname()) == nil { cfg.tlsName = u.Hostname() } } @@ -403,13 +712,14 @@ func (s *Server) startLeafNodeAcceptLoop() { port = 0 } - s.mu.Lock() - if s.shutdown { - s.mu.Unlock() + if s.isShuttingDown() { return } + + s.mu.Lock() hp := net.JoinHostPort(opts.LeafNode.Host, strconv.Itoa(port)) l, e := natsListen("tcp", hp) + s.leafNodeListenerErr = e if e != nil { s.mu.Unlock() s.Fatalf("Error listening on leafnode port: %d - %v", opts.LeafNode.Port, e) @@ -421,17 +731,23 @@ func (s *Server) startLeafNodeAcceptLoop() { tlsRequired := opts.LeafNode.TLSConfig != nil tlsVerify := tlsRequired && opts.LeafNode.TLSConfig.ClientAuth == tls.RequireAndVerifyClientCert + // Do not set compression in this Info object, it would possibly cause + // issues when sending asynchronous INFO to the remote. info := Info{ - ID: s.info.ID, - Version: s.info.Version, - GitCommit: gitCommit, - GoVersion: runtime.Version(), - AuthRequired: true, - TLSRequired: tlsRequired, - TLSVerify: tlsVerify, - MaxPayload: s.info.MaxPayload, // TODO(dlc) - Allow override? - Headers: s.supportsHeaders(), - Proto: 1, // Fixed for now. + ID: s.info.ID, + Name: s.info.Name, + Version: s.info.Version, + GitCommit: gitCommit, + GoVersion: runtime.Version(), + AuthRequired: true, + TLSRequired: tlsRequired, + TLSVerify: tlsVerify, + MaxPayload: s.info.MaxPayload, // TODO(dlc) - Allow override? + Headers: s.supportsHeaders(), + JetStream: opts.JetStream, + Domain: opts.JetStreamDomain, + Proto: s.getServerProto(), + InfoOnConnect: true, } // If we have selected a random port... if port == 0 { @@ -442,7 +758,7 @@ func (s *Server) startLeafNodeAcceptLoop() { s.leafNodeInfo = info // Possibly override Host/Port and set IP based on Cluster.Advertise if err := s.setLeafNodeInfoHostPortAndIP(); err != nil { - s.Fatalf("Error setting leafnode INFO with LeafNode.Advertise value of %s, err=%v", s.opts.LeafNode.Advertise, err) + s.Fatalf("Error setting leafnode INFO with LeafNode.Advertise value of %s, err=%v", opts.LeafNode.Advertise, err) l.Close() s.mu.Unlock() return @@ -471,27 +787,52 @@ func (s *Server) startLeafNodeAcceptLoop() { if warn { s.Warnf(leafnodeTLSInsecureWarning) } - go s.acceptConnections(l, "Leafnode", func(conn net.Conn) { s.createLeafNode(conn, nil) }, nil) + go s.acceptConnections(l, "Leafnode", func(conn net.Conn) { s.createLeafNode(conn, nil, nil, nil) }, nil) s.mu.Unlock() } // RegEx to match a creds file with user JWT and Seed. -var credsRe = regexp.MustCompile(`\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))`) +var credsRe = regexp.MustCompile(`\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}(\r?\n|\z)))`) +// clusterName is provided as argument to avoid lock ordering issues with the locked client c // Lock should be held entering here. -func (c *client) sendLeafConnect(clusterName string, tlsRequired bool) error { +func (c *client) sendLeafConnect(clusterName string, headers bool) error { // We support basic user/pass and operator based user JWT with signatures. cinfo := leafConnectInfo{ - TLS: tlsRequired, - Name: c.srv.info.ID, - Hub: c.leaf.remote.Hub, - Cluster: clusterName, - } + Version: VERSION, + ID: c.srv.info.ID, + Domain: c.srv.info.Domain, + Name: c.srv.info.Name, + Hub: c.leaf.remote.Hub, + Cluster: clusterName, + Headers: headers, + JetStream: c.acc.jetStreamConfigured(), + DenyPub: c.leaf.remote.DenyImports, + Compression: c.leaf.compression, + RemoteAccount: c.acc.GetName(), + Proto: c.srv.getServerProto(), + } + + // If a signature callback is specified, this takes precedence over anything else. + if cb := c.leaf.remote.SignatureCB; cb != nil { + nonce := c.nonce + c.mu.Unlock() + jwt, sigraw, err := cb(nonce) + c.mu.Lock() + if err == nil && c.isClosed() { + err = ErrConnectionClosed + } + if err != nil { + c.Errorf("Error signing the nonce: %v", err) + return err + } + sig := base64.RawURLEncoding.EncodeToString(sigraw) + cinfo.JWT, cinfo.Sig = jwt, sig - // Check for credentials first, that will take precedence.. - if creds := c.leaf.remote.Credentials; creds != "" { + } else if creds := c.leaf.remote.Credentials; creds != _EMPTY_ { + // Check for credentials first, that will take precedence.. c.Debugf("Authenticating with credentials file %q", c.leaf.remote.Credentials) - contents, err := ioutil.ReadFile(creds) + contents, err := os.ReadFile(creds) if err != nil { c.Errorf("%v", err) return err @@ -518,18 +859,40 @@ func (c *client) sendLeafConnect(clusterName string, tlsRequired bool) error { sigraw, _ := kp.Sign(c.nonce) sig := base64.RawURLEncoding.EncodeToString(sigraw) - cinfo.JWT = string(tmp) + cinfo.JWT = bytesToString(tmp) cinfo.Sig = sig - } else if userInfo := c.leaf.remote.curURL.User; userInfo != nil { + } else if nkey := c.leaf.remote.Nkey; nkey != _EMPTY_ { + kp, err := nkeys.FromSeed([]byte(nkey)) + if err != nil { + c.Errorf("Remote nkey has malformed seed") + return err + } + // Wipe our key on exit. + defer kp.Wipe() + sigraw, _ := kp.Sign(c.nonce) + sig := base64.RawURLEncoding.EncodeToString(sigraw) + pkey, _ := kp.PublicKey() + cinfo.Nkey = pkey + cinfo.Sig = sig + } + // In addition, and this is to allow auth callout, set user/password or + // token if applicable. + if userInfo := c.leaf.remote.curURL.User; userInfo != nil { + // For backward compatibility, if only username is provided, set both + // Token and User, not just Token. cinfo.User = userInfo.Username() - cinfo.Pass, _ = userInfo.Password() + var ok bool + cinfo.Pass, ok = userInfo.Password() + if !ok { + cinfo.Token = cinfo.User + } } else if c.leaf.remote.username != _EMPTY_ { cinfo.User = c.leaf.remote.username cinfo.Pass = c.leaf.remote.password } b, err := json.Marshal(cinfo) if err != nil { - c.Errorf("Error marshaling CONNECT to route: %v\n", err) + c.Errorf("Error marshaling CONNECT to remote leafnode: %v\n", err) return err } // Although this call is made before the writeLoop is created, @@ -569,7 +932,7 @@ func (s *Server) addLeafNodeURL(urlStr string) bool { func (s *Server) removeLeafNodeURL(urlStr string) bool { // Don't need to do this if we are removing the route connection because // we are shuting down... - if s.shutdown { + if s.isShuttingDown() { return false } if s.leafURLsMap.removeUrl(urlStr) { @@ -581,10 +944,10 @@ func (s *Server) removeLeafNodeURL(urlStr string) bool { // Server lock is held on entry func (s *Server) generateLeafNodeInfoJSON() { + s.leafNodeInfo.Cluster = s.cachedClusterName() s.leafNodeInfo.LeafNodeURLs = s.leafURLsMap.getAsStringSlice() - b, _ := json.Marshal(s.leafNodeInfo) - pcs := [][]byte{[]byte("INFO"), b, []byte(CR_LF)} - s.leafNodeInfoJSON = bytes.Join(pcs, []byte(" ")) + s.leafNodeInfo.WSConnectURLs = s.websocket.connectURLsMap.getAsStringSlice() + s.leafNodeInfoJSON = generateInfoJSON(&s.leafNodeInfo) } // Sends an async INFO protocol so that the connected servers can update @@ -598,7 +961,7 @@ func (s *Server) sendAsyncLeafNodeInfo() { } // Called when an inbound leafnode connection is accepted or we create one for a solicited leafnode. -func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client { +func (s *Server) createLeafNode(conn net.Conn, rURL *url.URL, remote *leafNodeCfg, ws *websocket) *client { // Snapshot server options. opts := s.getOpts() @@ -608,256 +971,221 @@ func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client { if maxSubs == 0 { maxSubs = -1 } - now := time.Now() + now := time.Now().UTC() c := &client{srv: s, nc: conn, kind: LEAF, opts: defaultOpts, mpay: maxPay, msubs: maxSubs, start: now, last: now} // Do not update the smap here, we need to do it in initLeafNodeSmapAndSendSubs c.leaf = &leaf{} + // For accepted LN connections, ws will be != nil if it was accepted + // through the Websocket port. + c.ws = ws + + // For remote, check if the scheme starts with "ws", if so, we will initiate + // a remote Leaf Node connection as a websocket connection. + if remote != nil && rURL != nil && isWSURL(rURL) { + remote.RLock() + c.ws = &websocket{compress: remote.Websocket.Compression, maskwrite: !remote.Websocket.NoMasking} + remote.RUnlock() + } + // Determines if we are soliciting the connection or not. var solicited bool - var sendSysConnectEvent bool var acc *Account + var remoteSuffix string + if remote != nil { + // For now, if lookup fails, we will constantly try + // to recreate this LN connection. + lacc := remote.LocalAccount + var err error + acc, err = s.LookupAccount(lacc) + if err != nil { + // An account not existing is something that can happen with nats/http account resolver and the account + // has not yet been pushed, or the request failed for other reasons. + // remote needs to be set or retry won't happen + c.leaf.remote = remote + c.closeConnection(MissingAccount) + s.Errorf("Unable to lookup account %s for solicited leafnode connection: %v", lacc, err) + return nil + } + remoteSuffix = fmt.Sprintf(" for account: %s", acc.traceLabel()) + } c.mu.Lock() c.initClient() + c.Noticef("Leafnode connection created%s %s", remoteSuffix, c.opts.Name) + + var ( + tlsFirst bool + tlsFirstFallback time.Duration + infoTimeout time.Duration + ) if remote != nil { solicited = true - // Users can bind to any local account, if its empty - // we will assume the $G account. - if remote.LocalAccount == "" { - remote.LocalAccount = globalAccountName - } + remote.Lock() c.leaf.remote = remote c.setPermissions(remote.perms) - if c.leaf.remote.Hub { - sendSysConnectEvent = true - } else { + if !c.leaf.remote.Hub { c.leaf.isSpoke = true } - c.mu.Unlock() - // TODO: Decide what should be the optimal behavior here. - // For now, if lookup fails, we will constantly try - // to recreate this LN connection. - var err error - acc, err = s.LookupAccount(remote.LocalAccount) - if err != nil { - c.Errorf("No local account %q for leafnode: %v", remote.LocalAccount, err) - c.closeConnection(MissingAccount) - return nil - } - c.mu.Lock() + tlsFirst = remote.TLSHandshakeFirst + infoTimeout = remote.FirstInfoTimeout + remote.Unlock() c.acc = acc } else { c.flags.set(expectConnect) + if ws != nil { + c.Debugf("Leafnode compression=%v", c.ws.compress) + } + tlsFirst = opts.LeafNode.TLSHandshakeFirst + if f := opts.LeafNode.TLSHandshakeFirstFallback; f > 0 { + tlsFirstFallback = f + } } c.mu.Unlock() var nonce [nonceLen]byte + var info *Info - // Grab server variables - s.mu.Lock() - info := s.copyLeafNodeInfo() + // Grab this before the client lock below. if !solicited { + // Grab server variables + s.mu.Lock() + info = s.copyLeafNodeInfo() + // For tests that want to simulate old servers, do not set the compression + // on the INFO protocol if configured with CompressionNotSupported. + if cm := opts.LeafNode.Compression.Mode; cm != CompressionNotSupported { + info.Compression = cm + } s.generateNonce(nonce[:]) + s.mu.Unlock() } - clusterName := s.info.Cluster - s.mu.Unlock() // Grab lock c.mu.Lock() - // If connection has been closed, this function will unlock and call - // closeConnection() to ensure proper clean-up. - isClosedUnlock := func() bool { - if c.isClosed() { - c.mu.Unlock() - c.closeConnection(WriteError) - return true - } - return false - } - - // I don't think that the connection can be closed this early (since it isn't - // registered anywhere and doesn't have read/write loops running), but let's - // check in case code is changed in the future and there is such possibility. - if isClosedUnlock() { - return nil - } - + var preBuf []byte if solicited { - // We need to wait here for the info, but not for too long. - c.nc.SetReadDeadline(time.Now().Add(DEFAULT_LEAFNODE_INFO_WAIT)) - br := bufio.NewReaderSize(c.nc, MAX_CONTROL_LINE_SIZE) - info, err := br.ReadString('\n') - if err != nil { - c.mu.Unlock() - if err == io.EOF { - c.closeConnection(ClientClosed) - } else { - c.closeConnection(ReadError) - } - return nil - } - c.nc.SetReadDeadline(time.Time{}) - - c.mu.Unlock() - // Handle only connection to wrong port here, others will be handled below. - if err := c.parse([]byte(info)); err == ErrConnectedToWrongPort { - c.Errorf(err.Error()) - c.closeConnection(WrongPort) - return nil - } - c.mu.Lock() - - if !c.flags.isSet(infoReceived) { - c.mu.Unlock() - c.Errorf("Did not get the remote leafnode's INFO, timed-out") - c.closeConnection(ReadError) - return nil - } - - // Not sure that can happen, but in case the connection was marked - // as closed during the call to parse... - if isClosedUnlock() { - return nil - } - - // Do TLS here as needed. - tlsRequired := remote.TLS || remote.TLSConfig != nil - if tlsRequired { - c.Debugf("Starting TLS leafnode client handshake") - // Specify the ServerName we are expecting. - var tlsConfig *tls.Config - if remote.TLSConfig != nil { - tlsConfig = remote.TLSConfig.Clone() - } else { - tlsConfig = &tls.Config{MinVersion: tls.VersionTLS12} - } - - var host string - // If ServerName was given to us from the option, use that, always. - if tlsConfig.ServerName == "" { - url := remote.getCurrentURL() - host = url.Hostname() - // We need to check if this host is an IP. If so, we probably - // had this advertised to us and should use the configured host - // name for the TLS server name. - if remote.tlsName != "" && net.ParseIP(host) != nil { - host = remote.tlsName + // For websocket connection, we need to send an HTTP request, + // and get the response before starting the readLoop to get + // the INFO, etc.. + if c.isWebsocket() { + var err error + var closeReason ClosedState + + preBuf, closeReason, err = c.leafNodeSolicitWSConnection(opts, rURL, remote) + if err != nil { + c.Errorf("Error soliciting websocket connection: %v", err) + c.mu.Unlock() + if closeReason != 0 { + c.closeConnection(closeReason) } - tlsConfig.ServerName = host - } - - c.nc = tls.Client(c.nc, tlsConfig) - - conn := c.nc.(*tls.Conn) - - // Setup the timeout - var wait time.Duration - if remote.TLSTimeout == 0 { - wait = TLS_TIMEOUT - } else { - wait = secondsToDuration(remote.TLSTimeout) - } - time.AfterFunc(wait, func() { tlsTimeout(c, conn) }) - conn.SetReadDeadline(time.Now().Add(wait)) - - // Force handshake - c.mu.Unlock() - if err = conn.Handshake(); err != nil { - // If we overrode and used the saved tlsName but that failed - // we will clear that here. This is for the case that another server - // does not have the same tlsName, maybe only IPs. - // https://github.com/nats-io/nats-server/issues/1256 - if _, ok := err.(x509.HostnameError); ok { - remote.Lock() - if host == remote.tlsName { - remote.tlsName = "" - } - remote.Unlock() - } - c.Errorf("TLS handshake error: %v", err) - c.closeConnection(TLSHandshakeError) return nil } - // Reset the read deadline - conn.SetReadDeadline(time.Time{}) - - // Re-Grab lock - c.mu.Lock() - - // Timeout may have closed the connection while the lock was released. - if isClosedUnlock() { - return nil + } else { + // If configured to do TLS handshake first + if tlsFirst { + if _, err := c.leafClientHandshakeIfNeeded(remote, opts); err != nil { + c.mu.Unlock() + return nil + } } + // We need to wait for the info, but not for too long. + c.nc.SetReadDeadline(time.Now().Add(infoTimeout)) } - if err := c.sendLeafConnect(clusterName, tlsRequired); err != nil { - c.mu.Unlock() - c.closeConnection(ProtocolViolation) - return nil - } - c.Debugf("Remote leafnode connect msg sent") - + // We will process the INFO from the readloop and finish by + // sending the CONNECT and finish registration later. } else { // Send our info to the other side. // Remember the nonce we sent here for signatures, etc. c.nonce = make([]byte, nonceLen) copy(c.nonce, nonce[:]) - info.Nonce = string(c.nonce) + info.Nonce = bytesToString(c.nonce) info.CID = c.cid - b, _ := json.Marshal(info) - pcs := [][]byte{[]byte("INFO"), b, []byte(CR_LF)} - // We have to send from this go routine because we may - // have to block for TLS handshake before we start our - // writeLoop go routine. The other side needs to receive - // this before it can initiate the TLS handshake.. - c.sendProtoNow(bytes.Join(pcs, []byte(" "))) - - // The above call could have marked the connection as closed (due to - // TCP error), so if that is the case, bail out here. - if isClosedUnlock() { - return nil + proto := generateInfoJSON(info) + + var pre []byte + // We need first to check for "TLS First" fallback delay. + if tlsFirstFallback > 0 { + // We wait and see if we are getting any data. Since we did not send + // the INFO protocol yet, only clients that use TLS first should be + // sending data (the TLS handshake). We don't really check the content: + // if it is a rogue agent and not an actual client performing the + // TLS handshake, the error will be detected when performing the + // handshake on our side. + pre = make([]byte, 4) + c.nc.SetReadDeadline(time.Now().Add(tlsFirstFallback)) + n, _ := io.ReadFull(c.nc, pre[:]) + c.nc.SetReadDeadline(time.Time{}) + // If we get any data (regardless of possible timeout), we will proceed + // with the TLS handshake. + if n > 0 { + pre = pre[:n] + } else { + // We did not get anything so we will send the INFO protocol. + pre = nil + // Set the boolean to false for the rest of the function. + tlsFirst = false + } } - // Check to see if we need to spin up TLS. - if info.TLSRequired { - c.Debugf("Starting TLS leafnode server handshake") - c.nc = tls.Server(c.nc, opts.LeafNode.TLSConfig) - conn := c.nc.(*tls.Conn) - - // Setup the timeout - ttl := secondsToDuration(opts.LeafNode.TLSTimeout) - time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) - conn.SetReadDeadline(time.Now().Add(ttl)) + if !tlsFirst { + // We have to send from this go routine because we may + // have to block for TLS handshake before we start our + // writeLoop go routine. The other side needs to receive + // this before it can initiate the TLS handshake.. + c.sendProtoNow(proto) - // Force handshake - c.mu.Unlock() - if err := conn.Handshake(); err != nil { - c.Errorf("TLS handshake error: %v", err) - c.closeConnection(TLSHandshakeError) + // The above call could have marked the connection as closed (due to TCP error). + if c.isClosed() { + c.mu.Unlock() + c.closeConnection(WriteError) return nil } - // Reset the read deadline - conn.SetReadDeadline(time.Time{}) - - // Re-Grab lock - c.mu.Lock() + } - // Indicate that handshake is complete (used in monitoring) - c.flags.set(handshakeComplete) + // Check to see if we need to spin up TLS. + if !c.isWebsocket() && info.TLSRequired { + // If we have a prebuffer create a multi-reader. + if len(pre) > 0 { + c.nc = &tlsMixConn{c.nc, bytes.NewBuffer(pre)} + } + // Perform server-side TLS handshake. + if err := c.doTLSServerHandshake(tlsHandshakeLeaf, opts.LeafNode.TLSConfig, opts.LeafNode.TLSTimeout, opts.LeafNode.TLSPinnedCerts); err != nil { + c.mu.Unlock() + return nil + } + } - // Timeout may have closed the connection while the lock was released. - if isClosedUnlock() { + // If the user wants the TLS handshake to occur first, now that it is + // done, send the INFO protocol. + if tlsFirst { + c.flags.set(didTLSFirst) + c.sendProtoNow(proto) + if c.isClosed() { + c.mu.Unlock() + c.closeConnection(WriteError) return nil } } // Leaf nodes will always require a CONNECT to let us know // when we are properly bound to an account. - // The connection may have been closed - c.setAuthTimer(secondsToDuration(opts.LeafNode.AuthTimeout)) + // + // If compression is configured, we can't set the authTimer here because + // it would cause the parser to fail any incoming protocol that is not a + // CONNECT (and we need to exchange INFO protocols for compression + // negotiation). So instead, use the ping timer until we are done with + // negotiation and can set the auth timer. + timeout := secondsToDuration(opts.LeafNode.AuthTimeout) + if needsCompression(opts.LeafNode.Compression.Mode) { + c.ping.tmr = time.AfterFunc(timeout, func() { + c.authTimeout() + }) + } else { + c.setAuthTimer(timeout) + } } // Keep track in case server is shutdown before we can successfully register. @@ -869,62 +1197,138 @@ func (s *Server) createLeafNode(conn net.Conn, remote *leafNodeCfg) *client { } // Spin up the read loop. - s.startGoRoutine(func() { c.readLoop(nil) }) + s.startGoRoutine(func() { c.readLoop(preBuf) }) - // Spin up the write loop. - s.startGoRoutine(func() { c.writeLoop() }) - - // Set the Ping timer - s.setFirstPingTimer(c) + // We will spin the write loop for solicited connections only + // when processing the INFO and after switching to TLS if needed. + if !solicited { + s.startGoRoutine(func() { c.writeLoop() }) + } c.mu.Unlock() - c.Debugf("Leafnode connection created") + return c +} - // Update server's accounting here if we solicited. - // Also send our local subs. - if solicited { - // Make sure we register with the account here. - c.registerWithAccount(acc) - s.addLeafNodeConnection(c, _EMPTY_, false) - s.initLeafNodeSmapAndSendSubs(c) - if sendSysConnectEvent { - s.sendLeafNodeConnect(acc) - } - - // The above functions are not atomically under the client - // lock doing those operations. It is possible - since we - // have started the read/write loops - that the connection - // is closed before or in between. This would leave the - // closed LN connection possible registered with the account - // and/or the server's leafs map. So check if connection - // is closed, and if so, manually cleanup. - c.mu.Lock() - closed := c.isClosed() - c.mu.Unlock() - if closed { - s.removeLeafNodeConnection(c) - if prev := acc.removeClient(c); prev == 1 { - s.decActiveAccounts() - } - } +// Will perform the client-side TLS handshake if needed. Assumes that this +// is called by the solicit side (remote will be non nil). Returns `true` +// if TLS is required, `false` otherwise. +// Lock held on entry. +func (c *client) leafClientHandshakeIfNeeded(remote *leafNodeCfg, opts *Options) (bool, error) { + // Check if TLS is required and gather TLS config variables. + tlsRequired, tlsConfig, tlsName, tlsTimeout := c.leafNodeGetTLSConfigForSolicit(remote) + if !tlsRequired { + return false, nil } - return c + // If TLS required, peform handshake. + // Get the URL that was used to connect to the remote server. + rURL := remote.getCurrentURL() + + // Perform the client-side TLS handshake. + if resetTLSName, err := c.doTLSClientHandshake(tlsHandshakeLeaf, rURL, tlsConfig, tlsName, tlsTimeout, opts.LeafNode.TLSPinnedCerts); err != nil { + // Check if we need to reset the remote's TLS name. + if resetTLSName { + remote.Lock() + remote.tlsName = _EMPTY_ + remote.Unlock() + } + return false, err + } + return true, nil } -func (c *client) processLeafnodeInfo(info *Info) error { +func (c *client) processLeafnodeInfo(info *Info) { c.mu.Lock() - defer c.mu.Unlock() - if c.leaf == nil || c.isClosed() { - return nil + c.mu.Unlock() + return + } + s := c.srv + opts := s.getOpts() + remote := c.leaf.remote + didSolicit := remote != nil + firstINFO := !c.flags.isSet(infoReceived) + + // In case of websocket, the TLS handshake has been already done. + // So check only for non websocket connections and for configurations + // where the TLS Handshake was not done first. + if didSolicit && !c.flags.isSet(handshakeComplete) && !c.isWebsocket() && !remote.TLSHandshakeFirst { + // If the server requires TLS, we need to set this in the remote + // otherwise if there is no TLS configuration block for the remote, + // the solicit side will not attempt to perform the TLS handshake. + if firstINFO && info.TLSRequired { + remote.TLS = true + } + if _, err := c.leafClientHandshakeIfNeeded(remote, opts); err != nil { + c.mu.Unlock() + return + } + } + + // Check for compression, unless already done. + if firstINFO && !c.flags.isSet(compressionNegotiated) { + // Prevent from getting back here. + c.flags.set(compressionNegotiated) + + var co *CompressionOpts + if !didSolicit { + co = &opts.LeafNode.Compression + } else { + co = &remote.Compression + } + if needsCompression(co.Mode) { + // Release client lock since following function will need server lock. + c.mu.Unlock() + compress, err := s.negotiateLeafCompression(c, didSolicit, info.Compression, co) + if err != nil { + c.sendErrAndErr(err.Error()) + c.closeConnection(ProtocolViolation) + return + } + if compress { + // Done for now, will get back another INFO protocol... + return + } + // No compression because one side does not want/can't, so proceed. + c.mu.Lock() + // Check that the connection did not close if the lock was released. + if c.isClosed() { + c.mu.Unlock() + return + } + } else { + // Coming from an old server, the Compression field would be the empty + // string. For servers that are configured with CompressionNotSupported, + // this makes them behave as old servers. + if info.Compression == _EMPTY_ || co.Mode == CompressionNotSupported { + c.leaf.compression = CompressionNotSupported + } else { + c.leaf.compression = CompressionOff + } + } + // Accepting side does not normally process an INFO protocol during + // initial connection handshake. So we keep it consistent by returning + // if we are not soliciting. + if !didSolicit { + // If we had created the ping timer instead of the auth timer, we will + // clear the ping timer and set the auth timer now that the compression + // negotiation is done. + if info.Compression != _EMPTY_ && c.ping.tmr != nil { + clearTimer(&c.ping.tmr) + c.setAuthTimer(secondsToDuration(opts.LeafNode.AuthTimeout)) + } + c.mu.Unlock() + return + } + // Fall through and process the INFO protocol as usual. } - // Mark that the INFO protocol has been received. // Note: For now, only the initial INFO has a nonce. We // will probably do auto key rotation at some point. - if c.flags.setIfNotSet(infoReceived) { + if firstINFO { + // Mark that the INFO protocol has been received. + c.flags.set(infoReceived) // Prevent connecting to non leafnode port. Need to do this only for // the first INFO, not for async INFO updates... // @@ -944,20 +1348,47 @@ func (c *client) processLeafnodeInfo(info *Info) error { // As seen from above, a solicited LeafNode connection should receive // from the remote server an INFO with CID and LeafNodeURLs. Anything // else should be considered an attempt to connect to a wrong port. - if c.leaf.remote != nil && (info.CID == 0 || info.LeafNodeURLs == nil) { - return ErrConnectedToWrongPort + if didSolicit && (info.CID == 0 || info.LeafNodeURLs == nil) { + c.mu.Unlock() + c.Errorf(ErrConnectedToWrongPort.Error()) + c.closeConnection(WrongPort) + return + } + // Reject a cluster that contains spaces. + if info.Cluster != _EMPTY_ && strings.Contains(info.Cluster, " ") { + c.mu.Unlock() + c.sendErrAndErr(ErrClusterNameHasSpaces.Error()) + c.closeConnection(ProtocolViolation) + return } // Capture a nonce here. c.nonce = []byte(info.Nonce) - if info.TLSRequired && c.leaf.remote != nil { - c.leaf.remote.TLS = true + if info.TLSRequired && didSolicit { + remote.TLS = true } supportsHeaders := c.srv.supportsHeaders() c.headers = supportsHeaders && info.Headers + + // Remember the remote server. + // Pre 2.2.0 servers are not sending their server name. + // In that case, use info.ID, which, for those servers, matches + // the content of the field `Name` in the leafnode CONNECT protocol. + if info.Name == _EMPTY_ { + c.leaf.remoteServer = info.ID + } else { + c.leaf.remoteServer = info.Name + } + c.leaf.remoteDomain = info.Domain + c.leaf.remoteCluster = info.Cluster + // We send the protocol version in the INFO protocol. + // Keep track of it, so we know if this connection supports message + // tracing for instance. + c.opts.Protocol = info.Proto } + // For both initial INFO and async INFO protocols, Possibly // update our list of remote leafnode URLs we can connect to. - if c.leaf.remote != nil && len(info.LeafNodeURLs) > 0 { + if didSolicit && (len(info.LeafNodeURLs) > 0 || len(info.WSConnectURLs) > 0) { // Consider the incoming array as the most up-to-date // representation of the remote cluster's list of URLs. c.updateLeafNodeURLs(info) @@ -972,16 +1403,115 @@ func (c *client) processLeafnodeInfo(info *Info) error { // Check if we have local deny clauses that we need to merge. if remote := c.leaf.remote; remote != nil { if len(remote.DenyExports) > 0 { + if perms.Publish == nil { + perms.Publish = &SubjectPermission{} + } perms.Publish.Deny = append(perms.Publish.Deny, remote.DenyExports...) } if len(remote.DenyImports) > 0 { + if perms.Subscribe == nil { + perms.Subscribe = &SubjectPermission{} + } perms.Subscribe.Deny = append(perms.Subscribe.Deny, remote.DenyImports...) } } c.setPermissions(perms) } - return nil + var resumeConnect bool + + // If this is a remote connection and this is the first INFO protocol, + // then we need to finish the connect process by sending CONNECT, etc.. + if firstINFO && didSolicit { + // Clear deadline that was set in createLeafNode while waiting for the INFO. + c.nc.SetDeadline(time.Time{}) + resumeConnect = true + } else if !firstINFO && didSolicit { + c.leaf.remoteAccName = info.RemoteAccount + } + + // Check if we have the remote account information and if so make sure it's stored. + if info.RemoteAccount != _EMPTY_ { + s.leafRemoteAccounts.Store(c.acc.Name, info.RemoteAccount) + } + c.mu.Unlock() + + finishConnect := info.ConnectInfo + if resumeConnect && s != nil { + s.leafNodeResumeConnectProcess(c) + if !info.InfoOnConnect { + finishConnect = true + } + } + if finishConnect { + s.leafNodeFinishConnectProcess(c) + } + + // Check to see if we need to kick any internal source or mirror consumers. + // This will be a no-op if JetStream not enabled for this server or if the bound account + // does not have jetstream. + s.checkInternalSyncConsumers(c.acc) +} + +func (s *Server) negotiateLeafCompression(c *client, didSolicit bool, infoCompression string, co *CompressionOpts) (bool, error) { + // Negotiate the appropriate compression mode (or no compression) + cm, err := selectCompressionMode(co.Mode, infoCompression) + if err != nil { + return false, err + } + c.mu.Lock() + // For "auto" mode, set the initial compression mode based on RTT + if cm == CompressionS2Auto { + if c.rttStart.IsZero() { + c.rtt = computeRTT(c.start) + } + cm = selectS2AutoModeBasedOnRTT(c.rtt, co.RTTThresholds) + } + // Keep track of the negotiated compression mode. + c.leaf.compression = cm + cid := c.cid + var nonce string + if !didSolicit { + nonce = bytesToString(c.nonce) + } + c.mu.Unlock() + + if !needsCompression(cm) { + return false, nil + } + + // If we end-up doing compression... + + // Generate an INFO with the chosen compression mode. + s.mu.Lock() + info := s.copyLeafNodeInfo() + info.Compression, info.CID, info.Nonce = compressionModeForInfoProtocol(co, cm), cid, nonce + infoProto := generateInfoJSON(info) + s.mu.Unlock() + + // If we solicited, then send this INFO protocol BEFORE switching + // to compression writer. However, if we did not, we send it after. + c.mu.Lock() + if didSolicit { + c.enqueueProto(infoProto) + // Make sure it is completely flushed (the pending bytes goes to + // 0) before proceeding. + for c.out.pb > 0 && !c.isClosed() { + c.flushOutbound() + } + } + // This is to notify the readLoop that it should switch to a + // (de)compression reader. + c.in.flags.set(switchToCompression) + // Create the compress writer before queueing the INFO protocol for + // a route that did not solicit. It will make sure that that proto + // is sent with compression on. + c.out.cw = s2.NewWriter(nil, s2WriterOptions(cm)...) + if !didSolicit { + c.enqueueProto(infoProto) + } + c.mu.Unlock() + return true, nil } // When getting a leaf node INFO protocol, use the provided @@ -991,11 +1521,29 @@ func (c *client) updateLeafNodeURLs(info *Info) { cfg.Lock() defer cfg.Unlock() - cfg.urls = make([]*url.URL, 0, 1+len(info.LeafNodeURLs)) + // We have ensured that if a remote has a WS scheme, then all are. + // So check if first is WS, then add WS URLs, otherwise, add non WS ones. + if len(cfg.URLs) > 0 && isWSURL(cfg.URLs[0]) { + // It does not really matter if we use "ws://" or "wss://" here since + // we will have already marked that the remote should use TLS anyway. + // But use proper scheme for log statements, etc... + proto := wsSchemePrefix + if cfg.TLS { + proto = wsSchemePrefixTLS + } + c.doUpdateLNURLs(cfg, proto, info.WSConnectURLs) + return + } + c.doUpdateLNURLs(cfg, "nats-leaf", info.LeafNodeURLs) +} + +func (c *client) doUpdateLNURLs(cfg *leafNodeCfg, scheme string, URLs []string) { + cfg.urls = make([]*url.URL, 0, 1+len(URLs)) // Add the ones we receive in the protocol - for _, surl := range info.LeafNodeURLs { - url, err := url.Parse("nats-leaf://" + surl) + for _, surl := range URLs { + url, err := url.Parse(fmt.Sprintf("%s://%s", scheme, surl)) if err != nil { + // As per below, the URLs we receive should not have contained URL info, so this should be safe to log. c.Errorf("Error parsing url %q: %v", surl, err) continue } @@ -1058,7 +1606,7 @@ func (s *Server) setLeafNodeInfoHostPortAndIP() error { // Add the connection to the map of leaf nodes. // If `checkForDup` is true (invoked when a leafnode is accepted), then we check -// if a connection already exists for the same server name (ID) and account. +// if a connection already exists for the same server name and account. // That can happen when the remote is attempting to reconnect while the accepting // side did not detect the connection as broken yet. // But it can also happen when there is a misconfiguration and the remote is @@ -1068,22 +1616,34 @@ func (s *Server) setLeafNodeInfoHostPortAndIP() error { // (this solves the stale connection situation). An error is returned to help the // remote detect the misconfiguration when the duplicate is the result of that // misconfiguration. -func (s *Server) addLeafNodeConnection(c *client, srvName string, checkForDup bool) { +func (s *Server) addLeafNodeConnection(c *client, srvName, clusterName string, checkForDup bool) { var accName string c.mu.Lock() cid := c.cid - if c.acc != nil { - accName = c.acc.Name - } + acc := c.acc + if acc != nil { + accName = acc.Name + } + myRemoteDomain := c.leaf.remoteDomain + mySrvName := c.leaf.remoteServer + remoteAccName := c.leaf.remoteAccName + myClustName := c.leaf.remoteCluster + solicited := c.leaf.remote != nil c.mu.Unlock() var old *client s.mu.Lock() - if checkForDup { + // We check for empty because in some test we may send empty CONNECT{} + if checkForDup && srvName != _EMPTY_ { for _, ol := range s.leafs { ol.mu.Lock() - // We check for empty because in some test we may send empty CONNECT{} - if srvName != _EMPTY_ && ol.opts.Name == srvName && ol.acc.Name == accName { + // We care here only about non solicited Leafnode. This function + // is more about replacing stale connections than detecting loops. + // We have code for the loop detection elsewhere, which also delays + // attempt to reconnect. + if !ol.isSolicitedLeafNode() && ol.leaf.remoteServer == srvName && + ol.leaf.remoteCluster == clusterName && ol.acc.Name == accName && + remoteAccName != _EMPTY_ && ol.leaf.remoteAccName == remoteAccName { old = ol } ol.mu.Unlock() @@ -1103,14 +1663,136 @@ func (s *Server) addLeafNodeConnection(c *client, srvName string, checkForDup bo old.closeConnection(DuplicateRemoteLeafnodeConnection) c.Warnf("Replacing connection from same server") } + + srvDecorated := func() string { + if myClustName == _EMPTY_ { + return mySrvName + } + return fmt.Sprintf("%s/%s", mySrvName, myClustName) + } + + opts := s.getOpts() + sysAcc := s.SystemAccount() + js := s.getJetStream() + var meta *raft + if js != nil { + if mg := js.getMetaGroup(); mg != nil { + meta = mg.(*raft) + } + } + blockMappingOutgoing := false + // Deny (non domain) JetStream API traffic unless system account is shared + // and domain names are identical and extending is not disabled + + // Check if backwards compatibility has been enabled and needs to be acted on + forceSysAccDeny := false + if len(opts.JsAccDefaultDomain) > 0 { + if acc == sysAcc { + for _, d := range opts.JsAccDefaultDomain { + if d == _EMPTY_ { + // Extending JetStream via leaf node is mutually exclusive with a domain mapping to the empty/default domain. + // As soon as one mapping to "" is found, disable the ability to extend JS via a leaf node. + c.Noticef("Not extending remote JetStream domain %q due to presence of empty default domain", myRemoteDomain) + forceSysAccDeny = true + break + } + } + } else if domain, ok := opts.JsAccDefaultDomain[accName]; ok && domain == _EMPTY_ { + // for backwards compatibility with old setups that do not have a domain name set + c.Debugf("Skipping deny %q for account %q due to default domain", jsAllAPI, accName) + return + } + } + + // If the server has JS disabled, it may still be part of a JetStream that could be extended. + // This is either signaled by js being disabled and a domain set, + // or in cases where no domain name exists, an extension hint is set. + // However, this is only relevant in mixed setups. + // + // If the system account connects but default domains are present, JetStream can't be extended. + if opts.JetStreamDomain != myRemoteDomain || (!opts.JetStream && (opts.JetStreamDomain == _EMPTY_ && opts.JetStreamExtHint != jsWillExtend)) || + sysAcc == nil || acc == nil || forceSysAccDeny { + // If domain names mismatch always deny. This applies to system accounts as well as non system accounts. + // Not having a system account, account or JetStream disabled is considered a mismatch as well. + if acc != nil && acc == sysAcc { + c.Noticef("System account connected from %s", srvDecorated()) + c.Noticef("JetStream not extended, domains differ") + c.mergeDenyPermissionsLocked(both, denyAllJs) + // When a remote with a system account is present in a server, unless otherwise disabled, the server will be + // started in observer mode. Now that it is clear that this not used, turn the observer mode off. + if solicited && meta != nil && meta.IsObserver() { + meta.setObserver(false, extNotExtended) + c.Debugf("Turning JetStream metadata controller Observer Mode off") + // Take note that the domain was not extended to avoid this state from startup. + writePeerState(js.config.StoreDir, meta.currentPeerState()) + // Meta controller can't be leader yet. + // Yet it is possible that due to observer mode every server already stopped campaigning. + // Therefore this server needs to be kicked into campaigning gear explicitly. + meta.Campaign() + } + } else { + c.Noticef("JetStream using domains: local %q, remote %q", opts.JetStreamDomain, myRemoteDomain) + c.mergeDenyPermissionsLocked(both, denyAllClientJs) + } + blockMappingOutgoing = true + } else if acc == sysAcc { + // system account and same domain + s.sys.client.Noticef("Extending JetStream domain %q as System Account connected from server %s", + myRemoteDomain, srvDecorated()) + // In an extension use case, pin leadership to server remotes connect to. + // Therefore, server with a remote that are not already in observer mode, need to be put into it. + if solicited && meta != nil && !meta.IsObserver() { + meta.setObserver(true, extExtended) + c.Debugf("Turning JetStream metadata controller Observer Mode on - System Account Connected") + // Take note that the domain was not extended to avoid this state next startup. + writePeerState(js.config.StoreDir, meta.currentPeerState()) + // If this server is the leader already, step down so a new leader can be elected (that is not an observer) + meta.StepDown() + } + } else { + // This deny is needed in all cases (system account shared or not) + // If the system account is shared, jsAllAPI traffic will go through the system account. + // So in order to prevent duplicate delivery (from system and actual account) suppress it on the account. + // If the system account is NOT shared, jsAllAPI traffic has no business + c.Debugf("Adding deny %+v for account %q", denyAllClientJs, accName) + c.mergeDenyPermissionsLocked(both, denyAllClientJs) + } + // If we have a specified JetStream domain we will want to add a mapping to + // allow access cross domain for each non-system account. + if opts.JetStreamDomain != _EMPTY_ && opts.JetStream && acc != nil && acc != sysAcc { + for src, dest := range generateJSMappingTable(opts.JetStreamDomain) { + if err := acc.AddMapping(src, dest); err != nil { + c.Debugf("Error adding JetStream domain mapping: %s", err.Error()) + } else { + c.Debugf("Adding JetStream Domain Mapping %q -> %s to account %q", src, dest, accName) + } + } + if blockMappingOutgoing { + src := fmt.Sprintf(jsDomainAPI, opts.JetStreamDomain) + // make sure that messages intended for this domain, do not leave the cluster via this leaf node connection + // This is a guard against a miss-config with two identical domain names and will only cover some forms + // of this issue, not all of them. + // This guards against a hub and a spoke having the same domain name. + // But not two spokes having the same one and the request coming from the hub. + c.mergeDenyPermissionsLocked(pub, []string{src}) + c.Debugf("Adding deny %q for outgoing messages to account %q", src, accName) + } + } } func (s *Server) removeLeafNodeConnection(c *client) { c.mu.Lock() cid := c.cid - if c.leaf != nil && c.leaf.tsubt != nil { - c.leaf.tsubt.Stop() - c.leaf.tsubt = nil + if c.leaf != nil { + if c.leaf.tsubt != nil { + c.leaf.tsubt.Stop() + c.leaf.tsubt = nil + } + if c.leaf.gwSub != nil { + s.gwLeafSubs.Remove(c.leaf.gwSub) + // We need to set this to nil for GC to release the connection + c.leaf.gwSub = nil + } } c.mu.Unlock() s.mu.Lock() @@ -1119,19 +1801,43 @@ func (s *Server) removeLeafNodeConnection(c *client) { s.removeFromTempClients(cid) } +// Connect information for solicited leafnodes. type leafConnectInfo struct { - JWT string `json:"jwt,omitempty"` - Sig string `json:"sig,omitempty"` - User string `json:"user,omitempty"` - Pass string `json:"pass,omitempty"` - TLS bool `json:"tls_required"` - Comp bool `json:"compression,omitempty"` - Name string `json:"name,omitempty"` - Hub bool `json:"is_hub,omitempty"` - Cluster string `json:"cluster,omitempty"` + Version string `json:"version,omitempty"` + Nkey string `json:"nkey,omitempty"` + JWT string `json:"jwt,omitempty"` + Sig string `json:"sig,omitempty"` + User string `json:"user,omitempty"` + Pass string `json:"pass,omitempty"` + Token string `json:"auth_token,omitempty"` + ID string `json:"server_id,omitempty"` + Domain string `json:"domain,omitempty"` + Name string `json:"name,omitempty"` + Hub bool `json:"is_hub,omitempty"` + Cluster string `json:"cluster,omitempty"` + Headers bool `json:"headers,omitempty"` + JetStream bool `json:"jetstream,omitempty"` + DenyPub []string `json:"deny_pub,omitempty"` + + // There was an existing field called: + // >> Comp bool `json:"compression,omitempty"` + // that has never been used. With support for compression, we now need + // a field that is a string. So we use a different json tag: + Compression string `json:"compress_mode,omitempty"` // Just used to detect wrong connection attempts. Gateway string `json:"gateway,omitempty"` + + // Tells the accept side which account the remote is binding to. + RemoteAccount string `json:"remote_account,omitempty"` + + // The accept side of a LEAF connection, unlike ROUTER and GATEWAY, receives + // only the CONNECT protocol, and no INFO. So we need to send the protocol + // version as part of the CONNECT. It will indicate if a connection supports + // some features, such as message tracing. + // We use `protocol` as the JSON tag, so this is automatically unmarshal'ed + // in the low level process CONNECT. + Proto int `json:"protocol,omitempty"` } // processLeafNodeConnect will process the inbound connect args. @@ -1140,7 +1846,7 @@ type leafConnectInfo struct { func (c *client) processLeafNodeConnect(s *Server, arg []byte, lang string) error { // Way to detect clients that incorrectly connect to the route listen // port. Client provided "lang" in the CONNECT protocol while LEAFNODEs don't. - if lang != "" { + if lang != _EMPTY_ { c.sendErrAndErr(ErrClientConnectedToLeafNodePort.Error()) c.closeConnection(WrongPort) return ErrClientConnectedToLeafNodePort @@ -1152,9 +1858,23 @@ func (c *client) processLeafNodeConnect(s *Server, arg []byte, lang string) erro return err } + // Reject a cluster that contains spaces. + if proto.Cluster != _EMPTY_ && strings.Contains(proto.Cluster, " ") { + c.sendErrAndErr(ErrClusterNameHasSpaces.Error()) + c.closeConnection(ProtocolViolation) + return ErrClusterNameHasSpaces + } + + // Check for cluster name collisions. + if cn := s.cachedClusterName(); cn != _EMPTY_ && proto.Cluster != _EMPTY_ && proto.Cluster == cn { + c.sendErrAndErr(ErrLeafNodeHasSameClusterName.Error()) + c.closeConnection(ClusterNamesIdentical) + return ErrLeafNodeHasSameClusterName + } + // Reject if this has Gateway which means that it would be from a gateway // connection that incorrectly connects to the leafnode port. - if proto.Gateway != "" { + if proto.Gateway != _EMPTY_ { errTxt := fmt.Sprintf("Rejecting connection from gateway %q on the leafnode port", proto.Gateway) c.Errorf(errTxt) c.sendErr(errTxt) @@ -1162,11 +1882,52 @@ func (c *client) processLeafNodeConnect(s *Server, arg []byte, lang string) erro return ErrWrongGateway } + if mv := s.getOpts().LeafNode.MinVersion; mv != _EMPTY_ { + major, minor, update, _ := versionComponents(mv) + if !versionAtLeast(proto.Version, major, minor, update) { + // We are going to send back an INFO because otherwise recent + // versions of the remote server would simply break the connection + // after 2 seconds if not receiving it. Instead, we want the + // other side to just "stall" until we finish waiting for the holding + // period and close the connection below. + s.sendPermsAndAccountInfo(c) + c.sendErrAndErr(fmt.Sprintf("connection rejected since minimum version required is %q", mv)) + select { + case <-c.srv.quitCh: + case <-time.After(leafNodeWaitBeforeClose): + } + c.closeConnection(MinimumVersionRequired) + return ErrMinimumVersionRequired + } + } + + // Check if this server supports headers. + supportHeaders := c.srv.supportsHeaders() + c.mu.Lock() // Leaf Nodes do not do echo or verbose or pedantic. c.opts.Verbose = false c.opts.Echo = false c.opts.Pedantic = false + // This inbound connection will be marked as supporting headers if this server + // support headers and the remote has sent in the CONNECT protocol that it does + // support headers too. + c.headers = supportHeaders && proto.Headers + // If the compression level is still not set, set it based on what has been + // given to us in the CONNECT protocol. + if c.leaf.compression == _EMPTY_ { + // But if proto.Compression is _EMPTY_, set it to CompressionNotSupported + if proto.Compression == _EMPTY_ { + c.leaf.compression = CompressionNotSupported + } else { + c.leaf.compression = proto.Compression + } + } + + // Remember the remote server. + c.leaf.remoteServer = proto.Name + // Remember the remote account name + c.leaf.remoteAccName = proto.RemoteAccount // If the other side has declared itself a hub, so we will take on the spoke role. if proto.Hub { @@ -1174,52 +1935,123 @@ func (c *client) processLeafNodeConnect(s *Server, arg []byte, lang string) erro } // The soliciting side is part of a cluster. - if proto.Cluster != "" { + if proto.Cluster != _EMPTY_ { c.leaf.remoteCluster = proto.Cluster } + + c.leaf.remoteDomain = proto.Domain + + // When a leaf solicits a connection to a hub, the perms that it will use on the soliciting leafnode's + // behalf are correct for them, but inside the hub need to be reversed since data is flowing in the opposite direction. + if !c.isSolicitedLeafNode() && c.perms != nil { + sp, pp := c.perms.sub, c.perms.pub + c.perms.sub, c.perms.pub = pp, sp + if c.opts.Import != nil { + c.darray = c.opts.Import.Deny + } else { + c.darray = nil + } + } + + // Set the Ping timer + c.setFirstPingTimer() + + // If we received pub deny permissions from the other end, merge with existing ones. + c.mergeDenyPermissions(pub, proto.DenyPub) + + acc := c.acc c.mu.Unlock() + // Register the cluster, even if empty, as long as we are acting as a hub. + if !proto.Hub { + acc.registerLeafNodeCluster(proto.Cluster) + } + // Add in the leafnode here since we passed through auth at this point. - s.addLeafNodeConnection(c, proto.Name, true) + s.addLeafNodeConnection(c, proto.Name, proto.Cluster, true) // If we have permissions bound to this leafnode we need to send then back to the // origin server for local enforcement. - s.sendPermsInfo(c) + s.sendPermsAndAccountInfo(c) // Create and initialize the smap since we know our bound account now. // This will send all registered subs too. s.initLeafNodeSmapAndSendSubs(c) // Announce the account connect event for a leaf node. - // This will no-op as needed. + // This will be a no-op as needed. s.sendLeafNodeConnect(c.acc) + // Check to see if we need to kick any internal source or mirror consumers. + // This will be a no-op if JetStream not enabled for this server or if the bound account + // does not have jetstream. + s.checkInternalSyncConsumers(acc) + return nil } +// checkInternalSyncConsumers +func (s *Server) checkInternalSyncConsumers(acc *Account) { + // Grab our js + js := s.getJetStream() + + // Only applicable if we have JS and the leafnode has JS as well. + // We check for remote JS outside. + if !js.isEnabled() || acc == nil { + return + } + + // We will check all streams in our local account. They must be a leader and + // be sourcing or mirroring. We will check the external config on the stream itself + // if this is cross domain, or if the remote domain is empty, meaning we might be + // extending the system across this leafnode connection and hence we would be extending + // our own domain. + jsa := js.lookupAccount(acc) + if jsa == nil { + return + } + + var streams []*stream + jsa.mu.RLock() + for _, mset := range jsa.streams { + mset.cfgMu.RLock() + // We need to have a mirror or source defined. + // We do not want to force another lock here to look for leader status, + // so collect and after we release jsa will make sure. + if mset.cfg.Mirror != nil || len(mset.cfg.Sources) > 0 { + streams = append(streams, mset) + } + mset.cfgMu.RUnlock() + } + jsa.mu.RUnlock() + + // Now loop through all candidates and check if we are the leader and have NOT + // created the sync up consumer. + for _, mset := range streams { + mset.retryDisconnectedSyncConsumers() + } +} + // Returns the remote cluster name. This is set only once so does not require a lock. func (c *client) remoteCluster() string { if c.leaf == nil { - return "" + return _EMPTY_ } return c.leaf.remoteCluster } // Sends back an info block to the soliciting leafnode to let it know about // its permission settings for local enforcement. -func (s *Server) sendPermsInfo(c *client) { - if c.perms == nil { - return - } +func (s *Server) sendPermsAndAccountInfo(c *client) { // Copy info := s.copyLeafNodeInfo() c.mu.Lock() info.CID = c.cid info.Import = c.opts.Import info.Export = c.opts.Export - b, _ := json.Marshal(info) - pcs := [][]byte{[]byte("INFO"), b, []byte(CR_LF)} - c.enqueueProto(bytes.Join(pcs, []byte(" "))) + info.RemoteAccount = c.acc.Name + info.ConnectInfo = true + c.enqueueProto(generateInfoJSON(info)) c.mu.Unlock() } @@ -1233,33 +2065,62 @@ func (s *Server) initLeafNodeSmapAndSendSubs(c *client) { return } // Collect all account subs here. - _subs := [32]*subscription{} + _subs := [1024]*subscription{} subs := _subs[:0] ims := []string{} - acc.mu.Lock() + + // Hold the client lock otherwise there can be a race and miss some subs. + c.mu.Lock() + defer c.mu.Unlock() + + acc.mu.RLock() accName := acc.Name + accNTag := acc.nameTag + + // To make printing look better when no friendly name present. + if accNTag != _EMPTY_ { + accNTag = "/" + accNTag + } + // If we are solicited we only send interest for local clients. if c.isSpokeLeafNode() { - acc.sl.localSubs(&subs) + acc.sl.localSubs(&subs, true) } else { acc.sl.All(&subs) } // Check if we have an existing service import reply. - siReply := acc.siReply + siReply := copyBytes(acc.siReply) // Since leaf nodes only send on interest, if the bound // account has import services we need to send those over. for isubj := range acc.imports.services { + if c.isSpokeLeafNode() && !c.canSubscribe(isubj) { + c.Debugf("Not permitted to import service %q on behalf of %s%s", isubj, accName, accNTag) + continue + } ims = append(ims, isubj) } + // Likewise for mappings. + for _, m := range acc.mappings { + if c.isSpokeLeafNode() && !c.canSubscribe(m.src) { + c.Debugf("Not permitted to import mapping %q on behalf of %s%s", m.src, accName, accNTag) + continue + } + ims = append(ims, m.src) + } + // Create a unique subject that will be used for loop detection. lds := acc.lds + acc.mu.RUnlock() + + // Check if we have to create the LDS. if lds == _EMPTY_ { lds = leafNodeLoopDetectionSubjectPrefix + nuid.Next() + acc.mu.Lock() acc.lds = lds + acc.mu.Unlock() } - acc.mu.Unlock() // Now check for gateway interest. Leafnodes will put this into // the proper mode to propagate, but they are not held in the account. @@ -1283,16 +2144,30 @@ func (s *Server) initLeafNodeSmapAndSendSubs(c *client) { if c.isSpokeLeafNode() { // Add a fake subscription for this solicited leafnode connection // so that we can send back directly for mapped GW replies. - c.srv.gwLeafSubs.Insert(&subscription{client: c, subject: []byte(gwReplyPrefix + ">")}) + // We need to keep track of this subscription so it can be removed + // when the connection is closed so that the GC can release it. + c.leaf.gwSub = &subscription{client: c, subject: []byte(gwReplyPrefix + ">")} + c.srv.gwLeafSubs.Insert(c.leaf.gwSub) } // Now walk the results and add them to our smap - c.mu.Lock() + rc := c.leaf.remoteCluster c.leaf.smap = make(map[string]int32) for _, sub := range subs { + // Check perms regardless of role. + if c.perms != nil && !c.canSubscribe(string(sub.subject)) { + c.Debugf("Not permitted to subscribe to %q on behalf of %s%s", sub.subject, accName, accNTag) + continue + } // We ignore ourselves here. - if c != sub.client { - c.leaf.smap[keyFromSub(sub)]++ + // Also don't add the subscription if it has a origin cluster and the + // cluster name matches the one of the client we are sending to. + if c != sub.client && (sub.origin == nil || (bytesToString(sub.origin) != rc)) { + count := int32(1) + if len(sub.queue) > 0 && sub.qw > 0 { + count = sub.qw + } + c.leaf.smap[keyFromSub(sub)] += count if c.leaf.tsub == nil { c.leaf.tsub = make(map[*subscription]struct{}) } @@ -1310,8 +2185,8 @@ func (s *Server) initLeafNodeSmapAndSendSubs(c *client) { c.leaf.smap[oldGWReplyPrefix+"*.>"]++ c.leaf.smap[gwReplyPrefix+">"]++ } - // Detect loop by subscribing to a specific subject and checking - // if this is coming back to us. + // Detect loops by subscribing to a specific subject and checking + // if this sub is coming back to us. c.leaf.smap[lds]++ // Check if we need to add an existing siReply to our map. @@ -1340,7 +2215,6 @@ func (s *Server) initLeafNodeSmapAndSendSubs(c *client) { c.mu.Unlock() }) } - c.mu.Unlock() } // updateInterestForAccountOnGateway called from gateway code when processing RS+ and RS-. @@ -1350,56 +2224,97 @@ func (s *Server) updateInterestForAccountOnGateway(accName string, sub *subscrip s.Debugf("No or bad account for %q, failed to update interest from gateway", accName) return } - s.updateLeafNodes(acc, sub, delta) + acc.updateLeafNodes(sub, delta) } -// updateLeafNodes will make sure to update the smap for the subscription. Will -// also forward to all leaf nodes as needed. -func (s *Server) updateLeafNodes(acc *Account, sub *subscription, delta int32) { +// updateLeafNodesEx will make sure to update the account smap for the subscription. +// Will also forward to all leaf nodes as needed. +// If `hubOnly` is true, then will update only leaf nodes that connect to this server +// (that is, for which this server acts as a hub to them). +func (acc *Account) updateLeafNodesEx(sub *subscription, delta int32, hubOnly bool) { if acc == nil || sub == nil { return } - _l := [32]*client{} - leafs := _l[:0] + // We will do checks for no leafnodes and same cluster here inline and under the + // general account read lock. + // If we feel we need to update the leafnodes we will do that out of line to avoid + // blocking routes or GWs. - // Grab all leaf nodes. Ignore a leafnode if sub's client is a leafnode and matches. acc.mu.RLock() - for _, ln := range acc.lleafs { - if ln != sub.client { - leafs = append(leafs, ln) - } + // First check if we even have leafnodes here. + if acc.nleafs == 0 { + acc.mu.RUnlock() + return + } + + // Is this a loop detection subject. + isLDS := bytes.HasPrefix(sub.subject, []byte(leafNodeLoopDetectionSubjectPrefix)) + + // Capture the cluster even if its empty. + var cluster string + if sub.origin != nil { + cluster = bytesToString(sub.origin) } + + // If we have an isolated cluster we can return early, as long as it is not a loop detection subject. + // Empty clusters will return false for the check. + if !isLDS && acc.isLeafNodeClusterIsolated(cluster) { + acc.mu.RUnlock() + return + } + + // We can release the general account lock. acc.mu.RUnlock() - for _, ln := range leafs { - // Check to make sure this sub does not have an origin cluster than matches the leafnode. + // We can hold the list lock here to avoid having to copy a large slice. + acc.lmu.RLock() + defer acc.lmu.RUnlock() + + // Do this once. + subject := string(sub.subject) + + // Walk the connected leafnodes. + for _, ln := range acc.lleafs { + if ln == sub.client { + continue + } ln.mu.Lock() - skip := sub.origin != nil && string(sub.origin) == ln.remoteCluster() - ln.mu.Unlock() - if skip { + // If `hubOnly` is true, it means that we want to update only leafnodes + // that connect to this server (so isHubLeafNode() would return `true`). + if hubOnly && !ln.isHubLeafNode() { + ln.mu.Unlock() continue } - ln.updateSmap(sub, delta) + // Check to make sure this sub does not have an origin cluster that matches the leafnode. + // If skipped, make sure that we still let go the "$LDS." subscription that allows + // the detection of loops as long as different cluster. + clusterDifferent := cluster != ln.remoteCluster() + if (isLDS && clusterDifferent) || ((cluster == _EMPTY_ || clusterDifferent) && (delta <= 0 || ln.canSubscribe(subject))) { + ln.updateSmap(sub, delta, isLDS) + } + ln.mu.Unlock() } } +// updateLeafNodes will make sure to update the account smap for the subscription. +// Will also forward to all leaf nodes as needed. +func (acc *Account) updateLeafNodes(sub *subscription, delta int32) { + acc.updateLeafNodesEx(sub, delta, false) +} + // This will make an update to our internal smap and determine if we should send out // an interest update to the remote side. -func (c *client) updateSmap(sub *subscription, delta int32) { - key := keyFromSub(sub) - - c.mu.Lock() +// Lock should be held. +func (c *client) updateSmap(sub *subscription, delta int32, isLDS bool) { if c.leaf.smap == nil { - c.mu.Unlock() return } // If we are solicited make sure this is a local client or a non-solicited leaf node skind := sub.client.kind updateClient := skind == CLIENT || skind == SYSTEM || skind == JETSTREAM || skind == ACCOUNT - if c.isSpokeLeafNode() && !(updateClient || (skind == LEAF && !sub.client.isSpokeLeafNode())) { - c.mu.Unlock() + if !isLDS && c.isSpokeLeafNode() && !(updateClient || (skind == LEAF && !sub.client.isSpokeLeafNode())) { return } @@ -1412,14 +2327,18 @@ func (c *client) updateSmap(sub *subscription, delta int32) { c.leaf.tsubt.Stop() c.leaf.tsubt = nil } - c.mu.Unlock() return } } - n := c.leaf.smap[key] + key := keyFromSub(sub) + n, ok := c.leaf.smap[key] + if delta < 0 && !ok { + return + } + // We will update if its a queue, if count is zero (or negative), or we were 0 and are N > 0. - update := sub.queue != nil || n == 0 || n+delta <= 0 + update := sub.queue != nil || (n <= 0 && n+delta > 0) || (n > 0 && n+delta <= 0) n += delta if n > 0 { c.leaf.smap[key] = n @@ -1429,7 +2348,45 @@ func (c *client) updateSmap(sub *subscription, delta int32) { if update { c.sendLeafNodeSubUpdate(key, n) } - c.mu.Unlock() +} + +// Used to force add subjects to the subject map. +func (c *client) forceAddToSmap(subj string) { + c.mu.Lock() + defer c.mu.Unlock() + + if c.leaf.smap == nil { + return + } + n := c.leaf.smap[subj] + if n != 0 { + return + } + // Place into the map since it was not there. + c.leaf.smap[subj] = 1 + c.sendLeafNodeSubUpdate(subj, 1) +} + +// Used to force remove a subject from the subject map. +func (c *client) forceRemoveFromSmap(subj string) { + c.mu.Lock() + defer c.mu.Unlock() + + if c.leaf.smap == nil { + return + } + n := c.leaf.smap[subj] + if n == 0 { + return + } + n-- + if n == 0 { + // Remove is now zero + delete(c.leaf.smap, subj) + c.sendLeafNodeSubUpdate(subj, 0) + } else { + c.leaf.smap[subj] = n + } } // Send the subscription interest change to the other side. @@ -1445,8 +2402,16 @@ func (c *client) sendLeafNodeSubUpdate(key string, n int32) { checkPerms = false } } - if checkPerms && !c.canSubscribe(key) { - return + if checkPerms { + var subject string + if sep := strings.IndexByte(key, ' '); sep != -1 { + subject = key[:sep] + } else { + subject = key + } + if !c.canSubscribe(subject) { + return + } } } // If we are here we can send over to the other side. @@ -1458,24 +2423,56 @@ func (c *client) sendLeafNodeSubUpdate(key string, n int32) { // Helper function to build the key. func keyFromSub(sub *subscription) string { - var _rkey [1024]byte - var key []byte - + var sb strings.Builder + sb.Grow(len(sub.subject) + len(sub.queue) + 1) + sb.Write(sub.subject) if sub.queue != nil { // Just make the key subject spc group, e.g. 'foo bar' - key = _rkey[:0] - key = append(key, sub.subject...) - key = append(key, byte(' ')) - key = append(key, sub.queue...) + sb.WriteByte(' ') + sb.Write(sub.queue) + } + return sb.String() +} + +const ( + keyRoutedSub = "R" + keyRoutedSubByte = 'R' + keyRoutedLeafSub = "L" + keyRoutedLeafSubByte = 'L' +) + +// Helper function to build the key that prevents collisions between normal +// routed subscriptions and routed subscriptions on behalf of a leafnode. +// Keys will look like this: +// "R foo" -> plain routed sub on "foo" +// "R foo bar" -> queue routed sub on "foo", queue "bar" +// "L foo bar" -> plain routed leaf sub on "foo", leaf "bar" +// "L foo bar baz" -> queue routed sub on "foo", queue "bar", leaf "baz" +func keyFromSubWithOrigin(sub *subscription) string { + var sb strings.Builder + sb.Grow(2 + len(sub.origin) + 1 + len(sub.subject) + 1 + len(sub.queue)) + leaf := len(sub.origin) > 0 + if leaf { + sb.WriteByte(keyRoutedLeafSubByte) } else { - key = sub.subject + sb.WriteByte(keyRoutedSubByte) + } + sb.WriteByte(' ') + sb.Write(sub.subject) + if sub.queue != nil { + sb.WriteByte(' ') + sb.Write(sub.queue) + } + if leaf { + sb.WriteByte(' ') + sb.Write(sub.origin) } - return string(key) + return sb.String() } // Lock should be held. func (c *client) writeLeafSub(w *bytes.Buffer, key string, n int32) { - if key == "" { + if key == _EMPTY_ { return } if n > 0 { @@ -1523,12 +2520,21 @@ func (c *client) processLeafSub(argo []byte) (err error) { args := splitArg(arg) sub := &subscription{client: c} + delta := int32(1) switch len(args) { case 1: sub.queue = nil case 3: sub.queue = args[1] sub.qw = int32(parseSize(args[2])) + // TODO: (ik) We should have a non empty queue name and a queue + // weight >= 1. For 2.11, we may want to return an error if that + // is not the case, but for now just overwrite `delta` if queue + // weight is greater than 1 (it is possible after a reconnect/ + // server restart to receive a queue weight > 1 for a new sub). + if sub.qw > 1 { + delta = sub.qw + } default: return fmt.Errorf("processLeafSub Parse Error: '%s'", arg) } @@ -1543,7 +2549,8 @@ func (c *client) processLeafSub(argo []byte) (err error) { acc := c.acc // Check if we have a loop. ldsPrefix := bytes.HasPrefix(sub.subject, []byte(leafNodeLoopDetectionSubjectPrefix)) - if ldsPrefix && string(sub.subject) == acc.getLDSubject() { + + if ldsPrefix && bytesToString(sub.subject) == acc.getLDSubject() { c.mu.Unlock() c.handleLeafNodeLoop(true) return nil @@ -1558,10 +2565,16 @@ func (c *client) processLeafSub(argo []byte) (err error) { checkPerms = false } } - if checkPerms && c.isHubLeafNode() && !c.canSubscribe(string(sub.subject)) { - c.mu.Unlock() - c.leafSubPermViolation(sub.subject) - return nil + + // If we are a hub check that we can publish to this subject. + if checkPerms { + subj := string(sub.subject) + if subjectIsLiteral(subj) && !c.pubAllowedFullCheck(subj, true, true) { + c.mu.Unlock() + c.leafSubPermViolation(sub.subject) + c.Debugf(fmt.Sprintf("Permissions Violation for Subscription to %q", sub.subject)) + return nil + } } // Check if we have a maximum on the number of subscriptions. @@ -1583,9 +2596,8 @@ func (c *client) processLeafSub(argo []byte) (err error) { } else { sub.sid = arg } - key := string(sub.sid) + key := bytesToString(sub.sid) osub := c.subs[key] - updateGWs := false if osub == nil { c.subs[key] = sub // Now place into the account sl. @@ -1596,17 +2608,20 @@ func (c *client) processLeafSub(argo []byte) (err error) { c.sendErr("Invalid Subscription") return nil } - updateGWs = srv.gateway.enabled } else if sub.queue != nil { // For a queue we need to update the weight. + delta = sub.qw - atomic.LoadInt32(&osub.qw) atomic.StoreInt32(&osub.qw, sub.qw) acc.sl.UpdateRemoteQSub(osub) } spoke := c.isSpokeLeafNode() c.mu.Unlock() - if err := c.addShadowSubscriptions(acc, sub); err != nil { - c.Errorf(err.Error()) + // Only add in shadow subs if a new sub or qsub. + if osub == nil { + if err := c.addShadowSubscriptions(acc, sub); err != nil { + c.Errorf(err.Error()) + } } // If we are not solicited, treat leaf node subscriptions similar to a @@ -1614,14 +2629,14 @@ func (c *client) processLeafSub(argo []byte) (err error) { // other leaf nodes as needed. if !spoke { // If we are routing add to the route map for the associated account. - srv.updateRouteSubscriptionMap(acc, sub, 1) - if updateGWs { - srv.gatewayUpdateSubInterest(acc.Name, sub, 1) + srv.updateRouteSubscriptionMap(acc, sub, delta) + if srv.gateway.enabled { + srv.gatewayUpdateSubInterest(acc.Name, sub, delta) } } // Now check on leafnode updates for other leaf nodes. We understand solicited // and non-solicited state in this call so we will do the right thing. - srv.updateLeafNodes(acc, sub, 1) + acc.updateLeafNodes(sub, delta) return nil } @@ -1635,6 +2650,7 @@ func (c *client) handleLeafNodeLoop(sendErr bool) { if sendErr { c.sendErr(errTxt) } + c.Errorf(errTxt) // If we are here with "sendErr" false, it means that this is the server // that received the error. The other side will have closed the connection, @@ -1656,25 +2672,32 @@ func (c *client) processLeafUnsub(arg []byte) error { return nil } - updateGWs := false + spoke := c.isSpokeLeafNode() // We store local subs by account and subject and optionally queue name. // LS- will have the arg exactly as the key. sub, ok := c.subs[string(arg)] - c.mu.Unlock() - - if ok { - c.unsubscribe(acc, sub, true, true) - updateGWs = srv.gateway.enabled + if !ok { + // If not found, don't try to update routes/gws/leaf nodes. + c.mu.Unlock() + return nil } + delta := int32(1) + if len(sub.queue) > 0 { + delta = sub.qw + } + c.mu.Unlock() - // If we are routing subtract from the route map for the associated account. - srv.updateRouteSubscriptionMap(acc, sub, -1) - // Gateways - if updateGWs { - srv.gatewayUpdateSubInterest(acc.Name, sub, -1) + c.unsubscribe(acc, sub, true, true) + if !spoke { + // If we are routing subtract from the route map for the associated account. + srv.updateRouteSubscriptionMap(acc, sub, -delta) + // Gateways + if srv.gateway.enabled { + srv.gatewayUpdateSubInterest(acc.Name, sub, -delta) + } } // Now check on leafnode updates for other leaf nodes. - srv.updateLeafNodes(acc, sub, -1) + acc.updateLeafNodes(sub, -delta) return nil } @@ -1839,14 +2862,7 @@ func (c *client) processInboundLeafMsg(msg []byte) { c.in.msgs++ c.in.bytes += int32(len(msg) - LEN_CR_LF) - // Check pub permissions - if c.perms != nil && (c.perms.pub.allow != nil || c.perms.pub.deny != nil) && c.isHubLeafNode() && !c.pubAllowed(string(c.pa.subject)) { - c.leafPubPermViolation(c.pa.subject) - return - } - - srv := c.srv - acc := c.acc + srv, acc, subject := c.srv, c.acc, string(c.pa.subject) // Mostly under testing scenarios. if srv == nil || acc == nil { @@ -1860,7 +2876,7 @@ func (c *client) processInboundLeafMsg(msg []byte) { genid := atomic.LoadUint64(&c.acc.sl.genid) if genid == c.in.genid && c.in.results != nil { - r, ok = c.in.results[string(c.pa.subject)] + r, ok = c.in.results[subject] } else { // Reset our L1 completely. c.in.results = make(map[string]*SublistResult) @@ -1869,18 +2885,19 @@ func (c *client) processInboundLeafMsg(msg []byte) { // Go back to the sublist data structure. if !ok { - r = c.acc.sl.Match(string(c.pa.subject)) - c.in.results[string(c.pa.subject)] = r + r = c.acc.sl.Match(subject) // Prune the results cache. Keeps us from unbounded growth. Random delete. - if len(c.in.results) > maxResultCacheSize { + if len(c.in.results) >= maxResultCacheSize { n := 0 - for subject := range c.in.results { - delete(c.in.results, subject) + for subj := range c.in.results { + delete(c.in.results, subj) if n++; n > pruneSize { break } } } + // Then add the new cache entry. + c.in.results[subject] = r } // Collect queue names if needed. @@ -1898,21 +2915,21 @@ func (c *client) processInboundLeafMsg(msg []byte) { atomic.LoadInt64(&c.srv.gateway.totalQSubs) > 0 { flag |= pmrCollectQueueNames } + // If this is a mapped subject that means the mapped interest + // is what got us here, but this might not have a queue designation + // If that is the case, make sure we ignore to process local queue subscribers. + if len(c.pa.mapped) > 0 && len(c.pa.queues) == 0 { + flag |= pmrIgnoreEmptyQueueFilter + } _, qnames = c.processMsgResults(acc, r, msg, nil, c.pa.subject, c.pa.reply, flag) } // Now deal with gateways if c.srv.gateway.enabled { - c.sendMsgToGateways(acc, msg, c.pa.subject, c.pa.reply, qnames) + c.sendMsgToGateways(acc, msg, c.pa.subject, c.pa.reply, qnames, true) } } -// Handles a publish permission violation. -// See leafPermViolation() for details. -func (c *client) leafPubPermViolation(subj []byte) { - c.leafPermViolation(true, subj) -} - // Handles a subscription permission violation. // See leafPermViolation() for details. func (c *client) leafSubPermViolation(subj []byte) { @@ -1945,6 +2962,13 @@ func (c *client) leafPermViolation(pub bool, subj []byte) { // Invoked from generic processErr() for LEAF connections. func (c *client) leafProcessErr(errStr string) { + // Check if we got a cluster name collision. + if strings.Contains(errStr, ErrLeafNodeHasSameClusterName.Error()) { + _, delay := c.setLeafConnectDelayIfSoliciting(leafNodeReconnectDelayAfterClusterNameSame) + c.Errorf("Leafnode connection dropped with same cluster name error. Delaying attempt to reconnect for %v", delay) + return + } + // We will look for Loop detected error coming from the other side. // If we solicit, set the connect delay. if !strings.Contains(errStr, "Loop detected") { @@ -1970,3 +2994,264 @@ func (c *client) setLeafConnectDelayIfSoliciting(delay time.Duration) (string, t c.mu.Unlock() return accName, delay } + +// For the given remote Leafnode configuration, this function returns +// if TLS is required, and if so, will return a clone of the TLS Config +// (since some fields will be changed during handshake), the TLS server +// name that is remembered, and the TLS timeout. +func (c *client) leafNodeGetTLSConfigForSolicit(remote *leafNodeCfg) (bool, *tls.Config, string, float64) { + var ( + tlsConfig *tls.Config + tlsName string + tlsTimeout float64 + ) + + remote.RLock() + defer remote.RUnlock() + + tlsRequired := remote.TLS || remote.TLSConfig != nil + if tlsRequired { + if remote.TLSConfig != nil { + tlsConfig = remote.TLSConfig.Clone() + } else { + tlsConfig = &tls.Config{MinVersion: tls.VersionTLS12} + } + tlsName = remote.tlsName + tlsTimeout = remote.TLSTimeout + if tlsTimeout == 0 { + tlsTimeout = float64(TLS_TIMEOUT / time.Second) + } + } + + return tlsRequired, tlsConfig, tlsName, tlsTimeout +} + +// Initiates the LeafNode Websocket connection by: +// - doing the TLS handshake if needed +// - sending the HTTP request +// - waiting for the HTTP response +// +// Since some bufio reader is used to consume the HTTP response, this function +// returns the slice of buffered bytes (if any) so that the readLoop that will +// be started after that consume those first before reading from the socket. +// The boolean +// +// Lock held on entry. +func (c *client) leafNodeSolicitWSConnection(opts *Options, rURL *url.URL, remote *leafNodeCfg) ([]byte, ClosedState, error) { + remote.RLock() + compress := remote.Websocket.Compression + // By default the server will mask outbound frames, but it can be disabled with this option. + noMasking := remote.Websocket.NoMasking + infoTimeout := remote.FirstInfoTimeout + remote.RUnlock() + // Will do the client-side TLS handshake if needed. + tlsRequired, err := c.leafClientHandshakeIfNeeded(remote, opts) + if err != nil { + // 0 will indicate that the connection was already closed + return nil, 0, err + } + + // For http request, we need the passed URL to contain either http or https scheme. + scheme := "http" + if tlsRequired { + scheme = "https" + } + // We will use the `/leafnode` path to tell the accepting WS server that it should + // create a LEAF connection, not a CLIENT. + // In case we use the user's URL path in the future, make sure we append the user's + // path to our `/leafnode` path. + lpath := leafNodeWSPath + if curPath := rURL.EscapedPath(); curPath != _EMPTY_ { + if curPath[0] == '/' { + curPath = curPath[1:] + } + lpath = path.Join(curPath, lpath) + } else { + lpath = lpath[1:] + } + ustr := fmt.Sprintf("%s://%s/%s", scheme, rURL.Host, lpath) + u, _ := url.Parse(ustr) + req := &http.Request{ + Method: "GET", + URL: u, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: make(http.Header), + Host: u.Host, + } + wsKey, err := wsMakeChallengeKey() + if err != nil { + return nil, WriteError, err + } + + req.Header["Upgrade"] = []string{"websocket"} + req.Header["Connection"] = []string{"Upgrade"} + req.Header["Sec-WebSocket-Key"] = []string{wsKey} + req.Header["Sec-WebSocket-Version"] = []string{"13"} + if compress { + req.Header.Add("Sec-WebSocket-Extensions", wsPMCReqHeaderValue) + } + if noMasking { + req.Header.Add(wsNoMaskingHeader, wsNoMaskingValue) + } + c.nc.SetDeadline(time.Now().Add(infoTimeout)) + if err := req.Write(c.nc); err != nil { + return nil, WriteError, err + } + + var resp *http.Response + + br := bufio.NewReaderSize(c.nc, MAX_CONTROL_LINE_SIZE) + resp, err = http.ReadResponse(br, req) + if err == nil && + (resp.StatusCode != 101 || + !strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") || + !strings.EqualFold(resp.Header.Get("Connection"), "upgrade") || + resp.Header.Get("Sec-Websocket-Accept") != wsAcceptKey(wsKey)) { + + err = fmt.Errorf("invalid websocket connection") + } + // Check compression extension... + if err == nil && c.ws.compress { + // Check that not only permessage-deflate extension is present, but that + // we also have server and client no context take over. + srvCompress, noCtxTakeover := wsPMCExtensionSupport(resp.Header, false) + + // If server does not support compression, then simply disable it in our side. + if !srvCompress { + c.ws.compress = false + } else if !noCtxTakeover { + err = fmt.Errorf("compression negotiation error") + } + } + // Same for no masking... + if err == nil && noMasking { + // Check if server accepts no masking + if resp.Header.Get(wsNoMaskingHeader) != wsNoMaskingValue { + // Nope, need to mask our writes as any client would do. + c.ws.maskwrite = true + } + } + if resp != nil { + resp.Body.Close() + } + if err != nil { + return nil, ReadError, err + } + c.Debugf("Leafnode compression=%v masking=%v", c.ws.compress, c.ws.maskwrite) + + var preBuf []byte + // We have to slurp whatever is in the bufio reader and pass that to the readloop. + if n := br.Buffered(); n != 0 { + preBuf, _ = br.Peek(n) + } + return preBuf, 0, nil +} + +const connectProcessTimeout = 2 * time.Second + +// This is invoked for remote LEAF remote connections after processing the INFO +// protocol. +func (s *Server) leafNodeResumeConnectProcess(c *client) { + clusterName := s.ClusterName() + + c.mu.Lock() + if c.isClosed() { + c.mu.Unlock() + return + } + if err := c.sendLeafConnect(clusterName, c.headers); err != nil { + c.mu.Unlock() + c.closeConnection(WriteError) + return + } + + // Spin up the write loop. + s.startGoRoutine(func() { c.writeLoop() }) + + // timeout leafNodeFinishConnectProcess + c.ping.tmr = time.AfterFunc(connectProcessTimeout, func() { + c.mu.Lock() + // check if leafNodeFinishConnectProcess was called and prevent later leafNodeFinishConnectProcess + if !c.flags.setIfNotSet(connectProcessFinished) { + c.mu.Unlock() + return + } + clearTimer(&c.ping.tmr) + closed := c.isClosed() + c.mu.Unlock() + if !closed { + c.sendErrAndDebug("Stale Leaf Node Connection - Closing") + c.closeConnection(StaleConnection) + } + }) + c.mu.Unlock() + c.Debugf("Remote leafnode connect msg sent") +} + +// This is invoked for remote LEAF connections after processing the INFO +// protocol and leafNodeResumeConnectProcess. +// This will send LS+ the CONNECT protocol and register the leaf node. +func (s *Server) leafNodeFinishConnectProcess(c *client) { + c.mu.Lock() + if !c.flags.setIfNotSet(connectProcessFinished) { + c.mu.Unlock() + return + } + if c.isClosed() { + c.mu.Unlock() + s.removeLeafNodeConnection(c) + return + } + remote := c.leaf.remote + // Check if we will need to send the system connect event. + remote.RLock() + sendSysConnectEvent := remote.Hub + remote.RUnlock() + + // Capture account before releasing lock + acc := c.acc + // cancel connectProcessTimeout + clearTimer(&c.ping.tmr) + c.mu.Unlock() + + // Make sure we register with the account here. + if err := c.registerWithAccount(acc); err != nil { + if err == ErrTooManyAccountConnections { + c.maxAccountConnExceeded() + return + } else if err == ErrLeafNodeLoop { + c.handleLeafNodeLoop(true) + return + } + c.Errorf("Registering leaf with account %s resulted in error: %v", acc.Name, err) + c.closeConnection(ProtocolViolation) + return + } + s.addLeafNodeConnection(c, _EMPTY_, _EMPTY_, false) + s.initLeafNodeSmapAndSendSubs(c) + if sendSysConnectEvent { + s.sendLeafNodeConnect(acc) + } + + // The above functions are not atomically under the client + // lock doing those operations. It is possible - since we + // have started the read/write loops - that the connection + // is closed before or in between. This would leave the + // closed LN connection possible registered with the account + // and/or the server's leafs map. So check if connection + // is closed, and if so, manually cleanup. + c.mu.Lock() + closed := c.isClosed() + if !closed { + c.setFirstPingTimer() + } + c.mu.Unlock() + if closed { + s.removeLeafNodeConnection(c) + if prev := acc.removeClient(c); prev == 1 { + s.decActiveAccounts() + } + } +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/log.go b/vendor/github.com/nats-io/nats-server/v2/server/log.go index 48a56f3..2cd294c 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/log.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/log.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,9 +14,11 @@ package server import ( + "fmt" "io" "os" "sync/atomic" + "time" srvlog "github.com/nats-io/nats-server/v2/logger" ) @@ -25,22 +27,22 @@ import ( type Logger interface { // Log a notice statement - Noticef(format string, v ...interface{}) + Noticef(format string, v ...any) // Log a warning statement - Warnf(format string, v ...interface{}) + Warnf(format string, v ...any) // Log a fatal error - Fatalf(format string, v ...interface{}) + Fatalf(format string, v ...any) // Log an error - Errorf(format string, v ...interface{}) + Errorf(format string, v ...any) // Log a debug statement - Debugf(format string, v ...interface{}) + Debugf(format string, v ...any) // Log a trace statement - Tracef(format string, v ...interface{}) + Tracef(format string, v ...any) } // ConfigureLogger configures and sets the logger for the server. @@ -64,12 +66,22 @@ func (s *Server) ConfigureLogger() { } if opts.LogFile != "" { - log = srvlog.NewFileLogger(opts.LogFile, opts.Logtime, opts.Debug, opts.Trace, true) + log = srvlog.NewFileLogger(opts.LogFile, opts.Logtime, opts.Debug, opts.Trace, true, srvlog.LogUTC(opts.LogtimeUTC)) if opts.LogSizeLimit > 0 { if l, ok := log.(*srvlog.Logger); ok { l.SetSizeLimit(opts.LogSizeLimit) } } + if opts.LogMaxFiles > 0 { + if l, ok := log.(*srvlog.Logger); ok { + al := int(opts.LogMaxFiles) + if int64(al) != opts.LogMaxFiles { + // set to default (no max) on overflow + al = 0 + } + l.SetMaxNumFiles(al) + } + } } else if opts.RemoteSyslog != "" { log = srvlog.NewRemoteSysLogger(opts.RemoteSyslog, opts.Debug, opts.Trace) } else if syslog { @@ -82,12 +94,19 @@ func (s *Server) ConfigureLogger() { if err != nil || (stat.Mode()&os.ModeCharDevice) == 0 { colors = false } - log = srvlog.NewStdLogger(opts.Logtime, opts.Debug, opts.Trace, colors, true) + log = srvlog.NewStdLogger(opts.Logtime, opts.Debug, opts.Trace, colors, true, srvlog.LogUTC(opts.LogtimeUTC)) } s.SetLoggerV2(log, opts.Debug, opts.Trace, opts.TraceVerbose) } +// Returns our current logger. +func (s *Server) Logger() Logger { + s.logging.Lock() + defer s.logging.Unlock() + return s.logging.logger +} + // SetLogger sets the logger of the server func (s *Server) SetLogger(logger Logger, debugFlag, traceFlag bool) { s.SetLoggerV2(logger, debugFlag, traceFlag, false) @@ -145,8 +164,11 @@ func (s *Server) ReOpenLogFile() { if opts.LogFile == "" { s.Noticef("File log re-open ignored, not a file logger") } else { - fileLog := srvlog.NewFileLogger(opts.LogFile, - opts.Logtime, opts.Debug, opts.Trace, true) + fileLog := srvlog.NewFileLogger( + opts.LogFile, opts.Logtime, + opts.Debug, opts.Trace, true, + srvlog.LogUTC(opts.LogtimeUTC), + ) s.SetLogger(fileLog, opts.Debug, opts.Trace) if opts.LogSizeLimit > 0 { fileLog.SetSizeLimit(opts.LogSizeLimit) @@ -156,77 +178,105 @@ func (s *Server) ReOpenLogFile() { } // Noticef logs a notice statement -func (s *Server) Noticef(format string, v ...interface{}) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { +func (s *Server) Noticef(format string, v ...any) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Noticef(format, v...) }, format, v...) } // Errorf logs an error -func (s *Server) Errorf(format string, v ...interface{}) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { +func (s *Server) Errorf(format string, v ...any) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Errorf(format, v...) }, format, v...) } // Error logs an error with a scope -func (s *Server) Errors(scope interface{}, e error) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { +func (s *Server) Errors(scope any, e error) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Errorf(format, v...) }, "%s - %s", scope, UnpackIfErrorCtx(e)) } // Error logs an error with a context func (s *Server) Errorc(ctx string, e error) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Errorf(format, v...) }, "%s: %s", ctx, UnpackIfErrorCtx(e)) } // Error logs an error with a scope and context -func (s *Server) Errorsc(scope interface{}, ctx string, e error) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { +func (s *Server) Errorsc(scope any, ctx string, e error) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Errorf(format, v...) }, "%s - %s: %s", scope, ctx, UnpackIfErrorCtx(e)) } // Warnf logs a warning error -func (s *Server) Warnf(format string, v ...interface{}) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { +func (s *Server) Warnf(format string, v ...any) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Warnf(format, v...) }, format, v...) } +func (s *Server) rateLimitFormatWarnf(format string, v ...any) { + if _, loaded := s.rateLimitLogging.LoadOrStore(format, time.Now()); loaded { + return + } + statement := fmt.Sprintf(format, v...) + s.Warnf("%s", statement) +} + +func (s *Server) RateLimitWarnf(format string, v ...any) { + statement := fmt.Sprintf(format, v...) + if _, loaded := s.rateLimitLogging.LoadOrStore(statement, time.Now()); loaded { + return + } + s.Warnf("%s", statement) +} + +func (s *Server) RateLimitDebugf(format string, v ...any) { + statement := fmt.Sprintf(format, v...) + if _, loaded := s.rateLimitLogging.LoadOrStore(statement, time.Now()); loaded { + return + } + s.Debugf("%s", statement) +} + // Fatalf logs a fatal error -func (s *Server) Fatalf(format string, v ...interface{}) { - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { +func (s *Server) Fatalf(format string, v ...any) { + if s.isShuttingDown() { + s.Errorf(format, v) + return + } + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Fatalf(format, v...) }, format, v...) } // Debugf logs a debug statement -func (s *Server) Debugf(format string, v ...interface{}) { +func (s *Server) Debugf(format string, v ...any) { if atomic.LoadInt32(&s.logging.debug) == 0 { return } - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Debugf(format, v...) }, format, v...) } // Tracef logs a trace statement -func (s *Server) Tracef(format string, v ...interface{}) { +func (s *Server) Tracef(format string, v ...any) { if atomic.LoadInt32(&s.logging.trace) == 0 { return } - s.executeLogCall(func(logger Logger, format string, v ...interface{}) { + s.executeLogCall(func(logger Logger, format string, v ...any) { logger.Tracef(format, v...) }, format, v...) } -func (s *Server) executeLogCall(f func(logger Logger, format string, v ...interface{}), format string, args ...interface{}) { +func (s *Server) executeLogCall(f func(logger Logger, format string, v ...any), format string, args ...any) { s.logging.RLock() defer s.logging.RUnlock() if s.logging.logger == nil { diff --git a/vendor/github.com/nats-io/nats-server/v2/server/memstore.go b/vendor/github.com/nats-io/nats-server/v2/server/memstore.go index 9d93229..7bd3be1 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/memstore.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/memstore.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,30 +14,41 @@ package server import ( + crand "crypto/rand" + "encoding/binary" "fmt" - "math/rand" - "sort" + "math" + "slices" "sync" "time" + + "github.com/nats-io/nats-server/v2/server/ats" + + "github.com/nats-io/nats-server/v2/server/avl" + "github.com/nats-io/nats-server/v2/server/gsl" + "github.com/nats-io/nats-server/v2/server/stree" + "github.com/nats-io/nats-server/v2/server/thw" ) // TODO(dlc) - This is a fairly simplistic approach but should do for now. type memStore struct { - mu sync.RWMutex - cfg StreamConfig - state StreamState - msgs map[uint64]*storedMsg - scb StorageUpdateHandler - ageChk *time.Timer - consumers int -} - -type storedMsg struct { - subj string - hdr []byte - msg []byte - seq uint64 - ts int64 // nanoseconds + mu sync.RWMutex + cfg StreamConfig + state StreamState + msgs map[uint64]*StoreMsg + fss *stree.SubjectTree[SimpleState] + dmap avl.SequenceSet + maxp int64 + scb StorageUpdateHandler + rmcb StorageRemoveMsgHandler + sdmcb SubjectDeleteMarkerUpdateHandler + ageChk *time.Timer // Timer to expire messages. + ageChkRun bool // Whether message expiration is currently running. + ageChkTime int64 // When the message expiration is scheduled to run. + consumers int + receivedAny bool + ttls *thw.HashWheel + sdm *SDMMeta } func newMemStore(cfg *StreamConfig) (*memStore, error) { @@ -47,7 +58,26 @@ func newMemStore(cfg *StreamConfig) (*memStore, error) { if cfg.Storage != MemoryStorage { return nil, fmt.Errorf("memStore requires memory storage type in config") } - return &memStore{msgs: make(map[uint64]*storedMsg), cfg: *cfg}, nil + ms := &memStore{ + msgs: make(map[uint64]*StoreMsg), + fss: stree.NewSubjectTree[SimpleState](), + maxp: cfg.MaxMsgsPer, + cfg: *cfg, + } + // Only create a THW if we're going to allow TTLs. + if cfg.AllowMsgTTL { + ms.ttls = thw.NewHashWheel() + } + if cfg.FirstSeq > 0 { + if _, err := ms.purge(cfg.FirstSeq); err != nil { + return nil, err + } + } + + // Register with access time service. + ats.Register() + + return ms, nil } func (ms *memStore) UpdateConfig(cfg *StreamConfig) error { @@ -60,6 +90,12 @@ func (ms *memStore) UpdateConfig(cfg *StreamConfig) error { ms.mu.Lock() ms.cfg = *cfg + // Create or delete the THW if needed. + if cfg.AllowMsgTTL && ms.ttls == nil { + ms.recoverTTLState() + } else if !cfg.AllowMsgTTL && ms.ttls != nil { + ms.ttls = nil + } // Limits checks and enforcement. ms.enforceMsgLimit() ms.enforceBytesLimit() @@ -70,92 +106,268 @@ func (ms *memStore) UpdateConfig(cfg *StreamConfig) error { if ms.ageChk != nil && ms.cfg.MaxAge == 0 { ms.ageChk.Stop() ms.ageChk = nil + ms.ageChkTime = 0 + } + // Make sure to update MaxMsgsPer + if cfg.MaxMsgsPer < -1 { + cfg.MaxMsgsPer = -1 + } + maxp := ms.maxp + ms.maxp = cfg.MaxMsgsPer + // If the value is smaller, or was unset before, we need to enforce that. + if ms.maxp > 0 && (maxp == 0 || ms.maxp < maxp) { + lm := uint64(ms.maxp) + ms.fss.IterFast(func(subj []byte, ss *SimpleState) bool { + if ss.Msgs > lm { + ms.enforcePerSubjectLimit(bytesToString(subj), ss) + } + return true + }) } ms.mu.Unlock() - if cfg.MaxAge != 0 { + if cfg.MaxAge != 0 || cfg.AllowMsgTTL { ms.expireMsgs() } return nil } -// Store stores a message. -func (ms *memStore) StoreMsg(subj string, hdr, msg []byte) (uint64, int64, error) { - ms.mu.Lock() +// Lock should be held. +func (ms *memStore) recoverTTLState() { + ms.ttls = thw.NewHashWheel() + if ms.state.Msgs == 0 { + return + } + + var ( + seq uint64 + smv StoreMsg + sm *StoreMsg + ) + defer ms.resetAgeChk(0) + for sm, seq, _ = ms.loadNextMsgLocked(fwcs, true, 0, &smv); sm != nil; sm, seq, _ = ms.loadNextMsgLocked(fwcs, true, seq+1, &smv) { + if len(sm.hdr) == 0 { + continue + } + if ttl, _ := getMessageTTL(sm.hdr); ttl > 0 { + expires := time.Duration(sm.ts) + (time.Second * time.Duration(ttl)) + ms.ttls.Add(seq, int64(expires)) + } + } +} + +// Stores a raw message with expected sequence number and timestamp. +// Lock should be held. +func (ms *memStore) storeRawMsg(subj string, hdr, msg []byte, seq uint64, ts, ttl int64) error { + if ms.msgs == nil { + return ErrStoreClosed + } + + // Tracking by subject. + var ss *SimpleState + var asl bool + if len(subj) > 0 { + var ok bool + if ss, ok = ms.fss.Find(stringToBytes(subj)); ok { + asl = ms.maxp > 0 && ss.Msgs >= uint64(ms.maxp) + } + } // Check if we are discarding new messages when we reach the limit. if ms.cfg.Discard == DiscardNew { - if ms.cfg.MaxMsgs > 0 && ms.state.Msgs >= uint64(ms.cfg.MaxMsgs) { - ms.mu.Unlock() - return 0, 0, ErrMaxMsgs + if asl && ms.cfg.DiscardNewPer { + return ErrMaxMsgsPerSubject } - if ms.cfg.MaxBytes > 0 && ms.state.Bytes+uint64(len(msg)) >= uint64(ms.cfg.MaxBytes) { - ms.mu.Unlock() - return 0, 0, ErrMaxBytes + // If we are discard new and limits policy and clustered, we do the enforcement + // above and should not disqualify the message here since it could cause replicas to drift. + if ms.cfg.Retention == LimitsPolicy || ms.cfg.Replicas == 1 { + if ms.cfg.MaxMsgs > 0 && ms.state.Msgs >= uint64(ms.cfg.MaxMsgs) { + // If we are tracking max messages per subject and are at the limit we will replace, so this is ok. + if !asl { + return ErrMaxMsgs + } + } + if ms.cfg.MaxBytes > 0 && ms.state.Bytes+memStoreMsgSize(subj, hdr, msg) >= uint64(ms.cfg.MaxBytes) { + if !asl { + return ErrMaxBytes + } + // If we are here we are at a subject maximum, need to determine if dropping last message gives us enough room. + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + ms.recalculateForSubj(subj, ss) + } + sm, ok := ms.msgs[ss.First] + if !ok || memStoreMsgSize(sm.subj, sm.hdr, sm.msg) < memStoreMsgSize(subj, hdr, msg) { + return ErrMaxBytes + } + } } } - // Grab time. - now := time.Now() - ts := now.UnixNano() + if seq != ms.state.LastSeq+1 { + if seq > 0 { + return ErrSequenceMismatch + } + seq = ms.state.LastSeq + 1 + } - seq := ms.state.LastSeq + 1 + // Adjust first if needed. + now := time.Unix(0, ts).UTC() if ms.state.Msgs == 0 { ms.state.FirstSeq = seq - ms.state.FirstTime = now.UTC() + ms.state.FirstTime = now } - // Make copies - https://github.com/go101/go101/wiki + // Make copies // TODO(dlc) - Maybe be smarter here. if len(msg) > 0 { - msg = append(msg[:0:0], msg...) + msg = copyBytes(msg) } if len(hdr) > 0 { - hdr = append(hdr[:0:0], hdr...) + hdr = copyBytes(hdr) } - startBytes := int64(ms.state.Bytes) - ms.msgs[seq] = &storedMsg{subj, hdr, msg, seq, ts} + // FIXME(dlc) - Could pool at this level? + sm := &StoreMsg{subj, nil, nil, make([]byte, 0, len(hdr)+len(msg)), seq, ts} + sm.buf = append(sm.buf, hdr...) + sm.buf = append(sm.buf, msg...) + if len(hdr) > 0 { + sm.hdr = sm.buf[:len(hdr)] + } + sm.msg = sm.buf[len(hdr):] + ms.msgs[seq] = sm ms.state.Msgs++ ms.state.Bytes += memStoreMsgSize(subj, hdr, msg) ms.state.LastSeq = seq - ms.state.LastTime = now.UTC() + ms.state.LastTime = now + + // Track per subject. + if len(subj) > 0 { + if ss != nil { + ss.Msgs++ + ss.Last = seq + ss.lastNeedsUpdate = false + // Check per subject limits. + if ms.maxp > 0 && ss.Msgs > uint64(ms.maxp) { + ms.enforcePerSubjectLimit(subj, ss) + } + } else { + ms.fss.Insert([]byte(subj), SimpleState{Msgs: 1, First: seq, Last: seq}) + } + } // Limits checks and enforcement. ms.enforceMsgLimit() ms.enforceBytesLimit() + // Per-message TTL. + if ms.ttls != nil && ttl > 0 { + expires := time.Duration(ts) + (time.Second * time.Duration(ttl)) + ms.ttls.Add(seq, int64(expires)) + } + // Check if we have and need the age expiration timer running. - if ms.ageChk == nil && ms.cfg.MaxAge != 0 { + switch { + case ms.ttls != nil && ttl > 0: + ms.resetAgeChk(0) + case ms.ageChk == nil && (ms.cfg.MaxAge > 0 || ms.ttls != nil): ms.startAgeChk() } + + return nil +} + +// StoreRawMsg stores a raw message with expected sequence number and timestamp. +func (ms *memStore) StoreRawMsg(subj string, hdr, msg []byte, seq uint64, ts, ttl int64) error { + ms.mu.Lock() + err := ms.storeRawMsg(subj, hdr, msg, seq, ts, ttl) cb := ms.scb - stopBytes := int64(ms.state.Bytes) + // Check if first message timestamp requires expiry + // sooner than initial replica expiry timer set to MaxAge when initializing. + if !ms.receivedAny && ms.cfg.MaxAge != 0 && ts > 0 { + ms.receivedAny = true + // Calculate duration when the next expireMsgs should be called. + ms.resetAgeChk(int64(time.Millisecond) * 50) + } ms.mu.Unlock() - if cb != nil { - cb(1, stopBytes-startBytes, seq, subj) + if err == nil && cb != nil { + cb(1, int64(memStoreMsgSize(subj, hdr, msg)), seq, subj) + } + + return err +} + +// Store stores a message. +func (ms *memStore) StoreMsg(subj string, hdr, msg []byte, ttl int64) (uint64, int64, error) { + ms.mu.Lock() + seq, ts := ms.state.LastSeq+1, time.Now().UnixNano() + err := ms.storeRawMsg(subj, hdr, msg, seq, ts, ttl) + cb := ms.scb + ms.mu.Unlock() + + if err != nil { + seq, ts = 0, 0 + } else if cb != nil { + cb(1, int64(memStoreMsgSize(subj, hdr, msg)), seq, subj) } - return seq, ts, nil + return seq, ts, err } // SkipMsg will use the next sequence number but not store anything. -func (ms *memStore) SkipMsg() uint64 { +func (ms *memStore) SkipMsg(seq uint64) (uint64, error) { // Grab time. - now := time.Now().UTC() + now := time.Unix(0, ats.AccessTime()).UTC() ms.mu.Lock() - seq := ms.state.LastSeq + 1 + defer ms.mu.Unlock() + + // Check sequence matches our last sequence. + if seq != ms.state.LastSeq+1 { + if seq > 0 { + return 0, ErrSequenceMismatch + } + seq = ms.state.LastSeq + 1 + } + ms.state.LastSeq = seq ms.state.LastTime = now if ms.state.Msgs == 0 { - ms.state.FirstSeq = seq - ms.state.FirstTime = now + ms.state.FirstSeq = seq + 1 + ms.state.FirstTime = time.Time{} + } else { + ms.dmap.Insert(seq) } - ms.updateFirstSeq(seq) - ms.mu.Unlock() - return seq + return seq, nil +} + +// Skip multiple msgs. +func (ms *memStore) SkipMsgs(seq uint64, num uint64) error { + // Grab time. + now := time.Unix(0, ats.AccessTime()).UTC() + + ms.mu.Lock() + defer ms.mu.Unlock() + + // Check sequence matches our last sequence. + if seq != ms.state.LastSeq+1 { + if seq > 0 { + return ErrSequenceMismatch + } + seq = ms.state.LastSeq + 1 + } + lseq := seq + num - 1 + + ms.state.LastSeq = lseq + ms.state.LastTime = now + if ms.state.Msgs == 0 { + ms.state.FirstSeq, ms.state.FirstTime = lseq+1, time.Time{} + } else { + for ; seq <= lseq; seq++ { + ms.dmap.Insert(seq) + } + } + return nil } // RegisterStorageUpdates registers a callback for updates to storage changes. @@ -167,9 +379,23 @@ func (ms *memStore) RegisterStorageUpdates(cb StorageUpdateHandler) { ms.mu.Unlock() } +// RegisterStorageRemoveMsg registers a callback to remove messages. +// Replicated streams should propose removals, R1 can remove inline. +func (ms *memStore) RegisterStorageRemoveMsg(cb StorageRemoveMsgHandler) { + ms.mu.Lock() + ms.rmcb = cb + ms.mu.Unlock() +} + +// RegisterSubjectDeleteMarkerUpdates registers a callback for updates to new subject delete markers. +func (ms *memStore) RegisterSubjectDeleteMarkerUpdates(cb SubjectDeleteMarkerUpdateHandler) { + ms.mu.Lock() + ms.sdmcb = cb + ms.mu.Unlock() +} + // GetSeqFromTime looks for the first sequence number that has the message // with >= timestamp. -// FIXME(dlc) - inefficient. func (ms *memStore) GetSeqFromTime(t time.Time) uint64 { ts := t.UnixNano() ms.mu.RLock() @@ -180,163 +406,1423 @@ func (ms *memStore) GetSeqFromTime(t time.Time) uint64 { if ts <= ms.msgs[ms.state.FirstSeq].ts { return ms.state.FirstSeq } - last := ms.msgs[ms.state.LastSeq].ts + // LastSeq is not guaranteed to be present since last does not go backwards. + var lmsg *StoreMsg + for lseq := ms.state.LastSeq; lseq > ms.state.FirstSeq; lseq-- { + if lmsg = ms.msgs[lseq]; lmsg != nil { + break + } + } + if lmsg == nil { + return ms.state.LastSeq + 1 + } + + last := lmsg.ts if ts == last { - return ms.state.LastSeq + return lmsg.seq } if ts > last { return ms.state.LastSeq + 1 } - index := sort.Search(len(ms.msgs), func(i int) bool { - return ms.msgs[uint64(i)+ms.state.FirstSeq].ts >= ts - }) - return uint64(index) + ms.state.FirstSeq + + var ( + cts int64 + cseq uint64 + off uint64 + ) + + // Using a binary search, but need to be aware of interior deletes. + fseq := ms.state.FirstSeq + lseq := ms.state.LastSeq + seq := lseq + 1 +loop: + for fseq <= lseq { + mid := fseq + (lseq-fseq)/2 + off = 0 + // Potentially skip over gaps. We keep the original middle but keep track of a + // potential delete range with an offset. + for { + msg := ms.msgs[mid+off] + if msg == nil { + off++ + if mid+off <= lseq { + continue + } else { + // Continue search to the left. Purposely ignore the skipped deletes here. + lseq = mid - 1 + continue loop + } + } + cts = msg.ts + cseq = msg.seq + break + } + if cts >= ts { + seq = cseq + if mid == fseq { + break + } + // Continue search to the left. + lseq = mid - 1 + } else { + // Continue search to the right (potentially skipping over interior deletes). + fseq = mid + off + 1 + } + } + return seq } -// Will check the msg limit and drop firstSeq msg if needed. -// Lock should be held. -func (ms *memStore) enforceMsgLimit() { - if ms.cfg.MaxMsgs <= 0 || ms.state.Msgs <= uint64(ms.cfg.MaxMsgs) { - return +// FilteredState will return the SimpleState associated with the filtered subject and a proposed starting sequence. +func (ms *memStore) FilteredState(sseq uint64, subj string) SimpleState { + // This needs to be a write lock, as filteredStateLocked can + // mutate the per-subject state. + ms.mu.Lock() + defer ms.mu.Unlock() + + return ms.filteredStateLocked(sseq, subj, false) +} + +func (ms *memStore) filteredStateLocked(sseq uint64, filter string, lastPerSubject bool) SimpleState { + if sseq < ms.state.FirstSeq { + sseq = ms.state.FirstSeq } - for nmsgs := ms.state.Msgs; nmsgs > uint64(ms.cfg.MaxMsgs); nmsgs = ms.state.Msgs { - ms.deleteFirstMsgOrPanic() + + // If past the end no results. + if sseq > ms.state.LastSeq { + return SimpleState{} } -} -// Will check the bytes limit and drop msgs if needed. -// Lock should be held. -func (ms *memStore) enforceBytesLimit() { - if ms.cfg.MaxBytes <= 0 || ms.state.Bytes <= uint64(ms.cfg.MaxBytes) { - return + if filter == _EMPTY_ { + filter = fwcs } - for bs := ms.state.Bytes; bs > uint64(ms.cfg.MaxBytes); bs = ms.state.Bytes { - ms.deleteFirstMsgOrPanic() + isAll := filter == fwcs + + // First check if we can optimize this part. + // This means we want all and the starting sequence was before this block. + if isAll && sseq <= ms.state.FirstSeq { + total := ms.state.Msgs + if lastPerSubject { + total = uint64(ms.fss.Size()) + } + return SimpleState{ + Msgs: total, + First: ms.state.FirstSeq, + Last: ms.state.LastSeq, + } } -} -// Will start the age check timer. -// Lock should be held. -func (ms *memStore) startAgeChk() { - if ms.ageChk == nil && ms.cfg.MaxAge != 0 { - ms.ageChk = time.AfterFunc(ms.cfg.MaxAge, ms.expireMsgs) + _tsa, _fsa := [32]string{}, [32]string{} + tsa, fsa := _tsa[:0], _fsa[:0] + wc := subjectHasWildcard(filter) + if wc { + fsa = tokenizeSubjectIntoSlice(fsa[:0], filter) } -} + // 1. See if we match any subs from fss. + // 2. If we match and the sseq is past ss.Last then we can use meta only. + // 3. If we match we need to do a partial, break and clear any totals and do a full scan like num pending. -// Will expire msgs that are too old. -func (ms *memStore) expireMsgs() { - ms.mu.Lock() - defer ms.mu.Unlock() + isMatch := func(subj string) bool { + if isAll { + return true + } + if !wc { + return subj == filter + } + tsa = tokenizeSubjectIntoSlice(tsa[:0], subj) + return isSubsetMatchTokenized(tsa, fsa) + } + + var ss SimpleState + update := func(fss *SimpleState) { + msgs, first, last := fss.Msgs, fss.First, fss.Last + if lastPerSubject { + msgs, first = 1, last + } + ss.Msgs += msgs + if ss.First == 0 || first < ss.First { + ss.First = first + } + if last > ss.Last { + ss.Last = last + } + } - now := time.Now().UnixNano() - minAge := now - int64(ms.cfg.MaxAge) - for { - if sm, ok := ms.msgs[ms.state.FirstSeq]; ok && sm.ts <= minAge { - ms.deleteFirstMsgOrPanic() + var havePartial bool + var totalSkipped uint64 + // We will track start and end sequences as we go. + ms.fss.Match(stringToBytes(filter), func(subj []byte, fss *SimpleState) { + if fss.firstNeedsUpdate || fss.lastNeedsUpdate { + ms.recalculateForSubj(bytesToString(subj), fss) + } + if sseq <= fss.First { + update(fss) + } else if sseq <= fss.Last { + // We matched but it is a partial. + havePartial = true + // Don't break here, we will update to keep tracking last. + update(fss) } else { - if !ok { - if ms.ageChk != nil { - ms.ageChk.Stop() - ms.ageChk = nil + totalSkipped += fss.Msgs + } + }) + + // If we did not encounter any partials we can return here. + if !havePartial { + return ss + } + + // If we are here we need to scan the msgs. + // Capture first and last sequences for scan and then clear what we had. + first, last := ss.First, ss.Last + // To track if we decide to exclude we need to calculate first. + var needScanFirst bool + if first < sseq { + first = sseq + needScanFirst = true + } + + // Now we want to check if it is better to scan inclusive and recalculate that way + // or leave and scan exclusive and adjust our totals. + // ss.Last is always correct here. + toScan, toExclude := last-first, first-ms.state.FirstSeq+ms.state.LastSeq-ss.Last + var seen map[string]bool + if lastPerSubject { + seen = make(map[string]bool) + } + if toScan < toExclude { + ss.Msgs, ss.First = 0, 0 + + update := func(sm *StoreMsg) { + ss.Msgs++ + if ss.First == 0 { + ss.First = sm.seq + } + if seen != nil { + seen[sm.subj] = true + } + } + // Check if easier to just scan msgs vs the sequence range. + // This can happen with lots of interior deletes. + if last-first > uint64(len(ms.msgs)) { + for _, sm := range ms.msgs { + if sm.seq >= first && sm.seq <= last && !seen[sm.subj] && isMatch(sm.subj) { + update(sm) + } + } + } else { + for seq := first; seq <= last; seq++ { + if sm, ok := ms.msgs[seq]; ok && !seen[sm.subj] && isMatch(sm.subj) { + update(sm) + } + } + } + } else { + // We will adjust from the totals above by scanning what we need to exclude. + ss.First = first + ss.Msgs += totalSkipped + var adjust uint64 + var tss *SimpleState + + update := func(sm *StoreMsg) { + if lastPerSubject { + tss, _ = ms.fss.Find(stringToBytes(sm.subj)) + } + // If we are last per subject, make sure to only adjust if all messages are before our first. + if tss == nil || tss.Last < first { + adjust++ + } + if seen != nil { + seen[sm.subj] = true + } + } + // Check if easier to just scan msgs vs the sequence range. + if first-ms.state.FirstSeq > uint64(len(ms.msgs)) { + for _, sm := range ms.msgs { + if sm.seq < first && !seen[sm.subj] && isMatch(sm.subj) { + update(sm) + } + } + } else { + for seq := ms.state.FirstSeq; seq < first; seq++ { + if sm, ok := ms.msgs[seq]; ok && !seen[sm.subj] && isMatch(sm.subj) { + update(sm) + } + } + } + // Now do range at end. + for seq := last + 1; seq < ms.state.LastSeq; seq++ { + if sm, ok := ms.msgs[seq]; ok && !seen[sm.subj] && isMatch(sm.subj) { + adjust++ + if seen != nil { + seen[sm.subj] = true + } + } + } + ss.Msgs -= adjust + if needScanFirst { + // Check if easier to just scan msgs vs the sequence range. + // Since we will need to scan all of the msgs vs below where we break on the first match, + // we will only do so if a few orders of magnitude lower. + if last-first > 100*uint64(len(ms.msgs)) { + low := ms.state.LastSeq + for _, sm := range ms.msgs { + if sm.seq >= first && sm.seq < last && isMatch(sm.subj) { + if sm.seq < low { + low = sm.seq + } + } + } + if low < ms.state.LastSeq { + ss.First = low } } else { - fireIn := time.Duration(sm.ts-now) + ms.cfg.MaxAge - if ms.ageChk != nil { - ms.ageChk.Reset(fireIn) - } else { - ms.ageChk = time.AfterFunc(fireIn, ms.expireMsgs) + for seq := first; seq < last; seq++ { + if sm, ok := ms.msgs[seq]; ok && isMatch(sm.subj) { + ss.First = seq + break + } } } - return } } + + return ss } -// Purge will remove all messages from this store. -// Will return the number of purged messages. -func (ms *memStore) Purge() (uint64, error) { +// SubjectsState returns a map of SimpleState for all matching subjects. +func (ms *memStore) SubjectsState(subject string) map[string]SimpleState { + // This needs to be a write lock, as we can mutate the per-subject state. ms.mu.Lock() - purged := uint64(len(ms.msgs)) - cb := ms.scb - bytes := int64(ms.state.Bytes) - ms.state.FirstSeq = ms.state.LastSeq + 1 - ms.state.FirstTime = time.Time{} - ms.state.Bytes = 0 - ms.state.Msgs = 0 - ms.msgs = make(map[uint64]*storedMsg) - ms.mu.Unlock() + defer ms.mu.Unlock() - if cb != nil { - cb(-int64(purged), -bytes, 0, _EMPTY_) + if ms.fss.Size() == 0 { + return nil } - return purged, nil -} - -// Compact will remove all messages from this store up to -// but not including the seq parameter. -// Will return the number of purged messages. -func (ms *memStore) Compact(seq uint64) (uint64, error) { - if seq == 0 { - return ms.Purge() - } - ms.mu.Lock() - sm, ok := ms.msgs[seq] - if !ok { - ms.mu.Unlock() - return 0, ErrStoreMsgNotFound + if subject == _EMPTY_ { + subject = fwcs } - ms.state.FirstSeq = seq - ms.state.FirstTime = time.Unix(0, sm.ts).UTC() - var purged, bytes uint64 - for seq := seq - 1; seq > 0; seq-- { - sm := ms.msgs[seq] - if sm == nil { - continue + fss := make(map[string]SimpleState) + ms.fss.Match(stringToBytes(subject), func(subj []byte, ss *SimpleState) { + subjs := string(subj) + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + ms.recalculateForSubj(subjs, ss) } - bytes += memStoreMsgSize(sm.subj, sm.hdr, sm.msg) - purged++ - delete(ms.msgs, seq) - } - ms.state.Msgs -= purged - ms.state.Bytes -= bytes + oss := fss[subjs] + if oss.First == 0 { // New + fss[subjs] = *ss + } else { + // Merge here. + oss.Last, oss.Msgs = ss.Last, oss.Msgs+ss.Msgs + fss[subjs] = oss + } + }) + return fss +} - cb := ms.scb - ms.mu.Unlock() +// AllLastSeqs will return a sorted list of last sequences for all subjects. +func (ms *memStore) AllLastSeqs() ([]uint64, error) { + ms.mu.RLock() + defer ms.mu.RUnlock() + return ms.allLastSeqsLocked() +} - if cb != nil { - cb(-int64(purged), -int64(bytes), 0, _EMPTY_) +// allLastSeqsLocked will return a sorted list of last sequences for all +// subjects, but won't take the lock to do it, to avoid the issue of compounding +// read locks causing a deadlock with a write lock. +func (ms *memStore) allLastSeqsLocked() ([]uint64, error) { + if len(ms.msgs) == 0 { + return nil, nil } - return purged, nil + seqs := make([]uint64, 0, ms.fss.Size()) + ms.fss.IterFast(func(subj []byte, ss *SimpleState) bool { + seqs = append(seqs, ss.Last) + return true + }) + + slices.Sort(seqs) + return seqs, nil } -func (ms *memStore) deleteFirstMsgOrPanic() { - if !ms.deleteFirstMsg() { - panic("jetstream memstore has inconsistent state, can't find first seq msg") +// Helper to determine if the filter(s) represent all the subjects. +// Most clients send in subjects even if they match the stream's ingest subjects. +// Lock should be held. +func (ms *memStore) filterIsAll(filters []string) bool { + if len(filters) != len(ms.cfg.Subjects) { + return false + } + // Sort so we can compare. + slices.Sort(filters) + for i, subj := range filters { + if !subjectIsSubsetMatch(ms.cfg.Subjects[i], subj) { + return false + } + } + return true +} + +// MultiLastSeqs will return a sorted list of sequences that match all subjects presented in filters. +// We will not exceed the maxSeq, which if 0 becomes the store's last sequence. +func (ms *memStore) MultiLastSeqs(filters []string, maxSeq uint64, maxAllowed int) ([]uint64, error) { + ms.mu.RLock() + defer ms.mu.RUnlock() + + if len(ms.msgs) == 0 { + return nil, nil + } + + // See if we can short circuit if we think they are asking for all last sequences and have no maxSeq or maxAllowed set. + if maxSeq == 0 && maxAllowed <= 0 && ms.filterIsAll(filters) { + return ms.allLastSeqsLocked() + } + + // Implied last sequence. + if maxSeq == 0 { + maxSeq = ms.state.LastSeq + } + + seqs := make([]uint64, 0, 64) + seen := make(map[uint64]struct{}) + + addIfNotDupe := func(seq uint64) { + if _, ok := seen[seq]; !ok { + seqs = append(seqs, seq) + seen[seq] = struct{}{} + } + } + + for _, filter := range filters { + ms.fss.Match(stringToBytes(filter), func(subj []byte, ss *SimpleState) { + if ss.Last <= maxSeq { + addIfNotDupe(ss.Last) + } else if ss.Msgs > 1 { + // The last is greater than maxSeq. + s := bytesToString(subj) + for seq := maxSeq; seq > 0; seq-- { + if sm, ok := ms.msgs[seq]; ok && sm.subj == s { + addIfNotDupe(seq) + break + } + } + } + }) + // If maxAllowed was sepcified check that we will not exceed that. + if maxAllowed > 0 && len(seqs) > maxAllowed { + return nil, ErrTooManyResults + } + } + slices.Sort(seqs) + return seqs, nil +} + +// SubjectsTotals return message totals per subject. +func (ms *memStore) SubjectsTotals(filterSubject string) map[string]uint64 { + ms.mu.RLock() + defer ms.mu.RUnlock() + return ms.subjectsTotalsLocked(filterSubject) +} + +// Lock should be held. +func (ms *memStore) subjectsTotalsLocked(filterSubject string) map[string]uint64 { + if ms.fss.Size() == 0 { + return nil + } + + _tsa, _fsa := [32]string{}, [32]string{} + tsa, fsa := _tsa[:0], _fsa[:0] + fsa = tokenizeSubjectIntoSlice(fsa[:0], filterSubject) + isAll := filterSubject == _EMPTY_ || filterSubject == fwcs + + fst := make(map[string]uint64) + ms.fss.Match(stringToBytes(filterSubject), func(subj []byte, ss *SimpleState) { + subjs := string(subj) + if isAll { + fst[subjs] = ss.Msgs + } else { + if tsa = tokenizeSubjectIntoSlice(tsa[:0], subjs); isSubsetMatchTokenized(tsa, fsa) { + fst[subjs] = ss.Msgs + } + } + }) + return fst +} + +// NumPending will return the number of pending messages matching the filter subject starting at sequence. +func (ms *memStore) NumPending(sseq uint64, filter string, lastPerSubject bool) (total, validThrough uint64) { + // This needs to be a write lock, as filteredStateLocked can mutate the per-subject state. + ms.mu.Lock() + defer ms.mu.Unlock() + + ss := ms.filteredStateLocked(sseq, filter, lastPerSubject) + return ss.Msgs, ms.state.LastSeq +} + +// NumPending will return the number of pending messages matching any subject in the sublist starting at sequence. +func (ms *memStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPerSubject bool) (total, validThrough uint64) { + if sl == nil { + return ms.NumPending(sseq, fwcs, lastPerSubject) + } + + // This needs to be a write lock, as we can mutate the per-subject state. + ms.mu.Lock() + defer ms.mu.Unlock() + + var ss SimpleState + if sseq < ms.state.FirstSeq { + sseq = ms.state.FirstSeq + } + // If past the end no results. + if sseq > ms.state.LastSeq { + return 0, ms.state.LastSeq + } + + update := func(fss *SimpleState) { + msgs, first, last := fss.Msgs, fss.First, fss.Last + if lastPerSubject { + msgs, first = 1, last + } + ss.Msgs += msgs + if ss.First == 0 || first < ss.First { + ss.First = first + } + if last > ss.Last { + ss.Last = last + } + } + + var havePartial bool + var totalSkipped uint64 + // We will track start and end sequences as we go. + stree.IntersectGSL[SimpleState](ms.fss, sl, func(subj []byte, fss *SimpleState) { + if fss.firstNeedsUpdate || fss.lastNeedsUpdate { + ms.recalculateForSubj(bytesToString(subj), fss) + } + if sseq <= fss.First { + update(fss) + } else if sseq <= fss.Last { + // We matched but it is a partial. + havePartial = true + // Don't break here, we will update to keep tracking last. + update(fss) + } else { + totalSkipped += fss.Msgs + } + }) + + // If we did not encounter any partials we can return here. + if !havePartial { + return ss.Msgs, ms.state.LastSeq + } + + // If we are here we need to scan the msgs. + // Capture first and last sequences for scan and then clear what we had. + first, last := ss.First, ss.Last + // To track if we decide to exclude we need to calculate first. + if first < sseq { + first = sseq + } + + // Now we want to check if it is better to scan inclusive and recalculate that way + // or leave and scan exclusive and adjust our totals. + // ss.Last is always correct here. + toScan, toExclude := last-first, first-ms.state.FirstSeq+ms.state.LastSeq-ss.Last + var seen map[string]bool + if lastPerSubject { + seen = make(map[string]bool) + } + if toScan < toExclude { + ss.Msgs, ss.First = 0, 0 + + update := func(sm *StoreMsg) { + ss.Msgs++ + if ss.First == 0 { + ss.First = sm.seq + } + if seen != nil { + seen[sm.subj] = true + } + } + // Check if easier to just scan msgs vs the sequence range. + // This can happen with lots of interior deletes. + if last-first > uint64(len(ms.msgs)) { + for _, sm := range ms.msgs { + if sm.seq >= first && sm.seq <= last && !seen[sm.subj] && sl.HasInterest(sm.subj) { + update(sm) + } + } + } else { + for seq := first; seq <= last; seq++ { + if sm, ok := ms.msgs[seq]; ok && !seen[sm.subj] && sl.HasInterest(sm.subj) { + update(sm) + } + } + } + } else { + // We will adjust from the totals above by scanning what we need to exclude. + ss.First = first + ss.Msgs += totalSkipped + var adjust uint64 + var tss *SimpleState + + update := func(sm *StoreMsg) { + if lastPerSubject { + tss, _ = ms.fss.Find(stringToBytes(sm.subj)) + } + // If we are last per subject, make sure to only adjust if all messages are before our first. + if tss == nil || tss.Last < first { + adjust++ + } + if seen != nil { + seen[sm.subj] = true + } + } + // Check if easier to just scan msgs vs the sequence range. + if first-ms.state.FirstSeq > uint64(len(ms.msgs)) { + for _, sm := range ms.msgs { + if sm.seq < first && !seen[sm.subj] && sl.HasInterest(sm.subj) { + update(sm) + } + } + } else { + for seq := ms.state.FirstSeq; seq < first; seq++ { + if sm, ok := ms.msgs[seq]; ok && !seen[sm.subj] && sl.HasInterest(sm.subj) { + update(sm) + } + } + } + // Now do range at end. + for seq := last + 1; seq < ms.state.LastSeq; seq++ { + if sm, ok := ms.msgs[seq]; ok && !seen[sm.subj] && sl.HasInterest(sm.subj) { + adjust++ + if seen != nil { + seen[sm.subj] = true + } + } + } + ss.Msgs -= adjust + } + + return ss.Msgs, ms.state.LastSeq +} + +// Will check the msg limit for this tracked subject. +// Lock should be held. +func (ms *memStore) enforcePerSubjectLimit(subj string, ss *SimpleState) { + if ms.maxp <= 0 { + return + } + for nmsgs := ss.Msgs; nmsgs > uint64(ms.maxp); nmsgs = ss.Msgs { + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + ms.recalculateForSubj(subj, ss) + } + if !ms.removeMsg(ss.First, false) { + break + } + } +} + +// Will check the msg limit and drop firstSeq msg if needed. +// Lock should be held. +func (ms *memStore) enforceMsgLimit() { + if ms.cfg.Discard != DiscardOld { + return + } + if ms.cfg.MaxMsgs <= 0 || ms.state.Msgs <= uint64(ms.cfg.MaxMsgs) { + return + } + for nmsgs := ms.state.Msgs; nmsgs > uint64(ms.cfg.MaxMsgs); nmsgs = ms.state.Msgs { + ms.deleteFirstMsgOrPanic() + } +} + +// Will check the bytes limit and drop msgs if needed. +// Lock should be held. +func (ms *memStore) enforceBytesLimit() { + if ms.cfg.Discard != DiscardOld { + return + } + if ms.cfg.MaxBytes <= 0 || ms.state.Bytes <= uint64(ms.cfg.MaxBytes) { + return + } + for bs := ms.state.Bytes; bs > uint64(ms.cfg.MaxBytes); bs = ms.state.Bytes { + ms.deleteFirstMsgOrPanic() + } +} + +// Will start the age check timer. +// Lock should be held. +func (ms *memStore) startAgeChk() { + if ms.ageChk != nil { + return + } + if ms.cfg.MaxAge != 0 || ms.ttls != nil { + ms.ageChk = time.AfterFunc(ms.cfg.MaxAge, ms.expireMsgs) + } +} + +// Lock should be held. +func (ms *memStore) resetAgeChk(delta int64) { + // If we're already expiring messages, it will make sure to reset. + // Don't trigger again, as that could result in many expire goroutines. + if ms.ageChkRun { + return + } + + var next int64 = math.MaxInt64 + if ms.ttls != nil { + next = ms.ttls.GetNextExpiration(next) + } + + // If there's no MaxAge and there's nothing waiting to be expired then + // don't bother continuing. The next storeRawMsg() will wake us up if + // needs be. + if ms.cfg.MaxAge <= 0 && next == math.MaxInt64 { + clearTimer(&ms.ageChk) + return + } + + // Check to see if we should be firing sooner than MaxAge for an expiring TTL. + fireIn := ms.cfg.MaxAge + + // If delta for next-to-expire message is unset, but we still have messages to remove. + // Assume messages are removed through proposals, and we need to speed up subsequent age check. + if delta == 0 && ms.state.Msgs > 0 { + if until := 2 * time.Second; until < fireIn { + fireIn = until + } + } + + if next < math.MaxInt64 { + // Looks like there's a next expiration, use it either if there's no + // MaxAge set or if it looks to be sooner than MaxAge is. + if until := time.Until(time.Unix(0, next)); fireIn == 0 || until < fireIn { + fireIn = until + } + } + + // If not then look at the delta provided (usually gap to next age expiry). + if delta > 0 { + if fireIn == 0 || time.Duration(delta) < fireIn { + fireIn = time.Duration(delta) + } + } + + // Make sure we aren't firing too often either way, otherwise we can + // negatively impact stream ingest performance. + if fireIn < 250*time.Millisecond { + fireIn = 250 * time.Millisecond + } + + // If we want to kick the timer to run later than what was assigned before, don't reset it. + // Otherwise, we could get in a situation where the timer is continuously reset, and it never runs. + expires := ats.AccessTime() + fireIn.Nanoseconds() + if ms.ageChkTime > 0 && expires > ms.ageChkTime { + return + } + + ms.ageChkTime = expires + if ms.ageChk != nil { + ms.ageChk.Reset(fireIn) + } else { + ms.ageChk = time.AfterFunc(fireIn, ms.expireMsgs) + } +} + +// Lock should be held. +func (ms *memStore) cancelAgeChk() { + if ms.ageChk != nil { + ms.ageChk.Stop() + ms.ageChk = nil + ms.ageChkTime = 0 + } +} + +// Will expire msgs that are too old. +func (ms *memStore) expireMsgs() { + var smv StoreMsg + var sm *StoreMsg + ms.mu.Lock() + maxAge := int64(ms.cfg.MaxAge) + minAge := time.Now().UnixNano() - maxAge + rmcb := ms.rmcb + sdmcb := ms.sdmcb + sdmTTL := int64(ms.cfg.SubjectDeleteMarkerTTL.Seconds()) + sdmEnabled := sdmTTL > 0 + + // If SDM is enabled, but handlers aren't set up yet. Try again later. + if sdmEnabled && (rmcb == nil || sdmcb == nil) { + ms.resetAgeChk(0) + ms.mu.Unlock() + return + } + ms.ageChkRun = true + ms.mu.Unlock() + + if maxAge > 0 { + var seq uint64 + for sm, seq, _ = ms.LoadNextMsg(fwcs, true, 0, &smv); sm != nil && sm.ts <= minAge; sm, seq, _ = ms.LoadNextMsg(fwcs, true, seq+1, &smv) { + if len(sm.hdr) > 0 { + if ttl, err := getMessageTTL(sm.hdr); err == nil && ttl < 0 { + // The message has a negative TTL, therefore it must "never expire". + minAge = time.Now().UnixNano() - maxAge + continue + } + } + if sdmEnabled { + if last, ok := ms.shouldProcessSdm(seq, sm.subj); ok { + sdm := last && !isSubjectDeleteMarker(sm.hdr) + ms.handleRemovalOrSdm(seq, sm.subj, sdm, sdmTTL) + } + } else { + ms.mu.Lock() + ms.removeMsg(seq, false) + ms.mu.Unlock() + } + // Recalculate in case we are expiring a bunch. + minAge = time.Now().UnixNano() - maxAge + } + } + + ms.mu.Lock() + defer ms.mu.Unlock() + + // TODO: Not great that we're holding the lock here, but the timed hash wheel isn't thread-safe. + nextTTL := int64(math.MaxInt64) + var rmSeqs []thw.HashWheelEntry + if ms.ttls != nil { + ms.ttls.ExpireTasks(func(seq uint64, ts int64) bool { + rmSeqs = append(rmSeqs, thw.HashWheelEntry{Seq: seq, Expires: ts}) + // We might need to remove messages out of band, those can fail, and we can be shutdown halfway + // through so don't remove from THW just yet. + return false + }) + if maxAge > 0 { + // Only check if we're expiring something in the next MaxAge interval, saves us a bit + // of work if MaxAge will beat us to the next expiry anyway. + nextTTL = ms.ttls.GetNextExpiration(time.Now().Add(time.Duration(maxAge)).UnixNano()) + } else { + nextTTL = ms.ttls.GetNextExpiration(math.MaxInt64) + } + } + + // Remove messages collected by THW. + if !sdmEnabled { + for _, rm := range rmSeqs { + ms.removeMsg(rm.Seq, false) + } + } else { + // THW is unordered, so must sort by sequence and must not be holding the lock. + ms.mu.Unlock() + slices.SortFunc(rmSeqs, func(a, b thw.HashWheelEntry) int { + if a.Seq == b.Seq { + return 0 + } else if a.Seq < b.Seq { + return -1 + } else { + return 1 + } + }) + for _, rm := range rmSeqs { + // Need to grab subject for the specified sequence if for SDM, and check + // if the message hasn't been removed in the meantime. + // We need to grab the message and check if we should process SDM while holding the lock, + // otherwise we can race if a deletion of this message is in progress. + ms.mu.Lock() + sm, _ = ms.loadMsgLocked(rm.Seq, &smv, false) + if sm == nil { + ms.ttls.Remove(rm.Seq, rm.Expires) + ms.mu.Unlock() + continue + } + last, ok := ms.shouldProcessSdmLocked(rm.Seq, sm.subj) + ms.mu.Unlock() + if ok { + sdm := last && !isSubjectDeleteMarker(sm.hdr) + ms.handleRemovalOrSdm(rm.Seq, sm.subj, sdm, sdmTTL) + } + } + ms.mu.Lock() + } + + // Only cancel if no message left, not on potential lookup error that would result in sm == nil. + ms.ageChkRun, ms.ageChkTime = false, 0 + if ms.state.Msgs == 0 && nextTTL == math.MaxInt64 { + ms.cancelAgeChk() + } else { + if sm == nil { + ms.resetAgeChk(0) + } else { + ms.resetAgeChk(sm.ts - minAge) + } + } +} + +func (ms *memStore) shouldProcessSdm(seq uint64, subj string) (bool, bool) { + ms.mu.Lock() + defer ms.mu.Unlock() + return ms.shouldProcessSdmLocked(seq, subj) +} + +// Lock should be held. +func (ms *memStore) shouldProcessSdmLocked(seq uint64, subj string) (bool, bool) { + if ms.sdm == nil { + ms.sdm = newSDMMeta() + } + + if p, ok := ms.sdm.pending[seq]; ok { + // Don't allow more proposals for the same sequence if we already did recently. + if time.Since(time.Unix(0, p.ts)) < 2*time.Second { + return p.last, false + } + // If we're about to use the cached value, and we knew it was last before, + // quickly check that we don't have more remaining messages for the subject now. + // Which means we are not the last anymore and must reset to not remove later data. + if p.last { + msgs := ms.subjectsTotalsLocked(subj)[subj] + numPending := ms.sdm.totals[subj] + if remaining := msgs - numPending; remaining > 0 { + p.last = false + } + } + ms.sdm.pending[seq] = SDMBySeq{p.last, time.Now().UnixNano()} + return p.last, true + } + + msgs := ms.subjectsTotalsLocked(subj)[subj] + if msgs == 0 { + return false, true + } + numPending := ms.sdm.totals[subj] + remaining := msgs - numPending + return ms.sdm.trackPending(seq, subj, remaining == 1), true +} + +func (ms *memStore) handleRemovalOrSdm(seq uint64, subj string, sdm bool, sdmTTL int64) { + if sdm { + var _hdr [128]byte + hdr := fmt.Appendf( + _hdr[:0], + "NATS/1.0\r\n%s: %s\r\n%s: %s\r\n%s: %s\r\n\r\n", + JSMarkerReason, JSMarkerReasonMaxAge, + JSMessageTTL, time.Duration(sdmTTL)*time.Second, + JSMsgRollup, JSMsgRollupSubject, + ) + msg := &inMsg{ + subj: subj, + hdr: hdr, + } + ms.sdmcb(msg) + } else { + ms.rmcb(seq) + } +} + +// PurgeEx will remove messages based on subject filters, sequence and number of messages to keep. +// Will return the number of purged messages. +func (ms *memStore) PurgeEx(subject string, sequence, keep uint64) (purged uint64, err error) { + if subject == _EMPTY_ || subject == fwcs { + if keep == 0 && sequence == 0 { + return ms.purge(0) + } + if sequence > 1 { + return ms.compact(sequence) + } else if keep > 0 { + ms.mu.RLock() + msgs, lseq := ms.state.Msgs, ms.state.LastSeq + ms.mu.RUnlock() + if keep >= msgs { + return 0, nil + } + return ms.compact(lseq - keep + 1) + } + return 0, nil + + } + eq := compareFn(subject) + if ss := ms.FilteredState(1, subject); ss.Msgs > 0 { + if keep > 0 { + if keep >= ss.Msgs { + return 0, nil + } + ss.Msgs -= keep + } + last := ss.Last + if sequence > 1 { + last = sequence - 1 + } + ms.mu.Lock() + for seq := ss.First; seq <= last; seq++ { + if sm, ok := ms.msgs[seq]; ok && eq(sm.subj, subject) { + if ok := ms.removeMsg(sm.seq, false); ok { + purged++ + if purged >= ss.Msgs { + break + } + } + } + } + ms.mu.Unlock() + } + return purged, nil +} + +// Purge will remove all messages from this store. +// Will return the number of purged messages. +func (ms *memStore) Purge() (uint64, error) { + return ms.purge(0) +} + +func (ms *memStore) purge(fseq uint64) (uint64, error) { + ms.mu.Lock() + purged := uint64(len(ms.msgs)) + cb := ms.scb + bytes := int64(ms.state.Bytes) + if fseq == 0 { + fseq = ms.state.LastSeq + 1 + } else if fseq < ms.state.LastSeq { + ms.mu.Unlock() + return 0, fmt.Errorf("partial purges not supported on memory store") + } + ms.state.FirstSeq = fseq + ms.state.LastSeq = fseq - 1 + ms.state.FirstTime = time.Time{} + ms.state.Bytes = 0 + ms.state.Msgs = 0 + if ms.msgs != nil { + ms.msgs = make(map[uint64]*StoreMsg) + } + ms.fss = stree.NewSubjectTree[SimpleState]() + ms.dmap.Empty() + ms.sdm.empty() + ms.mu.Unlock() + + if cb != nil { + cb(-int64(purged), -bytes, 0, _EMPTY_) + } + + return purged, nil +} + +// Compact will remove all messages from this store up to +// but not including the seq parameter. +// Will return the number of purged messages. +func (ms *memStore) Compact(seq uint64) (uint64, error) { + return ms.compact(seq) +} + +func (ms *memStore) compact(seq uint64) (uint64, error) { + if seq == 0 { + return ms.Purge() + } + + var purged, bytes uint64 + + ms.mu.Lock() + // Short-circuit if the store was already compacted past this point. + if ms.state.FirstSeq > seq { + ms.mu.Unlock() + return purged, nil + } + + cb := ms.scb + if seq <= ms.state.LastSeq { + fseq := ms.state.FirstSeq + // Determine new first sequence. + for ; seq <= ms.state.LastSeq; seq++ { + if sm, ok := ms.msgs[seq]; ok { + ms.state.FirstSeq = seq + ms.state.FirstTime = time.Unix(0, sm.ts).UTC() + break + } + } + for seq := seq - 1; seq >= fseq; seq-- { + if sm := ms.msgs[seq]; sm != nil { + bytes += memStoreMsgSize(sm.subj, sm.hdr, sm.msg) + purged++ + ms.removeSeqPerSubject(sm.subj, seq) + // Must delete message after updating per-subject info, to be consistent with file store. + delete(ms.msgs, seq) + } else if !ms.dmap.IsEmpty() { + ms.dmap.Delete(seq) + } + } + if purged > ms.state.Msgs { + purged = ms.state.Msgs + } + ms.state.Msgs -= purged + if bytes > ms.state.Bytes { + bytes = ms.state.Bytes + } + ms.state.Bytes -= bytes + } else { + // We are compacting past the end of our range. Do purge and set sequences correctly + // such that the next message placed will have seq. + purged = uint64(len(ms.msgs)) + bytes = ms.state.Bytes + ms.state.Bytes = 0 + ms.state.Msgs = 0 + ms.state.FirstSeq = seq + ms.state.FirstTime = time.Time{} + ms.state.LastSeq = seq - 1 + // Reset msgs, fss and dmap. + ms.msgs = make(map[uint64]*StoreMsg) + ms.fss = stree.NewSubjectTree[SimpleState]() + ms.dmap.Empty() + ms.sdm.empty() + } + ms.mu.Unlock() + + if cb != nil { + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) + } + + return purged, nil +} + +// Will completely reset our store. +func (ms *memStore) reset() error { + ms.mu.Lock() + var purged, bytes uint64 + cb := ms.scb + if cb != nil { + for _, sm := range ms.msgs { + purged++ + bytes += memStoreMsgSize(sm.subj, sm.hdr, sm.msg) + } + } + + // Reset + ms.state.FirstSeq = 0 + ms.state.FirstTime = time.Time{} + ms.state.LastSeq = 0 + ms.state.LastTime = time.Now().UTC() + // Update msgs and bytes. + ms.state.Msgs = 0 + ms.state.Bytes = 0 + // Reset msgs, fss and dmap. + ms.msgs = make(map[uint64]*StoreMsg) + ms.fss = stree.NewSubjectTree[SimpleState]() + ms.dmap.Empty() + ms.sdm.empty() + + ms.mu.Unlock() + + if cb != nil { + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) + } + + return nil +} + +// Truncate will truncate a stream store up to seq. Sequence needs to be valid. +func (ms *memStore) Truncate(seq uint64) error { + // Check for request to reset. + if seq == 0 { + return ms.reset() + } + + var purged, bytes uint64 + + ms.mu.Lock() + lsm, ok := ms.msgs[seq] + lastTime := ms.state.LastTime + if ok && lsm != nil { + lastTime = time.Unix(0, lsm.ts).UTC() + } + + for i := ms.state.LastSeq; i > seq; i-- { + if sm := ms.msgs[i]; sm != nil { + purged++ + bytes += memStoreMsgSize(sm.subj, sm.hdr, sm.msg) + ms.removeSeqPerSubject(sm.subj, i) + // Must delete message after updating per-subject info, to be consistent with file store. + delete(ms.msgs, i) + } else if !ms.dmap.IsEmpty() { + ms.dmap.Delete(i) + } + } + // Reset last. + ms.state.LastSeq = seq + ms.state.LastTime = lastTime + // Update msgs and bytes. + if purged > ms.state.Msgs { + purged = ms.state.Msgs + } + ms.state.Msgs -= purged + if bytes > ms.state.Bytes { + bytes = ms.state.Bytes + } + ms.state.Bytes -= bytes + + cb := ms.scb + ms.mu.Unlock() + + if cb != nil { + cb(-int64(purged), -int64(bytes), 0, _EMPTY_) + } + + return nil +} + +func (ms *memStore) deleteFirstMsgOrPanic() { + if !ms.deleteFirstMsg() { + panic("jetstream memstore has inconsistent state, can't find first seq msg") + } +} + +func (ms *memStore) deleteFirstMsg() bool { + return ms.removeMsg(ms.state.FirstSeq, false) +} + +// SubjectForSeq will return what the subject is for this sequence if found. +func (ms *memStore) SubjectForSeq(seq uint64) (string, error) { + ms.mu.RLock() + defer ms.mu.RUnlock() + if seq < ms.state.FirstSeq { + return _EMPTY_, ErrStoreMsgNotFound + } + if sm, ok := ms.msgs[seq]; ok { + return sm.subj, nil + } + return _EMPTY_, ErrStoreMsgNotFound +} + +// LoadMsg will lookup the message by sequence number and return it if found. +func (ms *memStore) LoadMsg(seq uint64, smp *StoreMsg) (*StoreMsg, error) { + return ms.loadMsgLocked(seq, smp, true) +} + +// loadMsgLocked will lookup the message by sequence number and return it if found. +func (ms *memStore) loadMsgLocked(seq uint64, smp *StoreMsg, needMSLock bool) (*StoreMsg, error) { + if needMSLock { + ms.mu.RLock() + } + sm, ok := ms.msgs[seq] + last := ms.state.LastSeq + if needMSLock { + ms.mu.RUnlock() + } + + if !ok || sm == nil { + var err = ErrStoreEOF + if seq <= last { + err = ErrStoreMsgNotFound + } + return nil, err + } + + if smp == nil { + smp = new(StoreMsg) + } + sm.copy(smp) + return smp, nil +} + +// LoadLastMsg will return the last message we have that matches a given subject. +// The subject can be a wildcard. +func (ms *memStore) LoadLastMsg(subject string, smp *StoreMsg) (*StoreMsg, error) { + var sm *StoreMsg + var ok bool + + // This needs to be a write lock, as filteredStateLocked can + // mutate the per-subject state. + ms.mu.Lock() + defer ms.mu.Unlock() + + if subject == _EMPTY_ || subject == fwcs { + sm, ok = ms.msgs[ms.state.LastSeq] + } else if subjectIsLiteral(subject) { + var ss *SimpleState + if ss, ok = ms.fss.Find(stringToBytes(subject)); ok && ss.Msgs > 0 { + sm, ok = ms.msgs[ss.Last] + } + } else if ss := ms.filteredStateLocked(1, subject, true); ss.Msgs > 0 { + sm, ok = ms.msgs[ss.Last] + } + if !ok || sm == nil { + return nil, ErrStoreMsgNotFound + } + + if smp == nil { + smp = new(StoreMsg) + } + sm.copy(smp) + return smp, nil +} + +// LoadNextMsgMulti will find the next message matching any entry in the sublist. +func (ms *memStore) LoadNextMsgMulti(sl *gsl.SimpleSublist, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) { + // TODO(dlc) - for now simple linear walk to get started. + ms.mu.RLock() + defer ms.mu.RUnlock() + + if start < ms.state.FirstSeq { + start = ms.state.FirstSeq + } + + // If past the end no results. + if start > ms.state.LastSeq || ms.state.Msgs == 0 { + return nil, ms.state.LastSeq, ErrStoreEOF + } + + // Initial setup. + fseq, lseq := start, ms.state.LastSeq + + for nseq := fseq; nseq <= lseq; nseq++ { + sm, ok := ms.msgs[nseq] + if !ok { + continue + } + if sl.HasInterest(sm.subj) { + if smp == nil { + smp = new(StoreMsg) + } + sm.copy(smp) + return smp, nseq, nil + } + } + return nil, ms.state.LastSeq, ErrStoreEOF +} + +// LoadNextMsg will find the next message matching the filter subject starting at the start sequence. +// The filter subject can be a wildcard. +func (ms *memStore) LoadNextMsg(filter string, wc bool, start uint64, smp *StoreMsg) (*StoreMsg, uint64, error) { + ms.mu.Lock() + defer ms.mu.Unlock() + return ms.loadNextMsgLocked(filter, wc, start, smp) +} + +// Lock should be held. +func (ms *memStore) loadNextMsgLocked(filter string, wc bool, start uint64, smp *StoreMsg) (*StoreMsg, uint64, error) { + if start < ms.state.FirstSeq { + start = ms.state.FirstSeq + } + + // If past the end no results. + if start > ms.state.LastSeq || ms.state.Msgs == 0 { + return nil, ms.state.LastSeq, ErrStoreEOF + } + + if filter == _EMPTY_ { + filter = fwcs } + isAll := filter == fwcs + + // Skip scan of ms.fss if number of messages in the block are less than + // 1/2 the number of subjects in ms.fss. Or we have a wc and lots of fss entries. + const linearScanMaxFSS = 256 + doLinearScan := isAll || 2*int(ms.state.LastSeq-start) < ms.fss.Size() || (wc && ms.fss.Size() > linearScanMaxFSS) + + // Initial setup. + fseq, lseq := start, ms.state.LastSeq + + if !doLinearScan { + subs := []string{filter} + if wc || isAll { + subs = subs[:0] + ms.fss.Match(stringToBytes(filter), func(subj []byte, val *SimpleState) { + subs = append(subs, string(subj)) + }) + } + fseq, lseq = ms.state.LastSeq, uint64(0) + for _, subj := range subs { + ss, ok := ms.fss.Find(stringToBytes(subj)) + if !ok { + continue + } + if ss.firstNeedsUpdate || ss.lastNeedsUpdate { + ms.recalculateForSubj(subj, ss) + } + if ss.First < fseq { + fseq = ss.First + } + if ss.Last > lseq { + lseq = ss.Last + } + } + if fseq < start { + fseq = start + } + } + + eq := subjectsEqual + if wc { + eq = subjectIsSubsetMatch + } + + for nseq := fseq; nseq <= lseq; nseq++ { + if sm, ok := ms.msgs[nseq]; ok && (isAll || eq(sm.subj, filter)) { + if smp == nil { + smp = new(StoreMsg) + } + sm.copy(smp) + return smp, nseq, nil + } + } + return nil, ms.state.LastSeq, ErrStoreEOF } -func (ms *memStore) deleteFirstMsg() bool { - return ms.removeMsg(ms.state.FirstSeq, false) +// Will load the next non-deleted msg starting at the start sequence and walking backwards. +func (ms *memStore) LoadPrevMsg(start uint64, smp *StoreMsg) (sm *StoreMsg, err error) { + ms.mu.RLock() + defer ms.mu.RUnlock() + + if ms.msgs == nil { + return nil, ErrStoreClosed + } + if ms.state.Msgs == 0 || start < ms.state.FirstSeq { + return nil, ErrStoreEOF + } + if start > ms.state.LastSeq { + start = ms.state.LastSeq + } + + for seq := start; seq >= ms.state.FirstSeq; seq-- { + if sm, ok := ms.msgs[seq]; ok { + if smp == nil { + smp = new(StoreMsg) + } + sm.copy(smp) + return smp, nil + } + } + return nil, ErrStoreEOF } -// LoadMsg will lookup the message by sequence number and return it if found. -func (ms *memStore) LoadMsg(seq uint64) (string, []byte, []byte, int64, error) { +// LoadPrevMsgMulti will find the previous message matching any entry in the sublist. +func (ms *memStore) LoadPrevMsgMulti(sl *gsl.SimpleSublist, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) { + // TODO(dlc) - for now simple linear walk to get started. ms.mu.RLock() - sm, ok := ms.msgs[seq] - last := ms.state.LastSeq - ms.mu.RUnlock() + defer ms.mu.RUnlock() - if !ok || sm == nil { - var err = ErrStoreEOF - if seq <= last { - err = ErrStoreMsgNotFound + if start > ms.state.LastSeq { + start = ms.state.LastSeq + } + + // If past the start no results. + if start < ms.state.FirstSeq || ms.state.Msgs == 0 { + return nil, ms.state.FirstSeq, ErrStoreEOF + } + + // Initial setup. + fseq, lseq := start, ms.state.FirstSeq + + for nseq := fseq; nseq >= lseq; nseq-- { + sm, ok := ms.msgs[nseq] + if !ok { + continue + } + if sl.HasInterest(sm.subj) { + if smp == nil { + smp = new(StoreMsg) + } + sm.copy(smp) + return smp, nseq, nil } - return "", nil, nil, 0, err } - return sm.subj, sm.hdr, sm.msg, sm.ts, nil + return nil, ms.state.LastSeq, ErrStoreEOF } // RemoveMsg will remove the message from this store. @@ -360,15 +1846,17 @@ func (ms *memStore) EraseMsg(seq uint64) (bool, error) { // Lock should be held. func (ms *memStore) updateFirstSeq(seq uint64) { if seq != ms.state.FirstSeq { + // Interior delete. return } - var nsm *storedMsg + var nsm *StoreMsg var ok bool for nseq := ms.state.FirstSeq + 1; nseq <= ms.state.LastSeq; nseq++ { if nsm, ok = ms.msgs[nseq]; ok { break } } + oldFirst := ms.state.FirstSeq if nsm != nil { ms.state.FirstSeq = nsm.seq ms.state.FirstTime = time.Unix(0, nsm.ts).UTC() @@ -377,10 +1865,91 @@ func (ms *memStore) updateFirstSeq(seq uint64) { ms.state.FirstSeq = ms.state.LastSeq + 1 ms.state.FirstTime = time.Time{} } + + if oldFirst == ms.state.FirstSeq-1 { + ms.dmap.Delete(oldFirst) + } else { + for seq := oldFirst; seq < ms.state.FirstSeq; seq++ { + ms.dmap.Delete(seq) + } + } +} + +// Remove a seq from the fss and select new first. +// Lock should be held. +func (ms *memStore) removeSeqPerSubject(subj string, seq uint64) { + ss, ok := ms.fss.Find(stringToBytes(subj)) + if !ok { + return + } + ms.sdm.removeSeqAndSubject(seq, subj) + if ss.Msgs == 1 { + ms.fss.Delete(stringToBytes(subj)) + return + } + ss.Msgs-- + + // Only one left + if ss.Msgs == 1 { + if !ss.lastNeedsUpdate && seq != ss.Last { + ss.First = ss.Last + ss.firstNeedsUpdate = false + return + } + if !ss.firstNeedsUpdate && seq != ss.First { + ss.Last = ss.First + ss.lastNeedsUpdate = false + return + } + } + + // We can lazily calculate the first/last sequence when needed. + ss.firstNeedsUpdate = seq == ss.First || ss.firstNeedsUpdate + ss.lastNeedsUpdate = seq == ss.Last || ss.lastNeedsUpdate +} + +// Will recalculate the first and/or last sequence for this subject. +// Lock should be held. +func (ms *memStore) recalculateForSubj(subj string, ss *SimpleState) { + if ss.firstNeedsUpdate { + tseq := ss.First + 1 + if tseq < ms.state.FirstSeq { + tseq = ms.state.FirstSeq + } + for ; tseq <= ss.Last; tseq++ { + if sm := ms.msgs[tseq]; sm != nil && sm.subj == subj { + ss.First = tseq + ss.firstNeedsUpdate = false + if ss.Msgs == 1 { + ss.Last = tseq + ss.lastNeedsUpdate = false + return + } + break + } + } + } + if ss.lastNeedsUpdate { + tseq := ss.Last - 1 + if tseq > ms.state.LastSeq { + tseq = ms.state.LastSeq + } + for ; tseq >= ss.First; tseq-- { + if sm := ms.msgs[tseq]; sm != nil && sm.subj == subj { + ss.Last = tseq + ss.lastNeedsUpdate = false + if ss.Msgs == 1 { + ss.First = tseq + ss.firstNeedsUpdate = false + } + return + } + } + } } // Removes the message referenced by seq. -// Lock should he held. +// Lock should be held. func (ms *memStore) removeMsg(seq uint64, secure bool) bool { var ss uint64 sm, ok := ms.msgs[seq] @@ -390,106 +1959,566 @@ func (ms *memStore) removeMsg(seq uint64, secure bool) bool { ss = memStoreMsgSize(sm.subj, sm.hdr, sm.msg) - delete(ms.msgs, seq) - ms.state.Msgs-- - ms.state.Bytes -= ss + if ms.state.Msgs > 0 { + ms.state.Msgs-- + if ss > ms.state.Bytes { + ss = ms.state.Bytes + } + ms.state.Bytes -= ss + } + ms.dmap.Insert(seq) ms.updateFirstSeq(seq) + // Remove any per subject tracking. + ms.removeSeqPerSubject(sm.subj, seq) + if ms.ttls != nil { + if ttl, err := getMessageTTL(sm.hdr); err == nil { + expires := time.Duration(sm.ts) + (time.Second * time.Duration(ttl)) + ms.ttls.Remove(seq, int64(expires)) + } + } + if secure { if len(sm.hdr) > 0 { sm.hdr = make([]byte, len(sm.hdr)) - rand.Read(sm.hdr) + crand.Read(sm.hdr) } if len(sm.msg) > 0 { sm.msg = make([]byte, len(sm.msg)) - rand.Read(sm.msg) + crand.Read(sm.msg) } sm.seq, sm.ts = 0, 0 } + // Must delete message after updating per-subject info, to be consistent with file store. + delete(ms.msgs, seq) + if ms.scb != nil { + // We do not want to hold any locks here. ms.mu.Unlock() - delta := int64(ss) - ms.scb(-1, -delta, seq, sm.subj) + if ms.scb != nil { + delta := int64(ss) + ms.scb(-1, -delta, seq, sm.subj) + } ms.mu.Lock() } return ok } +// Type returns the type of the underlying store. +func (ms *memStore) Type() StorageType { + return MemoryStorage +} + +// FastState will fill in state with only the following. +// Msgs, Bytes, First and Last Sequence and Time and NumDeleted. +func (ms *memStore) FastState(state *StreamState) { + ms.mu.RLock() + state.Msgs = ms.state.Msgs + state.Bytes = ms.state.Bytes + state.FirstSeq = ms.state.FirstSeq + state.FirstTime = ms.state.FirstTime + state.LastSeq = ms.state.LastSeq + state.LastTime = ms.state.LastTime + if state.LastSeq > state.FirstSeq { + state.NumDeleted = int((state.LastSeq - state.FirstSeq + 1) - state.Msgs) + if state.NumDeleted < 0 { + state.NumDeleted = 0 + } + } + state.Consumers = ms.consumers + state.NumSubjects = ms.fss.Size() + ms.mu.RUnlock() +} + func (ms *memStore) State() StreamState { ms.mu.RLock() + defer ms.mu.RUnlock() + state := ms.state state.Consumers = ms.consumers - ms.mu.RUnlock() + state.NumSubjects = ms.fss.Size() + state.Deleted = nil + + // Calculate interior delete details. + if numDeleted := int((state.LastSeq - state.FirstSeq + 1) - state.Msgs); numDeleted > 0 { + state.Deleted = make([]uint64, 0, numDeleted) + fseq, lseq := state.FirstSeq, state.LastSeq + ms.dmap.Range(func(seq uint64) bool { + if seq < fseq || seq > lseq { + ms.dmap.Delete(seq) + } else { + state.Deleted = append(state.Deleted, seq) + } + return true + }) + } + if len(state.Deleted) > 0 { + state.NumDeleted = len(state.Deleted) + } + return state } +func (ms *memStore) Utilization() (total, reported uint64, err error) { + ms.mu.RLock() + defer ms.mu.RUnlock() + return ms.state.Bytes, ms.state.Bytes, nil +} + func memStoreMsgSize(subj string, hdr, msg []byte) uint64 { return uint64(len(subj) + len(hdr) + len(msg) + 16) // 8*2 for seq + age } // Delete is same as Stop for memory store. func (ms *memStore) Delete() error { - ms.Purge() return ms.Stop() } func (ms *memStore) Stop() error { ms.mu.Lock() + if ms.msgs == nil { + ms.mu.Unlock() + return nil + } if ms.ageChk != nil { ms.ageChk.Stop() ms.ageChk = nil + ms.ageChkTime = 0 } ms.msgs = nil ms.mu.Unlock() + + // These can't come back, so stop is same as Delete. + ms.Purge() + + // Unregister from the access time service. + ats.Unregister() + return nil } -func (ms *memStore) incConsumers() { +func (ms *memStore) isClosed() bool { + ms.mu.RLock() + defer ms.mu.RUnlock() + return ms.msgs == nil +} + +type consumerMemStore struct { + mu sync.Mutex + ms StreamStore + cfg ConsumerConfig + state ConsumerState + closed bool +} + +func (ms *memStore) ConsumerStore(name string, cfg *ConsumerConfig) (ConsumerStore, error) { + if ms == nil { + return nil, fmt.Errorf("memstore is nil") + } + if ms.isClosed() { + return nil, ErrStoreClosed + } + if cfg == nil || name == _EMPTY_ { + return nil, fmt.Errorf("bad consumer config") + } + o := &consumerMemStore{ms: ms, cfg: *cfg} + ms.AddConsumer(o) + return o, nil +} + +func (ms *memStore) AddConsumer(o ConsumerStore) error { ms.mu.Lock() ms.consumers++ ms.mu.Unlock() + return nil } -func (ms *memStore) decConsumers() { +func (ms *memStore) RemoveConsumer(o ConsumerStore) error { ms.mu.Lock() if ms.consumers > 0 { ms.consumers-- } ms.mu.Unlock() + return nil } -type consumerMemStore struct { - ms *memStore +func (ms *memStore) Snapshot(_ time.Duration, _, _ bool) (*SnapshotResult, error) { + return nil, fmt.Errorf("no impl") } -func (ms *memStore) ConsumerStore(_ string, _ *ConsumerConfig) (ConsumerStore, error) { - ms.incConsumers() - return &consumerMemStore{ms}, nil +// Binary encoded state snapshot, >= v2.10 server. +func (ms *memStore) EncodedStreamState(failed uint64) ([]byte, error) { + ms.mu.RLock() + defer ms.mu.RUnlock() + + // Quick calculate num deleted. + numDeleted := int((ms.state.LastSeq - ms.state.FirstSeq + 1) - ms.state.Msgs) + if numDeleted < 0 { + numDeleted = 0 + } + + // Encoded is Msgs, Bytes, FirstSeq, LastSeq, Failed, NumDeleted and optional DeletedBlocks + var buf [1024]byte + buf[0], buf[1] = streamStateMagic, streamStateVersion + n := hdrLen + n += binary.PutUvarint(buf[n:], ms.state.Msgs) + n += binary.PutUvarint(buf[n:], ms.state.Bytes) + n += binary.PutUvarint(buf[n:], ms.state.FirstSeq) + n += binary.PutUvarint(buf[n:], ms.state.LastSeq) + n += binary.PutUvarint(buf[n:], failed) + n += binary.PutUvarint(buf[n:], uint64(numDeleted)) + + b := buf[0:n] + + if numDeleted > 0 { + buf, err := ms.dmap.Encode(nil) + if err != nil { + return nil, err + } + b = append(b, buf...) + } + + return b, nil } -func (ms *memStore) Snapshot(_ time.Duration, _, _ bool) (*SnapshotResult, error) { - return nil, fmt.Errorf("no impl") +// SyncDeleted will make sure this stream has same deleted state as dbs. +func (ms *memStore) SyncDeleted(dbs DeleteBlocks) { + ms.mu.Lock() + defer ms.mu.Unlock() + + // For now we share one dmap, so if we have one entry here check if states are the same. + // Note this will work for any DeleteBlock type, but we expect this to be a dmap too. + if len(dbs) == 1 { + min, max, num := ms.dmap.State() + if pmin, pmax, pnum := dbs[0].State(); pmin == min && pmax == max && pnum == num { + return + } + } + lseq := ms.state.LastSeq + for _, db := range dbs { + // Skip if beyond our current state. + if first, _, _ := db.State(); first > lseq { + continue + } + db.Range(func(seq uint64) bool { + ms.removeMsg(seq, false) + return true + }) + } +} + +func (o *consumerMemStore) Update(state *ConsumerState) error { + // Sanity checks. + if state.AckFloor.Consumer > state.Delivered.Consumer { + return fmt.Errorf("bad ack floor for consumer") + } + if state.AckFloor.Stream > state.Delivered.Stream { + return fmt.Errorf("bad ack floor for stream") + } + + // Copy to our state. + var pending map[uint64]*Pending + var redelivered map[uint64]uint64 + if len(state.Pending) > 0 { + pending = make(map[uint64]*Pending, len(state.Pending)) + for seq, p := range state.Pending { + pending[seq] = &Pending{p.Sequence, p.Timestamp} + if seq <= state.AckFloor.Stream || seq > state.Delivered.Stream { + return fmt.Errorf("bad pending entry, sequence [%d] out of range", seq) + } + } + } + if len(state.Redelivered) > 0 { + redelivered = make(map[uint64]uint64, len(state.Redelivered)) + for seq, dc := range state.Redelivered { + redelivered[seq] = dc + } + } + + // Replace our state. + o.mu.Lock() + defer o.mu.Unlock() + + // Check to see if this is an outdated update. + if state.Delivered.Consumer < o.state.Delivered.Consumer || state.AckFloor.Stream < o.state.AckFloor.Stream { + return fmt.Errorf("old update ignored") + } + + o.state.Delivered = state.Delivered + o.state.AckFloor = state.AckFloor + o.state.Pending = pending + o.state.Redelivered = redelivered + + return nil +} + +// SetStarting sets our starting stream sequence. +func (o *consumerMemStore) SetStarting(sseq uint64) error { + o.mu.Lock() + o.state.Delivered.Stream = sseq + o.mu.Unlock() + return nil +} + +// UpdateStarting updates our starting stream sequence. +func (o *consumerMemStore) UpdateStarting(sseq uint64) { + o.mu.Lock() + defer o.mu.Unlock() + + if sseq > o.state.Delivered.Stream { + o.state.Delivered.Stream = sseq + // For AckNone just update delivered and ackfloor at the same time. + if o.cfg.AckPolicy == AckNone { + o.state.AckFloor.Stream = sseq + } + } +} + +// HasState returns if this store has a recorded state. +func (o *consumerMemStore) HasState() bool { + o.mu.Lock() + defer o.mu.Unlock() + // We have a running state. + return o.state.Delivered.Consumer != 0 || o.state.Delivered.Stream != 0 +} + +func (o *consumerMemStore) UpdateDelivered(dseq, sseq, dc uint64, ts int64) error { + o.mu.Lock() + defer o.mu.Unlock() + + if dc != 1 && o.cfg.AckPolicy == AckNone { + return ErrNoAckPolicy + } + + // On restarts the old leader may get a replay from the raft logs that are old. + if dseq <= o.state.AckFloor.Consumer { + return nil + } + + // See if we expect an ack for this. + if o.cfg.AckPolicy != AckNone { + // Need to create pending records here. + if o.state.Pending == nil { + o.state.Pending = make(map[uint64]*Pending) + } + var p *Pending + // Check for an update to a message already delivered. + if sseq <= o.state.Delivered.Stream { + if p = o.state.Pending[sseq]; p != nil { + // Do not update p.Sequence, that should be the original delivery sequence. + p.Timestamp = ts + } + } else { + // Add to pending. + o.state.Pending[sseq] = &Pending{dseq, ts} + } + // Update delivered as needed. + if dseq > o.state.Delivered.Consumer { + o.state.Delivered.Consumer = dseq + } + if sseq > o.state.Delivered.Stream { + o.state.Delivered.Stream = sseq + } + + if dc > 1 { + if maxdc := uint64(o.cfg.MaxDeliver); maxdc > 0 && dc > maxdc { + // Make sure to remove from pending. + delete(o.state.Pending, sseq) + } + if o.state.Redelivered == nil { + o.state.Redelivered = make(map[uint64]uint64) + } + // Only update if greater than what we already have. + if o.state.Redelivered[sseq] < dc-1 { + o.state.Redelivered[sseq] = dc - 1 + } + } + } else { + // For AckNone just update delivered and ackfloor at the same time. + if dseq > o.state.Delivered.Consumer { + o.state.Delivered.Consumer = dseq + o.state.AckFloor.Consumer = dseq + } + if sseq > o.state.Delivered.Stream { + o.state.Delivered.Stream = sseq + o.state.AckFloor.Stream = sseq + } + } + + return nil } -// No-ops. -func (os *consumerMemStore) Update(_ *ConsumerState) error { return nil } +func (o *consumerMemStore) UpdateAcks(dseq, sseq uint64) error { + o.mu.Lock() + defer o.mu.Unlock() + + if o.cfg.AckPolicy == AckNone { + return ErrNoAckPolicy + } + + // On restarts the old leader may get a replay from the raft logs that are old. + if dseq <= o.state.AckFloor.Consumer { + return nil + } + + if len(o.state.Pending) == 0 || o.state.Pending[sseq] == nil { + delete(o.state.Redelivered, sseq) + return ErrStoreMsgNotFound + } + + // Check for AckAll here. + if o.cfg.AckPolicy == AckAll { + sgap := sseq - o.state.AckFloor.Stream + o.state.AckFloor.Consumer = dseq + o.state.AckFloor.Stream = sseq + if sgap > uint64(len(o.state.Pending)) { + for seq := range o.state.Pending { + if seq <= sseq { + delete(o.state.Pending, seq) + delete(o.state.Redelivered, seq) + } + } + } else { + for seq := sseq; seq > sseq-sgap && len(o.state.Pending) > 0; seq-- { + delete(o.state.Pending, seq) + delete(o.state.Redelivered, seq) + } + } + return nil + } + + // AckExplicit + + // First delete from our pending state. + if p, ok := o.state.Pending[sseq]; ok { + delete(o.state.Pending, sseq) + if dseq > p.Sequence && p.Sequence > 0 { + dseq = p.Sequence // Use the original. + } + } + + if len(o.state.Pending) == 0 { + o.state.AckFloor.Consumer = o.state.Delivered.Consumer + o.state.AckFloor.Stream = o.state.Delivered.Stream + } else if dseq == o.state.AckFloor.Consumer+1 { + o.state.AckFloor.Consumer = dseq + o.state.AckFloor.Stream = sseq + + if o.state.Delivered.Consumer > dseq { + for ss := sseq + 1; ss <= o.state.Delivered.Stream; ss++ { + if p, ok := o.state.Pending[ss]; ok { + if p.Sequence > 0 { + o.state.AckFloor.Consumer = p.Sequence - 1 + o.state.AckFloor.Stream = ss - 1 + } + break + } + } + } + } + // We do these regardless. + delete(o.state.Redelivered, sseq) + + return nil +} -func (os *consumerMemStore) UpdateDelivered(_, _, _ uint64, _ int64) error { return nil } +func (o *consumerMemStore) UpdateConfig(cfg *ConsumerConfig) error { + o.mu.Lock() + defer o.mu.Unlock() -func (os *consumerMemStore) UpdateAcks(_, _ uint64) error { return nil } + // This is mostly unchecked here. We are assuming the upper layers have done sanity checking. + o.cfg = *cfg + return nil +} -func (os *consumerMemStore) Stop() error { - os.ms.decConsumers() +func (o *consumerMemStore) Stop() error { + o.mu.Lock() + o.closed = true + ms := o.ms + o.mu.Unlock() + ms.RemoveConsumer(o) return nil } -func (os *consumerMemStore) Delete() error { - return os.Stop() +func (o *consumerMemStore) Delete() error { + return o.Stop() +} + +func (o *consumerMemStore) StreamDelete() error { + return o.Stop() +} + +func (o *consumerMemStore) State() (*ConsumerState, error) { + return o.stateWithCopy(true) +} + +// This will not copy pending or redelivered, so should only be done under the +// consumer owner's lock. +func (o *consumerMemStore) BorrowState() (*ConsumerState, error) { + return o.stateWithCopy(false) +} + +func (o *consumerMemStore) stateWithCopy(doCopy bool) (*ConsumerState, error) { + o.mu.Lock() + defer o.mu.Unlock() + + if o.closed { + return nil, ErrStoreClosed + } + + state := &ConsumerState{} + + state.Delivered = o.state.Delivered + state.AckFloor = o.state.AckFloor + if len(o.state.Pending) > 0 { + if doCopy { + state.Pending = o.copyPending() + } else { + state.Pending = o.state.Pending + } + } + if len(o.state.Redelivered) > 0 { + if doCopy { + state.Redelivered = o.copyRedelivered() + } else { + state.Redelivered = o.state.Redelivered + } + } + return state, nil +} + +// EncodedState for this consumer store. +func (o *consumerMemStore) EncodedState() ([]byte, error) { + o.mu.Lock() + defer o.mu.Unlock() + + if o.closed { + return nil, ErrStoreClosed + } + + return encodeConsumerState(&o.state), nil +} + +func (o *consumerMemStore) copyPending() map[uint64]*Pending { + pending := make(map[uint64]*Pending, len(o.state.Pending)) + for seq, p := range o.state.Pending { + pending[seq] = &Pending{p.Sequence, p.Timestamp} + } + return pending +} + +func (o *consumerMemStore) copyRedelivered() map[uint64]uint64 { + redelivered := make(map[uint64]uint64, len(o.state.Redelivered)) + for seq, dc := range o.state.Redelivered { + redelivered[seq] = dc + } + return redelivered } -func (os *consumerMemStore) State() (*ConsumerState, error) { return nil, nil } +// Type returns the type of the underlying store. +func (o *consumerMemStore) Type() StorageType { return MemoryStorage } // Templates type templateMemStore struct{} @@ -499,5 +2528,5 @@ func newTemplateMemStore() *templateMemStore { } // No-ops for memstore. -func (ts *templateMemStore) Store(t *StreamTemplate) error { return nil } -func (ts *templateMemStore) Delete(t *StreamTemplate) error { return nil } +func (ts *templateMemStore) Store(t *streamTemplate) error { return nil } +func (ts *templateMemStore) Delete(t *streamTemplate) error { return nil } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/monitor.go b/vendor/github.com/nats-io/nats-server/v2/server/monitor.go index 6c941f2..f749a7d 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/monitor.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/monitor.go @@ -1,4 +1,4 @@ -// Copyright 2013-2019 The NATS Authors +// Copyright 2013-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,13 +14,26 @@ package server import ( + "bytes" + "cmp" + "crypto/sha256" "crypto/tls" + "crypto/x509" + "encoding/hex" "encoding/json" + "expvar" "fmt" + "maps" + "math" "net" "net/http" "net/url" + "os" + "path/filepath" "runtime" + "runtime/debug" + "runtime/pprof" + "slices" "sort" "strconv" "strings" @@ -31,15 +44,6 @@ import ( "github.com/nats-io/nats-server/v2/server/pse" ) -// Snapshot this -var numCores int -var maxProcs int - -func init() { - numCores = runtime.NumCPU() - maxProcs = runtime.GOMAXPROCS(0) -} - // Connz represents detailed information on current client connections. type Connz struct { ID string `json:"server_id"` @@ -76,6 +80,9 @@ type ConnzOptions struct { // Filter for this explicit client connection. CID uint64 `json:"cid"` + // Filter for this explicit client connection based on the MQTT client ID + MQTTClient string `json:"mqtt_client"` + // Filter by connection state. State ConnState `json:"state"` @@ -86,6 +93,9 @@ type ConnzOptions struct { // Filter by account. Account string `json:"acc"` + + // Filter by subject interest + FilterSubject string `json:"filter_subject"` } // ConnState is for filtering states of connections. We will only have two, open and closed. @@ -102,31 +112,50 @@ const ( // ConnInfo has detailed information on a per connection basis. type ConnInfo struct { - Cid uint64 `json:"cid"` - IP string `json:"ip"` - Port int `json:"port"` - Start time.Time `json:"start"` - LastActivity time.Time `json:"last_activity"` - Stop *time.Time `json:"stop,omitempty"` - Reason string `json:"reason,omitempty"` - RTT string `json:"rtt,omitempty"` - Uptime string `json:"uptime"` - Idle string `json:"idle"` - Pending int `json:"pending_bytes"` - InMsgs int64 `json:"in_msgs"` - OutMsgs int64 `json:"out_msgs"` - InBytes int64 `json:"in_bytes"` - OutBytes int64 `json:"out_bytes"` - NumSubs uint32 `json:"subscriptions"` - Name string `json:"name,omitempty"` - Lang string `json:"lang,omitempty"` - Version string `json:"version,omitempty"` - TLSVersion string `json:"tls_version,omitempty"` - TLSCipher string `json:"tls_cipher_suite,omitempty"` - AuthorizedUser string `json:"authorized_user,omitempty"` - Account string `json:"account,omitempty"` - Subs []string `json:"subscriptions_list,omitempty"` - SubsDetail []SubDetail `json:"subscriptions_list_detail,omitempty"` + Cid uint64 `json:"cid"` + Kind string `json:"kind,omitempty"` + Type string `json:"type,omitempty"` + IP string `json:"ip"` + Port int `json:"port"` + Start time.Time `json:"start"` + LastActivity time.Time `json:"last_activity"` + Stop *time.Time `json:"stop,omitempty"` + Reason string `json:"reason,omitempty"` + RTT string `json:"rtt,omitempty"` + Uptime string `json:"uptime"` + Idle string `json:"idle"` + Pending int `json:"pending_bytes"` + InMsgs int64 `json:"in_msgs"` + OutMsgs int64 `json:"out_msgs"` + InBytes int64 `json:"in_bytes"` + OutBytes int64 `json:"out_bytes"` + NumSubs uint32 `json:"subscriptions"` + Name string `json:"name,omitempty"` + Lang string `json:"lang,omitempty"` + Version string `json:"version,omitempty"` + TLSVersion string `json:"tls_version,omitempty"` + TLSCipher string `json:"tls_cipher_suite,omitempty"` + TLSPeerCerts []*TLSPeerCert `json:"tls_peer_certs,omitempty"` + TLSFirst bool `json:"tls_first,omitempty"` + AuthorizedUser string `json:"authorized_user,omitempty"` + Account string `json:"account,omitempty"` + Subs []string `json:"subscriptions_list,omitempty"` + SubsDetail []SubDetail `json:"subscriptions_list_detail,omitempty"` + JWT string `json:"jwt,omitempty"` + IssuerKey string `json:"issuer_key,omitempty"` + NameTag string `json:"name_tag,omitempty"` + Tags jwt.TagList `json:"tags,omitempty"` + MQTTClient string `json:"mqtt_client,omitempty"` // This is the MQTT client id + + // Internal + rtt int64 // For fast sorting +} + +// TLSPeerCert contains basic information about a TLS peer certificate +type TLSPeerCert struct { + Subject string `json:"subject,omitempty"` + SubjectPKISha256 string `json:"spki_sha256,omitempty"` + CertSha256 string `json:"cert_sha256,omitempty"` } // DefaultConnListSize is the default size of the connection list. @@ -166,13 +195,14 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { state = ConnOpen user string acc string + a *Account + filter string + mqttCID string ) if opts != nil { // If no sort option given or sort is by uptime, then sort by cid - if opts.Sort == "" { - sortOpt = ByCid - } else { + if opts.Sort != _EMPTY_ { sortOpt = opts.Sort if !sortOpt.IsValid() { return nil, fmt.Errorf("invalid sorting option: %s", sortOpt) @@ -181,11 +211,9 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { // Auth specifics. auth = opts.Username - if !auth && (user != "" || acc != "") { - return nil, fmt.Errorf("filter by user or account only allowed with auth option") - } user = opts.User acc = opts.Account + mqttCID = opts.MQTTClient subs = opts.Subscriptions subsDet = opts.SubscriptionsDetail @@ -208,18 +236,24 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { if sortOpt == ByReason && state != ConnClosed { return nil, fmt.Errorf("sort by reason only valid on closed connections") } - // If searching by CID if opts.CID > 0 { cid = opts.CID limit = 1 } + // If filtering by subject. + if opts.FilterSubject != _EMPTY_ && opts.FilterSubject != fwcs { + if acc == _EMPTY_ { + return nil, fmt.Errorf("filter by subject only valid with account filtering") + } + filter = opts.FilterSubject + } } c := &Connz{ Offset: offset, Limit: limit, - Now: time.Now(), + Now: time.Now().UTC(), } // Open clients @@ -227,8 +261,32 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { // Hold for closed clients if requested. var closedClients []*closedClient + var clist map[uint64]*client + + if acc != _EMPTY_ { + var err error + a, err = s.lookupAccount(acc) + if err != nil { + return c, nil + } + a.mu.RLock() + clist = make(map[uint64]*client, a.numLocalConnections()) + for c := range a.clients { + if c.kind == CLIENT || c.kind == LEAF { + clist[c.cid] = c + } + } + a.mu.RUnlock() + } + // Walk the open client list with server lock held. - s.mu.Lock() + s.mu.RLock() + // Default to all client unless filled in above. + if clist == nil { + clist = make(map[uint64]*client, len(s.clients)+len(s.leafs)) + maps.Copy(clist, s.clients) + maps.Copy(clist, s.leafs) + } // copy the server id for monitoring c.ID = s.info.ID @@ -237,14 +295,27 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { // may be smaller if pagination is used. switch state { case ConnOpen: - c.Total = len(s.clients) + c.Total = len(clist) case ConnClosed: - c.Total = s.closed.len() closedClients = s.closed.closedClients() c.Total = len(closedClients) case ConnAll: + c.Total = len(clist) closedClients = s.closed.closedClients() - c.Total = len(s.clients) + len(closedClients) + c.Total += len(closedClients) + } + + // We may need to filter these connections. + if acc != _EMPTY_ && len(closedClients) > 0 { + var ccc []*closedClient + for _, cc := range closedClients { + if cc.acc != acc { + continue + } + ccc = append(ccc, cc) + } + c.Total -= (len(closedClients) - len(ccc)) + closedClients = ccc } totalClients := c.Total @@ -272,7 +343,17 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { // Search by individual CID. if cid > 0 { - if state == ConnClosed || state == ConnAll { + // Let's first check if user also selects on ConnOpen or ConnAll + // and look for opened connections. + if state == ConnOpen || state == ConnAll { + if client := s.clients[cid]; client != nil { + openClients = append(openClients, client) + closedClients = nil + } + } + // If we did not find, and the user selected for ConnClosed or ConnAll, + // look for closed connections. + if len(openClients) == 0 && (state == ConnClosed || state == ConnAll) { copyClosed := closedClients closedClients = nil for _, cc := range copyClosed { @@ -281,29 +362,44 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { break } } - } else if state == ConnOpen || state == ConnAll { - client := s.clients[cid] - if client != nil { - openClients = append(openClients, client) - } } } else { // Gather all open clients. if state == ConnOpen || state == ConnAll { - for _, client := range s.clients { + for _, client := range clist { // If we have an account specified we need to filter. - if acc != "" && (client.acc == nil || client.acc.Name != acc) { + if acc != _EMPTY_ && (client.acc == nil || client.acc.Name != acc) { continue } // Do user filtering second - if user != "" && client.opts.Username != user { + if user != _EMPTY_ && client.getRawAuthUserLock() != user { + continue + } + // Do mqtt client ID filtering next + if mqttCID != _EMPTY_ && client.getMQTTClientID() != mqttCID { continue } openClients = append(openClients, client) } } } - s.mu.Unlock() + s.mu.RUnlock() + + // Filter by subject now if needed. We do this outside of server lock. + if filter != _EMPTY_ { + var oc []*client + for _, c := range openClients { + c.mu.Lock() + for _, sub := range c.subs { + if SubjectsCollide(filter, string(sub.subject)) { + oc = append(oc, c) + break + } + } + c.mu.Unlock() + openClients = oc + } + } // Just return with empty array if nothing here. if len(openClients) == 0 && len(closedClients) == 0 { @@ -312,13 +408,12 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { } // Now whip through and generate ConnInfo entries - // Open Clients i := 0 for _, client := range openClients { client.mu.Lock() ci := &conns[i] - ci.fill(client, client.nc, c.Now) + ci.fill(client, client.nc, c.Now, auth) // Fill in subscription data if requested. if len(client.subs) > 0 { if subsDet { @@ -329,11 +424,14 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { } // Fill in user if auth requested. if auth { - ci.AuthorizedUser = client.opts.Username - // Add in account iff not the global account. - if client.acc != nil && (client.acc.Name != globalAccountName) { - ci.Account = client.acc.Name + ci.AuthorizedUser = client.getRawAuthUser() + if name := client.acc.GetName(); name != globalAccountName { + ci.Account = name } + ci.JWT = client.opts.JWT + ci.IssuerKey = issuerForClient(client) + ci.Tags = client.tags + ci.NameTag = client.acc.getNameTag() } client.mu.Unlock() pconns[i] = ci @@ -346,14 +444,17 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { } for _, cc := range closedClients { // If we have an account specified we need to filter. - if acc != "" && cc.acc != acc { + if acc != _EMPTY_ && cc.acc != acc { continue } // Do user filtering second - if user != "" && cc.user != user { + if user != _EMPTY_ && cc.user != user { + continue + } + // Do mqtt client ID filtering next + if mqttCID != _EMPTY_ && cc.MQTTClient != mqttCID { continue } - // Copy if needed for any changes to the ConnInfo if needCopy { cx := *cc @@ -373,9 +474,11 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { // Fill in user if auth requested. if auth { cc.AuthorizedUser = cc.user - // Add in account iff not the global account. - if cc.acc != "" && (cc.acc != globalAccountName) { + if cc.acc != _EMPTY_ && (cc.acc != globalAccountName) { cc.Account = cc.acc + if acc, err := s.LookupAccount(cc.acc); err == nil { + cc.NameTag = acc.getNameTag() + } } } pconns[i] = &cc.ConnInfo @@ -406,13 +509,15 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { case ByLast: sort.Sort(sort.Reverse(byLast{pconns})) case ByIdle: - sort.Sort(sort.Reverse(byIdle{pconns})) + sort.Sort(sort.Reverse(byIdle{pconns, c.Now})) case ByUptime: sort.Sort(byUptime{pconns, time.Now()}) case ByStop: sort.Sort(sort.Reverse(byStop{pconns})) case ByReason: sort.Sort(byReason{pconns}) + case ByRTT: + sort.Sort(sort.Reverse(byRTT{pconns})) } minoff := c.Offset @@ -441,13 +546,20 @@ func (s *Server) Connz(opts *ConnzOptions) (*Connz, error) { // Fills in the ConnInfo from the client. // client should be locked. -func (ci *ConnInfo) fill(client *client, nc net.Conn, now time.Time) { +func (ci *ConnInfo) fill(client *client, nc net.Conn, now time.Time, auth bool) { + // For fast sort if required. + rtt := client.getRTT() + ci.rtt = int64(rtt) + ci.Cid = client.cid + ci.MQTTClient = client.getMQTTClientID() + ci.Kind = client.kindString() + ci.Type = client.clientTypeString() ci.Start = client.start ci.LastActivity = client.last ci.Uptime = myUptime(now.Sub(client.start)) ci.Idle = myUptime(now.Sub(client.last)) - ci.RTT = client.getRTT() + ci.RTT = rtt.String() ci.OutMsgs = client.outMsgs ci.OutBytes = client.outBytes ci.NumSubs = uint32(len(client.subs)) @@ -464,10 +576,15 @@ func (ci *ConnInfo) fill(client *client, nc net.Conn, now time.Time) { // Exclude clients that are still doing handshake so we don't block in // ConnectionState(). if client.flags.isSet(handshakeComplete) && nc != nil { - conn := nc.(*tls.Conn) - cs := conn.ConnectionState() - ci.TLSVersion = tlsVersion(cs.Version) - ci.TLSCipher = tlsCipher(cs.CipherSuite) + if conn, ok := nc.(*tls.Conn); ok { + cs := conn.ConnectionState() + ci.TLSVersion = tlsVersion(cs.Version) + ci.TLSCipher = tlsCipher(cs.CipherSuite) + if auth && len(cs.PeerCertificates) > 0 { + ci.TLSPeerCerts = makePeerCerts(cs.PeerCertificates) + } + ci.TLSFirst = client.flags.isSet(didTLSFirst) + } } if client.port != 0 { @@ -476,15 +593,27 @@ func (ci *ConnInfo) fill(client *client, nc net.Conn, now time.Time) { } } +func makePeerCerts(pc []*x509.Certificate) []*TLSPeerCert { + res := make([]*TLSPeerCert, len(pc)) + for i, c := range pc { + tmp := sha256.Sum256(c.RawSubjectPublicKeyInfo) + ssha := hex.EncodeToString(tmp[:]) + tmp = sha256.Sum256(c.Raw) + csha := hex.EncodeToString(tmp[:]) + res[i] = &TLSPeerCert{Subject: c.Subject.String(), SubjectPKISha256: ssha, CertSha256: csha} + } + return res +} + // Assume lock is held -func (c *client) getRTT() string { +func (c *client) getRTT() time.Duration { if c.rtt == 0 { // If a real client, go ahead and send ping now to get a value // for RTT. For tests and telnet, or if client is closing, etc skip. - if c.opts.Lang != "" { + if c.opts.Lang != _EMPTY_ { c.sendRTTPingLocked() } - return "" + return 0 } var rtt time.Duration if c.rtt > time.Microsecond && c.rtt < time.Millisecond { @@ -492,12 +621,12 @@ func (c *client) getRTT() string { } else { rtt = c.rtt.Truncate(time.Nanosecond) } - return rtt.String() + return rtt } func decodeBool(w http.ResponseWriter, r *http.Request, param string) (bool, error) { str := r.URL.Query().Get(param) - if str == "" { + if str == _EMPTY_ { return false, nil } val, err := strconv.ParseBool(str) @@ -511,7 +640,7 @@ func decodeBool(w http.ResponseWriter, r *http.Request, param string) (bool, err func decodeUint64(w http.ResponseWriter, r *http.Request, param string) (uint64, error) { str := r.URL.Query().Get(param) - if str == "" { + if str == _EMPTY_ { return 0, nil } val, err := strconv.ParseUint(str, 10, 64) @@ -525,7 +654,7 @@ func decodeUint64(w http.ResponseWriter, r *http.Request, param string) (uint64, func decodeInt(w http.ResponseWriter, r *http.Request, param string) (int, error) { str := r.URL.Query().Get(param) - if str == "" { + if str == _EMPTY_ { return 0, nil } val, err := strconv.Atoi(str) @@ -539,7 +668,7 @@ func decodeInt(w http.ResponseWriter, r *http.Request, param string) (int, error func decodeState(w http.ResponseWriter, r *http.Request) (ConnState, error) { str := r.URL.Query().Get("state") - if str == "" { + if str == _EMPTY_ { return ConnOpen, nil } switch strings.ToLower(str) { @@ -595,6 +724,7 @@ func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) { user := r.URL.Query().Get("user") acc := r.URL.Query().Get("acc") + mqttCID := r.URL.Query().Get("mqtt_client") connzOpts := &ConnzOptions{ Sort: sortOpt, @@ -604,6 +734,7 @@ func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) { Offset: offset, Limit: limit, CID: cid, + MQTTClient: mqttCID, State: state, User: user, Account: acc, @@ -631,6 +762,7 @@ func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) { // Routez represents detailed information on current client connections. type Routez struct { ID string `json:"server_id"` + Name string `json:"server_name"` Now time.Time `json:"now"` Import *SubjectPermission `json:"import,omitempty"` Export *SubjectPermission `json:"export,omitempty"` @@ -650,14 +782,19 @@ type RoutezOptions struct { type RouteInfo struct { Rid uint64 `json:"rid"` RemoteID string `json:"remote_id"` + RemoteName string `json:"remote_name"` DidSolicit bool `json:"did_solicit"` IsConfigured bool `json:"is_configured"` IP string `json:"ip"` Port int `json:"port"` + Start time.Time `json:"start"` + LastActivity time.Time `json:"last_activity"` + RTT string `json:"rtt,omitempty"` + Uptime string `json:"uptime"` + Idle string `json:"idle"` Import *SubjectPermission `json:"import,omitempty"` Export *SubjectPermission `json:"export,omitempty"` Pending int `json:"pending_size"` - RTT string `json:"rtt,omitempty"` InMsgs int64 `json:"in_msgs"` OutMsgs int64 `json:"out_msgs"` InBytes int64 `json:"in_bytes"` @@ -665,19 +802,21 @@ type RouteInfo struct { NumSubs uint32 `json:"subscriptions"` Subs []string `json:"subscriptions_list,omitempty"` SubsDetail []SubDetail `json:"subscriptions_list_detail,omitempty"` + Account string `json:"account,omitempty"` + Compression string `json:"compression,omitempty"` } // Routez returns a Routez struct containing information about routes. func (s *Server) Routez(routezOpts *RoutezOptions) (*Routez, error) { rs := &Routez{Routes: []*RouteInfo{}} - rs.Now = time.Now() + rs.Now = time.Now().UTC() if routezOpts == nil { routezOpts = &RoutezOptions{} } s.mu.Lock() - rs.NumRoutes = len(s.routes) + rs.NumRoutes = s.numRoutes() // copy the server id for monitoring rs.ID = s.info.ID @@ -687,13 +826,14 @@ func (s *Server) Routez(routezOpts *RoutezOptions) (*Routez, error) { rs.Import = perms.Import rs.Export = perms.Export } + rs.Name = s.getOpts().ServerName - // Walk the list - for _, r := range s.routes { + addRoute := func(r *client) { r.mu.Lock() ri := &RouteInfo{ Rid: r.cid, RemoteID: r.route.remoteID, + RemoteName: r.route.remoteName, DidSolicit: r.route.didSolicit, IsConfigured: r.route.routeType == Explicit, InMsgs: atomic.LoadInt64(&r.inMsgs), @@ -702,8 +842,15 @@ func (s *Server) Routez(routezOpts *RoutezOptions) (*Routez, error) { OutBytes: r.outBytes, NumSubs: uint32(len(r.subs)), Import: r.opts.Import, + Pending: int(r.out.pb), Export: r.opts.Export, - RTT: r.getRTT(), + RTT: r.getRTT().String(), + Start: r.start, + LastActivity: r.last, + Uptime: myUptime(rs.Now.Sub(r.start)), + Idle: myUptime(rs.Now.Sub(r.last)), + Account: string(r.route.accName), + Compression: r.route.compression, } if len(r.subs) > 0 { @@ -723,6 +870,11 @@ func (s *Server) Routez(routezOpts *RoutezOptions) (*Routez, error) { r.mu.Unlock() rs.Routes = append(rs.Routes, ri) } + + // Walk the list + s.forEachRoute(func(r *client) { + addRoute(r) + }) s.mu.Unlock() return rs, nil } @@ -785,21 +937,21 @@ type SubszOptions struct { // SubDetail is for verbose information for subscriptions. type SubDetail struct { - Account string `json:"account,omitempty"` - Subject string `json:"subject"` - Queue string `json:"qgroup,omitempty"` - Sid string `json:"sid"` - Msgs int64 `json:"msgs"` - Max int64 `json:"max,omitempty"` - Cid uint64 `json:"cid"` + Account string `json:"account,omitempty"` + AccountTag string `json:"account_tag,omitempty"` + Subject string `json:"subject"` + Queue string `json:"qgroup,omitempty"` + Sid string `json:"sid"` + Msgs int64 `json:"msgs"` + Max int64 `json:"max,omitempty"` + Cid uint64 `json:"cid"` } // Subscription client should be locked and guaranteed to be present. func newSubDetail(sub *subscription) SubDetail { sd := newClientSubDetail(sub) - if sub.client.acc != nil { - sd.Account = sub.client.acc.GetName() - } + sd.Account = sub.client.acc.GetName() + sd.AccountTag = sub.client.acc.getNameTag() return sd } @@ -821,9 +973,9 @@ func (s *Server) Subsz(opts *SubszOptions) (*Subsz, error) { subdetail bool test bool offset int + testSub string + filterAcc string limit = DefaultSubListSize - testSub = "" - filterAcc = "" ) if opts != nil { @@ -836,14 +988,14 @@ func (s *Server) Subsz(opts *SubszOptions) (*Subsz, error) { if limit <= 0 { limit = DefaultSubListSize } - if opts.Test != "" { + if opts.Test != _EMPTY_ { testSub = opts.Test test = true if !IsValidLiteralSubject(testSub) { return nil, fmt.Errorf("invalid test subject, must be valid publish subject: %s", testSub) } } - if opts.Account != "" { + if opts.Account != _EMPTY_ { filterAcc = opts.Account } } @@ -851,22 +1003,22 @@ func (s *Server) Subsz(opts *SubszOptions) (*Subsz, error) { slStats := &SublistStats{} // FIXME(dlc) - Make account aware. - sz := &Subsz{s.info.ID, time.Now(), slStats, 0, offset, limit, nil} + sz := &Subsz{s.info.ID, time.Now().UTC(), slStats, 0, offset, limit, nil} if subdetail { var raw [4096]*subscription subs := raw[:0] - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) - if filterAcc != "" && acc.GetName() != filterAcc { + if filterAcc != _EMPTY_ && acc.GetName() != filterAcc { return true } slStats.add(acc.sl.Stats()) - acc.sl.localSubs(&subs) + acc.sl.localSubs(&subs, false) return true }) - details := make([]SubDetail, len(subs)) + details := make([]SubDetail, 0, len(subs)) i := 0 // TODO(dlc) - may be inefficient and could just do normal match when total subs is large and filtering. for _, sub := range subs { @@ -878,7 +1030,7 @@ func (s *Server) Subsz(opts *SubszOptions) (*Subsz, error) { continue } sub.client.mu.Lock() - details[i] = newSubDetail(sub) + details = append(details, newSubDetail(sub)) sub.client.mu.Unlock() i++ } @@ -895,11 +1047,11 @@ func (s *Server) Subsz(opts *SubszOptions) (*Subsz, error) { maxoff = maxIndex } sz.Subs = details[minoff:maxoff] - sz.Total = len(sz.Subs) + sz.Total = len(details) } else { - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) - if filterAcc != "" && acc.GetName() != filterAcc { + if filterAcc != _EMPTY_ && acc.GetName() != filterAcc { return true } slStats.add(acc.sl.Stats()) @@ -982,119 +1134,262 @@ func (s *Server) HandleStacksz(w http.ResponseWriter, r *http.Request) { ResponseHandler(w, r, buf[:n]) } +type IpqueueszStatusIPQ struct { + Pending int `json:"pending"` + InProgress int `json:"in_progress,omitempty"` +} + +type IpqueueszStatus map[string]IpqueueszStatusIPQ + +func (s *Server) Ipqueuesz(opts *IpqueueszOptions) *IpqueueszStatus { + all, qfilter := opts.All, opts.Filter + queues := IpqueueszStatus{} + s.ipQueues.Range(func(k, v any) bool { + var pending, inProgress int + name := k.(string) + queue, ok := v.(interface { + len() int + inProgress() int64 + }) + if ok { + pending = queue.len() + inProgress = int(queue.inProgress()) + } + if !all && (pending == 0 && inProgress == 0) { + return true + } else if qfilter != _EMPTY_ && !strings.Contains(name, qfilter) { + return true + } + queues[name] = IpqueueszStatusIPQ{Pending: pending, InProgress: inProgress} + return true + }) + return &queues +} + +func (s *Server) HandleIPQueuesz(w http.ResponseWriter, r *http.Request) { + all, err := decodeBool(w, r, "all") + if err != nil { + return + } + qfilter := r.URL.Query().Get("queues") + + queues := s.Ipqueuesz(&IpqueueszOptions{ + All: all, + Filter: qfilter, + }) + + b, _ := json.MarshalIndent(queues, "", " ") + ResponseHandler(w, r, b) +} + // Varz will output server information on the monitoring port at /varz. type Varz struct { - ID string `json:"server_id"` - Name string `json:"server_name"` - Version string `json:"version"` - Proto int `json:"proto"` - GitCommit string `json:"git_commit,omitempty"` - GoVersion string `json:"go"` - Host string `json:"host"` - Port int `json:"port"` - AuthRequired bool `json:"auth_required,omitempty"` - TLSRequired bool `json:"tls_required,omitempty"` - TLSVerify bool `json:"tls_verify,omitempty"` - IP string `json:"ip,omitempty"` - ClientConnectURLs []string `json:"connect_urls,omitempty"` - WSConnectURLs []string `json:"ws_connect_urls,omitempty"` - MaxConn int `json:"max_connections"` - MaxSubs int `json:"max_subscriptions,omitempty"` - PingInterval time.Duration `json:"ping_interval"` - MaxPingsOut int `json:"ping_max"` - HTTPHost string `json:"http_host"` - HTTPPort int `json:"http_port"` - HTTPBasePath string `json:"http_base_path"` - HTTPSPort int `json:"https_port"` - AuthTimeout float64 `json:"auth_timeout"` - MaxControlLine int32 `json:"max_control_line"` - MaxPayload int `json:"max_payload"` - MaxPending int64 `json:"max_pending"` - Cluster ClusterOptsVarz `json:"cluster,omitempty"` - Gateway GatewayOptsVarz `json:"gateway,omitempty"` - LeafNode LeafNodeOptsVarz `json:"leaf,omitempty"` - JetStream JetStreamVarz `json:"jetstream,omitempty"` - TLSTimeout float64 `json:"tls_timeout"` - WriteDeadline time.Duration `json:"write_deadline"` - Start time.Time `json:"start"` - Now time.Time `json:"now"` - Uptime string `json:"uptime"` - Mem int64 `json:"mem"` - Cores int `json:"cores"` - MaxProcs int `json:"gomaxprocs"` - CPU float64 `json:"cpu"` - Connections int `json:"connections"` - TotalConnections uint64 `json:"total_connections"` - Routes int `json:"routes"` - Remotes int `json:"remotes"` - Leafs int `json:"leafnodes"` - InMsgs int64 `json:"in_msgs"` - OutMsgs int64 `json:"out_msgs"` - InBytes int64 `json:"in_bytes"` - OutBytes int64 `json:"out_bytes"` - SlowConsumers int64 `json:"slow_consumers"` - Subscriptions uint32 `json:"subscriptions"` - HTTPReqStats map[string]uint64 `json:"http_req_stats"` - ConfigLoadTime time.Time `json:"config_load_time"` + ID string `json:"server_id"` // ID is the unique server ID generated at start + Name string `json:"server_name"` // Name is the configured server name, equals ID when not set + Version string `json:"version"` // Version is the version of the running server + Proto int `json:"proto"` // Proto is the protocol version this server supports + GitCommit string `json:"git_commit,omitempty"` // GitCommit is the git repository commit hash that the build corresponds with + GoVersion string `json:"go"` // GoVersion is the version of Go used to build this binary + Host string `json:"host"` // Host is the hostname the server runs on + Port int `json:"port"` // Port is the port the server listens on for client connections + AuthRequired bool `json:"auth_required,omitempty"` // AuthRequired indicates if users are required to authenticate to join the server + TLSRequired bool `json:"tls_required,omitempty"` // TLSRequired indicates if connections must use TLS when connecting to this server + TLSVerify bool `json:"tls_verify,omitempty"` // TLSVerify indicates if full TLS verification will be performed + TLSOCSPPeerVerify bool `json:"tls_ocsp_peer_verify,omitempty"` // TLSOCSPPeerVerify indicates if the OCSP protocol will be used to verify peers + IP string `json:"ip,omitempty"` // IP is the IP address the server listens on if set + ClientConnectURLs []string `json:"connect_urls,omitempty"` // ClientConnectURLs is the list of URLs NATS clients can use to connect to this server + WSConnectURLs []string `json:"ws_connect_urls,omitempty"` // WSConnectURLs is the list of URLs websocket clients can use to connect to this server + MaxConn int `json:"max_connections"` // MaxConn is the maximum amount of connections the server can accept + MaxSubs int `json:"max_subscriptions,omitempty"` // MaxSubs is the maximum amount of subscriptions the server can manage + PingInterval time.Duration `json:"ping_interval"` // PingInterval is the interval the server will send PING messages during periods of inactivity on a connection + MaxPingsOut int `json:"ping_max"` // MaxPingsOut is the number of unanswered PINGs after which the connection will be considered stale + HTTPHost string `json:"http_host"` // HTTPHost is the HTTP host monitoring connections are accepted on + HTTPPort int `json:"http_port"` // HTTPPort is the port monitoring connections are accepted on + HTTPBasePath string `json:"http_base_path"` // HTTPBasePath is the path prefix for access to monitor endpoints + HTTPSPort int `json:"https_port"` // HTTPSPort is the HTTPS host monitoring connections are accepted on` + AuthTimeout float64 `json:"auth_timeout"` // AuthTimeout is the amount of seconds connections have to complete authentication + MaxControlLine int32 `json:"max_control_line"` // MaxControlLine is the amount of bytes a signal control message may be + MaxPayload int `json:"max_payload"` // MaxPayload is the maximum amount of bytes a message may have as payload + MaxPending int64 `json:"max_pending"` // MaxPending is the maximum amount of unprocessed bytes a connection may have + Cluster ClusterOptsVarz `json:"cluster,omitempty"` // Cluster is the Cluster state + Gateway GatewayOptsVarz `json:"gateway,omitempty"` // Gateway is the Super Cluster state + LeafNode LeafNodeOptsVarz `json:"leaf,omitempty"` // LeafNode is the Leafnode state + MQTT MQTTOptsVarz `json:"mqtt,omitempty"` // MQTT is the MQTT state + Websocket WebsocketOptsVarz `json:"websocket,omitempty"` // Websocket is the Websocket client state + JetStream JetStreamVarz `json:"jetstream,omitempty"` // JetStream is the JetStream state + TLSTimeout float64 `json:"tls_timeout"` // TLSTimeout is how long TLS operations have to complete + WriteDeadline time.Duration `json:"write_deadline"` // WriteDeadline is the maximum time writes to sockets have to complete + WriteTimeout string `json:"write_timeout,omitempty"` // WriteTimeout is the closure policy for write deadline errors + Start time.Time `json:"start"` // Start is time when the server was started + Now time.Time `json:"now"` // Now is the current time of the server + Uptime string `json:"uptime"` // Uptime is how long the server has been running + Mem int64 `json:"mem"` // Mem is the resident memory allocation + Cores int `json:"cores"` // Cores is the number of cores the process has access to + MaxProcs int `json:"gomaxprocs"` // MaxProcs is the configured GOMAXPROCS value + MemLimit int64 `json:"gomemlimit,omitempty"` // MemLimit is the configured GOMEMLIMIT value + CPU float64 `json:"cpu"` // CPU is the current total CPU usage + Connections int `json:"connections"` // Connections is the current connected connections + TotalConnections uint64 `json:"total_connections"` // TotalConnections is the total connections the server have ever handled + Routes int `json:"routes"` // Routes is the number of connected route servers + Remotes int `json:"remotes"` // Remotes is the configured route remote endpoints + Leafs int `json:"leafnodes"` // Leafs is the number connected leafnode clients + InMsgs int64 `json:"in_msgs"` // InMsgs is the number of messages this server received + OutMsgs int64 `json:"out_msgs"` // OutMsgs is the number of message this server sent + InBytes int64 `json:"in_bytes"` // InBytes is the number of bytes this server received + OutBytes int64 `json:"out_bytes"` // OutMsgs is the number of bytes this server sent + SlowConsumers int64 `json:"slow_consumers"` // SlowConsumers is the total count of clients that were disconnected since start due to being slow consumers + Subscriptions uint32 `json:"subscriptions"` // Subscriptions is the count of active subscriptions + HTTPReqStats map[string]uint64 `json:"http_req_stats"` // HTTPReqStats is the number of requests each HTTP endpoint received + ConfigLoadTime time.Time `json:"config_load_time"` // ConfigLoadTime is the time the configuration was loaded or reloaded + ConfigDigest string `json:"config_digest"` // ConfigDigest is a calculated hash of the current configuration + Tags jwt.TagList `json:"tags,omitempty"` // Tags are the tags assigned to the server in configuration + Metadata map[string]string `json:"metadata,omitempty"` // Metadata is the metadata assigned to the server in configuration + TrustedOperatorsJwt []string `json:"trusted_operators_jwt,omitempty"` // TrustedOperatorsJwt is the JWTs for all trusted operators + TrustedOperatorsClaim []*jwt.OperatorClaims `json:"trusted_operators_claim,omitempty"` // TrustedOperatorsClaim is the decoded claims for each trusted operator + SystemAccount string `json:"system_account,omitempty"` // SystemAccount is the name of the System account + PinnedAccountFail uint64 `json:"pinned_account_fails,omitempty"` // PinnedAccountFail is how often user logon fails due to the issuer account not being pinned. + OCSPResponseCache *OCSPResponseCacheVarz `json:"ocsp_peer_cache,omitempty"` // OCSPResponseCache is the state of the OCSP cache // OCSPResponseCache holds information about + SlowConsumersStats *SlowConsumersStats `json:"slow_consumer_stats"` // SlowConsumersStats is statistics about all detected Slow Consumer + TLSCertNotAfter time.Time `json:"tls_cert_not_after,omitzero"` // TLSCertNotAfter is the expiration date of the TLS certificate of this server } // JetStreamVarz contains basic runtime information about jetstream type JetStreamVarz struct { - MaxMemory int64 `json:"max_memory,omitempty"` - MaxStore int64 `json:"max_store,omitempty"` - StoreDir string `json:"store_dir,omitempty"` - Accounts int `json:"accounts,omitempty"` + Config *JetStreamConfig `json:"config,omitempty"` // Config is the active JetStream configuration + Stats *JetStreamStats `json:"stats,omitempty"` // Stats is the statistics for the JetStream server + Meta *MetaClusterInfo `json:"meta,omitempty"` // Meta is information about the JetStream metalayer + Limits *JSLimitOpts `json:"limits,omitempty"` // Limits are the configured JetStream limits } // ClusterOptsVarz contains monitoring cluster information type ClusterOptsVarz struct { - Name string `json:"name,omitempty"` - Host string `json:"addr,omitempty"` - Port int `json:"cluster_port,omitempty"` - AuthTimeout float64 `json:"auth_timeout,omitempty"` - URLs []string `json:"urls,omitempty"` + Name string `json:"name,omitempty"` // Name is the configured cluster name + Host string `json:"addr,omitempty"` // Host is the host the cluster listens on for connections + Port int `json:"cluster_port,omitempty"` // Port is the port the cluster listens on for connections + AuthTimeout float64 `json:"auth_timeout,omitempty"` // AuthTimeout is the time cluster connections have to complete authentication + URLs []string `json:"urls,omitempty"` // URLs is the list of cluster URLs + TLSTimeout float64 `json:"tls_timeout,omitempty"` // TLSTimeout is how long TLS operations have to complete + TLSRequired bool `json:"tls_required,omitempty"` // TLSRequired indicates if TLS is required for connections + TLSVerify bool `json:"tls_verify,omitempty"` // TLSVerify indicates if full verification of TLS connections is performed + PoolSize int `json:"pool_size,omitempty"` // PoolSize is the configured route connection pool size + WriteDeadline time.Duration `json:"write_deadline,omitempty"` // WriteDeadline is the maximum time writes to sockets have to complete + WriteTimeout string `json:"write_timeout,omitempty"` // WriteTimeout is the closure policy for write deadline errors + TLSCertNotAfter time.Time `json:"tls_cert_not_after,omitzero"` // TLSCertNotAfter is the expiration date of the TLS certificate } // GatewayOptsVarz contains monitoring gateway information type GatewayOptsVarz struct { - Name string `json:"name,omitempty"` - Host string `json:"host,omitempty"` - Port int `json:"port,omitempty"` - AuthTimeout float64 `json:"auth_timeout,omitempty"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - Advertise string `json:"advertise,omitempty"` - ConnectRetries int `json:"connect_retries,omitempty"` - Gateways []RemoteGatewayOptsVarz `json:"gateways,omitempty"` - RejectUnknown bool `json:"reject_unknown,omitempty"` // config got renamed to reject_unknown_cluster + Name string `json:"name,omitempty"` // Name is the configured cluster name + Host string `json:"host,omitempty"` // Host is the host the gateway listens on for connections + Port int `json:"port,omitempty"` // Port is the post gateway connections listens on + AuthTimeout float64 `json:"auth_timeout,omitempty"` // AuthTimeout is the time cluster connections have to complete authentication + TLSTimeout float64 `json:"tls_timeout,omitempty"` // TLSTimeout is how long TLS operations have to complete + TLSRequired bool `json:"tls_required,omitempty"` // TLSRequired indicates if TLS is required for connections + TLSVerify bool `json:"tls_verify,omitempty"` // TLSVerify indicates if full verification of TLS connections is performed + Advertise string `json:"advertise,omitempty"` // Advertise is the URL advertised to remote gateway clients + ConnectRetries int `json:"connect_retries,omitempty"` // ConnectRetries is how many connection attempts the route will make + Gateways []RemoteGatewayOptsVarz `json:"gateways,omitempty"` // Gateways is state of configured gateway remotes + RejectUnknown bool `json:"reject_unknown,omitempty"` // RejectUnknown indicates if unknown cluster connections will be rejected + WriteDeadline time.Duration `json:"write_deadline,omitempty"` // WriteDeadline is the maximum time writes to sockets have to complete + WriteTimeout string `json:"write_timeout,omitempty"` // WriteTimeout is the closure policy for write deadline errors + TLSCertNotAfter time.Time `json:"tls_cert_not_after,omitzero"` // TLSCertNotAfter is the expiration date of the TLS certificaet } // RemoteGatewayOptsVarz contains monitoring remote gateway information type RemoteGatewayOptsVarz struct { - Name string `json:"name"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - URLs []string `json:"urls,omitempty"` + Name string `json:"name"` // Name is the name of the remote gateway + TLSTimeout float64 `json:"tls_timeout,omitempty"` // TLSTimeout is how long TLS operations have to complete + URLs []string `json:"urls,omitempty"` // URLs is the list of Gateway URLs } // LeafNodeOptsVarz contains monitoring leaf node information type LeafNodeOptsVarz struct { - Host string `json:"host,omitempty"` - Port int `json:"port,omitempty"` - AuthTimeout float64 `json:"auth_timeout,omitempty"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - Remotes []RemoteLeafOptsVarz `json:"remotes,omitempty"` + Host string `json:"host,omitempty"` // Host is the host the server listens on + Port int `json:"port,omitempty"` // Port is the port the server listens on + AuthTimeout float64 `json:"auth_timeout,omitempty"` // AuthTimeout is the time Leafnode connections have to complete authentication + TLSTimeout float64 `json:"tls_timeout,omitempty"` // TLSTimeout is how long TLS operations have to complete + TLSRequired bool `json:"tls_required,omitempty"` // TLSRequired indicates if TLS is required for connections + TLSVerify bool `json:"tls_verify,omitempty"` // TLSVerify indicates if full verification of TLS connections is performed + Remotes []RemoteLeafOptsVarz `json:"remotes,omitempty"` // Remotes is state of configured Leafnode remotes + TLSOCSPPeerVerify bool `json:"tls_ocsp_peer_verify,omitempty"` // TLSOCSPPeerVerify indicates if OCSP verification will be performed + WriteDeadline time.Duration `json:"write_deadline,omitempty"` // WriteDeadline is the maximum time writes to sockets have to complete + WriteTimeout string `json:"write_timeout,omitempty"` // WriteTimeout is the closure policy for write deadline errors + TLSCertNotAfter time.Time `json:"tls_cert_not_after,omitzero"` // TLSCertNotAfter is the expiration date of the TLS certificate +} + +// DenyRules Contains lists of subjects not allowed to be imported/exported +type DenyRules struct { + Exports []string `json:"exports,omitempty"` // Exports are denied exports + Imports []string `json:"imports,omitempty"` // Imports are denied imports } // RemoteLeafOptsVarz contains monitoring remote leaf node information type RemoteLeafOptsVarz struct { - LocalAccount string `json:"local_account,omitempty"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - URLs []string `json:"urls,omitempty"` + LocalAccount string `json:"local_account,omitempty"` // LocalAccount is the local account this leaf is logged into + TLSTimeout float64 `json:"tls_timeout,omitempty"` // TLSTimeout is how long TLS operations have to complete + URLs []string `json:"urls,omitempty"` // URLs is the list of URLs for the remote Leafnode connection + Deny *DenyRules `json:"deny,omitempty"` // Deny is the configured import and exports that the Leafnode may not access + TLSOCSPPeerVerify bool `json:"tls_ocsp_peer_verify,omitempty"` // TLSOCSPPeerVerify indicates if OCSP verification will be done +} + +// MQTTOptsVarz contains monitoring MQTT information +type MQTTOptsVarz struct { + Host string `json:"host,omitempty"` // Host is the host the server listens on + Port int `json:"port,omitempty"` // Port is the port the server listens on + NoAuthUser string `json:"no_auth_user,omitempty"` // NoAuthUser is the user that will be used for unauthenticated connections + AuthTimeout float64 `json:"auth_timeout,omitempty"` // AuthTimeout is how long authentication has to complete + TLSMap bool `json:"tls_map,omitempty"` // TLSMap indicates if TLS Mapping is enabled + TLSTimeout float64 `json:"tls_timeout,omitempty"` // TLSTimeout is how long TLS operations have to complete + TLSPinnedCerts []string `json:"tls_pinned_certs,omitempty"` // TLSPinnedCerts is the list of certificates pinned to this connection + JsDomain string `json:"js_domain,omitempty"` // JsDomain is the JetStream domain used for MQTT state + AckWait time.Duration `json:"ack_wait,omitempty"` // AckWait is how long the internal JetStream state store will allow acks to complete + MaxAckPending uint16 `json:"max_ack_pending,omitempty"` // MaxAckPending is how many outstanding acks the internal JetStream state store will allow + TLSOCSPPeerVerify bool `json:"tls_ocsp_peer_verify,omitempty"` // TLSOCSPPeerVerify indicates if OCSP verification will be done + TLSCertNotAfter time.Time `json:"tls_cert_not_after,omitzero"` // TLSCertNotAfter is the expiration date of the TLS certificate +} + +// WebsocketOptsVarz contains monitoring websocket information +type WebsocketOptsVarz struct { + Host string `json:"host,omitempty"` // Host is the host the server listens on + Port int `json:"port,omitempty"` // Port is the port the server listens on + Advertise string `json:"advertise,omitempty"` // Advertise is the connection URL the server advertises + NoAuthUser string `json:"no_auth_user,omitempty"` // NoAuthUser is the user that will be used for unauthenticated connections + JWTCookie string `json:"jwt_cookie,omitempty"` // JWTCookie is the name of a cookie the server will read for the connection JWT + HandshakeTimeout time.Duration `json:"handshake_timeout,omitempty"` // HandshakeTimeout is how long the connection has to complete the websocket setup + AuthTimeout float64 `json:"auth_timeout,omitempty"` // AuthTimeout is how long authentication has to complete + NoTLS bool `json:"no_tls,omitempty"` // NoTLS indicates if TLS is disabled + TLSMap bool `json:"tls_map,omitempty"` // TLSMap indicates if TLS Mapping is enabled + TLSPinnedCerts []string `json:"tls_pinned_certs,omitempty"` // TLSPinnedCerts is the list of certificates pinned to this connection + SameOrigin bool `json:"same_origin,omitempty"` // SameOrigin indicates if same origin connections are allowed + AllowedOrigins []string `json:"allowed_origins,omitempty"` // AllowedOrigins list of configured trusted origins + Compression bool `json:"compression,omitempty"` // Compression indicates if compression is supported + TLSOCSPPeerVerify bool `json:"tls_ocsp_peer_verify,omitempty"` // TLSOCSPPeerVerify indicates if OCSP verification will be done + TLSCertNotAfter time.Time `json:"tls_cert_not_after,omitzero"` // TLSCertNotAfter is the expiration date of the TLS certificate +} + +// OCSPResponseCacheVarz contains OCSP response cache information +type OCSPResponseCacheVarz struct { + Type string `json:"cache_type,omitempty"` // Type is the kind of cache being used + Hits int64 `json:"cache_hits,omitempty"` // Hits is how many times the cache was able to answer a request + Misses int64 `json:"cache_misses,omitempty"` // Misses is how many times the cache failed to answer a request + Responses int64 `json:"cached_responses,omitempty"` // Responses is how many responses are currently stored in the cache + Revokes int64 `json:"cached_revoked_responses,omitempty"` // Revokes is how many of the stored cache entries are revokes + Goods int64 `json:"cached_good_responses,omitempty"` // Goods is how many of the stored cache entries are good responses + Unknowns int64 `json:"cached_unknown_responses,omitempty"` // Unknowns is how many of the stored cache entries are unknown responses } // VarzOptions are the options passed to Varz(). // Currently, there are no options defined. type VarzOptions struct{} +// SlowConsumersStats contains information about the slow consumers from different type of connections. +type SlowConsumersStats struct { + Clients uint64 `json:"clients"` // Clients is how many Clients were slow consumers + Routes uint64 `json:"routes"` // Routes is how many Routes were slow consumers + Gateways uint64 `json:"gateways"` // Gateways is how many Gateways were slow consumers + Leafs uint64 `json:"leafs"` // Leafs is how many Leafnodes were slow consumers +} + func myUptime(d time.Duration) string { // Just use total seconds for uptime, and display days / years tsecs := d / time.Second @@ -1118,6 +1413,22 @@ func myUptime(d time.Duration) string { return fmt.Sprintf("%ds", tsecs) } +func tlsCertNotAfter(config *tls.Config) time.Time { + if config == nil || len(config.Certificates) == 0 { + return time.Time{} + } + cert := config.Certificates[0] + leaf := cert.Leaf + if leaf == nil { + var err error + leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return time.Time{} + } + } + return leaf.NotAfter +} + // HandleRoot will show basic info and links to others handlers. func (s *Server) HandleRoot(w http.ResponseWriter, r *http.Request) { // This feels dumb to me, but is required: https://code.google.com/p/go/issues/detail?id=4799 @@ -1128,38 +1439,96 @@ func (s *Server) HandleRoot(w http.ResponseWriter, r *http.Request) { s.mu.Lock() s.httpReqStats[RootPath]++ s.mu.Unlock() + + // Calculate source url. If git set go directly to that tag, otherwise just main. + var srcUrl string + if gitCommit == _EMPTY_ { + srcUrl = "https://github.com/nats-io/nats-server" + } else if serverVersion != _EMPTY_ { + srcUrl = fmt.Sprintf("https://github.com/nats-io/nats-server/tree/%s", serverVersion) + } else { + srcUrl = fmt.Sprintf("https://github.com/nats-io/nats-server/tree/%s", gitCommit) + } + fmt.Fprintf(w, ` - - - - - - NATS -
- varz
- connz
- routez
- gatewayz
- leafz
- subsz
- accountz
-
- help + + + + + + + + v%s + + +
+ General %s + JetStream %s + Connections %s + Accounts %s + Account Stats %s + Subscriptions %s + Routes %s + LeafNodes %s + Gateways %s + Raft Groups %s + Health Probe %s + Expvar %s + Help `, - s.basePath(VarzPath), - s.basePath(ConnzPath), - s.basePath(RoutezPath), - s.basePath(GatewayzPath), - s.basePath(LeafzPath), - s.basePath(SubszPath), - s.basePath(AccountzPath), + srcUrl, + VERSION, + s.basePath(VarzPath), VarzPath, + s.basePath(JszPath), JszPath, + s.basePath(ConnzPath), ConnzPath, + s.basePath(AccountzPath), AccountzPath, + s.basePath(AccountStatzPath), AccountStatzPath, + s.basePath(SubszPath), SubszPath, + s.basePath(RoutezPath), RoutezPath, + s.basePath(LeafzPath), LeafzPath, + s.basePath(GatewayzPath), GatewayzPath, + s.basePath(RaftzPath), RaftzPath, + s.basePath(HealthzPath), HealthzPath, + s.basePath(ExpvarzPath), ExpvarzPath, ) } +func (s *Server) updateJszVarz(js *jetStream, v *JetStreamVarz, doConfig bool) { + if doConfig { + js.mu.RLock() + // We want to snapshot the config since it will then be available outside + // of the js lock. So make a copy first, then point to this copy. + cfg := js.config + v.Config = &cfg + js.mu.RUnlock() + } + v.Stats = js.usageStats() + v.Limits = &s.getOpts().JetStreamLimits + if mg := js.getMetaGroup(); mg != nil { + if ci := s.raftNodeToClusterInfo(mg); ci != nil { + v.Meta = &MetaClusterInfo{Name: ci.Name, Leader: ci.Leader, Peer: getHash(ci.Leader), Size: mg.ClusterSize()} + if ci.Leader == s.info.Name { + v.Meta.Replicas = ci.Replicas + } + if ipq := s.jsAPIRoutedReqs; ipq != nil { + v.Meta.Pending = ipq.len() + } + } + } +} + // Varz returns a Varz struct containing the server information. func (s *Server) Varz(varzOpts *VarzOptions) (*Varz, error) { var rss, vss int64 @@ -1168,12 +1537,16 @@ func (s *Server) Varz(varzOpts *VarzOptions) (*Varz, error) { // We want to do that outside of the lock. pse.ProcUsage(&pcpu, &rss, &vss) - s.mu.Lock() + s.mu.RLock() // We need to create a new instance of Varz (with no reference // whatsoever to anything stored in the server) since the user // has access to the returned value. v := s.createVarz(pcpu, rss) - s.mu.Unlock() + s.mu.RUnlock() + + if js := s.getJetStream(); js != nil { + s.updateJszVarz(js, &v.JetStream, true) + } return v, nil } @@ -1186,6 +1559,15 @@ func (s *Server) createVarz(pcpu float64, rss int64) *Varz { c := &opts.Cluster gw := &opts.Gateway ln := &opts.LeafNode + mqtt := &opts.MQTT + ws := &opts.Websocket + clustTlsReq := c.TLSConfig != nil + gatewayTlsReq := gw.TLSConfig != nil + leafTlsReq := ln.TLSConfig != nil + leafTlsVerify := leafTlsReq && ln.TLSConfig.ClientAuth == tls.RequireAndVerifyClientCert + leafTlsOCSPPeerVerify := s.ocspPeerVerify && leafTlsReq && ln.tlsConfigOpts.OCSPPeerConfig != nil && ln.tlsConfigOpts.OCSPPeerConfig.Verify + mqttTlsOCSPPeerVerify := s.ocspPeerVerify && mqtt.TLSConfig != nil && mqtt.tlsConfigOpts.OCSPPeerConfig != nil && mqtt.tlsConfigOpts.OCSPPeerConfig.Verify + wsTlsOCSPPeerVerify := s.ocspPeerVerify && ws.TLSConfig != nil && ws.tlsConfigOpts.OCSPPeerConfig != nil && ws.tlsConfigOpts.OCSPPeerConfig.Verify varz := &Varz{ ID: info.ID, Version: info.Version, @@ -1201,10 +1583,16 @@ func (s *Server) createVarz(pcpu float64, rss int64) *Varz { HTTPBasePath: opts.HTTPBasePath, HTTPSPort: opts.HTTPSPort, Cluster: ClusterOptsVarz{ - Name: info.Cluster, - Host: c.Host, - Port: c.Port, - AuthTimeout: c.AuthTimeout, + Name: info.Cluster, + Host: c.Host, + Port: c.Port, + AuthTimeout: c.AuthTimeout, + TLSTimeout: c.TLSTimeout, + TLSRequired: clustTlsReq, + TLSVerify: clustTlsReq, + PoolSize: opts.Cluster.PoolSize, + WriteDeadline: opts.Cluster.WriteDeadline, + WriteTimeout: opts.Cluster.WriteTimeout.String(), }, Gateway: GatewayOptsVarz{ Name: gw.Name, @@ -1212,22 +1600,69 @@ func (s *Server) createVarz(pcpu float64, rss int64) *Varz { Port: gw.Port, AuthTimeout: gw.AuthTimeout, TLSTimeout: gw.TLSTimeout, + TLSRequired: gatewayTlsReq, + TLSVerify: gatewayTlsReq, Advertise: gw.Advertise, ConnectRetries: gw.ConnectRetries, Gateways: []RemoteGatewayOptsVarz{}, RejectUnknown: gw.RejectUnknown, + WriteDeadline: opts.Cluster.WriteDeadline, + WriteTimeout: opts.Cluster.WriteTimeout.String(), }, LeafNode: LeafNodeOptsVarz{ - Host: ln.Host, - Port: ln.Port, - AuthTimeout: ln.AuthTimeout, - TLSTimeout: ln.TLSTimeout, - Remotes: []RemoteLeafOptsVarz{}, + Host: ln.Host, + Port: ln.Port, + AuthTimeout: ln.AuthTimeout, + TLSTimeout: ln.TLSTimeout, + TLSRequired: leafTlsReq, + TLSVerify: leafTlsVerify, + TLSOCSPPeerVerify: leafTlsOCSPPeerVerify, + Remotes: []RemoteLeafOptsVarz{}, + WriteDeadline: opts.Cluster.WriteDeadline, + WriteTimeout: opts.Cluster.WriteTimeout.String(), + }, + MQTT: MQTTOptsVarz{ + Host: mqtt.Host, + Port: mqtt.Port, + NoAuthUser: mqtt.NoAuthUser, + AuthTimeout: mqtt.AuthTimeout, + TLSMap: mqtt.TLSMap, + TLSTimeout: mqtt.TLSTimeout, + JsDomain: mqtt.JsDomain, + AckWait: mqtt.AckWait, + MaxAckPending: mqtt.MaxAckPending, + TLSOCSPPeerVerify: mqttTlsOCSPPeerVerify, + }, + Websocket: WebsocketOptsVarz{ + Host: ws.Host, + Port: ws.Port, + Advertise: ws.Advertise, + NoAuthUser: ws.NoAuthUser, + JWTCookie: ws.JWTCookie, + AuthTimeout: ws.AuthTimeout, + NoTLS: ws.NoTLS, + TLSMap: ws.TLSMap, + SameOrigin: ws.SameOrigin, + AllowedOrigins: copyStrings(ws.AllowedOrigins), + Compression: ws.Compression, + HandshakeTimeout: ws.HandshakeTimeout, + TLSOCSPPeerVerify: wsTlsOCSPPeerVerify, }, - Start: s.start, - MaxSubs: opts.MaxSubs, - Cores: numCores, - MaxProcs: maxProcs, + Start: s.start.UTC(), + MaxSubs: opts.MaxSubs, + Cores: runtime.NumCPU(), + MaxProcs: runtime.GOMAXPROCS(0), + Tags: opts.Tags, + TrustedOperatorsJwt: opts.operatorJWT, + TrustedOperatorsClaim: opts.TrustedOperators, + } + if mm := debug.SetMemoryLimit(-1); mm < math.MaxInt64 { + varz.MemLimit = mm + } + // If this is a leaf without cluster, reset the cluster name (that is otherwise + // set to the server name). + if s.leafNoCluster { + varz.Cluster.Name = _EMPTY_ } if len(opts.Routes) > 0 { varz.Cluster.URLs = urlsToStrings(opts.Routes) @@ -1245,25 +1680,26 @@ func (s *Server) createVarz(pcpu float64, rss int64) *Varz { if l := len(ln.Remotes); l > 0 { rlna := make([]RemoteLeafOptsVarz, l) for i, r := range ln.Remotes { + var deny *DenyRules + if len(r.DenyImports) > 0 || len(r.DenyExports) > 0 { + deny = &DenyRules{ + Imports: r.DenyImports, + Exports: r.DenyExports, + } + } + remoteTlsOCSPPeerVerify := s.ocspPeerVerify && r.tlsConfigOpts != nil && r.tlsConfigOpts.OCSPPeerConfig != nil && r.tlsConfigOpts.OCSPPeerConfig.Verify + rlna[i] = RemoteLeafOptsVarz{ - LocalAccount: r.LocalAccount, - URLs: urlsToStrings(r.URLs), - TLSTimeout: r.TLSTimeout, + LocalAccount: r.LocalAccount, + URLs: urlsToStrings(r.URLs), + TLSTimeout: r.TLSTimeout, + Deny: deny, + TLSOCSPPeerVerify: remoteTlsOCSPPeerVerify, } } varz.LeafNode.Remotes = rlna } - if s.js != nil { - s.js.mu.RLock() - varz.JetStream = JetStreamVarz{ - MaxMemory: s.js.config.MaxMemory, - MaxStore: s.js.config.MaxStore, - StoreDir: s.js.config.StoreDir, - } - s.js.mu.RUnlock() - } - // Finish setting it up with fields that can be updated during // configuration reload and runtime. s.updateVarzConfigReloadableFields(varz) @@ -1301,12 +1737,39 @@ func (s *Server) updateVarzConfigReloadableFields(v *Varz) { v.MaxPending = opts.MaxPending v.TLSTimeout = opts.TLSTimeout v.WriteDeadline = opts.WriteDeadline - v.ConfigLoadTime = s.configTime + v.WriteTimeout = opts.WriteTimeout.String() + v.ConfigLoadTime = s.configTime.UTC() + v.ConfigDigest = opts.configDigest // Update route URLs if applicable if s.varzUpdateRouteURLs { v.Cluster.URLs = urlsToStrings(opts.Routes) s.varzUpdateRouteURLs = false } + if s.sys != nil && s.sys.account != nil { + v.SystemAccount = s.sys.account.GetName() + } + v.MQTT.TLSPinnedCerts = getPinnedCertsAsSlice(opts.MQTT.TLSPinnedCerts) + v.Websocket.TLSPinnedCerts = getPinnedCertsAsSlice(opts.Websocket.TLSPinnedCerts) + + v.TLSOCSPPeerVerify = s.ocspPeerVerify && v.TLSRequired && s.opts.tlsConfigOpts != nil && s.opts.tlsConfigOpts.OCSPPeerConfig != nil && s.opts.tlsConfigOpts.OCSPPeerConfig.Verify + + v.TLSCertNotAfter = tlsCertNotAfter(opts.TLSConfig) + v.Cluster.TLSCertNotAfter = tlsCertNotAfter(opts.Cluster.TLSConfig) + v.Gateway.TLSCertNotAfter = tlsCertNotAfter(opts.Gateway.TLSConfig) + v.LeafNode.TLSCertNotAfter = tlsCertNotAfter(opts.LeafNode.TLSConfig) + v.MQTT.TLSCertNotAfter = tlsCertNotAfter(opts.MQTT.TLSConfig) + v.Websocket.TLSCertNotAfter = tlsCertNotAfter(opts.Websocket.TLSConfig) +} + +func getPinnedCertsAsSlice(certs PinnedCertSet) []string { + if len(certs) == 0 { + return nil + } + res := make([]string, 0, len(certs)) + for cn := range certs { + res = append(res, cn) + } + return res } // Updates the runtime Varz fields, that is, fields that change during @@ -1314,7 +1777,7 @@ func (s *Server) updateVarzConfigReloadableFields(v *Varz) { // is done. // Server lock is held on entry. func (s *Server) updateVarzRuntimeFields(v *Varz, forceUpdate bool, pcpu float64, rss int64) { - v.Now = time.Now() + v.Now = time.Now().UTC() v.Uptime = myUptime(time.Since(s.start)) v.Mem = rss v.CPU = pcpu @@ -1326,16 +1789,30 @@ func (s *Server) updateVarzRuntimeFields(v *Varz, forceUpdate bool, pcpu float64 } v.Connections = len(s.clients) v.TotalConnections = s.totalClients - v.Routes = len(s.routes) - v.Remotes = len(s.remotes) + v.Routes = s.numRoutes() + v.Remotes = s.numRemotes() v.Leafs = len(s.leafs) v.InMsgs = atomic.LoadInt64(&s.inMsgs) v.InBytes = atomic.LoadInt64(&s.inBytes) v.OutMsgs = atomic.LoadInt64(&s.outMsgs) v.OutBytes = atomic.LoadInt64(&s.outBytes) v.SlowConsumers = atomic.LoadInt64(&s.slowConsumers) - // FIXME(dlc) - make this multi-account aware. - v.Subscriptions = s.gacc.sl.Count() + v.SlowConsumersStats = &SlowConsumersStats{ + Clients: s.NumSlowConsumersClients(), + Routes: s.NumSlowConsumersRoutes(), + Gateways: s.NumSlowConsumersGateways(), + Leafs: s.NumSlowConsumersLeafs(), + } + v.PinnedAccountFail = atomic.LoadUint64(&s.pinnedAccFail) + + // Make sure to reset in case we are re-using. + v.Subscriptions = 0 + s.accounts.Range(func(k, val any) bool { + acc := val.(*Account) + v.Subscriptions += acc.sl.Count() + return true + }) + v.HTTPReqStats = make(map[string]uint64, len(s.httpReqStats)) for key, val := range s.httpReqStats { v.HTTPReqStats[key] = val @@ -1366,15 +1843,33 @@ func (s *Server) updateVarzRuntimeFields(v *Varz, forceUpdate bool, pcpu float64 rgw.varzUpdateURLs = false } rgw.RUnlock() + } else if g.Name == gw.name && len(gw.ownCfgURLs) > 0 { + // This is a remote that correspond to this very same server. + // We report the URLs that were configured (if any). + // Since we don't support changes to the gateway configuration + // at this time, we could do this only if g.URLs has not been already + // set, but let's do it regardless in case we add support for + // gateway config reload. + g.URLs = g.URLs[:0] + g.URLs = append(g.URLs, gw.ownCfgURLs...) } } } gw.RUnlock() - if s.js != nil { - s.js.mu.RLock() - v.JetStream.Accounts = len(s.js.accounts) - s.js.mu.RUnlock() + if s.ocsprc != nil && s.ocsprc.Type() != "none" { + stats := s.ocsprc.Stats() + if stats != nil { + v.OCSPResponseCache = &OCSPResponseCacheVarz{ + s.ocsprc.Type(), + stats.Hits, + stats.Misses, + stats.Responses, + stats.Revokes, + stats.Goods, + stats.Unknowns, + } + } } } @@ -1397,13 +1892,33 @@ func (s *Server) HandleVarz(w http.ResponseWriter, r *http.Request) { // Use server lock to create/update the server's varz object. s.mu.Lock() + var created bool s.httpReqStats[VarzPath]++ if s.varz == nil { s.varz = s.createVarz(pcpu, rss) + created = true } else { s.updateVarzRuntimeFields(s.varz, false, pcpu, rss) } s.mu.Unlock() + // Since locking is jetStream -> Server, need to update jetstream + // varz outside of server lock. + + if js := s.getJetStream(); js != nil { + var v JetStreamVarz + // Work on stack variable + s.updateJszVarz(js, &v, created) + // Now update server's varz + s.mu.RLock() + sv := &s.varz.JetStream + if created { + sv.Config = v.Config + } + sv.Stats = v.Stats + sv.Meta = v.Meta + sv.Limits = v.Limits + s.mu.RUnlock() + } // Do the marshaling outside of server lock, but under varzMu lock. b, err := json.MarshalIndent(s.varz, "", " ") @@ -1427,6 +1942,14 @@ type GatewayzOptions struct { // AccountName will limit the list of accounts to that account name (makes Accounts implicit) AccountName string `json:"account_name"` + + // AccountSubscriptions indicates if subscriptions should be included in the results. + // Note: This is used only if `Accounts` or `AccountName` are specified. + AccountSubscriptions bool `json:"subscriptions"` + + // AccountSubscriptionsDetail indicates if subscription details should be included in the results. + // Note: This is used only if `Accounts` or `AccountName` are specified. + AccountSubscriptionsDetail bool `json:"subscriptions_detail"` } // Gatewayz represents detailed information on Gateways @@ -1449,21 +1972,23 @@ type RemoteGatewayz struct { // AccountGatewayz represents interest mode for this account type AccountGatewayz struct { - Name string `json:"name"` - InterestMode string `json:"interest_mode"` - NoInterestCount int `json:"no_interest_count,omitempty"` - InterestOnlyThreshold int `json:"interest_only_threshold,omitempty"` - TotalSubscriptions int `json:"num_subs,omitempty"` - NumQueueSubscriptions int `json:"num_queue_subs,omitempty"` + Name string `json:"name"` + InterestMode string `json:"interest_mode"` + NoInterestCount int `json:"no_interest_count,omitempty"` + InterestOnlyThreshold int `json:"interest_only_threshold,omitempty"` + TotalSubscriptions int `json:"num_subs,omitempty"` + NumQueueSubscriptions int `json:"num_queue_subs,omitempty"` + Subs []string `json:"subscriptions_list,omitempty"` + SubsDetail []SubDetail `json:"subscriptions_list_detail,omitempty"` } // Gatewayz returns a Gatewayz struct containing information about gateways. func (s *Server) Gatewayz(opts *GatewayzOptions) (*Gatewayz, error) { srvID := s.ID() - now := time.Now() + now := time.Now().UTC() gw := s.gateway gw.RLock() - if !gw.enabled { + if !gw.enabled || gw.info == nil { gw.RUnlock() gwz := &Gatewayz{ ID: srvID, @@ -1555,7 +2080,7 @@ func createOutboundRemoteGatewayz(c *client, opts *GatewayzOptions, now time.Tim rgw.IsConfigured = !c.gw.cfg.isImplicit() } rgw.Connection = &ConnInfo{} - rgw.Connection.fill(c, c.nc, now) + rgw.Connection.fill(c, c.nc, now, false) name = c.gw.name } c.mu.Unlock() @@ -1580,14 +2105,14 @@ func createOutboundAccountsGatewayz(opts *GatewayzOptions, gw *gateway) []*Accou if !ok { return nil } - a := createAccountOutboundGatewayz(accName, ei) + a := createAccountOutboundGatewayz(opts, accName, ei) return []*AccountGatewayz{a} } accs := make([]*AccountGatewayz, 0, 4) - gw.outsim.Range(func(k, v interface{}) bool { + gw.outsim.Range(func(k, v any) bool { name := k.(string) - a := createAccountOutboundGatewayz(name, v) + a := createAccountOutboundGatewayz(opts, name, v) accs = append(accs, a) return true }) @@ -1595,7 +2120,7 @@ func createOutboundAccountsGatewayz(opts *GatewayzOptions, gw *gateway) []*Accou } // Returns an AccountGatewayz for this gateway outbound connection -func createAccountOutboundGatewayz(name string, ei interface{}) *AccountGatewayz { +func createAccountOutboundGatewayz(opts *GatewayzOptions, name string, ei any) *AccountGatewayz { a := &AccountGatewayz{ Name: name, InterestOnlyThreshold: gatewayMaxRUnsubBeforeSwitch, @@ -1607,6 +2132,23 @@ func createAccountOutboundGatewayz(name string, ei interface{}) *AccountGatewayz a.NoInterestCount = len(e.ni) a.NumQueueSubscriptions = e.qsubs a.TotalSubscriptions = int(e.sl.Count()) + if opts.AccountSubscriptions || opts.AccountSubscriptionsDetail { + var subsa [4096]*subscription + subs := subsa[:0] + e.sl.All(&subs) + if opts.AccountSubscriptions { + a.Subs = make([]string, 0, len(subs)) + } else { + a.SubsDetail = make([]SubDetail, 0, len(subs)) + } + for _, sub := range subs { + if opts.AccountSubscriptions { + a.Subs = append(a.Subs, string(sub.subject)) + } else { + a.SubsDetail = append(a.SubsDetail, newClientSubDetail(sub)) + } + } + } e.RUnlock() } else { a.InterestMode = Optimistic.String() @@ -1639,7 +2181,7 @@ func (s *Server) createInboundsRemoteGatewayz(opts *GatewayzOptions, now time.Ti rgw.Accounts = createInboundAccountsGatewayz(opts, c.gw) } rgw.Connection = &ConnInfo{} - rgw.Connection.fill(c, c.nc, now) + rgw.Connection.fill(c, c.nc, now, false) igws = append(igws, rgw) m[c.gw.name] = igws } @@ -1698,6 +2240,10 @@ func (s *Server) HandleGatewayz(w http.ResponseWriter, r *http.Request) { s.httpReqStats[GatewayzPath]++ s.mu.Unlock() + subs, subsDet, err := decodeSubs(w, r) + if err != nil { + return + } accs, err := decodeBool(w, r, "accs") if err != nil { return @@ -1709,9 +2255,11 @@ func (s *Server) HandleGatewayz(w http.ResponseWriter, r *http.Request) { } opts := &GatewayzOptions{ - Name: gwName, - Accounts: accs, - AccountName: accName, + Name: gwName, + Accounts: accs, + AccountName: accName, + AccountSubscriptions: subs, + AccountSubscriptionsDetail: subsDet, } gw, err := s.Gatewayz(opts) if err != nil { @@ -1745,16 +2293,20 @@ type LeafzOptions struct { // LeafInfo has detailed information on each remote leafnode connection. type LeafInfo struct { - Account string `json:"account"` - IP string `json:"ip"` - Port int `json:"port"` - RTT string `json:"rtt,omitempty"` - InMsgs int64 `json:"in_msgs"` - OutMsgs int64 `json:"out_msgs"` - InBytes int64 `json:"in_bytes"` - OutBytes int64 `json:"out_bytes"` - NumSubs uint32 `json:"subscriptions"` - Subs []string `json:"subscriptions_list,omitempty"` + ID uint64 `json:"id"` + Name string `json:"name"` + IsSpoke bool `json:"is_spoke"` + Account string `json:"account"` + IP string `json:"ip"` + Port int `json:"port"` + RTT string `json:"rtt,omitempty"` + InMsgs int64 `json:"in_msgs"` + OutMsgs int64 `json:"out_msgs"` + InBytes int64 `json:"in_bytes"` + OutBytes int64 `json:"out_bytes"` + NumSubs uint32 `json:"subscriptions"` + Subs []string `json:"subscriptions_list,omitempty"` + Compression string `json:"compression,omitempty"` } // Leafz returns a Leafz structure containing information about leafnodes. @@ -1765,7 +2317,7 @@ func (s *Server) Leafz(opts *LeafzOptions) (*Leafz, error) { if len(s.leafs) > 0 { lconns = make([]*client, 0, len(s.leafs)) for _, ln := range s.leafs { - if opts != nil && opts.Account != "" { + if opts != nil && opts.Account != _EMPTY_ { ln.mu.Lock() ok := ln.acc.Name == opts.Account ln.mu.Unlock() @@ -1778,21 +2330,25 @@ func (s *Server) Leafz(opts *LeafzOptions) (*Leafz, error) { } s.mu.Unlock() - var leafnodes []*LeafInfo + leafnodes := make([]*LeafInfo, 0, len(lconns)) + if len(lconns) > 0 { - leafnodes = make([]*LeafInfo, 0, len(lconns)) for _, ln := range lconns { ln.mu.Lock() lni := &LeafInfo{ - Account: ln.acc.Name, - IP: ln.host, - Port: int(ln.port), - RTT: ln.getRTT(), - InMsgs: atomic.LoadInt64(&ln.inMsgs), - OutMsgs: ln.outMsgs, - InBytes: atomic.LoadInt64(&ln.inBytes), - OutBytes: ln.outBytes, - NumSubs: uint32(len(ln.subs)), + ID: ln.cid, + Name: ln.leaf.remoteServer, + IsSpoke: ln.isSpokeLeafNode(), + Account: ln.acc.Name, + IP: ln.host, + Port: int(ln.port), + RTT: ln.getRTT().String(), + InMsgs: atomic.LoadInt64(&ln.inMsgs), + OutMsgs: ln.outMsgs, + InBytes: atomic.LoadInt64(&ln.inBytes), + OutBytes: ln.outBytes, + NumSubs: uint32(len(ln.subs)), + Compression: ln.leaf.compression, } if opts != nil && opts.Subscriptions { lni.Subs = make([]string, 0, len(ln.subs)) @@ -1804,9 +2360,10 @@ func (s *Server) Leafz(opts *LeafzOptions) (*Leafz, error) { leafnodes = append(leafnodes, lni) } } + return &Leafz{ ID: s.ID(), - Now: time.Now(), + Now: time.Now().UTC(), NumLeafs: len(leafnodes), Leafs: leafnodes, }, nil @@ -1837,18 +2394,97 @@ func (s *Server) HandleLeafz(w http.ResponseWriter, r *http.Request) { ResponseHandler(w, r, b) } -// ResponseHandler handles responses for monitoring routes +// Leafz represents detailed information on Leafnodes. +type AccountStatz struct { + ID string `json:"server_id"` + Now time.Time `json:"now"` + Accounts []*AccountStat `json:"account_statz"` +} + +// AccountStatzOptions are options passed to account stats requests. +type AccountStatzOptions struct { + Accounts []string `json:"accounts"` + IncludeUnused bool `json:"include_unused"` +} + +// Leafz returns a AccountStatz structure containing summary information about accounts. +func (s *Server) AccountStatz(opts *AccountStatzOptions) (*AccountStatz, error) { + stz := &AccountStatz{ + ID: s.ID(), + Now: time.Now().UTC(), + Accounts: []*AccountStat{}, + } + if opts == nil || len(opts.Accounts) == 0 { + s.accounts.Range(func(key, a any) bool { + acc := a.(*Account) + acc.mu.RLock() + if opts.IncludeUnused || acc.numLocalConnections() != 0 { + stz.Accounts = append(stz.Accounts, acc.statz()) + } + acc.mu.RUnlock() + return true + }) + } else { + for _, a := range opts.Accounts { + if acc, ok := s.accounts.Load(a); ok { + acc := acc.(*Account) + acc.mu.RLock() + if opts.IncludeUnused || acc.numLocalConnections() != 0 { + stz.Accounts = append(stz.Accounts, acc.statz()) + } + acc.mu.RUnlock() + } + } + } + return stz, nil +} + +// HandleAccountStatz process HTTP requests for statz information of all accounts. +func (s *Server) HandleAccountStatz(w http.ResponseWriter, r *http.Request) { + s.mu.Lock() + s.httpReqStats[AccountStatzPath]++ + s.mu.Unlock() + + unused, err := decodeBool(w, r, "unused") + if err != nil { + return + } + + l, err := s.AccountStatz(&AccountStatzOptions{IncludeUnused: unused}) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + b, err := json.MarshalIndent(l, "", " ") + if err != nil { + s.Errorf("Error marshaling response to %s request: %v", AccountStatzPath, err) + return + } + + // Handle response + ResponseHandler(w, r, b) +} + +// ResponseHandler handles responses for monitoring routes. func ResponseHandler(w http.ResponseWriter, r *http.Request, data []byte) { + handleResponse(http.StatusOK, w, r, data) +} + +// handleResponse handles responses for monitoring routes with a specific HTTP status code. +func handleResponse(code int, w http.ResponseWriter, r *http.Request, data []byte) { // Get callback from request callback := r.URL.Query().Get("callback") - // If callback is not empty then - if callback != "" { + if callback != _EMPTY_ { // Response for JSONP w.Header().Set("Content-Type", "application/javascript") + w.WriteHeader(code) fmt.Fprintf(w, "%s(%s)", callback, data) } else { // Otherwise JSON w.Header().Set("Content-Type", "application/json") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.WriteHeader(code) w.Write(data) } } @@ -1917,6 +2553,14 @@ func (reason ClosedState) String() string { return "Duplicate Remote LeafNode Connection" case DuplicateClientID: return "Duplicate Client ID" + case DuplicateServerName: + return "Duplicate Server Name" + case MinimumVersionRequired: + return "Minimum Version Required" + case ClusterNamesIdentical: + return "Cluster Names Identical" + case Kicked: + return "Kicked" } return "Unknown State" @@ -1933,7 +2577,7 @@ func newExtServiceLatency(l *serviceLatency) *jwt.ServiceLatency { return nil } return &jwt.ServiceLatency{ - Sampling: int(l.sampling), + Sampling: jwt.SamplingRate(l.sampling), Results: jwt.Subject(l.subject), } } @@ -1950,7 +2594,8 @@ type ExtImport struct { type ExtExport struct { jwt.Export - ApprovedAccounts []string `json:"approved_accounts,omitempty"` + ApprovedAccounts []string `json:"approved_accounts,omitempty"` + RevokedAct map[string]time.Time `json:"revoked_activations,omitempty"` } type ExtVrIssues struct { @@ -1964,6 +2609,7 @@ type ExtMap map[string][]*MapDest type AccountInfo struct { AccountName string `json:"account_name"` LastUpdate time.Time `json:"update_time,omitempty"` + IsSystem bool `json:"is_system,omitempty"` Expired bool `json:"expired"` Complete bool `json:"complete"` JetStream bool `json:"jetstream_enabled"` @@ -1974,19 +2620,22 @@ type AccountInfo struct { Exports []ExtExport `json:"exports,omitempty"` Imports []ExtImport `json:"imports,omitempty"` Jwt string `json:"jwt,omitempty"` + IssuerKey string `json:"issuer_key,omitempty"` + NameTag string `json:"name_tag,omitempty"` + Tags jwt.TagList `json:"tags,omitempty"` Claim *jwt.AccountClaims `json:"decoded_jwt,omitempty"` Vr []ExtVrIssues `json:"validation_result_jwt,omitempty"` RevokedUser map[string]time.Time `json:"revoked_user,omitempty"` - RevokedAct map[string]time.Time `json:"revoked_activations,omitempty"` Sublist *SublistStats `json:"sublist_stats,omitempty"` Responses map[string]ExtImport `json:"responses,omitempty"` } type Accountz struct { - ID string `json:"server_id"` - Now time.Time `json:"now"` - Accounts []string `json:"accounts,omitempty"` - Account *AccountInfo `json:"account_detail,omitempty"` + ID string `json:"server_id"` + Now time.Time `json:"now"` + SystemAccount string `json:"system_account,omitempty"` + Accounts []string `json:"accounts,omitempty"` + Account *AccountInfo `json:"account_detail,omitempty"` } // HandleAccountz process HTTP requests for account information. @@ -2009,21 +2658,25 @@ func (s *Server) HandleAccountz(w http.ResponseWriter, r *http.Request) { func (s *Server) Accountz(optz *AccountzOptions) (*Accountz, error) { a := &Accountz{ ID: s.ID(), - Now: time.Now(), + Now: time.Now().UTC(), } - if optz.Account == "" { + if sacc := s.SystemAccount(); sacc != nil { + a.SystemAccount = sacc.GetName() + } + if optz == nil || optz.Account == _EMPTY_ { a.Accounts = []string{} - s.accounts.Range(func(key, value interface{}) bool { + s.accounts.Range(func(key, value any) bool { a.Accounts = append(a.Accounts, key.(string)) return true }) return a, nil - } else if aInfo, err := s.accountInfo(optz.Account); err != nil { + } + aInfo, err := s.accountInfo(optz.Account) + if err != nil { return nil, err - } else { - a.Account = aInfo - return a, nil } + a.Account = aInfo + return a, nil } func newExtImport(v *serviceImport) ExtImport { @@ -2036,10 +2689,12 @@ func newExtImport(v *serviceImport) ExtImport { imp.Tracking = v.tracking imp.Invalid = v.invalid imp.Import = jwt.Import{ - Subject: jwt.Subject(v.from), + Subject: jwt.Subject(v.to), Account: v.acc.Name, Type: jwt.Service, - To: jwt.Subject(v.to), + // Deprecated so we duplicate. Use LocalSubject. + To: jwt.Subject(v.from), + LocalSubject: jwt.RenamingSubject(v.from), } imp.TrackingHdr = v.trackingHdr imp.Latency = newExtServiceLatency(v.latency) @@ -2058,10 +2713,11 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { } else { a = v.(*Account) } + isSys := a == s.SystemAccount() a.mu.RLock() defer a.mu.RUnlock() var vrIssues []ExtVrIssues - claim, _ := jwt.DecodeAccountClaims(a.claimJWT) //ignore error + claim, _ := jwt.DecodeAccountClaims(a.claimJWT) // ignore error if claim != nil { vr := jwt.ValidationResults{} claim.Validate(&vr) @@ -2070,6 +2726,17 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { vrIssues[i] = ExtVrIssues{v.Description, v.Blocking, v.TimeCheck} } } + collectRevocations := func(revocations map[string]int64) map[string]time.Time { + l := len(revocations) + if l == 0 { + return nil + } + rev := make(map[string]time.Time, l) + for k, v := range revocations { + rev[k] = time.Unix(v, 0) + } + return rev + } exports := []ExtExport{} for k, v := range a.exports.services { e := ExtExport{ @@ -2086,6 +2753,7 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { for name := range v.approved { e.ApprovedAccounts = append(e.ApprovedAccounts, name) } + e.RevokedAct = collectRevocations(v.actsRevoked) } exports = append(exports, e) } @@ -2102,6 +2770,7 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { for name := range v.approved { e.ApprovedAccounts = append(e.ApprovedAccounts, name) } + e.RevokedAct = collectRevocations(v.actsRevoked) } exports = append(exports, e) } @@ -2114,16 +2783,18 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { if v != nil { imp.Invalid = v.invalid imp.Import = jwt.Import{ - Subject: jwt.Subject(v.from), - Account: v.acc.Name, - Type: jwt.Stream, - To: jwt.Subject(v.to), + Subject: jwt.Subject(v.from), + Account: v.acc.Name, + Type: jwt.Stream, + LocalSubject: jwt.RenamingSubject(v.to), } } imports = append(imports, imp) } - for _, v := range a.imports.services { - imports = append(imports, newExtImport(v)) + for _, sis := range a.imports.services { + for _, v := range sis { + imports = append(imports, newExtImport(v)) + } } responses := map[string]ExtImport{} for k, v := range a.exports.responses { @@ -2132,7 +2803,7 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { mappings := ExtMap{} for _, m := range a.mappings { var dests []*MapDest - src := "" + var src string if m == nil { src = "nil" if _, ok := mappings[src]; ok { // only set if not present (keep orig in case nil is used) @@ -2142,7 +2813,7 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { } else { src = m.src for _, d := range m.dests { - dests = append(dests, &MapDest{d.tr.dest, d.weight, ""}) + dests = append(dests, &MapDest{d.tr.dest, d.weight, _EMPTY_}) } for c, cd := range m.cdests { for _, d := range cd { @@ -2152,31 +2823,1341 @@ func (s *Server) accountInfo(accName string) (*AccountInfo, error) { } mappings[src] = dests } - collectRevocations := func(revocations map[string]int64) map[string]time.Time { - rev := map[string]time.Time{} - for k, v := range a.usersRevoked { - rev[k] = time.Unix(v, 0) - } - return rev - } return &AccountInfo{ - accName, - a.updated, - a.expired, - !a.incomplete, - a.js != nil, - a.numLocalLeafNodes(), - a.numLocalConnections(), - a.sl.Count(), - mappings, - exports, - imports, - a.claimJWT, - claim, - vrIssues, - collectRevocations(a.usersRevoked), - collectRevocations(a.actsRevoked), - a.sl.Stats(), - responses, + AccountName: accName, + LastUpdate: a.updated.UTC(), + IsSystem: isSys, + Expired: a.expired.Load(), + Complete: !a.incomplete, + JetStream: a.js != nil, + LeafCnt: a.numLocalLeafNodes(), + ClientCnt: a.numLocalConnections(), + SubCnt: a.sl.Count(), + Mappings: mappings, + Exports: exports, + Imports: imports, + Jwt: a.claimJWT, + IssuerKey: a.Issuer, + NameTag: a.getNameTagLocked(), + Tags: a.tags, + Claim: claim, + Vr: vrIssues, + RevokedUser: collectRevocations(a.usersRevoked), + Sublist: a.sl.Stats(), + Responses: responses, }, nil } + +// JSzOptions are options passed to Jsz +type JSzOptions struct { + Account string `json:"account,omitempty"` + Accounts bool `json:"accounts,omitempty"` + Streams bool `json:"streams,omitempty"` + Consumer bool `json:"consumer,omitempty"` + DirectConsumer bool `json:"direct_consumer,omitempty"` + Config bool `json:"config,omitempty"` + LeaderOnly bool `json:"leader_only,omitempty"` + Offset int `json:"offset,omitempty"` + Limit int `json:"limit,omitempty"` + RaftGroups bool `json:"raft,omitempty"` + StreamLeaderOnly bool `json:"stream_leader_only,omitempty"` +} + +// HealthzOptions are options passed to Healthz +type HealthzOptions struct { + // Deprecated: Use JSEnabledOnly instead + JSEnabled bool `json:"js-enabled,omitempty"` + JSEnabledOnly bool `json:"js-enabled-only,omitempty"` + JSServerOnly bool `json:"js-server-only,omitempty"` + JSMetaOnly bool `json:"js-meta-only,omitempty"` + Account string `json:"account,omitempty"` + Stream string `json:"stream,omitempty"` + Consumer string `json:"consumer,omitempty"` + Details bool `json:"details,omitempty"` +} + +// ProfilezOptions are options passed to Profilez +type ProfilezOptions struct { + Name string `json:"name"` + Debug int `json:"debug"` + Duration time.Duration `json:"duration,omitempty"` +} + +// IpqueueszOptions are options passed to Ipqueuesz +type IpqueueszOptions struct { + All bool `json:"all"` + Filter string `json:"filter"` +} + +// RaftzOptions are options passed to Raftz +type RaftzOptions struct { + AccountFilter string `json:"account"` + GroupFilter string `json:"group"` +} + +// StreamDetail shows information about the stream state and its consumers. +type StreamDetail struct { + Name string `json:"name"` + Created time.Time `json:"created"` + Cluster *ClusterInfo `json:"cluster,omitempty"` + Config *StreamConfig `json:"config,omitempty"` + State StreamState `json:"state,omitempty"` + Consumer []*ConsumerInfo `json:"consumer_detail,omitempty"` + DirectConsumer []*ConsumerInfo `json:"direct_consumer_detail,omitempty"` + Mirror *StreamSourceInfo `json:"mirror,omitempty"` + Sources []*StreamSourceInfo `json:"sources,omitempty"` + RaftGroup string `json:"stream_raft_group,omitempty"` + ConsumerRaftGroups []*RaftGroupDetail `json:"consumer_raft_groups,omitempty"` +} + +// RaftGroupDetail shows information details about the Raft group. +type RaftGroupDetail struct { + Name string `json:"name"` + RaftGroup string `json:"raft_group,omitempty"` +} + +type AccountDetail struct { + Name string `json:"name"` + Id string `json:"id"` + JetStreamStats + Streams []StreamDetail `json:"stream_detail,omitempty"` +} + +// MetaSnapshotStats shows information about meta snapshots. +type MetaSnapshotStats struct { + PendingEntries uint64 `json:"pending_entries"` // PendingEntries is the count of pending entries in the meta layer + PendingSize uint64 `json:"pending_size"` // PendingSize is the size in bytes of pending entries in the meta layer + LastTime time.Time `json:"last_time,omitempty"` // LastTime is when the last meta snapshot was taken + LastDuration time.Duration `json:"last_duration,omitempty"` // LastDuration is how long the last meta snapshot took +} + +// MetaClusterInfo shows information about the meta group. +type MetaClusterInfo struct { + Name string `json:"name,omitempty"` // Name is the name of the cluster + Leader string `json:"leader,omitempty"` // Leader is the server name of the cluster leader + Peer string `json:"peer,omitempty"` // Peer is unique ID of the leader + Replicas []*PeerInfo `json:"replicas,omitempty"` // Replicas is a list of known peers + Size int `json:"cluster_size"` // Size is the known size of the cluster + Pending int `json:"pending"` // Pending is how many RAFT messages are not yet processed + Snapshot *MetaSnapshotStats `json:"snapshot"` // Snapshot contains meta snapshot statistics +} + +// JSInfo has detailed information on JetStream. +type JSInfo struct { + JetStreamStats + ID string `json:"server_id"` + Now time.Time `json:"now"` + Disabled bool `json:"disabled,omitempty"` + Config JetStreamConfig `json:"config,omitempty"` + Limits *JSLimitOpts `json:"limits,omitempty"` + Streams int `json:"streams"` + StreamsLeader int `json:"streams_leader,omitempty"` + Consumers int `json:"consumers"` + ConsumersLeader int `json:"consumers_leader,omitempty"` + Messages uint64 `json:"messages"` + Bytes uint64 `json:"bytes"` + Meta *MetaClusterInfo `json:"meta_cluster,omitempty"` + AccountDetails []*AccountDetail `json:"account_details,omitempty"` + Total int `json:"total"` +} + +func (s *Server) accountDetail(jsa *jsAccount, optStreams, optConsumers, optDirectConsumers, optCfg, optRaft, optStreamLeader bool) *AccountDetail { + jsa.mu.RLock() + acc := jsa.account + name := acc.GetName() + id := name + if acc.nameTag != _EMPTY_ { + name = acc.nameTag + } + jsa.usageMu.RLock() + totalMem, totalStore := jsa.storageTotals() + detail := AccountDetail{ + Name: name, + Id: id, + JetStreamStats: JetStreamStats{ + Memory: totalMem, + Store: totalStore, + API: JetStreamAPIStats{ + Total: jsa.apiTotal, + Errors: jsa.apiErrors, + }, + }, + Streams: make([]StreamDetail, 0, len(jsa.streams)), + } + if reserved, ok := jsa.limits[_EMPTY_]; ok { + detail.JetStreamStats.ReservedMemory = uint64(reserved.MaxMemory) + detail.JetStreamStats.ReservedStore = uint64(reserved.MaxStore) + } + jsa.usageMu.RUnlock() + + var streams []*stream + if optStreams { + for _, stream := range jsa.streams { + streams = append(streams, stream) + } + } + jsa.mu.RUnlock() + + if js := s.getJetStream(); js != nil && optStreams { + for _, stream := range streams { + rgroup := stream.raftGroup() + ci := js.clusterInfo(rgroup) + var cfg *StreamConfig + if optCfg { + c := stream.config() + cfg = &c + } + // Skip if we are only looking for stream leaders. + if optStreamLeader && ci != nil && ci.Leader != s.Name() { + continue + } + sdet := StreamDetail{ + Name: stream.name(), + Created: stream.createdTime(), + State: stream.state(), + Cluster: ci, + Config: cfg, + Mirror: stream.mirrorInfo(), + Sources: stream.sourcesInfo(), + } + if optRaft && rgroup != nil { + sdet.RaftGroup = rgroup.Name + sdet.ConsumerRaftGroups = make([]*RaftGroupDetail, 0) + } + if optConsumers { + for _, consumer := range stream.getPublicConsumers() { + cInfo := consumer.info() + if cInfo == nil { + continue + } + if !optCfg { + cInfo.Config = nil + } + sdet.Consumer = append(sdet.Consumer, cInfo) + if optRaft { + crgroup := consumer.raftGroup() + if crgroup != nil { + sdet.ConsumerRaftGroups = append(sdet.ConsumerRaftGroups, + &RaftGroupDetail{cInfo.Name, crgroup.Name}, + ) + } + } + } + if optDirectConsumers { + for _, consumer := range stream.getDirectConsumers() { + cInfo := consumer.info() + if cInfo == nil { + continue + } + if !optCfg { + cInfo.Config = nil + } + sdet.DirectConsumer = append(sdet.Consumer, cInfo) + } + } + } + detail.Streams = append(detail.Streams, sdet) + } + } + return &detail +} + +func (s *Server) JszAccount(opts *JSzOptions) (*AccountDetail, error) { + js := s.getJetStream() + if js == nil { + return nil, fmt.Errorf("jetstream not enabled") + } + acc := opts.Account + account, ok := s.accounts.Load(acc) + if !ok { + return nil, fmt.Errorf("account %q not found", acc) + } + js.mu.RLock() + jsa, ok := js.accounts[account.(*Account).Name] + js.mu.RUnlock() + if !ok { + return nil, fmt.Errorf("account %q not jetstream enabled", acc) + } + return s.accountDetail(jsa, opts.Streams, opts.Consumer, opts.DirectConsumer, opts.Config, opts.RaftGroups, opts.StreamLeaderOnly), nil +} + +// helper to get cluster info from node via dummy group +func (s *Server) raftNodeToClusterInfo(node RaftNode) *ClusterInfo { + if node == nil { + return nil + } + peers := node.Peers() + peerList := make([]string, len(peers)) + for i, p := range peers { + peerList[i] = p.ID + } + group := &raftGroup{ + Name: _EMPTY_, + Peers: peerList, + node: node, + } + return s.getJetStream().clusterInfo(group) +} + +// Jsz returns a Jsz structure containing information about JetStream. +func (s *Server) Jsz(opts *JSzOptions) (*JSInfo, error) { + // set option defaults + if opts == nil { + opts = &JSzOptions{} + } + if opts.Offset < 0 { + opts.Offset = 0 + } + if opts.Limit == 0 { + opts.Limit = 1024 + } + if opts.Consumer { + opts.Streams = true + } + if opts.Streams && opts.Account == _EMPTY_ { + opts.Accounts = true + } + + jsi := &JSInfo{ + ID: s.ID(), + Now: time.Now().UTC(), + } + + js := s.getJetStream() + if js == nil || !js.isEnabled() { + if opts.LeaderOnly { + return nil, fmt.Errorf("%w: not leader", errSkipZreq) + } + + jsi.Disabled = true + return jsi, nil + } + + jsi.Limits = &s.getOpts().JetStreamLimits + + js.mu.RLock() + isLeader := js.cluster == nil || js.cluster.isLeader() + js.mu.RUnlock() + + if opts.LeaderOnly && !isLeader { + return nil, fmt.Errorf("%w: not leader", errSkipZreq) + } + + var accounts []*jsAccount + + js.mu.RLock() + jsi.Config = js.config + for _, info := range js.accounts { + accounts = append(accounts, info) + } + js.mu.RUnlock() + + jsi.Total = len(accounts) + + if mg := js.getMetaGroup(); mg != nil { + if ci := s.raftNodeToClusterInfo(mg); ci != nil { + entries, bytes := mg.Size() + jsi.Meta = &MetaClusterInfo{Name: ci.Name, Leader: ci.Leader, Peer: getHash(ci.Leader), Size: mg.ClusterSize()} + if isLeader { + jsi.Meta.Replicas = ci.Replicas + } + if ipq := s.jsAPIRoutedReqs; ipq != nil { + jsi.Meta.Pending = ipq.len() + } + // Add meta snapshot stats + jsi.Meta.Snapshot = &MetaSnapshotStats{ + PendingEntries: entries, + PendingSize: bytes, + } + js.mu.RLock() + cluster := js.cluster + js.mu.RUnlock() + if cluster != nil { + timeNanos := atomic.LoadInt64(&cluster.lastMetaSnapTime) + durationNanos := atomic.LoadInt64(&cluster.lastMetaSnapDuration) + if timeNanos > 0 { + jsi.Meta.Snapshot.LastTime = time.Unix(0, timeNanos).UTC() + } + if durationNanos > 0 { + jsi.Meta.Snapshot.LastDuration = time.Duration(durationNanos) + } + } + } + } + + jsi.JetStreamStats = *js.usageStats() + + // If a specific account is requested, track the index. + filterIdx := -1 + + // Calculate the stats of all accounts and streams regardless of the filtering. + for i, jsa := range accounts { + if jsa.acc().GetName() == opts.Account { + filterIdx = i + } + + jsa.mu.RLock() + streams := make([]*stream, 0, len(jsa.streams)) + for _, stream := range jsa.streams { + streams = append(streams, stream) + } + jsa.mu.RUnlock() + + jsi.Streams += len(streams) + for _, stream := range streams { + streamState := stream.state() + jsi.Messages += streamState.Msgs + jsi.Bytes += streamState.Bytes + jsi.Consumers += streamState.Consumers + if opts.RaftGroups { + if node := stream.raftNode(); node == nil || node.Leader() { + jsi.StreamsLeader++ + } + for _, consumer := range stream.getPublicConsumers() { + if node := consumer.raftNode(); node == nil || node.Leader() { + jsi.ConsumersLeader++ + } + } + } + } + } + + // Targeted account takes precedence. + if filterIdx >= 0 { + accounts = accounts[filterIdx : filterIdx+1] + } else if opts.Accounts { + + if opts.Limit > 0 { + // Sort by name for a consistent read (barring any concurrent changes) + slices.SortFunc(accounts, func(i, j *jsAccount) int { return cmp.Compare(i.acc().Name, j.acc().Name) }) + + // Offset larger than the number of accounts. + offset := min(opts.Offset, len(accounts)) + accounts = accounts[offset:] + + limit := min(opts.Limit, len(accounts)) + accounts = accounts[:limit] + } + } else { + accounts = nil + } + + if len(accounts) > 0 { + jsi.AccountDetails = make([]*AccountDetail, 0, len(accounts)) + + for _, jsa := range accounts { + detail := s.accountDetail(jsa, opts.Streams, opts.Consumer, opts.DirectConsumer, opts.Config, opts.RaftGroups, opts.StreamLeaderOnly) + jsi.AccountDetails = append(jsi.AccountDetails, detail) + } + } + + return jsi, nil +} + +// HandleJsz process HTTP requests for jetstream information. +func (s *Server) HandleJsz(w http.ResponseWriter, r *http.Request) { + s.mu.Lock() + s.httpReqStats[JszPath]++ + s.mu.Unlock() + accounts, err := decodeBool(w, r, "accounts") + if err != nil { + return + } + streams, err := decodeBool(w, r, "streams") + if err != nil { + return + } + consumers, err := decodeBool(w, r, "consumers") + if err != nil { + return + } + directConsumers, err := decodeBool(w, r, "direct-consumers") + if err != nil { + return + } + config, err := decodeBool(w, r, "config") + if err != nil { + return + } + offset, err := decodeInt(w, r, "offset") + if err != nil { + return + } + limit, err := decodeInt(w, r, "limit") + if err != nil { + return + } + leader, err := decodeBool(w, r, "leader-only") + if err != nil { + return + } + rgroups, err := decodeBool(w, r, "raft") + if err != nil { + return + } + + sleader, err := decodeBool(w, r, "stream-leader-only") + if err != nil { + return + } + + l, err := s.Jsz(&JSzOptions{ + Account: r.URL.Query().Get("acc"), + Accounts: accounts, + Streams: streams, + Consumer: consumers, + DirectConsumer: directConsumers, + Config: config, + LeaderOnly: leader, + Offset: offset, + Limit: limit, + RaftGroups: rgroups, + StreamLeaderOnly: sleader, + }) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + b, err := json.MarshalIndent(l, "", " ") + if err != nil { + s.Errorf("Error marshaling response to /jsz request: %v", err) + } + + // Handle response + ResponseHandler(w, r, b) +} + +type HealthStatus struct { + Status string `json:"status"` + StatusCode int `json:"status_code,omitempty"` + Error string `json:"error,omitempty"` + Errors []HealthzError `json:"errors,omitempty"` +} + +type HealthzError struct { + Type HealthZErrorType `json:"type"` + Account string `json:"account,omitempty"` + Stream string `json:"stream,omitempty"` + Consumer string `json:"consumer,omitempty"` + Error string `json:"error,omitempty"` +} + +type HealthZErrorType int + +const ( + HealthzErrorConn HealthZErrorType = iota + HealthzErrorBadRequest + HealthzErrorJetStream + HealthzErrorAccount + HealthzErrorStream + HealthzErrorConsumer +) + +func (t HealthZErrorType) String() string { + switch t { + case HealthzErrorConn: + return "CONNECTION" + case HealthzErrorBadRequest: + return "BAD_REQUEST" + case HealthzErrorJetStream: + return "JETSTREAM" + case HealthzErrorAccount: + return "ACCOUNT" + case HealthzErrorStream: + return "STREAM" + case HealthzErrorConsumer: + return "CONSUMER" + default: + return "unknown" + } +} + +func (t HealthZErrorType) MarshalJSON() ([]byte, error) { + return json.Marshal(t.String()) +} + +func (t *HealthZErrorType) UnmarshalJSON(data []byte) error { + switch string(data) { + case `"CONNECTION"`: + *t = HealthzErrorConn + case `"BAD_REQUEST"`: + *t = HealthzErrorBadRequest + case `"JETSTREAM"`: + *t = HealthzErrorJetStream + case `"ACCOUNT"`: + *t = HealthzErrorAccount + case `"STREAM"`: + *t = HealthzErrorStream + case `"CONSUMER"`: + *t = HealthzErrorConsumer + default: + return fmt.Errorf("unknown healthz error type %q", data) + } + return nil +} + +// https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check +func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request) { + s.mu.Lock() + s.httpReqStats[HealthzPath]++ + s.mu.Unlock() + + jsEnabled, err := decodeBool(w, r, "js-enabled") + if err != nil { + return + } + if jsEnabled { + s.Warnf("Healthcheck: js-enabled deprecated, use js-enabled-only instead") + } + jsEnabledOnly, err := decodeBool(w, r, "js-enabled-only") + if err != nil { + return + } + jsServerOnly, err := decodeBool(w, r, "js-server-only") + if err != nil { + return + } + jsMetaOnly, err := decodeBool(w, r, "js-meta-only") + if err != nil { + return + } + + includeDetails, err := decodeBool(w, r, "details") + if err != nil { + return + } + + hs := s.healthz(&HealthzOptions{ + JSEnabled: jsEnabled, + JSEnabledOnly: jsEnabledOnly, + JSServerOnly: jsServerOnly, + JSMetaOnly: jsMetaOnly, + Account: r.URL.Query().Get("account"), + Stream: r.URL.Query().Get("stream"), + Consumer: r.URL.Query().Get("consumer"), + Details: includeDetails, + }) + + code := hs.StatusCode + if hs.Error != _EMPTY_ { + s.Warnf("Healthcheck failed: %q", hs.Error) + } else if len(hs.Errors) != 0 { + s.Warnf("Healthcheck failed: %d errors", len(hs.Errors)) + } + // Remove StatusCode from JSON representation when responding via HTTP + // since this is already in the response. + hs.StatusCode = 0 + b, err := json.Marshal(hs) + if err != nil { + s.Errorf("Error marshaling response to /healthz request: %v", err) + } + + handleResponse(code, w, r, b) +} + +// Generate health status. +func (s *Server) healthz(opts *HealthzOptions) *HealthStatus { + var health = &HealthStatus{Status: "ok"} + + // set option defaults + if opts == nil { + opts = &HealthzOptions{} + } + details := opts.Details + defer func() { + // for response with details enabled, set status to either "error" or "ok" + if details { + if len(health.Errors) != 0 { + health.Status = "error" + } else { + health.Status = "ok" + } + } + // if no specific status code was set, set it based on the presence of errors + if health.StatusCode == 0 { + if health.Error != _EMPTY_ || len(health.Errors) != 0 { + health.StatusCode = http.StatusServiceUnavailable + } else { + health.StatusCode = http.StatusOK + } + } + }() + + if opts.Account == _EMPTY_ && opts.Stream != _EMPTY_ { + health.StatusCode = http.StatusBadRequest + if !details { + health.Status = "error" + health.Error = fmt.Sprintf("%q must not be empty when checking stream health", "account") + } else { + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorBadRequest, + Error: fmt.Sprintf("%q must not be empty when checking stream health", "account"), + }) + } + return health + } + + if opts.Stream == _EMPTY_ && opts.Consumer != _EMPTY_ { + health.StatusCode = http.StatusBadRequest + if !details { + health.Status = "error" + health.Error = fmt.Sprintf("%q must not be empty when checking consumer health", "stream") + } else { + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorBadRequest, + Error: fmt.Sprintf("%q must not be empty when checking consumer health", "stream"), + }) + } + return health + } + + if err := s.readyForConnections(time.Millisecond); err != nil { + health.StatusCode = http.StatusInternalServerError + health.Status = "error" + if !details { + health.Error = err.Error() + } else { + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorConn, + Error: err.Error(), + }) + } + return health + } + + // If JSServerOnly is true, then do not check further accounts, streams and consumers. + if opts.JSServerOnly { + return health + } + + sopts := s.getOpts() + + // If JS is not enabled in the config, we stop. + if !sopts.JetStream { + return health + } + + // Access the Jetstream state to perform additional checks. + js := s.getJetStream() + const na = "unavailable" + if !js.isEnabled() { + health.StatusCode = http.StatusServiceUnavailable + health.Status = na + if !details { + health.Error = NewJSNotEnabledError().Error() + } else { + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorJetStream, + Error: NewJSNotEnabledError().Error(), + }) + } + return health + } + // Only check if JS is enabled, skip meta and asset check. + if opts.JSEnabledOnly || opts.JSEnabled { + return health + } + + // Clustered JetStream + js.mu.RLock() + cc := js.cluster + js.mu.RUnlock() + + // Currently single server we make sure the streams were recovered. + if cc == nil { + sdir := js.config.StoreDir + // Whip through account folders and pull each stream name. + fis, _ := os.ReadDir(sdir) + var accFound, streamFound, consumerFound bool + for _, fi := range fis { + if fi.Name() == snapStagingDir { + continue + } + if opts.Account != _EMPTY_ { + if fi.Name() != opts.Account { + continue + } + accFound = true + } + acc, err := s.LookupAccount(fi.Name()) + if err != nil { + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream account '%s' could not be resolved", fi.Name()) + return health + } + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorAccount, + Account: fi.Name(), + Error: fmt.Sprintf("JetStream account '%s' could not be resolved", fi.Name()), + }) + continue + } + sfis, _ := os.ReadDir(filepath.Join(sdir, fi.Name(), "streams")) + for _, sfi := range sfis { + if opts.Stream != _EMPTY_ { + if sfi.Name() != opts.Stream { + continue + } + streamFound = true + } + stream := sfi.Name() + s, err := acc.lookupStream(stream) + if err != nil { + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream stream '%s > %s' could not be recovered", acc, stream) + return health + } + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorStream, + Account: acc.Name, + Stream: stream, + Error: fmt.Sprintf("JetStream stream '%s > %s' could not be recovered", acc, stream), + }) + continue + } + if streamFound { + // if consumer option is passed, verify that the consumer exists on stream + if opts.Consumer != _EMPTY_ { + for _, cons := range s.consumers { + if cons.name == opts.Consumer { + consumerFound = true + break + } + } + } + break + } + } + if accFound { + break + } + } + if opts.Account != _EMPTY_ && !accFound { + health.StatusCode = http.StatusNotFound + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream account %q not found", opts.Account) + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorAccount, + Account: opts.Account, + Error: fmt.Sprintf("JetStream account %q not found", opts.Account), + }, + } + } + return health + } + if opts.Stream != _EMPTY_ && !streamFound { + health.StatusCode = http.StatusNotFound + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream stream %q not found on account %q", opts.Stream, opts.Account) + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorStream, + Account: opts.Account, + Stream: opts.Stream, + Error: fmt.Sprintf("JetStream stream %q not found on account %q", opts.Stream, opts.Account), + }, + } + } + return health + } + if opts.Consumer != _EMPTY_ && !consumerFound { + health.StatusCode = http.StatusNotFound + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream consumer %q not found for stream %q on account %q", opts.Consumer, opts.Stream, opts.Account) + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorConsumer, + Account: opts.Account, + Stream: opts.Stream, + Consumer: opts.Consumer, + Error: fmt.Sprintf("JetStream consumer %q not found for stream %q on account %q", opts.Consumer, opts.Stream, opts.Account), + }, + } + } + } + return health + } + + // If we are here we want to check for any assets assigned to us. + var meta RaftNode + js.mu.RLock() + meta = cc.meta + js.mu.RUnlock() + + // If no meta leader. + if meta == nil || meta.GroupLeader() == _EMPTY_ { + if !details { + health.Status = na + health.Error = "JetStream has not established contact with a meta leader" + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorJetStream, + Error: "JetStream has not established contact with a meta leader", + }, + } + } + return health + } + + // If we are not current with the meta leader. + if !meta.Healthy() { + if !details { + health.Status = na + health.Error = "JetStream is not current with the meta leader" + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorJetStream, + Error: "JetStream is not current with the meta leader", + }, + } + } + return health + } + + // Are we still recovering meta layer? + if js.isMetaRecovering() { + if !details { + health.Status = na + health.Error = "JetStream is still recovering meta layer" + + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorJetStream, + Error: "JetStream is still recovering meta layer", + }, + } + } + return health + } + + // Skips doing full healthz and only checks the meta leader. + if opts.JSMetaOnly { + return health + } + + // Range across all accounts, the streams assigned to them, and the consumers. + // If they are assigned to this server check their status. + ourID := meta.ID() + + // Copy the meta layer so we do not need to hold the js read lock for an extended period of time. + var streams map[string]map[string]*streamAssignment + js.mu.RLock() + if opts.Account == _EMPTY_ { + // Collect all relevant streams and consumers. + streams = make(map[string]map[string]*streamAssignment, len(cc.streams)) + for acc, asa := range cc.streams { + nasa := make(map[string]*streamAssignment) + for stream, sa := range asa { + // If we are a member and we are not being restored, select for check. + if sa.Group.isMember(ourID) && sa.Restore == nil { + csa := sa.copyGroup() + csa.consumers = make(map[string]*consumerAssignment) + for consumer, ca := range sa.consumers { + if ca.Group.isMember(ourID) { + // Use original here. Not a copy. + csa.consumers[consumer] = ca + } + } + nasa[stream] = csa + } + } + streams[acc] = nasa + } + } else { + streams = make(map[string]map[string]*streamAssignment, 1) + asa, ok := cc.streams[opts.Account] + if !ok { + health.StatusCode = http.StatusNotFound + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream account %q not found", opts.Account) + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorAccount, + Account: opts.Account, + Error: fmt.Sprintf("JetStream account %q not found", opts.Account), + }, + } + } + js.mu.RUnlock() + return health + } + nasa := make(map[string]*streamAssignment) + if opts.Stream != _EMPTY_ { + sa, ok := asa[opts.Stream] + if !ok || !sa.Group.isMember(ourID) { + health.StatusCode = http.StatusNotFound + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream stream %q not found on account %q", opts.Stream, opts.Account) + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorStream, + Account: opts.Account, + Stream: opts.Stream, + Error: fmt.Sprintf("JetStream stream %q not found on account %q", opts.Stream, opts.Account), + }, + } + } + js.mu.RUnlock() + return health + } + csa := sa.copyGroup() + csa.consumers = make(map[string]*consumerAssignment) + var consumerFound bool + for consumer, ca := range sa.consumers { + if opts.Consumer != _EMPTY_ { + if consumer != opts.Consumer || !ca.Group.isMember(ourID) { + continue + } + consumerFound = true + } + // If we are a member and we are not being restored, select for check. + if sa.Group.isMember(ourID) && sa.Restore == nil { + csa.consumers[consumer] = ca + } + if consumerFound { + break + } + } + if opts.Consumer != _EMPTY_ && !consumerFound { + health.StatusCode = http.StatusNotFound + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream consumer %q not found for stream %q on account %q", opts.Consumer, opts.Stream, opts.Account) + } else { + health.Errors = []HealthzError{ + { + Type: HealthzErrorConsumer, + Account: opts.Account, + Stream: opts.Stream, + Consumer: opts.Consumer, + Error: fmt.Sprintf("JetStream consumer %q not found for stream %q on account %q", opts.Consumer, opts.Stream, opts.Account), + }, + } + } + js.mu.RUnlock() + return health + } + nasa[opts.Stream] = csa + } else { + for stream, sa := range asa { + // If we are a member and we are not being restored, select for check. + if sa.Group.isMember(ourID) && sa.Restore == nil { + csa := sa.copyGroup() + csa.consumers = make(map[string]*consumerAssignment) + for consumer, ca := range sa.consumers { + if ca.Group.isMember(ourID) { + csa.consumers[consumer] = ca + } + } + nasa[stream] = csa + } + } + } + streams[opts.Account] = nasa + } + js.mu.RUnlock() + + // Use our copy to traverse so we do not need to hold the js lock. + for accName, asa := range streams { + acc, err := s.LookupAccount(accName) + if err != nil && len(asa) > 0 { + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream can not lookup account %q: %v", accName, err) + return health + } + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorAccount, + Account: accName, + Error: fmt.Sprintf("JetStream can not lookup account %q: %v", accName, err), + }) + continue + } + + for stream, sa := range asa { + if sa != nil && sa.unsupported != nil { + continue + } + // Make sure we can look up + if err := js.isStreamHealthy(acc, sa); err != nil { + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream stream '%s > %s' is not current: %s", accName, stream, err) + return health + } + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorStream, + Account: accName, + Stream: stream, + Error: fmt.Sprintf("JetStream stream '%s > %s' is not current: %s", accName, stream, err), + }) + continue + } + mset, _ := acc.lookupStream(stream) + // Now check consumers. + for consumer, ca := range sa.consumers { + if err := js.isConsumerHealthy(mset, consumer, ca); err != nil { + if !details { + health.Status = na + health.Error = fmt.Sprintf("JetStream consumer '%s > %s > %s' is not current: %s", acc, stream, consumer, err) + return health + } + health.Errors = append(health.Errors, HealthzError{ + Type: HealthzErrorConsumer, + Account: accName, + Stream: stream, + Consumer: consumer, + Error: fmt.Sprintf("JetStream consumer '%s > %s > %s' is not current: %s", acc, stream, consumer, err), + }) + } + } + } + } + // Success. + return health +} + +// Healthz returns the health status of the server. +func (s *Server) Healthz(opts *HealthzOptions) *HealthStatus { + return s.healthz(opts) +} + +type ExpvarzStatus struct { + Memstats json.RawMessage `json:"memstats"` + Cmdline json.RawMessage `json:"cmdline"` +} + +func (s *Server) expvarz(_ *ExpvarzEventOptions) *ExpvarzStatus { + var stat ExpvarzStatus + + const memStatsKey = "memstats" + const cmdLineKey = "cmdline" + + expvar.Do(func(v expvar.KeyValue) { + switch v.Key { + case memStatsKey: + stat.Memstats = json.RawMessage(v.Value.String()) + + case cmdLineKey: + stat.Cmdline = json.RawMessage(v.Value.String()) + } + }) + + return &stat +} + +type ProfilezStatus struct { + Profile []byte `json:"profile"` + Error string `json:"error"` +} + +func (s *Server) profilez(opts *ProfilezOptions) *ProfilezStatus { + var buffer bytes.Buffer + switch opts.Name { + case _EMPTY_: + return &ProfilezStatus{ + Error: "Profile name not specified", + } + case "cpu": + if opts.Duration <= 0 || opts.Duration > 15*time.Second { + return &ProfilezStatus{ + Error: fmt.Sprintf("Duration %s should be between 0s and 15s", opts.Duration), + } + } + if err := pprof.StartCPUProfile(&buffer); err != nil { + return &ProfilezStatus{ + Error: fmt.Sprintf("Failed to start CPU profile: %s", err), + } + } + time.Sleep(opts.Duration) + pprof.StopCPUProfile() + default: + profile := pprof.Lookup(opts.Name) + if profile == nil { + return &ProfilezStatus{ + Error: fmt.Sprintf("Profile %q not found", opts.Name), + } + } + if err := profile.WriteTo(&buffer, opts.Debug); err != nil { + return &ProfilezStatus{ + Error: fmt.Sprintf("Profile %q error: %s", opts.Name, err), + } + } + } + return &ProfilezStatus{ + Profile: buffer.Bytes(), + } +} + +type RaftzGroup struct { + ID string `json:"id"` + State string `json:"state"` + Size int `json:"size"` + QuorumNeeded int `json:"quorum_needed"` + Observer bool `json:"observer,omitempty"` + Paused bool `json:"paused,omitempty"` + Committed uint64 `json:"committed"` + Applied uint64 `json:"applied"` + CatchingUp bool `json:"catching_up,omitempty"` + Leader string `json:"leader,omitempty"` + LeaderSince *time.Time `json:"leader_since,omitempty"` + EverHadLeader bool `json:"ever_had_leader"` + Term uint64 `json:"term"` + Vote string `json:"voted_for,omitempty"` + PTerm uint64 `json:"pterm"` + PIndex uint64 `json:"pindex"` + SystemAcc bool `json:"system_account"` + TrafficAcc string `json:"traffic_account"` + IPQPropLen int `json:"ipq_proposal_len"` + IPQEntryLen int `json:"ipq_entry_len"` + IPQRespLen int `json:"ipq_resp_len"` + IPQApplyLen int `json:"ipq_apply_len"` + WAL StreamState `json:"wal"` + WALError error `json:"wal_error,omitempty"` + Peers map[string]RaftzGroupPeer `json:"peers"` +} + +type RaftzGroupPeer struct { + Name string `json:"name"` + Known bool `json:"known"` + LastReplicatedIndex uint64 `json:"last_replicated_index,omitempty"` + LastSeen string `json:"last_seen,omitempty"` +} + +type RaftzStatus map[string]map[string]RaftzGroup + +func (s *Server) HandleRaftz(w http.ResponseWriter, r *http.Request) { + if s.raftNodes == nil { + w.WriteHeader(404) + w.Write([]byte("No Raft nodes registered")) + return + } + + groups := s.Raftz(&RaftzOptions{ + AccountFilter: r.URL.Query().Get("acc"), + GroupFilter: r.URL.Query().Get("group"), + }) + + if groups == nil { + w.WriteHeader(404) + w.Write([]byte("No Raft nodes returned, check supplied filters")) + return + } + + b, _ := json.MarshalIndent(groups, "", " ") + ResponseHandler(w, r, b) +} + +func (s *Server) Raftz(opts *RaftzOptions) *RaftzStatus { + afilter, gfilter := opts.AccountFilter, opts.GroupFilter + + if afilter == _EMPTY_ { + if sys := s.SystemAccount(); sys != nil { + afilter = sys.Name + } else { + return nil + } + } + + groups := map[string]RaftNode{} + infos := RaftzStatus{} // account -> group ID + + s.rnMu.RLock() + if gfilter != _EMPTY_ { + if rg, ok := s.raftNodes[gfilter]; ok && rg != nil { + if n, ok := rg.(*raft); ok { + if n.accName == afilter { + groups[gfilter] = rg + } + } + } + } else { + for name, rg := range s.raftNodes { + if rg == nil { + continue + } + if n, ok := rg.(*raft); ok { + if n.accName != afilter { + continue + } + groups[name] = rg + } + } + } + s.rnMu.RUnlock() + + for name, rg := range groups { + n, ok := rg.(*raft) + if n == nil || !ok { + continue + } + if _, ok := infos[n.accName]; !ok { + infos[n.accName] = map[string]RaftzGroup{} + } + // Only take the lock once, using the public RaftNode functions would + // cause us to take and release the locks over and over again. + n.RLock() + info := RaftzGroup{ + ID: n.id, + State: RaftState(n.state.Load()).String(), + Size: n.csz, + QuorumNeeded: n.qn, + Observer: n.observer, + Paused: n.paused, + Committed: n.commit, + Applied: n.applied, + CatchingUp: n.catchup != nil, + Leader: n.leader, + LeaderSince: n.leaderSince.Load(), + EverHadLeader: n.pleader.Load(), + Term: n.term, + Vote: n.vote, + PTerm: n.pterm, + PIndex: n.pindex, + SystemAcc: n.IsSystemAccount(), + TrafficAcc: n.acc.GetName(), + IPQPropLen: n.prop.len(), + IPQEntryLen: n.entry.len(), + IPQRespLen: n.resp.len(), + IPQApplyLen: n.apply.len(), + WALError: n.werr, + Peers: map[string]RaftzGroupPeer{}, + } + n.wal.FastState(&info.WAL) + for id, p := range n.peers { + if id == n.id { + continue + } + peer := RaftzGroupPeer{ + Name: s.serverNameForNode(id), + Known: p.kp, + LastReplicatedIndex: p.li, + } + if !p.ts.IsZero() { + peer.LastSeen = time.Since(p.ts).String() + } + info.Peers[id] = peer + } + n.RUnlock() + infos[n.accName][name] = info + } + + return &infos +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/monitor_sort_opts.go b/vendor/github.com/nats-io/nats-server/v2/server/monitor_sort_opts.go index 10258d2..3a2a0b6 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/monitor_sort_opts.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/monitor_sort_opts.go @@ -1,4 +1,4 @@ -// Copyright 2013-2018 The NATS Authors +// Copyright 2013-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -45,7 +45,7 @@ const ( ByUptime SortOpt = "uptime" // By the amount of time connections exist ByStop SortOpt = "stop" // By the stop time for a closed connection ByReason SortOpt = "reason" // By the reason for a closed connection - + ByRTT SortOpt = "rtt" // By the round trip time ) // Individual sort options provide the Less for sort.Interface. Len and Swap are on cList. @@ -92,12 +92,13 @@ func (l byLast) Less(i, j int) bool { } // Idle time -type byIdle struct{ ConnInfos } +type byIdle struct { + ConnInfos + now time.Time +} func (l byIdle) Less(i, j int) bool { - ii := l.ConnInfos[i].LastActivity.Sub(l.ConnInfos[i].Start) - ij := l.ConnInfos[j].LastActivity.Sub(l.ConnInfos[j].Start) - return ii < ij + return l.now.Sub(l.ConnInfos[i].LastActivity) < l.now.Sub(l.ConnInfos[j].LastActivity) } // Uptime @@ -139,10 +140,15 @@ func (l byReason) Less(i, j int) bool { return l.ConnInfos[i].Reason < l.ConnInfos[j].Reason } +// RTT - Default is descending +type byRTT struct{ ConnInfos } + +func (l byRTT) Less(i, j int) bool { return l.ConnInfos[i].rtt < l.ConnInfos[j].rtt } + // IsValid determines if a sort option is valid func (s SortOpt) IsValid() bool { switch s { - case "", ByCid, ByStart, BySubs, ByPending, ByOutMsgs, ByInMsgs, ByOutBytes, ByInBytes, ByLast, ByIdle, ByUptime, ByStop, ByReason: + case _EMPTY_, ByCid, ByStart, BySubs, ByPending, ByOutMsgs, ByInMsgs, ByOutBytes, ByInBytes, ByLast, ByIdle, ByUptime, ByStop, ByReason, ByRTT: return true default: return false diff --git a/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go b/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go index b2470ff..b4d4717 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2020-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,6 +15,7 @@ package server import ( "bytes" + "cmp" "crypto/tls" "encoding/binary" "encoding/json" @@ -22,12 +23,16 @@ import ( "fmt" "io" "net" + "net/http" + "slices" "strconv" "strings" "sync" + "sync/atomic" "time" "unicode/utf8" + "github.com/nats-io/jwt/v2" "github.com/nats-io/nuid" ) @@ -66,7 +71,8 @@ const ( mqttPubFlagRetain = byte(0x01) mqttPubFlagQoS = byte(0x06) mqttPubFlagDup = byte(0x08) - mqttPubQos1 = byte(0x2) // 1 << 1 + mqttPubQos1 = byte(0x1 << 1) + mqttPubQoS2 = byte(0x2 << 1) // Subscribe flags mqttSubscribeFlags = byte(0x2) @@ -82,6 +88,7 @@ const ( mqttConnAckRCServerUnavailable = byte(0x3) mqttConnAckRCBadUserOrPassword = byte(0x4) mqttConnAckRCNotAuthorized = byte(0x5) + mqttConnAckRCQoS2WillRejected = byte(0x10) // Maximum payload size of a control packet mqttMaxPayloadSize = 0xFFFFFFF @@ -90,49 +97,155 @@ const ( mqttTopicLevelSep = '/' mqttSingleLevelWC = '+' mqttMultiLevelWC = '#' + mqttReservedPre = '$' // This is appended to the sid of a subscription that is // created on the upper level subject because of the MQTT // wildcard '#' semantic. mqttMultiLevelSidSuffix = " fwc" + // This is the prefix used for all subjects used by MQTT code. + mqttPrefix = "$MQTT." + // This is the prefix for NATS subscriptions subjects associated as delivery // subject of JS consumer. We want to make them unique so will prevent users // MQTT subscriptions to start with this. - mqttSubPrefix = "$MQTT.sub." - - // MQTT Stream names prefix. Will be used to prevent users from creating - // JS consumers on those. - mqttStreamNamePrefix = "$MQTT_" + mqttSubPrefix = mqttPrefix + "sub." // Stream name for MQTT messages on a given account - mqttStreamName = mqttStreamNamePrefix + "msgs" + mqttStreamName = "$MQTT_msgs" + mqttStreamSubjectPrefix = mqttPrefix + "msgs." // Stream name for MQTT retained messages on a given account - mqttRetainedMsgsStreamName = mqttStreamNamePrefix + "rmsgs" + mqttRetainedMsgsStreamName = "$MQTT_rmsgs" + mqttRetainedMsgsStreamSubject = mqttPrefix + "rmsgs." // Stream name for MQTT sessions on a given account - mqttSessionsStreamName = mqttStreamNamePrefix + "sessions" - - // Normally, MQTT server should not redeliver QoS 1 messages to clients, - // except after client reconnects. However, NATS Server will redeliver - // unacknowledged messages after this default interval. This can be - // changed with the server.Options.MQTT.AckWait option. + mqttSessStreamName = "$MQTT_sess" + mqttSessStreamSubjectPrefix = mqttPrefix + "sess." + + // Stream name prefix for MQTT sessions on a given account + mqttSessionsStreamNamePrefix = "$MQTT_sess_" + + // Stream name and subject for incoming MQTT QoS2 messages + mqttQoS2IncomingMsgsStreamName = "$MQTT_qos2in" + mqttQoS2IncomingMsgsStreamSubjectPrefix = mqttPrefix + "qos2.in." + + // Stream name and subjects for outgoing MQTT QoS (PUBREL) messages + mqttOutStreamName = "$MQTT_out" + mqttOutSubjectPrefix = mqttPrefix + "out." + mqttPubRelSubjectPrefix = mqttPrefix + "out.pubrel." + mqttPubRelDeliverySubjectPrefix = mqttPrefix + "deliver.pubrel." + mqttPubRelConsumerDurablePrefix = "$MQTT_PUBREL_" + + // As per spec, MQTT server may not redeliver QoS 1 and 2 messages to + // clients, except after client reconnects. However, NATS Server will + // redeliver unacknowledged messages after this default interval. This can + // be changed with the server.Options.MQTT.AckWait option. mqttDefaultAckWait = 30 * time.Second // This is the default for the outstanding number of pending QoS 1 // messages sent to a session with QoS 1 subscriptions. mqttDefaultMaxAckPending = 1024 + + // A session's list of subscriptions cannot have a cumulative MaxAckPending + // of more than this limit. + mqttMaxAckTotalLimit = 0xFFFF + + // Prefix of the reply subject for JS API requests. + mqttJSARepliesPrefix = mqttPrefix + "JSA." + + // Those are tokens that are used for the reply subject of JS API requests. + // For instance "$MQTT.JSA..SC." is the reply subject + // for a request to create a stream (where is the server name hash), + // while "$MQTT.JSA..SL." is for a stream lookup, etc... + mqttJSAIdTokenPos = 3 + mqttJSATokenPos = 4 + mqttJSAClientIDPos = 5 + mqttJSAStreamCreate = "SC" + mqttJSAStreamUpdate = "SU" + mqttJSAStreamLookup = "SL" + mqttJSAStreamDel = "SD" + mqttJSAConsumerCreate = "CC" + mqttJSAConsumerLookup = "CL" + mqttJSAConsumerDel = "CD" + mqttJSAMsgStore = "MS" + mqttJSAMsgLoad = "ML" + mqttJSAMsgDelete = "MD" + mqttJSASessPersist = "SP" + mqttJSARetainedMsgDel = "RD" + mqttJSAStreamNames = "SN" + + // This is how long to keep a client in the flappers map before closing the + // connection. This prevent quick reconnect from those clients that keep + // wanting to connect with a client ID already in use. + mqttSessFlappingJailDur = time.Second + + // This is how frequently the timer to cleanup the sessions flappers map is firing. + mqttSessFlappingCleanupInterval = 5 * time.Second + + // Default retry delay if transfer of old session streams to new one fails + mqttDefaultTransferRetry = 5 * time.Second + + // For Websocket URLs + mqttWSPath = "/mqtt" + + mqttInitialPubHeader = 16 // An overkill, should need 7 bytes max + mqttProcessSubTooLong = 100 * time.Millisecond + mqttDefaultRetainedCacheTTL = 2 * time.Minute + mqttRetainedTransferTimeout = 10 * time.Second + mqttDefaultJSAPITimeout = 5 * time.Second + mqttRetainedFlagDelMarker = '-' +) + +const ( + sparkbNBIRTH = "NBIRTH" + sparkbDBIRTH = "DBIRTH" + sparkbNDEATH = "NDEATH" + sparkbDDEATH = "DDEATH" +) + +var ( + sparkbNamespaceTopicPrefix = []byte("spBv1.0/") + sparkbCertificatesTopicPrefix = []byte("$sparkplug/certificates/") +) + +var ( + mqttPingResponse = []byte{mqttPacketPingResp, 0x0} + mqttProtoName = []byte("MQTT") + mqttOldProtoName = []byte("MQIsdp") + mqttSessJailDur = mqttSessFlappingJailDur + mqttFlapCleanItvl = mqttSessFlappingCleanupInterval + mqttRetainedCacheTTL = mqttDefaultRetainedCacheTTL ) var ( - mqttPingResponse = []byte{mqttPacketPingResp, 0x0} - mqttProtoName = []byte("MQTT") - mqttOldProtoName = []byte("MQIsdp") + errMQTTNotWebsocketPort = errors.New("MQTT clients over websocket must connect to the Websocket port, not the MQTT port") + errMQTTTopicFilterCannotBeEmpty = errors.New("topic filter cannot be empty") + errMQTTMalformedVarInt = errors.New("malformed variable int") + errMQTTSecondConnectPacket = errors.New("received a second CONNECT packet") + errMQTTServerNameMustBeSet = errors.New("mqtt requires server name to be explicitly set") + errMQTTUserMixWithUsersNKeys = errors.New("mqtt authentication username not compatible with presence of users/nkeys") + errMQTTTokenMixWIthUsersNKeys = errors.New("mqtt authentication token not compatible with presence of users/nkeys") + errMQTTAckWaitMustBePositive = errors.New("ack wait must be a positive value") + errMQTTJSAPITimeoutMustBePositive = errors.New("JS API timeout must be a positive value") + errMQTTStandaloneNeedsJetStream = errors.New("mqtt requires JetStream to be enabled if running in standalone mode") + errMQTTConnFlagReserved = errors.New("connect flags reserved bit not set to 0") + errMQTTWillAndRetainFlag = errors.New("if Will flag is set to 0, Will Retain flag must be 0 too") + errMQTTPasswordFlagAndNoUser = errors.New("password flag set but username flag is not") + errMQTTCIDEmptyNeedsCleanFlag = errors.New("when client ID is empty, clean session flag must be set to 1") + errMQTTEmptyWillTopic = errors.New("empty Will topic not allowed") + errMQTTEmptyUsername = errors.New("empty user name not allowed") + errMQTTTopicIsEmpty = errors.New("topic cannot be empty") + errMQTTPacketIdentifierIsZero = errors.New("packet identifier cannot be 0") + errMQTTUnsupportedCharacters = errors.New("character ' ' not supported for MQTT topics") + errMQTTInvalidSession = errors.New("invalid MQTT session") + errMQTTInvalidRetainFlags = errors.New("invalid retained message flags") ) type srvMQTT struct { listener net.Listener + listenerErr error authOverride bool sessmgr mqttSessionManager } @@ -143,54 +256,138 @@ type mqttSessionManager struct { } type mqttAccountSessionManager struct { - mu sync.RWMutex - sstream *Stream // stream where sessions are recorded - mstream *Stream // messages stream - rstream *Stream // retained messages stream - sessions map[string]*mqttSession // key is MQTT client ID - sl *Sublist // sublist allowing to find retained messages for given subscription - retmsgs map[string]*mqttRetainedMsg // retained messages + mu sync.RWMutex + sessions map[string]*mqttSession // key is MQTT client ID + sessByHash map[string]*mqttSession // key is MQTT client ID hash + sessLocked map[string]struct{} // key is MQTT client ID and indicate that a session can not be taken by a new client at this time + flappers map[string]int64 // When connection connects with client ID already in use + flapTimer *time.Timer // Timer to perform some cleanup of the flappers map + sl *Sublist // sublist allowing to find retained messages for given subscription + retmsgs map[string]*mqttRetainedMsgRef // retained messages + rmsCache *sync.Map // map[subject]mqttRetainedMsg + jsa mqttJSA + domainTk string // Domain (with trailing "."), or possibly empty. This is added to session subject. +} + +type mqttJSAResponse struct { + reply string // will be used to map to the original request in jsa.NewRequestExMulti + value any +} + +type mqttJSA struct { + mu sync.Mutex + id string + c *client + sendq *ipQueue[*mqttJSPubMsg] + rplyr string + replies sync.Map // [string]chan *mqttJSAResponse + nuid *nuid.NUID + quitCh chan struct{} + domain string // Domain or possibly empty. This is added to session subject. + domainSet bool // covers if domain was set, even to empty + timeout time.Duration +} + +type mqttJSPubMsg struct { + subj string + reply string + hdr int + msg []byte +} + +type mqttRetMsgDel struct { + Subject string `json:"subject"` + Seq uint64 `json:"seq"` } type mqttSession struct { - mu sync.Mutex - c *client - subs map[string]byte - cons map[string]*Consumer - stream *Stream - sseq uint64 // stream sequence where this sesion is recorded - pending map[uint16]*mqttPending // Key is the PUBLISH packet identifier sent to client and maps to a mqttPending record - cpending map[*Consumer]map[uint64]uint16 // For each JS consumer, the key is the stream sequence and maps to the PUBLISH packet identifier - ppi uint16 // publish packet identifier + // subsMu is a "quick" version of the session lock, sufficient for the QoS0 + // callback. It only guarantees that a new subscription is initialized, and + // its retained messages if any have been queued up for delivery. The QoS12 + // callback uses the session lock. + mu sync.Mutex + subsMu sync.RWMutex + + id string // client ID + idHash string // client ID hash + c *client + jsa *mqttJSA + subs map[string]byte // Key is MQTT SUBSCRIBE filter, value is the subscription QoS + cons map[string]*ConsumerConfig + pubRelConsumer *ConsumerConfig + pubRelSubscribed bool + pubRelDeliverySubject string + pubRelDeliverySubjectB []byte + pubRelSubject string + seq uint64 + + // pendingPublish maps packet identifiers (PI) to JetStream ACK subjects for + // QoS1 and 2 PUBLISH messages pending delivery to the session's client. + pendingPublish map[uint16]*mqttPending + + // pendingPubRel maps PIs to JetStream ACK subjects for QoS2 PUBREL + // messages pending delivery to the session's client. + pendingPubRel map[uint16]*mqttPending + + // cpending maps delivery attempts (that come with a JS ACK subject) to + // existing PIs. + cpending map[string]map[uint64]uint16 // composite key: jsDur, sseq + + // "Last used" publish packet identifier (PI). starting point searching for the next available. + last_pi uint16 + + // Maximum number of pending acks for this session. maxp uint16 - stalled bool + tmaxack int clean bool + domainTk string } type mqttPersistedSession struct { - ID string `json:"id,omitempty"` - Clean bool `json:"clean,omitempty"` - Subs map[string]byte `json:"subs,omitempty"` - Cons map[string]string `json:"cons,omitempty"` + Origin string `json:"origin,omitempty"` + ID string `json:"id,omitempty"` + Clean bool `json:"clean,omitempty"` + Subs map[string]byte `json:"subs,omitempty"` + Cons map[string]*ConsumerConfig `json:"cons,omitempty"` + PubRel *ConsumerConfig `json:"pubrel,omitempty"` } type mqttRetainedMsg struct { - Msg []byte `json:"msg,omitempty"` - Flags byte `json:"flags,omitempty"` - Source string `json:"source,omitempty"` + Origin string `json:"origin,omitempty"` + Subject string `json:"subject,omitempty"` + Topic string `json:"topic,omitempty"` + Msg []byte `json:"msg,omitempty"` + Flags byte `json:"flags,omitempty"` + Source string `json:"source,omitempty"` + + expiresFromCache time.Time +} - // non exported +type mqttRetainedMsgRef struct { sseq uint64 sub *subscription } +// mqttSub contains fields associated with a MQTT subscription, and is added to +// the main subscription struct for MQTT message delivery subscriptions. The +// delivery callbacks may get invoked before sub.mqtt is set up, so they should +// acquire either sess.mu or sess.subsMu before accessing it. type mqttSub struct { - qos byte - // Pending serialization of retained messages to be sent when subscription is registered - prm *mqttWriter - // This is the corresponding JS consumer. This is applicable to a subscription that is - // done for QoS > 0 (the subscription attached to a JS consumer's delivery subject). - jsCons *Consumer + // The sub's QOS and the JS durable name. They can change when + // re-subscribing, and are used in the delivery callbacks. They can be + // quickly accessed using sess.subsMu.RLock, or under the main session lock. + qos byte + jsDur string + + // Pending serialization of retained messages to be sent when subscription + // is registered. The sub's delivery callbacks must wait until `prm` is + // ready (can block on sess.mu for that, too). + prm [][]byte + + // If this subscription needs to be checked for being reserved. E.g. '#' or + // '*' or '*/'. It is set up at the time of subscription and is immutable + // after that. + reserved bool } type mqtt struct { @@ -199,20 +396,27 @@ type mqtt struct { pp *mqttPublish asm *mqttAccountSessionManager // quick reference to account session manager, immutable after processConnect() sess *mqttSession // quick reference to session, immutable after processConnect() + cid string // client ID + + // rejectQoS2Pub tells the MQTT client to not accept QoS2 PUBLISH, instead + // error and terminate the connection. + rejectQoS2Pub bool + + // downgradeQOS2Sub tells the MQTT client to downgrade QoS2 SUBSCRIBE + // requests to QoS1. + downgradeQoS2Sub bool } type mqttPending struct { - sseq uint64 // stream sequence - dseq uint64 // consumer delivery sequence - dcount uint64 // consumer delivery count - jsCons *Consumer // pointer to JS consumer (to which we will call ackMsg() on with above info) + sseq uint64 // stream sequence + jsAckSubject string // the ACK subject to send the ack to + jsDur string // JS durable name } type mqttConnectProto struct { - clientID string - rd time.Duration - will *mqttWill - flags byte + rd time.Duration + will *mqttWill + flags byte } type mqttIOReader interface { @@ -224,6 +428,8 @@ type mqttReader struct { reader mqttIOReader buf []byte pos int + pstart int + pbuf []byte } type mqttWriter struct { @@ -232,6 +438,8 @@ type mqttWriter struct { type mqttWill struct { topic []byte + subject []byte + mapped []byte message []byte qos byte retain bool @@ -240,18 +448,61 @@ type mqttWill struct { type mqttFilter struct { filter string qos byte + // Used only for tracing and should not be used after parsing of (un)sub protocols. + ttopic []byte } type mqttPublish struct { + topic []byte subject []byte + mapped []byte msg []byte sz int pi uint16 flags byte - szb [9]byte // MQTT max payload size is 268,435,455 +} + +// When we re-encode incoming MQTT PUBLISH messages for NATS delivery, we add +// the following headers: +// - "Nmqtt-Pub" (*always) indicates that the message originated from MQTT, and +// contains the original message QoS. +// - "Nmqtt-Subject" contains the original MQTT subject from mqttParsePub. +// - "Nmqtt-Mapped" contains the mapping during mqttParsePub. +// +// When we submit a PUBREL for delivery, we add a "Nmqtt-PubRel" header that +// contains the PI. +const ( + // NATS header that indicates that the message originated from MQTT and + // stores the published message QOS. + mqttNatsHeader = "Nmqtt-Pub" + + // NATS headers to store retained message metadata (along with the original + // message as binary). + mqttNatsRetainedMessageTopic = "Nmqtt-RTopic" + mqttNatsRetainedMessageOrigin = "Nmqtt-ROrigin" + mqttNatsRetainedMessageFlags = "Nmqtt-RFlags" + mqttNatsRetainedMessageSource = "Nmqtt-RSource" + + // NATS header that indicates that the message is an MQTT PubRel and stores + // the PI. + mqttNatsPubRelHeader = "Nmqtt-PubRel" + + // NATS headers to store the original MQTT subject and the subject mapping. + mqttNatsHeaderSubject = "Nmqtt-Subject" + mqttNatsHeaderMapped = "Nmqtt-Mapped" +) + +type mqttParsedPublishNATSHeader struct { + qos byte + subject []byte + mapped []byte } func (s *Server) startMQTT() { + if s.isShuttingDown() { + return + } + sopts := s.getOpts() o := &sopts.MQTT @@ -264,12 +515,9 @@ func (s *Server) startMQTT() { } hp := net.JoinHostPort(o.Host, strconv.Itoa(port)) s.mu.Lock() - if s.shutdown { - s.mu.Unlock() - return - } s.mqtt.sessmgr.sessions = make(map[string]*mqttAccountSessionManager) hl, err = net.Listen("tcp", hp) + s.mqtt.listenerErr = err if err != nil { s.mu.Unlock() s.Fatalf("Unable to listen for MQTT connections: %v", err) @@ -284,14 +532,14 @@ func (s *Server) startMQTT() { scheme = "tls" } s.Noticef("Listening for MQTT clients on %s://%s:%d", scheme, o.Host, o.Port) - go s.acceptConnections(hl, "MQTT", func(conn net.Conn) { s.createMQTTClient(conn) }, nil) + go s.acceptConnections(hl, "MQTT", func(conn net.Conn) { s.createMQTTClient(conn, nil) }, nil) s.mu.Unlock() } // This is similar to createClient() but has some modifications specifi to MQTT clients. // The comments have been kept to minimum to reduce code size. Check createClient() for // more details. -func (s *Server) createMQTTClient(conn net.Conn) *client { +func (s *Server) createMQTTClient(conn net.Conn, ws *websocket) *client { opts := s.getOpts() maxPay := int32(opts.MaxPayload) @@ -301,7 +549,12 @@ func (s *Server) createMQTTClient(conn net.Conn) *client { } now := time.Now() - c := &client{srv: s, nc: conn, mpay: maxPay, msubs: maxSubs, start: now, last: now, mqtt: &mqtt{}} + mqtt := &mqtt{ + rejectQoS2Pub: opts.MQTT.rejectQoS2Pub, + downgradeQoS2Sub: opts.MQTT.downgradeQoS2Sub, + } + c := &client{srv: s, nc: conn, mpay: maxPay, msubs: maxSubs, start: now, last: now, mqtt: mqtt, ws: ws} + c.headers = true c.mqtt.pp = &mqttPublish{} // MQTT clients don't send NATS CONNECT protocols. So make it an "echo" // client, but disable verbose and pedantic (by not setting them). @@ -324,8 +577,8 @@ func (s *Server) createMQTTClient(conn net.Conn) *client { c.mu.Unlock() s.mu.Lock() - if !s.running || s.ldm { - if s.shutdown { + if !s.isRunning() || s.ldm { + if s.isShuttingDown() { conn.Close() } s.mu.Unlock() @@ -339,15 +592,21 @@ func (s *Server) createMQTTClient(conn net.Conn) *client { } s.clients[c.cid] = c - tlsRequired := opts.MQTT.TLSConfig != nil + // Websocket TLS handshake is already done when getting to this function. + tlsRequired := opts.MQTT.TLSConfig != nil && ws == nil s.mu.Unlock() c.mu.Lock() - isClosed := c.isClosed() + // In case connection has already been closed + if c.isClosed() { + c.mu.Unlock() + c.closeConnection(WriteError) + return nil + } var pre []byte - if !isClosed && tlsRequired && opts.AllowNonTLS { + if tlsRequired && opts.AllowNonTLS { pre = make([]byte, 4) c.nc.SetReadDeadline(time.Now().Add(secondsToDuration(opts.MQTT.TLSTimeout))) n, _ := io.ReadFull(c.nc, pre[:]) @@ -360,39 +619,17 @@ func (s *Server) createMQTTClient(conn net.Conn) *client { } } - if !isClosed && tlsRequired { - c.Debugf("Starting TLS client connection handshake") + if tlsRequired { if len(pre) > 0 { c.nc = &tlsMixConn{c.nc, bytes.NewBuffer(pre)} pre = nil } - c.nc = tls.Server(c.nc, opts.MQTT.TLSConfig) - conn := c.nc.(*tls.Conn) - - ttl := secondsToDuration(opts.MQTT.TLSTimeout) - time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) - conn.SetReadDeadline(time.Now().Add(ttl)) - - c.mu.Unlock() - if err := conn.Handshake(); err != nil { - c.Errorf("TLS handshake error: %v", err) - c.closeConnection(TLSHandshakeError) + // Perform server-side TLS handshake. + if err := c.doTLSServerHandshake(tlsHandshakeMQTT, opts.MQTT.TLSConfig, opts.MQTT.TLSTimeout, opts.MQTT.TLSPinnedCerts); err != nil { + c.mu.Unlock() return nil } - conn.SetReadDeadline(time.Time{}) - - c.mu.Lock() - - c.flags.set(handshakeComplete) - - isClosed = c.isClosed() - } - - if isClosed { - c.mu.Unlock() - c.closeConnection(WriteError) - return nil } if authRequired { @@ -439,6 +676,11 @@ func validateMQTTOptions(o *Options) error { if mo.Port == 0 { return nil } + // We have to force the server name to be explicitly set and be unique when + // in cluster mode. + if o.ServerName == _EMPTY_ && (o.Cluster.Port != 0 || o.Gateway.Port != 0) { + return errMQTTServerNameMustBeSet + } // If there is a NoAuthUser, we need to have Users defined and // the user to be present. if mo.NoAuthUser != _EMPTY_ { @@ -449,14 +691,32 @@ func validateMQTTOptions(o *Options) error { // Token/Username not possible if there are users/nkeys if len(o.Users) > 0 || len(o.Nkeys) > 0 { if mo.Username != _EMPTY_ { - return fmt.Errorf("mqtt authentication username not compatible with presence of users/nkeys") + return errMQTTUserMixWithUsersNKeys } if mo.Token != _EMPTY_ { - return fmt.Errorf("mqtt authentication token not compatible with presence of users/nkeys") + return errMQTTTokenMixWIthUsersNKeys } } if mo.AckWait < 0 { - return fmt.Errorf("ack wait must be a positive value") + return errMQTTAckWaitMustBePositive + } + if mo.JSAPITimeout < 0 { + return errMQTTJSAPITimeoutMustBePositive + } + // If strictly standalone and there is no JS enabled, then it won't work... + // For leafnodes, we could either have remote(s) and it would be ok, or no + // remote but accept from a remote side that has "hub" property set, which + // then would ok too. So we fail only if we have no leafnode config at all. + if !o.JetStream && o.Cluster.Port == 0 && o.Gateway.Port == 0 && + o.LeafNode.Port == 0 && len(o.LeafNode.Remotes) == 0 { + return errMQTTStandaloneNeedsJetStream + } + if err := validatePinnedCerts(mo.TLSPinnedCerts); err != nil { + return fmt.Errorf("mqtt: %v", err) + } + if mo.ConsumerReplicas > 0 && mo.StreamReplicas > 0 && mo.ConsumerReplicas > mo.StreamReplicas { + return fmt.Errorf("mqtt: consumer_replicas (%v) cannot be higher than stream_replicas (%v)", + mo.ConsumerReplicas, mo.StreamReplicas) } return nil } @@ -467,6 +727,16 @@ func (c *client) isMqtt() bool { return c.mqtt != nil } +// If this is an MQTT client, returns the session client ID, +// otherwise returns the empty string. +// Lock held on entry +func (c *client) getMQTTClientID() string { + if !c.isMqtt() { + return _EMPTY_ + } + return c.mqtt.cid +} + // Parse protocols inside the given buffer. // This is invoked from the readLoop. func (c *client) mqttParse(buf []byte) error { @@ -483,6 +753,7 @@ func (c *client) mqttParse(buf []byte) error { r.reader.SetReadDeadline(time.Time{}) } } + hasMappings := c.in.flags.isSet(hasMappings) c.mu.Unlock() r.reset(buf) @@ -490,9 +761,13 @@ func (c *client) mqttParse(buf []byte) error { var err error var b byte var pl int + var complete bool for err == nil && r.hasMore() { + // Keep track of the starting of the packet, in case we have a partial + r.pstart = r.pos + // Read packet type and flags if b, err = r.readByte("packet type"); err != nil { break @@ -504,19 +779,60 @@ func (c *client) mqttParse(buf []byte) error { // If client was not connected yet, the first packet must be // a mqttPacketConnect otherwise we fail the connection. if !connected && pt != mqttPacketConnect { - err = errors.New("not connected") + // If the buffer indicates that it may be a websocket handshake + // but the client is not websocket, it means that the client + // connected to the MQTT port instead of the Websocket port. + if bytes.HasPrefix(buf, []byte("GET ")) && !c.isWebsocket() { + err = errMQTTNotWebsocketPort + } else { + err = fmt.Errorf("the first packet should be a CONNECT (%v), got %v", mqttPacketConnect, pt) + } break } - if pl, err = r.readPacketLen(); err != nil { + pl, complete, err = r.readPacketLen() + if err != nil || !complete { break } switch pt { + // Packets that we receive back when we act as the "sender": PUBACK, + // PUBREC, PUBCOMP. + case mqttPacketPubAck: + var pi uint16 + pi, err = mqttParsePIPacket(r) + if trace { + c.traceInOp("PUBACK", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) + } + if err == nil { + err = c.mqttProcessPubAck(pi) + } + + case mqttPacketPubRec: + var pi uint16 + pi, err = mqttParsePIPacket(r) + if trace { + c.traceInOp("PUBREC", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) + } + if err == nil { + err = c.mqttProcessPubRec(pi) + } + + case mqttPacketPubComp: + var pi uint16 + pi, err = mqttParsePIPacket(r) + if trace { + c.traceInOp("PUBCOMP", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) + } + if err == nil { + c.mqttProcessPubComp(pi) + } + + // Packets where we act as the "receiver": PUBLISH, PUBREL, SUBSCRIBE, UNSUBSCRIBE. case mqttPacketPub: pp := c.mqtt.pp pp.flags = b & mqttPacketFlagMask - err = c.mqttParsePub(r, pl, pp) + err = c.mqttParsePub(r, pl, pp, hasMappings) if trace { c.traceInOp("PUBLISH", errOrTrace(err, mqttPubTrace(pp))) if err == nil { @@ -524,57 +840,56 @@ func (c *client) mqttParse(buf []byte) error { } } if err == nil { - s.mqttProcessPub(c, pp) - if pp.pi > 0 { - c.mqttEnqueuePubAck(pp.pi) - if trace { - c.traceOutOp("PUBACK", []byte(fmt.Sprintf("pi=%v", pp.pi))) - } - } + err = s.mqttProcessPub(c, pp, trace) } - case mqttPacketPubAck: + + case mqttPacketPubRel: var pi uint16 - pi, err = mqttParsePubAck(r, pl) + pi, err = mqttParsePIPacket(r) if trace { - c.traceInOp("PUBACK", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) + c.traceInOp("PUBREL", errOrTrace(err, fmt.Sprintf("pi=%v", pi))) } if err == nil { - c.mqttProcessPubAck(pi) + err = s.mqttProcessPubRel(c, pi, trace) } + case mqttPacketSub: var pi uint16 // packet identifier var filters []*mqttFilter var subs []*subscription pi, filters, err = c.mqttParseSubs(r, b, pl) if trace { - c.traceInOp("SUBSCRIBE", errOrTrace(err, mqttSubscribeTrace(filters))) + c.traceInOp("SUBSCRIBE", errOrTrace(err, mqttSubscribeTrace(pi, filters))) } if err == nil { subs, err = c.mqttProcessSubs(filters) if err == nil && trace { - c.traceOutOp("SUBACK", []byte(mqttSubscribeTrace(filters))) + c.traceOutOp("SUBACK", []byte(fmt.Sprintf("pi=%v", pi))) } } if err == nil { c.mqttEnqueueSubAck(pi, filters) c.mqttSendRetainedMsgsToNewSubs(subs) } + case mqttPacketUnsub: var pi uint16 // packet identifier var filters []*mqttFilter pi, filters, err = c.mqttParseUnsubs(r, b, pl) if trace { - c.traceInOp("UNSUBSCRIBE", errOrTrace(err, mqttUnsubscribeTrace(filters))) + c.traceInOp("UNSUBSCRIBE", errOrTrace(err, mqttUnsubscribeTrace(pi, filters))) } if err == nil { err = c.mqttProcessUnsubs(filters) if err == nil && trace { - c.traceOutOp("UNSUBACK", []byte(strconv.FormatInt(int64(pi), 10))) + c.traceOutOp("UNSUBACK", []byte(fmt.Sprintf("pi=%v", pi))) } } if err == nil { c.mqttEnqueueUnsubAck(pi) } + + // Packets that we get both as a receiver and sender: PING, CONNECT, DISCONNECT case mqttPacketPing: if trace { c.traceInOp("PINGREQ", nil) @@ -583,16 +898,21 @@ func (c *client) mqttParse(buf []byte) error { if trace { c.traceOutOp("PINGRESP", nil) } + case mqttPacketConnect: // It is an error to receive a second connect packet if connected { - err = errors.New("second connect packet") + err = errMQTTSecondConnectPacket break } var rc byte var cp *mqttConnectProto var sessp bool - rc, cp, err = c.mqttParseConnect(r, pl) + rc, cp, err = c.mqttParseConnect(r, hasMappings) + // Add the client id to the client's string, regardless of error. + // We may still get the client_id if the call above fails somewhere + // after parsing the client ID itself. + c.ncs.Store(fmt.Sprintf("%s - %q", c, c.mqtt.cid)) if trace && cp != nil { c.traceInOp("CONNECT", errOrTrace(err, c.mqttConnectTrace(cp))) } @@ -602,11 +922,17 @@ func (c *client) mqttParse(buf []byte) error { c.traceOutOp("CONNACK", []byte(fmt.Sprintf("sp=%v rc=%v", sessp, rc))) } } else if err == nil { - if err = s.mqttProcessConnect(c, cp, trace); err == nil { + if err = s.mqttProcessConnect(c, cp, trace); err != nil { + err = fmt.Errorf("unable to connect: %v", err) + } else { + // Add this debug statement so users running in Debug mode + // will have the client id printed here for the first time. + c.Debugf("Client connected") connected = true rd = cp.rd } } + case mqttPacketDisconnect: if trace { c.traceInOp("DISCONNECT", nil) @@ -618,14 +944,10 @@ func (c *client) mqttParse(buf []byte) error { c.mqtt.cp.will = nil } c.mu.Unlock() + s.mqttHandleClosedClient(c) c.closeConnection(ClientClosed) return nil - case mqttPacketPubRec: - fallthrough - case mqttPacketPubRel: - fallthrough - case mqttPacketPubComp: - err = fmt.Errorf("protocol %d not supported", pt>>4) + default: err = fmt.Errorf("received unknown packet type %d", pt>>4) } @@ -645,53 +967,65 @@ func (c *client) mqttTraceMsg(msg []byte) { } } -// Update the session (possibly remove it) of this disconnected client. +// The MQTT client connection has been closed, or the DISCONNECT packet was received. +// For a "clean" session, we will delete the session, otherwise, simply removing +// the binding. We will also send the "will" message if applicable. +// +// Runs from the client's readLoop. +// No lock held on entry. func (s *Server) mqttHandleClosedClient(c *client) { c.mu.Lock() - cp := c.mqtt.cp - accName := c.acc.Name + asm := c.mqtt.asm + sess := c.mqtt.sess c.mu.Unlock() - if cp == nil { + + // If asm or sess are nil, it means that we have failed a client + // before it was associated with a session, so nothing more to do. + if asm == nil || sess == nil { return } - sm := &s.mqtt.sessmgr - sm.mu.RLock() - asm, ok := sm.sessions[accName] - sm.mu.RUnlock() - if !ok { + + // Add this session to the locked map for the rest of the execution. + if err := asm.lockSession(sess, c); err != nil { return } + defer asm.unlockSession(sess) asm.mu.Lock() - defer asm.mu.Unlock() - es, ok := asm.sessions[cp.clientID] - // If not found, ignore. - if !ok { - return - } - es.mu.Lock() - defer es.mu.Unlock() - // If this client is not the currently registered client, ignore. - if es.c != c { - return - } - // It the session was created with "clean session" flag, we cleanup - // when the client disconnects. - if es.clean { - es.clear() - delete(asm.sessions, cp.clientID) - } else { - // Clear the client from the session, but session stays. - es.c = nil + // Clear the client from the session, but session may stay. + sess.mu.Lock() + sess.c = nil + doClean := sess.clean + sess.mu.Unlock() + // If it was a clean session, then we remove from the account manager, + // and we will call clear() outside of any lock. + if doClean { + asm.removeSession(sess, false) + } + // Remove in case it was in the flappers map. + asm.removeSessFromFlappers(sess.id) + asm.mu.Unlock() + + // This needs to be done outside of any lock. + if doClean { + if err := sess.clear(true); err != nil { + c.Errorf(err.Error()) + } } + + // Now handle the "will". This function will be a no-op if there is no "will" to send. + s.mqttHandleWill(c) } // Updates the MaxAckPending for all MQTT sessions, updating the // JetStream consumers and updating their max ack pending and forcing // a expiration of pending messages. +// +// Runs from a server configuration reload routine. +// No lock held on entry. func (s *Server) mqttUpdateMaxAckPending(newmaxp uint16) { msm := &s.mqtt.sessmgr - s.accounts.Range(func(k, _ interface{}) bool { + s.accounts.Range(func(k, _ any) bool { accName := k.(string) msm.mu.RLock() asm := msm.sessions[accName] @@ -704,15 +1038,6 @@ func (s *Server) mqttUpdateMaxAckPending(newmaxp uint16) { for _, sess := range asm.sessions { sess.mu.Lock() sess.maxp = newmaxp - // Do not check for sess.stalled here because due to original - // consumer's maxp it is possible that the consumer was stalled - // and MQTT code did not have to stall the session. - for _, cons := range sess.cons { - cons.mu.Lock() - cons.maxp = int(newmaxp) - cons.forceExpirePending() - cons.mu.Unlock() - } sess.mu.Unlock() } asm.mu.RUnlock() @@ -720,20 +1045,77 @@ func (s *Server) mqttUpdateMaxAckPending(newmaxp uint16) { }) } -////////////////////////////////////////////////////////////////////////////// -// -// Sessions Manager related functions -// -////////////////////////////////////////////////////////////////////////////// +func (s *Server) mqttGetJSAForAccount(acc string) *mqttJSA { + sm := &s.mqtt.sessmgr + + sm.mu.RLock() + asm := sm.sessions[acc] + sm.mu.RUnlock() + + if asm == nil { + return nil + } + + asm.mu.RLock() + jsa := &asm.jsa + asm.mu.RUnlock() + return jsa +} + +func (s *Server) mqttStoreQoSMsgForAccountOnNewSubject(hdr int, msg []byte, acc, subject string) { + if s == nil || hdr <= 0 { + return + } + h := mqttParsePublishNATSHeader(msg[:hdr]) + if h == nil || h.qos == 0 { + return + } + jsa := s.mqttGetJSAForAccount(acc) + if jsa == nil { + return + } + jsa.storeMsg(mqttStreamSubjectPrefix+subject, hdr, msg) +} + +func mqttParsePublishNATSHeader(headerBytes []byte) *mqttParsedPublishNATSHeader { + if len(headerBytes) == 0 { + return nil + } + + pubValue := getHeader(mqttNatsHeader, headerBytes) + if len(pubValue) == 0 { + return nil + } + return &mqttParsedPublishNATSHeader{ + qos: pubValue[0] - '0', + subject: getHeader(mqttNatsHeaderSubject, headerBytes), + mapped: getHeader(mqttNatsHeaderMapped, headerBytes), + } +} + +func mqttParsePubRelNATSHeader(headerBytes []byte) uint16 { + if len(headerBytes) == 0 { + return 0 + } + + pubrelValue := getHeader(mqttNatsPubRelHeader, headerBytes) + if len(pubrelValue) == 0 { + return 0 + } + pi, _ := strconv.ParseUint(string(pubrelValue), 10, 16) + return uint16(pi) +} // Returns the MQTT sessions manager for a given account. // If new, creates the required JetStream streams/consumers // for handling of sessions and messages. -func (sm *mqttSessionManager) getOrCreateAccountSessionManager(clientID string, c *client) (*mqttAccountSessionManager, error) { +func (s *Server) getOrCreateMQTTAccountSessionManager(c *client) (*mqttAccountSessionManager, error) { + sm := &s.mqtt.sessmgr + c.mu.Lock() acc := c.acc - accName := acc.GetName() c.mu.Unlock() + accName := acc.GetName() sm.mu.RLock() asm, ok := sm.sessions[accName] @@ -743,6 +1125,11 @@ func (sm *mqttSessionManager) getOrCreateAccountSessionManager(clientID string, return asm, nil } + // We will pass the quitCh to the account session manager if we happen to create it. + s.mu.Lock() + quitCh := s.quitCh + s.mu.Unlock() + // Not found, now take the write lock and check again sm.mu.Lock() defer sm.mu.Unlock() @@ -750,335 +1137,2049 @@ func (sm *mqttSessionManager) getOrCreateAccountSessionManager(clientID string, if ok { return asm, nil } - // First check that we have JS enabled for this account. - // TODO: Since we check only when creating a session manager for this - // account, would probably need to do some cleanup if JS can be disabled - // on config reload. - if !acc.JetStreamEnabled() { - return nil, fmt.Errorf("JetStream must be enabled for account %q used by MQTT client ID %q", - accName, clientID) - } // Need to create one here. - asm = &mqttAccountSessionManager{sessions: make(map[string]*mqttSession)} - if err := asm.init(acc, c); err != nil { + asm, err := s.mqttCreateAccountSessionManager(acc, quitCh) + if err != nil { return nil, err } sm.sessions[accName] = asm return asm, nil } -////////////////////////////////////////////////////////////////////////////// -// -// Account Sessions Manager related functions -// -////////////////////////////////////////////////////////////////////////////// - -// Creates JS streams/consumers for handling of sessions and messages for this -// account. Note that lookup are performed in case we are in a restart -// situation and the account is loaded for the first time but had state on disk. +// Creates JS streams/consumers for handling of sessions and messages for this account. // // Global session manager lock is held on entry. -func (as *mqttAccountSessionManager) init(acc *Account, c *client) error { - opts := c.srv.getOpts() +func (s *Server) mqttCreateAccountSessionManager(acc *Account, quitCh chan struct{}) (*mqttAccountSessionManager, error) { var err error - // Start with sessions stream - as.sstream, err = acc.LookupStream(mqttSessionsStreamName) - if err != nil { - as.sstream, err = acc.AddStream(&StreamConfig{ - Subjects: []string{}, - Name: mqttSessionsStreamName, - Storage: FileStorage, - Retention: InterestPolicy, - internal: true, - allowNoSubject: true, - }) - if err != nil { - return fmt.Errorf("unable to create sessions stream for MQTT account %q: %v", acc.GetName(), err) - } - } - // Create the stream for the messages. - as.mstream, err = acc.LookupStream(mqttStreamName) - if err != nil { - as.mstream, err = acc.AddStream(&StreamConfig{ - Subjects: []string{}, - Name: mqttStreamName, - Storage: FileStorage, - Retention: InterestPolicy, - internal: true, - allowNoSubject: true, - }) - if err != nil { - return fmt.Errorf("unable to create messages stream for MQTT account %q: %v", acc.GetName(), err) - } - } - // Create the stream for retained messages. - as.rstream, err = acc.LookupStream(mqttRetainedMsgsStreamName) - if err != nil { - as.rstream, err = acc.AddStream(&StreamConfig{ - Subjects: []string{}, - Name: mqttRetainedMsgsStreamName, - Storage: FileStorage, - Retention: InterestPolicy, - internal: true, - allowNoSubject: true, - }) - if err != nil { - return fmt.Errorf("unable to create retained messages stream for MQTT account %q: %v", acc.GetName(), err) + + accName := acc.GetName() + + opts := s.getOpts() + c := s.createInternalAccountClient() + c.acc = acc + + id := s.NodeName() + + mqttJSAPITimeout := opts.MQTT.JSAPITimeout + if mqttJSAPITimeout == 0 { + mqttJSAPITimeout = mqttDefaultJSAPITimeout + } + + replicas := opts.MQTT.StreamReplicas + if replicas <= 0 { + replicas = s.mqttDetermineReplicas() + } + qname := fmt.Sprintf("[ACC:%s] MQTT ", accName) + as := &mqttAccountSessionManager{ + sessions: make(map[string]*mqttSession), + sessByHash: make(map[string]*mqttSession), + sessLocked: make(map[string]struct{}), + flappers: make(map[string]int64), + jsa: mqttJSA{ + id: id, + c: c, + rplyr: mqttJSARepliesPrefix + id + ".", + sendq: newIPQueue[*mqttJSPubMsg](s, qname+"send"), + nuid: nuid.New(), + quitCh: quitCh, + timeout: mqttJSAPITimeout, + }, + rmsCache: &sync.Map{}, + } + // TODO record domain name in as here + + // The domain to communicate with may be required for JS calls. + // Search from specific (per account setting) to generic (mqtt setting) + if opts.JsAccDefaultDomain != nil { + if d, ok := opts.JsAccDefaultDomain[accName]; ok { + if d != _EMPTY_ { + as.jsa.domain = d + } + as.jsa.domainSet = true } + // in case domain was set to empty, check if there are more generic domain overwrites } - // Now recover all sessions (in case it did already exist) - if state := as.sstream.State(); state.Msgs > 0 { - for seq := state.FirstSeq; seq <= state.LastSeq; seq++ { - _, _, content, _, err := as.sstream.store.LoadMsg(seq) - if err != nil { - if err != errDeletedMsg { - c.Errorf("Error loading session record at sequence %v: %v", seq, err) - } - continue - } - ps := &mqttPersistedSession{} - if err := json.Unmarshal(content, ps); err != nil { - c.Errorf("Error unmarshaling session record at sequence %v: %v", seq, err) - continue - } - if as.sessions == nil { - as.sessions = make(map[string]*mqttSession) - } - es, ok := as.sessions[ps.ID] - if ok && es.sseq != 0 { - as.sstream.DeleteMsg(es.sseq) - } else if !ok { - es = mqttSessionCreate(opts) - es.stream = as.sstream - as.sessions[ps.ID] = es - } - es.sseq = seq - es.clean = ps.Clean - es.subs = ps.Subs - if l := len(ps.Cons); l > 0 { - if es.cons == nil { - es.cons = make(map[string]*Consumer, l) - } - for sid, name := range ps.Cons { - if cons := as.mstream.LookupConsumer(name); cons != nil { - es.cons[sid] = cons - } - } - } + if as.jsa.domain == _EMPTY_ { + if d := opts.MQTT.JsDomain; d != _EMPTY_ { + as.jsa.domain = d + as.jsa.domainSet = true } } - // Finally, recover retained messages. - if state := as.rstream.State(); state.Msgs > 0 { - for seq := state.FirstSeq; seq <= state.LastSeq; seq++ { - subject, _, content, _, err := as.rstream.store.LoadMsg(seq) - if err != nil { - if err != errDeletedMsg { - c.Errorf("Error loading retained message at sequence %v: %v", seq, err) - } - continue - } - rm := &mqttRetainedMsg{} - if err := json.Unmarshal(content, &rm); err != nil { - c.Errorf("Error unmarshaling retained message on subject %q, sequence %v: %v", subject, seq, err) - continue - } - rm = as.handleRetainedMsg(subject, rm) - rm.sseq = seq + // We need to include the domain in the subject prefix used to store sessions in the $MQTT_sess stream. + if as.jsa.domainSet { + if as.jsa.domain != _EMPTY_ { + as.domainTk = as.jsa.domain + "." } + } else if d := s.getOpts().JetStreamDomain; d != _EMPTY_ { + as.domainTk = d + "." } - return nil -} - -// Add/Replace this message from the retained messages map. -// Returns the retained message actually stored in the map, which means that -// it may be different from the given `rm`. -// -// Account session manager lock held on entry. -func (as *mqttAccountSessionManager) handleRetainedMsg(key string, rm *mqttRetainedMsg) *mqttRetainedMsg { - if as.retmsgs == nil { - as.retmsgs = make(map[string]*mqttRetainedMsg) - as.sl = NewSublistWithCache() + if as.jsa.domainSet { + s.Noticef("Creating MQTT streams/consumers with replicas %v for account %q in domain %q", replicas, accName, as.jsa.domain) } else { - // Check if we already had one. If so, update the existing one. - if erm, exists := as.retmsgs[key]; exists { - erm.Msg = rm.Msg - erm.Flags = rm.Flags - erm.Source = rm.Source - return erm - } + s.Noticef("Creating MQTT streams/consumers with replicas %v for account %q", replicas, accName) } - rm.sub = &subscription{subject: []byte(key)} - as.retmsgs[key] = rm - as.sl.Insert(rm.sub) - return rm -} - -// Process subscriptions for the given session/client. -// -// When `fromSubProto` is false, it means that this is invoked from the CONNECT -// protocol, when restoring subscriptions that were saved for this session. -// In that case, there is no need to update the session record. -// -// When `fromSubProto` is true, it means that this call is invoked from the -// processing of the SUBSCRIBE protocol, which means that the session needs to -// be updated. It also means that if a subscription on same subject with same -// QoS already exist, we should not be recreating the subscription/JS durable, -// since it was already done when processing the CONNECT protocol. -// -// Account session manager lock held on entry. -// Session lock held when `fromSubProto` is false. -func (as *mqttAccountSessionManager) processSubs(sess *mqttSession, clientID string, c *client, - filters []*mqttFilter, fromSubProto, trace bool) ([]*subscription, error) { - if fromSubProto { - sess.mu.Lock() - defer sess.mu.Unlock() - if sess.c != c { - return nil, fmt.Errorf("client %q no longer registered with MQTT session", clientID) - } - } + var subs []*subscription + var success bool + closeCh := make(chan struct{}) - addJSConsToSess := func(sid string, cons *Consumer) { - if cons == nil { + defer func() { + if success { return } - if sess.cons == nil { - sess.cons = make(map[string]*Consumer) + for _, sub := range subs { + c.processUnsub(sub.sid) } - sess.cons[sid] = cons + close(closeCh) + }() + + // We create all subscriptions before starting the go routine that will do + // sends otherwise we could get races. + // Note that using two different clients (one for the subs, one for the + // sends) would cause other issues such as registration of recent subs in + // the "sub" client would be invisible to the check for GW routed replies + // (shouldMapReplyForGatewaySend) since the client there would be the "sender". + + jsa := &as.jsa + sid := int64(1) + // This is a subscription that will process all JS API replies. We could split to + // individual subscriptions if needed, but since there is a bit of common code, + // that seemed like a good idea to be all in one place. + if err := as.createSubscription(jsa.rplyr+">", + as.processJSAPIReplies, &sid, &subs); err != nil { + return nil, err } - setupSub := func(sub *subscription, qos byte) { - if sub.mqtt == nil { - sub.mqtt = &mqttSub{} - } - sub.mqtt.qos = qos - if fromSubProto { - as.serializeRetainedMsgsForSub(sess, c, sub, trace) - } + // We will listen for replies to session persist requests so that we can + // detect the use of a session with the same client ID anywhere in the cluster. + // `$MQTT.JSA.{js-id}.SP.{client-id-hash}.{uuid}` + if err := as.createSubscription(mqttJSARepliesPrefix+"*."+mqttJSASessPersist+".*.*", + as.processSessionPersist, &sid, &subs); err != nil { + return nil, err } - subs := make([]*subscription, 0, len(filters)) - for _, f := range filters { - if f.qos > 1 { - f.qos = 1 - } + // We create the subscription on "$MQTT.sub." to limit the subjects + // that a user would allow permissions on. + rmsubj := mqttSubPrefix + nuid.Next() + if err := as.createSubscription(rmsubj, as.processRetainedMsg, &sid, &subs); err != nil { + return nil, err + } + + // Create a subscription to be notified of retained messages delete requests. + rmdelsubj := mqttJSARepliesPrefix + "*." + mqttJSARetainedMsgDel + if err := as.createSubscription(rmdelsubj, as.processRetainedMsgDel, &sid, &subs); err != nil { + return nil, err + } + + // No more creation of subscriptions past this point otherwise RACEs may happen. + + // Start the go routine that will send JS API requests. + s.startGoRoutine(func() { + defer s.grWG.Done() + as.sendJSAPIrequests(s, c, accName, closeCh) + }) + + // Start the go routine that will clean up cached retained messages that expired. + s.startGoRoutine(func() { + defer s.grWG.Done() + as.cleanupRetainedMessageCache(s, closeCh) + }) + + lookupStream := func(stream, txt string) (*StreamInfo, error) { + si, err := jsa.lookupStream(stream) + if err != nil { + if IsNatsErr(err, JSStreamNotFoundErr) { + return nil, nil + } + return nil, fmt.Errorf("lookup %s stream for account %q: %v", txt, accName, err) + } + if opts.MQTT.StreamReplicas == 0 { + return si, nil + } + sr := 1 + if si.Cluster != nil { + sr += len(si.Cluster.Replicas) + } + if replicas != sr { + s.Warnf("MQTT %s stream replicas mismatch: current is %v but configuration is %v for '%s > %s'", + txt, sr, replicas, accName, stream) + } + return si, nil + } + + if si, err := lookupStream(mqttSessStreamName, "sessions"); err != nil { + return nil, err + } else if si == nil { + // Create the stream for the sessions. + cfg := &StreamConfig{ + Name: mqttSessStreamName, + Subjects: []string{mqttSessStreamSubjectPrefix + as.domainTk + ">"}, + Storage: FileStorage, + Retention: LimitsPolicy, + Replicas: replicas, + MaxMsgsPer: 1, + } + if _, created, err := jsa.createStream(cfg); err == nil && created { + as.transferUniqueSessStreamsToMuxed(s) + } else if isErrorOtherThan(err, JSStreamNameExistErr) { + return nil, fmt.Errorf("create sessions stream for account %q: %v", accName, err) + } + } + + if si, err := lookupStream(mqttStreamName, "messages"); err != nil { + return nil, err + } else if si == nil { + // Create the stream for the messages. + cfg := &StreamConfig{ + Name: mqttStreamName, + Subjects: []string{mqttStreamSubjectPrefix + ">"}, + Storage: FileStorage, + Retention: InterestPolicy, + Replicas: replicas, + } + if _, _, err := jsa.createStream(cfg); isErrorOtherThan(err, JSStreamNameExistErr) { + return nil, fmt.Errorf("create messages stream for account %q: %v", accName, err) + } + } + + if si, err := lookupStream(mqttQoS2IncomingMsgsStreamName, "QoS2 incoming messages"); err != nil { + return nil, err + } else if si == nil { + // Create the stream for the incoming QoS2 messages that have not been + // PUBREL-ed by the sender. Subject is + // "$MQTT.qos2..", the .PI is to achieve exactly + // once for each PI. + cfg := &StreamConfig{ + Name: mqttQoS2IncomingMsgsStreamName, + Subjects: []string{mqttQoS2IncomingMsgsStreamSubjectPrefix + ">"}, + Storage: FileStorage, + Retention: LimitsPolicy, + Discard: DiscardNew, + MaxMsgsPer: 1, + DiscardNewPer: true, + Replicas: replicas, + } + if _, _, err := jsa.createStream(cfg); isErrorOtherThan(err, JSStreamNameExistErr) { + return nil, fmt.Errorf("create QoS2 incoming messages stream for account %q: %v", accName, err) + } + } + + if si, err := lookupStream(mqttOutStreamName, "QoS2 outgoing PUBREL"); err != nil { + return nil, err + } else if si == nil { + // Create the stream for the incoming QoS2 messages that have not been + // PUBREL-ed by the sender. NATS messages are submitted as + // "$MQTT.pubrel." + cfg := &StreamConfig{ + Name: mqttOutStreamName, + Subjects: []string{mqttOutSubjectPrefix + ">"}, + Storage: FileStorage, + Retention: InterestPolicy, + Replicas: replicas, + } + if _, _, err := jsa.createStream(cfg); isErrorOtherThan(err, JSStreamNameExistErr) { + return nil, fmt.Errorf("create QoS2 outgoing PUBREL stream for account %q: %v", accName, err) + } + } + + // This is the only case where we need "si" after lookup/create + needToTransfer := true + si, err := lookupStream(mqttRetainedMsgsStreamName, "retained messages") + switch { + case err != nil: + return nil, err + + case si == nil: + // Create the stream for retained messages. + cfg := &StreamConfig{ + Name: mqttRetainedMsgsStreamName, + Subjects: []string{mqttRetainedMsgsStreamSubject + ">"}, + Storage: FileStorage, + Retention: LimitsPolicy, + Replicas: replicas, + MaxMsgsPer: 1, + } + // We will need "si" outside of this block. + si, _, err = jsa.createStream(cfg) + if err != nil { + if isErrorOtherThan(err, JSStreamNameExistErr) { + return nil, fmt.Errorf("create retained messages stream for account %q: %v", accName, err) + } + // Suppose we had a race and the stream was actually created by another + // node, we really need "si" after that, so lookup the stream again here. + si, err = lookupStream(mqttRetainedMsgsStreamName, "retained messages") + if err != nil { + return nil, err + } + } + needToTransfer = false + + default: + needToTransfer = si.Config.MaxMsgsPer != 1 + } + + // Doing this check outside of above if/else due to possible race when + // creating the stream. + wantedSubj := mqttRetainedMsgsStreamSubject + ">" + if len(si.Config.Subjects) != 1 || si.Config.Subjects[0] != wantedSubj { + // Update only the Subjects at this stage, not MaxMsgsPer yet. + si.Config.Subjects = []string{wantedSubj} + if si, err = jsa.updateStream(&si.Config); err != nil { + return nil, fmt.Errorf("failed to update stream config: %w", err) + } + } + + transferRMS := func() error { + if !needToTransfer { + return nil + } + + as.transferRetainedToPerKeySubjectStream(s) + + // We need another lookup to have up-to-date si.State values in order + // to load all retained messages. + si, err = lookupStream(mqttRetainedMsgsStreamName, "retained messages") + if err != nil { + return err + } + needToTransfer = false + return nil + } + + // Attempt to transfer all "single subject" retained messages to new + // subjects. It may fail, will log its own error; ignore it the first time + // and proceed to updating MaxMsgsPer. Then we invoke transferRMS() again, + // which will get another chance to resolve the error; if not we bail there. + if err = transferRMS(); err != nil { + return nil, err + } + + // Now, if the stream does not have MaxMsgsPer set to 1, and there are no + // more messages on the single $MQTT.rmsgs subject, update the stream again. + if si.Config.MaxMsgsPer != 1 { + si.Config.MaxMsgsPer = 1 + // We will need an up-to-date si, so don't use local variable here. + if si, err = jsa.updateStream(&si.Config); err != nil { + return nil, fmt.Errorf("failed to update stream config: %w", err) + } + } + + // If we failed the first time, there is now at most one lingering message + // in the old subject. Try again (it will be a NO-OP if succeeded the first + // time). + if err = transferRMS(); err != nil { + return nil, err + } + + // Opportunistically delete the old (legacy) consumer, from v2.10.10 and + // before. Ignore any errors that might arise. + rmLegacyDurName := mqttRetainedMsgsStreamName + "_" + jsa.id + jsa.deleteConsumer(mqttRetainedMsgsStreamName, rmLegacyDurName, true) + + // Create a new, uniquely names consumer for retained messages for this + // server. The prior one will expire eventually. + ccfg := &CreateConsumerRequest{ + Stream: mqttRetainedMsgsStreamName, + Config: ConsumerConfig{ + Name: mqttRetainedMsgsStreamName + "_" + nuid.Next(), + FilterSubject: mqttRetainedMsgsStreamSubject + ">", + DeliverSubject: rmsubj, + ReplayPolicy: ReplayInstant, + AckPolicy: AckNone, + InactiveThreshold: 5 * time.Minute, + }, + } + if _, err := jsa.createEphemeralConsumer(ccfg); err != nil { + return nil, fmt.Errorf("create retained messages consumer for account %q: %v", accName, err) + } + + // Set this so that on defer we don't cleanup. + success = true + + return as, nil +} + +func (s *Server) mqttDetermineReplicas() int { + // If not clustered, then replica will be 1. + if !s.JetStreamIsClustered() { + return 1 + } + opts := s.getOpts() + replicas := 0 + for _, u := range opts.Routes { + host := u.Hostname() + // If this is an IP just add one. + if net.ParseIP(host) != nil { + replicas++ + } else { + addrs, _ := net.LookupHost(host) + replicas += len(addrs) + } + } + if replicas < 1 { + replicas = 1 + } else if replicas > 3 { + replicas = 3 + } + return replicas +} + +////////////////////////////////////////////////////////////////////////////// +// +// JS APIs related functions +// +////////////////////////////////////////////////////////////////////////////// + +func (jsa *mqttJSA) newRequest(kind, subject string, hdr int, msg []byte) (any, error) { + return jsa.newRequestEx(kind, subject, _EMPTY_, hdr, msg) +} + +func (jsa *mqttJSA) prefixDomain(subject string) string { + if jsa.domain != _EMPTY_ { + // rewrite js api prefix with domain + if sub := strings.TrimPrefix(subject, JSApiPrefix+"."); sub != subject { + subject = fmt.Sprintf("$JS.%s.API.%s", jsa.domain, sub) + } + } + return subject +} + +func (jsa *mqttJSA) newRequestEx(kind, subject, cidHash string, hdr int, msg []byte) (any, error) { + responses, err := jsa.newRequestExMulti(kind, subject, cidHash, []int{hdr}, [][]byte{msg}) + if err != nil { + return nil, err + } + if len(responses) != 1 { + return nil, fmt.Errorf("unreachable: invalid number of responses (%d)", len(responses)) + } + return responses[0].value, nil +} + +// newRequestExMulti sends multiple messages on the same subject and waits for +// all responses. It returns the same number of responses in the same order as +// msgs parameter. In case of a timeout it returns an error as well as all +// responses received as a sparsely populated array, matching msgs, with nils +// for the values that have not yet been received. +// +// Note that each response may represent an error and should be inspected as +// such by the caller. +func (jsa *mqttJSA) newRequestExMulti(kind, subject, cidHash string, hdrs []int, msgs [][]byte) ([]*mqttJSAResponse, error) { + if len(hdrs) != len(msgs) { + return nil, fmt.Errorf("unreachable: invalid number of messages (%d) or header offsets (%d)", len(msgs), len(hdrs)) + } + responseCh := make(chan *mqttJSAResponse, len(msgs)) + + // Generate and queue all outgoing requests, have all results reported to + // responseCh, and store a map of reply subjects to the original subjects' + // indices. + r2i := map[string]int{} + for i, msg := range msgs { + hdr := hdrs[i] + var sb strings.Builder + // Either we use nuid.Next() which uses a global lock, or our own nuid object, but + // then it needs to be "write" protected. This approach will reduce across account + // contention since we won't use the global nuid's lock. + jsa.mu.Lock() + uid := jsa.nuid.Next() + sb.WriteString(jsa.rplyr) + jsa.mu.Unlock() + + sb.WriteString(kind) + sb.WriteByte(btsep) + if cidHash != _EMPTY_ { + sb.WriteString(cidHash) + sb.WriteByte(btsep) + } + sb.WriteString(uid) + reply := sb.String() + + // Add responseCh to the reply channel map. It will be cleaned out on + // timeout (see below), or in processJSAPIReplies upon receiving the + // response. + jsa.replies.Store(reply, responseCh) + + subject = jsa.prefixDomain(subject) + jsa.sendq.push(&mqttJSPubMsg{ + subj: subject, + reply: reply, + hdr: hdr, + msg: msg, + }) + r2i[reply] = i + } + + // Wait for all responses to come back, or for the timeout to expire. We + // don't want to use time.After() which causes memory growth because the + // timer can't be stopped and will need to expire to then be garbage + // collected. + c := 0 + responses := make([]*mqttJSAResponse, len(msgs)) + start := time.Now() + t := time.NewTimer(jsa.timeout) + defer t.Stop() + for { + select { + case r := <-responseCh: + i := r2i[r.reply] + responses[i] = r + c++ + if c == len(msgs) { + return responses, nil + } + + case <-jsa.quitCh: + return nil, ErrServerNotRunning + + case <-t.C: + var reply string + now := time.Now() + for reply = range r2i { // preserve the last value for Errorf + jsa.replies.Delete(reply) + } + + if len(msgs) == 1 { + return responses, fmt.Errorf("timeout after %v: request type %q on %q (reply=%q)", now.Sub(start), kind, subject, reply) + } else { + return responses, fmt.Errorf("timeout after %v: request type %q on %q: got %d out of %d", now.Sub(start), kind, subject, c, len(msgs)) + } + } + } +} + +func (jsa *mqttJSA) sendAck(ackSubject string) { + // Send to the ack subject with no payload. + jsa.sendMsg(ackSubject, nil) +} + +func (jsa *mqttJSA) sendMsg(subj string, msg []byte) { + if subj == _EMPTY_ { + return + } + // We pass -1 for the hdr so that the send loop does not need to + // add the "client info" header. This is not a JS API request per se. + jsa.sendq.push(&mqttJSPubMsg{subj: subj, msg: msg, hdr: -1}) +} + +func (jsa *mqttJSA) createEphemeralConsumer(cfg *CreateConsumerRequest) (*JSApiConsumerCreateResponse, error) { + cfgb, err := json.Marshal(cfg) + if err != nil { + return nil, err + } + subj := fmt.Sprintf(JSApiConsumerCreateT, cfg.Stream) + ccri, err := jsa.newRequest(mqttJSAConsumerCreate, subj, 0, cfgb) + if err != nil { + return nil, err + } + ccr := ccri.(*JSApiConsumerCreateResponse) + return ccr, ccr.ToError() +} + +func (jsa *mqttJSA) createDurableConsumer(cfg *CreateConsumerRequest) (*JSApiConsumerCreateResponse, error) { + cfgb, err := json.Marshal(cfg) + if err != nil { + return nil, err + } + subj := fmt.Sprintf(JSApiDurableCreateT, cfg.Stream, cfg.Config.Durable) + ccri, err := jsa.newRequest(mqttJSAConsumerCreate, subj, 0, cfgb) + if err != nil { + return nil, err + } + ccr := ccri.(*JSApiConsumerCreateResponse) + return ccr, ccr.ToError() +} + +// if noWait is specified, does not wait for the JS response, returns nil +func (jsa *mqttJSA) deleteConsumer(streamName, consName string, noWait bool) (*JSApiConsumerDeleteResponse, error) { + subj := fmt.Sprintf(JSApiConsumerDeleteT, streamName, consName) + if noWait { + jsa.sendMsg(subj, nil) + return nil, nil + } + + cdri, err := jsa.newRequest(mqttJSAConsumerDel, subj, 0, nil) + if err != nil { + return nil, err + } + cdr := cdri.(*JSApiConsumerDeleteResponse) + return cdr, cdr.ToError() +} + +func (jsa *mqttJSA) createStream(cfg *StreamConfig) (*StreamInfo, bool, error) { + cfgb, err := json.Marshal(cfg) + if err != nil { + return nil, false, err + } + scri, err := jsa.newRequest(mqttJSAStreamCreate, fmt.Sprintf(JSApiStreamCreateT, cfg.Name), 0, cfgb) + if err != nil { + return nil, false, err + } + scr := scri.(*JSApiStreamCreateResponse) + return scr.StreamInfo, scr.DidCreate, scr.ToError() +} + +func (jsa *mqttJSA) updateStream(cfg *StreamConfig) (*StreamInfo, error) { + cfgb, err := json.Marshal(cfg) + if err != nil { + return nil, err + } + scri, err := jsa.newRequest(mqttJSAStreamUpdate, fmt.Sprintf(JSApiStreamUpdateT, cfg.Name), 0, cfgb) + if err != nil { + return nil, err + } + scr := scri.(*JSApiStreamUpdateResponse) + return scr.StreamInfo, scr.ToError() +} + +func (jsa *mqttJSA) lookupStream(name string) (*StreamInfo, error) { + slri, err := jsa.newRequest(mqttJSAStreamLookup, fmt.Sprintf(JSApiStreamInfoT, name), 0, nil) + if err != nil { + return nil, err + } + slr := slri.(*JSApiStreamInfoResponse) + return slr.StreamInfo, slr.ToError() +} + +func (jsa *mqttJSA) deleteStream(name string) (bool, error) { + sdri, err := jsa.newRequest(mqttJSAStreamDel, fmt.Sprintf(JSApiStreamDeleteT, name), 0, nil) + if err != nil { + return false, err + } + sdr := sdri.(*JSApiStreamDeleteResponse) + return sdr.Success, sdr.ToError() +} + +func (jsa *mqttJSA) loadLastMsgFor(streamName string, subject string) (*StoredMsg, error) { + mreq := &JSApiMsgGetRequest{LastFor: subject} + req, err := json.Marshal(mreq) + if err != nil { + return nil, err + } + lmri, err := jsa.newRequest(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), 0, req) + if err != nil { + return nil, err + } + lmr := lmri.(*JSApiMsgGetResponse) + return lmr.Message, lmr.ToError() +} + +func (jsa *mqttJSA) loadLastMsgForMulti(streamName string, subjects []string) ([]*JSApiMsgGetResponse, error) { + marshaled := make([][]byte, 0, len(subjects)) + headerBytes := make([]int, 0, len(subjects)) + for _, subject := range subjects { + mreq := &JSApiMsgGetRequest{LastFor: subject} + bb, err := json.Marshal(mreq) + if err != nil { + return nil, err + } + marshaled = append(marshaled, bb) + headerBytes = append(headerBytes, 0) + } + + all, err := jsa.newRequestExMulti(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), _EMPTY_, headerBytes, marshaled) + // all has the same order as subjects, preserve it as we unmarshal + responses := make([]*JSApiMsgGetResponse, len(all)) + for i, v := range all { + if v != nil { + responses[i] = v.value.(*JSApiMsgGetResponse) + } + } + return responses, err +} + +func (jsa *mqttJSA) loadNextMsgFor(streamName string, subject string) (*StoredMsg, error) { + mreq := &JSApiMsgGetRequest{NextFor: subject} + req, err := json.Marshal(mreq) + if err != nil { + return nil, err + } + lmri, err := jsa.newRequest(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), 0, req) + if err != nil { + return nil, err + } + lmr := lmri.(*JSApiMsgGetResponse) + return lmr.Message, lmr.ToError() +} + +func (jsa *mqttJSA) loadMsg(streamName string, seq uint64) (*StoredMsg, error) { + mreq := &JSApiMsgGetRequest{Seq: seq} + req, err := json.Marshal(mreq) + if err != nil { + return nil, err + } + lmri, err := jsa.newRequest(mqttJSAMsgLoad, fmt.Sprintf(JSApiMsgGetT, streamName), 0, req) + if err != nil { + return nil, err + } + lmr := lmri.(*JSApiMsgGetResponse) + return lmr.Message, lmr.ToError() +} + +func (jsa *mqttJSA) storeMsgNoWait(subject string, hdrLen int, msg []byte) { + jsa.sendq.push(&mqttJSPubMsg{ + subj: subject, + msg: msg, + hdr: hdrLen, + }) +} + +func (jsa *mqttJSA) storeMsg(subject string, headers int, msg []byte) (*JSPubAckResponse, error) { + smri, err := jsa.newRequest(mqttJSAMsgStore, subject, headers, msg) + if err != nil { + return nil, err + } + smr := smri.(*JSPubAckResponse) + return smr, smr.ToError() +} + +func (jsa *mqttJSA) storeSessionMsg(domainTk, cidHash string, hdr int, msg []byte) (*JSPubAckResponse, error) { + // Compute subject where the session is being stored + subject := mqttSessStreamSubjectPrefix + domainTk + cidHash + + // Passing cidHash will add it to the JS reply subject, so that we can use + // it in processSessionPersist. + smri, err := jsa.newRequestEx(mqttJSASessPersist, subject, cidHash, hdr, msg) + if err != nil { + return nil, err + } + smr := smri.(*JSPubAckResponse) + return smr, smr.ToError() +} + +func (jsa *mqttJSA) loadSessionMsg(domainTk, cidHash string) (*StoredMsg, error) { + subject := mqttSessStreamSubjectPrefix + domainTk + cidHash + return jsa.loadLastMsgFor(mqttSessStreamName, subject) +} + +func (jsa *mqttJSA) deleteMsg(stream string, seq uint64, wait bool) error { + dreq := JSApiMsgDeleteRequest{Seq: seq, NoErase: true} + req, _ := json.Marshal(dreq) + subj := jsa.prefixDomain(fmt.Sprintf(JSApiMsgDeleteT, stream)) + if !wait { + jsa.sendq.push(&mqttJSPubMsg{ + subj: subj, + msg: req, + }) + return nil + } + dmi, err := jsa.newRequest(mqttJSAMsgDelete, subj, 0, req) + if err != nil { + return err + } + dm := dmi.(*JSApiMsgDeleteResponse) + return dm.ToError() +} + +////////////////////////////////////////////////////////////////////////////// +// +// Account Sessions Manager related functions +// +////////////////////////////////////////////////////////////////////////////// + +// Returns true if `err` is not nil and does not match the api error with ErrorIdentifier id +func isErrorOtherThan(err error, id ErrorIdentifier) bool { + return err != nil && !IsNatsErr(err, id) +} + +// Process JS API replies. +// +// Can run from various go routines (consumer's loop, system send loop, etc..). +func (as *mqttAccountSessionManager) processJSAPIReplies(_ *subscription, pc *client, _ *Account, subject, _ string, msg []byte) { + token := tokenAt(subject, mqttJSATokenPos) + if token == _EMPTY_ { + return + } + jsa := &as.jsa + chi, ok := jsa.replies.Load(subject) + if !ok { + return + } + jsa.replies.Delete(subject) + ch := chi.(chan *mqttJSAResponse) + out := func(value any) { + ch <- &mqttJSAResponse{reply: subject, value: value} + } + switch token { + case mqttJSAStreamCreate: + var resp = &JSApiStreamCreateResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAStreamUpdate: + var resp = &JSApiStreamUpdateResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAStreamLookup: + var resp = &JSApiStreamInfoResponse{} + if err := json.Unmarshal(msg, &resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAStreamDel: + var resp = &JSApiStreamDeleteResponse{} + if err := json.Unmarshal(msg, &resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAConsumerCreate: + var resp = &JSApiConsumerCreateResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAConsumerDel: + var resp = &JSApiConsumerDeleteResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAMsgStore, mqttJSASessPersist: + var resp = &JSPubAckResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAMsgLoad: + var resp = &JSApiMsgGetResponse{} + if err := json.Unmarshal(msg, &resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAStreamNames: + var resp = &JSApiStreamNamesResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + case mqttJSAMsgDelete: + var resp = &JSApiMsgDeleteResponse{} + if err := json.Unmarshal(msg, resp); err != nil { + resp.Error = NewJSInvalidJSONError(err) + } + out(resp) + default: + pc.Warnf("Unknown reply code %q", token) + } +} + +// This will both load all retained messages and process updates from the cluster. +// +// Run from various go routines (JS consumer, etc..). +// No lock held on entry. +func (as *mqttAccountSessionManager) processRetainedMsg(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + h, m := c.msgParts(rmsg) + // We need to strip the trailing "\r\n". + if l := len(m); l >= LEN_CR_LF { + m = m[:l-LEN_CR_LF] + } + rm, err := mqttDecodeRetainedMessage(subject, h, m) + if err != nil { + return + } + // The as.jsa.id is immutable, so no need to have a rlock here. + local := rm.Origin == as.jsa.id + // Get the stream sequence for this message. + seq, _, _ := ackReplyInfo(reply) + if len(m) == 0 { + // An empty payload means that we need to remove the retained message. + rmSeq := as.removeRetainedMsg(rm.Subject, 0) + if local { + if rmSeq > 0 { + // This is for backward compatibility reasons. + // Should be removed in a future release. + as.notifyRetainedMsgDeleted(rm.Subject, rmSeq) + } + // Delete this very message we just processed, we don't need it anymore. + as.deleteRetainedMsg(seq) + } + } else { + // Add this retained message. The `rm.Msg` references some buffer that we + // don't own. But addRetainedMsg() will take care of making a copy of + // `rm.Msg` it `rm` ends-up being stored in the cache. + as.addRetainedMsg(rm.Subject, &mqttRetainedMsgRef{sseq: seq}, rm) + } +} + +// NOTE: This is maintained for backward compatibility reasons. Should be removed in 2.14/2.15? +func (as *mqttAccountSessionManager) processRetainedMsgDel(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + idHash := tokenAt(subject, 3) + if idHash == _EMPTY_ || idHash == as.jsa.id { + return + } + _, msg := c.msgParts(rmsg) + if len(msg) < LEN_CR_LF { + return + } + var drm mqttRetMsgDel + if err := json.Unmarshal(msg, &drm); err != nil { + return + } + as.removeRetainedMsg(drm.Subject, drm.Seq) +} + +// This will receive all JS API replies for a request to store a session record, +// including the reply for our own server, which we will ignore. +// This allows us to detect that some application somewhere else in the cluster +// is connecting with the same client ID, and therefore we need to close the +// connection that is currently using this client ID. +// +// Can run from various go routines (system send loop, etc..). +// No lock held on entry. +func (as *mqttAccountSessionManager) processSessionPersist(_ *subscription, pc *client, _ *Account, subject, _ string, rmsg []byte) { + // Ignore our own responses here (they are handled elsewhere) + if tokenAt(subject, mqttJSAIdTokenPos) == as.jsa.id { + return + } + cIDHash := tokenAt(subject, mqttJSAClientIDPos) + _, msg := pc.msgParts(rmsg) + if len(msg) < LEN_CR_LF { + return + } + var par = &JSPubAckResponse{} + if err := json.Unmarshal(msg, par); err != nil { + return + } + if err := par.Error; err != nil { + return + } + as.mu.RLock() + // Note that as.domainTk includes a terminal '.', so strip to compare to PubAck.Domain. + dl := len(as.domainTk) + if dl > 0 { + dl-- + } + ignore := par.Domain != as.domainTk[:dl] + as.mu.RUnlock() + if ignore { + return + } + + as.mu.Lock() + defer as.mu.Unlock() + sess, ok := as.sessByHash[cIDHash] + if !ok { + return + } + // If our current session's stream sequence is higher, it means that this + // update is stale, so we don't do anything here. + sess.mu.Lock() + ignore = par.Sequence < sess.seq + sess.mu.Unlock() + if ignore { + return + } + as.removeSession(sess, false) + sess.mu.Lock() + if ec := sess.c; ec != nil { + as.addSessToFlappers(sess.id) + ec.Warnf("Closing because a remote connection has started with the same client ID: %q", sess.id) + // Disassociate the client from the session so that on client close, + // nothing will be done with regards to cleaning up the session, + // such as deleting stream, etc.. + sess.c = nil + // Remove in separate go routine. + go ec.closeConnection(DuplicateClientID) + } + sess.mu.Unlock() +} + +// Adds this client ID to the flappers map, and if needed start the timer +// for map cleanup. +// +// Lock held on entry. +func (as *mqttAccountSessionManager) addSessToFlappers(clientID string) { + as.flappers[clientID] = time.Now().UnixNano() + if as.flapTimer == nil { + as.flapTimer = time.AfterFunc(mqttFlapCleanItvl, func() { + as.mu.Lock() + defer as.mu.Unlock() + // In case of shutdown, this will be nil + if as.flapTimer == nil { + return + } + now := time.Now().UnixNano() + for cID, tm := range as.flappers { + if now-tm > int64(mqttSessJailDur) { + delete(as.flappers, cID) + } + } + as.flapTimer.Reset(mqttFlapCleanItvl) + }) + } +} + +// Remove this client ID from the flappers map. +// +// Lock held on entry. +func (as *mqttAccountSessionManager) removeSessFromFlappers(clientID string) { + delete(as.flappers, clientID) + // Do not stop/set timer to nil here. Better leave the timer run at its + // regular interval and detect that there is nothing to do. The timer + // will be stopped on shutdown. +} + +// Helper to create a subscription. It updates the sid and array of subscriptions. +func (as *mqttAccountSessionManager) createSubscription(subject string, cb msgHandler, sid *int64, subs *[]*subscription) error { + sub, err := as.jsa.c.processSub([]byte(subject), nil, []byte(strconv.FormatInt(*sid, 10)), cb, false) + if err != nil { + return err + } + *sid++ + *subs = append(*subs, sub) + return nil +} + +// A timer loop to cleanup up expired cached retained messages for a given MQTT account. +// The closeCh is used by the caller to be able to interrupt this routine +// if the rest of the initialization fails, since the quitCh is really +// only used when the server shutdown. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) cleanupRetainedMessageCache(s *Server, closeCh chan struct{}) { + tt := time.NewTicker(mqttRetainedCacheTTL) + defer tt.Stop() + for { + select { + case <-tt.C: + // Set a limit to the number of retained messages to scan since we + // lock as for it. Since the map enumeration gives random order we + // should eventually clean up everything. + i, maxScan := 0, 10*1000 + now := time.Now() + as.rmsCache.Range(func(key, value any) bool { + rm := value.(*mqttRetainedMsg) + if now.After(rm.expiresFromCache) { + as.rmsCache.Delete(key) + } + i++ + return i < maxScan + }) + + case <-closeCh: + return + case <-s.quitCh: + return + } + } +} + +// Loop to send JS API requests for a given MQTT account. +// The closeCh is used by the caller to be able to interrupt this routine +// if the rest of the initialization fails, since the quitCh is really +// only used when the server shutdown. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) sendJSAPIrequests(s *Server, c *client, accName string, closeCh chan struct{}) { + var cluster string + if s.JetStreamEnabled() && !as.jsa.domainSet { + // Only request the own cluster when it is clear that + cluster = s.cachedClusterName() + } + as.mu.RLock() + sendq := as.jsa.sendq + quitCh := as.jsa.quitCh + ci := ClientInfo{Account: accName, Cluster: cluster} + acc := c.acc + as.mu.RUnlock() + + // The account session manager does not have a suhtdown API per-se, instead, + // we will cleanup things when this go routine exits after detecting that the + // server is shutdown or the initialization of the account manager failed. + defer func() { + as.mu.Lock() + if as.flapTimer != nil { + as.flapTimer.Stop() + as.flapTimer = nil + } + as.mu.Unlock() + }() + + b, _ := json.Marshal(ci) + hdrStart := bytes.Buffer{} + hdrStart.WriteString(hdrLine) + http.Header{ClientInfoHdr: []string{string(b)}}.Write(&hdrStart) + hdrStart.WriteString(CR_LF) + hdrStart.WriteString(CR_LF) + hdrb := hdrStart.Bytes() + + for { + select { + case <-sendq.ch: + pmis := sendq.pop() + for _, r := range pmis { + var nsize int + + msg := r.msg + // If r.hdr is set to -1, it means that there is no need for any header. + if r.hdr != -1 { + bb := bytes.Buffer{} + if r.hdr > 0 { + // This means that the header has been set by the caller and is + // already part of `msg`, so simply set c.pa.hdr to the given value. + c.pa.hdr = r.hdr + nsize = len(msg) + msg = append(msg, _CRLF_...) + } else { + // We need the ClientInfo header, so add it here. + bb.Write(hdrb) + c.pa.hdr = bb.Len() + bb.Write(r.msg) + nsize = bb.Len() + bb.WriteString(_CRLF_) + msg = bb.Bytes() + } + c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr)) + } else { + c.pa.hdr = -1 + c.pa.hdb = nil + nsize = len(msg) + msg = append(msg, _CRLF_...) + } + + c.pa.subject = []byte(r.subj) + c.pa.reply = []byte(r.reply) + c.pa.size = nsize + c.pa.szb = []byte(strconv.Itoa(nsize)) + c.pa.mapped = nil + + if acc.hasMappings() { + if changed := c.selectMappedSubject(); changed { + c.traceOutOp("MAPPINGS", fmt.Appendf(nil, "%s -> %s", c.pa.mapped, c.pa.subject)) + } + } + c.processInboundClientMsg(msg) + c.flushClients(0) + } + sendq.recycle(&pmis) + + case <-closeCh: + return + case <-quitCh: + return + } + } +} + +// Add/Replace this message from the retained messages map. +// If a message for this topic already existed, the existing record is updated +// with the provided information. +// Lock not held on entry. +func (as *mqttAccountSessionManager) addRetainedMsg(key string, rf *mqttRetainedMsgRef, rm *mqttRetainedMsg) { + as.mu.Lock() + defer as.mu.Unlock() + if as.retmsgs == nil { + as.retmsgs = make(map[string]*mqttRetainedMsgRef) + as.sl = NewSublistWithCache() + } else { + // Check if we already had one retained message. If so, update the existing one. + if erf, exists := as.retmsgs[key]; exists { + // Update the stream sequence with the new value. + erf.sseq = rf.sseq + // Update the in-memory retained message cache but only for messages + // that are already in the cache, i.e. have been (recently) used. + // If that is the case, we ask setCachedRetainedMsg() to make a copy + // of rm.Msg bytes slice. + as.setCachedRetainedMsg(key, rm, true, true) + return + } + } + rf.sub = &subscription{subject: []byte(key)} + as.retmsgs[key] = rf + as.sl.Insert(rf.sub) +} + +// Remove the retained message stored with the `subject` key from the map/cache. +// When invoked from the retained message stream's consumer, this function will +// be called with `seq == 0`, this is because add/remove are serialized in this +// stream and so the request is to remove the current retained message. +// But in some conditions, we will invoke this function from some other places +// with `seq > 0` which means that the retained message will be removed only if +// its sequence is the same than the provided one. +// This function returns the sequence associated with the existing retained +// message that is being removed (used with `seq == 0`) and returns 0 if the +// retained message was not removed from the map (not found or sequence did not +// match). +func (as *mqttAccountSessionManager) removeRetainedMsg(subject string, seq uint64) uint64 { + as.mu.Lock() + defer as.mu.Unlock() + rm, ok := as.retmsgs[subject] + if !ok || (seq > 0 && rm.sseq != seq) { + return 0 + } + seq = rm.sseq + as.rmsCache.Delete(subject) + delete(as.retmsgs, subject) + as.sl.Remove(rm.sub) + return seq +} + +// First check if this session's client ID is already in the "locked" map, +// which if it is the case means that another client is now bound to this +// session and this should return an error. +// If not in the "locked" map, but the client is not bound with this session, +// then same error is returned. +// Finally, if all checks ok, then the session's ID is added to the "locked" map. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) lockSession(sess *mqttSession, c *client) error { + as.mu.Lock() + defer as.mu.Unlock() + var fail bool + if _, fail = as.sessLocked[sess.id]; !fail { + sess.mu.Lock() + fail = sess.c != c + sess.mu.Unlock() + } + if fail { + return fmt.Errorf("another session is in use with client ID %q", sess.id) + } + as.sessLocked[sess.id] = struct{}{} + return nil +} + +// Remove the session from the "locked" map. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) unlockSession(sess *mqttSession) { + as.mu.Lock() + delete(as.sessLocked, sess.id) + as.mu.Unlock() +} + +// Simply adds the session to the various sessions maps. +// The boolean `lock` indicates if this function should acquire the lock +// prior to adding to the maps. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) addSession(sess *mqttSession, lock bool) { + if lock { + as.mu.Lock() + } + as.sessions[sess.id] = sess + as.sessByHash[sess.idHash] = sess + if lock { + as.mu.Unlock() + } +} + +// Simply removes the session from the various sessions maps. +// The boolean `lock` indicates if this function should acquire the lock +// prior to removing from the maps. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) removeSession(sess *mqttSession, lock bool) { + if lock { + as.mu.Lock() + } + delete(as.sessions, sess.id) + delete(as.sessByHash, sess.idHash) + if lock { + as.mu.Unlock() + } +} + +// Helper to set the sub's mqtt fields and possibly serialize (pre-loaded) +// retained messages. +// +// Session lock held on entry. Acquires the subs lock and holds it for +// the duration. Non-MQTT messages coming into mqttDeliverMsgCbQoS0 will be +// waiting. +func (sess *mqttSession) processQOS12Sub( + c *client, // subscribing client. + subject, sid []byte, isReserved bool, qos byte, jsDurName string, h msgHandler, // subscription parameters. +) (*subscription, error) { + return sess.processSub(c, subject, sid, isReserved, qos, jsDurName, h, false, nil, false, nil) +} + +func (sess *mqttSession) processSub( + c *client, // subscribing client. + subject, sid []byte, isReserved bool, qos byte, jsDurName string, h msgHandler, // subscription parameters. + initShadow bool, // do we need to scan for shadow subscriptions? (not for QOS1+) + rms map[string]*mqttRetainedMsg, // preloaded rms (can be empty, or missing items if errors) + trace bool, // trace serialized retained messages in the log? + as *mqttAccountSessionManager, // needed only for rms serialization. +) (*subscription, error) { + start := time.Now() + defer func() { + elapsed := time.Since(start) + if elapsed > mqttProcessSubTooLong { + c.Warnf("Took too long to process subscription for %q: %v", subject, elapsed) + } + }() + + // Hold subsMu to prevent QOS0 messages callback from doing anything until + // the (MQTT) sub is initialized. + sess.subsMu.Lock() + defer sess.subsMu.Unlock() + + sub, err := c.processSub(subject, nil, sid, h, false) + if err != nil { + // c.processSub already called c.Errorf(), so no need here. + return nil, err + } + subs := []*subscription{sub} + if initShadow { + subs = append(subs, sub.shadow...) + } + for _, ss := range subs { + if ss.mqtt == nil { + // reserved is set only once and once the subscription has been + // created it can be considered immutable. + ss.mqtt = &mqttSub{ + reserved: isReserved, + } + } + // QOS and jsDurName can be changed on an existing subscription, so + // accessing it later requires a lock. + ss.mqtt.qos = qos + ss.mqtt.jsDur = jsDurName + } + + if len(rms) > 0 { + // Only deal with retained messages for the normal subscription, + // not the shadow one (which is for a different account and subject). + as.serializeRetainedMsgsForSub(rms, sess, c, sub, trace) + } + + return sub, nil +} + +// Process subscriptions for the given session/client. +// +// When `fromSubProto` is false, it means that this is invoked from the CONNECT +// protocol, when restoring subscriptions that were saved for this session. +// In that case, there is no need to update the session record. +// +// When `fromSubProto` is true, it means that this call is invoked from the +// processing of the SUBSCRIBE protocol, which means that the session needs to +// be updated. It also means that if a subscription on same subject with same +// QoS already exist, we should not be recreating the subscription/JS durable, +// since it was already done when processing the CONNECT protocol. +// +// Runs from the client's readLoop. +// Lock not held on entry, but session is in the locked map. +func (as *mqttAccountSessionManager) processSubs(sess *mqttSession, c *client, + filters []*mqttFilter, fromSubProto, trace bool) ([]*subscription, error) { + + // Helper to determine if we need to create a separate top-level + // subscription for a wildcard. + fwc := func(subject string) (bool, string, string) { + if !mqttNeedSubForLevelUp(subject) { + return false, _EMPTY_, _EMPTY_ + } + // Say subject is "foo.>", remove the ".>" so that it becomes "foo" + fwcsubject := subject[:len(subject)-2] + // Change the sid to "foo fwc" + fwcsid := fwcsubject + mqttMultiLevelSidSuffix + + return true, fwcsubject, fwcsid + } + + rmSubjects := map[string]uint64{} + // Preload retained messages for all requested subscriptions. Also, since + // it's the first iteration over the filter list, do some cleanup. + for _, f := range filters { + if f.qos > 2 { + f.qos = 2 + } + if c.mqtt.downgradeQoS2Sub && f.qos == 2 { + c.Warnf("Downgrading subscription QoS2 to QoS1 for %q, as configured", f.filter) + f.qos = 1 + } + + // Do not allow subscribing to our internal subjects. + // + // TODO: (levb: not sure why since one can subscribe to `#` and it'll + // include everything; I guess this would discourage? Otherwise another + // candidate for DO NOT DELIVER prefix list). + if strings.HasPrefix(f.filter, mqttSubPrefix) { + f.qos = mqttSubAckFailure + continue + } + + if f.qos == 2 { + if err := sess.ensurePubRelConsumerSubscription(c); err != nil { + c.Errorf("failed to initialize PUBREL processing: %v", err) + f.qos = mqttSubAckFailure + continue + } + } + + // Find retained messages. + if fromSubProto { + as.addRetainedSubjectsForSubject(rmSubjects, f.filter) + if need, subject, _ := fwc(f.filter); need { + as.addRetainedSubjectsForSubject(rmSubjects, subject) + } + } + } + + var rms map[string]*mqttRetainedMsg + if len(rmSubjects) > 0 { + // Make the best effort to load retained messages. + rms = as.loadRetainedMessages(rmSubjects, c) + } + + // Small helper to add the consumer config to the session. + addJSConsToSess := func(sid string, cc *ConsumerConfig) { + if cc == nil { + return + } + if sess.cons == nil { + sess.cons = make(map[string]*ConsumerConfig) + } + sess.cons[sid] = cc + } + + var err error + subs := make([]*subscription, 0, len(filters)) + for _, f := range filters { + // Skip what's already been identified as a failure. + if f.qos == mqttSubAckFailure { + continue + } subject := f.filter + bsubject := []byte(subject) sid := subject + bsid := bsubject + isReserved := isMQTTReservedSubscription(subject) + + var jscons *ConsumerConfig + var jssub *subscription + + // Note that if a subscription already exists on this subject, the + // existing sub is returned. Need to update the qos. + var sub *subscription + var err error + + const processShadowSubs = true + + as.mu.Lock() + sess.mu.Lock() + sub, err = sess.processSub(c, + bsubject, bsid, isReserved, f.qos, // main subject + _EMPTY_, mqttDeliverMsgCbQoS0, // no jsDur for QOS0 + processShadowSubs, + rms, trace, as) + sess.mu.Unlock() + as.mu.Unlock() + + if err != nil { + f.qos = mqttSubAckFailure + sess.cleanupFailedSub(c, sub, jscons, jssub) + continue + } + + // This will create (if not already exist) a JS consumer for + // subscriptions of QoS >= 1. But if a JS consumer already exists and + // the subscription for same subject is now a QoS==0, then the JS + // consumer will be deleted. + jscons, jssub, err = sess.processJSConsumer(c, subject, sid, f.qos, fromSubProto) + if err != nil { + f.qos = mqttSubAckFailure + sess.cleanupFailedSub(c, sub, jscons, jssub) + continue + } + + // Process the wildcard subject if needed. + if need, fwcsubject, fwcsid := fwc(subject); need { + var fwjscons *ConsumerConfig + var fwjssub *subscription + var fwcsub *subscription + + // See note above about existing subscription. + as.mu.Lock() + sess.mu.Lock() + fwcsub, err = sess.processSub(c, + []byte(fwcsubject), []byte(fwcsid), isReserved, f.qos, // FWC (top-level wildcard) subject + _EMPTY_, mqttDeliverMsgCbQoS0, // no jsDur for QOS0 + processShadowSubs, + rms, trace, as) + sess.mu.Unlock() + as.mu.Unlock() + if err != nil { + // c.processSub already called c.Errorf(), so no need here. + f.qos = mqttSubAckFailure + sess.cleanupFailedSub(c, sub, jscons, jssub) + continue + } + + fwjscons, fwjssub, err = sess.processJSConsumer(c, fwcsubject, fwcsid, f.qos, fromSubProto) + if err != nil { + // c.processSub already called c.Errorf(), so no need here. + f.qos = mqttSubAckFailure + sess.cleanupFailedSub(c, sub, jscons, jssub) + sess.cleanupFailedSub(c, fwcsub, fwjscons, fwjssub) + continue + } + + subs = append(subs, fwcsub) + addJSConsToSess(fwcsid, fwjscons) + } + + subs = append(subs, sub) + addJSConsToSess(sid, jscons) + } + + if fromSubProto { + err = sess.update(filters, true) + } + + return subs, err +} + +// Retained publish messages matching this subscription are serialized in the +// subscription's `prm` mqtt writer. This buffer will be queued for outbound +// after the subscription is processed and SUBACK is sent or possibly when +// server processes an incoming published message matching the newly +// registered subscription. +// +// Runs from the client's readLoop. +// Account session manager lock held on entry. +// Session lock held on entry. +func (as *mqttAccountSessionManager) serializeRetainedMsgsForSub(rms map[string]*mqttRetainedMsg, sess *mqttSession, c *client, sub *subscription, trace bool) { + if len(as.retmsgs) == 0 || len(rms) == 0 { + return + } + result := as.sl.ReverseMatch(string(sub.subject)) + if len(result.psubs) == 0 { + return + } + toTrace := []mqttPublish{} + for _, psub := range result.psubs { + + rm := rms[string(psub.subject)] + if rm == nil { + // This should not happen since we pre-load messages into rms before + // calling serialize. + continue + } + var pi uint16 + qos := min(mqttGetQoS(rm.Flags), sub.mqtt.qos) + if c.mqtt.rejectQoS2Pub && qos == 2 { + c.Warnf("Rejecting retained message with QoS2 for subscription %q, as configured", sub.subject) + continue + } + if qos > 0 { + pi = sess.trackPublishRetained() + + // If we failed to get a PI for this message, send it as a QoS0, the + // best we can do? + if pi == 0 { + qos = 0 + } + } + + // Need to use the subject for the retained message, not the `sub` subject. + // We can find the published retained message in rm.sub.subject. + // Set the RETAIN flag: [MQTT-3.3.1-8]. + flags, headerBytes := mqttMakePublishHeader(pi, qos, false, true, []byte(rm.Topic), len(rm.Msg)) + c.mu.Lock() + sub.mqtt.prm = append(sub.mqtt.prm, headerBytes, rm.Msg) + c.mu.Unlock() + if trace { + toTrace = append(toTrace, mqttPublish{ + topic: []byte(rm.Topic), + flags: flags, + pi: pi, + sz: len(rm.Msg), + }) + } + } + for _, pp := range toTrace { + c.traceOutOp("PUBLISH", []byte(mqttPubTrace(&pp))) + } +} + +// Appends the stored message subjects for all retained message records that +// match the given subscription's `subject` (which could have wildcards). +// +// Account session manager NOT lock held on entry. +func (as *mqttAccountSessionManager) addRetainedSubjectsForSubject(list map[string]uint64, topSubject string) { + as.mu.RLock() + if len(as.retmsgs) == 0 { + as.mu.RUnlock() + return + } + result := as.sl.ReverseMatch(topSubject) + as.mu.RUnlock() - if strings.HasPrefix(subject, mqttSubPrefix) { - f.qos = mqttSubAckFailure + for _, sub := range result.psubs { + if _, ok := list[string(sub.subject)]; ok { continue } + var seq uint64 + as.mu.RLock() + if rm, ok := as.retmsgs[string(sub.subject)]; ok { + seq = rm.sseq + } + as.mu.RUnlock() + if seq > 0 { + list[string(sub.subject)] = seq + } + } +} - var jscons *Consumer - var jssub *subscription +type warner interface { + Warnf(format string, v ...any) +} - // Note that if a subscription already exists on this subject, - // the existing sub is returned. Need to update the qos. - sub, err := c.processSub([]byte(subject), nil, []byte(sid), mqttDeliverMsgCb, false) - if err == nil { - setupSub(sub, f.qos) - // This will create (if not already exist) a JS consumer for subscriptions - // of QoS >= 1. But if a JS consumer already exists and the subscription - // for same subject is now a QoS==0, then the JS consumer will be deleted. - jscons, jssub, err = c.mqttProcessJSConsumer(sess, as.mstream, - subject, sid, f.qos, fromSubProto) +// Loads a list of retained messages given a list of stored message subjects. +func (as *mqttAccountSessionManager) loadRetainedMessages(subjects map[string]uint64, w warner) map[string]*mqttRetainedMsg { + rms := make(map[string]*mqttRetainedMsg, len(subjects)) + ss := []string{} + for s := range subjects { + if rm := as.getCachedRetainedMsg(s); rm != nil { + rms[s] = rm + } else { + ss = append(ss, mqttRetainedMsgsStreamSubject+s) + } + } + + if len(ss) == 0 { + return rms + } + + // Although we have the stream sequence for a given subject, we still use + // the load with "last for subject" because it will cover the cases where a + // new retained message has arrived since we collected the subject/seq pair. + // If we were doing a load "by seq" and the message is not found, we would + // incorrectly remove the retained message from our map. + results, err := as.jsa.loadLastMsgForMulti(mqttRetainedMsgsStreamName, ss) + // If an error occurred, warn, but then proceed with what we got. + if err != nil { + w.Warnf("error loading retained messages: %v", err) + } + for i, result := range results { + if result == nil { + continue // skip requests that timed out } + if err := result.ToError(); err != nil { + // Skip the "$MQTT.rmsgs." prefix... + subj := ss[i][len(mqttRetainedMsgsStreamSubject):] + if IsNatsErr(err, JSNoMessageFoundErr) { + // If there is no message for that subject, delete from our map. + // The good thing here is that we handle the race where a retained + // message may just arrive and be replacing it in the map. The + // removeRetainedMsg() function below will not remove if the sequence + // does not match. + seq := subjects[subj] + as.removeRetainedMsg(subj, seq) + } + w.Warnf("failed to load retained message for subject %q: %v", subj, err) + continue + } + rm, err := mqttDecodeRetainedMessage(result.Message.Subject, result.Message.Header, result.Message.Data) if err != nil { - c.Errorf("error subscribing to %q: err=%v", subject, err) - f.qos = mqttSubAckFailure - c.mqttCleanupFailedSub(sub, jscons, jssub) + // Unlikely that we can recover from that, so remove the message. + // (see comment above if failing to load the message). + subj := ss[i][len(mqttRetainedMsgsStreamSubject):] + seq := subjects[subj] + as.removeRetainedMsg(subj, seq) + w.Warnf("failed to decode retained message for subject %q: %v", subj, err) continue } - if mqttNeedSubForLevelUp(subject) { - var fwjscons *Consumer - var fwjssub *subscription - var fwcsub *subscription - // Say subject is "foo.>", remove the ".>" so that it becomes "foo" - fwcsubject := subject[:len(subject)-2] - // Change the sid to "foo fwc" - fwcsid := fwcsubject + mqttMultiLevelSidSuffix - // See note above about existing subscription. - fwcsub, err = c.processSub([]byte(fwcsubject), nil, []byte(fwcsid), mqttDeliverMsgCb, false) - if err == nil { - setupSub(fwcsub, f.qos) - fwjscons, fwjssub, err = c.mqttProcessJSConsumer(sess, as.mstream, - fwcsubject, fwcsid, f.qos, fromSubProto) - } - if err != nil { - c.Errorf("error subscribing to %q: err=%v", fwcsubject, err) - f.qos = mqttSubAckFailure - c.mqttCleanupFailedSub(sub, jscons, jssub) - c.mqttCleanupFailedSub(fwcsub, fwjscons, fwjssub) - continue + // Add the loaded retained message to the cache, and to the results map. + // We don't need setCachedRetainedMsg() to clone the `rm.Msg` bytes slice + // since we own it. + as.setCachedRetainedMsg(rm.Subject, rm, false, false) + rms[rm.Subject] = rm + } + return rms +} + +// Composes a NATS message for a storeable mqttRetainedMsg. +// If the body is empty, the flags are encoded in a way that will cause older +// servers to fail to decode the message in processRetainedMsg callback and +// will simply ignore it, which is what we want. +func mqttEncodeRetainedMessage(rm *mqttRetainedMsg) (natsMsg []byte, headerLen int) { + delRM := len(rm.Msg) == 0 + + // No need to encode the subject, we can restore it from topic. + l := len(hdrLine) + l += len(mqttNatsRetainedMessageTopic) + 1 + len(rm.Topic) + 2 // 1 byte for ':', 2 bytes for CRLF + if rm.Origin != _EMPTY_ { + l += len(mqttNatsRetainedMessageOrigin) + 1 + len(rm.Origin) + 2 // 1 byte for ':', 2 bytes for CRLF + } + if rm.Source != _EMPTY_ { + l += len(mqttNatsRetainedMessageSource) + 1 + len(rm.Source) + 2 // 1 byte for ':', 2 bytes for CRLF + } + l += len(mqttNatsRetainedMessageFlags) + 1 + 2 + 2 // 1 byte for ':', 2 bytes for the flags, 2 bytes for CRLF + l += 2 // 2 bytes for the extra CRLF after the header + if delRM { + l++ // Will add the delete marker before the flag + } else { + l += len(rm.Msg) + } + + buf := bytes.NewBuffer(make([]byte, 0, l)) + + buf.WriteString(hdrLine) + + buf.WriteString(mqttNatsRetainedMessageTopic) + buf.WriteByte(':') + buf.WriteString(rm.Topic) + buf.WriteString(_CRLF_) + + buf.WriteString(mqttNatsRetainedMessageFlags) + buf.WriteByte(':') + if delRM { + buf.WriteByte(mqttRetainedFlagDelMarker) + } + buf.WriteString(strconv.FormatUint(uint64(rm.Flags), 16)) + buf.WriteString(_CRLF_) + + if rm.Origin != _EMPTY_ { + buf.WriteString(mqttNatsRetainedMessageOrigin) + buf.WriteByte(':') + buf.WriteString(rm.Origin) + buf.WriteString(_CRLF_) + } + if rm.Source != _EMPTY_ { + buf.WriteString(mqttNatsRetainedMessageSource) + buf.WriteByte(':') + buf.WriteString(rm.Source) + buf.WriteString(_CRLF_) + } + + // End of header, finalize + buf.WriteString(_CRLF_) + headerLen = buf.Len() + buf.Write(rm.Msg) + return buf.Bytes(), headerLen +} + +func mqttSliceHeaders(headers map[string][]byte, hdr []byte) { + // Skip the hdrLine + if !bytes.HasPrefix(hdr, stringToBytes(hdrLine)) { + return + } + crLFAsBytes := stringToBytes(CR_LF) + for i := len(hdrLine); i < len(hdr); { + // Search for key/val delimiter. + del := bytes.IndexByte(hdr[i:], ':') + // Not found or key is length 0, we stop. + if del < 0 || del == i { + break + } + keyStart := i + // Walk back to remove spaces between the key and ':' if applicable. + index := keyStart + del - 1 + for index > keyStart && hdr[index] == ' ' { + index-- + } + key := hdr[keyStart : index+1] + // If what we had is only spaces, we stop. + if len(key) == 0 { + break + } + i += del + 1 + valStart := i + // Search for `\r\n`. + nl := bytes.Index(hdr[valStart:], crLFAsBytes) + // If we don't find, we stop. + if nl < 0 { + break + } + // Look if the caller is interested in this key. + if _, ok := headers[bytesToString(key)]; ok { + index := valStart + // Remove possible spaces between the ':' and the value. + for index < valStart+nl && hdr[index] == ' ' { + index++ } - subs = append(subs, fwcsub) - addJSConsToSess(fwcsid, fwjscons) + // Create a slice and limit capacity to the value range. + val := hdr[index : valStart+nl : valStart+nl] + // Record in the caller's map the value for this key. + headers[bytesToString(key)] = val } - subs = append(subs, sub) - addJSConsToSess(sid, jscons) + // Reposition to past the `\r\n`. + i += nl + 2 } - var err error - if fromSubProto { - err = sess.update(clientID, filters, true) +} + +// Decodes a retained message based on the content of the header `h`. +// The returned `*mqttRetainedMsg` object will hold a reference to `m`. +// If the buffer `m` is not owned by the caller, it is the caller +// responsibility to make a copy of the byte slice. +func mqttDecodeRetainedMessage(subject string, h, m []byte) (*mqttRetainedMsg, error) { + headers := map[string][]byte{ + mqttNatsRetainedMessageOrigin: nil, + mqttNatsRetainedMessageFlags: nil, + mqttNatsRetainedMessageSource: nil, + } + var rm *mqttRetainedMsg + // Retrieve the values for the above headers. + mqttSliceHeaders(headers, h) + // Get the flag header. + fHeader := headers[mqttNatsRetainedMessageFlags] + // If we don't, it could be that this is an old retained message that + // was JSON encoded. + if len(fHeader) > 0 { + if len(fHeader) > 1 && fHeader[0] == mqttRetainedFlagDelMarker { + fHeader = fHeader[1:] + } + flagsUint, err := strconv.ParseUint(bytesToString(fHeader), 16, 8) + if err != nil { + // Since the error is currently not reported in the server, we + // will simply replace with this one. + return nil, errMQTTInvalidRetainFlags + } + rm = &mqttRetainedMsg{ + Flags: byte(flagsUint), + Origin: string(headers[mqttNatsRetainedMessageOrigin]), + Source: string(headers[mqttNatsRetainedMessageSource]), + Msg: m, + } + } else { + if err := json.Unmarshal(m, &rm); err != nil { + return nil, err + } } - return subs, err + // Now check that the values are correct. + // + // For "Flags", anything at or above binary (1111) is too big. + if rm.Flags >= mqttPacketFlagMask { + return nil, errMQTTInvalidRetainFlags + } + if qos := mqttGetQoS(rm.Flags); qos > 2 { + return nil, errMQTTInvalidRetainFlags + } + // We store `Topic` in the retained message because we used to store + // all retained messages under the same subject `$MQTT_rmsgs` in + // the retained messages stream. That is no longer the case, and to + // cover setups where the retained message stream is sourced from another + // account and has some subject transforms, simply reconstruct the + // topic/subject based on the `subject` passed to this function. + rm.Subject = strings.TrimPrefix(subject, mqttRetainedMsgsStreamSubject) + rm.Topic = bytesToString(natsSubjectStrToMQTTTopic(rm.Subject)) + return rm, nil } -// Retained publish messages matching this subscription are serialized in the -// subscription's `prm` mqtt writer. This buffer will be queued for outbound -// after the subscription is processed and SUBACK is sent or possibly when -// server processes an incoming published message matching the newly -// registered subscription. +// Creates the session stream (limit msgs of 1) for this client ID if it does +// not already exist. If it exists, recover the single record to rebuild the +// state of the session. If there is a session record but this session is not +// registered in the runtime of this server, then a request is made to the +// owner to close the client associated with this session since specification +// [MQTT-3.1.4-2] specifies that if the ClientId represents a Client already +// connected to the Server then the Server MUST disconnect the existing client. // -// Account session manager lock held on entry. -// Session lock held on entry -func (as *mqttAccountSessionManager) serializeRetainedMsgsForSub(sess *mqttSession, c *client, sub *subscription, trace bool) { - if len(as.retmsgs) > 0 { - var rmsa [64]*mqttRetainedMsg - rms := rmsa[:0] - - as.getRetainedPublishMsgs(string(sub.subject), &rms) - for _, rm := range rms { - if sub.mqtt.prm == nil { - sub.mqtt.prm = &mqttWriter{} - } - prm := sub.mqtt.prm - pi := sess.getPubAckIdentifier(mqttGetQoS(rm.Flags), sub) - // Need to use the subject for the retained message, not the `sub` subject. - // We can find the published retained message in rm.sub.subject. - flags := mqttSerializePublishMsg(prm, pi, false, true, string(rm.sub.subject), rm.Msg) - if trace { - pp := mqttPublish{ - flags: flags, - pi: pi, - subject: rm.sub.subject, - sz: len(rm.Msg), - } - c.traceOutOp("PUBLISH", []byte(mqttPubTrace(&pp))) +// Runs from the client's readLoop. +// Lock not held on entry, but session is in the locked map. +func (as *mqttAccountSessionManager) createOrRestoreSession(clientID string, opts *Options) (*mqttSession, bool, error) { + jsa := &as.jsa + formatError := func(errTxt string, err error) (*mqttSession, bool, error) { + accName := jsa.c.acc.GetName() + return nil, false, fmt.Errorf("%s for account %q, session %q: %v", errTxt, accName, clientID, err) + } + + hash := getHash(clientID) + smsg, err := jsa.loadSessionMsg(as.domainTk, hash) + if err != nil { + if isErrorOtherThan(err, JSNoMessageFoundErr) { + return formatError("loading session record", err) + } + // Message not found, so reate the session... + // Create a session and indicate that this session did not exist. + sess := mqttSessionCreate(jsa, clientID, hash, 0, opts) + sess.domainTk = as.domainTk + return sess, false, nil + } + // We need to recover the existing record now. + ps := &mqttPersistedSession{} + if err := json.Unmarshal(smsg.Data, ps); err != nil { + return formatError(fmt.Sprintf("unmarshal of session record at sequence %v", smsg.Sequence), err) + } + + // Restore this session (even if we don't own it), the caller will do the right thing. + sess := mqttSessionCreate(jsa, clientID, hash, smsg.Sequence, opts) + sess.domainTk = as.domainTk + sess.clean = ps.Clean + sess.subs = ps.Subs + sess.cons = ps.Cons + sess.pubRelConsumer = ps.PubRel + as.addSession(sess, true) + return sess, true, nil +} + +// Sends a request to delete a message, but does not wait for the response. +// +// No lock held on entry. +func (as *mqttAccountSessionManager) deleteRetainedMsg(seq uint64) { + as.jsa.deleteMsg(mqttRetainedMsgsStreamName, seq, false) +} + +// Sends a message indicating that a retained message on a given subject and stream sequence +// is being removed. +// NOTE: This is maintained for backward compatibility reasons. Should be removed in 2.14/2.15? +func (as *mqttAccountSessionManager) notifyRetainedMsgDeleted(subject string, seq uint64) { + req := mqttRetMsgDel{ + Subject: subject, + Seq: seq, + } + b, _ := json.Marshal(&req) + jsa := &as.jsa + jsa.sendq.push(&mqttJSPubMsg{ + subj: jsa.rplyr + mqttJSARetainedMsgDel, + msg: b, + }) +} + +func (as *mqttAccountSessionManager) transferUniqueSessStreamsToMuxed(log *Server) { + // Set retry to true, will be set to false on success. + retry := true + defer func() { + if retry { + next := mqttDefaultTransferRetry + log.Warnf("Failed to transfer all MQTT session streams, will try again in %v", next) + time.AfterFunc(next, func() { as.transferUniqueSessStreamsToMuxed(log) }) + } + }() + + jsa := &as.jsa + sni, err := jsa.newRequestEx(mqttJSAStreamNames, JSApiStreams, _EMPTY_, 0, nil) + if err != nil { + log.Errorf("Unable to transfer MQTT session streams: %v", err) + return + } + snames := sni.(*JSApiStreamNamesResponse) + if snames.Error != nil { + log.Errorf("Unable to transfer MQTT session streams: %v", snames.ToError()) + return + } + var oldMQTTSessStreams []string + for _, sn := range snames.Streams { + if strings.HasPrefix(sn, mqttSessionsStreamNamePrefix) { + oldMQTTSessStreams = append(oldMQTTSessStreams, sn) + } + } + ns := len(oldMQTTSessStreams) + if ns == 0 { + // Nothing to do + retry = false + return + } + log.Noticef("Transferring %v MQTT session streams...", ns) + for _, sn := range oldMQTTSessStreams { + log.Noticef(" Transferring stream %q to %q", sn, mqttSessStreamName) + smsg, err := jsa.loadLastMsgFor(sn, sn) + if err != nil { + log.Errorf(" Unable to load session record: %v", err) + return + } + ps := &mqttPersistedSession{} + if err := json.Unmarshal(smsg.Data, ps); err != nil { + log.Warnf(" Unable to unmarshal the content of this stream, may not be a legitimate MQTT session stream, skipping") + continue + } + // Store record to MQTT session stream + if _, err := jsa.storeSessionMsg(as.domainTk, getHash(ps.ID), 0, smsg.Data); err != nil { + log.Errorf(" Unable to transfer the session record: %v", err) + return + } + jsa.deleteStream(sn) + } + log.Noticef("Transfer of %v MQTT session streams done!", ns) + retry = false +} + +func (as *mqttAccountSessionManager) transferRetainedToPerKeySubjectStream(log *Server) error { + jsa := &as.jsa + var processed int + var transferred int + + start := time.Now() + deadline := start.Add(mqttRetainedTransferTimeout) + for { + // Try and look up messages on the original undivided "$MQTT.rmsgs" subject. + // If nothing is returned here, we assume to have migrated all old messages. + smsg, err := jsa.loadNextMsgFor(mqttRetainedMsgsStreamName, "$MQTT.rmsgs") + if IsNatsErr(err, JSNoMessageFoundErr) { + // We've ran out of messages to transfer, done. + break + } + if err != nil { + log.Warnf(" Unable to transfer a retained message: failed to load from '$MQTT.rmsgs': %s", err) + return err + } + + // Unmarshal the message so that we can obtain the subject name. Do not + // use mqttDecodeRetainedMessage() here because these messages are from + // older versions, and contain the full JSON encoding in payload. + var rmsg mqttRetainedMsg + if err = json.Unmarshal(smsg.Data, &rmsg); err == nil { + // Store the message again, this time with the new per-key subject. + subject := mqttRetainedMsgsStreamSubject + rmsg.Subject + if _, err = jsa.storeMsg(subject, 0, smsg.Data); err != nil { + log.Errorf(" Unable to transfer the retained message with sequence %d: %v", smsg.Sequence, err) } + transferred++ + } else { + log.Warnf(" Unable to unmarshal retained message with sequence %d, skipping", smsg.Sequence) + } + + // Delete the original message. + if err := jsa.deleteMsg(mqttRetainedMsgsStreamName, smsg.Sequence, true); err != nil { + log.Errorf(" Unable to clean up the retained message with sequence %d: %v", smsg.Sequence, err) + return err + } + processed++ + + now := time.Now() + if now.After(deadline) { + err := fmt.Errorf("timed out while transferring retained messages from '$MQTT.rmsgs' after %v, %d processed, %d successfully transferred", now.Sub(start), processed, transferred) + log.Noticef(err.Error()) + return err } } + if processed > 0 { + log.Noticef("Processed %d messages from '$MQTT.rmsgs', successfully transferred %d in %v", processed, transferred, time.Since(start)) + } else { + log.Debugf("No messages found to transfer from '$MQTT.rmsgs'") + } + return nil } -// Returns in the provided slice all publish retained message records that -// match the given subscription's `subject` (which could have wildcards). +func (as *mqttAccountSessionManager) getCachedRetainedMsg(subject string) *mqttRetainedMsg { + v, ok := as.rmsCache.Load(subject) + if !ok { + return nil + } + rm := v.(*mqttRetainedMsg) + if rm.expiresFromCache.Before(time.Now()) { + as.rmsCache.Delete(subject) + return nil + } + return rm +} + +// If cache is enabled, the expiration for the `rm` is bumped by +// `mqttRetainedCacheTTL` seconds. +// If `onlyReplace` is true, then the `rm` object is stored in the cache using +// the `subject` key only if there was already an object stored under that key. +// If `copyMsgBytes` is true, then the `rm.Msg` bytes are copied (because it +// references some buffer that is not owned by the caller). // -// Account session manager lock held on entry. -func (as *mqttAccountSessionManager) getRetainedPublishMsgs(subject string, rms *[]*mqttRetainedMsg) { - result := as.sl.ReverseMatch(subject) - if len(result.psubs) == 0 { +// Note: currently `onlyReplace` and `cloneMsgBytes` always have the same +// value (all `true` or all `false`) however we use different booleans to +// better express the intent. +func (as *mqttAccountSessionManager) setCachedRetainedMsg(subject string, rm *mqttRetainedMsg, onlyReplace, copyMsgBytes bool) { + if rm == nil { return } - for _, sub := range result.psubs { - // Since this is a reverse match, the subscription objects here - // contain literals corresponding to the published subjects. - if rm, ok := as.retmsgs[string(sub.subject)]; ok { - *rms = append(*rms, rm) + rm.expiresFromCache = time.Now().Add(mqttRetainedCacheTTL) + if onlyReplace { + if _, ok := as.rmsCache.Load(subject); !ok { + return } } + if copyMsgBytes { + rm.Msg = copyBytes(rm.Msg) + } + as.rmsCache.Store(subject, rm) } ////////////////////////////////////////////////////////////////////////////// @@ -1089,64 +3190,130 @@ func (as *mqttAccountSessionManager) getRetainedPublishMsgs(subject string, rms // Returns a new mqttSession object with max ack pending set based on // option or use mqttDefaultMaxAckPending if no option set. -func mqttSessionCreate(opts *Options) *mqttSession { +func mqttSessionCreate(jsa *mqttJSA, id, idHash string, seq uint64, opts *Options) *mqttSession { maxp := opts.MQTT.MaxAckPending if maxp == 0 { maxp = mqttDefaultMaxAckPending } - return &mqttSession{maxp: maxp} + + return &mqttSession{ + jsa: jsa, + id: id, + idHash: idHash, + seq: seq, + maxp: maxp, + pubRelSubject: mqttPubRelSubjectPrefix + idHash, + pubRelDeliverySubject: mqttPubRelDeliverySubjectPrefix + idHash, + pubRelDeliverySubjectB: []byte(mqttPubRelDeliverySubjectPrefix + idHash), + } } // Persists a session. Note that if the session's current client does not match // the given client, nothing is done. // -// Lock held on entry. -func (sess *mqttSession) save(clientID string) error { +// Lock not held on entry. +func (sess *mqttSession) save() error { + sess.mu.Lock() ps := mqttPersistedSession{ - ID: clientID, - Clean: sess.clean, - Subs: sess.subs, - } - if l := len(sess.cons); l > 0 { - cons := make(map[string]string, l) - for sid, jscons := range sess.cons { - cons[sid] = jscons.Name() - } - ps.Cons = cons + Origin: sess.jsa.id, + ID: sess.id, + Clean: sess.clean, + Subs: sess.subs, + Cons: sess.cons, + PubRel: sess.pubRelConsumer, } - sessBytes, _ := json.Marshal(&ps) - newSeq, _, err := sess.stream.store.StoreMsg("sessions", nil, sessBytes) + b, _ := json.Marshal(&ps) + + domainTk, cidHash := sess.domainTk, sess.idHash + seq := sess.seq + sess.mu.Unlock() + + var hdr int + if seq != 0 { + bb := bytes.Buffer{} + bb.WriteString(hdrLine) + bb.WriteString(JSExpectedLastSubjSeq) + bb.WriteString(":") + bb.WriteString(strconv.FormatInt(int64(seq), 10)) + bb.WriteString(CR_LF) + bb.WriteString(CR_LF) + hdr = bb.Len() + bb.Write(b) + b = bb.Bytes() + } + + resp, err := sess.jsa.storeSessionMsg(domainTk, cidHash, hdr, b) if err != nil { - return err + return fmt.Errorf("unable to persist session %q (seq=%v): %v", ps.ID, seq, err) } - if sess.sseq != 0 { - sess.stream.DeleteMsg(sess.sseq) - } - sess.sseq = newSeq + sess.mu.Lock() + sess.seq = resp.Sequence + sess.mu.Unlock() return nil } -// Delete JS consumers for this session and delete the persisted session from -// the stream. +// Clear the session. // -// Lock held on entry. -func (sess *mqttSession) clear() { - for consName, cons := range sess.cons { - delete(sess.cons, consName) - cons.Delete() +// Runs from the client's readLoop. +// Lock not held on entry, but session is in the locked map. +func (sess *mqttSession) clear(noWait bool) error { + var durs []string + var pubRelDur string + + sess.mu.Lock() + id := sess.id + seq := sess.seq + if l := len(sess.cons); l > 0 { + durs = make([]string, 0, l) + } + for sid, cc := range sess.cons { + delete(sess.cons, sid) + durs = append(durs, cc.Durable) + } + if sess.pubRelConsumer != nil { + pubRelDur = sess.pubRelConsumer.Durable + } + + sess.subs = nil + sess.pendingPublish = nil + sess.pendingPubRel = nil + sess.cpending = nil + sess.pubRelConsumer = nil + sess.seq = 0 + sess.tmaxack = 0 + sess.mu.Unlock() + + for _, dur := range durs { + if _, err := sess.jsa.deleteConsumer(mqttStreamName, dur, noWait); isErrorOtherThan(err, JSConsumerNotFoundErr) { + return fmt.Errorf("unable to delete consumer %q for session %q: %v", dur, sess.id, err) + } } - if sess.stream != nil && sess.sseq != 0 { - sess.stream.DeleteMsg(sess.sseq) - sess.sseq = 0 + if pubRelDur != _EMPTY_ { + _, err := sess.jsa.deleteConsumer(mqttOutStreamName, pubRelDur, noWait) + if isErrorOtherThan(err, JSConsumerNotFoundErr) { + return fmt.Errorf("unable to delete consumer %q for session %q: %v", pubRelDur, sess.id, err) + } + } + + if seq > 0 { + err := sess.jsa.deleteMsg(mqttSessStreamName, seq, !noWait) + // Ignore the various errors indicating that the message (or sequence) + // is already deleted, can happen in a cluster. + if isErrorOtherThan(err, JSSequenceNotFoundErrF) { + if isErrorOtherThan(err, JSStreamMsgDeleteFailedF) || !strings.Contains(err.Error(), ErrStoreMsgNotFound.Error()) { + return fmt.Errorf("unable to delete session %q record at sequence %v: %v", id, seq, err) + } + } } - sess.subs, sess.pending, sess.cpending = nil, nil, nil + return nil } // This will update the session record for this client in the account's MQTT // sessions stream if the session had any change in the subscriptions. // -// Lock held on entry. -func (sess *mqttSession) update(clientID string, filters []*mqttFilter, add bool) error { +// Runs from the client's readLoop. +// Lock not held on entry, but session is in the locked map. +func (sess *mqttSession) update(filters []*mqttFilter, add bool) error { // Evaluate if we need to persist anything. var needUpdate bool for _, f := range filters { @@ -1170,100 +3337,233 @@ func (sess *mqttSession) update(clientID string, filters []*mqttFilter, add bool } var err error if needUpdate { - err = sess.save(clientID) + err = sess.save() } return err } -// If both pQos and sub.mqtt.qos are > 0, then this will return the next -// packet identifier to use for a published message. +func (sess *mqttSession) bumpPI() uint16 { + var avail bool + next := sess.last_pi + for i := 0; i < 0xFFFF; i++ { + next++ + if next == 0 { + next = 1 + } + + _, usedInPublish := sess.pendingPublish[next] + _, usedInPubRel := sess.pendingPubRel[next] + if !usedInPublish && !usedInPubRel { + sess.last_pi = next + avail = true + break + } + } + if !avail { + return 0 + } + return sess.last_pi +} + +// trackPublishRetained is invoked when a retained (QoS) message is published. +// It need a new PI to be allocated, so we add it to the pendingPublish map, +// with an empty value. Since cpending (not pending) is used to serialize the PI +// mappings, we need to add this PI there as well. Make a unique key by using +// mqttRetainedMsgsStreamName for the durable name, and PI for sseq. // // Lock held on entry -func (sess *mqttSession) getPubAckIdentifier(pQos byte, sub *subscription) uint16 { - pi, _ := sess.trackPending(pQos, _EMPTY_, sub) +func (sess *mqttSession) trackPublishRetained() uint16 { + // Make sure we initialize the tracking maps. + if sess.pendingPublish == nil { + sess.pendingPublish = make(map[uint16]*mqttPending) + } + if sess.cpending == nil { + sess.cpending = make(map[string]map[uint64]uint16) + } + + pi := sess.bumpPI() + if pi == 0 { + return 0 + } + sess.pendingPublish[pi] = &mqttPending{} + return pi } -// If publish message QoS (pQos) and the subscription's QoS are both at least 1, -// this function will assign a packet identifier (pi) and will keep track of -// the pending ack. If the message has already been redelivered (reply != ""), -// the returned boolean will be `true`. +// trackPublish is invoked when a (QoS) PUBLISH message is to be delivered. It +// detects an untracked (new) message based on its sequence extracted from its +// delivery-time jsAckSubject, and adds it to the tracking maps. Returns a PI to +// use for the message (new, or previously used), and whether this is a +// duplicate delivery attempt. // // Lock held on entry -func (sess *mqttSession) trackPending(pQos byte, reply string, sub *subscription) (uint16, bool) { - if pQos == 0 || sub.mqtt.qos == 0 { - return 0, false - } +func (sess *mqttSession) trackPublish(jsDur, jsAckSubject string) (uint16, bool) { var dup bool var pi uint16 - bumpPI := func() uint16 { - var avail bool - next := sess.ppi - for i := 0; i < 0xFFFF; i++ { - next++ - if next == 0 { - next = 1 - } - if _, used := sess.pending[next]; !used { - sess.ppi = next - avail = true - break - } + if jsAckSubject == _EMPTY_ || jsDur == _EMPTY_ { + return 0, false + } + + // Make sure we initialize the tracking maps. + if sess.pendingPublish == nil { + sess.pendingPublish = make(map[uint16]*mqttPending) + } + if sess.cpending == nil { + sess.cpending = make(map[string]map[uint64]uint16) + } + + // Get the stream sequence and duplicate flag from the ack reply subject. + sseq, _, dcount := ackReplyInfo(jsAckSubject) + if dcount > 1 { + dup = true + } + + var ack *mqttPending + sseqToPi, ok := sess.cpending[jsDur] + if !ok { + sseqToPi = make(map[uint64]uint16) + sess.cpending[jsDur] = sseqToPi + } else { + pi = sseqToPi[sseq] + } + + if pi != 0 { + // There is a possible race between a PUBLISH re-delivery calling us, + // and a PUBREC received already having submitting a PUBREL into JS . If + // so, indicate no need for (re-)delivery by returning a PI of 0. + _, usedForPubRel := sess.pendingPubRel[pi] + if /*dup && */ usedForPubRel { + return 0, false + } + + // We should have a pending JS ACK for this PI. + ack = sess.pendingPublish[pi] + } else { + // sess.maxp will always have a value > 0. + if len(sess.pendingPublish) >= int(sess.maxp) { + // Indicate that we did not assign a packet identifier. + // The caller will not send the message to the subscription + // and JS will redeliver later, based on consumer's AckWait. + return 0, false + } + + pi = sess.bumpPI() + if pi == 0 { + return 0, false + } + + sseqToPi[sseq] = pi + } + + if ack == nil { + sess.pendingPublish[pi] = &mqttPending{ + jsDur: jsDur, + sseq: sseq, + jsAckSubject: jsAckSubject, + } + } else { + ack.jsAckSubject = jsAckSubject + ack.sseq = sseq + ack.jsDur = jsDur + } + + return pi, dup +} + +// Stops a PI from being tracked as a PUBLISH. It can still be in use for a +// pending PUBREL. +// +// Lock held on entry +func (sess *mqttSession) untrackPublish(pi uint16) (jsAckSubject string) { + ack, ok := sess.pendingPublish[pi] + if !ok { + return _EMPTY_ + } + + delete(sess.pendingPublish, pi) + if len(sess.pendingPublish) == 0 { + sess.last_pi = 0 + } + + if len(sess.cpending) != 0 && ack.jsDur != _EMPTY_ { + if sseqToPi := sess.cpending[ack.jsDur]; sseqToPi != nil { + delete(sseqToPi, ack.sseq) } - if !avail { - return 0 + } + + return ack.jsAckSubject +} + +// trackAsPubRel is invoked in 2 cases: (a) when we receive a PUBREC and we need +// to change from tracking the PI as a PUBLISH to a PUBREL; and (b) when we +// attempt to deliver the PUBREL to record the JS ack subject for it. +// +// Lock held on entry +func (sess *mqttSession) trackAsPubRel(pi uint16, jsAckSubject string) { + if sess.pubRelConsumer == nil { + // The cosumer MUST be set up already. + return + } + jsDur := sess.pubRelConsumer.Durable + + if sess.pendingPubRel == nil { + sess.pendingPubRel = make(map[uint16]*mqttPending) + } + + if jsAckSubject == _EMPTY_ { + sess.pendingPubRel[pi] = &mqttPending{ + jsDur: jsDur, } - return sess.ppi + return } - if reply == _EMPTY_ || sub.mqtt.jsCons == nil { - return bumpPI(), false - } + sseq, _, _ := ackReplyInfo(jsAckSubject) - // Here, we have an ACK subject and a JS consumer... - jsCons := sub.mqtt.jsCons - if sess.pending == nil { - sess.pending = make(map[uint16]*mqttPending) - sess.cpending = make(map[*Consumer]map[uint64]uint16) + if sess.cpending == nil { + sess.cpending = make(map[string]map[uint64]uint16) } - // Get the stream sequence and other from the ack reply subject - sseq, dseq, dcount := ackReplyInfo(reply) - - var pending *mqttPending - // For this JS consumer, check to see if we already have sseq->pi - sseqToPi, ok := sess.cpending[jsCons] - if !ok { + sseqToPi := sess.cpending[jsDur] + if sseqToPi == nil { sseqToPi = make(map[uint64]uint16) - sess.cpending[jsCons] = sseqToPi - } else if pi, ok = sseqToPi[sseq]; ok { - // If we already have a pi, get the ack so we update it. - // We will reuse the save packet identifier (pi). - pending = sess.pending[pi] + sess.cpending[jsDur] = sseqToPi } - if pi == 0 { - // sess.maxp will always have a value > 0. - if len(sess.pending) >= int(sess.maxp) { - // Indicate that we did not assign a packet identifier. - // The caller will not send the message to the subscription - // and JS will redeliver later, based on consumer's AckWait. - sess.stalled = true - return 0, false - } - pi = bumpPI() - sseqToPi[sseq] = pi + sseqToPi[sseq] = pi + sess.pendingPubRel[pi] = &mqttPending{ + jsDur: sess.pubRelConsumer.Durable, + sseq: sseq, + jsAckSubject: jsAckSubject, } - if pending == nil { - pending = &mqttPending{jsCons: jsCons, sseq: sseq} - sess.pending[pi] = pending +} + +// Stops a PI from being tracked as a PUBREL. +// +// Lock held on entry +func (sess *mqttSession) untrackPubRel(pi uint16) (jsAckSubject string) { + ack, ok := sess.pendingPubRel[pi] + if !ok { + return _EMPTY_ } - // Update pending with consumer delivery sequence and count - pending.dseq, pending.dcount = dseq, dcount - // If redelivery, return DUP flag - if dcount > 1 { - dup = true + + delete(sess.pendingPubRel, pi) + + if sess.pubRelConsumer != nil && len(sess.cpending) > 0 { + if sseqToPi := sess.cpending[ack.jsDur]; sseqToPi != nil { + delete(sseqToPi, ack.sseq) + } } - return pi, dup + + return ack.jsAckSubject +} + +// Sends a consumer delete request, but does not wait for response. +// +// Lock not held on entry. +func (sess *mqttSession) deleteConsumer(cc *ConsumerConfig) { + sess.mu.Lock() + sess.tmaxack -= cc.MaxAckPending + sess.jsa.deleteConsumer(mqttStreamName, cc.Durable, true) + sess.mu.Unlock() } ////////////////////////////////////////////////////////////////////////////// @@ -1273,14 +3573,7 @@ func (sess *mqttSession) trackPending(pQos byte, reply string, sub *subscription ////////////////////////////////////////////////////////////////////////////// // Parse the MQTT connect protocol -func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProto, error) { - - // Make sure that we have the expected length in the buffer, - // and if not, this will read it from the underlying reader. - if err := r.ensurePacketInBuffer(pl); err != nil { - return 0, nil, err - } - +func (c *client) mqttParseConnect(r *mqttReader, hasMappings bool) (byte, *mqttConnectProto, error) { // Protocol name proto, err := r.readBytes("protocol name", false) if err != nil { @@ -1315,7 +3608,7 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt // Spec [MQTT-3.1.2-3] if cp.flags&mqttConnFlagReserved != 0 { - return 0, nil, fmt.Errorf("connect flags reserved bit not set to 0") + return 0, nil, errMQTTConnFlagReserved } var hasWill bool @@ -1329,7 +3622,7 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt } // Spec [MQTT-3.1.2-15] if wretain { - return 0, nil, fmt.Errorf("if Will flag is set to 0, Will Retain flag must be 0 too") + return 0, nil, errMQTTWillAndRetainFlag } } else { // Spec [MQTT-3.1.2-14] @@ -1339,13 +3632,17 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt hasWill = true } + if c.mqtt.rejectQoS2Pub && hasWill && wqos == 2 { + return mqttConnAckRCQoS2WillRejected, nil, fmt.Errorf("server does not accept QoS2 for Will messages") + } + // Spec [MQTT-3.1.2-19] hasUser := cp.flags&mqttConnFlagUsernameFlag != 0 // Spec [MQTT-3.1.2-21] hasPassword := cp.flags&mqttConnFlagPasswordFlag != 0 // Spec [MQTT-3.1.2-22] if !hasUser && hasPassword { - return 0, nil, fmt.Errorf("password flag set but username flag is not") + return 0, nil, errMQTTPasswordFlagAndNoUser } // Keep alive @@ -1363,21 +3660,21 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt // Spec [MQTT-3.1.3-1]: client ID, will topic, will message, username, password // Client ID - cp.clientID, err = r.readString("client ID") + c.mqtt.cid, err = r.readString("client ID") if err != nil { return 0, nil, err } // Spec [MQTT-3.1.3-7] - if cp.clientID == _EMPTY_ { + if c.mqtt.cid == _EMPTY_ { if cp.flags&mqttConnFlagCleanSession == 0 { - return mqttConnAckRCIdentifierRejected, nil, fmt.Errorf("when client ID is empty, clean session flag must be set to 1") + return mqttConnAckRCIdentifierRejected, nil, errMQTTCIDEmptyNeedsCleanFlag } // Spec [MQTT-3.1.3-6] - cp.clientID = nuid.Next() + c.mqtt.cid = nuid.Next() } // Spec [MQTT-3.1.3-4] and [MQTT-3.1.3-9] - if !utf8.ValidString(cp.clientID) { - return mqttConnAckRCIdentifierRejected, nil, fmt.Errorf("invalid utf8 for client ID: %q", cp.clientID) + if !utf8.ValidString(c.mqtt.cid) { + return mqttConnAckRCIdentifierRejected, nil, fmt.Errorf("invalid utf8 for client ID: %q", c.mqtt.cid) } if hasWill { @@ -1386,34 +3683,46 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt retain: wretain, } var topic []byte - topic, err = r.readBytes("Will topic", false) + // Need to make a copy since we need to hold to this topic after the + // parsing of this protocol. + topic, err = r.readBytes("Will topic", true) if err != nil { return 0, nil, err } if len(topic) == 0 { - return 0, nil, fmt.Errorf("empty Will topic not allowed") + return 0, nil, errMQTTEmptyWillTopic } if !utf8.Valid(topic) { - return 0, nil, fmt.Errorf("invalide utf8 for Will topic %q", topic) + return 0, nil, fmt.Errorf("invalid utf8 for Will topic %q", topic) } // Convert MQTT topic to NATS subject - var copied bool - copied, topic, err = mqttTopicToNATSPubSubject(topic) + cp.will.subject, err = mqttTopicToNATSPubSubject(topic) if err != nil { return 0, nil, err } - if !copied { - topic = copyBytes(topic) + // Check for subject mapping. + if hasMappings { + // For selectMappedSubject to work, we need to have c.pa.subject set. + // If there is a change, c.pa.mapped will be set after the call. + c.pa.subject = cp.will.subject + if changed := c.selectMappedSubject(); changed { + // We need to keep track of the NATS subject/mapped in the `cp` structure. + cp.will.subject = c.pa.subject + cp.will.mapped = c.pa.mapped + // We also now need to map the original MQTT topic to the new topic + // based on the new subject. + topic = natsSubjectToMQTTTopic(cp.will.subject) + } + // Reset those now. + c.pa.subject, c.pa.mapped = nil, nil } cp.will.topic = topic - // Now will message - var msg []byte - msg, err = r.readBytes("Will message", false) + // Now "will" message. + // Ask for a copy since we need to hold to this after parsing of this protocol. + cp.will.message, err = r.readBytes("Will message", true) if err != nil { return 0, nil, err } - cp.will.message = make([]byte, 0, len(msg)) - cp.will.message = append(cp.will.message, msg...) } if hasUser { @@ -1422,7 +3731,7 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt return 0, nil, err } if c.opts.Username == _EMPTY_ { - return mqttConnAckRCBadUserOrPassword, nil, fmt.Errorf("empty user name not allowed") + return mqttConnAckRCBadUserOrPassword, nil, errMQTTEmptyUsername } // Spec [MQTT-3.1.3-11] if !utf8.ValidString(c.opts.Username) { @@ -1436,12 +3745,13 @@ func (c *client) mqttParseConnect(r *mqttReader, pl int) (byte, *mqttConnectProt return 0, nil, err } c.opts.Token = c.opts.Password + c.opts.JWT = c.opts.Password } return 0, cp, nil } func (c *client) mqttConnectTrace(cp *mqttConnectProto) string { - trace := fmt.Sprintf("clientID=%s", cp.clientID) + trace := fmt.Sprintf("clientID=%s", c.mqtt.cid) if cp.rd > 0 { trace += fmt.Sprintf(" keepAlive=%v", cp.rd) } @@ -1449,6 +3759,9 @@ func (c *client) mqttConnectTrace(cp *mqttConnectProto) string { trace += fmt.Sprintf(" will=(topic=%s QoS=%v retain=%v)", cp.will.topic, cp.will.qos, cp.will.retain) } + if cp.flags&mqttConnFlagCleanSession != 0 { + trace += " clean" + } if c.opts.Username != _EMPTY_ { trace += fmt.Sprintf(" username=%s", c.opts.Username) } @@ -1458,6 +3771,24 @@ func (c *client) mqttConnectTrace(cp *mqttConnectProto) string { return trace } +// Process the CONNECT packet. +// +// For the first session on the account, an account session manager will be created, +// along with the JetStream streams/consumer necessary for the working of MQTT. +// +// The session, identified by a client ID, will be registered, or if already existing, +// will be resumed. If the session exists but is associated with an existing client, +// the old client is evicted, as per the specifications. +// +// Due to specific locking requirements around JS API requests, we cannot hold some +// locks for the entire duration of processing of some protocols, therefore, we use +// a map that registers the client ID in a "locked" state. If a different client tries +// to connect and the server detects that the client ID is in that map, it will try +// a little bit until it is not, or fail the new client, since we can't protect +// processing of protocols in the original client. This is not expected to happen often. +// +// Runs from the client's readLoop. +// No lock held on entry. func (s *Server) mqttProcessConnect(c *client, cp *mqttConnectProto, trace bool) error { sendConnAck := func(rc byte, sessp bool) { c.mqttEnqueueConnAck(rc, sessp) @@ -1467,39 +3798,101 @@ func (s *Server) mqttProcessConnect(c *client, cp *mqttConnectProto, trace bool) } c.mu.Lock() + cid := c.mqtt.cid c.clearAuthTimer() c.mu.Unlock() if !s.isClientAuthorized(c) { - sendConnAck(mqttConnAckRCNotAuthorized, false) - c.closeConnection(AuthenticationViolation) + if trace { + c.traceOutOp("CONNACK", []byte(fmt.Sprintf("sp=%v rc=%v", false, mqttConnAckRCNotAuthorized))) + } + c.authViolation() return ErrAuthentication } - // Now that we are are authenticated, we have the client bound to the account. + // Now that we are authenticated, we have the client bound to the account. // Get the account's level MQTT sessions manager. If it does not exists yet, // this will create it along with the streams where sessions and messages // are stored. - sm := &s.mqtt.sessmgr - asm, err := sm.getOrCreateAccountSessionManager(cp.clientID, c) + asm, err := s.getOrCreateMQTTAccountSessionManager(c) if err != nil { return err } - // Rest of code runs under the account's sessions manager write lock. + // Most of the session state is altered only in the readLoop so does not + // need locking. For things that can be access in the readLoop and in + // callbacks, we will use explicit locking. + // To prevent other clients to connect with the same client ID, we will + // add the client ID to a "locked" map so that the connect somewhere else + // is put on hold. + // This keep track of how many times this client is detecting that its + // client ID is in the locked map. After a short amount, the server will + // fail this inbound client. + locked := 0 + +CHECK: asm.mu.Lock() - defer asm.mu.Unlock() + // Check if different applications keep trying to connect with the same + // client ID at the same time. + if tm, ok := asm.flappers[cid]; ok { + // If the last time it tried to connect was more than 1 sec ago, + // then accept and remove from flappers map. + if time.Now().UnixNano()-tm > int64(mqttSessJailDur) { + asm.removeSessFromFlappers(cid) + } else { + // Will hold this client for a second and then close it. We + // do this so that if the client has a reconnect feature we + // don't end-up with very rapid flapping between apps. + // We need to wait in place and not schedule the connection + // close because if this is a misbehaved client that does + // not wait for the CONNACK and sends other protocols, the + // server would not have a fully setup client and may panic. + asm.mu.Unlock() + select { + case <-s.quitCh: + case <-time.After(mqttSessJailDur): + } + c.closeConnection(DuplicateClientID) + return ErrConnectionClosed + } + } + // If an existing session is in the process of processing some packet, we can't + // evict the old client just yet. So try again to see if the state clears, but + // if it does not, then we have no choice but to fail the new client instead of + // the old one. + if _, ok := asm.sessLocked[cid]; ok { + asm.mu.Unlock() + if locked++; locked == 10 { + return fmt.Errorf("other session with client ID %q is in the process of connecting", cid) + } + time.Sleep(100 * time.Millisecond) + goto CHECK + } + + // Register this client ID the "locked" map for the duration if this function. + asm.sessLocked[cid] = struct{}{} + // And remove it on exit, regardless of error or not. + defer func() { + asm.mu.Lock() + delete(asm.sessLocked, cid) + asm.mu.Unlock() + }() // Is the client requesting a clean session or not. cleanSess := cp.flags&mqttConnFlagCleanSession != 0 // Session present? Assume false, will be set to true only when applicable. sessp := false // Do we have an existing session for this client ID - es, ok := asm.sessions[cp.clientID] - if !ok { - es = mqttSessionCreate(s.getOpts()) + es, exists := asm.sessions[cid] + asm.mu.Unlock() + + // The session is not in the map, but may be on disk, so try to recover + // or create the stream if not. + if !exists { + es, exists, err = asm.createOrRestoreSession(cid, s.getOpts()) + if err != nil { + return err + } } - es.mu.Lock() - defer es.mu.Unlock() - if ok { + if exists { // Clear the session if client wants a clean session. // Also, Spec [MQTT-3.2.2-1]: don't report session present if cleanSess || es.clean { @@ -1508,7 +3901,10 @@ func (s *Server) mqttProcessConnect(c *client, cp *mqttConnectProto, trace bool) // This Session lasts as long as the Network Connection. State data // associated with this Session MUST NOT be reused in any subsequent // Session. - es.clear() + if err := es.clear(false); err != nil { + asm.removeSession(es, true) + return err + } } else { // Report to the client that the session was present sessp = true @@ -1516,24 +3912,43 @@ func (s *Server) mqttProcessConnect(c *client, cp *mqttConnectProto, trace bool) // Spec [MQTT-3.1.4-2]. If the ClientId represents a Client already // connected to the Server then the Server MUST disconnect the existing // client. - if ec := es.c; ec != nil { + // Bind with the new client. This needs to be protected because can be + // accessed outside of the readLoop. + es.mu.Lock() + ec := es.c + es.c = c + es.clean = cleanSess + // Clear this flag so we resubscribe to PUBREL subject is needed. + es.pubRelSubscribed = false + es.mu.Unlock() + if ec != nil { + // Remove "will" of existing client before closing ec.mu.Lock() - // Remove will before closing ec.mqtt.cp.will = nil ec.mu.Unlock() + // Add to the map of the flappers + asm.mu.Lock() + asm.addSessToFlappers(cid) + asm.mu.Unlock() + c.Warnf("Replacing old client %q since both have the same client ID %q", ec, cid) // Close old client in separate go routine go ec.closeConnection(DuplicateClientID) } - // Bind with the new client - es.c = c - es.clean = cleanSess } else { // Spec [MQTT-3.2.2-3]: if the Server does not have stored Session state, // it MUST set Session Present to 0 in the CONNACK packet. - es.c, es.clean, es.stream = c, cleanSess, asm.sstream - es.save(cp.clientID) - // Now save this new session into the account sessions - asm.sessions[cp.clientID] = es + es.mu.Lock() + es.c, es.clean = c, cleanSess + es.mu.Unlock() + // Now add this new session into the account sessions + asm.addSession(es, true) + } + // We would need to save only if it did not exist previously, but we save + // always in case we are running in cluster mode. This will notify other + // running servers that this session is being used. + if err := es.save(); err != nil { + asm.removeSession(es, true) + return err } c.mu.Lock() c.flags.set(connectReceived) @@ -1541,32 +3956,20 @@ func (s *Server) mqttProcessConnect(c *client, cp *mqttConnectProto, trace bool) c.mqtt.asm = asm c.mqtt.sess = es c.mu.Unlock() - // - // Spec [MQTT-3.2.0-1]: CONNACK must be the first protocol sent to the - // session. However, we are going to possibly restore the subscriptions - // first and then send the CONNACK. This will help tests that restore - // a MQTT connection with subs and immediately use NATS to publish. - // In that case, message would not be received because the pub could - // occur before the subscriptions are processed here. It would be - // easy to fix test with doing a PINGREQ/PINGRESP before doing NATS pub, - // but it seems better to ensure that everything is setup before sending - // back the CONNACK. - // Note that since we are under the session lock, the subs callback will - // have to wait to acquire the lock, so we are still guaranteed to enqueue - // the CONNACK before any message. - // + + // Spec [MQTT-3.2.0-1]: CONNACK must be the first protocol sent to the session. + sendConnAck(mqttConnAckRCConnectionAccepted, sessp) + // Process possible saved subscriptions. if l := len(es.subs); l > 0 { filters := make([]*mqttFilter, 0, l) for subject, qos := range es.subs { filters = append(filters, &mqttFilter{filter: subject, qos: qos}) } - if _, err := asm.processSubs(es, cp.clientID, c, filters, false, trace); err != nil { + if _, err := asm.processSubs(es, c, filters, false, trace); err != nil { return err } } - // Now send the CONNACK - sendConnAck(mqttConnAckRCConnectionAccepted, sessp) return nil } @@ -1596,7 +3999,9 @@ func (s *Server) mqttHandleWill(c *client) { return } pp := c.mqtt.pp - pp.subject = will.topic + pp.topic = will.topic + pp.subject = will.subject + pp.mapped = will.mapped pp.msg = will.message pp.sz = len(will.message) pp.pi = 0 @@ -1605,7 +4010,7 @@ func (s *Server) mqttHandleWill(c *client) { pp.flags |= mqttPubFlagRetain } c.mu.Unlock() - s.mqttProcessPub(c, pp) + s.mqttInitiateMsgDelivery(c, pp) c.flushClients(0) } @@ -1615,35 +4020,54 @@ func (s *Server) mqttHandleWill(c *client) { // ////////////////////////////////////////////////////////////////////////////// -func (c *client) mqttParsePub(r *mqttReader, pl int, pp *mqttPublish) error { +func (c *client) mqttParsePub(r *mqttReader, pl int, pp *mqttPublish, hasMappings bool) error { qos := mqttGetQoS(pp.flags) - if qos > 1 { - return fmt.Errorf("publish QoS=%v not supported", qos) + if qos > 2 { + return fmt.Errorf("QoS=%v is invalid in MQTT", qos) } - if err := r.ensurePacketInBuffer(pl); err != nil { - return err + + if c.mqtt.rejectQoS2Pub && qos == 2 { + return fmt.Errorf("QoS=2 is disabled for PUBLISH messages") } + // Keep track of where we are when starting to read the variable header start := r.pos var err error - pp.subject, err = r.readBytes("topic", false) + pp.topic, err = r.readBytes("topic", false) if err != nil { return err } - if len(pp.subject) == 0 { - return fmt.Errorf("topic cannot be empty") + if len(pp.topic) == 0 { + return errMQTTTopicIsEmpty } // Convert the topic to a NATS subject. This call will also check that // there is no MQTT wildcards (Spec [MQTT-3.3.2-2] and [MQTT-4.7.1-1]) - // Note that this may not result in a copy if there is no special - // conversion. It is good because after the message is processed we - // won't have a reference to the buffer and we save a copy. - _, pp.subject, err = mqttTopicToNATSPubSubject(pp.subject) + // Note that this may not result in a copy if there is no conversion. + // It is good because after the message is processed we won't have a + // reference to the buffer and we save a copy. + pp.subject, err = mqttTopicToNATSPubSubject(pp.topic) if err != nil { return err } + // Check for subject mapping. + if hasMappings { + // For selectMappedSubject to work, we need to have c.pa.subject set. + // If there is a change, c.pa.mapped will be set after the call. + c.pa.subject = pp.subject + if changed := c.selectMappedSubject(); changed { + // We need to keep track of the NATS subject/mapped in the `pp` structure. + pp.subject = c.pa.subject + pp.mapped = c.pa.mapped + // We also now need to map the original MQTT topic to the new topic + // based on the new subject. + pp.topic = natsSubjectToMQTTTopic(pp.subject) + } + // Reset those now. + c.pa.subject, c.pa.mapped = nil, nil + } + if qos > 0 { pp.pi, err = r.readUint16("packet identifier") if err != nil { @@ -1678,94 +4102,363 @@ func mqttPubTrace(pp *mqttPublish) string { piStr = fmt.Sprintf(" pi=%v", pp.pi) } return fmt.Sprintf("%s dup=%v QoS=%v retain=%v size=%v%s", - pp.subject, dup, qos, retain, pp.sz, piStr) + pp.topic, dup, qos, retain, pp.sz, piStr) +} + +// mqttComputeNatsMsgSize computes the size the NATS message to be delivered +// based on a MQTT PUBLISH packet. +// encodePP: whether to encode complete MQTT PUBLISH packet header information +// - false: initial delivery (QoS 0/1) needs only base header +// - true: QoS2 storage needs to encode Nmqtt-Subject and Nmqtt-Mapped +func mqttComputeNatsMsgSize(pp *mqttPublish, encodePP bool) int { + size := len(hdrLine) + + len(mqttNatsHeader) + 2 + 2 + // 2 for ':', and 2 for CRLF + 2 + // end-of-header CRLF + pp.sz + if encodePP { + size += len(mqttNatsHeaderSubject) + 1 + // +1 for ':' + len(pp.subject) + 2 // 2 for CRLF + + if len(pp.mapped) > 0 { + size += len(mqttNatsHeaderMapped) + 1 + // +1 for ':' + len(pp.mapped) + 2 // 2 for CRLF + } + } + return size } -func (s *Server) mqttProcessPub(c *client, pp *mqttPublish) { - c.pa.subject, c.pa.hdr, c.pa.size = pp.subject, -1, pp.sz +// Composes a NATS message from a MQTT PUBLISH packet. The message includes an +// internal header containint the original packet's QoS, and for QoS2 packets +// the original subject. +// +// Example (QoS2, subject: "foo.bar"): +// +// NATS/1.0\r\n +// Nmqtt-Pub:2foo.bar\r\n +// \r\n +func mqttNewDeliverableMessage(pp *mqttPublish, encodePP bool) (natsMsg []byte, headerLen int) { + size := mqttComputeNatsMsgSize(pp, encodePP) - // Convert size into bytes. - i := len(pp.szb) - if pp.sz > 0 { - for l := pp.sz; l > 0; l /= 10 { - i-- - pp.szb[i] = digits[l%10] + buf := bytes.NewBuffer(make([]byte, 0, size)) + + qos := mqttGetQoS(pp.flags) + + buf.WriteString(hdrLine) + buf.WriteString(mqttNatsHeader) + buf.WriteByte(':') + buf.WriteByte(qos + '0') + buf.WriteString(_CRLF_) + + if encodePP { + buf.WriteString(mqttNatsHeaderSubject) + buf.WriteByte(':') + buf.Write(pp.subject) + buf.WriteString(_CRLF_) + + if len(pp.mapped) > 0 { + buf.WriteString(mqttNatsHeaderMapped) + buf.WriteByte(':') + buf.Write(pp.mapped) + buf.WriteString(_CRLF_) } - } else { - i-- - pp.szb[i] = digits[0] } - c.pa.szb = pp.szb[i:] - // This will work for QoS 0 but mqtt msg delivery callback will ignore - // delivery for QoS > 0 published messages (since it is handled specifically - // with call to directProcessInboundJetStreamMsg). - // However, this needs to be invoked before directProcessInboundJetStreamMsg() - // in case we are dealing with publish retained messages. - c.processInboundClientMsg(pp.msg) - if mqttGetQoS(pp.flags) > 0 { - // Since this is the fast path, we access the messages stream directly here - // without locking. All the fields mqtt.asm.mstream are immutable. - c.mqtt.asm.mstream.processInboundJetStreamMsg(nil, c, string(c.pa.subject), "", pp.msg) + // End of header + buf.WriteString(_CRLF_) + + headerLen = buf.Len() + + buf.Write(pp.msg) + return buf.Bytes(), headerLen +} + +// Composes a NATS message for a pending PUBREL packet. The message includes an +// internal header containing the PI for PUBREL/PUBCOMP. +// +// Example (PI:123): +// +// NATS/1.0\r\n +// Nmqtt-PubRel:123\r\n +// \r\n +func mqttNewDeliverablePubRel(pi uint16) (natsMsg []byte, headerLen int) { + size := len(hdrLine) + + len(mqttNatsPubRelHeader) + 6 + 2 + // 6 for ':65535', and 2 for CRLF + 2 // end-of-header CRLF + buf := bytes.NewBuffer(make([]byte, 0, size)) + buf.WriteString(hdrLine) + buf.WriteString(mqttNatsPubRelHeader) + buf.WriteByte(':') + buf.WriteString(strconv.FormatInt(int64(pi), 10)) + buf.WriteString(_CRLF_) + buf.WriteString(_CRLF_) + return buf.Bytes(), buf.Len() +} + +// Process the PUBLISH packet. +// +// Runs from the client's readLoop. +// No lock held on entry. +func (s *Server) mqttProcessPub(c *client, pp *mqttPublish, trace bool) error { + qos := mqttGetQoS(pp.flags) + + // Enforce max_payload using existing client max payload logic (mpay) by + // checking the total NATS message size that would be processed. + if maxPayload := atomic.LoadInt32(&c.mpay); maxPayload != jwt.NoLimit { + if total := mqttComputeNatsMsgSize(pp, qos == 2); total > int(maxPayload) { + c.maxPayloadViolation(total, maxPayload) + return ErrMaxPayload + } + } + + switch qos { + case 0: + return s.mqttInitiateMsgDelivery(c, pp) + + case 1: + // [MQTT-4.3.2-2]. Initiate onward delivery of the Application Message, + // Send PUBACK. + // + // The receiver is not required to complete delivery of the Application + // Message before sending the PUBACK. When its original sender receives + // the PUBACK packet, ownership of the Application Message is + // transferred to the receiver. + err := s.mqttInitiateMsgDelivery(c, pp) + if err == nil { + c.mqttEnqueuePubResponse(mqttPacketPubAck, pp.pi, trace) + } + return err + + case 2: + // [MQTT-4.3.3-2]. Method A, Store message, send PUBREC. + // + // The receiver is not required to complete delivery of the Application + // Message before sending the PUBREC or PUBCOMP. When its original + // sender receives the PUBREC packet, ownership of the Application + // Message is transferred to the receiver. + err := s.mqttStoreQoS2MsgOnce(c, pp) + if err == nil { + c.mqttEnqueuePubResponse(mqttPacketPubRec, pp.pi, trace) + } + return err + + default: + return fmt.Errorf("unreachable: invalid QoS in mqttProcessPub: %v", qos) + } +} + +func (s *Server) mqttInitiateMsgDelivery(c *client, pp *mqttPublish) error { + natsMsg, headerLen := mqttNewDeliverableMessage(pp, false) + + // Set the client's pubarg for processing. + c.pa.subject = pp.subject + c.pa.mapped = pp.mapped + c.pa.reply = nil + c.pa.hdr = headerLen + c.pa.hdb = []byte(strconv.FormatInt(int64(c.pa.hdr), 10)) + c.pa.size = len(natsMsg) + c.pa.szb = []byte(strconv.FormatInt(int64(c.pa.size), 10)) + defer func() { + c.pa.subject = nil + c.pa.mapped = nil + c.pa.reply = nil + c.pa.hdr = -1 + c.pa.hdb = nil + c.pa.size = 0 + c.pa.szb = nil + }() + + _, permIssue := c.processInboundClientMsg(natsMsg) + if permIssue { + return nil + } + + // If QoS 0 messages don't need to be stored, other (1 and 2) do. Store them + // JetStream under "$MQTT.msgs." + if qos := mqttGetQoS(pp.flags); qos == 0 { + return nil + } + + // We need to call flushClients now since this we may have called c.addToPCD + // with destination clients (possibly a route). Without calling flushClients + // the following call may then be stuck waiting for a reply that may never + // come because the destination is not flushed (due to c.out.fsp > 0, + // see addToPCD and writeLoop for details). + c.flushClients(0) + + _, err := c.mqtt.sess.jsa.storeMsg(mqttStreamSubjectPrefix+string(c.pa.subject), headerLen, natsMsg) + + return err +} + +var mqttMaxMsgErrPattern = fmt.Sprintf("%s (%v)", ErrMaxMsgsPerSubject.Error(), JSStreamStoreFailedF) + +func (s *Server) mqttStoreQoS2MsgOnce(c *client, pp *mqttPublish) error { + // `true` means encode the MQTT PUBLISH packet in the NATS message header. + natsMsg, headerLen := mqttNewDeliverableMessage(pp, true) + + // Do not broadcast the message until it has been deduplicated and released + // by the sender. Instead store this QoS2 message as + // "$MQTT.qos2..". If the message is a duplicate, we get back + // a ErrMaxMsgsPerSubject, otherwise it does not change the flow, still need + // to send a PUBREC back to the client. The original subject (translated + // from MQTT topic) is included in the NATS header of the stored message to + // use for latter delivery. + _, err := c.mqtt.sess.jsa.storeMsg(c.mqttQoS2InternalSubject(pp.pi), headerLen, natsMsg) + + // TODO: would prefer a more robust and performant way of checking the + // error, but it comes back wrapped as an API result. + if err != nil && + (isErrorOtherThan(err, JSStreamStoreFailedF) || err.Error() != mqttMaxMsgErrPattern) { + return err + } + + return nil +} + +func (c *client) mqttQoS2InternalSubject(pi uint16) string { + return mqttQoS2IncomingMsgsStreamSubjectPrefix + c.mqtt.cid + "." + strconv.FormatUint(uint64(pi), 10) +} + +// Process a PUBREL packet (QoS2, acting as Receiver). +// +// Runs from the client's readLoop. +// No lock held on entry. +func (s *Server) mqttProcessPubRel(c *client, pi uint16, trace bool) error { + // Once done with the processing, send a PUBCOMP back to the client. + defer c.mqttEnqueuePubResponse(mqttPacketPubComp, pi, trace) + + // See if there is a message pending for this pi. All failures are treated + // as "not found". + asm := c.mqtt.asm + stored, _ := asm.jsa.loadLastMsgFor(mqttQoS2IncomingMsgsStreamName, c.mqttQoS2InternalSubject(pi)) + + if stored == nil { + // No message found, nothing to do. + return nil + } + // Best attempt to delete the message from the QoS2 stream. + asm.jsa.deleteMsg(mqttQoS2IncomingMsgsStreamName, stored.Sequence, true) + + // only MQTT QoS2 messages should be here, and they must have a subject. + h := mqttParsePublishNATSHeader(stored.Header) + if h == nil || h.qos != 2 || len(h.subject) == 0 { + return errors.New("invalid message in QoS2 PUBREL stream") } - c.pa.subject, c.pa.hdr, c.pa.size, c.pa.szb = nil, -1, 0, nil + + pp := &mqttPublish{ + topic: natsSubjectToMQTTTopic(h.subject), + subject: h.subject, + mapped: h.mapped, + msg: stored.Data, + sz: len(stored.Data), + pi: pi, + flags: h.qos << 1, + } + + return s.mqttInitiateMsgDelivery(c, pp) } // Invoked when processing an inbound client message. If the "retain" flag is // set, the message is stored so it can be later resent to (re)starting // subscriptions that match the subject. // -// Invoked from the publisher's readLoop. No client lock is held on entry. +// Invoked from the MQTT publisher's readLoop. No client lock is held on entry. func (c *client) mqttHandlePubRetain() { pp := c.mqtt.pp - if mqttIsRetained(pp.flags) { - key := string(pp.subject) - asm := c.mqtt.asm - asm.mu.Lock() - // Spec [MQTT-3.3.1-11]. Payload of size 0 removes the retained message, - // but should still be delivered as a normal message. - if pp.sz == 0 { - if asm.retmsgs != nil { - if erm, ok := asm.retmsgs[key]; ok { - delete(asm.retmsgs, key) - asm.sl.Remove(erm.sub) - if erm.sseq != 0 { - asm.rstream.DeleteMsg(erm.sseq) - } - } - } - } else { - // Spec [MQTT-3.3.1-5]. Store the retained message with its QoS. - // When coming from a publish protocol, `pp` is referencing a stack - // variable that itself possibly references the read buffer. - rm := &mqttRetainedMsg{ - Msg: copyBytes(pp.msg), - Flags: pp.flags, - Source: c.opts.Username, - } - rm = asm.handleRetainedMsg(key, rm) - rmBytes, _ := json.Marshal(rm) - // TODO: For now we will report the error but continue... - seq, _, err := asm.rstream.store.StoreMsg(key, nil, rmBytes) - if err != nil { - c.mu.Lock() - acc := c.acc - c.mu.Unlock() - c.Errorf("unable to store retained message for account %q, subject %q: %v", - acc.GetName(), key, err) - } - // If it has been replaced, rm.sseq will be != 0 - if rm.sseq != 0 { - asm.rstream.DeleteMsg(rm.sseq) - } - // Keep track of current stream sequence (possibly 0 if failed to store) - rm.sseq = seq - } + retainMQTT := mqttIsRetained(pp.flags) + isBirth, _, isCertificate := sparkbParseBirthDeathTopic(pp.topic) + retainSparkbBirth := isBirth && !isCertificate - asm.mu.Unlock() + // [tck-id-topics-nbirth-mqtt] NBIRTH messages MUST be published with MQTT + // QoS equal to 0 and retain equal to false. + // + // [tck-id-conformance-mqtt-aware-nbirth-mqtt-retain] A Sparkplug Aware MQTT + // Server MUST make NBIRTH messages available on the topic: + // $sparkplug/certificates/namespace/group_id/NBIRTH/edge_node_id with the + // MQTT retain flag set to true. + if retainMQTT == retainSparkbBirth { + // (retainSparkbBirth && retainMQTT) : not valid, so ignore altogether. + // (!retainSparkbBirth && !retainMQTT) : nothing to do. + return + } - // Clear the retain flag for a normal published message. + asm := c.mqtt.asm + key := string(pp.subject) + + // Always clear the retain flag to deliver a normal published message. + defer func() { pp.flags &= ^mqttPubFlagRetain + }() + + // Spec [MQTT-3.3.1-11]. Payload of size 0 removes the retained message, but + // should still be delivered as a normal message. + // + // We used to delete the message here from our map, the stream, and notify + // the network about the delete. We no longer do that. Instead, we store + // the message with an empty body. When servers will get the empty body + // in processRetainedMsg, then will remove the message from their map. This + // effectively serializes all add/remove of retained messages without the + // need for "network" notifications about deletes (we still support that + // for backward compatibility but will be pulled in future releases). + + rm := &mqttRetainedMsg{ + Origin: asm.jsa.id, + Msg: pp.msg, // will copy these bytes later as we process rm. + Flags: pp.flags, + Source: c.opts.Username, + } + + if retainSparkbBirth { + // [tck-id-conformance-mqtt-aware-store] A Sparkplug Aware MQTT Server + // MUST store NBIRTH and DBIRTH messages as they pass through the MQTT + // Server. + // + // [tck-id-conformance-mqtt-aware-nbirth-mqtt-topic]. A Sparkplug Aware + // MQTT Server MUST make NBIRTH messages available on a topic of the + // form: $sparkplug/certificates/namespace/group_id/NBIRTH/edge_node_id + // + // [tck-id-conformance-mqtt-aware-dbirth-mqtt-topic] A Sparkplug Aware + // MQTT Server MUST make DBIRTH messages available on a topic of the + // form: + // $sparkplug/certificates/namespace/group_id/DBIRTH/edge_node_id/device_id + topic := append(sparkbCertificatesTopicPrefix, pp.topic...) + subject, _ := mqttTopicToNATSPubSubject(topic) + rm.Topic = string(topic) + rm.Subject = string(subject) + + // will use to save the retained message. + key = string(subject) + + // Store the retained message with the RETAIN flag set. + rm.Flags |= mqttPubFlagRetain + + if pp.sz > 0 { + // Copy the payload out of pp since we will be sending the message + // asynchronously. + msg := make([]byte, pp.sz) + copy(msg, pp.msg[:pp.sz]) + asm.jsa.sendMsg(key, msg) + } + + } else { // isRetained + // Spec [MQTT-3.3.1-5]. Store the retained message with its QoS. + // + // When coming from a publish protocol, `pp` is referencing a stack + // variable that itself possibly references the read buffer. + rm.Topic = string(pp.topic) + } + + // Set the key to the subject of the message for retained, or the composed + // $sparkplug subject for sparkB. + rm.Subject = key + rmBytes, hdr := mqttEncodeRetainedMessage(rm) // will copy the payload bytes + _, err := asm.jsa.storeMsg(mqttRetainedMsgsStreamSubject+key, hdr, rmBytes) + if err != nil { + c.mu.Lock() + acc := c.acc + c.mu.Unlock() + c.Errorf("unable to store retained message for account %q, subject %q: %v", + acc.GetName(), key, err) } } @@ -1774,66 +4467,126 @@ func (c *client) mqttHandlePubRetain() { // case, the retained message is removed from the map and will no longer be // sent to (re)starting subscriptions. // -// Server lock is held on entry +// Server lock MUST NOT be held on entry. func (s *Server) mqttCheckPubRetainedPerms() { sm := &s.mqtt.sessmgr sm.mu.RLock() - defer sm.mu.RUnlock() + done := len(sm.sessions) == 0 + sm.mu.RUnlock() + + if done { + return + } + + s.mu.Lock() + users := make(map[string]*User, len(s.users)) + for un, u := range s.users { + users[un] = u + } + s.mu.Unlock() + // First get a list of all of the sessions. + sm.mu.RLock() + asms := make([]*mqttAccountSessionManager, 0, len(sm.sessions)) for _, asm := range sm.sessions { + asms = append(asms, asm) + } + sm.mu.RUnlock() + + type retainedMsg struct { + subj string + rmsg *mqttRetainedMsgRef + } + + // For each session we will obtain a list of retained messages. + var _rms [128]retainedMsg + rms := _rms[:0] + for _, asm := range asms { + // Get all of the retained messages. Then we will sort them so + // that they are in sequence order, which should help the file + // store to not have to load out-of-order blocks so often. + asm.mu.RLock() + rms = rms[:0] // reuse slice + for subj, rf := range asm.retmsgs { + rms = append(rms, retainedMsg{ + subj: subj, + rmsg: rf, + }) + } + jsaID := asm.jsa.id + asm.mu.RUnlock() + slices.SortFunc(rms, func(i, j retainedMsg) int { return cmp.Compare(i.rmsg.sseq, j.rmsg.sseq) }) + perms := map[string]*perm{} - asm.mu.Lock() - for subject, rm := range asm.retmsgs { - if rm.Source == _EMPTY_ { + for _, rf := range rms { + jsm, err := asm.jsa.loadMsg(mqttRetainedMsgsStreamName, rf.rmsg.sseq) + if err != nil || jsm == nil { + continue + } + rm, err := mqttDecodeRetainedMessage(jsm.Subject, jsm.Header, jsm.Data) + if err != nil { + continue + } + // We deal only with messages that have a source (the username that produced + // this message) and were produced on this server. + if rm.Source == _EMPTY_ || rm.Origin != jsaID { continue } // Lookup source from global users. - u := s.users[rm.Source] + u := users[rm.Source] if u != nil { p, ok := perms[rm.Source] if !ok { p = generatePubPerms(u.Permissions) - perms[rm.Source] = p + perms[rm.Source] = p // possibly nil } // If there is permission and no longer allowed to publish in // the subject, remove the publish retained message from the map. - if p != nil && !pubAllowed(p, subject) { + if p != nil && !pubAllowed(p, rf.subj) { u = nil } } // Not present or permissions have changed such that the source can't - // publish on that subject anymore: remove it from the map. + // publish on that subject anymore: delete this retained message. if u == nil { - delete(asm.retmsgs, subject) - asm.rstream.DeleteMsg(rm.sseq) - asm.sl.Remove(rm.sub) + // Set the payload to empty to notify that we are deleting this + // retained message. We will send this message async. + rm.Msg = nil + rmBytes, hdrLen := mqttEncodeRetainedMessage(rm) + asm.jsa.storeMsgNoWait(mqttRetainedMsgsStreamSubject+rm.Subject, hdrLen, rmBytes) } } - asm.mu.Unlock() } } // Helper to generate only pub permissions from a Permissions object func generatePubPerms(perms *Permissions) *perm { + // If given permissions is `nil`, then it means that permissions block + // has been removed (so the user is now allowed to publish on everything) + // or was never there in the first place. Returning `nil` will let the + // caller know that there are no permissions to enforce. + if perms == nil { + return nil + } var p *perm if perms.Publish.Allow != nil { p = &perm{} p.allow = NewSublistWithCache() - } - for _, pubSubject := range perms.Publish.Allow { - sub := &subscription{subject: []byte(pubSubject)} - p.allow.Insert(sub) + for _, pubSubject := range perms.Publish.Allow { + sub := &subscription{subject: []byte(pubSubject)} + p.allow.Insert(sub) + } } if len(perms.Publish.Deny) > 0 { if p == nil { p = &perm{} } p.deny = NewSublistWithCache() - } - for _, pubSubject := range perms.Publish.Deny { - sub := &subscription{subject: []byte(pubSubject)} - p.deny.Insert(sub) + for _, pubSubject := range perms.Publish.Deny { + sub := &subscription{subject: []byte(pubSubject)} + p.deny.Insert(sub) + } } return p } @@ -1842,90 +4595,125 @@ func generatePubPerms(perms *Permissions) *perm { func pubAllowed(perms *perm, subject string) bool { allowed := true if perms.allow != nil { - r := perms.allow.Match(subject) - allowed = len(r.psubs) != 0 + np, _ := perms.allow.NumInterest(subject) + allowed = np != 0 } // If we have a deny list and are currently allowed, check that as well. if allowed && perms.deny != nil { - r := perms.deny.Match(subject) - allowed = len(r.psubs) == 0 + np, _ := perms.deny.NumInterest(subject) + allowed = np == 0 } return allowed } -func mqttWritePublish(w *mqttWriter, qos byte, dup, retain bool, subject string, pi uint16, payload []byte) { - flags := qos << 1 - if dup { - flags |= mqttPubFlagDup - } - if retain { - flags |= mqttPubFlagRetain - } - w.WriteByte(mqttPacketPub | flags) - pkLen := 2 + len(subject) + len(payload) - if qos > 0 { - pkLen += 2 - } - w.WriteVarInt(pkLen) - w.WriteString(subject) - if qos > 0 { - w.WriteUint16(pi) - } - w.Write([]byte(payload)) -} - -func (c *client) mqttEnqueuePubAck(pi uint16) { - proto := [4]byte{mqttPacketPubAck, 0x2, 0, 0} +func (c *client) mqttEnqueuePubResponse(packetType byte, pi uint16, trace bool) { + proto := [4]byte{packetType, 0x2, 0, 0} proto[2] = byte(pi >> 8) proto[3] = byte(pi) + + // Bits 3,2,1 and 0 of the fixed header in the PUBREL Control Packet are + // reserved and MUST be set to 0,0,1 and 0 respectively. The Server MUST treat + // any other value as malformed and close the Network Connection [MQTT-3.6.1-1]. + if packetType == mqttPacketPubRel { + proto[0] |= 0x2 + } + c.mu.Lock() c.enqueueProto(proto[:4]) c.mu.Unlock() -} -func mqttParsePubAck(r *mqttReader, pl int) (uint16, error) { - if err := r.ensurePacketInBuffer(pl); err != nil { - return 0, err + if trace { + name := "(???)" + switch packetType { + case mqttPacketPubAck: + name = "PUBACK" + case mqttPacketPubRec: + name = "PUBREC" + case mqttPacketPubRel: + name = "PUBREL" + case mqttPacketPubComp: + name = "PUBCOMP" + } + c.traceOutOp(name, []byte(fmt.Sprintf("pi=%v", pi))) } +} + +func mqttParsePIPacket(r *mqttReader) (uint16, error) { pi, err := r.readUint16("packet identifier") if err != nil { return 0, err } if pi == 0 { - return 0, fmt.Errorf("packet identifier cannot be 0") + return 0, errMQTTPacketIdentifierIsZero } return pi, nil } -func (c *client) mqttProcessPubAck(pi uint16) { +// Process a PUBACK (QoS1) or a PUBREC (QoS2) packet, acting as Sender. Set +// isPubRec to false to process as a PUBACK. +// +// Runs from the client's readLoop. No lock held on entry. +func (c *client) mqttProcessPublishReceived(pi uint16, isPubRec bool) (err error) { sess := c.mqtt.sess if sess == nil { - return + return errMQTTInvalidSession } + + var jsAckSubject string sess.mu.Lock() - defer sess.mu.Unlock() + // Must be the same client, and the session must have been setup for QoS2. if sess.c != c { - return + sess.mu.Unlock() + return errMQTTInvalidSession } - if ack, ok := sess.pending[pi]; ok { - delete(sess.pending, pi) - jsCons := ack.jsCons - if sseqToPi, ok := sess.cpending[jsCons]; ok { - delete(sseqToPi, ack.sseq) - } - jsCons.ackMsg(ack.sseq, ack.dseq, ack.dcount) - if len(sess.pending) == 0 { - sess.ppi = 0 - } - if sess.stalled && len(sess.pending) < int(sess.maxp) { - sess.stalled = false - for _, cons := range sess.cons { - cons.mu.Lock() - cons.forceExpirePending() - cons.mu.Unlock() - } + if isPubRec { + // The JS ACK subject for the PUBREL will be filled in at the delivery + // attempt. + sess.trackAsPubRel(pi, _EMPTY_) + } + jsAckSubject = sess.untrackPublish(pi) + sess.mu.Unlock() + + if isPubRec { + natsMsg, headerLen := mqttNewDeliverablePubRel(pi) + _, err = sess.jsa.storeMsg(sess.pubRelSubject, headerLen, natsMsg) + if err != nil { + // Failure to send out PUBREL will terminate the connection. + return err } } + + // Send the ack to JS to remove the pending message from the consumer. + sess.jsa.sendAck(jsAckSubject) + return nil +} + +func (c *client) mqttProcessPubAck(pi uint16) error { + return c.mqttProcessPublishReceived(pi, false) +} + +func (c *client) mqttProcessPubRec(pi uint16) error { + return c.mqttProcessPublishReceived(pi, true) +} + +// Runs from the client's readLoop. No lock held on entry. +func (c *client) mqttProcessPubComp(pi uint16) { + sess := c.mqtt.sess + if sess == nil { + return + } + + var jsAckSubject string + sess.mu.Lock() + if sess.c != c { + sess.mu.Unlock() + return + } + jsAckSubject = sess.untrackPubRel(pi) + sess.mu.Unlock() + + // Send the ack to JS to remove the pending message from the consumer. + sess.jsa.sendAck(jsAckSubject) } // Return the QoS from the given PUBLISH protocol's flags @@ -1937,6 +4725,32 @@ func mqttIsRetained(flags byte) bool { return flags&mqttPubFlagRetain != 0 } +func sparkbParseBirthDeathTopic(topic []byte) (isBirth, isDeath, isCertificate bool) { + if bytes.HasPrefix(topic, sparkbCertificatesTopicPrefix) { + isCertificate = true + topic = topic[len(sparkbCertificatesTopicPrefix):] + } + if !bytes.HasPrefix(topic, sparkbNamespaceTopicPrefix) { + return false, false, false + } + topic = topic[len(sparkbNamespaceTopicPrefix):] + + parts := bytes.Split(topic, []byte{'/'}) + if len(parts) < 3 || len(parts) > 4 { + return false, false, false + } + typ := bytesToString(parts[1]) + switch typ { + case sparkbNBIRTH, sparkbDBIRTH: + isBirth = true + case sparkbNDEATH, sparkbDDEATH: + isDeath = true + default: + return false, false, false + } + return isBirth, isDeath, isCertificate +} + ////////////////////////////////////////////////////////////////////////////// // // SUBSCRIBE related functions @@ -1960,9 +4774,6 @@ func (c *client) mqttParseSubsOrUnsubs(r *mqttReader, b byte, pl int, sub bool) if rf := b & 0xf; rf != expectedFlag { return 0, nil, fmt.Errorf("wrong %ssubscribe reserved flags: %x", action, rf) } - if err := r.ensurePacketInBuffer(pl); err != nil { - return 0, nil, err - } pi, err := r.readUint16("packet identifier") if err != nil { return 0, nil, fmt.Errorf("reading packet identifier: %v", err) @@ -1972,21 +4783,26 @@ func (c *client) mqttParseSubsOrUnsubs(r *mqttReader, b byte, pl int, sub bool) for r.pos < end { // Don't make a copy now because, this will happen during conversion // or when processing the sub. - filter, err := r.readBytes("topic filter", false) + topic, err := r.readBytes("topic filter", false) if err != nil { return 0, nil, err } - if len(filter) == 0 { - return 0, nil, errors.New("topic filter cannot be empty") + if len(topic) == 0 { + return 0, nil, errMQTTTopicFilterCannotBeEmpty } // Spec [MQTT-3.8.3-1], [MQTT-3.10.3-1] - if !utf8.Valid(filter) { - return 0, nil, fmt.Errorf("invalid utf8 for topic filter %q", filter) + if !utf8.Valid(topic) { + return 0, nil, fmt.Errorf("invalid utf8 for topic filter %q", topic) } var qos byte - // This won't return an error. We will find out if the subject - // is valid or not when trying to create the subscription. - _, filter, _ = mqttFilterToNATSSubject(filter) + // We are going to report if we had an error during the conversion, + // but we don't fail the parsing. When processing the sub, we will + // have an error then, and the processing of subs code will send + // the proper mqttSubAckFailure flag for this given subscription. + filter, err := mqttFilterToNATSSubject(topic) + if err != nil { + c.Errorf("invalid topic %q: %v", topic, err) + } if sub { qos, err = r.readByte("QoS") if err != nil { @@ -1997,7 +4813,8 @@ func (c *client) mqttParseSubsOrUnsubs(r *mqttReader, b byte, pl int, sub bool) return 0, nil, fmt.Errorf("subscribe QoS value must be 0, 1 or 2, got %v", qos) } } - filters = append(filters, &mqttFilter{string(filter), qos}) + f := &mqttFilter{ttopic: topic, filter: string(filter), qos: qos} + filters = append(filters, f) } // Spec [MQTT-3.8.3-3], [MQTT-3.10.3-2] if len(filters) == 0 { @@ -2006,114 +4823,339 @@ func (c *client) mqttParseSubsOrUnsubs(r *mqttReader, b byte, pl int, sub bool) return pi, filters, nil } -func mqttSubscribeTrace(filters []*mqttFilter) string { +func mqttSubscribeTrace(pi uint16, filters []*mqttFilter) string { var sep string - trace := "[" + sb := &strings.Builder{} + sb.WriteString("[") for i, f := range filters { - trace += sep + fmt.Sprintf("%s QoS=%v", f.filter, f.qos) + sb.WriteString(sep) + sb.Write(f.ttopic) + sb.WriteString(" (") + sb.WriteString(f.filter) + sb.WriteString(") QoS=") + sb.WriteString(fmt.Sprintf("%v", f.qos)) if i == 0 { sep = ", " } } - trace += "]" - return trace + sb.WriteString(fmt.Sprintf("] pi=%v", pi)) + return sb.String() } -func mqttDeliverMsgCb(sub *subscription, pc *client, subject, reply string, msg []byte) { - var ppFlags byte - var pQoS byte - var pi uint16 - var dup bool - var retained bool +// For a MQTT QoS0 subscription, we create a single NATS subscription on the +// actual subject, for instance "foo.bar". +// +// For a MQTT QoS1+ subscription, we create 2 subscriptions, one on "foo.bar" +// (as for QoS0, but sub.mqtt.qos will be 1 or 2), and one on the subject +// "$MQTT.sub." which is the delivery subject of the JS durable consumer +// with the filter subject "$MQTT.msgs.foo.bar". +// +// This callback delivers messages to the client as QoS0 messages, either +// because: (a) they have been produced as MQTT QoS0 messages (and therefore +// only this callback can receive them); (b) they are MQTT QoS1+ published +// messages but this callback is for a subscription that is QoS0; or (c) the +// published messages come from (other) NATS publishers on the subject. +// +// This callback must reject a message if it is known to be a QoS1+ published +// message and this is the callback for a QoS1+ subscription because in that +// case, it will be handled by the other callback. This avoid getting duplicate +// deliveries. +func mqttDeliverMsgCbQoS0(sub *subscription, pc *client, _ *Account, subject, reply string, rmsg []byte) { + if pc.kind == JETSTREAM && len(reply) > 0 && strings.HasPrefix(reply, jsAckPre) { + return + } // This is the client associated with the subscription. cc := sub.client // This is immutable sess := cc.mqtt.sess - // We lock to check some of the subscription's fields and if we need to - // keep track of pending acks, etc.. - sess.mu.Lock() - if sess.c != cc || sub.mqtt == nil { - sess.mu.Unlock() + + // Lock here, otherwise we may be called with sub.mqtt == nil. Ignore + // wildcard subscriptions if this subject starts with '$', per Spec + // [MQTT-4.7.2-1]. + sess.subsMu.RLock() + subQoS := sub.mqtt.qos + ignore := mqttMustIgnoreForReservedSub(sub, subject) + sess.subsMu.RUnlock() + + if ignore { return } - // Check the publisher's kind. If JETSTREAM it means that this is a persisted message - // that is being delivered. - if pc.kind == JETSTREAM { - // If there is no JS consumer attached to this subscription, it means that we are - // dealing with a bare NATS subscription, in which case we simply return to avoid - // duplicate delivery. - if sub.mqtt.jsCons == nil { - sess.mu.Unlock() + hdr, msg := pc.msgParts(rmsg) + var topic []byte + if pc.isMqtt() { + // This is an MQTT publisher directly connected to this server. + + // Check the subscription's QoS. If the message was published with a + // QoS>0 and the sub has the QoS>0 then the message will be delivered by + // mqttDeliverMsgCbQoS12. + msgQoS := mqttGetQoS(pc.mqtt.pp.flags) + if subQoS > 0 && msgQoS > 0 { return } - ppFlags = mqttPubQos1 - pQoS = 1 - // This is a QoS1 message for a QoS1 subscription, so get the pi and keep - // track of ack subject. - pi, dup = sess.trackPending(pQoS, reply, sub) - if pi == 0 { - // We have reached max pending, don't send the message now. - // JS will cause a redelivery and if by then the number of pending - // messages has fallen below threshold, the message will be resent. - sess.mu.Unlock() - return + topic = pc.mqtt.pp.topic + // If the subject is different than the one in pp.subject, then some + // mapping/transform occurred and we need to recreate the topic. + if subject != bytesToString(pc.mqtt.pp.subject) { + topic = natsSubjectStrToMQTTTopic(subject) } - // In JS case, we need to use the pc.ca.deliver value as the subject. - subject = string(pc.pa.deliver) - } else if pc.isMqtt() { - // This is a MQTT publisher... - ppFlags = pc.mqtt.pp.flags - pQoS = mqttGetQoS(ppFlags) - // If the QoS of published message and subscription is 1, then we return here to - // avoid duplicate delivery. The JetStream publisher will handle that case. - if pQoS > 0 && sub.mqtt.qos > 0 { - sess.mu.Unlock() + + } else { + // Non MQTT client, could be NATS publisher, or ROUTER, etc.. + h := mqttParsePublishNATSHeader(hdr) + + // Check the subscription's QoS. If the message was published with a + // QoS>0 (in the header) and the sub has the QoS>0 then the message will + // be delivered by mqttDeliverMsgCbQoS12. + if subQoS > 0 && h != nil && h.qos > 0 { return } - retained = mqttIsRetained(ppFlags) - } else { - // This is coming from a non MQTT publisher, so Qos 0, no dup nor retain flag, etc.. - // Should probably reject, for now just truncate. + + // If size is more than what a MQTT client can handle, we should probably reject, + // for now just truncate. if len(msg) > mqttMaxPayloadSize { msg = msg[:mqttMaxPayloadSize] } + topic = natsSubjectStrToMQTTTopic(subject) + } + + // Message never has a packet identifier nor is marked as duplicate. + pc.mqttEnqueuePublishMsgTo(cc, sub, 0, 0, false, topic, msg) +} + +// This is the callback attached to a JS durable subscription for a MQTT QoS 1+ +// sub. Only JETSTREAM should be sending a message to this subject (the delivery +// subject associated with the JS durable consumer), but in cluster mode, this +// can be coming from a route, gw, etc... We make sure that if this is the case, +// the message contains a NATS/MQTT header that indicates that this is a +// published QoS1+ message. +func mqttDeliverMsgCbQoS12(sub *subscription, pc *client, _ *Account, subject, reply string, rmsg []byte) { + // Message on foo.bar is stored under $MQTT.msgs.foo.bar, so the subject has to be + // at least as long as the stream subject prefix "$MQTT.msgs.", and after removing + // the prefix, has to be at least 1 character long. + if len(subject) < len(mqttStreamSubjectPrefix)+1 { + return + } + + hdr, msg := pc.msgParts(rmsg) + h := mqttParsePublishNATSHeader(hdr) + if pc.kind != JETSTREAM && (h == nil || h.qos == 0) { + // MQTT QoS 0 messages must be ignored, they will be delivered by the + // other callback, the direct NATS subscription. All JETSTREAM messages + // will have the header. + return + } + + // This is the client associated with the subscription. + cc := sub.client + + // This is immutable + sess := cc.mqtt.sess + + // We lock to check some of the subscription's fields and if we need to keep + // track of pending acks, etc. There is no need to acquire the subsMu RLock + // since sess.Lock is overarching for modifying subscriptions. + sess.mu.Lock() + if sess.c != cc || sub.mqtt == nil { + sess.mu.Unlock() + return } + + // In this callback we handle only QoS-published messages to QoS + // subscriptions. Ignore if either is 0, will be delivered by the other + // callback, mqttDeliverMsgCbQos1. + var qos byte + if h != nil { + qos = h.qos + } + if qos > sub.mqtt.qos { + qos = sub.mqtt.qos + } + if qos == 0 { + sess.mu.Unlock() + return + } + + // Check for reserved subject violation. If so, we will send the ack to + // remove the message, and do nothing else. + strippedSubj := subject[len(mqttStreamSubjectPrefix):] + if mqttMustIgnoreForReservedSub(sub, strippedSubj) { + sess.mu.Unlock() + sess.jsa.sendAck(reply) + return + } + + pi, dup := sess.trackPublish(sub.mqtt.jsDur, reply) + sess.mu.Unlock() + + if pi == 0 { + // We have reached max pending, don't send the message now. + // JS will cause a redelivery and if by then the number of pending + // messages has fallen below threshold, the message will be resent. + return + } + + originalTopic := natsSubjectStrToMQTTTopic(strippedSubj) + pc.mqttEnqueuePublishMsgTo(cc, sub, pi, qos, dup, originalTopic, msg) +} + +func mqttDeliverPubRelCb(sub *subscription, pc *client, _ *Account, subject, reply string, rmsg []byte) { + if sub.client.mqtt == nil || sub.client.mqtt.sess == nil || reply == _EMPTY_ { + return + } + + hdr, _ := pc.msgParts(rmsg) + pi := mqttParsePubRelNATSHeader(hdr) + if pi == 0 { + return + } + + // This is the client associated with the subscription. + cc := sub.client + + // This is immutable + sess := cc.mqtt.sess + + sess.mu.Lock() + if sess.c != cc || sess.pubRelConsumer == nil { + sess.mu.Unlock() + return + } + sess.trackAsPubRel(pi, reply) + trace := cc.trace sess.mu.Unlock() - sw := mqttWriter{} - w := &sw + cc.mqttEnqueuePubResponse(mqttPacketPubRel, pi, trace) +} + +// The MQTT Server MUST NOT match Topic Filters starting with a wildcard +// character (# or +) with Topic Names beginning with a $ character, Spec +// [MQTT-4.7.2-1]. We will return true if there is a violation. +// +// Session or subMu lock must be held on entry to protect access to sub.mqtt. +func mqttMustIgnoreForReservedSub(sub *subscription, subject string) bool { + // If the subject does not start with $ nothing to do here. + if !sub.mqtt.reserved || len(subject) == 0 || subject[0] != mqttReservedPre { + return false + } + return true +} + +// Check if a sub is a reserved wildcard. E.g. '#', '*', or '*/" prefix. +func isMQTTReservedSubscription(subject string) bool { + if len(subject) == 1 && (subject[0] == fwc || subject[0] == pwc) { + return true + } + // Match "*.<>" + if len(subject) > 1 && (subject[0] == pwc && subject[1] == btsep) { + return true + } + return false +} + +func sparkbReplaceDeathTimestamp(msg []byte) []byte { + const VARINT = 0 + const TIMESTAMP = 1 + + orig := msg + buf := bytes.NewBuffer(make([]byte, 0, len(msg)+16)) // 16 bytes should be enough if we need to add a timestamp + writeDeathTimestamp := func() { + // [tck-id-conformance-mqtt-aware-ndeath-timestamp] A Sparkplug Aware + // MQTT Server MAY replace the timestamp of NDEATH messages. If it does, + // it MUST set the timestamp to the UTC time at which it attempts to + // deliver the NDEATH to subscribed clients + // + // sparkB spec: 6.4.1. Google Protocol Buffer Schema + // optional uint64 timestamp = 1; // Timestamp at message sending time + // + // SparkplugB timestamps are milliseconds since epoch, represented as + // uint64 in go, transmitted as protobuf varint. + ts := uint64(time.Now().UnixMilli()) + buf.Write(protoEncodeVarint(TIMESTAMP<<3 | VARINT)) + buf.Write(protoEncodeVarint(ts)) + } + + for len(msg) > 0 { + fieldNumericID, fieldType, size, err := protoScanField(msg) + if err != nil { + return orig + } + if fieldType != VARINT || fieldNumericID != TIMESTAMP { + // Add the field as is + buf.Write(msg[:size]) + msg = msg[size:] + continue + } + + writeDeathTimestamp() + + // Add the rest of the message as is, we are done + buf.Write(msg[size:]) + return buf.Bytes() + } + + // Add timestamp if we did not find one. + writeDeathTimestamp() + + return buf.Bytes() +} + +// Common function to mqtt delivery callbacks to serialize and send the message +// to the `cc` client. +func (c *client) mqttEnqueuePublishMsgTo(cc *client, sub *subscription, pi uint16, qos byte, dup bool, topic, msg []byte) { + // [tck-id-conformance-mqtt-aware-nbirth-mqtt-retain] A Sparkplug Aware + // MQTT Server MUST make NBIRTH messages available on the topic: + // $sparkplug/certificates/namespace/group_id/NBIRTH/edge_node_id with + // the MQTT retain flag set to true + // + // [tck-id-conformance-mqtt-aware-dbirth-mqtt-retain] A Sparkplug Aware + // MQTT Server MUST make DBIRTH messages available on the topic: + // $sparkplug/certificates/namespace/group_id/DBIRTH/edge_node_id/device_id + // with the MQTT retain flag set to true + // + // $sparkplug/certificates messages are sent as NATS messages, so we + // need to add the retain flag when sending them to MQTT clients. + + retain := false + isBirth, isDeath, isCertificate := sparkbParseBirthDeathTopic(topic) + if isBirth && qos == 0 { + retain = isCertificate + } else if isDeath && !isCertificate { + msg = sparkbReplaceDeathTimestamp(msg) + } - flags := mqttSerializePublishMsg(w, pi, dup, retained, subject, msg) + flags, headerBytes := mqttMakePublishHeader(pi, qos, dup, retain, topic, len(msg)) cc.mu.Lock() if sub.mqtt.prm != nil { - cc.queueOutbound(sub.mqtt.prm.Bytes()) + for _, data := range sub.mqtt.prm { + cc.queueOutbound(data) + } sub.mqtt.prm = nil } - cc.queueOutbound(w.Bytes()) - pc.addToPCD(cc) - if cc.trace { + cc.queueOutbound(headerBytes) + cc.queueOutbound(msg) + c.addToPCD(cc) + trace := cc.trace + cc.mu.Unlock() + + if trace { pp := mqttPublish{ - flags: flags, - pi: pi, - subject: []byte(subject), - sz: len(msg), + topic: topic, + flags: flags, + pi: pi, + sz: len(msg), } cc.traceOutOp("PUBLISH", []byte(mqttPubTrace(&pp))) } - cc.mu.Unlock() } // Serializes to the given writer the message for the given subject. -func mqttSerializePublishMsg(w *mqttWriter, pi uint16, dup, retained bool, subject string, msg []byte) byte { - topic := natsSubjectToMQTTTopic(subject) - +func (w *mqttWriter) WritePublishHeader(pi uint16, qos byte, dup, retained bool, topic []byte, msgLen int) byte { // Compute len (will have to add packet id if message is sent as QoS>=1) - pkLen := 2 + len(topic) + len(msg) - + pkLen := 2 + len(topic) + msgLen var flags byte // Set flags for dup/retained/qos1 @@ -2123,23 +5165,30 @@ func mqttSerializePublishMsg(w *mqttWriter, pi uint16, dup, retained bool, subje if retained { flags |= mqttPubFlagRetain } - // For now, we have only QoS 1 - if pi > 0 { + if qos > 0 { pkLen += 2 - flags |= mqttPubQos1 + flags |= qos << 1 } w.WriteByte(mqttPacketPub | flags) w.WriteVarInt(pkLen) w.WriteBytes(topic) - if pi > 0 { + if qos > 0 { w.WriteUint16(pi) } - w.Write(msg) return flags } +// Serializes to the given writer the message for the given subject. +func mqttMakePublishHeader(pi uint16, qos byte, dup, retained bool, topic []byte, msgLen int) (byte, []byte) { + headerBuf := newMQTTWriter(mqttInitialPubHeader + len(topic)) + flags := headerBuf.WritePublishHeader(pi, qos, dup, retained, topic, msgLen) + return flags, headerBuf.Bytes() +} + +// Process the SUBSCRIBE packet. +// // Process the list of subscriptions and update the given filter // with the QoS that has been accepted (or failure). // @@ -2149,49 +5198,142 @@ func mqttSerializePublishMsg(w *mqttWriter, pi uint16, dup, retained bool, subje // which I read as the replacement cannot be a "remove then add" if there // is a chance that in between the 2 actions, published messages // would be "lost" because there would not be any matching subscription. +// +// Run from client's readLoop. +// No lock held on entry. func (c *client) mqttProcessSubs(filters []*mqttFilter) ([]*subscription, error) { // Those things are immutable, but since processing subs is not // really in the fast path, let's get them under the client lock. c.mu.Lock() asm := c.mqtt.asm sess := c.mqtt.sess - clientID := c.mqtt.cp.clientID trace := c.trace c.mu.Unlock() - asm.mu.RLock() - defer asm.mu.RUnlock() - return asm.processSubs(sess, clientID, c, filters, true, trace) + if err := asm.lockSession(sess, c); err != nil { + return nil, err + } + defer asm.unlockSession(sess) + return asm.processSubs(sess, c, filters, true, trace) } -func (c *client) mqttCleanupFailedSub(sub *subscription, jscons *Consumer, jssub *subscription) { - c.mu.Lock() - acc := c.acc - c.mu.Unlock() - +// Cleanup that is performed in processSubs if there was an error. +// +// Runs from client's readLoop. +// Lock not held on entry, but session is in the locked map. +func (sess *mqttSession) cleanupFailedSub(c *client, sub *subscription, cc *ConsumerConfig, jssub *subscription) { if sub != nil { - c.unsubscribe(acc, sub, true, true) + c.processUnsub(sub.sid) } if jssub != nil { - c.unsubscribe(acc, jssub, true, true) + c.processUnsub(jssub.sid) + } + if cc != nil { + sess.deleteConsumer(cc) + } +} + +// Make sure we are set up to deliver PUBREL messages to this QoS2-subscribed +// session. +func (sess *mqttSession) ensurePubRelConsumerSubscription(c *client) error { + + sess.mu.Lock() + pubRelSubscribed := sess.pubRelSubscribed + pubRelDeliverySubjectB := sess.pubRelDeliverySubjectB + pubRelDeliverySubject := sess.pubRelDeliverySubject + pubRelConsumer := sess.pubRelConsumer + sess.mu.Unlock() + + // Subscribe before the consumer is created so we don't loose any messages. + if !pubRelSubscribed { + _, err := c.processSub(pubRelDeliverySubjectB, nil, pubRelDeliverySubjectB, mqttDeliverPubRelCb, false) + if err != nil { + c.Errorf("Unable to create subscription for JetStream consumer on %q: %v", pubRelDeliverySubject, err) + return err + } + sess.mu.Lock() + sess.pubRelSubscribed = true + sess.mu.Unlock() + } + + // If the JS consumer already exists, we are done. + if pubRelConsumer != nil { + return nil + } + + opts := c.srv.getOpts() + ackWait := opts.MQTT.AckWait + if ackWait == 0 { + ackWait = mqttDefaultAckWait } - if jscons != nil { - jscons.Delete() + maxAckPending := int(opts.MQTT.MaxAckPending) + if maxAckPending == 0 { + maxAckPending = mqttDefaultMaxAckPending + } + + sess.mu.Lock() + pubRelSubject := sess.pubRelSubject + tmaxack := sess.tmaxack + idHash := sess.idHash + id := sess.id + sess.mu.Unlock() + + // Check that the limit of subs' maxAckPending are not going over the limit + if after := tmaxack + maxAckPending; after > mqttMaxAckTotalLimit { + return fmt.Errorf("max_ack_pending for all consumers would be %v which exceeds the limit of %v", + after, mqttMaxAckTotalLimit) + } + + ccr := &CreateConsumerRequest{ + Stream: mqttOutStreamName, + Config: ConsumerConfig{ + DeliverSubject: pubRelDeliverySubject, + Durable: mqttPubRelConsumerDurablePrefix + idHash, + AckPolicy: AckExplicit, + DeliverPolicy: DeliverNew, + FilterSubject: pubRelSubject, + AckWait: ackWait, + MaxAckPending: maxAckPending, + MemoryStorage: opts.MQTT.ConsumerMemoryStorage, + }, + } + if opts.MQTT.ConsumerInactiveThreshold > 0 { + ccr.Config.InactiveThreshold = opts.MQTT.ConsumerInactiveThreshold + } + if _, err := sess.jsa.createDurableConsumer(ccr); err != nil { + c.Errorf("Unable to add JetStream consumer for PUBREL for client %q: err=%v", id, err) + return err } + pubRelConsumer = &ccr.Config + tmaxack += maxAckPending + + sess.mu.Lock() + sess.pubRelConsumer = pubRelConsumer + sess.tmaxack = tmaxack + sess.mu.Unlock() + + return nil } // When invoked with a QoS of 0, looks for an existing JS durable consumer for // the given sid and if one is found, delete the JS durable consumer and unsub // the NATS subscription on the delivery subject. +// // With a QoS > 0, creates or update the existing JS durable consumer along with // its NATS subscription on a delivery subject. // -// Account session manager lock held on entry. -func (c *client) mqttProcessJSConsumer(sess *mqttSession, stream *Stream, subject, - sid string, qos byte, fromSubProto bool) (*Consumer, *subscription, error) { +// Session lock is acquired and released as needed. Session is in the locked +// map. +func (sess *mqttSession) processJSConsumer(c *client, subject, sid string, + qos byte, fromSubProto bool) (*ConsumerConfig, *subscription, error) { + + sess.mu.Lock() + cc, exists := sess.cons[sid] + tmaxack := sess.tmaxack + idHash := sess.idHash + sess.mu.Unlock() // Check if we are already a JS consumer for this SID. - cons, exists := sess.cons[sid] if exists { // If current QoS is 0, it means that we need to delete the existing // one (that was QoS > 0) @@ -2199,14 +5341,17 @@ func (c *client) mqttProcessJSConsumer(sess *mqttSession, stream *Stream, subjec // The JS durable consumer's delivery subject is on a NUID of // the form: mqttSubPrefix + . It is also used as the sid // for the NATS subscription, so use that for the lookup. - sub := c.subs[cons.Config().DeliverSubject] + c.mu.Lock() + sub := c.subs[cc.DeliverSubject] + c.mu.Unlock() + + sess.mu.Lock() delete(sess.cons, sid) - cons.Delete() + sess.mu.Unlock() + + sess.deleteConsumer(cc) if sub != nil { - c.mu.Lock() - acc := c.acc - c.mu.Unlock() - c.unsubscribe(acc, sub, true, true) + c.processUnsub(sub.sid) } return nil, nil, nil } @@ -2223,53 +5368,66 @@ func (c *client) mqttProcessJSConsumer(sess *mqttSession, stream *Stream, subjec return nil, nil, nil } var err error - inbox := mqttSubPrefix + nuid.Next() + var inbox string if exists { - cons.updateDeliverSubject(inbox) + inbox = cc.DeliverSubject } else { - durName := nuid.Next() + inbox = mqttSubPrefix + nuid.Next() opts := c.srv.getOpts() ackWait := opts.MQTT.AckWait if ackWait == 0 { ackWait = mqttDefaultAckWait } - maxAckPending := opts.MQTT.MaxAckPending + maxAckPending := int(opts.MQTT.MaxAckPending) if maxAckPending == 0 { maxAckPending = mqttDefaultMaxAckPending } - cc := &ConsumerConfig{ - DeliverSubject: inbox, - Durable: durName, - AckPolicy: AckExplicit, - DeliverPolicy: DeliverNew, - FilterSubject: subject, - AckWait: ackWait, - MaxAckPending: int(maxAckPending), - allowNoInterest: true, - } - cons, err = stream.AddConsumer(cc) - if err != nil { + + // Check that the limit of subs' maxAckPending are not going over the limit + if after := tmaxack + maxAckPending; after > mqttMaxAckTotalLimit { + return nil, nil, fmt.Errorf("max_ack_pending for all consumers would be %v which exceeds the limit of %v", + after, mqttMaxAckTotalLimit) + } + + durName := idHash + "_" + nuid.Next() + ccr := &CreateConsumerRequest{ + Stream: mqttStreamName, + Config: ConsumerConfig{ + DeliverSubject: inbox, + Durable: durName, + AckPolicy: AckExplicit, + DeliverPolicy: DeliverNew, + FilterSubject: mqttStreamSubjectPrefix + subject, + AckWait: ackWait, + MaxAckPending: maxAckPending, + MemoryStorage: opts.MQTT.ConsumerMemoryStorage, + }, + } + if opts.MQTT.ConsumerInactiveThreshold > 0 { + ccr.Config.InactiveThreshold = opts.MQTT.ConsumerInactiveThreshold + } + if _, err := sess.jsa.createDurableConsumer(ccr); err != nil { c.Errorf("Unable to add JetStream consumer for subscription on %q: err=%v", subject, err) return nil, nil, err } + cc = &ccr.Config + tmaxack += maxAckPending } + // This is an internal subscription on subject like "$MQTT.sub." that is setup - // for the JS durable's deliver subject. I don't think that there is any need to - // forward this subscription in the cluster/super cluster. - sub, err := c.processSub([]byte(inbox), nil, []byte(inbox), mqttDeliverMsgCb, true) + // for the JS durable's deliver subject. + sess.mu.Lock() + sess.tmaxack = tmaxack + sub, err := sess.processQOS12Sub(c, []byte(inbox), []byte(inbox), + isMQTTReservedSubscription(subject), qos, cc.Durable, mqttDeliverMsgCbQoS12) + sess.mu.Unlock() + if err != nil { - if !exists { - cons.Delete() - } + sess.deleteConsumer(cc) c.Errorf("Unable to create subscription for JetStream consumer on %q: %v", subject, err) return nil, nil, err } - if sub.mqtt == nil { - sub.mqtt = &mqttSub{} - } - sub.mqtt.qos = qos - sub.mqtt.jsCons = cons - return cons, sub, nil + return cc, sub, nil } // Queues the published retained messages for each subscription and signals @@ -2278,7 +5436,9 @@ func (c *client) mqttSendRetainedMsgsToNewSubs(subs []*subscription) { c.mu.Lock() for _, sub := range subs { if sub.mqtt != nil && sub.mqtt.prm != nil { - c.queueOutbound(sub.mqtt.prm.Bytes()) + for _, data := range sub.mqtt.prm { + c.queueOutbound(data) + } sub.mqtt.prm = nil } } @@ -2287,7 +5447,7 @@ func (c *client) mqttSendRetainedMsgsToNewSubs(subs []*subscription) { } func (c *client) mqttEnqueueSubAck(pi uint16, filters []*mqttFilter) { - w := &mqttWriter{} + w := newMQTTWriter(7 + len(filters)) w.WriteByte(mqttPacketSubAck) // packet length is 2 (for packet identifier) and 1 byte per filter. w.WriteVarInt(2 + len(filters)) @@ -2310,33 +5470,43 @@ func (c *client) mqttParseUnsubs(r *mqttReader, b byte, pl int) (uint16, []*mqtt return c.mqttParseSubsOrUnsubs(r, b, pl, false) } +// Process the UNSUBSCRIBE packet. +// +// Given the list of topics, this is going to unsubscribe the low level NATS subscriptions +// and delete the JS durable consumers when applicable. +// +// Runs from the client's readLoop. +// No lock held on entry. func (c *client) mqttProcessUnsubs(filters []*mqttFilter) error { // Those things are immutable, but since processing unsubs is not // really in the fast path, let's get them under the client lock. c.mu.Lock() + asm := c.mqtt.asm sess := c.mqtt.sess - clientID := c.mqtt.cp.clientID c.mu.Unlock() - sess.mu.Lock() - defer sess.mu.Unlock() - if sess.c != c { - return fmt.Errorf("client %q no longer registered with MQTT session", clientID) + if err := asm.lockSession(sess, c); err != nil { + return err } + defer asm.unlockSession(sess) removeJSCons := func(sid string) { - if jscons, ok := sess.cons[sid]; ok { + cc, ok := sess.cons[sid] + if ok { delete(sess.cons, sid) - jscons.Delete() - if seqPis, ok := sess.cpending[jscons]; ok { - delete(sess.cpending, jscons) + sess.deleteConsumer(cc) + // Need lock here since these are accessed by callbacks + sess.mu.Lock() + if seqPis, ok := sess.cpending[cc.Durable]; ok { + delete(sess.cpending, cc.Durable) for _, pi := range seqPis { - delete(sess.pending, pi) + delete(sess.pendingPublish, pi) } - if len(sess.pending) == 0 { - sess.ppi = 0 + if len(sess.pendingPublish) == 0 { + sess.last_pi = 0 } } + sess.mu.Unlock() } } for _, f := range filters { @@ -2355,11 +5525,11 @@ func (c *client) mqttProcessUnsubs(filters []*mqttFilter) error { } } } - return sess.update(clientID, filters, false) + return sess.update(filters, false) } func (c *client) mqttEnqueueUnsubAck(pi uint16) { - w := &mqttWriter{} + w := newMQTTWriter(4) w.WriteByte(mqttPacketUnsubAck) w.WriteVarInt(2) w.WriteUint16(pi) @@ -2368,17 +5538,22 @@ func (c *client) mqttEnqueueUnsubAck(pi uint16) { c.mu.Unlock() } -func mqttUnsubscribeTrace(filters []*mqttFilter) string { +func mqttUnsubscribeTrace(pi uint16, filters []*mqttFilter) string { var sep string - trace := "[" + sb := strings.Builder{} + sb.WriteString("[") for i, f := range filters { - trace += sep + f.filter + sb.WriteString(sep) + sb.Write(f.ttopic) + sb.WriteString(" (") + sb.WriteString(f.filter) + sb.WriteString(")") if i == 0 { sep = ", " } } - trace += "]" - return trace + sb.WriteString(fmt.Sprintf("] pi=%v", pi)) + return sb.String() } ////////////////////////////////////////////////////////////////////////////// @@ -2414,17 +5589,17 @@ func errOrTrace(err error, trace string) []byte { // Converts an MQTT Topic Name to a NATS Subject (used by PUBLISH) // See mqttToNATSSubjectConversion() for details. -func mqttTopicToNATSPubSubject(mt []byte) (bool, []byte, error) { +func mqttTopicToNATSPubSubject(mt []byte) ([]byte, error) { return mqttToNATSSubjectConversion(mt, false) } // Converts an MQTT Topic Filter to a NATS Subject (used by SUBSCRIBE) // See mqttToNATSSubjectConversion() for details. -func mqttFilterToNATSSubject(filter []byte) (bool, []byte, error) { +func mqttFilterToNATSSubject(filter []byte) ([]byte, error) { return mqttToNATSSubjectConversion(filter, true) } -// Converts an MQTT Topic Name or Filter to a NATS Subject +// Converts an MQTT Topic Name or Filter to a NATS Subject. // In MQTT: // - a Topic Name does not have wildcard (PUBLISH uses only topic names). // - a Topic Filter can include wildcards (SUBSCRIBE uses those). @@ -2432,95 +5607,117 @@ func mqttFilterToNATSSubject(filter []byte) (bool, []byte, error) { // - '/' is the topic level separator. // // Conversion that occurs: -// - '/' is replaced with '/.' if it is the first character in mt -// - '/' is replaced with './' if the last or next character in mt is '/' -// For instance, foo//bar would become foo./.bar -// - '/' is replaced with '.' for all other conditions (foo/bar -> foo.bar) -// - '.' and ' ' cause an error to be returned. +// - '/' is replaced with '/.' if it is the first character in mt +// - '/' is replaced with './' if the last or next character in mt is '/' +// For instance, foo//bar would become foo./.bar +// - '/' is replaced with '.' for all other conditions (foo/bar -> foo.bar) +// - '.' is replaced with '//'. +// - ' ' cause an error to be returned. // -// If a copy occurred, the returned boolean will indicate this condition. -func mqttToNATSSubjectConversion(mt []byte, wcOk bool) (bool, []byte, error) { - var res = mt - var newSlice bool +// If there is no need to convert anything (say "foo" remains "foo"), then +// the no memory is allocated and the returned slice is the original `mt`. +func mqttToNATSSubjectConversion(mt []byte, wcOk bool) ([]byte, error) { + var cp bool + var j int + res := mt - copyTopic := func(pos int) []byte { - if newSlice && cap(res) > pos+2 { - return res + makeCopy := func(i int) { + cp = true + res = make([]byte, 0, len(mt)+10) + if i > 0 { + res = append(res, mt[:i]...) } - newSlice = true - b := make([]byte, len(res)+10) - copy(b, res[:pos]) - res = b - return res } - var j int end := len(mt) - 1 for i := 0; i < len(mt); i++ { switch mt[i] { case mqttTopicLevelSep: if i == 0 || res[j-1] == btsep { - res = copyTopic(0) - res[j] = mqttTopicLevelSep + if !cp { + makeCopy(0) + } + res = append(res, mqttTopicLevelSep, btsep) j++ - res[j] = btsep } else if i == end || mt[i+1] == mqttTopicLevelSep { - res = copyTopic(j) - res[j] = btsep + if !cp { + makeCopy(i) + } + res = append(res, btsep, mqttTopicLevelSep) j++ - res[j] = mqttTopicLevelSep } else { - res[j] = btsep + if !cp { + makeCopy(i) + } + res = append(res, btsep) + } + case ' ': + // As of now, we cannot support ' ' in the MQTT topic/filter. + return nil, errMQTTUnsupportedCharacters + case btsep: + if !cp { + makeCopy(i) } - case btsep, ' ': - // As of now, we cannot support '.' or ' ' in the MQTT topic/filter. - return false, nil, fmt.Errorf("characters ' ' and '.' not supported for MQTT topics") + res = append(res, mqttTopicLevelSep, mqttTopicLevelSep) + j++ case mqttSingleLevelWC, mqttMultiLevelWC: if !wcOk { // Spec [MQTT-3.3.2-2] and [MQTT-4.7.1-1] // The wildcard characters can be used in Topic Filters, but MUST NOT be used within a Topic Name - return false, nil, fmt.Errorf("wildcards not allowed in publish's topic: %q", mt) + return nil, fmt.Errorf("wildcards not allowed in publish's topic: %q", mt) + } + if !cp { + makeCopy(i) } if mt[i] == mqttSingleLevelWC { - res[j] = pwc + res = append(res, pwc) } else { - res[j] = fwc + res = append(res, fwc) } default: - if newSlice { - res[j] = mt[i] + if cp { + res = append(res, mt[i]) } } j++ } - if newSlice && res[j-1] == btsep { - res = copyTopic(j) - res[j] = mqttTopicLevelSep + if cp && res[j-1] == btsep { + res = append(res, mqttTopicLevelSep) j++ } - return newSlice, res[:j], nil + return res[:j], nil } // Converts a NATS subject to MQTT topic. This is for publish // messages only, so there is no checking for wildcards. // Rules are reversed of mqttToNATSSubjectConversion. -func natsSubjectToMQTTTopic(subject string) []byte { - topic := []byte(subject) +func natsSubjectStrToMQTTTopic(subject string) []byte { + return natsSubjectToMQTTTopic(stringToBytes(subject)) +} + +func natsSubjectToMQTTTopic(subject []byte) []byte { + topic := make([]byte, len(subject)) end := len(subject) - 1 var j int for i := 0; i < len(subject); i++ { switch subject[i] { case mqttTopicLevelSep: - if !(i == 0 && i < end && subject[i+1] == btsep) { - topic[j] = mqttTopicLevelSep - j++ + if i < end { + switch c := subject[i+1]; c { + case btsep, mqttTopicLevelSep: + if c == btsep { + topic[j] = mqttTopicLevelSep + } else { + topic[j] = btsep + } + j++ + i++ + default: + } } case btsep: topic[j] = mqttTopicLevelSep j++ - if i < end && subject[i+1] == mqttTopicLevelSep { - i++ - } default: topic[j] = subject[i] j++ @@ -2547,18 +5744,17 @@ func mqttNeedSubForLevelUp(subject string) bool { // ////////////////////////////////////////////////////////////////////////////// -func copyBytes(b []byte) []byte { - if b == nil { - return nil - } - cbuf := make([]byte, len(b)) - copy(cbuf, b) - return cbuf -} - func (r *mqttReader) reset(buf []byte) { + if l := len(r.pbuf); l > 0 { + tmp := make([]byte, l+len(buf)) + copy(tmp, r.pbuf) + copy(tmp[l:], buf) + buf = tmp + r.pbuf = nil + } r.buf = buf r.pos = 0 + r.pstart = 0 } func (r *mqttReader) hasMore() bool { @@ -2574,7 +5770,11 @@ func (r *mqttReader) readByte(field string) (byte, error) { return b, nil } -func (r *mqttReader) readPacketLen() (int, error) { +func (r *mqttReader) readPacketLen() (int, bool, error) { + return r.readPacketLenWithCheck(true) +} + +func (r *mqttReader) readPacketLenWithCheck(check bool) (int, bool, error) { m := 1 v := 0 for { @@ -2583,45 +5783,23 @@ func (r *mqttReader) readPacketLen() (int, error) { b = r.buf[r.pos] r.pos++ } else { - var buf [1]byte - if _, err := r.reader.Read(buf[:1]); err != nil { - if err == io.EOF { - return 0, io.ErrUnexpectedEOF - } - return 0, fmt.Errorf("error reading packet length: %v", err) - } - b = buf[0] + break } v += int(b&0x7f) * m if (b & 0x80) == 0 { - return v, nil + if check && r.pos+v > len(r.buf) { + break + } + return v, true, nil } m *= 0x80 if m > 0x200000 { - return 0, errors.New("malformed variable int") - } - } -} - -func (r *mqttReader) ensurePacketInBuffer(pl int) error { - rem := len(r.buf) - r.pos - if rem >= pl { - return nil - } - b := make([]byte, pl) - start := copy(b, r.buf[r.pos:]) - for start != pl { - n, err := r.reader.Read(b[start:cap(b)]) - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return fmt.Errorf("error ensuring protocol is loaded: %v", err) + return 0, false, errMQTTMalformedVarInt } - start += n } - r.reset(b) - return nil + r.pbuf = make([]byte, len(r.buf)-r.pstart) + copy(r.pbuf, r.buf[r.pstart:]) + return 0, false, nil } func (r *mqttReader) readString(field string) (string, error) { @@ -2696,3 +5874,9 @@ func (w *mqttWriter) WriteVarInt(value int) { } } } + +func newMQTTWriter(cap int) *mqttWriter { + w := &mqttWriter{} + w.Grow(cap) + return w +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/msgtrace.go b/vendor/github.com/nats-io/nats-server/v2/server/msgtrace.go new file mode 100644 index 0000000..3f995f0 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/msgtrace.go @@ -0,0 +1,846 @@ +// Copyright 2024-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "encoding/json" + "fmt" + "math/rand" + "strconv" + "strings" + "sync/atomic" + "time" +) + +const ( + MsgTraceDest = "Nats-Trace-Dest" + MsgTraceHop = "Nats-Trace-Hop" + MsgTraceOriginAccount = "Nats-Trace-Origin-Account" + MsgTraceOnly = "Nats-Trace-Only" + + // External trace header. Note that this header is normally in lower + // case (https://www.w3.org/TR/trace-context/#header-name). Vendors + // MUST expect the header in any case (upper, lower, mixed), and + // SHOULD send the header name in lowercase. + traceParentHdr = "traceparent" +) + +type MsgTraceType string + +// Type of message trace events in the MsgTraceEvents list. +// This is needed to unmarshal the list. +const ( + MsgTraceIngressType = "in" + MsgTraceSubjectMappingType = "sm" + MsgTraceStreamExportType = "se" + MsgTraceServiceImportType = "si" + MsgTraceJetStreamType = "js" + MsgTraceEgressType = "eg" +) + +type MsgTraceEvent struct { + Server ServerInfo `json:"server"` + Request MsgTraceRequest `json:"request"` + Hops int `json:"hops,omitempty"` + Events MsgTraceEvents `json:"events"` +} + +type MsgTraceRequest struct { + // We are not making this an http.Header so that header name case is preserved. + Header map[string][]string `json:"header,omitempty"` + MsgSize int `json:"msgsize,omitempty"` +} + +type MsgTraceEvents []MsgTrace + +type MsgTrace interface { + new() MsgTrace + typ() MsgTraceType +} + +type MsgTraceBase struct { + Type MsgTraceType `json:"type"` + Timestamp time.Time `json:"ts"` +} + +type MsgTraceIngress struct { + MsgTraceBase + Kind int `json:"kind"` + CID uint64 `json:"cid"` + Name string `json:"name,omitempty"` + Account string `json:"acc"` + Subject string `json:"subj"` + Error string `json:"error,omitempty"` +} + +type MsgTraceSubjectMapping struct { + MsgTraceBase + MappedTo string `json:"to"` +} + +type MsgTraceStreamExport struct { + MsgTraceBase + Account string `json:"acc"` + To string `json:"to"` +} + +type MsgTraceServiceImport struct { + MsgTraceBase + Account string `json:"acc"` + From string `json:"from"` + To string `json:"to"` +} + +type MsgTraceJetStream struct { + MsgTraceBase + Stream string `json:"stream"` + Subject string `json:"subject,omitempty"` + NoInterest bool `json:"nointerest,omitempty"` + Error string `json:"error,omitempty"` +} + +type MsgTraceEgress struct { + MsgTraceBase + Kind int `json:"kind"` + CID uint64 `json:"cid"` + Name string `json:"name,omitempty"` + Hop string `json:"hop,omitempty"` + Account string `json:"acc,omitempty"` + Subscription string `json:"sub,omitempty"` + Queue string `json:"queue,omitempty"` + Error string `json:"error,omitempty"` + + // This is for applications that unmarshal the trace events + // and want to link an egress to route/leaf/gateway with + // the MsgTraceEvent from that server. + Link *MsgTraceEvent `json:"-"` +} + +// ------------------------------------------------------------- + +func (t MsgTraceBase) typ() MsgTraceType { return t.Type } +func (MsgTraceIngress) new() MsgTrace { return &MsgTraceIngress{} } +func (MsgTraceSubjectMapping) new() MsgTrace { return &MsgTraceSubjectMapping{} } +func (MsgTraceStreamExport) new() MsgTrace { return &MsgTraceStreamExport{} } +func (MsgTraceServiceImport) new() MsgTrace { return &MsgTraceServiceImport{} } +func (MsgTraceJetStream) new() MsgTrace { return &MsgTraceJetStream{} } +func (MsgTraceEgress) new() MsgTrace { return &MsgTraceEgress{} } + +var msgTraceInterfaces = map[MsgTraceType]MsgTrace{ + MsgTraceIngressType: MsgTraceIngress{}, + MsgTraceSubjectMappingType: MsgTraceSubjectMapping{}, + MsgTraceStreamExportType: MsgTraceStreamExport{}, + MsgTraceServiceImportType: MsgTraceServiceImport{}, + MsgTraceJetStreamType: MsgTraceJetStream{}, + MsgTraceEgressType: MsgTraceEgress{}, +} + +func (t *MsgTraceEvents) UnmarshalJSON(data []byte) error { + var raw []json.RawMessage + err := json.Unmarshal(data, &raw) + if err != nil { + return err + } + *t = make(MsgTraceEvents, len(raw)) + var tt MsgTraceBase + for i, r := range raw { + if err = json.Unmarshal(r, &tt); err != nil { + return err + } + tr, ok := msgTraceInterfaces[tt.Type] + if !ok { + return fmt.Errorf("unknown trace type %v", tt.Type) + } + te := tr.new() + if err := json.Unmarshal(r, te); err != nil { + return err + } + (*t)[i] = te + } + return nil +} + +func getTraceAs[T MsgTrace](e any) *T { + v, ok := e.(*T) + if ok { + return v + } + return nil +} + +func (t *MsgTraceEvent) Ingress() *MsgTraceIngress { + if len(t.Events) < 1 { + return nil + } + return getTraceAs[MsgTraceIngress](t.Events[0]) +} + +func (t *MsgTraceEvent) SubjectMapping() *MsgTraceSubjectMapping { + for _, e := range t.Events { + if e.typ() == MsgTraceSubjectMappingType { + return getTraceAs[MsgTraceSubjectMapping](e) + } + } + return nil +} + +func (t *MsgTraceEvent) StreamExports() []*MsgTraceStreamExport { + var se []*MsgTraceStreamExport + for _, e := range t.Events { + if e.typ() == MsgTraceStreamExportType { + se = append(se, getTraceAs[MsgTraceStreamExport](e)) + } + } + return se +} + +func (t *MsgTraceEvent) ServiceImports() []*MsgTraceServiceImport { + var si []*MsgTraceServiceImport + for _, e := range t.Events { + if e.typ() == MsgTraceServiceImportType { + si = append(si, getTraceAs[MsgTraceServiceImport](e)) + } + } + return si +} + +func (t *MsgTraceEvent) JetStream() *MsgTraceJetStream { + for _, e := range t.Events { + if e.typ() == MsgTraceJetStreamType { + return getTraceAs[MsgTraceJetStream](e) + } + } + return nil +} + +func (t *MsgTraceEvent) Egresses() []*MsgTraceEgress { + var eg []*MsgTraceEgress + for _, e := range t.Events { + if e.typ() == MsgTraceEgressType { + eg = append(eg, getTraceAs[MsgTraceEgress](e)) + } + } + return eg +} + +const ( + errMsgTraceOnlyNoSupport = "Not delivered because remote does not support message tracing" + errMsgTraceNoSupport = "Message delivered but remote does not support message tracing so no trace event generated from there" + errMsgTraceNoEcho = "Not delivered because of no echo" + errMsgTracePubViolation = "Not delivered because publish denied for this subject" + errMsgTraceSubDeny = "Not delivered because subscription denies this subject" + errMsgTraceSubClosed = "Not delivered because subscription is closed" + errMsgTraceClientClosed = "Not delivered because client is closed" + errMsgTraceAutoSubExceeded = "Not delivered because auto-unsubscribe exceeded" + errMsgTraceFastProdNoStall = "Not delivered because fast producer not stalled and consumer is slow" +) + +type msgTrace struct { + ready int32 + srv *Server + acc *Account + // Origin account name, set only if acc is nil when acc lookup failed. + oan string + dest string + event *MsgTraceEvent + js *MsgTraceJetStream + hop string + nhop string + tonly bool // Will only trace the message, not do delivery. + ct compressionType +} + +// This will be false outside of the tests, so when building the server binary, +// any code where you see `if msgTraceRunInTests` statement will be compiled +// out, so this will have no performance penalty. +var ( + msgTraceRunInTests bool + msgTraceCheckSupport bool +) + +// Returns the message trace object, if message is being traced, +// and `true` if we want to only trace, not actually deliver the message. +func (c *client) isMsgTraceEnabled() (*msgTrace, bool) { + t := c.pa.trace + if t == nil { + return nil, false + } + return t, t.tonly +} + +// For LEAF/ROUTER/GATEWAY, return false if the remote does not support +// message tracing (important if the tracing requests trace-only). +func (c *client) msgTraceSupport() bool { + // Exclude client connection from the protocol check. + return c.kind == CLIENT || c.opts.Protocol >= MsgTraceProto +} + +func getConnName(c *client) string { + switch c.kind { + case ROUTER: + if n := c.route.remoteName; n != _EMPTY_ { + return n + } + case GATEWAY: + if n := c.gw.remoteName; n != _EMPTY_ { + return n + } + case LEAF: + if n := c.leaf.remoteServer; n != _EMPTY_ { + return n + } + } + return c.opts.Name +} + +func getCompressionType(cts string) compressionType { + if cts == _EMPTY_ { + return noCompression + } + cts = strings.ToLower(cts) + if strings.Contains(cts, "snappy") || strings.Contains(cts, "s2") { + return snappyCompression + } + if strings.Contains(cts, "gzip") { + return gzipCompression + } + return unsupportedCompression +} + +func (c *client) initMsgTrace() *msgTrace { + // The code in the "if" statement is only running in test mode. + if msgTraceRunInTests { + // Check the type of client that tries to initialize a trace struct. + if !(c.kind == CLIENT || c.kind == ROUTER || c.kind == GATEWAY || c.kind == LEAF) { + panic(fmt.Sprintf("Unexpected client type %q trying to initialize msgTrace", c.kindString())) + } + // In some tests, we want to make a server behave like an old server + // and so even if a trace header is received, we want the server to + // simply ignore it. + if msgTraceCheckSupport { + if c.srv == nil || c.srv.getServerProto() < MsgTraceProto { + return nil + } + } + } + if c.pa.hdr <= 0 { + return nil + } + hdr := c.msgBuf[:c.pa.hdr] + headers, external := genHeaderMapIfTraceHeadersPresent(hdr) + if len(headers) == 0 { + return nil + } + // Little helper to give us the first value of a given header, or _EMPTY_ + // if key is not present. + getHdrVal := func(key string) string { + vv, ok := headers[key] + if !ok { + return _EMPTY_ + } + return vv[0] + } + ct := getCompressionType(getHdrVal(acceptEncodingHeader)) + var ( + dest string + traceOnly bool + ) + // Check for traceOnly only if not external. + if !external { + if to := getHdrVal(MsgTraceOnly); to != _EMPTY_ { + tos := strings.ToLower(to) + switch tos { + case "1", "true", "on": + traceOnly = true + } + } + dest = getHdrVal(MsgTraceDest) + // Check the destination to see if this is a valid public subject. + if !IsValidPublishSubject(dest) { + // We still have to return a msgTrace object (if traceOnly is set) + // because if we don't, the message will end-up being delivered to + // applications, which may break them. We report the error in any case. + c.Errorf("Destination %q is not valid, won't be able to trace events", dest) + if !traceOnly { + // We can bail, tracing will be disabled for this message. + return nil + } + } + } + var ( + // Account to use when sending the trace event + acc *Account + // Ingress' account name + ian string + // Origin account name + oan string + // The hop "id", taken from headers only when not from CLIENT + hop string + ) + if c.kind == ROUTER || c.kind == GATEWAY || c.kind == LEAF { + // The ingress account name will always be c.pa.account, but `acc` may + // be different if we have an origin account header. + if c.kind == LEAF { + ian = c.acc.GetName() + } else { + ian = string(c.pa.account) + } + // The remote will have set the origin account header only if the + // message changed account (think of service imports). + oan = getHdrVal(MsgTraceOriginAccount) + if oan == _EMPTY_ { + // For LEAF or ROUTER with pinned-account, we can use the c.acc. + if c.kind == LEAF || (c.kind == ROUTER && len(c.route.accName) > 0) { + acc = c.acc + } else { + // We will lookup account with c.pa.account (or ian). + oan = ian + } + } + // Unless we already got the account, we need to look it up. + if acc == nil { + // We don't want to do account resolving here. + if acci, ok := c.srv.accounts.Load(oan); ok { + acc = acci.(*Account) + // Since we have looked-up the account, we don't need oan, so + // clear it in case it was set. + oan = _EMPTY_ + } else { + // We still have to return a msgTrace object (if traceOnly is set) + // because if we don't, the message will end-up being delivered to + // applications, which may break them. We report the error in any case. + c.Errorf("Account %q was not found, won't be able to trace events", oan) + if !traceOnly { + // We can bail, tracing will be disabled for this message. + return nil + } + } + } + // Check the hop header + hop = getHdrVal(MsgTraceHop) + } else { + acc = c.acc + ian = acc.GetName() + } + // If external, we need to have the account's trace destination set, + // otherwise, we are not enabling tracing. + if external { + var sampling int + if acc != nil { + dest, sampling = acc.getTraceDestAndSampling() + } + if dest == _EMPTY_ { + // No account destination, no tracing for external trace headers. + return nil + } + // Check sampling, but only from origin server. + if c.kind == CLIENT && !sample(sampling) { + // Need to desactivate the traceParentHdr so that if the message + // is routed, it does possibly trigger a trace there. + disableTraceHeaders(c, hdr) + return nil + } + } + c.pa.trace = &msgTrace{ + srv: c.srv, + acc: acc, + oan: oan, + dest: dest, + ct: ct, + hop: hop, + event: &MsgTraceEvent{ + Request: MsgTraceRequest{ + Header: headers, + MsgSize: c.pa.size, + }, + Events: append(MsgTraceEvents(nil), &MsgTraceIngress{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceIngressType, + Timestamp: time.Now(), + }, + Kind: c.kind, + CID: c.cid, + Name: getConnName(c), + Account: ian, + Subject: string(c.pa.subject), + }), + }, + tonly: traceOnly, + } + return c.pa.trace +} + +func sample(sampling int) bool { + // Option parsing should ensure that sampling is [1..100], but consider + // any value outside of this range to be 100%. + if sampling <= 0 || sampling >= 100 { + return true + } + return rand.Int31n(100) <= int32(sampling) +} + +// This function will return the header as a map (instead of http.Header because +// we want to preserve the header names' case) and a boolean that indicates if +// the headers have been lifted due to the presence of the external trace header +// only. +// Note that because of the traceParentHdr, the search is done in a case +// insensitive way, but if the header is found, it is rewritten in lower case +// as suggested by the spec, but also to make it easier to disable the header +// when needed. +func genHeaderMapIfTraceHeadersPresent(hdr []byte) (map[string][]string, bool) { + + var ( + _keys = [64][]byte{} + _vals = [64][]byte{} + m map[string][]string + traceDestHdrFound bool + traceParentHdrFound bool + ) + // Skip the hdrLine + if !bytes.HasPrefix(hdr, stringToBytes(hdrLine)) { + return nil, false + } + + traceDestHdrAsBytes := stringToBytes(MsgTraceDest) + traceParentHdrAsBytes := stringToBytes(traceParentHdr) + crLFAsBytes := stringToBytes(CR_LF) + dashAsBytes := stringToBytes("-") + + keys := _keys[:0] + vals := _vals[:0] + + for i := len(hdrLine); i < len(hdr); { + // Search for key/val delimiter + del := bytes.IndexByte(hdr[i:], ':') + if del < 0 { + break + } + keyStart := i + key := hdr[keyStart : keyStart+del] + i += del + 1 + valStart := i + nl := bytes.Index(hdr[valStart:], crLFAsBytes) + if nl < 0 { + break + } + if len(key) > 0 { + val := bytes.Trim(hdr[valStart:valStart+nl], " \t") + vals = append(vals, val) + + // Check for the external trace header. + if bytes.EqualFold(key, traceParentHdrAsBytes) { + // Rewrite the header using lower case if needed. + if !bytes.Equal(key, traceParentHdrAsBytes) { + copy(hdr[keyStart:], traceParentHdrAsBytes) + } + // We will now check if the value has sampling or not. + // TODO(ik): Not sure if this header can have multiple values + // or not, and if so, what would be the rule to check for + // sampling. What is done here is to check them all until we + // found one with sampling. + if !traceParentHdrFound { + tk := bytes.Split(val, dashAsBytes) + if len(tk) == 4 && len([]byte(tk[3])) == 2 { + if hexVal, err := strconv.ParseInt(bytesToString(tk[3]), 16, 8); err == nil { + if hexVal&0x1 == 0x1 { + traceParentHdrFound = true + } + } + } + } + // Add to the keys with the external trace header in lower case. + keys = append(keys, traceParentHdrAsBytes) + } else { + // Is the key the Nats-Trace-Dest header? + if bytes.EqualFold(key, traceDestHdrAsBytes) { + traceDestHdrFound = true + } + // Add to the keys and preserve the key's case + keys = append(keys, key) + } + } + i += nl + 2 + } + if !traceDestHdrFound && !traceParentHdrFound { + return nil, false + } + m = make(map[string][]string, len(keys)) + for i, k := range keys { + hname := string(k) + m[hname] = append(m[hname], string(vals[i])) + } + return m, !traceDestHdrFound && traceParentHdrFound +} + +// Special case where we create a trace event before parsing the message. +// This is for cases where the connection will be closed when detecting +// an error during early message processing (for instance max payload). +func (c *client) initAndSendIngressErrEvent(hdr []byte, dest string, ingressError error) { + if ingressError == nil { + return + } + ct := getAcceptEncoding(hdr) + t := &msgTrace{ + srv: c.srv, + acc: c.acc, + dest: dest, + ct: ct, + event: &MsgTraceEvent{ + Request: MsgTraceRequest{MsgSize: c.pa.size}, + Events: append(MsgTraceEvents(nil), &MsgTraceIngress{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceIngressType, + Timestamp: time.Now(), + }, + Kind: c.kind, + CID: c.cid, + Name: getConnName(c), + Error: ingressError.Error(), + }), + }, + } + t.sendEvent() +} + +// Returns `true` if message tracing is enabled and we are tracing only, +// that is, we are not going to deliver the inbound message, returns +// `false` otherwise (no tracing, or tracing and message delivery). +func (t *msgTrace) traceOnly() bool { + return t != nil && t.tonly +} + +func (t *msgTrace) setOriginAccountHeaderIfNeeded(c *client, acc *Account, msg []byte) []byte { + var oan string + // If t.acc is set, only check that, not t.oan. + if t.acc != nil { + if t.acc != acc { + oan = t.acc.GetName() + } + } else if t.oan != acc.GetName() { + oan = t.oan + } + if oan != _EMPTY_ { + msg = c.setHeader(MsgTraceOriginAccount, oan, msg) + } + return msg +} + +func (t *msgTrace) setHopHeader(c *client, msg []byte) []byte { + e := t.event + e.Hops++ + if len(t.hop) > 0 { + t.nhop = fmt.Sprintf("%s.%d", t.hop, e.Hops) + } else { + t.nhop = fmt.Sprintf("%d", e.Hops) + } + return c.setHeader(MsgTraceHop, t.nhop, msg) +} + +// Will look for the MsgTraceSendTo and traceParentHdr headers and change the first +// character to an 'X' so that if this message is sent to a remote, the remote +// will not initialize tracing since it won't find the actual trace headers. +// The function returns the position of the headers so it can efficiently be +// re-enabled by calling enableTraceHeaders. +// Note that if `msg` can be either the header alone or the full message +// (header and payload). This function will use c.pa.hdr to limit the +// search to the header section alone. +func disableTraceHeaders(c *client, msg []byte) []int { + // Code largely copied from getHeader(), except that we don't need the value + if c.pa.hdr <= 0 { + return []int{-1, -1} + } + hdr := msg[:c.pa.hdr] + headers := [2]string{MsgTraceDest, traceParentHdr} + positions := [2]int{-1, -1} + for i := 0; i < 2; i++ { + key := stringToBytes(headers[i]) + pos := bytes.Index(hdr, key) + if pos < 0 { + continue + } + // Make sure this key does not have additional prefix. + if pos < 2 || hdr[pos-1] != '\n' || hdr[pos-2] != '\r' { + continue + } + index := pos + len(key) + if index >= len(hdr) { + continue + } + if hdr[index] != ':' { + continue + } + // Disable the trace by altering the first character of the header + hdr[pos] = 'X' + positions[i] = pos + } + // Return the positions of those characters so we can re-enable the headers. + return positions[:2] +} + +// Changes back the character at the given position `pos` in the `msg` +// byte slice to the first character of the MsgTraceSendTo header. +func enableTraceHeaders(msg []byte, positions []int) { + firstChar := [2]byte{MsgTraceDest[0], traceParentHdr[0]} + for i, pos := range positions { + if pos == -1 { + continue + } + msg[pos] = firstChar[i] + } +} + +func (t *msgTrace) setIngressError(err string) { + if i := t.event.Ingress(); i != nil { + i.Error = err + } +} + +func (t *msgTrace) addSubjectMappingEvent(subj []byte) { + if t == nil { + return + } + t.event.Events = append(t.event.Events, &MsgTraceSubjectMapping{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceSubjectMappingType, + Timestamp: time.Now(), + }, + MappedTo: string(subj), + }) +} + +func (t *msgTrace) addEgressEvent(dc *client, sub *subscription, err string) { + if t == nil { + return + } + e := &MsgTraceEgress{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceEgressType, + Timestamp: time.Now(), + }, + Kind: dc.kind, + CID: dc.cid, + Name: getConnName(dc), + Hop: t.nhop, + Error: err, + } + t.nhop = _EMPTY_ + // Specific to CLIENT connections... + if dc.kind == CLIENT { + // Set the subscription's subject and possibly queue name. + e.Subscription = string(sub.subject) + if len(sub.queue) > 0 { + e.Queue = string(sub.queue) + } + } + if dc.kind == CLIENT || dc.kind == LEAF { + if i := t.event.Ingress(); i != nil { + // If the Ingress' account is different from the destination's + // account, add the account name into the Egress trace event. + // This would happen with service imports. + if dcAccName := dc.acc.GetName(); dcAccName != i.Account { + e.Account = dcAccName + } + } + } + t.event.Events = append(t.event.Events, e) +} + +func (t *msgTrace) addStreamExportEvent(dc *client, to []byte) { + if t == nil { + return + } + dc.mu.Lock() + accName := dc.acc.GetName() + dc.mu.Unlock() + t.event.Events = append(t.event.Events, &MsgTraceStreamExport{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceStreamExportType, + Timestamp: time.Now(), + }, + Account: accName, + To: string(to), + }) +} + +func (t *msgTrace) addServiceImportEvent(accName, from, to string) { + if t == nil { + return + } + t.event.Events = append(t.event.Events, &MsgTraceServiceImport{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceServiceImportType, + Timestamp: time.Now(), + }, + Account: accName, + From: from, + To: to, + }) +} + +func (t *msgTrace) addJetStreamEvent(streamName string) { + if t == nil { + return + } + t.js = &MsgTraceJetStream{ + MsgTraceBase: MsgTraceBase{ + Type: MsgTraceJetStreamType, + Timestamp: time.Now(), + }, + Stream: streamName, + } + t.event.Events = append(t.event.Events, t.js) +} + +func (t *msgTrace) updateJetStreamEvent(subject string, noInterest bool) { + if t == nil { + return + } + // JetStream event should have been created in addJetStreamEvent + if t.js == nil { + return + } + t.js.Subject = subject + t.js.NoInterest = noInterest + // Update the timestamp since this is more accurate than when it + // was first added in addJetStreamEvent(). + t.js.Timestamp = time.Now() +} + +func (t *msgTrace) sendEventFromJetStream(err error) { + if t == nil { + return + } + // JetStream event should have been created in addJetStreamEvent + if t.js == nil { + return + } + if err != nil { + t.js.Error = err.Error() + } + t.sendEvent() +} + +func (t *msgTrace) sendEvent() { + if t == nil { + return + } + if t.js != nil { + ready := atomic.AddInt32(&t.ready, 1) == 2 + if !ready { + return + } + } + t.srv.sendInternalAccountSysMsg(t.acc, t.dest, &t.event.Server, t.event, t.ct) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/nkey.go b/vendor/github.com/nats-io/nats-server/v2/server/nkey.go index a792c6e..f057917 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/nkey.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/nkey.go @@ -1,4 +1,4 @@ -// Copyright 2018 The NATS Authors +// Copyright 2018-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,6 +14,7 @@ package server import ( + crand "crypto/rand" "encoding/base64" ) @@ -33,7 +34,7 @@ func (s *Server) NonceRequired() bool { // nonceRequired tells us if we should send a nonce. // Lock should be held on entry. func (s *Server) nonceRequired() bool { - return len(s.nkeys) > 0 || len(s.trustedKeys) > 0 + return s.getOpts().AlwaysEnableNonce || len(s.nkeys) > 0 || s.trustedKeys != nil } // Generate a nonce for INFO challenge. @@ -41,6 +42,6 @@ func (s *Server) nonceRequired() bool { func (s *Server) generateNonce(n []byte) { var raw [nonceRawLen]byte data := raw[:] - s.prand.Read(data) + crand.Read(data) base64.RawURLEncoding.Encode(n, data) } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ocsp.go b/vendor/github.com/nats-io/nats-server/v2/server/ocsp.go new file mode 100644 index 0000000..0239c65 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/ocsp.go @@ -0,0 +1,992 @@ +// Copyright 2021-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "encoding/asn1" + "encoding/base64" + "encoding/pem" + "errors" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "sync" + "time" + + "golang.org/x/crypto/ocsp" + + "github.com/nats-io/nats-server/v2/server/certidp" + "github.com/nats-io/nats-server/v2/server/certstore" +) + +const ( + defaultOCSPStoreDir = "ocsp" + defaultOCSPCheckInterval = 24 * time.Hour + minOCSPCheckInterval = 2 * time.Minute +) + +type OCSPMode uint8 + +const ( + // OCSPModeAuto staples a status, only if "status_request" is set in cert. + OCSPModeAuto OCSPMode = iota + + // OCSPModeAlways enforces OCSP stapling for certs and shuts down the server in + // case a server is revoked or cannot get OCSP staples. + OCSPModeAlways + + // OCSPModeNever disables OCSP stapling even if cert has Must-Staple flag. + OCSPModeNever + + // OCSPModeMust honors the Must-Staple flag from a certificate but also causing shutdown + // in case the certificate has been revoked. + OCSPModeMust +) + +// OCSPMonitor monitors the state of a staple per certificate. +type OCSPMonitor struct { + kind string + mu sync.Mutex + raw []byte + srv *Server + certFile string + resp *ocsp.Response + hc *http.Client + stopCh chan struct{} + Leaf *x509.Certificate + Issuer *x509.Certificate + + shutdownOnRevoke bool +} + +func (oc *OCSPMonitor) getNextRun() time.Duration { + oc.mu.Lock() + nextUpdate := oc.resp.NextUpdate + oc.mu.Unlock() + + now := time.Now() + if nextUpdate.IsZero() { + // If response is missing NextUpdate, we check the day after. + // Technically, if NextUpdate is missing, we can try whenever. + // https://tools.ietf.org/html/rfc6960#section-4.2.2.1 + return defaultOCSPCheckInterval + } + dur := nextUpdate.Sub(now) / 2 + + // If negative, then wait a couple of minutes before getting another staple. + if dur < 0 { + return minOCSPCheckInterval + } + + return dur +} + +func (oc *OCSPMonitor) getStatus() ([]byte, *ocsp.Response, error) { + raw, resp := oc.getCacheStatus() + if len(raw) > 0 && resp != nil { + // Check if the OCSP is still valid. + if err := validOCSPResponse(resp); err == nil { + return raw, resp, nil + } + } + var err error + raw, resp, err = oc.getLocalStatus() + if err == nil { + return raw, resp, nil + } + + return oc.getRemoteStatus() +} + +func (oc *OCSPMonitor) getCacheStatus() ([]byte, *ocsp.Response) { + oc.mu.Lock() + defer oc.mu.Unlock() + return oc.raw, oc.resp +} + +func (oc *OCSPMonitor) getLocalStatus() ([]byte, *ocsp.Response, error) { + opts := oc.srv.getOpts() + storeDir := opts.StoreDir + if storeDir == _EMPTY_ { + return nil, nil, fmt.Errorf("store_dir not set") + } + + // This key must be based upon the current full certificate, not the public key, + // so MUST be on the full raw certificate and not an SPKI or other reduced form. + key := fmt.Sprintf("%x", sha256.Sum256(oc.Leaf.Raw)) + + oc.mu.Lock() + raw, err := os.ReadFile(filepath.Join(storeDir, defaultOCSPStoreDir, key)) + oc.mu.Unlock() + if err != nil { + return nil, nil, err + } + + resp, err := ocsp.ParseResponse(raw, oc.Issuer) + if err != nil { + return nil, nil, fmt.Errorf("failed to get local status: %w", err) + } + if err := validOCSPResponse(resp); err != nil { + return nil, nil, err + } + + // Cache the response. + oc.mu.Lock() + oc.raw = raw + oc.resp = resp + oc.mu.Unlock() + + return raw, resp, nil +} + +func (oc *OCSPMonitor) getRemoteStatus() ([]byte, *ocsp.Response, error) { + opts := oc.srv.getOpts() + var overrideURLs []string + if config := opts.OCSPConfig; config != nil { + overrideURLs = config.OverrideURLs + } + getRequestBytes := func(u string, reqDER []byte, hc *http.Client) ([]byte, error) { + reqEnc := base64.StdEncoding.EncodeToString(reqDER) + u = fmt.Sprintf("%s/%s", u, reqEnc) + start := time.Now() + resp, err := hc.Get(u) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + oc.srv.Debugf("Received OCSP response (method=GET, status=%v, url=%s, duration=%.3fs)", + resp.StatusCode, u, time.Since(start).Seconds()) + if resp.StatusCode > 299 { + return nil, fmt.Errorf("non-ok http status on GET request (reqlen=%d): %d", len(reqEnc), resp.StatusCode) + } + return io.ReadAll(resp.Body) + } + postRequestBytes := func(u string, body []byte, hc *http.Client) ([]byte, error) { + hreq, err := http.NewRequest("POST", u, bytes.NewReader(body)) + if err != nil { + return nil, err + } + hreq.Header.Add("Content-Type", "application/ocsp-request") + hreq.Header.Add("Accept", "application/ocsp-response") + + start := time.Now() + resp, err := hc.Do(hreq) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + oc.srv.Debugf("Received OCSP response (method=POST, status=%v, url=%s, duration=%.3fs)", + resp.StatusCode, u, time.Since(start).Seconds()) + if resp.StatusCode > 299 { + return nil, fmt.Errorf("non-ok http status on POST request (reqlen=%d): %d", len(body), resp.StatusCode) + } + return io.ReadAll(resp.Body) + } + + // Request documentation: + // https://tools.ietf.org/html/rfc6960#appendix-A.1 + + reqDER, err := ocsp.CreateRequest(oc.Leaf, oc.Issuer, nil) + if err != nil { + return nil, nil, err + } + + responders := oc.Leaf.OCSPServer + if len(overrideURLs) > 0 { + responders = overrideURLs + } + if len(responders) == 0 { + return nil, nil, fmt.Errorf("no available ocsp servers") + } + + oc.mu.Lock() + hc := oc.hc + oc.mu.Unlock() + + var raw []byte + for _, u := range responders { + var postErr, getErr error + u = strings.TrimSuffix(u, "/") + // Prefer to make POST requests first. + raw, postErr = postRequestBytes(u, reqDER, hc) + if postErr == nil { + err = nil + break + } else { + // Fallback to use a GET request. + raw, getErr = getRequestBytes(u, reqDER, hc) + if getErr == nil { + err = nil + break + } else { + err = errors.Join(postErr, getErr) + } + } + } + if err != nil { + return nil, nil, fmt.Errorf("exhausted ocsp servers: %w", err) + } + resp, err := ocsp.ParseResponse(raw, oc.Issuer) + if err != nil { + return nil, nil, fmt.Errorf("failed to get remote status: %w", err) + } + if err := validOCSPResponse(resp); err != nil { + return nil, nil, err + } + + if storeDir := opts.StoreDir; storeDir != _EMPTY_ { + key := fmt.Sprintf("%x", sha256.Sum256(oc.Leaf.Raw)) + if err := oc.writeOCSPStatus(storeDir, key, raw); err != nil { + return nil, nil, fmt.Errorf("failed to write ocsp status: %w", err) + } + } + + oc.mu.Lock() + oc.raw = raw + oc.resp = resp + oc.mu.Unlock() + + return raw, resp, nil +} + +func (oc *OCSPMonitor) run() { + s := oc.srv + s.mu.Lock() + quitCh := s.quitCh + s.mu.Unlock() + + var doShutdown bool + defer func() { + // Need to decrement before shuting down, otherwise shutdown + // would be stuck waiting on grWG to go down to 0. + s.grWG.Done() + if doShutdown { + s.Shutdown() + } + }() + + oc.mu.Lock() + shutdownOnRevoke := oc.shutdownOnRevoke + certFile := oc.certFile + stopCh := oc.stopCh + kind := oc.kind + oc.mu.Unlock() + + var nextRun time.Duration + _, resp, err := oc.getStatus() + if err == nil && resp.Status == ocsp.Good { + nextRun = oc.getNextRun() + t := resp.NextUpdate.Format(time.RFC3339Nano) + s.Noticef( + "Found OCSP status for %s certificate at '%s': good, next update %s, checking again in %s", + kind, certFile, t, nextRun, + ) + } else if err == nil && shutdownOnRevoke { + // If resp.Status is ocsp.Revoked, ocsp.Unknown, or any other value. + s.Errorf("Found OCSP status for %s certificate at '%s': %s", kind, certFile, ocspStatusString(resp.Status)) + doShutdown = true + return + } + + for { + // On reload, if the certificate changes then need to stop this monitor. + select { + case <-time.After(nextRun): + case <-stopCh: + // In case of reload and have to restart the OCSP stapling monitoring. + return + case <-quitCh: + // Server quit channel. + return + } + _, resp, err := oc.getRemoteStatus() + if err != nil { + nextRun = oc.getNextRun() + s.Errorf("Bad OCSP status update for certificate '%s': %s, trying again in %v", certFile, err, nextRun) + continue + } + + switch n := resp.Status; n { + case ocsp.Good: + nextRun = oc.getNextRun() + t := resp.NextUpdate.Format(time.RFC3339Nano) + s.Noticef( + "Received OCSP status for %s certificate '%s': good, next update %s, checking again in %s", + kind, certFile, t, nextRun, + ) + continue + default: + s.Errorf("Received OCSP status for %s certificate '%s': %s", kind, certFile, ocspStatusString(n)) + if shutdownOnRevoke { + doShutdown = true + } + return + } + } +} + +func (oc *OCSPMonitor) stop() { + oc.mu.Lock() + stopCh := oc.stopCh + oc.mu.Unlock() + stopCh <- struct{}{} +} + +// NewOCSPMonitor takes a TLS configuration then wraps it with the callbacks set for OCSP verification +// along with a monitor that will periodically fetch OCSP staples. +func (srv *Server) NewOCSPMonitor(config *tlsConfigKind) (*tls.Config, *OCSPMonitor, error) { + kind := config.kind + tc := config.tlsConfig + tcOpts := config.tlsOpts + opts := srv.getOpts() + oc := opts.OCSPConfig + + // We need to track the CA certificate in case the CA is not present + // in the chain to be able to verify the signature of the OCSP staple. + var ( + certFile string + caFile string + ) + if kind == kindStringMap[CLIENT] { + tcOpts = opts.tlsConfigOpts + if opts.TLSCert != _EMPTY_ { + certFile = opts.TLSCert + } + if opts.TLSCaCert != _EMPTY_ { + caFile = opts.TLSCaCert + } + } + if tcOpts != nil { + certFile = tcOpts.CertFile + caFile = tcOpts.CaFile + } + + // NOTE: Currently OCSP Stapling is enabled only for the first certificate found. + var mon *OCSPMonitor + for _, currentCert := range tc.Certificates { + // Create local copy since this will be used in the GetCertificate callback. + cert := currentCert + + // This is normally non-nil, but can still be nil here when in tests + // or in some embedded scenarios. + if cert.Leaf == nil { + if len(cert.Certificate) <= 0 { + return nil, nil, fmt.Errorf("no certificate found") + } + var err error + cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return nil, nil, fmt.Errorf("error parsing certificate: %v", err) + } + } + var shutdownOnRevoke bool + mustStaple := hasOCSPStatusRequest(cert.Leaf) + if oc != nil { + switch { + case oc.Mode == OCSPModeNever: + if mustStaple { + srv.Warnf("Certificate at '%s' has MustStaple but OCSP is disabled", certFile) + } + return tc, nil, nil + case oc.Mode == OCSPModeAlways: + // Start the monitor for this cert even if it does not have + // the MustStaple flag and shutdown the server in case the + // staple ever gets revoked. + mustStaple = true + shutdownOnRevoke = true + case oc.Mode == OCSPModeMust && mustStaple: + shutdownOnRevoke = true + case oc.Mode == OCSPModeAuto && !mustStaple: + // "status_request" MustStaple flag not set in certificate. No need to do anything. + return tc, nil, nil + } + } + if !mustStaple { + // No explicit OCSP config and cert does not have MustStaple flag either. + return tc, nil, nil + } + + if err := srv.setupOCSPStapleStoreDir(); err != nil { + return nil, nil, err + } + + // TODO: Add OCSP 'responder_cert' option in case CA cert not available. + issuer, err := getOCSPIssuer(caFile, cert.Certificate) + if err != nil { + return nil, nil, err + } + + mon = &OCSPMonitor{ + kind: kind, + srv: srv, + hc: &http.Client{Timeout: 30 * time.Second}, + shutdownOnRevoke: shutdownOnRevoke, + certFile: certFile, + stopCh: make(chan struct{}, 1), + Leaf: cert.Leaf, + Issuer: issuer, + } + + // Get the certificate status from the memory, then remote OCSP responder. + if _, resp, err := mon.getStatus(); err != nil { + return nil, nil, fmt.Errorf("bad OCSP status update for certificate at '%s': %s", certFile, err) + } else if resp != nil && resp.Status != ocsp.Good && shutdownOnRevoke { + return nil, nil, fmt.Errorf("found existing OCSP status for certificate at '%s': %s", certFile, ocspStatusString(resp.Status)) + } + + // Callbacks below will be in charge of returning the certificate instead, + // so this has to be nil. + tc.Certificates = nil + + // GetCertificate returns a certificate that's presented to a client. + tc.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { + ccert := cert + raw, _, err := mon.getStatus() + if err != nil { + return nil, err + } + return &tls.Certificate{ + OCSPStaple: raw, + Certificate: ccert.Certificate, + PrivateKey: ccert.PrivateKey, + SupportedSignatureAlgorithms: ccert.SupportedSignatureAlgorithms, + SignedCertificateTimestamps: ccert.SignedCertificateTimestamps, + Leaf: ccert.Leaf, + }, nil + } + + // Check whether need to verify staples from a peer router or gateway connection. + switch kind { + case kindStringMap[ROUTER], kindStringMap[GATEWAY]: + tc.VerifyConnection = func(s tls.ConnectionState) error { + oresp := s.OCSPResponse + if oresp == nil { + return fmt.Errorf("%s peer missing OCSP Staple", kind) + } + + // Peer connections will verify the response of the staple. + if len(s.VerifiedChains) == 0 { + return fmt.Errorf("%s peer missing TLS verified chains", kind) + } + + chain := s.VerifiedChains[0] + peerLeaf := chain[0] + peerIssuer := certidp.GetLeafIssuerCert(chain, 0) + if peerIssuer == nil { + return fmt.Errorf("failed to get issuer certificate for %s peer", kind) + } + + // Response signature of issuer or issuer delegate is checked in the library parse + resp, err := ocsp.ParseResponseForCert(oresp, peerLeaf, peerIssuer) + if err != nil { + return fmt.Errorf("failed to parse OCSP response from %s peer: %w", kind, err) + } + + // If signer was issuer delegate double-check issuer delegate authorization + if resp.Certificate != nil { + ok := false + for _, eku := range resp.Certificate.ExtKeyUsage { + if eku == x509.ExtKeyUsageOCSPSigning { + ok = true + break + } + } + if !ok { + return fmt.Errorf("OCSP staple's signer missing authorization by CA to act as OCSP signer") + } + } + + // Check that the OCSP response is effective, take defaults for clockskew and default validity + peerOpts := certidp.OCSPPeerConfig{ClockSkew: -1, TTLUnsetNextUpdate: -1} + sLog := certidp.Log{Debugf: srv.Debugf} + if !certidp.OCSPResponseCurrent(resp, &peerOpts, &sLog) { + return fmt.Errorf("OCSP staple from %s peer not current", kind) + } + + if resp.Status != ocsp.Good { + return fmt.Errorf("bad status for OCSP Staple from %s peer: %s", kind, ocspStatusString(resp.Status)) + } + + return nil + } + + // When server makes a peer connection, need to also present an OCSP Staple. + tc.GetClientCertificate = func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) { + ccert := cert + raw, _, err := mon.getStatus() + if err != nil { + return nil, err + } + // NOTE: crypto/tls.sendClientCertificate internally also calls getClientCertificate + // so if for some reason these callbacks are triggered concurrently during a reconnect + // there can be a race. To avoid that, the OCSP monitor lock is used to serialize access + // to the staple which could also change inflight during an update. + mon.mu.Lock() + ccert.OCSPStaple = raw + mon.mu.Unlock() + + return &ccert, nil + } + default: + // GetClientCertificate returns a certificate that's presented to a server. + tc.GetClientCertificate = func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) { + return &cert, nil + } + } + } + return tc, mon, nil +} + +func (s *Server) setupOCSPStapleStoreDir() error { + opts := s.getOpts() + storeDir := opts.StoreDir + if storeDir == _EMPTY_ { + return nil + } + storeDir = filepath.Join(storeDir, defaultOCSPStoreDir) + if stat, err := os.Stat(storeDir); os.IsNotExist(err) { + if err := os.MkdirAll(storeDir, defaultDirPerms); err != nil { + return fmt.Errorf("could not create OCSP storage directory - %v", err) + } + } else if stat == nil || !stat.IsDir() { + return fmt.Errorf("OCSP storage directory is not a directory") + } + return nil +} + +type tlsConfigKind struct { + tlsConfig *tls.Config + tlsOpts *TLSConfigOpts + kind string + isLeafSpoke bool + apply func(*tls.Config) +} + +func (s *Server) configureOCSP() []*tlsConfigKind { + sopts := s.getOpts() + + configs := make([]*tlsConfigKind, 0) + + if config := sopts.TLSConfig; config != nil { + opts := sopts.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[CLIENT], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { sopts.TLSConfig = tc }, + } + configs = append(configs, o) + } + if config := sopts.Websocket.TLSConfig; config != nil { + opts := sopts.Websocket.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[CLIENT], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { sopts.Websocket.TLSConfig = tc }, + } + configs = append(configs, o) + } + if config := sopts.MQTT.TLSConfig; config != nil { + opts := sopts.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[CLIENT], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { sopts.MQTT.TLSConfig = tc }, + } + configs = append(configs, o) + } + if config := sopts.Cluster.TLSConfig; config != nil { + opts := sopts.Cluster.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[ROUTER], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { sopts.Cluster.TLSConfig = tc }, + } + configs = append(configs, o) + } + if config := sopts.LeafNode.TLSConfig; config != nil { + opts := sopts.LeafNode.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[LEAF], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { sopts.LeafNode.TLSConfig = tc }, + } + configs = append(configs, o) + } + for _, remote := range sopts.LeafNode.Remotes { + if config := remote.TLSConfig; config != nil { + // Use a copy of the remote here since will be used + // in the apply func callback below. + r, opts := remote, remote.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[LEAF], + tlsConfig: config, + tlsOpts: opts, + isLeafSpoke: true, + apply: func(tc *tls.Config) { r.TLSConfig = tc }, + } + configs = append(configs, o) + } + } + if config := sopts.Gateway.TLSConfig; config != nil { + opts := sopts.Gateway.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[GATEWAY], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { sopts.Gateway.TLSConfig = tc }, + } + configs = append(configs, o) + } + for _, remote := range sopts.Gateway.Gateways { + if config := remote.TLSConfig; config != nil { + gw, opts := remote, remote.tlsConfigOpts + o := &tlsConfigKind{ + kind: kindStringMap[GATEWAY], + tlsConfig: config, + tlsOpts: opts, + apply: func(tc *tls.Config) { gw.TLSConfig = tc }, + } + configs = append(configs, o) + } + } + return configs +} + +func (s *Server) enableOCSP() error { + configs := s.configureOCSP() + + for _, config := range configs { + + // We do not staple Leaf Hub and Leaf Spokes, use ocsp_peer + if config.kind != kindStringMap[LEAF] { + // OCSP Stapling feature, will also enable tls server peer check for gateway and route peers + tc, mon, err := s.NewOCSPMonitor(config) + if err != nil { + return err + } + // Check if an OCSP stapling monitor is required for this certificate. + if mon != nil { + s.ocsps = append(s.ocsps, mon) + + // Override the TLS config with one that follows OCSP stapling + config.apply(tc) + } + } + + // OCSP peer check (client mTLS, leaf mTLS, leaf remote TLS) + if config.kind == kindStringMap[CLIENT] || config.kind == kindStringMap[LEAF] { + tc, plugged, err := s.plugTLSOCSPPeer(config) + if err != nil { + return err + } + if plugged && tc != nil { + s.ocspPeerVerify = true + config.apply(tc) + } + } + } + + return nil +} + +func (s *Server) startOCSPMonitoring() { + s.mu.Lock() + ocsps := s.ocsps + s.mu.Unlock() + if ocsps == nil { + return + } + for _, mon := range ocsps { + m := mon + m.mu.Lock() + kind := m.kind + m.mu.Unlock() + s.Noticef("OCSP Stapling enabled for %s connections", kind) + s.startGoRoutine(func() { m.run() }) + } +} + +func (s *Server) reloadOCSP() error { + if err := s.setupOCSPStapleStoreDir(); err != nil { + return err + } + + s.mu.Lock() + ocsps := s.ocsps + s.mu.Unlock() + + // Stop all OCSP Stapling monitors in case there were any running. + for _, oc := range ocsps { + oc.stop() + } + + configs := s.configureOCSP() + + // Restart the monitors under the new configuration. + ocspm := make([]*OCSPMonitor, 0) + + // Reset server's ocspPeerVerify flag to re-detect at least one plugged OCSP peer + s.mu.Lock() + s.ocspPeerVerify = false + s.mu.Unlock() + s.stopOCSPResponseCache() + + for _, config := range configs { + // We do not staple Leaf Hub and Leaf Spokes, use ocsp_peer + if config.kind != kindStringMap[LEAF] { + tc, mon, err := s.NewOCSPMonitor(config) + if err != nil { + return err + } + // Check if an OCSP stapling monitor is required for this certificate. + if mon != nil { + ocspm = append(ocspm, mon) + + // Apply latest TLS configuration after OCSP monitors have started. + defer config.apply(tc) + } + } + + // OCSP peer check (client mTLS, leaf mTLS, leaf remote TLS) + if config.kind == kindStringMap[CLIENT] || config.kind == kindStringMap[LEAF] { + tc, plugged, err := s.plugTLSOCSPPeer(config) + if err != nil { + return err + } + if plugged && tc != nil { + s.ocspPeerVerify = true + defer config.apply(tc) + } + } + } + + // Replace stopped monitors with the new ones. + s.mu.Lock() + s.ocsps = ocspm + s.mu.Unlock() + + // Dispatch all goroutines once again. + s.startOCSPMonitoring() + + // Init and restart OCSP responder cache + s.stopOCSPResponseCache() + s.initOCSPResponseCache() + s.startOCSPResponseCache() + + return nil +} + +func hasOCSPStatusRequest(cert *x509.Certificate) bool { + // OID for id-pe-tlsfeature defined in RFC here: + // https://datatracker.ietf.org/doc/html/rfc7633 + tlsFeatures := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24} + const statusRequestExt = 5 + + // Example values: + // * [48 3 2 1 5] - seen when creating own certs locally + // * [30 3 2 1 5] - seen in the wild + // Documentation: + // https://tools.ietf.org/html/rfc6066 + + for _, ext := range cert.Extensions { + if !ext.Id.Equal(tlsFeatures) { + continue + } + + var val []int + rest, err := asn1.Unmarshal(ext.Value, &val) + if err != nil || len(rest) > 0 { + return false + } + + for _, n := range val { + if n == statusRequestExt { + return true + } + } + break + } + + return false +} + +// writeOCSPStatus writes an OCSP status to a temporary file then moves it to a +// new path, in an attempt to avoid corrupting existing data. +func (oc *OCSPMonitor) writeOCSPStatus(storeDir, file string, data []byte) error { + storeDir = filepath.Join(storeDir, defaultOCSPStoreDir) + tmp, err := os.CreateTemp(storeDir, "tmp-cert-status") + if err != nil { + return err + } + + if _, err := tmp.Write(data); err != nil { + tmp.Close() + os.Remove(tmp.Name()) + return err + } + if err := tmp.Close(); err != nil { + return err + } + + oc.mu.Lock() + err = os.Rename(tmp.Name(), filepath.Join(storeDir, file)) + oc.mu.Unlock() + if err != nil { + os.Remove(tmp.Name()) + return err + } + + return nil +} + +func parseCertPEM(name string) ([]*x509.Certificate, error) { + data, err := os.ReadFile(name) + if err != nil { + return nil, err + } + + var pemBytes []byte + + var block *pem.Block + for len(data) != 0 { + block, data = pem.Decode(data) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf("unexpected PEM certificate type: %s", block.Type) + } + + pemBytes = append(pemBytes, block.Bytes...) + } + + return x509.ParseCertificates(pemBytes) +} + +// getOCSPIssuerLocally determines a leaf's issuer from locally configured certificates +func getOCSPIssuerLocally(trustedCAs []*x509.Certificate, certBundle []*x509.Certificate) (*x509.Certificate, error) { + var vOpts x509.VerifyOptions + var leaf *x509.Certificate + trustedCAPool := x509.NewCertPool() + + // Require Leaf as first cert in bundle + if len(certBundle) > 0 { + leaf = certBundle[0] + } else { + return nil, fmt.Errorf("invalid ocsp ca configuration") + } + + // Allow Issuer to be configured as second cert in bundle + if len(certBundle) > 1 { + // The operator may have misconfigured the cert bundle + issuerCandidate := certBundle[1] + err := issuerCandidate.CheckSignature(leaf.SignatureAlgorithm, leaf.RawTBSCertificate, leaf.Signature) + if err != nil { + return nil, fmt.Errorf("invalid issuer configuration: %w", err) + } else { + return issuerCandidate, nil + } + } + + // Operator did not provide the Leaf Issuer in cert bundle second position + // so we will attempt to create at least one ordered verified chain from the + // trusted CA pool. + + // Specify CA trust store to validator; if unset, system trust store used + if len(trustedCAs) > 0 { + for _, ca := range trustedCAs { + trustedCAPool.AddCert(ca) + } + vOpts.Roots = trustedCAPool + } + + return certstore.GetLeafIssuer(leaf, vOpts), nil +} + +// getOCSPIssuer determines an issuer certificate from the cert (bundle) or the file-based CA trust store +func getOCSPIssuer(caFile string, chain [][]byte) (*x509.Certificate, error) { + var issuer *x509.Certificate + var trustedCAs []*x509.Certificate + var certBundle []*x509.Certificate + var err error + + // FIXME(tgb): extend if pluggable CA store provider added to NATS (i.e. other than PEM file) + + // Non-system default CA trust store passed + if caFile != _EMPTY_ { + trustedCAs, err = parseCertPEM(caFile) + if err != nil { + return nil, fmt.Errorf("failed to parse ca_file: %v", err) + } + } + + // Specify bundled intermediate CA store + for _, certBytes := range chain { + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return nil, fmt.Errorf("failed to parse cert: %v", err) + } + certBundle = append(certBundle, cert) + } + + issuer, err = getOCSPIssuerLocally(trustedCAs, certBundle) + if err != nil || issuer == nil { + return nil, fmt.Errorf("no issuers found") + } + + if !issuer.IsCA { + return nil, fmt.Errorf("%s invalid ca basic constraints: is not ca", issuer.Subject) + } + return issuer, nil +} + +func ocspStatusString(n int) string { + switch n { + case ocsp.Good: + return "good" + case ocsp.Revoked: + return "revoked" + default: + return "unknown" + } +} + +func validOCSPResponse(r *ocsp.Response) error { + // Time validation not handled by ParseResponse. + // https://tools.ietf.org/html/rfc6960#section-4.2.2.1 + if !r.NextUpdate.IsZero() && r.NextUpdate.Before(time.Now()) { + t := r.NextUpdate.Format(time.RFC3339Nano) + return fmt.Errorf("invalid ocsp NextUpdate, is past time: %s", t) + } + if r.ThisUpdate.After(time.Now()) { + t := r.ThisUpdate.Format(time.RFC3339Nano) + return fmt.Errorf("invalid ocsp ThisUpdate, is future time: %s", t) + } + + return nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ocsp_peer.go b/vendor/github.com/nats-io/nats-server/v2/server/ocsp_peer.go new file mode 100644 index 0000000..22d42ef --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/ocsp_peer.go @@ -0,0 +1,405 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "strings" + "time" + + "golang.org/x/crypto/ocsp" + + "github.com/nats-io/nats-server/v2/server/certidp" +) + +func parseOCSPPeer(v any) (pcfg *certidp.OCSPPeerConfig, retError error) { + var lt token + defer convertPanicToError(<, &retError) + tk, v := unwrapValue(v, <) + cm, ok := v.(map[string]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrIllegalPeerOptsConfig, v)} + } + pcfg = certidp.NewOCSPPeerConfig() + retError = nil + for mk, mv := range cm { + tk, mv = unwrapValue(mv, <) + switch strings.ToLower(mk) { + case "verify": + verify, ok := mv.(bool) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldGeneric, mk)} + } + pcfg.Verify = verify + case "allowed_clockskew": + at := float64(0) + switch mv := mv.(type) { + case int64: + at = float64(mv) + case float64: + at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, "unexpected type")} + } + at = d.Seconds() + default: + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, "unexpected type")} + } + if at >= 0 { + pcfg.ClockSkew = at + } + case "ca_timeout": + at := float64(0) + switch mv := mv.(type) { + case int64: + at = float64(mv) + case float64: + at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, err)} + } + at = d.Seconds() + default: + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, "unexpected type")} + } + if at >= 0 { + pcfg.Timeout = at + } + case "cache_ttl_when_next_update_unset": + at := float64(0) + switch mv := mv.(type) { + case int64: + at = float64(mv) + case float64: + at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, err)} + } + at = d.Seconds() + default: + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, "unexpected type")} + } + if at >= 0 { + pcfg.TTLUnsetNextUpdate = at + } + case "warn_only": + warnOnly, ok := mv.(bool) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldGeneric, mk)} + } + pcfg.WarnOnly = warnOnly + case "unknown_is_good": + unknownIsGood, ok := mv.(bool) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldGeneric, mk)} + } + pcfg.UnknownIsGood = unknownIsGood + case "allow_when_ca_unreachable": + allowWhenCAUnreachable, ok := mv.(bool) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldGeneric, mk)} + } + pcfg.AllowWhenCAUnreachable = allowWhenCAUnreachable + default: + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldGeneric, mk)} + } + } + return pcfg, nil +} + +func peerFromVerifiedChains(chains [][]*x509.Certificate) *x509.Certificate { + if len(chains) == 0 || len(chains[0]) == 0 { + return nil + } + return chains[0][0] +} + +// plugTLSOCSPPeer will plug the TLS handshake lifecycle for client mTLS connections and Leaf connections +func (s *Server) plugTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) { + if config == nil || config.tlsConfig == nil { + return nil, false, errors.New(certidp.ErrUnableToPlugTLSEmptyConfig) + } + kind := config.kind + isSpoke := config.isLeafSpoke + tcOpts := config.tlsOpts + if tcOpts == nil || tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify { + return nil, false, nil + } + s.Debugf(certidp.DbgPlugTLSForKind, config.kind) + // peer is a tls client + if kind == kindStringMap[CLIENT] || (kind == kindStringMap[LEAF] && !isSpoke) { + if !tcOpts.Verify { + return nil, false, errors.New(certidp.ErrMTLSRequired) + } + return s.plugClientTLSOCSPPeer(config) + } + // peer is a tls server + if kind == kindStringMap[LEAF] && isSpoke { + return s.plugServerTLSOCSPPeer(config) + } + return nil, false, nil +} + +func (s *Server) plugClientTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) { + if config == nil || config.tlsConfig == nil || config.tlsOpts == nil { + return nil, false, errors.New(certidp.ErrUnableToPlugTLSClient) + } + tc := config.tlsConfig + tcOpts := config.tlsOpts + kind := config.kind + if tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify { + return tc, false, nil + } + tc.VerifyConnection = func(cs tls.ConnectionState) error { + if !s.tlsClientOCSPValid(cs.VerifiedChains, tcOpts.OCSPPeerConfig) { + s.sendOCSPPeerRejectEvent(kind, peerFromVerifiedChains(cs.VerifiedChains), certidp.MsgTLSClientRejectConnection) + return errors.New(certidp.MsgTLSClientRejectConnection) + } + return nil + } + return tc, true, nil +} + +func (s *Server) plugServerTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) { + if config == nil || config.tlsConfig == nil || config.tlsOpts == nil { + return nil, false, errors.New(certidp.ErrUnableToPlugTLSServer) + } + tc := config.tlsConfig + tcOpts := config.tlsOpts + kind := config.kind + if tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify { + return tc, false, nil + } + tc.VerifyConnection = func(cs tls.ConnectionState) error { + if !s.tlsServerOCSPValid(cs.VerifiedChains, tcOpts.OCSPPeerConfig) { + s.sendOCSPPeerRejectEvent(kind, peerFromVerifiedChains(cs.VerifiedChains), certidp.MsgTLSServerRejectConnection) + return errors.New(certidp.MsgTLSServerRejectConnection) + } + return nil + } + return tc, true, nil +} + +// tlsServerOCSPValid evaluates verified chains (post successful TLS handshake) against OCSP +// eligibility. A verified chain is considered OCSP Valid if either none of the links are +// OCSP eligible, or current "good" responses from the CA can be obtained for each eligible link. +// Upon first OCSP Valid chain found, the Server is deemed OCSP Valid. If none of the chains are +// OCSP Valid, the Server is deemed OCSP Invalid. A verified self-signed certificate (chain length 1) +// is also considered OCSP Valid. +func (s *Server) tlsServerOCSPValid(chains [][]*x509.Certificate, opts *certidp.OCSPPeerConfig) bool { + s.Debugf(certidp.DbgNumServerChains, len(chains)) + return s.peerOCSPValid(chains, opts) +} + +// tlsClientOCSPValid evaluates verified chains (post successful TLS handshake) against OCSP +// eligibility. A verified chain is considered OCSP Valid if either none of the links are +// OCSP eligible, or current "good" responses from the CA can be obtained for each eligible link. +// Upon first OCSP Valid chain found, the Client is deemed OCSP Valid. If none of the chains are +// OCSP Valid, the Client is deemed OCSP Invalid. A verified self-signed certificate (chain length 1) +// is also considered OCSP Valid. +func (s *Server) tlsClientOCSPValid(chains [][]*x509.Certificate, opts *certidp.OCSPPeerConfig) bool { + s.Debugf(certidp.DbgNumClientChains, len(chains)) + return s.peerOCSPValid(chains, opts) +} + +func (s *Server) peerOCSPValid(chains [][]*x509.Certificate, opts *certidp.OCSPPeerConfig) bool { + peer := peerFromVerifiedChains(chains) + if peer == nil { + s.Errorf(certidp.ErrPeerEmptyAutoReject) + return false + } + for ci, chain := range chains { + s.Debugf(certidp.DbgLinksInChain, ci, len(chain)) + // Self-signed certificate is Client OCSP Valid (no CA) + if len(chain) == 1 { + s.Debugf(certidp.DbgSelfSignedValid, ci) + return true + } + // Check if any of the links in the chain are OCSP eligible + chainEligible := false + var eligibleLinks []*certidp.ChainLink + // Iterate over links skipping the root cert which is not OCSP eligible (self == issuer) + for linkPos := 0; linkPos < len(chain)-1; linkPos++ { + cert := chain[linkPos] + link := &certidp.ChainLink{ + Leaf: cert, + } + if certidp.CertOCSPEligible(link) { + chainEligible = true + issuerCert := certidp.GetLeafIssuerCert(chain, linkPos) + if issuerCert == nil { + // unexpected chain condition, reject Client as OCSP Invalid + return false + } + link.Issuer = issuerCert + eligibleLinks = append(eligibleLinks, link) + } + } + // A trust-store verified chain that is not OCSP eligible is always OCSP Valid + if !chainEligible { + s.Debugf(certidp.DbgValidNonOCSPChain, ci) + return true + } + s.Debugf(certidp.DbgChainIsOCSPEligible, ci, len(eligibleLinks)) + // Chain has at least one OCSP eligible link, so check each eligible link; + // any link with a !good OCSP response chain OCSP Invalid + chainValid := true + for _, link := range eligibleLinks { + // if option selected, good could reflect either ocsp.Good or ocsp.Unknown + if badReason, good := s.certOCSPGood(link, opts); !good { + s.Debugf(badReason) + s.sendOCSPPeerChainlinkInvalidEvent(peer, link.Leaf, badReason) + chainValid = false + break + } + } + if chainValid { + s.Debugf(certidp.DbgChainIsOCSPValid, ci) + return true + } + } + // If we are here, all chains had OCSP eligible links, but none of the chains achieved OCSP valid + s.Debugf(certidp.DbgNoOCSPValidChains) + return false +} + +func (s *Server) certOCSPGood(link *certidp.ChainLink, opts *certidp.OCSPPeerConfig) (string, bool) { + if link == nil || link.Leaf == nil || link.Issuer == nil || link.OCSPWebEndpoints == nil || len(*link.OCSPWebEndpoints) < 1 { + return "Empty chainlink found", false + } + var err error + sLogs := &certidp.Log{ + Debugf: s.Debugf, + Noticef: s.Noticef, + Warnf: s.Warnf, + Errorf: s.Errorf, + Tracef: s.Tracef, + } + fingerprint := certidp.GenerateFingerprint(link.Leaf) + // Used for debug/operator only, not match + subj := certidp.GetSubjectDNForm(link.Leaf) + var rawResp []byte + var ocspr *ocsp.Response + var useCachedResp bool + var rc = s.ocsprc + var cachedRevocation bool + // Check our cache before calling out to the CA OCSP responder + s.Debugf(certidp.DbgCheckingCacheForCert, subj, fingerprint) + if rawResp = rc.Get(fingerprint, sLogs); len(rawResp) > 0 { + // Signature validation of CA's OCSP response occurs in ParseResponse + ocspr, err = ocsp.ParseResponse(rawResp, link.Issuer) + if err == nil && ocspr != nil { + // Check if OCSP Response delegation present and if so is valid + if !certidp.ValidDelegationCheck(link.Issuer, ocspr) { + // Invalid delegation was already in cache, purge it and don't use it + s.Debugf(certidp.MsgCachedOCSPResponseInvalid, subj) + rc.Delete(fingerprint, true, sLogs) + goto AFTERCACHE + } + if certidp.OCSPResponseCurrent(ocspr, opts, sLogs) { + s.Debugf(certidp.DbgCurrentResponseCached, certidp.GetStatusAssertionStr(ocspr.Status)) + useCachedResp = true + } else { + // Cached response is not current, delete it and tidy runtime stats to reflect a miss; + // if preserve_revoked is enabled, the cache will not delete the cached response + s.Debugf(certidp.DbgExpiredResponseCached, certidp.GetStatusAssertionStr(ocspr.Status)) + rc.Delete(fingerprint, true, sLogs) + } + // Regardless of currency, record a cached revocation found in case AllowWhenCAUnreachable is set + if ocspr.Status == ocsp.Revoked { + cachedRevocation = true + } + } else { + // Bogus cached assertion, purge it and don't use it + s.Debugf(certidp.MsgCachedOCSPResponseInvalid, subj, fingerprint) + rc.Delete(fingerprint, true, sLogs) + goto AFTERCACHE + } + } +AFTERCACHE: + if !useCachedResp { + // CA OCSP responder callout needed + rawResp, err = certidp.FetchOCSPResponse(link, opts, sLogs) + if err != nil || rawResp == nil || len(rawResp) == 0 { + s.Warnf(certidp.ErrCAResponderCalloutFail, subj, err) + if opts.WarnOnly { + s.Warnf(certidp.MsgAllowWarnOnlyOccurred, subj) + return _EMPTY_, true + } + if opts.AllowWhenCAUnreachable && !cachedRevocation { + // Link has no cached history of revocation, so allow it to pass + s.Warnf(certidp.MsgAllowWhenCAUnreachableOccurred, subj) + return _EMPTY_, true + } else if opts.AllowWhenCAUnreachable { + // Link has cached but expired revocation so reject when CA is unreachable + s.Warnf(certidp.MsgAllowWhenCAUnreachableOccurredCachedRevoke, subj) + } + return certidp.MsgFailedOCSPResponseFetch, false + } + // Signature validation of CA's OCSP response occurs in ParseResponse + ocspr, err = ocsp.ParseResponse(rawResp, link.Issuer) + if err == nil && ocspr != nil { + // Check if OCSP Response delegation present and if so is valid + if !certidp.ValidDelegationCheck(link.Issuer, ocspr) { + s.Warnf(certidp.MsgOCSPResponseDelegationInvalid, subj) + if opts.WarnOnly { + // Can't use bogus assertion, but warn-only set so allow link to pass + s.Warnf(certidp.MsgAllowWarnOnlyOccurred, subj) + return _EMPTY_, true + } + return fmt.Sprintf(certidp.MsgOCSPResponseDelegationInvalid, subj), false + } + if !certidp.OCSPResponseCurrent(ocspr, opts, sLogs) { + s.Warnf(certidp.ErrNewCAResponseNotCurrent, subj) + if opts.WarnOnly { + // Can't use non-effective assertion, but warn-only set so allow link to pass + s.Warnf(certidp.MsgAllowWarnOnlyOccurred, subj) + return _EMPTY_, true + } + return certidp.MsgOCSPResponseNotEffective, false + } + } else { + s.Errorf(certidp.ErrCAResponseParseFailed, subj, err) + if opts.WarnOnly { + // Can't use bogus assertion, but warn-only set so allow link to pass + s.Warnf(certidp.MsgAllowWarnOnlyOccurred, subj) + return _EMPTY_, true + } + return certidp.MsgFailedOCSPResponseParse, false + } + // cache the valid fetched CA OCSP Response + rc.Put(fingerprint, ocspr, subj, sLogs) + } + + // Whether through valid cache response available or newly fetched valid response, now check the status + if ocspr.Status == ocsp.Revoked || (ocspr.Status == ocsp.Unknown && !opts.UnknownIsGood) { + s.Warnf(certidp.ErrOCSPInvalidPeerLink, subj, certidp.GetStatusAssertionStr(ocspr.Status)) + if opts.WarnOnly { + s.Warnf(certidp.MsgAllowWarnOnlyOccurred, subj) + return _EMPTY_, true + } + return fmt.Sprintf(certidp.MsgOCSPResponseInvalidStatus, certidp.GetStatusAssertionStr(ocspr.Status)), false + } + s.Debugf(certidp.DbgOCSPValidPeerLink, subj) + return _EMPTY_, true +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ocsp_responsecache.go b/vendor/github.com/nats-io/nats-server/v2/server/ocsp_responsecache.go new file mode 100644 index 0000000..c384812 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/ocsp_responsecache.go @@ -0,0 +1,636 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "os" + "path" + "path/filepath" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/klauspost/compress/s2" + "golang.org/x/crypto/ocsp" + + "github.com/nats-io/nats-server/v2/server/certidp" +) + +const ( + OCSPResponseCacheDefaultDir = "_rc_" + OCSPResponseCacheDefaultFilename = "cache.json" + OCSPResponseCacheDefaultTempFilePrefix = "ocsprc-*" + OCSPResponseCacheMinimumSaveInterval = 1 * time.Second + OCSPResponseCacheDefaultSaveInterval = 5 * time.Minute +) + +type OCSPResponseCacheType int + +const ( + NONE OCSPResponseCacheType = iota + 1 + LOCAL +) + +var OCSPResponseCacheTypeMap = map[string]OCSPResponseCacheType{ + "none": NONE, + "local": LOCAL, +} + +type OCSPResponseCacheConfig struct { + Type OCSPResponseCacheType + LocalStore string + PreserveRevoked bool + SaveInterval float64 +} + +func NewOCSPResponseCacheConfig() *OCSPResponseCacheConfig { + return &OCSPResponseCacheConfig{ + Type: LOCAL, + LocalStore: OCSPResponseCacheDefaultDir, + PreserveRevoked: false, + SaveInterval: OCSPResponseCacheDefaultSaveInterval.Seconds(), + } +} + +type OCSPResponseCacheStats struct { + Responses int64 `json:"size"` + Hits int64 `json:"hits"` + Misses int64 `json:"misses"` + Revokes int64 `json:"revokes"` + Goods int64 `json:"goods"` + Unknowns int64 `json:"unknowns"` +} + +type OCSPResponseCacheItem struct { + Subject string `json:"subject,omitempty"` + CachedAt time.Time `json:"cached_at"` + RespStatus certidp.StatusAssertion `json:"resp_status"` + RespExpires time.Time `json:"resp_expires,omitempty"` + Resp []byte `json:"resp"` +} + +type OCSPResponseCache interface { + Put(key string, resp *ocsp.Response, subj string, log *certidp.Log) + Get(key string, log *certidp.Log) []byte + Delete(key string, miss bool, log *certidp.Log) + Type() string + Start(s *Server) + Stop(s *Server) + Online() bool + Config() *OCSPResponseCacheConfig + Stats() *OCSPResponseCacheStats +} + +// NoOpCache is a no-op implementation of OCSPResponseCache +type NoOpCache struct { + config *OCSPResponseCacheConfig + stats *OCSPResponseCacheStats + online bool + mu *sync.RWMutex +} + +func (c *NoOpCache) Put(_ string, _ *ocsp.Response, _ string, _ *certidp.Log) {} + +func (c *NoOpCache) Get(_ string, _ *certidp.Log) []byte { + return nil +} + +func (c *NoOpCache) Delete(_ string, _ bool, _ *certidp.Log) {} + +func (c *NoOpCache) Start(_ *Server) { + c.mu.Lock() + defer c.mu.Unlock() + c.stats = &OCSPResponseCacheStats{} + c.online = true +} + +func (c *NoOpCache) Stop(_ *Server) { + c.mu.Lock() + defer c.mu.Unlock() + c.online = false +} + +func (c *NoOpCache) Online() bool { + c.mu.RLock() + defer c.mu.RUnlock() + return c.online +} + +func (c *NoOpCache) Type() string { + c.mu.RLock() + defer c.mu.RUnlock() + return "none" +} + +func (c *NoOpCache) Config() *OCSPResponseCacheConfig { + c.mu.RLock() + defer c.mu.RUnlock() + return c.config +} + +func (c *NoOpCache) Stats() *OCSPResponseCacheStats { + c.mu.RLock() + defer c.mu.RUnlock() + return c.stats +} + +// LocalCache is a local file implementation of OCSPResponseCache +type LocalCache struct { + config *OCSPResponseCacheConfig + stats *OCSPResponseCacheStats + online bool + cache map[string]OCSPResponseCacheItem + mu *sync.RWMutex + saveInterval time.Duration + dirty bool + timer *time.Timer +} + +// Put captures a CA OCSP response to the OCSP peer cache indexed by response fingerprint (a hash) +func (c *LocalCache) Put(key string, caResp *ocsp.Response, subj string, log *certidp.Log) { + c.mu.RLock() + if !c.online || caResp == nil || key == "" { + c.mu.RUnlock() + return + } + c.mu.RUnlock() + log.Debugf(certidp.DbgCachingResponse, subj, key) + rawC, err := c.Compress(caResp.Raw) + if err != nil { + log.Errorf(certidp.ErrResponseCompressFail, key, err) + return + } + log.Debugf(certidp.DbgAchievedCompression, float64(len(rawC))/float64(len(caResp.Raw))) + c.mu.Lock() + defer c.mu.Unlock() + // check if we are replacing and do stats + item, ok := c.cache[key] + if ok { + c.adjustStats(-1, item.RespStatus) + } + item = OCSPResponseCacheItem{ + Subject: subj, + CachedAt: time.Now().UTC().Round(time.Second), + RespStatus: certidp.StatusAssertionIntToVal[caResp.Status], + RespExpires: caResp.NextUpdate, + Resp: rawC, + } + c.cache[key] = item + c.adjustStats(1, item.RespStatus) + c.dirty = true +} + +// Get returns a CA OCSP response from the OCSP peer cache matching the response fingerprint (a hash) +func (c *LocalCache) Get(key string, log *certidp.Log) []byte { + c.mu.RLock() + defer c.mu.RUnlock() + if !c.online || key == "" { + return nil + } + val, ok := c.cache[key] + if ok { + atomic.AddInt64(&c.stats.Hits, 1) + log.Debugf(certidp.DbgCacheHit, key) + } else { + atomic.AddInt64(&c.stats.Misses, 1) + log.Debugf(certidp.DbgCacheMiss, key) + return nil + } + resp, err := c.Decompress(val.Resp) + if err != nil { + log.Errorf(certidp.ErrResponseDecompressFail, key, err) + return nil + } + return resp +} + +func (c *LocalCache) adjustStatsHitToMiss() { + atomic.AddInt64(&c.stats.Misses, 1) + atomic.AddInt64(&c.stats.Hits, -1) +} + +func (c *LocalCache) adjustStats(delta int64, rs certidp.StatusAssertion) { + if delta == 0 { + return + } + atomic.AddInt64(&c.stats.Responses, delta) + switch rs { + case ocsp.Good: + atomic.AddInt64(&c.stats.Goods, delta) + case ocsp.Revoked: + atomic.AddInt64(&c.stats.Revokes, delta) + case ocsp.Unknown: + atomic.AddInt64(&c.stats.Unknowns, delta) + } +} + +// Delete removes a CA OCSP response from the OCSP peer cache matching the response fingerprint (a hash) +func (c *LocalCache) Delete(key string, wasMiss bool, log *certidp.Log) { + c.mu.Lock() + defer c.mu.Unlock() + if !c.online || key == "" || c.config == nil { + return + } + item, ok := c.cache[key] + if !ok { + return + } + if item.RespStatus == ocsp.Revoked && c.config.PreserveRevoked { + log.Debugf(certidp.DbgPreservedRevocation, key) + if wasMiss { + c.adjustStatsHitToMiss() + } + return + } + log.Debugf(certidp.DbgDeletingCacheResponse, key) + delete(c.cache, key) + c.adjustStats(-1, item.RespStatus) + if wasMiss { + c.adjustStatsHitToMiss() + } + c.dirty = true +} + +// Start initializes the configured OCSP peer cache, loads a saved cache from disk (if present), and initializes runtime statistics +func (c *LocalCache) Start(s *Server) { + s.Debugf(certidp.DbgStartingCache) + c.loadCache(s) + c.initStats() + c.mu.Lock() + c.online = true + c.mu.Unlock() +} + +func (c *LocalCache) Stop(s *Server) { + c.mu.Lock() + s.Debugf(certidp.DbgStoppingCache) + c.online = false + c.timer.Stop() + c.mu.Unlock() + c.saveCache(s) +} + +func (c *LocalCache) Online() bool { + c.mu.RLock() + defer c.mu.RUnlock() + return c.online +} + +func (c *LocalCache) Type() string { + c.mu.RLock() + defer c.mu.RUnlock() + return "local" +} + +func (c *LocalCache) Config() *OCSPResponseCacheConfig { + c.mu.RLock() + defer c.mu.RUnlock() + return c.config +} + +func (c *LocalCache) Stats() *OCSPResponseCacheStats { + c.mu.RLock() + defer c.mu.RUnlock() + if c.stats == nil { + return nil + } + stats := OCSPResponseCacheStats{ + Responses: c.stats.Responses, + Hits: c.stats.Hits, + Misses: c.stats.Misses, + Revokes: c.stats.Revokes, + Goods: c.stats.Goods, + Unknowns: c.stats.Unknowns, + } + return &stats +} + +func (c *LocalCache) initStats() { + c.mu.Lock() + defer c.mu.Unlock() + c.stats = &OCSPResponseCacheStats{} + c.stats.Hits = 0 + c.stats.Misses = 0 + c.stats.Responses = int64(len(c.cache)) + for _, resp := range c.cache { + switch resp.RespStatus { + case ocsp.Good: + c.stats.Goods++ + case ocsp.Revoked: + c.stats.Revokes++ + case ocsp.Unknown: + c.stats.Unknowns++ + } + } +} + +func (c *LocalCache) Compress(buf []byte) ([]byte, error) { + bodyLen := int64(len(buf)) + var output bytes.Buffer + writer := s2.NewWriter(&output) + input := bytes.NewReader(buf[:bodyLen]) + if n, err := io.CopyN(writer, input, bodyLen); err != nil { + return nil, fmt.Errorf(certidp.ErrCannotWriteCompressed, err) + } else if n != bodyLen { + return nil, fmt.Errorf(certidp.ErrTruncatedWrite, n, bodyLen) + } + if err := writer.Close(); err != nil { + return nil, fmt.Errorf(certidp.ErrCannotCloseWriter, err) + } + return output.Bytes(), nil +} + +func (c *LocalCache) Decompress(buf []byte) ([]byte, error) { + bodyLen := int64(len(buf)) + input := bytes.NewReader(buf[:bodyLen]) + reader := io.NopCloser(s2.NewReader(input)) + output, err := io.ReadAll(reader) + if err != nil { + return nil, fmt.Errorf(certidp.ErrCannotReadCompressed, err) + } + return output, reader.Close() +} + +func (c *LocalCache) loadCache(s *Server) { + d := s.opts.OCSPCacheConfig.LocalStore + if d == _EMPTY_ { + d = OCSPResponseCacheDefaultDir + } + f := OCSPResponseCacheDefaultFilename + store, err := filepath.Abs(path.Join(d, f)) + if err != nil { + s.Errorf(certidp.ErrLoadCacheFail, err) + return + } + s.Debugf(certidp.DbgLoadingCache, store) + c.mu.Lock() + defer c.mu.Unlock() + c.cache = make(map[string]OCSPResponseCacheItem) + dat, err := os.ReadFile(store) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + s.Debugf(certidp.DbgNoCacheFound) + } else { + s.Warnf(certidp.ErrLoadCacheFail, err) + } + return + } + err = json.Unmarshal(dat, &c.cache) + if err != nil { + // make sure clean cache + c.cache = make(map[string]OCSPResponseCacheItem) + s.Warnf(certidp.ErrLoadCacheFail, err) + c.dirty = true + return + } + c.dirty = false +} + +func (c *LocalCache) saveCache(s *Server) { + c.mu.RLock() + dirty := c.dirty + c.mu.RUnlock() + if !dirty { + return + } + s.Debugf(certidp.DbgCacheDirtySave) + var d string + if c.config.LocalStore != _EMPTY_ { + d = c.config.LocalStore + } else { + d = OCSPResponseCacheDefaultDir + } + f := OCSPResponseCacheDefaultFilename + store, err := filepath.Abs(path.Join(d, f)) + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + s.Debugf(certidp.DbgSavingCache, store) + if _, err := os.Stat(d); os.IsNotExist(err) { + err = os.Mkdir(d, defaultDirPerms) + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + } + tmp, err := os.CreateTemp(d, OCSPResponseCacheDefaultTempFilePrefix) + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + defer func() { + tmp.Close() + os.Remove(tmp.Name()) + }() // clean up any temp files + + // RW lock here because we're going to snapshot the cache to disk and mark as clean if successful + c.mu.Lock() + defer c.mu.Unlock() + dat, err := json.MarshalIndent(c.cache, "", " ") + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + cacheSize, err := tmp.Write(dat) + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + err = tmp.Sync() + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + err = tmp.Close() + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + // do the final swap and overwrite any old saved peer cache + err = os.Rename(tmp.Name(), store) + if err != nil { + s.Errorf(certidp.ErrSaveCacheFail, err) + return + } + c.dirty = false + s.Debugf(certidp.DbgCacheSaved, cacheSize) +} + +var OCSPResponseCacheUsage = ` +You may enable OCSP peer response cacheing at server configuration root level: + +(If no TLS blocks are configured with OCSP peer verification, ocsp_cache is ignored.) + + ... + # short form enables with defaults + ocsp_cache: true + + # if false or undefined and one or more TLS blocks are configured with OCSP peer verification, "none" is implied + + # long form includes settable options + ocsp_cache { + + # Cache type (default local) + type: local + + # Cache file directory for local-type cache (default _rc_ in current working directory) + local_store: "_rc_" + + # Ignore cache deletes if cached OCSP response is Revoked status (default false) + preserve_revoked: false + + # For local store, interval to save in-memory cache to disk in seconds (default 300 seconds, minimum 1 second) + save_interval: 300 + } + ... + +Note: Cache of server's own OCSP response (staple) is enabled using the 'ocsp' configuration option. +` + +func (s *Server) initOCSPResponseCache() { + // No mTLS OCSP or Leaf OCSP enablements, so no need to init cache + s.mu.RLock() + if !s.ocspPeerVerify { + s.mu.RUnlock() + return + } + s.mu.RUnlock() + so := s.getOpts() + if so.OCSPCacheConfig == nil { + so.OCSPCacheConfig = NewOCSPResponseCacheConfig() + } + var cc = so.OCSPCacheConfig + s.mu.Lock() + defer s.mu.Unlock() + switch cc.Type { + case NONE: + s.ocsprc = &NoOpCache{config: cc, online: true, mu: &sync.RWMutex{}} + case LOCAL: + c := &LocalCache{ + config: cc, + online: false, + cache: make(map[string]OCSPResponseCacheItem), + mu: &sync.RWMutex{}, + dirty: false, + } + c.saveInterval = time.Duration(cc.SaveInterval) * time.Second + c.timer = time.AfterFunc(c.saveInterval, func() { + s.Debugf(certidp.DbgCacheSaveTimerExpired) + c.saveCache(s) + c.timer.Reset(c.saveInterval) + }) + s.ocsprc = c + default: + s.Fatalf(certidp.ErrBadCacheTypeConfig, cc.Type) + } +} + +func (s *Server) startOCSPResponseCache() { + // No mTLS OCSP or Leaf OCSP enablements, so no need to start cache + s.mu.RLock() + if !s.ocspPeerVerify || s.ocsprc == nil { + s.mu.RUnlock() + return + } + s.mu.RUnlock() + + // Could be heavier operation depending on cache implementation + s.ocsprc.Start(s) + if s.ocsprc.Online() { + s.Noticef(certidp.MsgCacheOnline, s.ocsprc.Type()) + } else { + s.Noticef(certidp.MsgCacheOffline, s.ocsprc.Type()) + } +} + +func (s *Server) stopOCSPResponseCache() { + s.mu.RLock() + if s.ocsprc == nil { + s.mu.RUnlock() + return + } + s.mu.RUnlock() + s.ocsprc.Stop(s) +} + +func parseOCSPResponseCache(v any) (pcfg *OCSPResponseCacheConfig, retError error) { + var lt token + defer convertPanicToError(<, &retError) + tk, v := unwrapValue(v, <) + cm, ok := v.(map[string]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrIllegalCacheOptsConfig, v)} + } + pcfg = NewOCSPResponseCacheConfig() + retError = nil + for mk, mv := range cm { + // Again, unwrap token value if line check is required. + tk, mv = unwrapValue(mv, <) + switch strings.ToLower(mk) { + case "type": + cache, ok := mv.(string) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingCacheOptFieldGeneric, mk)} + } + cacheType, exists := OCSPResponseCacheTypeMap[strings.ToLower(cache)] + if !exists { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrUnknownCacheType, cache)} + } + pcfg.Type = cacheType + case "local_store": + store, ok := mv.(string) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingCacheOptFieldGeneric, mk)} + } + pcfg.LocalStore = store + case "preserve_revoked": + preserve, ok := mv.(bool) + if !ok { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingCacheOptFieldGeneric, mk)} + } + pcfg.PreserveRevoked = preserve + case "save_interval": + at := float64(0) + switch mv := mv.(type) { + case int64: + at = float64(mv) + case float64: + at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingPeerOptFieldTypeConversion, err)} + } + at = d.Seconds() + default: + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingCacheOptFieldTypeConversion, "unexpected type")} + } + si := time.Duration(at) * time.Second + if si < OCSPResponseCacheMinimumSaveInterval { + si = OCSPResponseCacheMinimumSaveInterval + } + pcfg.SaveInterval = si.Seconds() + default: + return nil, &configErr{tk, fmt.Sprintf(certidp.ErrParsingCacheOptFieldGeneric, mk)} + } + } + return pcfg, nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/opts.go b/vendor/github.com/nats-io/nats-server/v2/server/opts.go index 3f44538..a7fcb2b 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/opts.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/opts.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,12 +15,13 @@ package server import ( "context" + "crypto/fips140" "crypto/tls" "crypto/x509" "errors" "flag" "fmt" - "io/ioutil" + "math" "net" "net/url" "os" @@ -34,9 +35,10 @@ import ( "time" "github.com/nats-io/jwt/v2" - "github.com/nats-io/nkeys" - "github.com/nats-io/nats-server/v2/conf" + "github.com/nats-io/nats-server/v2/server/certidp" + "github.com/nats-io/nats-server/v2/server/certstore" + "github.com/nats-io/nkeys" ) var allowUnknownTopLevelField = int32(0) @@ -53,28 +55,56 @@ func NoErrOnUnknownFields(noError bool) { atomic.StoreInt32(&allowUnknownTopLevelField, val) } +// PinnedCertSet is a set of lower case hex-encoded sha256 of DER encoded SubjectPublicKeyInfo +type PinnedCertSet map[string]struct{} + // ClusterOpts are options for clusters. // NOTE: This structure is no longer used for monitoring endpoints // and json tags are deprecated and may be removed in the future. type ClusterOpts struct { - Name string `json:"-"` - Host string `json:"addr,omitempty"` - Port int `json:"cluster_port,omitempty"` - Username string `json:"-"` - Password string `json:"-"` - AuthTimeout float64 `json:"auth_timeout,omitempty"` - Permissions *RoutePermissions `json:"-"` - TLSTimeout float64 `json:"-"` - TLSConfig *tls.Config `json:"-"` - TLSMap bool `json:"-"` - TLSCheckKnwonURLs bool `json:"-"` - ListenStr string `json:"-"` - Advertise string `json:"-"` - NoAdvertise bool `json:"-"` - ConnectRetries int `json:"-"` + Name string `json:"-"` + Host string `json:"addr,omitempty"` + Port int `json:"cluster_port,omitempty"` + Username string `json:"-"` + Password string `json:"-"` + AuthTimeout float64 `json:"auth_timeout,omitempty"` + Permissions *RoutePermissions `json:"-"` + TLSTimeout float64 `json:"-"` + TLSConfig *tls.Config `json:"-"` + TLSMap bool `json:"-"` + TLSCheckKnownURLs bool `json:"-"` + TLSPinnedCerts PinnedCertSet `json:"-"` + ListenStr string `json:"-"` + Advertise string `json:"-"` + NoAdvertise bool `json:"-"` + ConnectRetries int `json:"-"` + PoolSize int `json:"-"` + PinnedAccounts []string `json:"-"` + Compression CompressionOpts `json:"-"` + PingInterval time.Duration `json:"-"` + MaxPingsOut int `json:"-"` + WriteDeadline time.Duration `json:"-"` + WriteTimeout WriteTimeoutPolicy `json:"-"` // Not exported (used in tests) resolver netResolver + // Snapshot of configured TLS options. + tlsConfigOpts *TLSConfigOpts +} + +// CompressionOpts defines the compression mode and optional configuration. +type CompressionOpts struct { + Mode string + // If `Mode` is set to CompressionS2Auto, RTTThresholds provides the + // thresholds at which the compression level will go from + // CompressionS2Uncompressed to CompressionS2Fast, CompressionS2Better + // or CompressionS2Best. If a given level is not desired, specify 0 + // for this slot. For instance, the slice []{0, 10ms, 20ms} means that + // for any RTT up to 10ms included the compression level will be + // CompressionS2Fast, then from ]10ms..20ms], the level will be selected + // as CompressionS2Better. Anything above 20ms will result in picking + // the CompressionS2Best compression level. + RTTThresholds []time.Duration } // GatewayOpts are options for gateways. @@ -91,135 +121,283 @@ type GatewayOpts struct { TLSTimeout float64 `json:"tls_timeout,omitempty"` TLSMap bool `json:"-"` TLSCheckKnownURLs bool `json:"-"` + TLSPinnedCerts PinnedCertSet `json:"-"` Advertise string `json:"advertise,omitempty"` ConnectRetries int `json:"connect_retries,omitempty"` Gateways []*RemoteGatewayOpts `json:"gateways,omitempty"` RejectUnknown bool `json:"reject_unknown,omitempty"` // config got renamed to reject_unknown_cluster + WriteDeadline time.Duration `json:"-"` + WriteTimeout WriteTimeoutPolicy `json:"-"` // Not exported, for tests. resolver netResolver sendQSubsBufSize int + + // Snapshot of configured TLS options. + tlsConfigOpts *TLSConfigOpts } // RemoteGatewayOpts are options for connecting to a remote gateway // NOTE: This structure is no longer used for monitoring endpoints // and json tags are deprecated and may be removed in the future. type RemoteGatewayOpts struct { - Name string `json:"name"` - TLSConfig *tls.Config `json:"-"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - URLs []*url.URL `json:"urls,omitempty"` + Name string `json:"name"` + TLSConfig *tls.Config `json:"-"` + TLSTimeout float64 `json:"tls_timeout,omitempty"` + URLs []*url.URL `json:"urls,omitempty"` + tlsConfigOpts *TLSConfigOpts } // LeafNodeOpts are options for a given server to accept leaf node connections and/or connect to a remote cluster. type LeafNodeOpts struct { - Host string `json:"addr,omitempty"` - Port int `json:"port,omitempty"` - Username string `json:"-"` - Password string `json:"-"` - Account string `json:"-"` - Users []*User `json:"-"` - AuthTimeout float64 `json:"auth_timeout,omitempty"` - TLSConfig *tls.Config `json:"-"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - TLSMap bool `json:"-"` - Advertise string `json:"-"` - NoAdvertise bool `json:"-"` - ReconnectInterval time.Duration `json:"-"` + Host string `json:"addr,omitempty"` + Port int `json:"port,omitempty"` + Username string `json:"-"` + Password string `json:"-"` + Nkey string `json:"-"` + Account string `json:"-"` + Users []*User `json:"-"` + AuthTimeout float64 `json:"auth_timeout,omitempty"` + TLSConfig *tls.Config `json:"-"` + TLSTimeout float64 `json:"tls_timeout,omitempty"` + TLSMap bool `json:"-"` + TLSPinnedCerts PinnedCertSet `json:"-"` + // When set to true, the server will perform the TLS handshake before + // sending the INFO protocol. For remote leafnodes that are not configured + // with a similar option, their connection will fail with some sort + // of timeout or EOF error since they are expecting to receive an + // INFO protocol first. + TLSHandshakeFirst bool `json:"-"` + // If TLSHandshakeFirst is true and this value is strictly positive, + // the server will wait for that amount of time for the TLS handshake + // to start before falling back to previous behavior of sending the + // INFO protocol first. It allows for a mix of newer remote leafnodes + // that can require a TLS handshake first, and older that can't. + TLSHandshakeFirstFallback time.Duration `json:"-"` + Advertise string `json:"-"` + NoAdvertise bool `json:"-"` + ReconnectInterval time.Duration `json:"-"` + WriteDeadline time.Duration `json:"-"` + WriteTimeout WriteTimeoutPolicy `json:"-"` + + // Compression options + Compression CompressionOpts `json:"-"` // For solicited connections to other clusters/superclusters. Remotes []*RemoteLeafOpts `json:"remotes,omitempty"` + // This is the minimum version that is accepted for remote connections. + // Note that since the server version in the CONNECT protocol was added + // only starting at v2.8.0, any version below that will be rejected + // (since empty version string in CONNECT would fail the "version at + // least" test). + MinVersion string + // Not exported, for tests. resolver netResolver dialTimeout time.Duration connDelay time.Duration + + // Snapshot of configured TLS options. + tlsConfigOpts *TLSConfigOpts } +// SignatureHandler is used to sign a nonce from the server while +// authenticating with Nkeys. The callback should sign the nonce and +// return the JWT and the raw signature. +type SignatureHandler func([]byte) (string, []byte, error) + // RemoteLeafOpts are options for connecting to a remote server as a leaf node. type RemoteLeafOpts struct { - LocalAccount string `json:"local_account,omitempty"` - URLs []*url.URL `json:"urls,omitempty"` - Credentials string `json:"-"` - TLS bool `json:"-"` - TLSConfig *tls.Config `json:"-"` - TLSTimeout float64 `json:"tls_timeout,omitempty"` - Hub bool `json:"hub,omitempty"` - DenyImports []string `json:"-"` - DenyExports []string `json:"-"` + LocalAccount string `json:"local_account,omitempty"` + NoRandomize bool `json:"-"` + URLs []*url.URL `json:"urls,omitempty"` + Credentials string `json:"-"` + Nkey string `json:"-"` + SignatureCB SignatureHandler `json:"-"` + TLS bool `json:"-"` + TLSConfig *tls.Config `json:"-"` + TLSTimeout float64 `json:"tls_timeout,omitempty"` + TLSHandshakeFirst bool `json:"-"` + Hub bool `json:"hub,omitempty"` + DenyImports []string `json:"-"` + DenyExports []string `json:"-"` + + // FirstInfoTimeout is the amount of time the server will wait for the + // initial INFO protocol from the remote server before closing the + // connection. + FirstInfoTimeout time.Duration `json:"-"` + + // Compression options for this remote. Each remote could have a different + // setting and also be different from the LeafNode options. + Compression CompressionOpts `json:"-"` + + // When an URL has the "ws" (or "wss") scheme, then the server will initiate the + // connection as a websocket connection. By default, the websocket frames will be + // masked (as if this server was a websocket client to the remote server). The + // NoMasking option will change this behavior and will send umasked frames. + Websocket struct { + Compression bool `json:"-"` + NoMasking bool `json:"-"` + } + + tlsConfigOpts *TLSConfigOpts + + // If we are clustered and our local account has JetStream, if apps are accessing + // a stream or consumer leader through this LN and it gets dropped, the apps will + // not be able to work. This tells the system to migrate the leaders away from this server. + // This only changes leader for R>1 assets. + JetStreamClusterMigrate bool `json:"jetstream_cluster_migrate,omitempty"` + + // If JetStreamClusterMigrate is set to true, this is the time after which the leader + // will be migrated away from this server if still disconnected. + JetStreamClusterMigrateDelay time.Duration `json:"jetstream_cluster_migrate_delay,omitempty"` +} + +// JSLimitOpts are active limits for the meta cluster +type JSLimitOpts struct { + MaxRequestBatch int `json:"max_request_batch,omitempty"` // MaxRequestBatch is the maximum amount of updates that can be sent in a batch + MaxAckPending int `json:"max_ack_pending,omitempty"` // MaxAckPending is the server limit for maximum amount of outstanding Acks + MaxHAAssets int `json:"max_ha_assets,omitempty"` // MaxHAAssets is the maximum of Streams and Consumers that may have more than 1 replica + Duplicates time.Duration `json:"max_duplicate_window,omitempty"` // Duplicates is the maximum value for duplicate tracking on Streams +} + +type JSTpmOpts struct { + KeysFile string + KeyPassword string + SrkPassword string + Pcr int +} + +// AuthCallout option used to map external AuthN to NATS based AuthZ. +type AuthCallout struct { + // Must be a public account Nkey. + Issuer string + // Account to be used for sending requests. + Account string + // Users that will bypass auth_callout and be used for the auth service itself. + AuthUsers []string + // XKey is a public xkey for the authorization service. + // This will enable encryption for server requests and the authorization service responses. + XKey string + // AllowedAccounts that will be delegated to the auth service. + // If empty then all accounts will be delegated. + AllowedAccounts []string } // Options block for nats-server. // NOTE: This structure is no longer used for monitoring endpoints // and json tags are deprecated and may be removed in the future. type Options struct { - ConfigFile string `json:"-"` - ServerName string `json:"server_name"` - Host string `json:"addr"` - Port int `json:"port"` - ClientAdvertise string `json:"-"` - Trace bool `json:"-"` - Debug bool `json:"-"` - TraceVerbose bool `json:"-"` - NoLog bool `json:"-"` - NoSigs bool `json:"-"` - NoSublistCache bool `json:"-"` - NoHeaderSupport bool `json:"-"` - DisableShortFirstPing bool `json:"-"` - Logtime bool `json:"-"` - MaxConn int `json:"max_connections"` - MaxSubs int `json:"max_subscriptions,omitempty"` - Nkeys []*NkeyUser `json:"-"` - Users []*User `json:"-"` - Accounts []*Account `json:"-"` - NoAuthUser string `json:"-"` - SystemAccount string `json:"-"` - NoSystemAccount bool `json:"-"` - AllowNewAccounts bool `json:"-"` - Username string `json:"-"` - Password string `json:"-"` - Authorization string `json:"-"` - PingInterval time.Duration `json:"ping_interval"` - MaxPingsOut int `json:"ping_max"` - HTTPHost string `json:"http_host"` - HTTPPort int `json:"http_port"` - HTTPBasePath string `json:"http_base_path"` - HTTPSPort int `json:"https_port"` - AuthTimeout float64 `json:"auth_timeout"` - MaxControlLine int32 `json:"max_control_line"` - MaxPayload int32 `json:"max_payload"` - MaxPending int64 `json:"max_pending"` - Cluster ClusterOpts `json:"cluster,omitempty"` - Gateway GatewayOpts `json:"gateway,omitempty"` - LeafNode LeafNodeOpts `json:"leaf,omitempty"` - JetStream bool `json:"jetstream"` - JetStreamMaxMemory int64 `json:"-"` - JetStreamMaxStore int64 `json:"-"` - StoreDir string `json:"-"` - Websocket WebsocketOpts `json:"-"` - MQTT MQTTOpts `json:"-"` - ProfPort int `json:"-"` - PidFile string `json:"-"` - PortsFileDir string `json:"-"` - LogFile string `json:"-"` - LogSizeLimit int64 `json:"-"` - Syslog bool `json:"-"` - RemoteSyslog string `json:"-"` - Routes []*url.URL `json:"-"` - RoutesStr string `json:"-"` - TLSTimeout float64 `json:"tls_timeout"` - TLS bool `json:"-"` - TLSVerify bool `json:"-"` - TLSMap bool `json:"-"` - TLSCert string `json:"-"` - TLSKey string `json:"-"` - TLSCaCert string `json:"-"` - TLSConfig *tls.Config `json:"-"` - AllowNonTLS bool `json:"-"` - WriteDeadline time.Duration `json:"-"` - MaxClosedClients int `json:"-"` - LameDuckDuration time.Duration `json:"-"` - LameDuckGracePeriod time.Duration `json:"-"` + ConfigFile string `json:"-"` + ServerName string `json:"server_name"` + Host string `json:"addr"` + Port int `json:"port"` + DontListen bool `json:"dont_listen"` + ClientAdvertise string `json:"-"` + Trace bool `json:"-"` + Debug bool `json:"-"` + TraceVerbose bool `json:"-"` + // TraceHeaders if true will only trace message headers, not the payload + TraceHeaders bool `json:"-"` + NoLog bool `json:"-"` + NoSigs bool `json:"-"` + NoSublistCache bool `json:"-"` + NoHeaderSupport bool `json:"-"` + DisableShortFirstPing bool `json:"-"` + Logtime bool `json:"-"` + LogtimeUTC bool `json:"-"` + MaxConn int `json:"max_connections"` + MaxSubs int `json:"max_subscriptions,omitempty"` + MaxSubTokens uint8 `json:"-"` + Nkeys []*NkeyUser `json:"-"` + Users []*User `json:"-"` + Accounts []*Account `json:"-"` + NoAuthUser string `json:"-"` + DefaultSentinel string `json:"-"` + SystemAccount string `json:"-"` + NoSystemAccount bool `json:"-"` + Username string `json:"-"` + Password string `json:"-"` + Authorization string `json:"-"` + AuthCallout *AuthCallout `json:"-"` + PingInterval time.Duration `json:"ping_interval"` + MaxPingsOut int `json:"ping_max"` + HTTPHost string `json:"http_host"` + HTTPPort int `json:"http_port"` + HTTPBasePath string `json:"http_base_path"` + HTTPSPort int `json:"https_port"` + AuthTimeout float64 `json:"auth_timeout"` + MaxControlLine int32 `json:"max_control_line"` + MaxPayload int32 `json:"max_payload"` + MaxPending int64 `json:"max_pending"` + NoFastProducerStall bool `json:"-"` + Cluster ClusterOpts `json:"cluster,omitempty"` + Gateway GatewayOpts `json:"gateway,omitempty"` + LeafNode LeafNodeOpts `json:"leaf,omitempty"` + JetStream bool `json:"jetstream"` + JetStreamStrict bool `json:"-"` + JetStreamMaxMemory int64 `json:"-"` + JetStreamMaxStore int64 `json:"-"` + JetStreamDomain string `json:"-"` + JetStreamExtHint string `json:"-"` + JetStreamKey string `json:"-"` + JetStreamOldKey string `json:"-"` + JetStreamCipher StoreCipher `json:"-"` + JetStreamUniqueTag string + JetStreamLimits JSLimitOpts + JetStreamTpm JSTpmOpts + JetStreamMaxCatchup int64 + JetStreamRequestQueueLimit int64 + JetStreamMetaCompact uint64 + JetStreamMetaCompactSize uint64 + StreamMaxBufferedMsgs int `json:"-"` + StreamMaxBufferedSize int64 `json:"-"` + StoreDir string `json:"-"` + SyncInterval time.Duration `json:"-"` + SyncAlways bool `json:"-"` + JsAccDefaultDomain map[string]string `json:"-"` // account to domain name mapping + Websocket WebsocketOpts `json:"-"` + MQTT MQTTOpts `json:"-"` + ProfPort int `json:"-"` + ProfBlockRate int `json:"-"` + PidFile string `json:"-"` + PortsFileDir string `json:"-"` + LogFile string `json:"-"` + LogSizeLimit int64 `json:"-"` + LogMaxFiles int64 `json:"-"` + Syslog bool `json:"-"` + RemoteSyslog string `json:"-"` + Routes []*url.URL `json:"-"` + RoutesStr string `json:"-"` + TLSTimeout float64 `json:"tls_timeout"` + TLS bool `json:"-"` + TLSVerify bool `json:"-"` + TLSMap bool `json:"-"` + TLSCert string `json:"-"` + TLSKey string `json:"-"` + TLSCaCert string `json:"-"` + TLSConfig *tls.Config `json:"-"` + TLSPinnedCerts PinnedCertSet `json:"-"` + TLSRateLimit int64 `json:"-"` + // When set to true, the server will perform the TLS handshake before + // sending the INFO protocol. For clients that are not configured + // with a similar option, their connection will fail with some sort + // of timeout or EOF error since they are expecting to receive an + // INFO protocol first. + TLSHandshakeFirst bool `json:"-"` + // If TLSHandshakeFirst is true and this value is strictly positive, + // the server will wait for that amount of time for the TLS handshake + // to start before falling back to previous behavior of sending the + // INFO protocol first. It allows for a mix of newer clients that can + // require a TLS handshake first, and older clients that can't. + TLSHandshakeFirstFallback time.Duration `json:"-"` + AllowNonTLS bool `json:"-"` + WriteDeadline time.Duration `json:"-"` + WriteTimeout WriteTimeoutPolicy `json:"-"` + MaxClosedClients int `json:"-"` + LameDuckDuration time.Duration `json:"-"` + LameDuckGracePeriod time.Duration `json:"-"` // MaxTracedMsgLen is the maximum printable length for traced messages. MaxTracedMsgLen int `json:"-"` @@ -229,7 +407,11 @@ type Options struct { TrustedOperators []*jwt.OperatorClaims `json:"-"` AccountResolver AccountResolver `json:"-"` AccountResolverTLSConfig *tls.Config `json:"-"` - resolverPreloads map[string]string + + // AlwaysEnableNonce will always present a nonce to new connections + // typically used by custom Authentication implementations who embeds + // the server and so not presented as a configuration option + AlwaysEnableNonce bool CustomClientAuthentication Authentication `json:"-"` CustomRouterAuthentication Authentication `json:"-"` @@ -237,6 +419,9 @@ type Options struct { // CheckConfig configuration file syntax test was successful and exit. CheckConfig bool `json:"-"` + // DisableJetStreamBanner will not print the ascii art on startup for JetStream enabled servers + DisableJetStreamBanner bool `json:"-"` + // ConnectErrorReports specifies the number of failed attempts // at which point server should report the failure of an initial // connection to a route, gateway or leaf node. @@ -247,14 +432,41 @@ type Options struct { // that this applies to reconnect events. ReconnectErrorReports int + // Tags describing the server. They will be included in varz + // and used as a filter criteria for some system requests. + Tags jwt.TagList `json:"-"` + + // OCSPConfig enables OCSP Stapling in the server. + OCSPConfig *OCSPConfig + tlsConfigOpts *TLSConfigOpts + // private fields, used to know if bool options are explicitly // defined in config and/or command line params. inConfig map[string]bool inCmdLine map[string]bool + // private fields for operator mode + operatorJWT []string + resolverPreloads map[string]string + resolverPinnedAccounts map[string]struct{} + // private fields, used for testing gatewaysSolicitDelay time.Duration - routeProto int + overrideProto int + + // JetStream + maxMemSet bool + maxStoreSet bool + syncSet bool + + // OCSP Cache config enables next-gen cache for OCSP features + OCSPCacheConfig *OCSPResponseCacheConfig + + // Used to mark that we had a top level authorization block. + authBlockDefined bool + + // configDigest represents the state of configuration. + configDigest string } // WebsocketOpts are options for websocket @@ -275,6 +487,26 @@ type WebsocketOpts struct { // "jwt" specified in the CONNECT options is missing or empty. JWTCookie string + // Name of the cookie, which if present in WebSocket upgrade headers, + // will be treated as Username during CONNECT phase as long as + // "user" specified in the CONNECT options is missing or empty. + UsernameCookie string + + // Name of the cookie, which if present in WebSocket upgrade headers, + // will be treated as Password during CONNECT phase as long as + // "pass" specified in the CONNECT options is missing or empty. + PasswordCookie string + + // Name of the cookie, which if present in WebSocket upgrade headers, + // will be treated as Token during CONNECT phase as long as + // "auth_token" specified in the CONNECT options is missing or empty. + // Note that when this is useful for passing a JWT to an cuth callout + // when the server uses delegated authentication ("operator mode") or + // when using delegated authentication, but the auth callout validates some + // other JWT or string. Note that this does map to an actual server-wide + // "auth_token", note that using it for that purpose is greatly discouraged. + TokenCookie string + // Authentication section. If anything is configured in this section, // it will override the authorization configuration of regular clients. Username string @@ -298,6 +530,9 @@ type WebsocketOpts struct { // If true, map certificate values for authentication purposes. TLSMap bool + // When present, accepted client certificates (verify/verify_and_map) must be in this list + TLSPinnedCerts PinnedCertSet + // If true, the Origin header must match the request's host. SameOrigin bool @@ -315,6 +550,18 @@ type WebsocketOpts struct { // and write the response back to the client. This include the // time needed for the TLS Handshake. HandshakeTimeout time.Duration + + // How often to send pings to WebSocket clients. When set to a non-zero + // duration, this overrides the default PingInterval for WebSocket connections. + // If not set or zero, the server's default PingInterval will be used. + PingInterval time.Duration + + // Headers to be added to the upgrade response. + // Useful for adding custom headers like Strict-Transport-Security. + Headers map[string]string + + // Snapshot of configured TLS options. + tlsConfigOpts *TLSConfigOpts } // MQTTOpts are options for MQTT @@ -334,6 +581,36 @@ type MQTTOpts struct { Password string Token string + // JetStream domain mqtt is supposed to pick up + JsDomain string + + // Number of replicas for MQTT streams. + // Negative or 0 value means that the server(s) will pick a replica + // number based on the known size of the cluster (but capped at 3). + // Note that if an account was already connected, the stream's replica + // count is not modified. Use the NATS CLI to update the count if desired. + StreamReplicas int + + // Number of replicas for MQTT consumers. + // Negative or 0 value means that there is no override and the consumer + // will have the same replica factor that the stream it belongs to. + // If a value is specified, it will require to be lower than the stream + // replicas count (lower than StreamReplicas if specified, but also lower + // than the automatic value determined by cluster size). + // Note that existing consumers are not modified. + // + // UPDATE: This is no longer used while messages stream has interest policy retention + // which requires consumer replica count to match the parent stream. + ConsumerReplicas int + + // Indicate if the consumers should be created with memory storage. + // Note that existing consumers are not modified. + ConsumerMemoryStorage bool + + // If specified will have the system auto-cleanup the consumers after being + // inactive for the specified amount of time. + ConsumerInactiveThreshold time.Duration + // Timeout for the authentication process. AuthTimeout float64 @@ -343,21 +620,45 @@ type MQTTOpts struct { TLSMap bool // Timeout for the TLS handshake TLSTimeout float64 - - // AckWait is the amount of time after which a QoS 1 message sent to - // a client is redelivered as a DUPLICATE if the server has not - // received the PUBACK on the original Packet Identifier. - // The value has to be positive. - // Zero will cause the server to use the default value (1 hour). - // Note that changes to this option is applied only to new MQTT subscriptions. + // Set of allowable certificates + TLSPinnedCerts PinnedCertSet + + // AckWait is the amount of time after which a QoS 1 or 2 message sent to a + // client is redelivered as a DUPLICATE if the server has not received the + // PUBACK on the original Packet Identifier. The same value applies to + // PubRel redelivery. The value has to be positive. Zero will cause the + // server to use the default value (30 seconds). Note that changes to this + // option is applied only to new MQTT subscriptions (or sessions for + // PubRels). AckWait time.Duration - // MaxAckPending is the amount of QoS 1 messages the server can send to - // a session without receiving any PUBACK for those messages. - // The valid range is [0..65535]. - // Zero will cause the server to use the default value (1024). - // Note that changes to this option is applied only to new MQTT sessions. + // JSAPITimeout defines timeout for JetStream api calls (default is 5 seconds) + JSAPITimeout time.Duration + + // MaxAckPending is the amount of QoS 1 and 2 messages (combined) the server + // can send to a subscription without receiving any PUBACK for those + // messages. The valid range is [0..65535]. + // + // The total of subscriptions' MaxAckPending on a given session cannot + // exceed 65535. Attempting to create a subscription that would bring the + // total above the limit would result in the server returning 0x80 in the + // SUBACK for this subscription. + // + // Due to how the NATS Server handles the MQTT "#" wildcard, each + // subscription ending with "#" will use 2 times the MaxAckPending value. + // Note that changes to this option is applied only to new subscriptions. MaxAckPending uint16 + + // Snapshot of configured TLS options. + tlsConfigOpts *TLSConfigOpts + + // rejectQoS2Pub tells the MQTT client to not accept QoS2 PUBLISH, instead + // error and terminate the connection. + rejectQoS2Pub bool + + // downgradeQOS2Sub tells the MQTT client to downgrade QoS2 SUBSCRIBE + // requests to QoS1. + downgradeQoS2Sub bool } type netResolver interface { @@ -426,27 +727,57 @@ type authorization struct { user string pass string token string + nkey string acc string // Multiple Nkeys/Users nkeys []*NkeyUser users []*User timeout float64 defaultPermissions *Permissions + // Auth Callouts + callout *AuthCallout } // TLSConfigOpts holds the parsed tls config information, // used with flag parsing type TLSConfigOpts struct { - CertFile string - KeyFile string - CaFile string - Verify bool - Insecure bool - Map bool - TLSCheckKnownURLs bool - Timeout float64 - Ciphers []uint16 - CurvePreferences []tls.CurveID + CertFile string + KeyFile string + CaFile string + Verify bool + Insecure bool + Map bool + TLSCheckKnownURLs bool + HandshakeFirst bool // Indicate that the TLS handshake should occur first, before sending the INFO protocol. + FallbackDelay time.Duration // Where supported, indicates how long to wait for the handshake before falling back to sending the INFO protocol first. + Timeout float64 + RateLimit int64 + Ciphers []uint16 + CurvePreferences []tls.CurveID + PinnedCerts PinnedCertSet + CertStore certstore.StoreType + CertMatchBy certstore.MatchByType + CertMatch string + CertMatchSkipInvalid bool + CaCertsMatch []string + OCSPPeerConfig *certidp.OCSPPeerConfig + Certificates []*TLSCertPairOpt + MinVersion uint16 +} + +// TLSCertPairOpt are the paths to a certificate and private key. +type TLSCertPairOpt struct { + CertFile string + KeyFile string +} + +// OCSPConfig represents the options of OCSP stapling options. +type OCSPConfig struct { + // Mode defines the policy for OCSP stapling. + Mode OCSPMode + + // OverrideURLs is the http URL endpoint used to get OCSP staples. + OverrideURLs []string } var tlsUsage = ` @@ -492,7 +823,7 @@ func ProcessConfigFile(configFile string) (*Options, error) { // token is an item parsed from the configuration. type token interface { - Value() interface{} + Value() any Line() int IsUsedVariable() bool SourceFile() string @@ -503,7 +834,7 @@ type token interface { // to be able to report the line number in case of an incorrect // configuration. // also stores the token in lastToken for use in convertPanicToError -func unwrapValue(v interface{}, lastToken *token) (token, interface{}) { +func unwrapValue(v any, lastToken *token) (token, any) { switch tk := v.(type) { case token: if lastToken != nil { @@ -545,10 +876,10 @@ func convertPanicToError(lastToken *token, e *error) { // configureSystemAccount configures a system account // if present in the configuration. -func configureSystemAccount(o *Options, m map[string]interface{}) (retErr error) { +func configureSystemAccount(o *Options, m map[string]any) (retErr error) { var lt token defer convertPanicToError(<, &retErr) - configure := func(v interface{}) error { + configure := func(v any) error { tk, v := unwrapValue(v, <) sa, ok := v.(string) if !ok { @@ -583,16 +914,41 @@ func configureSystemAccount(o *Options, m map[string]interface{}) (retErr error) // or was present but set to false. func (o *Options) ProcessConfigFile(configFile string) error { o.ConfigFile = configFile - if configFile == "" { + if configFile == _EMPTY_ { return nil } - m, err := conf.ParseFileWithChecks(configFile) + m, digest, err := conf.ParseFileWithChecksDigest(configFile) + if err != nil { + return err + } + o.configDigest = digest + + return o.processConfigFile(configFile, m) +} + +// ProcessConfigString is the same as ProcessConfigFile, but expects the +// contents of the config file to be passed in rather than the file name. +func (o *Options) ProcessConfigString(data string) error { + m, err := conf.ParseWithChecks(data) if err != nil { return err } + + return o.processConfigFile(_EMPTY_, m) +} + +// ConfigDigest returns the digest representing the configuration. +func (o *Options) ConfigDigest() string { + return o.configDigest +} + +func (o *Options) processConfigFile(configFile string, m map[string]any) error { // Collect all errors and warnings and report them all together. errors := make([]error, 0) warnings := make([]error, 0) + if len(m) == 0 { + warnings = append(warnings, fmt.Errorf("%s: config has no values or is empty", configFile)) + } // First check whether a system account has been defined, // as that is a condition for other features to be enabled. @@ -604,6 +960,21 @@ func (o *Options) ProcessConfigFile(configFile string) error { o.processConfigFileLine(k, v, &errors, &warnings) } + // Post-process: check auth callout allowed accounts against configured accounts. + if o.AuthCallout != nil { + accounts := make(map[string]struct{}) + for _, acc := range o.Accounts { + accounts[acc.Name] = struct{}{} + } + + for _, acc := range o.AuthCallout.AllowedAccounts { + if _, ok := accounts[acc]; !ok { + err := &configErr{nil, fmt.Sprintf("auth_callout allowed account %q not found in configured accounts", acc)} + errors = append(errors, err) + } + } + } + if len(errors) > 0 || len(warnings) > 0 { return &processConfigErr{ errors: errors, @@ -614,7 +985,7 @@ func (o *Options) ProcessConfigFile(configFile string) error { return nil } -func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error, warnings *[]error) { +func (o *Options) processConfigFileLine(k string, v any, errors *[]error, warnings *[]error) { var lt token defer convertPanicToErrorList(<, errors) @@ -633,27 +1004,41 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error case "port": o.Port = int(v.(int64)) case "server_name": - o.ServerName = v.(string) + sn := v.(string) + if strings.Contains(sn, " ") { + err := &configErr{tk, ErrServerNameHasSpaces.Error()} + *errors = append(*errors, err) + return + } + o.ServerName = sn case "host", "net": o.Host = v.(string) case "debug": o.Debug = v.(bool) - trackExplicitVal(o, &o.inConfig, "Debug", o.Debug) + trackExplicitVal(&o.inConfig, "Debug", o.Debug) case "trace": o.Trace = v.(bool) - trackExplicitVal(o, &o.inConfig, "Trace", o.Trace) + trackExplicitVal(&o.inConfig, "Trace", o.Trace) case "trace_verbose": o.TraceVerbose = v.(bool) o.Trace = v.(bool) - trackExplicitVal(o, &o.inConfig, "TraceVerbose", o.TraceVerbose) - trackExplicitVal(o, &o.inConfig, "Trace", o.Trace) + trackExplicitVal(&o.inConfig, "TraceVerbose", o.TraceVerbose) + trackExplicitVal(&o.inConfig, "Trace", o.Trace) + case "trace_headers": + o.TraceHeaders = v.(bool) + o.Trace = v.(bool) + trackExplicitVal(&o.inConfig, "TraceHeaders", o.TraceHeaders) + trackExplicitVal(&o.inConfig, "Trace", o.Trace) case "logtime": o.Logtime = v.(bool) - trackExplicitVal(o, &o.inConfig, "Logtime", o.Logtime) + trackExplicitVal(&o.inConfig, "Logtime", o.Logtime) + case "logtime_utc": + o.LogtimeUTC = v.(bool) + trackExplicitVal(&o.inConfig, "LogtimeUTC", o.LogtimeUTC) case "mappings", "maps": gacc := NewAccount(globalAccountName) o.Accounts = append(o.Accounts, gacc) - err := parseAccountMappings(tk, gacc, errors, warnings) + err := parseAccountMappings(tk, gacc, errors) if err != nil { *errors = append(*errors, err) return @@ -666,40 +1051,69 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error *errors = append(*errors, err) return } + case "default_sentinel": + o.DefaultSentinel = v.(string) case "authorization": - auth, err := parseAuthorization(tk, o, errors, warnings) + auth, err := parseAuthorization(tk, errors, warnings) if err != nil { *errors = append(*errors, err) return } - + o.authBlockDefined = true o.Username = auth.user o.Password = auth.pass o.Authorization = auth.token - if (auth.user != "" || auth.pass != "") && auth.token != "" { + o.AuthTimeout = auth.timeout + o.AuthCallout = auth.callout + + if (auth.user != _EMPTY_ || auth.pass != _EMPTY_) && auth.token != _EMPTY_ { err := &configErr{tk, "Cannot have a user/pass and token"} *errors = append(*errors, err) return } - o.AuthTimeout = auth.timeout - // Check for multiple users defined - if auth.users != nil { - if auth.user != "" { + // In case parseAccounts() was done first, we need to check for duplicates. + unames := setupUsersAndNKeysDuplicateCheckMap(o) + // Check for multiple users defined. + // Note: auth.users will be != nil as long as `users: []` is present + // in the authorization block, even if empty, and will also account for + // nkey users. We also check for users/nkeys that may have been already + // added in parseAccounts() (which means they will be in unames) + if auth.users != nil || len(unames) > 0 { + if auth.user != _EMPTY_ { err := &configErr{tk, "Can not have a single user/pass and a users array"} *errors = append(*errors, err) return } - if auth.token != "" { + if auth.token != _EMPTY_ { err := &configErr{tk, "Can not have a token and a users array"} *errors = append(*errors, err) return } - // Users may have been added from Accounts parsing, so do an append here - o.Users = append(o.Users, auth.users...) + // Now check that if we have users, there is no duplicate, including + // users that may have been configured in parseAccounts(). + if len(auth.users) > 0 { + for _, u := range auth.users { + if _, ok := unames[u.Username]; ok { + err := &configErr{tk, fmt.Sprintf("Duplicate user %q detected", u.Username)} + *errors = append(*errors, err) + return + } + unames[u.Username] = struct{}{} + } + // Users may have been added from Accounts parsing, so do an append here + o.Users = append(o.Users, auth.users...) + } } - // Check for nkeys - if auth.nkeys != nil { + if len(auth.nkeys) > 0 { + for _, u := range auth.nkeys { + if _, ok := unames[u.Nkey]; ok { + err := &configErr{tk, fmt.Sprintf("Duplicate nkey %q detected", u.Nkey)} + *errors = append(*errors, err) + return + } + unames[u.Nkey] = struct{}{} + } // NKeys may have been added from Accounts parsing, so do an append here o.Nkeys = append(o.Nkeys, auth.nkeys...) } @@ -744,6 +1158,13 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error *errors = append(*errors, err) return } + case "store_dir", "storedir": + // Check if JetStream configuration is also setting the storage directory. + if o.StoreDir != _EMPTY_ { + *errors = append(*errors, &configErr{tk, "Duplicate 'store_dir' configuration"}) + return + } + o.StoreDir = v.(string) case "jetstream": err := parseJetStream(tk, o, errors, warnings) if err != nil { @@ -754,9 +1175,11 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error o.LogFile = v.(string) case "logfile_size_limit", "log_size_limit": o.LogSizeLimit = v.(int64) + case "logfile_max_num", "log_max_num": + o.LogMaxFiles = v.(int64) case "syslog": o.Syslog = v.(bool) - trackExplicitVal(o, &o.inConfig, "Syslog", o.Syslog) + trackExplicitVal(&o.inConfig, "Syslog", o.Syslog) case "remote_syslog": o.RemoteSyslog = v.(string) case "pidfile", "pid_file": @@ -765,6 +1188,8 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error o.PortsFileDir = v.(string) case "prof_port": o.ProfPort = int(v.(int64)) + case "prof_block_rate": + o.ProfBlockRate = int(v.(int64)) case "max_control_line": if v.(int64) > 1<<31-1 { err := &configErr{tk, fmt.Sprintf("%s value is too big", k)} @@ -787,6 +1212,18 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error o.MaxTracedMsgLen = int(v.(int64)) case "max_subscriptions", "max_subs": o.MaxSubs = int(v.(int64)) + case "max_sub_tokens", "max_subscription_tokens": + if n := v.(int64); n > math.MaxUint8 { + err := &configErr{tk, fmt.Sprintf("%s value is too big", k)} + *errors = append(*errors, err) + return + } else if n <= 0 { + err := &configErr{tk, fmt.Sprintf("%s value can not be negative", k)} + *errors = append(*errors, err) + return + } else { + o.MaxSubTokens = uint8(n) + } case "ping_interval": o.PingInterval = parseDuration("ping_interval", tk, v, errors, warnings) case "ping_max": @@ -804,11 +1241,67 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error } o.TLSTimeout = tc.Timeout o.TLSMap = tc.Map - + o.TLSPinnedCerts = tc.PinnedCerts + o.TLSRateLimit = tc.RateLimit + o.TLSHandshakeFirst = tc.HandshakeFirst + o.TLSHandshakeFirstFallback = tc.FallbackDelay + + // Need to keep track of path of the original TLS config + // and certs path for OCSP Stapling monitoring. + o.tlsConfigOpts = tc + case "ocsp": + switch vv := v.(type) { + case bool: + if vv { + // Default is Auto which honors Must Staple status request + // but does not shutdown the server in case it is revoked, + // letting the client choose whether to trust or not the server. + o.OCSPConfig = &OCSPConfig{Mode: OCSPModeAuto} + } else { + o.OCSPConfig = &OCSPConfig{Mode: OCSPModeNever} + } + case map[string]any: + ocsp := &OCSPConfig{Mode: OCSPModeAuto} + + for kk, kv := range vv { + _, v = unwrapValue(kv, &tk) + switch kk { + case "mode": + mode := v.(string) + switch { + case strings.EqualFold(mode, "always"): + ocsp.Mode = OCSPModeAlways + case strings.EqualFold(mode, "must"): + ocsp.Mode = OCSPModeMust + case strings.EqualFold(mode, "never"): + ocsp.Mode = OCSPModeNever + case strings.EqualFold(mode, "auto"): + ocsp.Mode = OCSPModeAuto + default: + *errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing ocsp config: unsupported ocsp mode %T", mode)}) + } + case "urls": + urls := v.([]string) + ocsp.OverrideURLs = urls + case "url": + url := v.(string) + ocsp.OverrideURLs = []string{url} + default: + *errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing ocsp config: unsupported field %T", kk)}) + return + } + } + o.OCSPConfig = ocsp + default: + *errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing ocsp config: unsupported type %T", v)}) + return + } case "allow_non_tls": o.AllowNonTLS = v.(bool) case "write_deadline": o.WriteDeadline = parseDuration("write_deadline", tk, v, errors, warnings) + case "write_timeout": + o.WriteTimeout = parseWriteDeadlinePolicy(tk, v.(string), errors) case "lame_duck_duration": dur, err := time.ParseDuration(v.(string)) if err != nil { @@ -842,6 +1335,22 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error opFiles = append(opFiles, v) case []string: opFiles = append(opFiles, v...) + case []any: + for _, t := range v { + if token, ok := t.(token); ok { + if v, ok := token.Value().(string); ok { + opFiles = append(opFiles, v) + } else { + err := &configErr{tk, fmt.Sprintf("error parsing operators: unsupported type %T where string is expected", token)} + *errors = append(*errors, err) + break + } + } else { + err := &configErr{tk, fmt.Sprintf("error parsing operators: unsupported type %T", t)} + *errors = append(*errors, err) + break + } + } default: err := &configErr{tk, fmt.Sprintf("error parsing operators: unsupported type %T", v)} *errors = append(*errors, err) @@ -849,12 +1358,13 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error // Assume for now these are file names, but they can also be the JWT itself inline. o.TrustedOperators = make([]*jwt.OperatorClaims, 0, len(opFiles)) for _, fname := range opFiles { - opc, err := ReadOperatorJWT(fname) + theJWT, opc, err := readOperatorJWT(fname) if err != nil { err := &configErr{tk, fmt.Sprintf("error parsing operator JWT: %v", err)} *errors = append(*errors, err) continue } + o.operatorJWT = append(o.operatorJWT, theJWT) o.TrustedOperators = append(o.TrustedOperators, opc) } if len(o.TrustedOperators) == 1 { @@ -866,7 +1376,7 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error } } // In case "system_account" is defined as well, it takes precedence - if o.SystemAccount == "" { + if o.SystemAccount == _EMPTY_ { o.SystemAccount = o.TrustedOperators[0].SystemAccount } } @@ -895,13 +1405,16 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error o.AccountResolver = ur } } - case map[string]interface{}: + case map[string]any: del := false - dir := "" - dirType := "" + hdel := false + hdel_set := false + dir := _EMPTY_ + dirType := _EMPTY_ limit := int64(0) ttl := time.Duration(0) sync := time.Duration(0) + opts := []DirResOption{} var err error if v, ok := v["dir"]; ok { _, v := unwrapValue(v, <) @@ -915,6 +1428,11 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error _, v := unwrapValue(v, <) del = v.(bool) } + if v, ok := v["hard_delete"]; ok { + _, v := unwrapValue(v, <) + hdel_set = true + hdel = v.(bool) + } if v, ok := v["limit"]; ok { _, v := unwrapValue(v, <) limit = v.(int64) @@ -927,33 +1445,62 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error _, v := unwrapValue(v, <) sync, err = time.ParseDuration(v.(string)) } + if v, ok := v["timeout"]; err == nil && ok { + _, v := unwrapValue(v, <) + var to time.Duration + if to, err = time.ParseDuration(v.(string)); err == nil { + opts = append(opts, FetchTimeout(to)) + } + } if err != nil { *errors = append(*errors, &configErr{tk, err.Error()}) return } - if dir == "" { - *errors = append(*errors, &configErr{tk, "dir has no value and needs to point to a directory"}) - return - } - if info, _ := os.Stat(dir); info != nil && (!info.IsDir() || info.Mode().Perm()&(1<<(uint(7))) == 0) { - *errors = append(*errors, &configErr{tk, "dir needs to point to an accessible directory"}) - return + + checkDir := func() { + if dir == _EMPTY_ { + *errors = append(*errors, &configErr{tk, "dir has no value and needs to point to a directory"}) + return + } + if info, _ := os.Stat(dir); info != nil && (!info.IsDir() || info.Mode().Perm()&(1<<(uint(7))) == 0) { + *errors = append(*errors, &configErr{tk, "dir needs to point to an accessible directory"}) + return + } } + var res AccountResolver switch strings.ToUpper(dirType) { case "CACHE": + checkDir() if sync != 0 { *errors = append(*errors, &configErr{tk, "CACHE does not accept sync"}) } if del { *errors = append(*errors, &configErr{tk, "CACHE does not accept allow_delete"}) } - res, err = NewCacheDirAccResolver(dir, limit, ttl) + if hdel_set { + *errors = append(*errors, &configErr{tk, "CACHE does not accept hard_delete"}) + } + res, err = NewCacheDirAccResolver(dir, limit, ttl, opts...) case "FULL": + checkDir() if ttl != 0 { *errors = append(*errors, &configErr{tk, "FULL does not accept ttl"}) } - res, err = NewDirAccResolver(dir, limit, sync, del) + if hdel_set && !del { + *errors = append(*errors, &configErr{tk, "hard_delete has no effect without delete"}) + } + delete := NoDelete + if del { + if hdel { + delete = HardDelete + } else { + delete = RenameDeleted + } + } + res, err = NewDirAccResolver(dir, limit, sync, delete, opts...) + case "MEM", "MEMORY": + res = &MemAccResolver{} } if err != nil { *errors = append(*errors, &configErr{tk, err.Error()}) @@ -976,13 +1523,18 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error *errors = append(*errors, err) return } - if o.AccountResolverTLSConfig, err = GenTLSConfig(tc); err != nil { + tlsConfig, err := GenTLSConfig(tc) + if err != nil { err := &configErr{tk, err.Error()} *errors = append(*errors, err) return } + o.AccountResolverTLSConfig = tlsConfig + // GenTLSConfig loads the CA file into ClientCAs, but since this will + // be used as a client connection, we need to set RootCAs. + o.AccountResolverTLSConfig.RootCAs = tlsConfig.ClientCAs case "resolver_preload": - mp, ok := v.(map[string]interface{}) + mp, ok := v.(map[string]any) if !ok { err := &configErr{tk, "preload should be a map of account_public_key:account_jwt"} *errors = append(*errors, err) @@ -992,8 +1544,7 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error for key, val := range mp { tk, val = unwrapValue(val, <) if jwtstr, ok := val.(string); !ok { - err := &configErr{tk, "preload map value should be a string JWT"} - *errors = append(*errors, err) + *errors = append(*errors, &configErr{tk, "preload map value should be a string JWT"}) continue } else { // Make sure this is a valid account JWT, that is a config error. @@ -1006,6 +1557,33 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error o.resolverPreloads[key] = jwtstr } } + case "resolver_pinned_accounts": + switch v := v.(type) { + case string: + o.resolverPinnedAccounts = map[string]struct{}{v: {}} + case []string: + o.resolverPinnedAccounts = make(map[string]struct{}) + for _, mv := range v { + o.resolverPinnedAccounts[mv] = struct{}{} + } + case []any: + o.resolverPinnedAccounts = make(map[string]struct{}) + for _, mv := range v { + tk, mv = unwrapValue(mv, <) + if key, ok := mv.(string); ok { + o.resolverPinnedAccounts[key] = struct{}{} + } else { + err := &configErr{tk, + fmt.Sprintf("error parsing resolver_pinned_accounts: unsupported type in array %T", mv)} + *errors = append(*errors, err) + continue + } + } + default: + err := &configErr{tk, fmt.Sprintf("error parsing resolver_pinned_accounts: unsupported type %T", v)} + *errors = append(*errors, err) + return + } case "no_auth_user": o.NoAuthUser = v.(string) case "system_account", "system": @@ -1022,7 +1600,7 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error o.TrustedKeys = []string{v} case []string: o.TrustedKeys = v - case []interface{}: + case []any: keys := make([]string, 0, len(v)) for _, mv := range v { tk, mv = unwrapValue(mv, <) @@ -1060,6 +1638,78 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error *errors = append(*errors, err) return } + case "server_tags": + var err error + switch v := v.(type) { + case string: + o.Tags.Add(v) + case []string: + o.Tags.Add(v...) + case []any: + for _, t := range v { + if token, ok := t.(token); ok { + if ts, ok := token.Value().(string); ok { + o.Tags.Add(ts) + continue + } else { + err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T where string is expected", token)} + } + } else { + err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T", t)} + } + break + } + default: + err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T", v)} + } + if err != nil { + *errors = append(*errors, err) + return + } + case "default_js_domain": + vv, ok := v.(map[string]any) + if !ok { + *errors = append(*errors, &configErr{tk, fmt.Sprintf("error default_js_domain config: unsupported type %T", v)}) + return + } + m := make(map[string]string) + for kk, kv := range vv { + _, v = unwrapValue(kv, &tk) + m[kk] = v.(string) + } + o.JsAccDefaultDomain = m + case "ocsp_cache": + var err error + switch vv := v.(type) { + case bool: + pc := NewOCSPResponseCacheConfig() + if vv { + // Set enabled + pc.Type = LOCAL + o.OCSPCacheConfig = pc + } else { + // Set disabled (none cache) + pc.Type = NONE + o.OCSPCacheConfig = pc + } + case map[string]any: + pc, err := parseOCSPResponseCache(v) + if err != nil { + *errors = append(*errors, err) + return + } + o.OCSPCacheConfig = pc + default: + err = &configErr{tk, fmt.Sprintf("error parsing tags: unsupported type %T", v)} + } + if err != nil { + *errors = append(*errors, err) + return + } + case "no_fast_producer_stall": + o.NoFastProducerStall = v.(bool) + case "max_closed_clients": + o.MaxClosedClients = int(v.(int64)) default: if au := atomic.LoadInt32(&allowUnknownTopLevelField); au == 0 && !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1073,7 +1723,18 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error } } -func parseDuration(field string, tk token, v interface{}, errors *[]error, warnings *[]error) time.Duration { +func setupUsersAndNKeysDuplicateCheckMap(o *Options) map[string]struct{} { + unames := make(map[string]struct{}, len(o.Users)+len(o.Nkeys)) + for _, u := range o.Users { + unames[u.Username] = struct{}{} + } + for _, u := range o.Nkeys { + unames[u.Nkey] = struct{}{} + } + return unames +} + +func parseDuration(field string, tk token, v any, errors *[]error, warnings *[]error) time.Duration { if wd, ok := v.(string); ok { if dur, err := time.ParseDuration(wd); err != nil { err := &configErr{tk, fmt.Sprintf("error parsing %s: %v", field, err)} @@ -1097,7 +1758,22 @@ func parseDuration(field string, tk token, v interface{}, errors *[]error, warni } } -func trackExplicitVal(opts *Options, pm *map[string]bool, name string, val bool) { +func parseWriteDeadlinePolicy(tk token, v string, errors *[]error) WriteTimeoutPolicy { + switch v { + case "default": + return WriteTimeoutPolicyDefault + case "close": + return WriteTimeoutPolicyClose + case "retry": + return WriteTimeoutPolicyRetry + default: + err := &configErr{tk, "write_timeout must be 'default', 'close' or 'retry'"} + *errors = append(*errors, err) + return WriteTimeoutPolicyDefault + } +} + +func trackExplicitVal(pm *map[string]bool, name string, val bool) { m := *pm if m == nil { m = make(map[string]bool) @@ -1113,7 +1789,7 @@ type hostPort struct { } // parseListen will parse listen option which is replacing host/net and port -func parseListen(v interface{}) (*hostPort, error) { +func parseListen(v any) (*hostPort, error) { hp := &hostPort{} switch vv := v.(type) { // Only a port @@ -1136,12 +1812,12 @@ func parseListen(v interface{}) (*hostPort, error) { } // parseCluster will parse the cluster config. -func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]error) error { +func parseCluster(v any, opts *Options, errors *[]error, warnings *[]error) error { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - cm, ok := v.(map[string]interface{}) + cm, ok := v.(map[string]any) if !ok { return &configErr{tk, fmt.Sprintf("Expected map to define cluster, got %T", v)} } @@ -1151,7 +1827,13 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { case "name": - opts.Cluster.Name = mv.(string) + cn := mv.(string) + if strings.Contains(cn, " ") { + err := &configErr{tk, ErrClusterNameHasSpaces.Error()} + *errors = append(*errors, err) + continue + } + opts.Cluster.Name = cn case "listen": hp, err := parseListen(mv) if err != nil { @@ -1166,7 +1848,7 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err case "host", "net": opts.Cluster.Host = mv.(string) case "authorization": - auth, err := parseAuthorization(tk, opts, errors, warnings) + auth, err := parseAuthorization(tk, errors, warnings) if err != nil { *errors = append(*errors, err) continue @@ -1176,6 +1858,17 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err *errors = append(*errors, err) continue } + if auth.token != _EMPTY_ { + err := &configErr{tk, "Cluster authorization does not support tokens"} + *errors = append(*errors, err) + continue + } + if auth.callout != nil { + err := &configErr{tk, "Cluster authorization does not support callouts"} + *errors = append(*errors, err) + continue + } + opts.Cluster.Username = auth.user opts.Cluster.Password = auth.pass opts.Cluster.AuthTimeout = auth.timeout @@ -1196,8 +1889,8 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err } } case "routes": - ra := mv.([]interface{}) - routes, errs := parseURLs(ra, "route") + ra := mv.([]any) + routes, errs := parseURLs(ra, "route", warnings) if errs != nil { *errors = append(*errors, errs...) continue @@ -1212,16 +1905,18 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err opts.Cluster.TLSConfig = config opts.Cluster.TLSTimeout = tlsopts.Timeout opts.Cluster.TLSMap = tlsopts.Map - opts.Cluster.TLSCheckKnwonURLs = tlsopts.TLSCheckKnownURLs + opts.Cluster.TLSPinnedCerts = tlsopts.PinnedCerts + opts.Cluster.TLSCheckKnownURLs = tlsopts.TLSCheckKnownURLs + opts.Cluster.tlsConfigOpts = tlsopts case "cluster_advertise", "advertise": opts.Cluster.Advertise = mv.(string) case "no_advertise": opts.Cluster.NoAdvertise = mv.(bool) - trackExplicitVal(opts, &opts.inConfig, "Cluster.NoAdvertise", opts.Cluster.NoAdvertise) + trackExplicitVal(&opts.inConfig, "Cluster.NoAdvertise", opts.Cluster.NoAdvertise) case "connect_retries": opts.Cluster.ConnectRetries = int(mv.(int64)) case "permissions": - perms, err := parseUserPermissions(mv, errors, warnings) + perms, err := parseUserPermissions(mv, errors) if err != nil { *errors = append(*errors, err) continue @@ -1234,6 +1929,26 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err } // This will possibly override permissions that were define in auth block setClusterPermissions(&opts.Cluster, perms) + case "pool_size": + opts.Cluster.PoolSize = int(mv.(int64)) + case "accounts": + opts.Cluster.PinnedAccounts, _ = parseStringArray("accounts", tk, <, mv, errors) + case "compression": + if err := parseCompression(&opts.Cluster.Compression, CompressionS2Fast, tk, mk, mv); err != nil { + *errors = append(*errors, err) + continue + } + case "ping_interval": + opts.Cluster.PingInterval = parseDuration("ping_interval", tk, mv, errors, warnings) + if opts.Cluster.PingInterval > routeMaxPingInterval { + *warnings = append(*warnings, &configErr{tk, fmt.Sprintf("Cluster 'ping_interval' will reset to %v which is the max for routes", routeMaxPingInterval)}) + } + case "ping_max": + opts.Cluster.MaxPingsOut = int(mv.(int64)) + case "write_deadline": + opts.Cluster.WriteDeadline = parseDuration("write_deadline", tk, mv, errors, warnings) + case "write_timeout": + opts.Cluster.WriteTimeout = parseWriteDeadlinePolicy(tk, mv.(string), errors) default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1250,14 +1965,72 @@ func parseCluster(v interface{}, opts *Options, errors *[]error, warnings *[]err return nil } -func parseURLs(a []interface{}, typ string) (urls []*url.URL, errors []error) { +// The parameter `chosenModeForOn` indicates which compression mode to use +// when the user selects "on" (or enabled, true, etc..). This is because +// we may have different defaults depending on where the compression is used. +func parseCompression(c *CompressionOpts, chosenModeForOn string, tk token, mk string, mv any) (retErr error) { + var lt token + defer convertPanicToError(<, &retErr) + + switch mv := mv.(type) { + case string: + // Do not validate here, it will be done in NewServer. + c.Mode = mv + case bool: + if mv { + c.Mode = chosenModeForOn + } else { + c.Mode = CompressionOff + } + case map[string]any: + for mk, mv := range mv { + tk, mv = unwrapValue(mv, <) + switch strings.ToLower(mk) { + case "mode": + c.Mode = mv.(string) + case "rtt_thresholds", "thresholds", "rtts", "rtt": + for _, iv := range mv.([]any) { + _, mv := unwrapValue(iv, <) + dur, err := time.ParseDuration(mv.(string)) + if err != nil { + return &configErr{tk, err.Error()} + } + c.RTTThresholds = append(c.RTTThresholds, dur) + } + default: + if !tk.IsUsedVariable() { + return &configErr{tk, fmt.Sprintf("unknown field %q", mk)} + } + } + } + default: + return &configErr{tk, fmt.Sprintf("field %q should be a boolean or a structure, got %T", mk, mv)} + } + return nil +} + +func parseURLs(a []any, typ string, warnings *[]error) (urls []*url.URL, errors []error) { urls = make([]*url.URL, 0, len(a)) var lt token defer convertPanicToErrorList(<, &errors) + dd := make(map[string]bool) + for _, u := range a { tk, u := unwrapValue(u, <) sURL := u.(string) + if dd[sURL] { + err := &configWarningErr{ + field: sURL, + configErr: configErr{ + token: tk, + reason: fmt.Sprintf("Duplicate %s entry detected", typ), + }, + } + *warnings = append(*warnings, err) + continue + } + dd[sURL] = true url, err := parseURL(sURL, typ) if err != nil { err := &configErr{tk, err.Error()} @@ -1273,17 +2046,19 @@ func parseURL(u string, typ string) (*url.URL, error) { urlStr := strings.TrimSpace(u) url, err := url.Parse(urlStr) if err != nil { + // Security note: if it's not well-formed but still reached us, then we're going to log as-is which might include password information here. + // If the URL parses, we don't log the credentials ever, but if it doesn't even parse we don't have a sane way to redact. return nil, fmt.Errorf("error parsing %s url [%q]", typ, urlStr) } return url, nil } -func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) error { +func parseGateway(v any, o *Options, errors *[]error, warnings *[]error) error { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - gm, ok := v.(map[string]interface{}) + gm, ok := v.(map[string]any) if !ok { return &configErr{tk, fmt.Sprintf("Expected gateway to be a map, got %T", v)} } @@ -1292,7 +2067,13 @@ func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { case "name": - o.Gateway.Name = mv.(string) + gn := mv.(string) + if strings.Contains(gn, " ") { + err := &configErr{tk, ErrGatewayNameHasSpaces.Error()} + *errors = append(*errors, err) + continue + } + o.Gateway.Name = gn case "listen": hp, err := parseListen(mv) if err != nil { @@ -1307,7 +2088,7 @@ func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) case "host", "net": o.Gateway.Host = mv.(string) case "authorization": - auth, err := parseAuthorization(tk, o, errors, warnings) + auth, err := parseAuthorization(tk, errors, warnings) if err != nil { *errors = append(*errors, err) continue @@ -1316,6 +2097,17 @@ func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) *errors = append(*errors, &configErr{tk, "Gateway authorization does not allow multiple users"}) continue } + if auth.token != _EMPTY_ { + err := &configErr{tk, "Gateway authorization does not support tokens"} + *errors = append(*errors, err) + continue + } + if auth.callout != nil { + err := &configErr{tk, "Gateway authorization does not support callouts"} + *errors = append(*errors, err) + continue + } + o.Gateway.Username = auth.user o.Gateway.Password = auth.pass o.Gateway.AuthTimeout = auth.timeout @@ -1329,6 +2121,8 @@ func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) o.Gateway.TLSTimeout = tlsopts.Timeout o.Gateway.TLSMap = tlsopts.Map o.Gateway.TLSCheckKnownURLs = tlsopts.TLSCheckKnownURLs + o.Gateway.TLSPinnedCerts = tlsopts.PinnedCerts + o.Gateway.tlsConfigOpts = tlsopts case "advertise": o.Gateway.Advertise = mv.(string) case "connect_retries": @@ -1341,6 +2135,10 @@ func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) o.Gateway.Gateways = gateways case "reject_unknown", "reject_unknown_cluster": o.Gateway.RejectUnknown = mv.(bool) + case "write_deadline": + o.Gateway.WriteDeadline = parseDuration("write_deadline", tk, mv, errors, warnings) + case "write_timeout": + o.Gateway.WriteTimeout = parseWriteDeadlinePolicy(tk, mv.(string), errors) default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1357,11 +2155,12 @@ func parseGateway(v interface{}, o *Options, errors *[]error, warnings *[]error) return nil } -var dynamicJSAccountLimits = &JetStreamAccountLimits{-1, -1, -1, -1} +var dynamicJSAccountLimits = JetStreamAccountLimits{-1, -1, -1, -1, -1, -1, -1, false} +var defaultJSAccountTiers = map[string]JetStreamAccountLimits{_EMPTY_: dynamicJSAccountLimits} // Parses jetstream account limits for an account. Simple setup with boolen is allowed, and we will // use dynamic account limits. -func parseJetStreamForAccount(v interface{}, acc *Account, errors *[]error, warnings *[]error) error { +func parseJetStreamForAccount(v any, acc *Account, errors *[]error) error { var lt token tk, v := unwrapValue(v, <) @@ -1370,19 +2169,19 @@ func parseJetStreamForAccount(v interface{}, acc *Account, errors *[]error, warn switch vv := v.(type) { case bool: if vv { - acc.jsLimits = dynamicJSAccountLimits + acc.jsLimits = defaultJSAccountTiers } case string: switch strings.ToLower(vv) { case "enabled", "enable": - acc.jsLimits = dynamicJSAccountLimits + acc.jsLimits = defaultJSAccountTiers case "disabled", "disable": acc.jsLimits = nil default: return &configErr{tk, fmt.Sprintf("Expected 'enabled' or 'disabled' for string value, got '%s'", vv)} } - case map[string]interface{}: - jsLimits := &JetStreamAccountLimits{-1, -1, -1, -1} + case map[string]any: + jsLimits := JetStreamAccountLimits{-1, -1, -1, -1, -1, -1, -1, false} for mk, mv := range vv { tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { @@ -1391,13 +2190,13 @@ func parseJetStreamForAccount(v interface{}, acc *Account, errors *[]error, warn if !ok { return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} } - jsLimits.MaxMemory = int64(vv) + jsLimits.MaxMemory = vv case "max_store", "max_file", "max_disk", "store", "disk": vv, ok := mv.(int64) if !ok { return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} } - jsLimits.MaxStore = int64(vv) + jsLimits.MaxStore = vv case "max_streams", "streams": vv, ok := mv.(int64) if !ok { @@ -1410,6 +2209,43 @@ func parseJetStreamForAccount(v interface{}, acc *Account, errors *[]error, warn return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} } jsLimits.MaxConsumers = int(vv) + case "max_bytes_required", "max_stream_bytes", "max_bytes": + vv, ok := mv.(bool) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a parseable bool for %q, got %v", mk, mv)} + } + jsLimits.MaxBytesRequired = vv + case "mem_max_stream_bytes", "memory_max_stream_bytes": + vv, ok := mv.(int64) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} + } + jsLimits.MemoryMaxStreamBytes = vv + case "disk_max_stream_bytes", "store_max_stream_bytes": + vv, ok := mv.(int64) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} + } + jsLimits.StoreMaxStreamBytes = vv + case "max_ack_pending": + vv, ok := mv.(int64) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} + } + jsLimits.MaxAckPending = int(vv) + case "cluster_traffic": + vv, ok := mv.(string) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected either 'system' or 'owner' string value for %q, got %v", mk, mv)} + } + switch vv { + case "system", _EMPTY_: + acc.nrgAccount = _EMPTY_ + case "owner": + acc.nrgAccount = acc.Name + default: + return &configErr{tk, fmt.Sprintf("Expected 'system' or 'owner' string value for %q, got %v", mk, mv)} + } default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1423,15 +2259,150 @@ func parseJetStreamForAccount(v interface{}, acc *Account, errors *[]error, warn } } } - acc.jsLimits = jsLimits + acc.jsLimits = map[string]JetStreamAccountLimits{_EMPTY_: jsLimits} default: return &configErr{tk, fmt.Sprintf("Expected map, bool or string to define JetStream, got %T", v)} } return nil } +// takes in a storage size as either an int or a string and returns an int64 value based on the input. +func getStorageSize(v any) (int64, error) { + _, ok := v.(int64) + if ok { + return v.(int64), nil + } + + s, ok := v.(string) + if !ok { + return 0, fmt.Errorf("must be int64 or string") + } + + if s == _EMPTY_ { + return 0, nil + } + + suffix := s[len(s)-1:] + prefix := s[:len(s)-1] + num, err := strconv.ParseInt(prefix, 10, 64) + if err != nil { + return 0, err + } + + suffixMap := map[string]int64{"K": 10, "M": 20, "G": 30, "T": 40} + + mult, ok := suffixMap[suffix] + if !ok { + return 0, fmt.Errorf("sizes defined as strings must end in K, M, G, T") + } + num *= 1 << mult + + return num, nil +} + // Parse enablement of jetstream for a server. -func parseJetStream(v interface{}, opts *Options, errors *[]error, warnings *[]error) error { +func parseJetStreamLimits(v any, opts *Options, errors *[]error) error { + var lt token + tk, v := unwrapValue(v, <) + + lim := JSLimitOpts{} + + vv, ok := v.(map[string]any) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a map to define JetStreamLimits, got %T", v)} + } + for mk, mv := range vv { + tk, mv = unwrapValue(mv, <) + switch strings.ToLower(mk) { + case "max_ack_pending": + lim.MaxAckPending = int(mv.(int64)) + case "max_ha_assets": + lim.MaxHAAssets = int(mv.(int64)) + case "max_request_batch": + lim.MaxRequestBatch = int(mv.(int64)) + case "duplicate_window": + var err error + lim.Duplicates, err = time.ParseDuration(mv.(string)) + if err != nil { + *errors = append(*errors, err) + } + default: + if !tk.IsUsedVariable() { + err := &unknownConfigFieldErr{ + field: mk, + configErr: configErr{ + token: tk, + }, + } + *errors = append(*errors, err) + continue + } + } + } + opts.JetStreamLimits = lim + return nil +} + +// Parse the JetStream TPM options. +func parseJetStreamTPM(v interface{}, opts *Options, errors *[]error) error { + var lt token + tk, v := unwrapValue(v, <) + + tpm := JSTpmOpts{} + + vv, ok := v.(map[string]interface{}) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a map to define JetStreamLimits, got %T", v)} + } + for mk, mv := range vv { + tk, mv = unwrapValue(mv, <) + switch strings.ToLower(mk) { + case "keys_file": + tpm.KeysFile = mv.(string) + case "encryption_password": + tpm.KeyPassword = mv.(string) + case "srk_password": + tpm.SrkPassword = mv.(string) + case "pcr": + tpm.Pcr = int(mv.(int64)) + case "cipher": + if err := setJetStreamEkCipher(opts, mv, tk); err != nil { + return err + } + default: + if !tk.IsUsedVariable() { + err := &unknownConfigFieldErr{ + field: mk, + configErr: configErr{ + token: tk, + }, + } + *errors = append(*errors, err) + continue + } + } + } + opts.JetStreamTpm = tpm + return nil +} + +func setJetStreamEkCipher(opts *Options, mv interface{}, tk token) error { + switch strings.ToLower(mv.(string)) { + case "chacha", "chachapoly": + if fips140.Enabled() { + return &configErr{tk, fmt.Sprintf("Cipher type %q cannot be used in FIPS-140 mode", mv)} + } + opts.JetStreamCipher = ChaCha + case "aes": + opts.JetStreamCipher = AES + default: + return &configErr{tk, fmt.Sprintf("Unknown cipher type: %q", mv)} + } + return nil +} + +// Parse enablement of jetstream for a server. +func parseJetStream(v any, opts *Options, errors *[]error, warnings *[]error) error { var lt token tk, v := unwrapValue(v, <) @@ -1449,16 +2420,108 @@ func parseJetStream(v interface{}, opts *Options, errors *[]error, warnings *[]e default: return &configErr{tk, fmt.Sprintf("Expected 'enabled' or 'disabled' for string value, got '%s'", vv)} } - case map[string]interface{}: + case map[string]any: + doEnable := true for mk, mv := range vv { tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { - case "store_dir", "storedir": + case "strict": + if v, ok := mv.(bool); ok { + opts.JetStreamStrict = v + } else { + return &configErr{tk, fmt.Sprintf("Expected 'true' or 'false' for bool value, got '%s'", mv)} + } + case "store", "store_dir", "storedir": + // StoreDir can be set at the top level as well so have to prevent ambiguous declarations. + if opts.StoreDir != _EMPTY_ { + return &configErr{tk, "Duplicate 'store_dir' configuration"} + } opts.StoreDir = mv.(string) + case "sync", "sync_interval": + if v, ok := mv.(string); ok && strings.ToLower(v) == "always" { + opts.SyncInterval = defaultSyncInterval + opts.SyncAlways = true + } else { + opts.SyncInterval = parseDuration(mk, tk, mv, errors, warnings) + } + opts.syncSet = true case "max_memory_store", "max_mem_store", "max_mem": - opts.JetStreamMaxMemory = mv.(int64) + s, err := getStorageSize(mv) + if err != nil { + return &configErr{tk, fmt.Sprintf("max_mem_store %s", err)} + } + opts.JetStreamMaxMemory = s + opts.maxMemSet = true case "max_file_store", "max_file": - opts.JetStreamMaxStore = mv.(int64) + s, err := getStorageSize(mv) + if err != nil { + return &configErr{tk, fmt.Sprintf("max_file_store %s", err)} + } + opts.JetStreamMaxStore = s + opts.maxStoreSet = true + case "domain": + opts.JetStreamDomain = mv.(string) + case "enable", "enabled": + doEnable = mv.(bool) + case "key", "ek", "encryption_key": + opts.JetStreamKey = mv.(string) + case "prev_key", "prev_ek", "prev_encryption_key": + opts.JetStreamOldKey = mv.(string) + case "cipher": + if err := setJetStreamEkCipher(opts, mv, tk); err != nil { + return err + } + case "extension_hint": + opts.JetStreamExtHint = mv.(string) + case "limits": + if err := parseJetStreamLimits(tk, opts, errors); err != nil { + return err + } + case "tpm": + if err := parseJetStreamTPM(tk, opts, errors); err != nil { + return err + } + case "unique_tag": + opts.JetStreamUniqueTag = strings.ToLower(strings.TrimSpace(mv.(string))) + case "max_outstanding_catchup": + s, err := getStorageSize(mv) + if err != nil { + return &configErr{tk, fmt.Sprintf("%s %s", strings.ToLower(mk), err)} + } + opts.JetStreamMaxCatchup = s + case "max_buffered_size": + s, err := getStorageSize(mv) + if err != nil { + return &configErr{tk, fmt.Sprintf("%s %s", strings.ToLower(mk), err)} + } + opts.StreamMaxBufferedSize = s + case "max_buffered_msgs": + mlen, ok := mv.(int64) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} + } + opts.StreamMaxBufferedMsgs = int(mlen) + case "request_queue_limit": + lim, ok := mv.(int64) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected a parseable size for %q, got %v", mk, mv)} + } + opts.JetStreamRequestQueueLimit = lim + case "meta_compact": + thres, ok := mv.(int64) + if !ok || thres < 0 { + return &configErr{tk, fmt.Sprintf("Expected an absolute size for %q, got %v", mk, mv)} + } + opts.JetStreamMetaCompact = uint64(thres) + case "meta_compact_size": + s, err := getStorageSize(mv) + if err != nil { + return &configErr{tk, fmt.Sprintf("%s %s", strings.ToLower(mk), err)} + } + if s < 0 { + return &configErr{tk, fmt.Sprintf("Expected an absolute size for %q, got %v", mk, mv)} + } + opts.JetStreamMetaCompactSize = uint64(s) default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1472,7 +2535,7 @@ func parseJetStream(v interface{}, opts *Options, errors *[]error, warnings *[]e } } } - opts.JetStream = true + opts.JetStream = doEnable default: return &configErr{tk, fmt.Sprintf("Expected map, bool or string to define JetStream, got %T", v)} } @@ -1481,12 +2544,12 @@ func parseJetStream(v interface{}, opts *Options, errors *[]error, warnings *[]e } // parseLeafNodes will parse the leaf node config. -func parseLeafNodes(v interface{}, opts *Options, errors *[]error, warnings *[]error) error { +func parseLeafNodes(v any, opts *Options, errors *[]error, warnings *[]error) error { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - cm, ok := v.(map[string]interface{}) + cm, ok := v.(map[string]any) if !ok { return &configErr{tk, fmt.Sprintf("Expected map to define a leafnode, got %T", v)} } @@ -1519,6 +2582,7 @@ func parseLeafNodes(v interface{}, opts *Options, errors *[]error, warnings *[]e opts.LeafNode.AuthTimeout = auth.timeout opts.LeafNode.Account = auth.acc opts.LeafNode.Users = auth.users + opts.LeafNode.Nkey = auth.nkey // Validate user info config for leafnode authorization if err := validateLeafNodeAuthOptions(opts); err != nil { *errors = append(*errors, &configErr{tk, err.Error()}) @@ -1533,7 +2597,7 @@ func parseLeafNodes(v interface{}, opts *Options, errors *[]error, warnings *[]e } opts.LeafNode.Remotes = remotes case "reconnect", "reconnect_delay", "reconnect_interval": - opts.LeafNode.ReconnectInterval = time.Duration(int(mv.(int64))) * time.Second + opts.LeafNode.ReconnectInterval = parseDuration("reconnect", tk, mv, errors, warnings) case "tls": tc, err := parseTLS(tk, true) if err != nil { @@ -1546,11 +2610,33 @@ func parseLeafNodes(v interface{}, opts *Options, errors *[]error, warnings *[]e continue } opts.LeafNode.TLSTimeout = tc.Timeout + opts.LeafNode.TLSMap = tc.Map + opts.LeafNode.TLSPinnedCerts = tc.PinnedCerts + opts.LeafNode.TLSHandshakeFirst = tc.HandshakeFirst + opts.LeafNode.TLSHandshakeFirstFallback = tc.FallbackDelay + opts.LeafNode.tlsConfigOpts = tc case "leafnode_advertise", "advertise": opts.LeafNode.Advertise = mv.(string) case "no_advertise": opts.LeafNode.NoAdvertise = mv.(bool) - trackExplicitVal(opts, &opts.inConfig, "LeafNode.NoAdvertise", opts.LeafNode.NoAdvertise) + trackExplicitVal(&opts.inConfig, "LeafNode.NoAdvertise", opts.LeafNode.NoAdvertise) + case "min_version", "minimum_version": + version := mv.(string) + if err := checkLeafMinVersionConfig(version); err != nil { + err = &configErr{tk, err.Error()} + *errors = append(*errors, err) + continue + } + opts.LeafNode.MinVersion = version + case "compression": + if err := parseCompression(&opts.LeafNode.Compression, CompressionS2Auto, tk, mk, mv); err != nil { + *errors = append(*errors, err) + continue + } + case "write_deadline": + opts.LeafNode.WriteDeadline = parseDuration("write_deadline", tk, mv, errors, warnings) + case "write_timeout": + opts.LeafNode.WriteTimeout = parseWriteDeadlinePolicy(tk, mv.(string), errors) default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1569,9 +2655,9 @@ func parseLeafNodes(v interface{}, opts *Options, errors *[]error, warnings *[]e // This is the authorization parser adapter for the leafnode's // authorization config. -func parseLeafAuthorization(v interface{}, errors *[]error, warnings *[]error) (*authorization, error) { +func parseLeafAuthorization(v any, errors, warnings *[]error) (*authorization, error) { var ( - am map[string]interface{} + am map[string]any tk token lt token auth = &authorization{} @@ -1579,7 +2665,7 @@ func parseLeafAuthorization(v interface{}, errors *[]error, warnings *[]error) ( defer convertPanicToErrorList(<, errors) _, v = unwrapValue(v, <) - am = v.(map[string]interface{}) + am = v.(map[string]any) for mk, mv := range am { tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { @@ -1587,17 +2673,35 @@ func parseLeafAuthorization(v interface{}, errors *[]error, warnings *[]error) ( auth.user = mv.(string) case "pass", "password": auth.pass = mv.(string) + case "nkey": + nk := mv.(string) + if !nkeys.IsValidPublicUserKey(nk) { + *errors = append(*errors, &configErr{tk, "Not a valid public nkey for leafnode authorization"}) + } + auth.nkey = nk case "timeout": - at := float64(1) + at := float64(0) switch mv := mv.(type) { case int64: at = float64(mv) case float64: at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf("error parsing leafnode authorization config, 'timeout' %s", err)} + } + at = d.Seconds() + default: + return nil, &configErr{tk, "error parsing leafnode authorization config, 'timeout' wrong type"} + } + if at > (60 * time.Second).Seconds() { + reason := fmt.Sprintf("timeout of %v (%f seconds) is high, consider keeping it under 60 seconds. possibly caused by unquoted duration; use '1m' instead of 1m, for example", mv, at) + *warnings = append(*warnings, &configWarningErr{field: mk, configErr: configErr{token: tk, reason: reason}}) } auth.timeout = at case "users": - users, err := parseLeafUsers(tk, errors, warnings) + users, err := parseLeafUsers(tk, errors) if err != nil { *errors = append(*errors, err) continue @@ -1624,7 +2728,7 @@ func parseLeafAuthorization(v interface{}, errors *[]error, warnings *[]error) ( // This is a trimmed down version of parseUsers that is adapted // for the users possibly defined in the authorization{} section // of leafnodes {}. -func parseLeafUsers(mv interface{}, errors *[]error, warnings *[]error) ([]*User, error) { +func parseLeafUsers(mv any, errors *[]error) ([]*User, error) { var ( tk token lt token @@ -1634,14 +2738,14 @@ func parseLeafUsers(mv interface{}, errors *[]error, warnings *[]error) ([]*User tk, mv = unwrapValue(mv, <) // Make sure we have an array - uv, ok := mv.([]interface{}) + uv, ok := mv.([]any) if !ok { return nil, &configErr{tk, fmt.Sprintf("Expected users field to be an array, got %v", mv)} } for _, u := range uv { tk, u = unwrapValue(u, <) // Check its a map/struct - um, ok := u.(map[string]interface{}) + um, ok := u.(map[string]any) if !ok { err := &configErr{tk, fmt.Sprintf("Expected user entry to be a map/struct, got %v", u)} *errors = append(*errors, err) @@ -1681,11 +2785,11 @@ func parseLeafUsers(mv interface{}, errors *[]error, warnings *[]error) ([]*User return users, nil } -func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([]*RemoteLeafOpts, error) { +func parseRemoteLeafNodes(v any, errors *[]error, warnings *[]error) ([]*RemoteLeafOpts, error) { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - ra, ok := v.([]interface{}) + ra, ok := v.([]any) if !ok { return nil, &configErr{tk, fmt.Sprintf("Expected remotes field to be an array, got %T", v)} } @@ -1693,7 +2797,7 @@ func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([] for _, r := range ra { tk, r = unwrapValue(r, <) // Check its a map/struct - rm, ok := r.(map[string]interface{}) + rm, ok := r.(map[string]any) if !ok { *errors = append(*errors, &configErr{tk, fmt.Sprintf("Expected remote leafnode entry to be a map/struct, got %v", r)}) continue @@ -1702,10 +2806,12 @@ func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([] for k, v := range rm { tk, v = unwrapValue(v, <) switch strings.ToLower(k) { + case "no_randomize", "dont_randomize": + remote.NoRandomize = v.(bool) case "url", "urls": switch v := v.(type) { - case []interface{}, []string: - urls, errs := parseURLs(v.([]interface{}), "leafnode") + case []any, []string: + urls, errs := parseURLs(v.([]any), "leafnode", warnings) if errs != nil { *errors = append(*errors, errs...) continue @@ -1730,7 +2836,24 @@ func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([] *errors = append(*errors, &configErr{tk, err.Error()}) continue } + // Can't have both creds and nkey + if remote.Nkey != _EMPTY_ { + *errors = append(*errors, &configErr{tk, "Remote leafnode can not have both creds and nkey defined"}) + continue + } remote.Credentials = p + case "nkey", "seed": + nk := v.(string) + if pb, _, err := nkeys.DecodeSeed([]byte(nk)); err != nil || pb != nkeys.PrefixByteUser { + err := &configErr{tk, fmt.Sprintf("Remote leafnode nkey is not a valid seed: %q", v)} + *errors = append(*errors, err) + continue + } + if remote.Credentials != _EMPTY_ { + *errors = append(*errors, &configErr{tk, "Remote leafnode can not have both creds and nkey defined"}) + continue + } + remote.Nkey = nk case "tls": tc, err := parseTLS(tk, true) if err != nil { @@ -1748,24 +2871,58 @@ func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([] if tc.Timeout > 0 { remote.TLSTimeout = tc.Timeout } else { - remote.TLSTimeout = float64(DEFAULT_LEAF_TLS_TIMEOUT) + remote.TLSTimeout = float64(DEFAULT_LEAF_TLS_TIMEOUT) / float64(time.Second) } + remote.TLSHandshakeFirst = tc.HandshakeFirst + remote.tlsConfigOpts = tc case "hub": remote.Hub = v.(bool) case "deny_imports", "deny_import": - subjects, err := parseSubjects(tk, errors, warnings) + subjects, err := parsePermSubjects(tk, errors) if err != nil { *errors = append(*errors, err) continue } remote.DenyImports = subjects case "deny_exports", "deny_export": - subjects, err := parseSubjects(tk, errors, warnings) + subjects, err := parsePermSubjects(tk, errors) if err != nil { *errors = append(*errors, err) continue } remote.DenyExports = subjects + case "ws_compress", "ws_compression", "websocket_compress", "websocket_compression": + remote.Websocket.Compression = v.(bool) + case "ws_no_masking", "websocket_no_masking": + remote.Websocket.NoMasking = v.(bool) + case "jetstream_cluster_migrate", "js_cluster_migrate": + var lt token + + tk, v := unwrapValue(v, <) + switch vv := v.(type) { + case bool: + remote.JetStreamClusterMigrate = vv + case map[string]any: + remote.JetStreamClusterMigrate = true + migrateConfig, ok := v.(map[string]any) + if !ok { + continue + } + val, ok := migrateConfig["leader_migrate_delay"] + tk, delay := unwrapValue(val, &tk) + if ok { + remote.JetStreamClusterMigrateDelay = parseDuration("leader_migrate_delay", tk, delay, errors, warnings) + } + default: + *errors = append(*errors, &configErr{tk, fmt.Sprintf("Expected boolean or map for jetstream_cluster_migrate, got %T", v)}) + } + case "compression": + if err := parseCompression(&remote.Compression, CompressionS2Auto, tk, k, v); err != nil { + *errors = append(*errors, err) + continue + } + case "first_info_timeout": + remote.FirstInfoTimeout = parseDuration(k, tk, v, errors, warnings) default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1804,13 +2961,13 @@ func getTLSConfig(tk token) (*tls.Config, *TLSConfigOpts, error) { return config, tc, nil } -func parseGateways(v interface{}, errors *[]error, warnings *[]error) ([]*RemoteGatewayOpts, error) { +func parseGateways(v any, errors *[]error, warnings *[]error) ([]*RemoteGatewayOpts, error) { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) // Make sure we have an array - ga, ok := v.([]interface{}) + ga, ok := v.([]any) if !ok { return nil, &configErr{tk, fmt.Sprintf("Expected gateways field to be an array, got %T", v)} } @@ -1818,7 +2975,7 @@ func parseGateways(v interface{}, errors *[]error, warnings *[]error) ([]*Remote for _, g := range ga { tk, g = unwrapValue(g, <) // Check its a map/struct - gm, ok := g.(map[string]interface{}) + gm, ok := g.(map[string]any) if !ok { *errors = append(*errors, &configErr{tk, fmt.Sprintf("Expected gateway entry to be a map/struct, got %v", g)}) continue @@ -1837,6 +2994,7 @@ func parseGateways(v interface{}, errors *[]error, warnings *[]error) ([]*Remote } gateway.TLSConfig = tls gateway.TLSTimeout = tlsopts.Timeout + gateway.tlsConfigOpts = tlsopts case "url": url, err := parseURL(v.(string), "gateway") if err != nil { @@ -1845,7 +3003,7 @@ func parseGateways(v interface{}, errors *[]error, warnings *[]error) ([]*Remote } gateway.URLs = append(gateway.URLs, url) case "urls": - urls, errs := parseURLs(v.([]interface{}), "gateway") + urls, errs := parseURLs(v.([]any), "gateway", warnings) if errs != nil { *errors = append(*errors, errs...) continue @@ -1892,14 +3050,17 @@ type export struct { rt ServiceRespType lat *serviceLatency rthr time.Duration + tPos uint + atrc bool // allow_trace } type importStream struct { - acc *Account - an string - sub string - to string - pre string + acc *Account + an string + sub string + to string + pre string + atrc bool // allow_trace } type importService struct { @@ -1915,9 +3076,9 @@ func isReservedAccount(name string) bool { return name == globalAccountName } -func parseAccountMapDest(v interface{}, tk token, errors *[]error, warnings *[]error) (*MapDest, *configErr) { +func parseAccountMapDest(v any, tk token, errors *[]error) (*MapDest, *configErr) { // These should be maps. - mv, ok := v.(map[string]interface{}) + mv, ok := v.(map[string]any) if !ok { err := &configErr{tk, "Expected an entry for the mapping destination"} *errors = append(*errors, err) @@ -1937,9 +3098,7 @@ func parseAccountMapDest(v interface{}, tk token, errors *[]error, warnings *[]e switch vv := dmv.(type) { case string: ws := vv - if strings.HasSuffix(ws, "%") { - ws = ws[:len(ws)-1] - } + ws = strings.TrimSuffix(ws, "%") weight, err := strconv.Atoi(ws) if err != nil { err := &configErr{tk, fmt.Sprintf("Invalid weight %q for mapping destination", ws)} @@ -1968,7 +3127,7 @@ func parseAccountMapDest(v interface{}, tk token, errors *[]error, warnings *[]e return nil, err } case "cluster": - mdest.OptCluster = dmv.(string) + mdest.Cluster = dmv.(string) default: err := &configErr{tk, fmt.Sprintf("Unknown field %q for mapping destination", k)} *errors = append(*errors, err) @@ -1986,12 +3145,12 @@ func parseAccountMapDest(v interface{}, tk token, errors *[]error, warnings *[]e } // parseAccountMappings is called to parse account mappings. -func parseAccountMappings(v interface{}, acc *Account, errors *[]error, warnings *[]error) error { +func parseAccountMappings(v any, acc *Account, errors *[]error) error { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - am := v.(map[string]interface{}) + am := v.(map[string]any) for subj, mv := range am { if !IsValidSubject(subj) { err := &configErr{tk, fmt.Sprintf("Subject %q is not a valid subject", subj)} @@ -2003,15 +3162,15 @@ func parseAccountMappings(v interface{}, acc *Account, errors *[]error, warnings switch vv := v.(type) { case string: if err := acc.AddMapping(subj, v.(string)); err != nil { - err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q: %v", subj, err)} + err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q to %q : %v", subj, v.(string), err)} *errors = append(*errors, err) continue } - case []interface{}: + case []any: var mappings []*MapDest - for _, mv := range v.([]interface{}) { + for _, mv := range v.([]any) { tk, amv := unwrapValue(mv, <) - mdest, err := parseAccountMapDest(amv, tk, errors, warnings) + mdest, err := parseAccountMapDest(amv, tk, errors) if err != nil { continue } @@ -2020,34 +3179,130 @@ func parseAccountMappings(v interface{}, acc *Account, errors *[]error, warnings // Now add them in.. if err := acc.AddWeightedMappings(subj, mappings...); err != nil { - err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q: %v", subj, err)} + err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q : %v", subj, err)} *errors = append(*errors, err) continue } - case interface{}: + case any: tk, amv := unwrapValue(mv, <) - mdest, err := parseAccountMapDest(amv, tk, errors, warnings) + mdest, err := parseAccountMapDest(amv, tk, errors) if err != nil { continue } // Now add it in.. if err := acc.AddWeightedMappings(subj, mdest); err != nil { - err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q: %v", subj, err)} + err := &configErr{tk, fmt.Sprintf("Error adding mapping for %q : %v", subj, err)} *errors = append(*errors, err) continue } - default: - err := &configErr{tk, fmt.Sprintf("Unknown type %T for mapping destination", vv)} - *errors = append(*errors, err) - continue + default: + err := &configErr{tk, fmt.Sprintf("Unknown type %T for mapping destination", vv)} + *errors = append(*errors, err) + continue + } + } + + return nil +} + +// parseAccountLimits is called to parse account limits in a server config. +func parseAccountLimits(mv any, acc *Account, errors *[]error) error { + var lt token + defer convertPanicToErrorList(<, errors) + + tk, v := unwrapValue(mv, <) + am, ok := v.(map[string]any) + if !ok { + return &configErr{tk, fmt.Sprintf("Expected account limits to be a map/struct, got %+v", v)} + } + + for k, v := range am { + tk, mv = unwrapValue(v, <) + switch strings.ToLower(k) { + case "max_connections", "max_conn": + acc.mconns = int32(mv.(int64)) + case "max_subscriptions", "max_subs": + acc.msubs = int32(mv.(int64)) + case "max_payload", "max_pay": + acc.mpay = int32(mv.(int64)) + case "max_leafnodes", "max_leafs": + acc.mleafs = int32(mv.(int64)) + default: + if !tk.IsUsedVariable() { + err := &configErr{tk, fmt.Sprintf("Unknown field %q parsing account limits", k)} + *errors = append(*errors, err) + } + } + } + + return nil +} + +func parseAccountMsgTrace(mv any, topKey string, acc *Account) error { + processDest := func(tk token, k string, v any) error { + td, ok := v.(string) + if !ok { + return &configErr{tk, fmt.Sprintf("Field %q should be a string, got %T", k, v)} + } + if !IsValidPublishSubject(td) { + return &configErr{tk, fmt.Sprintf("Trace destination %q is not valid", td)} + } + acc.traceDest = td + return nil + } + processSampling := func(tk token, n int) error { + if n <= 0 || n > 100 { + return &configErr{tk, fmt.Sprintf("Ttrace destination sampling value %d is invalid, needs to be [1..100]", n)} + } + acc.traceDestSampling = n + return nil + } + + var lt token + tk, v := unwrapValue(mv, <) + switch vv := v.(type) { + case string: + return processDest(tk, topKey, v) + case map[string]any: + for k, v := range vv { + tk, v := unwrapValue(v, <) + switch strings.ToLower(k) { + case "dest": + if err := processDest(tk, k, v); err != nil { + return err + } + case "sampling": + switch vv := v.(type) { + case int64: + if err := processSampling(tk, int(vv)); err != nil { + return err + } + case string: + s := strings.TrimSuffix(vv, "%") + n, err := strconv.Atoi(s) + if err != nil { + return &configErr{tk, fmt.Sprintf("Invalid trace destination sampling value %q", vv)} + } + if err := processSampling(tk, n); err != nil { + return err + } + default: + return &configErr{tk, fmt.Sprintf("Trace destination sampling field %q should be an integer or a percentage, got %T", k, v)} + } + default: + if !tk.IsUsedVariable() { + return &configErr{tk, fmt.Sprintf("Unknown field %q parsing account message trace map/struct %q", k, topKey)} + } + } } + default: + return &configErr{tk, fmt.Sprintf("Expected account message trace %q to be a string or a map/struct, got %T", topKey, v)} } - return nil } // parseAccounts will parse the different accounts syntax. -func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]error) error { +func parseAccounts(v any, opts *Options, errors *[]error, warnings *[]error) error { var ( importStreams []*importStream importServices []*importService @@ -2060,9 +3315,9 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er tk, v := unwrapValue(v, <) switch vv := v.(type) { // Simple array of account names. - case []interface{}, []string: - m := make(map[string]struct{}, len(v.([]interface{}))) - for _, n := range v.([]interface{}) { + case []any, []string: + m := make(map[string]struct{}, len(v.([]any))) + for _, n := range v.([]any) { tk, name := unwrapValue(n, <) ns := name.(string) // Check for reserved names. @@ -2080,10 +3335,13 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er m[ns] = struct{}{} } // More common map entry - case map[string]interface{}: + case map[string]any: // Track users across accounts, must be unique across // accounts and nkeys vs users. - uorn := make(map[string]struct{}) + // We also want to check for users that may have been added in + // parseAuthorization{} if that happened first. + uorn := setupUsersAndNKeysDuplicateCheckMap(opts) + for aname, mv := range vv { tk, amv := unwrapValue(mv, <) @@ -2093,7 +3351,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } // These should be maps. - mv, ok := amv.(map[string]interface{}) + mv, ok := amv.(map[string]any) if !ok { err := &configErr{tk, "Expected map entries for accounts"} *errors = append(*errors, err) @@ -2124,7 +3382,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } acc.Nkey = nk case "imports": - streams, services, err := parseAccountImports(tk, acc, errors, warnings) + streams, services, err := parseAccountImports(tk, acc, errors) if err != nil { *errors = append(*errors, err) continue @@ -2132,7 +3390,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er importStreams = append(importStreams, streams...) importServices = append(importServices, services...) case "exports": - streams, services, err := parseAccountExports(tk, acc, errors, warnings) + streams, services, err := parseAccountExports(tk, acc, errors) if err != nil { *errors = append(*errors, err) continue @@ -2140,7 +3398,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er exportStreams = append(exportStreams, streams...) exportServices = append(exportServices, services...) case "jetstream": - err := parseJetStreamForAccount(mv, acc, errors, warnings) + err := parseJetStreamForAccount(mv, acc, errors) if err != nil { *errors = append(*errors, err) continue @@ -2148,24 +3406,47 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er case "users": var err error usersTk = tk - nkeyUsr, users, err = parseUsers(mv, opts, errors, warnings) + nkeyUsr, users, err = parseUsers(mv, errors) if err != nil { *errors = append(*errors, err) continue } case "default_permissions": - permissions, err := parseUserPermissions(tk, errors, warnings) + permissions, err := parseUserPermissions(tk, errors) if err != nil { *errors = append(*errors, err) continue } acc.defaultPerms = permissions case "mappings", "maps": - err := parseAccountMappings(tk, acc, errors, warnings) + err := parseAccountMappings(tk, acc, errors) + if err != nil { + *errors = append(*errors, err) + continue + } + case "limits": + err := parseAccountLimits(tk, acc, errors) if err != nil { *errors = append(*errors, err) continue } + case "msg_trace", "trace_dest": + if err := parseAccountMsgTrace(tk, k, acc); err != nil { + *errors = append(*errors, err) + continue + } + // If trace destination is set but no sampling, set it to 100%. + if acc.traceDest != _EMPTY_ && acc.traceDestSampling == 0 { + acc.traceDestSampling = 100 + } else if acc.traceDestSampling > 0 && acc.traceDest == _EMPTY_ { + // If no trace destination is provided, no trace would be + // triggered, so if the user set a sampling value expecting + // something to happen, want and set the value to 0 for good + // measure. + *warnings = append(*warnings, + &configErr{tk, "Trace destination sampling ignored since no destination was set"}) + acc.traceDestSampling = 0 + } default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -2178,6 +3459,20 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } } } + // Report error if there is an authorization{} block + // with u/p or token and any user defined in accounts{} + if len(nkeyUsr) > 0 || len(users) > 0 { + if opts.Username != _EMPTY_ { + err := &configErr{usersTk, "Can not have a single user/pass and accounts"} + *errors = append(*errors, err) + continue + } + if opts.Authorization != _EMPTY_ { + err := &configErr{usersTk, "Can not have a token and accounts"} + *errors = append(*errors, err) + continue + } + } applyDefaultPermissions(users, nkeyUsr, acc.defaultPerms) for _, u := range nkeyUsr { if _, ok := uorn[u.Nkey]; ok { @@ -2229,7 +3524,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } accounts = append(accounts, ta) } - if err := stream.acc.AddStreamExport(stream.sub, accounts); err != nil { + if err := stream.acc.addStreamExportWithAccountPos(stream.sub, accounts, stream.tPos); err != nil { msg := fmt.Sprintf("Error adding stream export %q: %v", stream.sub, err) *errors = append(*errors, &configErr{tk, msg}) continue @@ -2247,7 +3542,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } accounts = append(accounts, ta) } - if err := service.acc.AddServiceExportWithResponse(service.sub, service.rt, accounts); err != nil { + if err := service.acc.addServiceExportWithResponseAndAccountPos(service.sub, service.rt, accounts, service.tPos); err != nil { msg := fmt.Sprintf("Error adding service export %q: %v", service.sub, err) *errors = append(*errors, &configErr{tk, msg}) continue @@ -2276,6 +3571,14 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er continue } } + + if service.atrc { + if err := service.acc.SetServiceExportAllowTrace(service.sub, true); err != nil { + msg := fmt.Sprintf("Error adding allow_trace for %q: %v", service.sub, err) + *errors = append(*errors, &configErr{tk, msg}) + continue + } + } } for _, stream := range importStreams { ta := am[stream.an] @@ -2284,14 +3587,14 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er *errors = append(*errors, &configErr{tk, msg}) continue } - if stream.pre != "" { - if err := stream.acc.AddStreamImport(ta, stream.sub, stream.pre); err != nil { + if stream.pre != _EMPTY_ { + if err := stream.acc.addStreamImportWithClaim(ta, stream.sub, stream.pre, stream.atrc, nil); err != nil { msg := fmt.Sprintf("Error adding stream import %q: %v", stream.sub, err) *errors = append(*errors, &configErr{tk, msg}) continue } } else { - if err := stream.acc.AddMappedStreamImport(ta, stream.sub, stream.to); err != nil { + if err := stream.acc.addMappedStreamImportWithClaim(ta, stream.sub, stream.to, stream.atrc, nil); err != nil { msg := fmt.Sprintf("Error adding stream import %q: %v", stream.sub, err) *errors = append(*errors, &configErr{tk, msg}) continue @@ -2305,7 +3608,7 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er *errors = append(*errors, &configErr{tk, msg}) continue } - if service.to == "" { + if service.to == _EMPTY_ { service.to = service.sub } if err := service.acc.AddServiceImport(ta, service.to, service.sub); err != nil { @@ -2324,13 +3627,13 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } // Parse the account exports -func parseAccountExports(v interface{}, acc *Account, errors, warnings *[]error) ([]*export, []*export, error) { +func parseAccountExports(v any, acc *Account, errors *[]error) ([]*export, []*export, error) { var lt token defer convertPanicToErrorList(<, errors) // This should be an array of objects/maps. tk, v := unwrapValue(v, <) - ims, ok := v.([]interface{}) + ims, ok := v.([]any) if !ok { return nil, nil, &configErr{tk, fmt.Sprintf("Exports should be an array, got %T", v)} } @@ -2340,7 +3643,7 @@ func parseAccountExports(v interface{}, acc *Account, errors, warnings *[]error) for _, v := range ims { // Should have stream or service - stream, service, err := parseExportStreamOrService(v, errors, warnings) + stream, service, err := parseExportStreamOrService(v, errors) if err != nil { *errors = append(*errors, err) continue @@ -2358,39 +3661,44 @@ func parseAccountExports(v interface{}, acc *Account, errors, warnings *[]error) } // Parse the account imports -func parseAccountImports(v interface{}, acc *Account, errors, warnings *[]error) ([]*importStream, []*importService, error) { +func parseAccountImports(v any, acc *Account, errors *[]error) ([]*importStream, []*importService, error) { var lt token defer convertPanicToErrorList(<, errors) // This should be an array of objects/maps. tk, v := unwrapValue(v, <) - ims, ok := v.([]interface{}) + ims, ok := v.([]any) if !ok { return nil, nil, &configErr{tk, fmt.Sprintf("Imports should be an array, got %T", v)} } var services []*importService var streams []*importStream - svcSubjects := map[string]*importService{} + svcSubjects := map[string][]*importService{} +IMS_LOOP: for _, v := range ims { // Should have stream or service - stream, service, err := parseImportStreamOrService(v, errors, warnings) + stream, service, err := parseImportStreamOrService(v, errors) if err != nil { *errors = append(*errors, err) continue } if service != nil { - if dup := svcSubjects[service.to]; dup != nil { - tk, _ := unwrapValue(v, <) - err := &configErr{tk, - fmt.Sprintf("Duplicate service import subject %q, previously used in import for account %q, subject %q", - service.to, dup.an, dup.sub)} - *errors = append(*errors, err) - continue + sisPerSubj := svcSubjects[service.to] + for _, dup := range sisPerSubj { + if dup.an == service.an { + tk, _ := unwrapValue(v, <) + err := &configErr{tk, + fmt.Sprintf("Duplicate service import subject %q, previously used in import for account %q, subject %q", + service.to, dup.an, dup.sub)} + *errors = append(*errors, err) + continue IMS_LOOP + } } - svcSubjects[service.to] = service service.acc = acc + sisPerSubj = append(sisPerSubj, service) + svcSubjects[service.to] = sisPerSubj services = append(services, service) } if stream != nil { @@ -2402,7 +3710,7 @@ func parseAccountImports(v interface{}, acc *Account, errors, warnings *[]error) } // Helper to parse an embedded account description for imported services or streams. -func parseAccount(v map[string]interface{}, errors, warnings *[]error) (string, string, error) { +func parseAccount(v map[string]any, errors *[]error) (string, string, error) { var lt token defer convertPanicToErrorList(<, errors) @@ -2431,11 +3739,11 @@ func parseAccount(v map[string]interface{}, errors, warnings *[]error) (string, // Parse an export stream or service. // e.g. -// {stream: "public.>"} # No accounts means public. -// {stream: "synadia.private.>", accounts: [cncf, natsio]} -// {service: "pub.request"} # No accounts means public. -// {service: "pub.special.request", accounts: [nats.io]} -func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*export, *export, error) { +// {stream: "public.>"} # No accounts means public. +// {stream: "synadia.private.>", accounts: [cncf, natsio]} +// {service: "pub.request"} # No accounts means public. +// {service: "pub.special.request", accounts: [nats.io]} +func parseExportStreamOrService(v any, errors *[]error) (*export, *export, error) { var ( curStream *export curService *export @@ -2448,11 +3756,15 @@ func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*expo thresh time.Duration latToken token lt token + accTokPos uint + atrc bool + atrcSeen bool + atrcToken token ) defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - vv, ok := v.(map[string]interface{}) + vv, ok := v.(map[string]any) if !ok { return nil, nil, &configErr{tk, fmt.Sprintf("Export Items should be a map with type entry, got %T", v)} } @@ -2475,6 +3787,11 @@ func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*expo *errors = append(*errors, err) continue } + if atrcToken != nil { + err := &configErr{atrcToken, "Detected allow_trace directive on non-service"} + *errors = append(*errors, err) + continue + } mvs, ok := mv.(string) if !ok { err := &configErr{tk, fmt.Sprintf("Expected stream name to be string, got %T", mv)} @@ -2510,6 +3827,9 @@ func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*expo if threshSeen { curService.rthr = thresh } + if atrcSeen { + curService.atrc = atrc + } case "response", "response_type": if rtSeen { err := &configErr{tk, "Duplicate response type definition"} @@ -2571,7 +3891,7 @@ func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*expo *errors = append(*errors, err) } case "accounts": - for _, iv := range mv.([]interface{}) { + for _, iv := range mv.([]any) { _, mv := unwrapValue(iv, <) accounts = append(accounts, mv.(string)) } @@ -2596,6 +3916,20 @@ func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*expo if curService != nil { curService.lat = lat } + case "account_token_position": + accTokPos = uint(mv.(int64)) + case "allow_trace": + atrcSeen = true + atrcToken = tk + atrc = mv.(bool) + if curStream != nil { + *errors = append(*errors, + &configErr{tk, "Detected allow_trace directive on non-service"}) + continue + } + if curService != nil { + curService.atrc = atrc + } default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -2608,11 +3942,17 @@ func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*expo } } } + if curStream != nil { + curStream.tPos = accTokPos + } + if curService != nil { + curService.tPos = accTokPos + } return curStream, curService, nil } // parseServiceLatency returns a latency config block. -func parseServiceLatency(root token, v interface{}) (l *serviceLatency, retErr error) { +func parseServiceLatency(root token, v any) (l *serviceLatency, retErr error) { var lt token defer convertPanicToError(<, &retErr) @@ -2623,7 +3963,7 @@ func parseServiceLatency(root token, v interface{}) (l *serviceLatency, retErr e }, nil } - latency, ok := v.(map[string]interface{}) + latency, ok := v.(map[string]any) if !ok { return nil, &configErr{token: root, reason: fmt.Sprintf("Expected latency entry to be a map/struct or string, got %T", v)} @@ -2690,21 +4030,24 @@ func parseServiceLatency(root token, v interface{}) (l *serviceLatency, retErr e // Parse an import stream or service. // e.g. -// {stream: {account: "synadia", subject:"public.synadia"}, prefix: "imports.synadia"} -// {stream: {account: "synadia", subject:"synadia.private.*"}} -// {service: {account: "synadia", subject: "pub.special.request"}, to: "synadia.request"} -func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*importStream, *importService, error) { +// {stream: {account: "synadia", subject:"public.synadia"}, prefix: "imports.synadia"} +// {stream: {account: "synadia", subject:"synadia.private.*"}} +// {service: {account: "synadia", subject: "pub.special.request"}, to: "synadia.request"} +func parseImportStreamOrService(v any, errors *[]error) (*importStream, *importService, error) { var ( curStream *importStream curService *importService pre, to string share bool lt token + atrc bool + atrcSeen bool + atrcToken token ) defer convertPanicToErrorList(<, errors) tk, mv := unwrapValue(v, <) - vv, ok := mv.(map[string]interface{}) + vv, ok := mv.(map[string]any) if !ok { return nil, nil, &configErr{tk, fmt.Sprintf("Import Items should be a map with type entry, got %T", mv)} } @@ -2717,55 +4060,63 @@ func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*impo *errors = append(*errors, err) continue } - ac, ok := mv.(map[string]interface{}) + ac, ok := mv.(map[string]any) if !ok { err := &configErr{tk, fmt.Sprintf("Stream entry should be an account map, got %T", mv)} *errors = append(*errors, err) continue } // Make sure this is a map with account and subject - accountName, subject, err := parseAccount(ac, errors, warnings) + accountName, subject, err := parseAccount(ac, errors) if err != nil { *errors = append(*errors, err) continue } - if accountName == "" || subject == "" { + if accountName == _EMPTY_ || subject == _EMPTY_ { err := &configErr{tk, "Expect an account name and a subject"} *errors = append(*errors, err) continue } curStream = &importStream{an: accountName, sub: subject} - if to != "" { + if to != _EMPTY_ { curStream.to = to } - if pre != "" { + if pre != _EMPTY_ { curStream.pre = pre } + if atrcSeen { + curStream.atrc = atrc + } case "service": if curStream != nil { err := &configErr{tk, "Detected service but already saw a stream"} *errors = append(*errors, err) continue } - ac, ok := mv.(map[string]interface{}) + if atrcToken != nil { + err := &configErr{atrcToken, "Detected allow_trace directive on a non-stream"} + *errors = append(*errors, err) + continue + } + ac, ok := mv.(map[string]any) if !ok { err := &configErr{tk, fmt.Sprintf("Service entry should be an account map, got %T", mv)} *errors = append(*errors, err) continue } // Make sure this is a map with account and subject - accountName, subject, err := parseAccount(ac, errors, warnings) + accountName, subject, err := parseAccount(ac, errors) if err != nil { *errors = append(*errors, err) continue } - if accountName == "" || subject == "" { + if accountName == _EMPTY_ || subject == _EMPTY_ { err := &configErr{tk, "Expect an account name and a subject"} *errors = append(*errors, err) continue } curService = &importService{an: accountName, sub: subject} - if to != "" { + if to != _EMPTY_ { curService.to = to } else { curService.to = subject @@ -2783,7 +4134,7 @@ func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*impo } if curStream != nil { curStream.to = to - if curStream.pre != "" { + if curStream.pre != _EMPTY_ { err := &configErr{tk, "Stream import can not have a 'prefix' and a 'to' property"} *errors = append(*errors, err) continue @@ -2794,6 +4145,18 @@ func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*impo if curService != nil { curService.share = share } + case "allow_trace": + if curService != nil { + err := &configErr{tk, "Detected allow_trace directive on a non-stream"} + *errors = append(*errors, err) + continue + } + atrcSeen = true + atrc = mv.(bool) + atrcToken = tk + if curStream != nil { + curStream.atrc = atrc + } default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -2828,9 +4191,9 @@ func applyDefaultPermissions(users []*User, nkeys []*NkeyUser, defaultP *Permiss } // Helper function to parse Authorization configs. -func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings *[]error) (*authorization, error) { +func parseAuthorization(v any, errors, warnings *[]error) (*authorization, error) { var ( - am map[string]interface{} + am map[string]any tk token lt token auth = &authorization{} @@ -2838,7 +4201,7 @@ func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings defer convertPanicToErrorList(<, errors) _, v = unwrapValue(v, <) - am = v.(map[string]interface{}) + am = v.(map[string]any) for mk, mv := range am { tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { @@ -2849,16 +4212,28 @@ func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings case "token": auth.token = mv.(string) case "timeout": - at := float64(1) + at := float64(0) switch mv := mv.(type) { case int64: at = float64(mv) case float64: at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf("error parsing authorization config, 'timeout' %s", err)} + } + at = d.Seconds() + default: + return nil, &configErr{tk, "error parsing authorization config, 'timeout' wrong type"} + } + if at > (60 * time.Second).Seconds() { + reason := fmt.Sprintf("timeout of %v (%f seconds) is high, consider keeping it under 60 seconds. possibly caused by unquoted duration; use '1m' instead of 1m, for example", mv, at) + *warnings = append(*warnings, &configWarningErr{field: mk, configErr: configErr{token: tk, reason: reason}}) } auth.timeout = at case "users": - nkeys, users, err := parseUsers(tk, opts, errors, warnings) + nkeys, users, err := parseUsers(tk, errors) if err != nil { *errors = append(*errors, err) continue @@ -2866,12 +4241,23 @@ func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings auth.users = users auth.nkeys = nkeys case "default_permission", "default_permissions", "permissions": - permissions, err := parseUserPermissions(tk, errors, warnings) + permissions, err := parseUserPermissions(tk, errors) if err != nil { *errors = append(*errors, err) continue } auth.defaultPermissions = permissions + case "auth_callout", "auth_hook": + if fips140.Enabled() { + *errors = append(*errors, fmt.Errorf("'auth_callout' cannot be configured in FIPS-140 mode")) + continue + } + ac, err := parseAuthCallout(tk, errors) + if err != nil { + *errors = append(*errors, err) + continue + } + auth.callout = ac default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -2891,7 +4277,7 @@ func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings } // Helper function to parse multiple users array with optional permissions. -func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]error) ([]*NkeyUser, []*User, error) { +func parseUsers(mv any, errors *[]error) ([]*NkeyUser, []*User, error) { var ( tk token lt token @@ -2902,7 +4288,7 @@ func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]erro tk, mv = unwrapValue(mv, <) // Make sure we have an array - uv, ok := mv.([]interface{}) + uv, ok := mv.([]any) if !ok { return nil, nil, &configErr{tk, fmt.Sprintf("Expected users field to be an array, got %v", mv)} } @@ -2910,7 +4296,7 @@ func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]erro tk, u = unwrapValue(u, <) // Check its a map/struct - um, ok := u.(map[string]interface{}) + um, ok := u.(map[string]any) if !ok { err := &configErr{tk, fmt.Sprintf("Expected user entry to be a map/struct, got %v", u)} *errors = append(*errors, err) @@ -2935,13 +4321,13 @@ func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]erro case "pass", "password": user.Password = v.(string) case "permission", "permissions", "authorization": - perms, err = parseUserPermissions(tk, errors, warnings) + perms, err = parseUserPermissions(tk, errors) if err != nil { *errors = append(*errors, err) continue } case "allowed_connection_types", "connection_types", "clients": - cts := parseAllowedConnectionTypes(tk, <, v, errors, warnings) + cts := parseAllowedConnectionTypes(tk, <, v, errors) nkey.AllowedConnectionTypes = cts user.AllowedConnectionTypes = cts default: @@ -2960,7 +4346,7 @@ func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]erro // Place perms if we have them. if perms != nil { // nkey takes precedent. - if nkey.Nkey != "" { + if nkey.Nkey != _EMPTY_ { nkey.Permissions = perms } else { user.Permissions = perms @@ -2968,15 +4354,15 @@ func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]erro } // Check to make sure we have at least an nkey or username defined. - if nkey.Nkey == "" && user.Username == "" { + if nkey.Nkey == _EMPTY_ && user.Username == _EMPTY_ { return nil, nil, &configErr{tk, "User entry requires a user"} - } else if nkey.Nkey != "" { + } else if nkey.Nkey != _EMPTY_ { // Make sure the nkey a proper public nkey for a user.. if !nkeys.IsValidPublicUserKey(nkey.Nkey) { return nil, nil, &configErr{tk, "Not a valid public nkey for a user"} } // If we have user or password defined here that is an error. - if user.Username != "" || user.Password != "" { + if user.Username != _EMPTY_ || user.Password != _EMPTY_ { return nil, nil, &configErr{tk, "Nkey users do not take usernames or passwords"} } keys = append(keys, nkey) @@ -2987,8 +4373,8 @@ func parseUsers(mv interface{}, opts *Options, errors *[]error, warnings *[]erro return keys, users, nil } -func parseAllowedConnectionTypes(tk token, lt *token, mv interface{}, errors *[]error, warnings *[]error) map[string]struct{} { - cts, err := parseStringArray("allowed connection types", tk, lt, mv, errors, warnings) +func parseAllowedConnectionTypes(tk token, lt *token, mv any, errors *[]error) map[string]struct{} { + cts, err := parseStringArray("allowed connection types", tk, lt, mv, errors) // If error, it has already been added to the `errors` array, simply return if err != nil { return nil @@ -3000,8 +4386,77 @@ func parseAllowedConnectionTypes(tk token, lt *token, mv interface{}, errors *[] return m } +// Helper function to parse auth callouts. +func parseAuthCallout(mv any, errors *[]error) (*AuthCallout, error) { + var ( + tk token + lt token + ac = &AuthCallout{} + ) + defer convertPanicToErrorList(<, errors) + + tk, mv = unwrapValue(mv, <) + pm, ok := mv.(map[string]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf("Expected authorization callout to be a map/struct, got %+v", mv)} + } + for k, v := range pm { + tk, mv = unwrapValue(v, <) + + switch strings.ToLower(k) { + case "issuer": + ac.Issuer = mv.(string) + if !nkeys.IsValidPublicAccountKey(ac.Issuer) { + return nil, &configErr{tk, fmt.Sprintf("Expected callout user to be a valid public account nkey, got %q", ac.Issuer)} + } + case "account", "acc": + ac.Account = mv.(string) + case "auth_users", "users": + aua, ok := mv.([]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf("Expected auth_users field to be an array, got %T", v)} + } + for _, uv := range aua { + _, uv = unwrapValue(uv, <) + ac.AuthUsers = append(ac.AuthUsers, uv.(string)) + } + case "xkey", "key": + ac.XKey = mv.(string) + if !nkeys.IsValidPublicCurveKey(ac.XKey) { + return nil, &configErr{tk, fmt.Sprintf("Expected callout xkey to be a valid public xkey, got %q", ac.XKey)} + } + case "allowed_accounts": + aua, ok := mv.([]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf("Expected allowed accounts field to be an array, got %T", v)} + } + for _, uv := range aua { + _, uv = unwrapValue(uv, <) + ac.AllowedAccounts = append(ac.AllowedAccounts, uv.(string)) + } + default: + if !tk.IsUsedVariable() { + err := &configErr{tk, fmt.Sprintf("Unknown field %q parsing authorization callout", k)} + *errors = append(*errors, err) + } + } + } + // Make sure we have all defined. All fields are required. + // If no account specified, selet $G. + if ac.Account == _EMPTY_ { + ac.Account = globalAccountName + } + if ac.Issuer == _EMPTY_ { + return nil, &configErr{tk, "Authorization callouts require an issuer to be specified"} + } + if len(ac.AuthUsers) == 0 { + return nil, &configErr{tk, "Authorization callouts require authorized users to be specified"} + } + return ac, nil +} + // Helper function to parse user/account permissions -func parseUserPermissions(mv interface{}, errors, warnings *[]error) (*Permissions, error) { +func parseUserPermissions(mv any, errors *[]error) (*Permissions, error) { var ( tk token lt token @@ -3010,7 +4465,7 @@ func parseUserPermissions(mv interface{}, errors, warnings *[]error) (*Permissio defer convertPanicToErrorList(<, errors) tk, mv = unwrapValue(mv, <) - pm, ok := mv.(map[string]interface{}) + pm, ok := mv.(map[string]any) if !ok { return nil, &configErr{tk, fmt.Sprintf("Expected permissions to be a map/struct, got %+v", mv)} } @@ -3022,14 +4477,14 @@ func parseUserPermissions(mv interface{}, errors, warnings *[]error) (*Permissio // Import is Publish // Export is Subscribe case "pub", "publish", "import": - perms, err := parseVariablePermissions(mv, errors, warnings) + perms, err := parseVariablePermissions(mv, errors) if err != nil { *errors = append(*errors, err) continue } p.Publish = perms case "sub", "subscribe", "export": - perms, err := parseVariablePermissions(mv, errors, warnings) + perms, err := parseVariablePermissions(mv, errors) if err != nil { *errors = append(*errors, err) continue @@ -3047,7 +4502,7 @@ func parseUserPermissions(mv interface{}, errors, warnings *[]error) (*Permissio p.Response = rp } } else { - p.Response = parseAllowResponses(v, errors, warnings) + p.Response = parseAllowResponses(v, errors) } if p.Response != nil { if p.Publish == nil { @@ -3069,19 +4524,19 @@ func parseUserPermissions(mv interface{}, errors, warnings *[]error) (*Permissio } // Top level parser for authorization configurations. -func parseVariablePermissions(v interface{}, errors, warnings *[]error) (*SubjectPermission, error) { +func parseVariablePermissions(v any, errors *[]error) (*SubjectPermission, error) { switch vv := v.(type) { - case map[string]interface{}: + case map[string]any: // New style with allow and/or deny properties. - return parseSubjectPermission(vv, errors, warnings) + return parseSubjectPermission(vv, errors) default: // Old style - return parseOldPermissionStyle(v, errors, warnings) + return parseOldPermissionStyle(v, errors) } } // Helper function to parse subject singletons and/or arrays -func parseSubjects(v interface{}, errors, warnings *[]error) ([]string, error) { +func parsePermSubjects(v any, errors *[]error) ([]string, error) { var lt token defer convertPanicToErrorList(<, errors) @@ -3093,7 +4548,7 @@ func parseSubjects(v interface{}, errors, warnings *[]error) ([]string, error) { subjects = append(subjects, vv) case []string: subjects = vv - case []interface{}: + case []any: for _, i := range vv { tk, i := unwrapValue(i, <) @@ -3106,20 +4561,20 @@ func parseSubjects(v interface{}, errors, warnings *[]error) ([]string, error) { default: return nil, &configErr{tk, fmt.Sprintf("Expected subject permissions to be a subject, or array of subjects, got %T", v)} } - if err := checkSubjectArray(subjects); err != nil { + if err := checkPermSubjectArray(subjects); err != nil { return nil, &configErr{tk, err.Error()} } return subjects, nil } // Helper function to parse a ResponsePermission. -func parseAllowResponses(v interface{}, errors, warnings *[]error) *ResponsePermission { +func parseAllowResponses(v any, errors *[]error) *ResponsePermission { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) // Check if this is a map. - pm, ok := v.(map[string]interface{}) + pm, ok := v.(map[string]any) if !ok { err := &configErr{tk, "error parsing response permissions, expected a boolean or a map"} *errors = append(*errors, err) @@ -3171,8 +4626,8 @@ func parseAllowResponses(v interface{}, errors, warnings *[]error) *ResponsePerm } // Helper function to parse old style authorization configs. -func parseOldPermissionStyle(v interface{}, errors, warnings *[]error) (*SubjectPermission, error) { - subjects, err := parseSubjects(v, errors, warnings) +func parseOldPermissionStyle(v any, errors *[]error) (*SubjectPermission, error) { + subjects, err := parsePermSubjects(v, errors) if err != nil { return nil, err } @@ -3180,11 +4635,11 @@ func parseOldPermissionStyle(v interface{}, errors, warnings *[]error) (*Subject } // Helper function to parse new style authorization into a SubjectPermission with Allow and Deny. -func parseSubjectPermission(v interface{}, errors, warnings *[]error) (*SubjectPermission, error) { +func parseSubjectPermission(v any, errors *[]error) (*SubjectPermission, error) { var lt token defer convertPanicToErrorList(<, errors) - m := v.(map[string]interface{}) + m := v.(map[string]any) if len(m) == 0 { return nil, nil } @@ -3193,14 +4648,14 @@ func parseSubjectPermission(v interface{}, errors, warnings *[]error) (*SubjectP tk, _ := unwrapValue(v, <) switch strings.ToLower(k) { case "allow": - subjects, err := parseSubjects(tk, errors, warnings) + subjects, err := parsePermSubjects(tk, errors) if err != nil { *errors = append(*errors, err) continue } p.Allow = subjects case "deny": - subjects, err := parseSubjects(tk, errors, warnings) + subjects, err := parsePermSubjects(tk, errors) if err != nil { *errors = append(*errors, err) continue @@ -3216,11 +4671,17 @@ func parseSubjectPermission(v interface{}, errors, warnings *[]error) (*SubjectP return p, nil } -// Helper function to validate subjects, etc for account permissioning. -func checkSubjectArray(sa []string) error { +// Helper function to validate permissions subjects. +func checkPermSubjectArray(sa []string) error { for _, s := range sa { if !IsValidSubject(s) { - return fmt.Errorf("subject %q is not a valid subject", s) + // Check here if this is a queue group qualified subject. + elements := strings.Fields(s) + if len(elements) != 2 { + return fmt.Errorf("subject %q is not a valid subject", s) + } else if !IsValidSubject(elements[0]) { + return fmt.Errorf("subject %q is not a valid subject", elements[0]) + } } } return nil @@ -3236,6 +4697,11 @@ func PrintTLSHelpAndDie() { for k := range curvePreferenceMap { fmt.Printf(" %s\n", k) } + if runtime.GOOS == "windows" { + fmt.Printf("%s\n", certstore.Usage) + } + fmt.Printf("%s", certidp.OCSPPeerUsage) + fmt.Printf("%s", OCSPResponseCacheUsage) os.Exit(0) } @@ -3256,17 +4722,35 @@ func parseCurvePreferences(curveName string) (tls.CurveID, error) { return curve, nil } +func parseTLSVersion(v any) (uint16, error) { + var tlsVersionNumber uint16 + switch v := v.(type) { + case string: + n, err := tlsVersionFromString(v) + if err != nil { + return 0, err + } + tlsVersionNumber = n + default: + return 0, fmt.Errorf("'min_version' wrong type: %v", v) + } + if tlsVersionNumber < tls.VersionTLS12 { + return 0, fmt.Errorf("unsupported TLS version: %s", tls.VersionName(tlsVersionNumber)) + } + return tlsVersionNumber, nil +} + // Helper function to parse TLS configs. -func parseTLS(v interface{}, isClientCtx bool) (t *TLSConfigOpts, retErr error) { +func parseTLS(v any, isClientCtx bool) (t *TLSConfigOpts, retErr error) { var ( - tlsm map[string]interface{} + tlsm map[string]any tc = TLSConfigOpts{} lt token ) defer convertPanicToError(<, &retErr) - _, v = unwrapValue(v, <) - tlsm = v.(map[string]interface{}) + tk, v := unwrapValue(v, <) + tlsm = v.(map[string]any) for mk, mv := range tlsm { tk, mv := unwrapValue(mv, <) switch strings.ToLower(mk) { @@ -3322,7 +4806,7 @@ func parseTLS(v interface{}, isClientCtx bool) (t *TLSConfigOpts, retErr error) } tc.TLSCheckKnownURLs = verify case "cipher_suites": - ra := mv.([]interface{}) + ra := mv.([]any) if len(ra) == 0 { return nil, &configErr{tk, "error parsing tls config, 'cipher_suites' cannot be empty"} } @@ -3336,7 +4820,7 @@ func parseTLS(v interface{}, isClientCtx bool) (t *TLSConfigOpts, retErr error) tc.Ciphers = append(tc.Ciphers, cipher) } case "curve_preferences": - ra := mv.([]interface{}) + ra := mv.([]any) if len(ra) == 0 { return nil, &configErr{tk, "error parsing tls config, 'curve_preferences' cannot be empty"} } @@ -3356,12 +4840,190 @@ func parseTLS(v interface{}, isClientCtx bool) (t *TLSConfigOpts, retErr error) at = float64(mv) case float64: at = mv + case string: + d, err := time.ParseDuration(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, 'timeout' %s", err)} + } + at = d.Seconds() + default: + return nil, &configErr{tk, "error parsing tls config, 'timeout' wrong type"} } tc.Timeout = at + case "connection_rate_limit": + at := int64(0) + switch mv := mv.(type) { + case int64: + at = mv + default: + return nil, &configErr{tk, "error parsing tls config, 'connection_rate_limit' wrong type"} + } + tc.RateLimit = at + case "pinned_certs": + ra, ok := mv.([]any) + if !ok { + return nil, &configErr{tk, "error parsing tls config, expected 'pinned_certs' to be a list of hex-encoded sha256 of DER encoded SubjectPublicKeyInfo"} + } + if len(ra) != 0 { + wl := PinnedCertSet{} + re := regexp.MustCompile("^[A-Fa-f0-9]{64}$") + for _, r := range ra { + tk, r := unwrapValue(r, <) + entry := strings.ToLower(r.(string)) + if !re.MatchString(entry) { + return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, 'pinned_certs' key %s does not look like hex-encoded sha256 of DER encoded SubjectPublicKeyInfo", entry)} + } + wl[entry] = struct{}{} + } + tc.PinnedCerts = wl + } + case "cert_store": + certStore, ok := mv.(string) + if !ok || certStore == _EMPTY_ { + return nil, &configErr{tk, certstore.ErrBadCertStoreField.Error()} + } + certStoreType, err := certstore.ParseCertStore(certStore) + if err != nil { + return nil, &configErr{tk, err.Error()} + } + tc.CertStore = certStoreType + case "cert_match_by": + certMatchBy, ok := mv.(string) + if !ok || certMatchBy == _EMPTY_ { + return nil, &configErr{tk, certstore.ErrBadCertMatchByField.Error()} + } + certMatchByType, err := certstore.ParseCertMatchBy(certMatchBy) + if err != nil { + return nil, &configErr{tk, err.Error()} + } + tc.CertMatchBy = certMatchByType + case "cert_match": + certMatch, ok := mv.(string) + if !ok || certMatch == _EMPTY_ { + return nil, &configErr{tk, certstore.ErrBadCertMatchField.Error()} + } + tc.CertMatch = certMatch + case "ca_certs_match": + rv := []string{} + switch mv := mv.(type) { + case string: + rv = append(rv, mv) + case []string: + rv = append(rv, mv...) + case []any: + for _, t := range mv { + if token, ok := t.(token); ok { + if ts, ok := token.Value().(string); ok { + rv = append(rv, ts) + continue + } else { + return nil, &configErr{tk, fmt.Sprintf("error parsing ca_cert_match: unsupported type %T where string is expected", token)} + } + } else { + return nil, &configErr{tk, fmt.Sprintf("error parsing ca_cert_match: unsupported type %T", t)} + } + } + } + tc.CaCertsMatch = rv + case "handshake_first", "first", "immediate": + switch mv := mv.(type) { + case bool: + tc.HandshakeFirst = mv + case string: + switch strings.ToLower(mv) { + case "true", "on": + tc.HandshakeFirst = true + case "false", "off": + tc.HandshakeFirst = false + case "auto", "auto_fallback": + tc.HandshakeFirst = true + tc.FallbackDelay = DEFAULT_TLS_HANDSHAKE_FIRST_FALLBACK_DELAY + default: + // Check to see if this is a duration. + if dur, err := time.ParseDuration(mv); err == nil { + tc.HandshakeFirst = true + tc.FallbackDelay = dur + break + } + return nil, &configErr{tk, fmt.Sprintf("field %q's value %q is invalid", mk, mv)} + } + default: + return nil, &configErr{tk, fmt.Sprintf("field %q should be a boolean or a string, got %T", mk, mv)} + } + case "cert_match_skip_invalid": + certMatchSkipInvalid, ok := mv.(bool) + if !ok { + return nil, &configErr{tk, certstore.ErrBadCertMatchSkipInvalidField.Error()} + } + tc.CertMatchSkipInvalid = certMatchSkipInvalid + case "ocsp_peer": + switch vv := mv.(type) { + case bool: + pc := certidp.NewOCSPPeerConfig() + if vv { + // Set enabled + pc.Verify = true + tc.OCSPPeerConfig = pc + } else { + // Set disabled + pc.Verify = false + tc.OCSPPeerConfig = pc + } + case map[string]any: + pc, err := parseOCSPPeer(mv) + if err != nil { + return nil, &configErr{tk, err.Error()} + } + tc.OCSPPeerConfig = pc + default: + return nil, &configErr{tk, fmt.Sprintf("error parsing ocsp peer config: unsupported type %T", v)} + } + case "certs", "certificates": + certs, ok := mv.([]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf("error parsing certificates config: unsupported type %T", v)} + } + tc.Certificates = make([]*TLSCertPairOpt, len(certs)) + for i, v := range certs { + tk, vv := unwrapValue(v, <) + pair, ok := vv.(map[string]any) + if !ok { + return nil, &configErr{tk, fmt.Sprintf("error parsing certificates config: unsupported type %T", vv)} + } + certPair := &TLSCertPairOpt{} + for k, v := range pair { + tk, vv = unwrapValue(v, <) + file, ok := vv.(string) + if !ok { + return nil, &configErr{tk, fmt.Sprintf("error parsing certificates config: unsupported type %T", vv)} + } + switch k { + case "cert_file": + certPair.CertFile = file + case "key_file": + certPair.KeyFile = file + default: + return nil, &configErr{tk, fmt.Sprintf("error parsing tls certs config, unknown field %q", k)} + } + } + if certPair.CertFile == _EMPTY_ || certPair.KeyFile == _EMPTY_ { + return nil, &configErr{tk, "error parsing certificates config: both 'cert_file' and 'cert_key' options are required"} + } + tc.Certificates[i] = certPair + } + case "min_version": + minVersion, err := parseTLSVersion(mv) + if err != nil { + return nil, &configErr{tk, fmt.Sprintf("error parsing tls config: %v", err)} + } + tc.MinVersion = minVersion default: - return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, unknown field [%q]", mk)} + return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, unknown field %q", mk)} } } + if len(tc.Certificates) > 0 && tc.CertFile != _EMPTY_ { + return nil, &configErr{tk, "error parsing tls config, cannot combine 'cert_file' option with 'certs' option"} + } // If cipher suites were not specified then use the defaults if tc.Ciphers == nil { @@ -3376,9 +5038,9 @@ func parseTLS(v interface{}, isClientCtx bool) (t *TLSConfigOpts, retErr error) return &tc, nil } -func parseSimpleAuth(v interface{}, errors *[]error, warnings *[]error) *authorization { +func parseSimpleAuth(v any, errors *[]error) *authorization { var ( - am map[string]interface{} + am map[string]any tk token lt token auth = &authorization{} @@ -3386,7 +5048,7 @@ func parseSimpleAuth(v interface{}, errors *[]error, warnings *[]error) *authori defer convertPanicToErrorList(<, errors) _, v = unwrapValue(v, <) - am = v.(map[string]interface{}) + am = v.(map[string]any) for mk, mv := range am { tk, mv = unwrapValue(mv, <) switch strings.ToLower(mk) { @@ -3421,11 +5083,11 @@ func parseSimpleAuth(v interface{}, errors *[]error, warnings *[]error) *authori return auth } -func parseStringArray(fieldName string, tk token, lt *token, mv interface{}, errors *[]error, warnings *[]error) ([]string, error) { +func parseStringArray(fieldName string, tk token, lt *token, mv any, errors *[]error) ([]string, error) { switch mv := mv.(type) { case string: return []string{mv}, nil - case []interface{}: + case []any: strs := make([]string, 0, len(mv)) for _, val := range mv { tk, val = unwrapValue(val, lt) @@ -3445,12 +5107,12 @@ func parseStringArray(fieldName string, tk token, lt *token, mv interface{}, err } } -func parseWebsocket(v interface{}, o *Options, errors *[]error, warnings *[]error) error { +func parseWebsocket(v any, o *Options, errors *[]error, warnings *[]error) error { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - gm, ok := v.(map[string]interface{}) + gm, ok := v.(map[string]any) if !ok { return &configErr{tk, fmt.Sprintf("Expected websocket to be a map, got %T", v)} } @@ -3487,10 +5149,12 @@ func parseWebsocket(v interface{}, o *Options, errors *[]error, warnings *[]erro continue } o.Websocket.TLSMap = tc.Map + o.Websocket.TLSPinnedCerts = tc.PinnedCerts + o.Websocket.tlsConfigOpts = tc case "same_origin": o.Websocket.SameOrigin = mv.(bool) case "allowed_origins", "allowed_origin", "allow_origins", "allow_origin", "origins", "origin": - o.Websocket.AllowedOrigins, _ = parseStringArray("allowed origins", tk, <, mv, errors, warnings) + o.Websocket.AllowedOrigins, _ = parseStringArray("allowed origins", tk, <, mv, errors) case "handshake_timeout": ht := time.Duration(0) switch mv := mv.(type) { @@ -3509,18 +5173,43 @@ func parseWebsocket(v interface{}, o *Options, errors *[]error, warnings *[]erro *errors = append(*errors, err) } o.Websocket.HandshakeTimeout = ht - case "compression": + case "compress", "compression": o.Websocket.Compression = mv.(bool) case "authorization", "authentication": - auth := parseSimpleAuth(tk, errors, warnings) + auth := parseSimpleAuth(tk, errors) o.Websocket.Username = auth.user o.Websocket.Password = auth.pass o.Websocket.Token = auth.token o.Websocket.AuthTimeout = auth.timeout case "jwt_cookie": o.Websocket.JWTCookie = mv.(string) + case "user_cookie": + o.Websocket.UsernameCookie = mv.(string) + case "pass_cookie": + o.Websocket.PasswordCookie = mv.(string) + case "token_cookie": + o.Websocket.TokenCookie = mv.(string) case "no_auth_user": o.Websocket.NoAuthUser = mv.(string) + case "headers": + m, ok := mv.(map[string]any) + if !ok { + err := &configErr{tk, fmt.Sprintf("error parsing headers: unsupported type %T", mv)} + *errors = append(*errors, err) + continue + } + o.Websocket.Headers = make(map[string]string) + for key, val := range m { + tk, val = unwrapValue(val, <) + if headerValue, ok := val.(string); !ok { + *errors = append(*errors, &configErr{tk, fmt.Sprintf("error parsing header key %s: unsupported type %T", key, val)}) + continue + } else { + o.Websocket.Headers[key] = headerValue + } + } + case "ping_interval": + o.Websocket.PingInterval = parseDuration("ping_interval", tk, mv, errors, warnings) default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -3537,12 +5226,12 @@ func parseWebsocket(v interface{}, o *Options, errors *[]error, warnings *[]erro return nil } -func parseMQTT(v interface{}, o *Options, errors *[]error, warnings *[]error) error { +func parseMQTT(v any, o *Options, errors *[]error, warnings *[]error) error { var lt token defer convertPanicToErrorList(<, errors) tk, v := unwrapValue(v, <) - gm, ok := v.(map[string]interface{}) + gm, ok := v.(map[string]any) if !ok { return &configErr{tk, fmt.Sprintf("Expected mqtt to be a map, got %T", v)} } @@ -3576,8 +5265,10 @@ func parseMQTT(v interface{}, o *Options, errors *[]error, warnings *[]error) er } o.MQTT.TLSTimeout = tc.Timeout o.MQTT.TLSMap = tc.Map + o.MQTT.TLSPinnedCerts = tc.PinnedCerts + o.MQTT.tlsConfigOpts = tc case "authorization", "authentication": - auth := parseSimpleAuth(tk, errors, warnings) + auth := parseSimpleAuth(tk, errors) o.MQTT.Username = auth.user o.MQTT.Password = auth.pass o.MQTT.Token = auth.token @@ -3586,6 +5277,8 @@ func parseMQTT(v interface{}, o *Options, errors *[]error, warnings *[]error) er o.MQTT.NoAuthUser = mv.(string) case "ack_wait", "ackwait": o.MQTT.AckWait = parseDuration("ack_wait", tk, mv, errors, warnings) + case "js_api_timeout", "api_timeout": + o.MQTT.JSAPITimeout = parseDuration("js_api_timeout", tk, mv, errors, warnings) case "max_ack_pending", "max_pending", "max_inflight": tmp := int(mv.(int64)) if tmp < 0 || tmp > 0xFFFF { @@ -3594,6 +5287,29 @@ func parseMQTT(v interface{}, o *Options, errors *[]error, warnings *[]error) er } else { o.MQTT.MaxAckPending = uint16(tmp) } + case "js_domain": + o.MQTT.JsDomain = mv.(string) + case "stream_replicas": + o.MQTT.StreamReplicas = int(mv.(int64)) + case "consumer_replicas": + err := &configWarningErr{ + field: mk, + configErr: configErr{ + token: tk, + reason: `consumer replicas setting ignored in this server version`, + }, + } + *warnings = append(*warnings, err) + case "consumer_memory_storage": + o.MQTT.ConsumerMemoryStorage = mv.(bool) + case "consumer_inactive_threshold", "consumer_auto_cleanup": + o.MQTT.ConsumerInactiveThreshold = parseDuration("consumer_inactive_threshold", tk, mv, errors, warnings) + + case "reject_qos2_publish": + o.MQTT.rejectQoS2Pub = mv.(bool) + case "downgrade_qos2_subscribe": + o.MQTT.downgradeQoS2Sub = mv.(bool) + default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -3624,11 +5340,13 @@ func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) { } switch { - case tc.CertFile != "" && tc.KeyFile == "": + case tc.CertFile != _EMPTY_ && tc.CertStore != certstore.STOREEMPTY: + return nil, certstore.ErrConflictCertFileAndStore + case tc.CertFile != _EMPTY_ && tc.KeyFile == _EMPTY_: return nil, fmt.Errorf("missing 'key_file' in TLS configuration") - case tc.CertFile == "" && tc.KeyFile != "": + case tc.CertFile == _EMPTY_ && tc.KeyFile != _EMPTY_: return nil, fmt.Errorf("missing 'cert_file' in TLS configuration") - case tc.CertFile != "" && tc.KeyFile != "": + case tc.CertFile != _EMPTY_ && tc.KeyFile != _EMPTY_: // Now load in cert and private key cert, err := tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile) if err != nil { @@ -3639,6 +5357,25 @@ func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) { return nil, fmt.Errorf("error parsing certificate: %v", err) } config.Certificates = []tls.Certificate{cert} + case tc.CertStore != certstore.STOREEMPTY: + err := certstore.TLSConfig(tc.CertStore, tc.CertMatchBy, tc.CertMatch, tc.CaCertsMatch, tc.CertMatchSkipInvalid, &config) + if err != nil { + return nil, err + } + case tc.Certificates != nil: + // Multiple certificate support. + config.Certificates = make([]tls.Certificate, len(tc.Certificates)) + for i, certPair := range tc.Certificates { + cert, err := tls.LoadX509KeyPair(certPair.CertFile, certPair.KeyFile) + if err != nil { + return nil, fmt.Errorf("error parsing X509 certificate/key pair %d/%d: %v", i+1, len(tc.Certificates), err) + } + cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return nil, fmt.Errorf("error parsing certificate %d/%d: %v", i+1, len(tc.Certificates), err) + } + config.Certificates[i] = cert + } } // Require client certificates as needed @@ -3646,8 +5383,8 @@ func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) { config.ClientAuth = tls.RequireAndVerifyClientCert } // Add in CAs if applicable. - if tc.CaFile != "" { - rootPEM, err := ioutil.ReadFile(tc.CaFile) + if tc.CaFile != _EMPTY_ { + rootPEM, err := os.ReadFile(tc.CaFile) if err != nil || rootPEM == nil { return nil, err } @@ -3658,6 +5395,13 @@ func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) { } config.ClientCAs = pool } + // Allow setting TLS minimum version. + if tc.MinVersion > 0 { + if tc.MinVersion < tls.VersionTLS12 { + return nil, fmt.Errorf("unsupported minimum TLS version: %s", tls.VersionName(tc.MinVersion)) + } + config.MinVersion = tc.MinVersion + } return &config, nil } @@ -3677,25 +5421,28 @@ func MergeOptions(fileOpts, flagOpts *Options) *Options { if flagOpts.Port != 0 { opts.Port = flagOpts.Port } - if flagOpts.Host != "" { + if flagOpts.Host != _EMPTY_ { opts.Host = flagOpts.Host } - if flagOpts.ClientAdvertise != "" { + if flagOpts.DontListen { + opts.DontListen = flagOpts.DontListen + } + if flagOpts.ClientAdvertise != _EMPTY_ { opts.ClientAdvertise = flagOpts.ClientAdvertise } - if flagOpts.Username != "" { + if flagOpts.Username != _EMPTY_ { opts.Username = flagOpts.Username } - if flagOpts.Password != "" { + if flagOpts.Password != _EMPTY_ { opts.Password = flagOpts.Password } - if flagOpts.Authorization != "" { + if flagOpts.Authorization != _EMPTY_ { opts.Authorization = flagOpts.Authorization } if flagOpts.HTTPPort != 0 { opts.HTTPPort = flagOpts.HTTPPort } - if flagOpts.HTTPBasePath != "" { + if flagOpts.HTTPBasePath != _EMPTY_ { opts.HTTPBasePath = flagOpts.HTTPBasePath } if flagOpts.Debug { @@ -3707,19 +5454,19 @@ func MergeOptions(fileOpts, flagOpts *Options) *Options { if flagOpts.Logtime { opts.Logtime = true } - if flagOpts.LogFile != "" { + if flagOpts.LogFile != _EMPTY_ { opts.LogFile = flagOpts.LogFile } - if flagOpts.PidFile != "" { + if flagOpts.PidFile != _EMPTY_ { opts.PidFile = flagOpts.PidFile } - if flagOpts.PortsFileDir != "" { + if flagOpts.PortsFileDir != _EMPTY_ { opts.PortsFileDir = flagOpts.PortsFileDir } if flagOpts.ProfPort != 0 { opts.ProfPort = flagOpts.ProfPort } - if flagOpts.Cluster.ListenStr != "" { + if flagOpts.Cluster.ListenStr != _EMPTY_ { opts.Cluster.ListenStr = flagOpts.Cluster.ListenStr } if flagOpts.Cluster.NoAdvertise { @@ -3728,12 +5475,18 @@ func MergeOptions(fileOpts, flagOpts *Options) *Options { if flagOpts.Cluster.ConnectRetries != 0 { opts.Cluster.ConnectRetries = flagOpts.Cluster.ConnectRetries } - if flagOpts.Cluster.Advertise != "" { + if flagOpts.Cluster.Advertise != _EMPTY_ { opts.Cluster.Advertise = flagOpts.Cluster.Advertise } - if flagOpts.RoutesStr != "" { + if flagOpts.RoutesStr != _EMPTY_ { mergeRoutes(&opts, flagOpts) } + if flagOpts.JetStream { + opts.JetStream = flagOpts.JetStream + } + if flagOpts.StoreDir != _EMPTY_ { + opts.StoreDir = flagOpts.StoreDir + } return &opts } @@ -3762,92 +5515,12 @@ func mergeRoutes(opts, flagOpts *Options) { opts.RoutesStr = flagOpts.RoutesStr } -// RemoveSelfReference removes this server from an array of routes -func RemoveSelfReference(clusterPort int, routes []*url.URL) ([]*url.URL, error) { - var cleanRoutes []*url.URL - cport := strconv.Itoa(clusterPort) - - selfIPs, err := getInterfaceIPs() - if err != nil { - return nil, err - } - for _, r := range routes { - host, port, err := net.SplitHostPort(r.Host) - if err != nil { - return nil, err - } - - ipList, err := getURLIP(host) - if err != nil { - return nil, err - } - if cport == port && isIPInList(selfIPs, ipList) { - continue - } - cleanRoutes = append(cleanRoutes, r) - } - - return cleanRoutes, nil -} - -func isIPInList(list1 []net.IP, list2 []net.IP) bool { - for _, ip1 := range list1 { - for _, ip2 := range list2 { - if ip1.Equal(ip2) { - return true - } - } - } - return false -} - -func getURLIP(ipStr string) ([]net.IP, error) { - ipList := []net.IP{} - - ip := net.ParseIP(ipStr) - if ip != nil { - ipList = append(ipList, ip) - return ipList, nil - } - - hostAddr, err := net.LookupHost(ipStr) - if err != nil { - return nil, fmt.Errorf("Error looking up host with route hostname: %v", err) - } - for _, addr := range hostAddr { - ip = net.ParseIP(addr) - if ip != nil { - ipList = append(ipList, ip) - } - } - return ipList, nil -} - -func getInterfaceIPs() ([]net.IP, error) { - var localIPs []net.IP - - interfaceAddr, err := net.InterfaceAddrs() - if err != nil { - return nil, fmt.Errorf("Error getting self referencing address: %v", err) - } - - for i := 0; i < len(interfaceAddr); i++ { - interfaceIP, _, _ := net.ParseCIDR(interfaceAddr[i].String()) - if net.ParseIP(interfaceIP.String()) != nil { - localIPs = append(localIPs, interfaceIP) - } else { - return nil, fmt.Errorf("Error parsing self referencing address: %v", err) - } - } - return localIPs, nil -} - func setBaselineOptions(opts *Options) { // Setup non-standard Go defaults - if opts.Host == "" { + if opts.Host == _EMPTY_ { opts.Host = DEFAULT_HOST } - if opts.HTTPHost == "" { + if opts.HTTPHost == _EMPTY_ { // Default to same bind from server if left undefined opts.HTTPHost = opts.Host } @@ -3872,8 +5545,8 @@ func setBaselineOptions(opts *Options) { if opts.AuthTimeout == 0 { opts.AuthTimeout = getDefaultAuthTimeout(opts.TLSConfig, opts.TLSTimeout) } - if opts.Cluster.Port != 0 { - if opts.Cluster.Host == "" { + if opts.Cluster.Port != 0 || opts.Cluster.ListenStr != _EMPTY_ { + if opts.Cluster.Host == _EMPTY_ { opts.Cluster.Host = DEFAULT_HOST } if opts.Cluster.TLSTimeout == 0 { @@ -3882,9 +5555,43 @@ func setBaselineOptions(opts *Options) { if opts.Cluster.AuthTimeout == 0 { opts.Cluster.AuthTimeout = getDefaultAuthTimeout(opts.Cluster.TLSConfig, opts.Cluster.TLSTimeout) } + if opts.Cluster.PoolSize == 0 { + opts.Cluster.PoolSize = DEFAULT_ROUTE_POOL_SIZE + } + // Unless pooling/accounts are disabled (by PoolSize being set to -1), + // check for Cluster.Accounts. Add the system account if not present and + // unless we have a configuration that disabled it. + if opts.Cluster.PoolSize > 0 { + sysAccName := opts.SystemAccount + if sysAccName == _EMPTY_ && !opts.NoSystemAccount { + sysAccName = DEFAULT_SYSTEM_ACCOUNT + } + if sysAccName != _EMPTY_ { + var found bool + for _, acc := range opts.Cluster.PinnedAccounts { + if acc == sysAccName { + found = true + break + } + } + if !found { + opts.Cluster.PinnedAccounts = append(opts.Cluster.PinnedAccounts, sysAccName) + } + } + } + // Default to compression "accept", which means that compression is not + // initiated, but if the remote selects compression, this server will + // use the same. + if c := &opts.Cluster.Compression; c.Mode == _EMPTY_ { + if testDefaultClusterCompression != _EMPTY_ { + c.Mode = testDefaultClusterCompression + } else { + c.Mode = CompressionAccept + } + } } if opts.LeafNode.Port != 0 { - if opts.LeafNode.Host == "" { + if opts.LeafNode.Host == _EMPTY_ { opts.LeafNode.Host = DEFAULT_HOST } if opts.LeafNode.TLSTimeout == 0 { @@ -3893,15 +5600,35 @@ func setBaselineOptions(opts *Options) { if opts.LeafNode.AuthTimeout == 0 { opts.LeafNode.AuthTimeout = getDefaultAuthTimeout(opts.LeafNode.TLSConfig, opts.LeafNode.TLSTimeout) } + // Default to compression "s2_auto". + if c := &opts.LeafNode.Compression; c.Mode == _EMPTY_ { + if testDefaultLeafNodeCompression != _EMPTY_ { + c.Mode = testDefaultLeafNodeCompression + } else { + c.Mode = CompressionS2Auto + } + } } // Set baseline connect port for remotes. for _, r := range opts.LeafNode.Remotes { if r != nil { for _, u := range r.URLs { - if u.Port() == "" { + if u.Port() == _EMPTY_ { u.Host = net.JoinHostPort(u.Host, strconv.Itoa(DEFAULT_LEAFNODE_PORT)) } } + // Default to compression "s2_auto". + if c := &r.Compression; c.Mode == _EMPTY_ { + if testDefaultLeafNodeCompression != _EMPTY_ { + c.Mode = testDefaultLeafNodeCompression + } else { + c.Mode = CompressionS2Auto + } + } + // Set default first info timeout value if not set. + if r.FirstInfoTimeout <= 0 { + r.FirstInfoTimeout = DEFAULT_LEAFNODE_INFO_WAIT + } } } @@ -3932,7 +5659,7 @@ func setBaselineOptions(opts *Options) { opts.LameDuckGracePeriod = DEFAULT_LAME_DUCK_GRACE_PERIOD } if opts.Gateway.Port != 0 { - if opts.Gateway.Host == "" { + if opts.Gateway.Host == _EMPTY_ { opts.Gateway.Host = DEFAULT_HOST } if opts.Gateway.TLSTimeout == 0 { @@ -3949,12 +5676,12 @@ func setBaselineOptions(opts *Options) { opts.ReconnectErrorReports = DEFAULT_RECONNECT_ERROR_REPORTS } if opts.Websocket.Port != 0 { - if opts.Websocket.Host == "" { + if opts.Websocket.Host == _EMPTY_ { opts.Websocket.Host = DEFAULT_HOST } } if opts.MQTT.Port != 0 { - if opts.MQTT.Host == "" { + if opts.MQTT.Host == _EMPTY_ { opts.MQTT.Host = DEFAULT_HOST } if opts.MQTT.TLSTimeout == 0 { @@ -3962,12 +5689,18 @@ func setBaselineOptions(opts *Options) { } } // JetStream - if opts.JetStreamMaxMemory == 0 { + if opts.JetStreamMaxMemory == 0 && !opts.maxMemSet { opts.JetStreamMaxMemory = -1 } - if opts.JetStreamMaxStore == 0 { + if opts.JetStreamMaxStore == 0 && !opts.maxStoreSet { opts.JetStreamMaxStore = -1 } + if opts.SyncInterval == 0 && !opts.syncSet { + opts.SyncInterval = defaultSyncInterval + } + if opts.JetStreamRequestQueueLimit <= 0 { + opts.JetStreamRequestQueueLimit = JSDefaultRequestQueueLimit + } } func getDefaultAuthTimeout(tls *tls.Config, tlsTimeout float64) float64 { @@ -4002,10 +5735,13 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, fs.BoolVar(&showHelp, "help", false, "Show this message.") fs.IntVar(&opts.Port, "port", 0, "Port to listen on.") fs.IntVar(&opts.Port, "p", 0, "Port to listen on.") - fs.StringVar(&opts.Host, "addr", "", "Network host to listen on.") - fs.StringVar(&opts.Host, "a", "", "Network host to listen on.") - fs.StringVar(&opts.Host, "net", "", "Network host to listen on.") - fs.StringVar(&opts.ClientAdvertise, "client_advertise", "", "Client URL to advertise to other servers.") + fs.StringVar(&opts.ServerName, "n", _EMPTY_, "Server name.") + fs.StringVar(&opts.ServerName, "name", _EMPTY_, "Server name.") + fs.StringVar(&opts.ServerName, "server_name", _EMPTY_, "Server name.") + fs.StringVar(&opts.Host, "addr", _EMPTY_, "Network host to listen on.") + fs.StringVar(&opts.Host, "a", _EMPTY_, "Network host to listen on.") + fs.StringVar(&opts.Host, "net", _EMPTY_, "Network host to listen on.") + fs.StringVar(&opts.ClientAdvertise, "client_advertise", _EMPTY_, "Client URL to advertise to other servers.") fs.BoolVar(&opts.Debug, "D", false, "Enable Debug logging.") fs.BoolVar(&opts.Debug, "debug", false, "Enable Debug logging.") fs.BoolVar(&opts.Trace, "V", false, "Enable Trace logging.") @@ -4015,18 +5751,19 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, fs.BoolVar(&dbgAndTrcAndVerboseTrc, "DVV", false, "Enable Debug and Verbose Trace logging. (Traces system account as well)") fs.BoolVar(&opts.Logtime, "T", true, "Timestamp log entries.") fs.BoolVar(&opts.Logtime, "logtime", true, "Timestamp log entries.") - fs.StringVar(&opts.Username, "user", "", "Username required for connection.") - fs.StringVar(&opts.Password, "pass", "", "Password required for connection.") - fs.StringVar(&opts.Authorization, "auth", "", "Authorization token required for connection.") + fs.BoolVar(&opts.LogtimeUTC, "logtime_utc", false, "Timestamps in UTC instead of local timezone.") + fs.StringVar(&opts.Username, "user", _EMPTY_, "Username required for connection.") + fs.StringVar(&opts.Password, "pass", _EMPTY_, "Password required for connection.") + fs.StringVar(&opts.Authorization, "auth", _EMPTY_, "Authorization token required for connection.") fs.IntVar(&opts.HTTPPort, "m", 0, "HTTP Port for /varz, /connz endpoints.") fs.IntVar(&opts.HTTPPort, "http_port", 0, "HTTP Port for /varz, /connz endpoints.") fs.IntVar(&opts.HTTPSPort, "ms", 0, "HTTPS Port for /varz, /connz endpoints.") fs.IntVar(&opts.HTTPSPort, "https_port", 0, "HTTPS Port for /varz, /connz endpoints.") - fs.StringVar(&configFile, "c", "", "Configuration file.") - fs.StringVar(&configFile, "config", "", "Configuration file.") + fs.StringVar(&configFile, "c", _EMPTY_, "Configuration file.") + fs.StringVar(&configFile, "config", _EMPTY_, "Configuration file.") fs.BoolVar(&opts.CheckConfig, "t", false, "Check configuration and exit.") - fs.StringVar(&signal, "sl", "", "Send signal to nats-server process (stop, quit, reopen, reload).") - fs.StringVar(&signal, "signal", "", "Send signal to nats-server process (stop, quit, reopen, reload).") + fs.StringVar(&signal, "sl", "", "Send signal to nats-server process (ldm, stop, quit, term, reopen, reload).") + fs.StringVar(&signal, "signal", "", "Send signal to nats-server process (ldm, stop, quit, term, reopen, reload).") fs.StringVar(&opts.PidFile, "P", "", "File to store process pid.") fs.StringVar(&opts.PidFile, "pid", "", "File to store process pid.") fs.StringVar(&opts.PortsFileDir, "ports_file_dir", "", "Creates a ports file in the specified directory (_.ports).") @@ -4035,29 +5772,29 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, fs.Int64Var(&opts.LogSizeLimit, "log_size_limit", 0, "Logfile size limit being auto-rotated") fs.BoolVar(&opts.Syslog, "s", false, "Enable syslog as log method.") fs.BoolVar(&opts.Syslog, "syslog", false, "Enable syslog as log method.") - fs.StringVar(&opts.RemoteSyslog, "r", "", "Syslog server addr (udp://127.0.0.1:514).") - fs.StringVar(&opts.RemoteSyslog, "remote_syslog", "", "Syslog server addr (udp://127.0.0.1:514).") + fs.StringVar(&opts.RemoteSyslog, "r", _EMPTY_, "Syslog server addr (udp://127.0.0.1:514).") + fs.StringVar(&opts.RemoteSyslog, "remote_syslog", _EMPTY_, "Syslog server addr (udp://127.0.0.1:514).") fs.BoolVar(&showVersion, "version", false, "Print version information.") fs.BoolVar(&showVersion, "v", false, "Print version information.") fs.IntVar(&opts.ProfPort, "profile", 0, "Profiling HTTP port.") - fs.StringVar(&opts.RoutesStr, "routes", "", "Routes to actively solicit a connection.") - fs.StringVar(&opts.Cluster.ListenStr, "cluster", "", "Cluster url from which members can solicit routes.") - fs.StringVar(&opts.Cluster.ListenStr, "cluster_listen", "", "Cluster url from which members can solicit routes.") - fs.StringVar(&opts.Cluster.Advertise, "cluster_advertise", "", "Cluster URL to advertise to other servers.") + fs.StringVar(&opts.RoutesStr, "routes", _EMPTY_, "Routes to actively solicit a connection.") + fs.StringVar(&opts.Cluster.ListenStr, "cluster", _EMPTY_, "Cluster url from which members can solicit routes.") + fs.StringVar(&opts.Cluster.ListenStr, "cluster_listen", _EMPTY_, "Cluster url from which members can solicit routes.") + fs.StringVar(&opts.Cluster.Advertise, "cluster_advertise", _EMPTY_, "Cluster URL to advertise to other servers.") fs.BoolVar(&opts.Cluster.NoAdvertise, "no_advertise", false, "Advertise known cluster IPs to clients.") fs.IntVar(&opts.Cluster.ConnectRetries, "connect_retries", 0, "For implicit routes, number of connect retries.") - fs.StringVar(&opts.Cluster.Name, "cluster_name", "", "Cluster Name, if not set one will be dynamically generated.") + fs.StringVar(&opts.Cluster.Name, "cluster_name", _EMPTY_, "Cluster Name, if not set one will be dynamically generated.") fs.BoolVar(&showTLSHelp, "help_tls", false, "TLS help.") fs.BoolVar(&opts.TLS, "tls", false, "Enable TLS.") fs.BoolVar(&opts.TLSVerify, "tlsverify", false, "Enable TLS with client verification.") - fs.StringVar(&opts.TLSCert, "tlscert", "", "Server certificate file.") - fs.StringVar(&opts.TLSKey, "tlskey", "", "Private key for server certificate.") - fs.StringVar(&opts.TLSCaCert, "tlscacert", "", "Client certificate CA for verification.") + fs.StringVar(&opts.TLSCert, "tlscert", _EMPTY_, "Server certificate file.") + fs.StringVar(&opts.TLSKey, "tlskey", _EMPTY_, "Private key for server certificate.") + fs.StringVar(&opts.TLSCaCert, "tlscacert", _EMPTY_, "Client certificate CA for verification.") fs.IntVar(&opts.MaxTracedMsgLen, "max_traced_msg_len", 0, "Maximum printable length for traced messages. 0 for unlimited.") fs.BoolVar(&opts.JetStream, "js", false, "Enable JetStream.") fs.BoolVar(&opts.JetStream, "jetstream", false, "Enable JetStream.") - fs.StringVar(&opts.StoreDir, "sd", "", "Storage directory.") - fs.StringVar(&opts.StoreDir, "store_dir", "", "Storage directory.") + fs.StringVar(&opts.StoreDir, "sd", _EMPTY_, "Storage directory.") + fs.StringVar(&opts.StoreDir, "store_dir", _EMPTY_, "Storage directory.") // The flags definition above set "default" values to some of the options. // Calling Parse() here will override the default options with any value @@ -4106,45 +5843,47 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, fs.Visit(func(f *flag.Flag) { switch f.Name { case "DVV": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", dbgAndTrcAndVerboseTrc) - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", dbgAndTrcAndVerboseTrc) - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "TraceVerbose", dbgAndTrcAndVerboseTrc) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Debug", dbgAndTrcAndVerboseTrc) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Trace", dbgAndTrcAndVerboseTrc) + trackExplicitVal(&FlagSnapshot.inCmdLine, "TraceVerbose", dbgAndTrcAndVerboseTrc) case "DV": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", dbgAndTrace) - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", dbgAndTrace) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Debug", dbgAndTrace) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Trace", dbgAndTrace) case "D": fallthrough case "debug": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Debug", FlagSnapshot.Debug) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Debug", FlagSnapshot.Debug) case "VV": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", trcAndVerboseTrc) - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "TraceVerbose", trcAndVerboseTrc) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Trace", trcAndVerboseTrc) + trackExplicitVal(&FlagSnapshot.inCmdLine, "TraceVerbose", trcAndVerboseTrc) case "V": fallthrough case "trace": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Trace", FlagSnapshot.Trace) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Trace", FlagSnapshot.Trace) case "T": fallthrough case "logtime": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Logtime", FlagSnapshot.Logtime) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Logtime", FlagSnapshot.Logtime) case "s": fallthrough case "syslog": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Syslog", FlagSnapshot.Syslog) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Syslog", FlagSnapshot.Syslog) case "no_advertise": - trackExplicitVal(FlagSnapshot, &FlagSnapshot.inCmdLine, "Cluster.NoAdvertise", FlagSnapshot.Cluster.NoAdvertise) + trackExplicitVal(&FlagSnapshot.inCmdLine, "Cluster.NoAdvertise", FlagSnapshot.Cluster.NoAdvertise) + case "js": + trackExplicitVal(&FlagSnapshot.inCmdLine, "JetStream", FlagSnapshot.JetStream) } }) // Process signal control. - if signal != "" { + if signal != _EMPTY_ { if err := processSignal(signal); err != nil { return nil, err } } // Parse config if given - if configFile != "" { + if configFile != _EMPTY_ { // This will update the options with values from the config file. err := opts.ProcessConfigFile(configFile) if err != nil { @@ -4208,7 +5947,7 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, flagErr = overrideCluster(opts) case "routes": // Keep in mind that the flag has updated opts.RoutesStr at this point. - if opts.RoutesStr == "" { + if opts.RoutesStr == _EMPTY_ { // Set routes array to nil since routes string is empty opts.Routes = nil return @@ -4233,7 +5972,7 @@ func ConfigureOptions(fs *flag.FlagSet, args []string, printVersion, printHelp, // If we don't have cluster defined in the configuration // file and no cluster listen string override, but we do // have a routes override, we need to report misconfiguration. - if opts.RoutesStr != "" && opts.Cluster.ListenStr == "" && opts.Cluster.Host == "" && opts.Cluster.Port == 0 { + if opts.RoutesStr != _EMPTY_ && opts.Cluster.ListenStr == _EMPTY_ && opts.Cluster.Host == _EMPTY_ && opts.Cluster.Port == 0 { return nil, errors.New("solicited routes require cluster capabilities, e.g. --cluster") } @@ -4253,10 +5992,10 @@ func normalizeBasePath(p string) string { // overrideTLS is called when at least "-tls=true" has been set. func overrideTLS(opts *Options) error { - if opts.TLSCert == "" { + if opts.TLSCert == _EMPTY_ { return errors.New("TLS Server certificate must be present and valid") } - if opts.TLSKey == "" { + if opts.TLSKey == _EMPTY_ { return errors.New("TLS Server private key must be present and valid") } @@ -4265,6 +6004,7 @@ func overrideTLS(opts *Options) error { tc.KeyFile = opts.TLSKey tc.CaFile = opts.TLSCaCert tc.Verify = opts.TLSVerify + tc.Ciphers = defaultCipherSuites() var err error opts.TLSConfig, err = GenTLSConfig(&tc) @@ -4275,7 +6015,7 @@ func overrideTLS(opts *Options) error { // has explicitly be set in the command line. If it is set to empty string, it will // clear the Cluster options. func overrideCluster(opts *Options) error { - if opts.Cluster.ListenStr == "" { + if opts.Cluster.ListenStr == _EMPTY_ { // This one is enough to disable clustering. opts.Cluster.Port = 0 return nil @@ -4318,8 +6058,8 @@ func overrideCluster(opts *Options) error { } else { // Since we override from flag and there is no user/pwd, make // sure we clear what we may have gotten from config file. - opts.Cluster.Username = "" - opts.Cluster.Password = "" + opts.Cluster.Username = _EMPTY_ + opts.Cluster.Password = _EMPTY_ } return nil @@ -4347,7 +6087,7 @@ func processSignal(signal string) error { // 2. If such a file exists and can be read, return its contents. // 3. Otherwise, return the original "pidStr" string. func maybeReadPidFile(pidStr string) string { - if b, err := ioutil.ReadFile(pidStr); err == nil { + if b, err := os.ReadFile(pidStr); err == nil { return string(b) } return pidStr @@ -4359,9 +6099,9 @@ func homeDir() (string, error) { userProfile := os.Getenv("USERPROFILE") home := filepath.Join(homeDrive, homePath) - if homeDrive == "" || homePath == "" { - if userProfile == "" { - return "", errors.New("nats: failed to get home dir, require %HOMEDRIVE% and %HOMEPATH% or %USERPROFILE%") + if homeDrive == _EMPTY_ || homePath == _EMPTY_ { + if userProfile == _EMPTY_ { + return _EMPTY_, errors.New("nats: failed to get home dir, require %HOMEDRIVE% and %HOMEPATH% or %USERPROFILE%") } home = userProfile } @@ -4370,8 +6110,8 @@ func homeDir() (string, error) { } home := os.Getenv("HOME") - if home == "" { - return "", errors.New("failed to get home dir, require $HOME") + if home == _EMPTY_ { + return _EMPTY_, errors.New("failed to get home dir, require $HOME") } return home, nil } @@ -4385,7 +6125,7 @@ func expandPath(p string) (string, error) { home, err := homeDir() if err != nil { - return "", err + return _EMPTY_, err } return filepath.Join(home, p[1:]), nil diff --git a/vendor/github.com/nats-io/nats-server/v2/server/parser.go b/vendor/github.com/nats-io/nats-server/v2/server/parser.go index ad2a83b..58d034a 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/parser.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/parser.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -35,18 +35,22 @@ type parseState struct { } type pubArg struct { - arg []byte - pacache []byte - origin []byte - account []byte - subject []byte - deliver []byte - reply []byte - szb []byte - hdb []byte - queues [][]byte - size int - hdr int + arg []byte + pacache []byte + origin []byte + account []byte + subject []byte + deliver []byte + mapped []byte + reply []byte + szb []byte + hdb []byte + queues [][]byte + size int + hdr int + psi []*serviceImport + trace *msgTrace + delivered bool // Only used for service imports } // Parser constants @@ -145,8 +149,7 @@ func (c *client) parse(buf []byte) error { // proper CONNECT if needed. authSet := c.awaitingAuth() // Snapshot max control line as well. - mcl := c.mcl - trace := c.trace + s, mcl, trace := c.srv, c.mcl, c.trace c.mu.Unlock() // Move to loop instead of range syntax to allow jumping of i @@ -158,7 +161,28 @@ func (c *client) parse(buf []byte) error { c.op = b if b != 'C' && b != 'c' { if authSet { - goto authErr + if s == nil { + goto authErr + } + var ok bool + // Check here for NoAuthUser. If this is set allow non CONNECT protos as our first. + // E.g. telnet proto demos. + if noAuthUser := s.getOpts().NoAuthUser; noAuthUser != _EMPTY_ { + s.mu.Lock() + user, exists := s.users[noAuthUser] + s.mu.Unlock() + if exists { + c.RegisterUser(user) + c.mu.Lock() + c.clearAuthTimer() + c.flags.set(connectReceived) + c.mu.Unlock() + authSet, ok = false, true + } + } + if !ok { + goto authErr + } } // If the connection is a gateway connection, make sure that // if this is an inbound, it starts with a CONNECT. @@ -257,12 +281,20 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } if trace { c.traceInOp("HPUB", arg) } - if err := c.processHeaderPub(arg); err != nil { + var remaining []byte + if i < len(buf) { + remaining = buf[i+1:] + } + if err := c.processHeaderPub(arg, remaining); err != nil { return err } + c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD // If we don't have a saved buffer then jump ahead with // the index. If this overruns what is left we fall out @@ -317,6 +349,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } var err error if c.kind == ROUTER || c.kind == GATEWAY { if trace { @@ -389,23 +424,16 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } if trace { c.traceInOp("PUB", arg) } if err := c.processPub(arg); err != nil { return err } - // Check if we have and account mappings or tees or filters. - // FIXME(dlc) - Probably better way to do this. - // Could add in cache but will be tricky since results based on pub subject are dynamic - // due to wildcard matching and weight sets. - if c.kind == CLIENT && c.in.flags.isSet(hasMappings) { - old := c.pa.subject - changed := c.selectMappedSubject() - if trace && changed { - c.traceInOp("MAPPING", []byte(fmt.Sprintf("%s -> %s", old, c.pa.subject))) - } - } + c.drop, c.as, c.state = 0, i+1, MSG_PAYLOAD // If we don't have a saved buffer then jump ahead with // the index. If this overruns what is left we fall out @@ -460,15 +488,36 @@ func (c *client) parse(buf []byte) error { } else { c.msgBuf = buf[c.as : i+1] } + + var mt *msgTrace + if c.pa.hdr > 0 { + mt = c.initMsgTrace() + } + // Check for mappings. + if (c.kind == CLIENT || c.kind == LEAF) && c.in.flags.isSet(hasMappings) { + changed := c.selectMappedSubject() + if changed { + if trace { + c.traceInOp("MAPPING", []byte(fmt.Sprintf("%s -> %s", c.pa.mapped, c.pa.subject))) + } + // c.pa.subject is the subject the original is now mapped to. + mt.addSubjectMappingEvent(c.pa.subject) + } + } if trace { c.traceMsg(c.msgBuf) } + c.processInboundMsg(c.msgBuf) + + mt.sendEvent() c.argBuf, c.msgBuf, c.header = nil, nil, nil c.drop, c.as, c.state = 0, i+1, OP_START // Drop all pub args - c.pa.arg, c.pa.pacache, c.pa.origin, c.pa.account, c.pa.subject = nil, nil, nil, nil, nil + c.pa.arg, c.pa.pacache, c.pa.origin, c.pa.account, c.pa.subject, c.pa.mapped = nil, nil, nil, nil, nil, nil c.pa.reply, c.pa.hdr, c.pa.size, c.pa.szb, c.pa.hdb, c.pa.queues = nil, -1, 0, nil, nil, nil + c.pa.trace = nil + c.pa.delivered = false lmsg = false case OP_A: switch b { @@ -506,6 +555,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } if trace { c.traceInOp("A+", arg) } @@ -545,6 +597,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } if trace { c.traceInOp("A-", arg) } @@ -596,6 +651,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } var err error switch c.kind { @@ -728,6 +786,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } var err error switch c.kind { @@ -745,7 +806,8 @@ func (c *client) parse(buf []byte) error { c.traceInOp("LS-", arg) } } - err = c.processRemoteUnsub(arg) + leafUnsub := c.op == 'L' || c.op == 'l' + err = c.processRemoteUnsub(arg, leafUnsub) case GATEWAY: if trace { c.traceInOp("RS-", arg) @@ -874,8 +936,11 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } if trace { - c.traceInOp("CONNECT", removePassFromTrace(arg)) + c.traceInOp("CONNECT", removeSecretsFromTrace(arg)) } if err := c.processConnect(arg); err != nil { return err @@ -932,6 +997,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } var err error if c.kind == ROUTER || c.kind == GATEWAY { switch c.op { @@ -1008,6 +1076,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } if err := c.processInfo(arg); err != nil { return err } @@ -1084,6 +1155,9 @@ func (c *client) parse(buf []byte) error { } else { arg = buf[c.as : i-c.drop] } + if err := c.overMaxControlLineLimit(arg, mcl); err != nil { + return err + } c.processErr(string(arg)) c.drop, c.as, c.state = 0, i+1, OP_START default: @@ -1111,11 +1185,7 @@ func (c *client) parse(buf []byte) error { // Check for violations of control line length here. Note that this is not // exact at all but the performance hit is too great to be precise, and // catching here should prevent memory exhaustion attacks. - if len(c.argBuf) > int(mcl) { - err := NewErrorCtx(ErrMaxControlLine, "State %d, max_control_line %d, Buffer len %d", - c.state, int(mcl), len(c.argBuf)) - c.sendErr(err.Error()) - c.closeConnection(MaxControlLineExceeded) + if err := c.overMaxControlLineLimit(c.argBuf, mcl); err != nil { return err } } @@ -1126,7 +1196,7 @@ func (c *client) parse(buf []byte) error { // read buffer and we are not able to process the msg. if c.argBuf == nil { - // Works also for MSG_ARG, when message comes from ROUTE. + // Works also for MSG_ARG, when message comes from ROUTE or GATEWAY. if err := c.clonePubArg(lmsg); err != nil { goto parseErr } @@ -1158,14 +1228,13 @@ authErr: parseErr: c.sendErr("Unknown Protocol Operation") - snip := protoSnippet(i, buf) - err := fmt.Errorf("%s parser ERROR, state=%d, i=%d: proto='%s...'", - c.typeString(), c.state, i, snip) + snip := protoSnippet(i, PROTO_SNIPPET_SIZE, buf) + err := fmt.Errorf("%s parser ERROR, state=%d, i=%d: proto='%s...'", c.kindString(), c.state, i, snip) return err } -func protoSnippet(start int, buf []byte) string { - stop := start + PROTO_SNIPPET_SIZE +func protoSnippet(start, max int, buf []byte) string { + stop := start + max bufSize := len(buf) if start >= bufSize { return `""` @@ -1176,6 +1245,23 @@ func protoSnippet(start int, buf []byte) string { return fmt.Sprintf("%q", buf[start:stop]) } +// Check if the length of buffer `arg` is over the max control line limit `mcl`. +// If so, an error is sent to the client and the connection is closed. +// The error ErrMaxControlLine is returned. +func (c *client) overMaxControlLineLimit(arg []byte, mcl int32) error { + if c.kind != CLIENT { + return nil + } + if len(arg) > int(mcl) { + err := NewErrorCtx(ErrMaxControlLine, "State %d, max_control_line %d, Buffer len %d (snip: %s...)", + c.state, int(mcl), len(c.argBuf), protoSnippet(0, MAX_CONTROL_LINE_SNIPPET_SIZE, arg)) + c.sendErr(err.Error()) + c.closeConnection(MaxControlLineExceeded) + return err + } + return nil +} + // clonePubArg is used when the split buffer scenario has the pubArg in the existing read buffer, but // we need to hold onto it into the next read. func (c *client) clonePubArg(lmsg bool) error { @@ -1203,7 +1289,7 @@ func (c *client) clonePubArg(lmsg bool) error { if c.pa.hdr < 0 { return c.processPub(c.argBuf) } else { - return c.processHeaderPub(c.argBuf) + return c.processHeaderPub(c.argBuf, nil) } } } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/proto.go b/vendor/github.com/nats-io/nats-server/v2/server/proto.go new file mode 100644 index 0000000..9843fff --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/proto.go @@ -0,0 +1,269 @@ +// Copyright 2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Inspired by https://github.com/protocolbuffers/protobuf-go/blob/master/encoding/protowire/wire.go + +package server + +import ( + "errors" + "fmt" + "math" +) + +var errProtoInsufficient = errors.New("insufficient data to read a value") +var errProtoOverflow = errors.New("too much data for a value") +var errProtoInvalidFieldNumber = errors.New("invalid field number") + +func protoScanField(b []byte) (num, typ, size int, err error) { + num, typ, sizeTag, err := protoScanTag(b) + if err != nil { + return 0, 0, 0, err + } + b = b[sizeTag:] + + sizeValue, err := protoScanFieldValue(typ, b) + if err != nil { + return 0, 0, 0, err + } + return num, typ, sizeTag + sizeValue, nil +} + +func protoScanTag(b []byte) (num, typ, size int, err error) { + tagint, size, err := protoScanVarint(b) + if err != nil { + return 0, 0, 0, err + } + + // NOTE: MessageSet allows for larger field numbers than normal. + if (tagint >> 3) > uint64(math.MaxInt32) { + return 0, 0, 0, errProtoInvalidFieldNumber + } + num = int(tagint >> 3) + if num < 1 { + return 0, 0, 0, errProtoInvalidFieldNumber + } + typ = int(tagint & 7) + + return num, typ, size, nil +} + +func protoScanFieldValue(typ int, b []byte) (size int, err error) { + switch typ { + case 0: + _, size, err = protoScanVarint(b) + case 5: // fixed32 + size = 4 + case 1: // fixed64 + size = 8 + case 2: // length-delimited + size, err = protoScanBytes(b) + default: + return 0, fmt.Errorf("unsupported type: %d", typ) + } + return size, err +} + +func protoScanVarint(b []byte) (v uint64, size int, err error) { + var y uint64 + if len(b) <= 0 { + return 0, 0, errProtoInsufficient + } + v = uint64(b[0]) + if v < 0x80 { + return v, 1, nil + } + v -= 0x80 + + if len(b) <= 1 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[1]) + v += y << 7 + if y < 0x80 { + return v, 2, nil + } + v -= 0x80 << 7 + + if len(b) <= 2 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[2]) + v += y << 14 + if y < 0x80 { + return v, 3, nil + } + v -= 0x80 << 14 + + if len(b) <= 3 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[3]) + v += y << 21 + if y < 0x80 { + return v, 4, nil + } + v -= 0x80 << 21 + + if len(b) <= 4 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[4]) + v += y << 28 + if y < 0x80 { + return v, 5, nil + } + v -= 0x80 << 28 + + if len(b) <= 5 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[5]) + v += y << 35 + if y < 0x80 { + return v, 6, nil + } + v -= 0x80 << 35 + + if len(b) <= 6 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[6]) + v += y << 42 + if y < 0x80 { + return v, 7, nil + } + v -= 0x80 << 42 + + if len(b) <= 7 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[7]) + v += y << 49 + if y < 0x80 { + return v, 8, nil + } + v -= 0x80 << 49 + + if len(b) <= 8 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[8]) + v += y << 56 + if y < 0x80 { + return v, 9, nil + } + v -= 0x80 << 56 + + if len(b) <= 9 { + return 0, 0, errProtoInsufficient + } + y = uint64(b[9]) + v += y << 63 + if y < 2 { + return v, 10, nil + } + return 0, 0, errProtoOverflow +} + +func protoScanBytes(b []byte) (size int, err error) { + l, lenSize, err := protoScanVarint(b) + if err != nil { + return 0, err + } + if l > uint64(len(b[lenSize:])) { + return 0, errProtoInsufficient + } + return lenSize + int(l), nil +} + +func protoEncodeVarint(v uint64) []byte { + b := make([]byte, 0, 10) + switch { + case v < 1<<7: + b = append(b, byte(v)) + case v < 1<<14: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte(v>>7)) + case v < 1<<21: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte(v>>14)) + case v < 1<<28: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte(v>>21)) + case v < 1<<35: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte(v>>28)) + case v < 1<<42: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte(v>>35)) + case v < 1<<49: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte(v>>42)) + case v < 1<<56: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte(v>>49)) + case v < 1<<63: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte(v>>56)) + default: + b = append(b, + byte((v>>0)&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte((v>>56)&0x7f|0x80), + 1) + } + return b +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_darwin.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_darwin.go index b00f1e0..7fd26b1 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_darwin.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_darwin.go @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -13,22 +13,74 @@ package pse +// On macs after some studying it seems that typical tools like ps and activity monitor report MaxRss and not +// current RSS. I wrote some C code to pull the real RSS and although it does not go down very often, when it does +// that is not reflected in the typical tooling one might compare us to, so we can skip cgo and just use rusage imo. +// We also do not use virtual memory in the upper layers at all, so ok to skip since rusage does not report vss. + import ( - "fmt" - "os" - "os/exec" + "math" + "sync" + "syscall" + "time" ) -// ProcUsage returns CPU usage -func ProcUsage(pcpu *float64, rss, vss *int64) error { - pidStr := fmt.Sprintf("%d", os.Getpid()) - out, err := exec.Command("ps", "o", "pcpu=,rss=,vsz=", "-p", pidStr).Output() - if err != nil { - *rss, *vss = -1, -1 - return fmt.Errorf("ps call failed:%v", err) +type lastUsage struct { + sync.Mutex + last time.Time + cpu time.Duration + rss int64 + pcpu float64 +} + +// To hold the last usage and call time. +var lu lastUsage + +func init() { + updateUsage() + periodic() +} + +// Get our usage. +func getUsage() (now time.Time, cpu time.Duration, rss int64) { + var ru syscall.Rusage + syscall.Getrusage(syscall.RUSAGE_SELF, &ru) + now = time.Now() + cpu = time.Duration(ru.Utime.Sec)*time.Second + time.Duration(ru.Utime.Usec)*time.Microsecond + cpu += time.Duration(ru.Stime.Sec)*time.Second + time.Duration(ru.Stime.Usec)*time.Microsecond + return now, cpu, ru.Maxrss +} + +// Update last usage. +// We need to have a prior sample to compute pcpu. +func updateUsage() (pcpu float64, rss int64) { + lu.Lock() + defer lu.Unlock() + + now, cpu, rss := getUsage() + // Don't skew pcpu by sampling too close to last sample. + if elapsed := now.Sub(lu.last); elapsed < 500*time.Millisecond { + // Always update rss. + lu.rss = rss + } else { + tcpu := float64(cpu - lu.cpu) + lu.last, lu.cpu, lu.rss = now, cpu, rss + // Want to make this one decimal place and not count on upper layers. + // Cores already taken into account via cpu time measurements. + lu.pcpu = math.Round(tcpu/float64(elapsed)*1000) / 10 } - fmt.Sscanf(string(out), "%f %d %d", pcpu, rss, vss) - *rss *= 1024 // 1k blocks, want bytes. - *vss *= 1024 // 1k blocks, want bytes. + return lu.pcpu, lu.rss +} + +// Sampling function to keep pcpu relevant. +func periodic() { + updateUsage() + time.AfterFunc(time.Second, periodic) +} + +// ProcUsage returns CPU and memory usage. +// Note upper layers do not use virtual memory size, so ok that it is not filled in here. +func ProcUsage(pcpu *float64, rss, vss *int64) error { + *pcpu, *rss = updateUsage() return nil } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_dragonfly.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_dragonfly.go new file mode 100644 index 0000000..55a917a --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_dragonfly.go @@ -0,0 +1,36 @@ +// Copyright 2015-2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copied from pse_openbsd.go + +package pse + +import ( + "fmt" + "os" + "os/exec" +) + +// ProcUsage returns CPU usage +func ProcUsage(pcpu *float64, rss, vss *int64) error { + pidStr := fmt.Sprintf("%d", os.Getpid()) + out, err := exec.Command("ps", "o", "pcpu=,rss=,vsz=", "-p", pidStr).Output() + if err != nil { + *rss, *vss = -1, -1 + return fmt.Errorf("ps call failed:%v", err) + } + fmt.Sscanf(string(out), "%f %d %d", pcpu, rss, vss) + *rss *= 1024 // 1k blocks, want bytes. + *vss *= 1024 // 1k blocks, want bytes. + return nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_cgo.go similarity index 96% rename from vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd.go rename to vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_cgo.go index 849440f..e759a48 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_cgo.go @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !amd64 +//go:build cgo && freebsd package pse diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_amd64.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_sysctl.go similarity index 52% rename from vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_amd64.go rename to vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_sysctl.go index 2d21e5c..f4ea199 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_amd64.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_freebsd_sysctl.go @@ -1,4 +1,4 @@ -// Copyright 2015-2020 The NATS Authors +// Copyright 2015-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,22 +11,37 @@ // See the License for the specific language governing permissions and // limitations under the License. -// This is the amd64-specific FreeBSD implementation, with hard-coded offset -// constants derived by running freebsd.txt; having this implementation allows -// us to compile without CGO, which lets us cross-compile for FreeBSD from our -// CI system and so supply binaries for FreeBSD amd64. +// There are two FreeBSD implementations; one which uses cgo and should build +// locally on any FreeBSD, and this one which uses sysctl but needs us to know +// the offset constants for the fields we care about. +// +// The advantage of this one is that without cgo, it is much easier to +// cross-compile to a target. The official releases are all built with +// cross-compilation. +// +// We've switched the other implementation to include '_cgo' in the filename, +// to show that it's not the default. This isn't an os or arch build tag, +// so we have to use explicit build-tags within. +// If lacking CGO support and targeting an unsupported arch, then before the +// change you would have a compile failure for not being able to cross-compile. +// After the change, you have a compile failure for not having the symbols +// because no source file satisfies them. +// Thus we are no worse off, and it's now much easier to extend support for +// non-CGO to new architectures, just by editing this file. // // To generate for other architectures: -// 1. Update pse_freebsd.go, change the build exclusion to exclude your arch -// 2. Copy this file to be built for your arch -// 3. Update `nativeEndian` below -// 4. Link `freebsd.txt` to have a .c filename and compile and run, then -// paste the outputs into the const section below. +// 1. Copy `freebsd.txt` to have a .c filename on a box running the target +// architecture, compile and run it. +// 2. Update the init() function below to include a case for this architecture +// 3. Update the build-tags in this file. + +//go:build !cgo && freebsd && (amd64 || arm64) package pse import ( "encoding/binary" + "runtime" "syscall" "golang.org/x/sys/unix" @@ -37,15 +52,34 @@ import ( // than little or big endian. var nativeEndian = binary.LittleEndian -const ( - KIP_OFF_size = 256 - KIP_OFF_rssize = 264 - KIP_OFF_pctcpu = 308 -) +var pageshift int // derived from getpagesize(3) in init() below -var pageshift int +var ( + // These are populated in the init function, based on the current architecture. + // (It's less file-count explosion than having one small file for each + // FreeBSD architecture). + KIP_OFF_size int + KIP_OFF_rssize int + KIP_OFF_pctcpu int +) func init() { + switch runtime.GOARCH { + // These are the values which come from compiling and running + // freebsd.txt as a C program. + // Most recently validated: 2025-04 with FreeBSD 14.2R in AWS. + case "amd64": + KIP_OFF_size = 256 + KIP_OFF_rssize = 264 + KIP_OFF_pctcpu = 308 + case "arm64": + KIP_OFF_size = 256 + KIP_OFF_rssize = 264 + KIP_OFF_pctcpu = 308 + default: + panic("code bug: server/pse FreeBSD support missing case for '" + runtime.GOARCH + "' but build-tags allowed us to build anyway?") + } + // To get the physical page size, the C library checks two places: // process ELF auxiliary info, AT_PAGESZ // as a fallback, the hw.pagesize sysctl diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_linux.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_linux.go index aa986d0..2dbd993 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_linux.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_linux.go @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,7 +16,6 @@ package pse import ( "bytes" "fmt" - "io/ioutil" "os" "sync/atomic" "syscall" @@ -29,6 +28,7 @@ var ( lastTotal int64 lastSeconds int64 ipcpu int64 + pageSize int64 ) const ( @@ -43,12 +43,13 @@ func init() { // Avoiding to generate docker image without CGO ticks = 100 // int64(C.sysconf(C._SC_CLK_TCK)) procStatFile = fmt.Sprintf("/proc/%d/stat", os.Getpid()) + pageSize = int64(os.Getpagesize()) periodic() } // Sampling function to keep pcpu relevant. func periodic() { - contents, err := ioutil.ReadFile(procStatFile) + contents, err := os.ReadFile(procStatFile) if err != nil { return } @@ -88,14 +89,14 @@ func periodic() { // ProcUsage returns CPU usage func ProcUsage(pcpu *float64, rss, vss *int64) error { - contents, err := ioutil.ReadFile(procStatFile) + contents, err := os.ReadFile(procStatFile) if err != nil { return err } fields := bytes.Fields(contents) // Memory - *rss = (parseInt64(fields[rssPos])) << 12 + *rss = (parseInt64(fields[rssPos])) * pageSize *vss = parseInt64(fields[vssPos]) // PCPU diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_netbsd.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_netbsd.go new file mode 100644 index 0000000..d8393f6 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_netbsd.go @@ -0,0 +1,36 @@ +// Copyright 2022 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copied from pse_openbsd.go + +package pse + +import ( + "fmt" + "os" + "os/exec" +) + +// ProcUsage returns CPU usage +func ProcUsage(pcpu *float64, rss, vss *int64) error { + pidStr := fmt.Sprintf("%d", os.Getpid()) + out, err := exec.Command("ps", "o", "pcpu=,rss=,vsz=", "-p", pidStr).Output() + if err != nil { + *rss, *vss = -1, -1 + return fmt.Errorf("ps call failed:%v", err) + } + fmt.Sscanf(string(out), "%f %d %d", pcpu, rss, vss) + *rss *= 1024 // 1k blocks, want bytes. + *vss *= 1024 // 1k blocks, want bytes. + return nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_rumprun.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_rumprun.go index 48e80fc..94ddf8f 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_rumprun.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_rumprun.go @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build rumprun +//go:build rumprun package pse diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_solaris.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_solaris.go index 8e40d2e..f812ba4 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_solaris.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_solaris.go @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -10,14 +10,36 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +// +// Copied from pse_openbsd.go + +//go:build illumos || solaris package pse -// This is a placeholder for now. -func ProcUsage(pcpu *float64, rss, vss *int64) error { - *pcpu = 0.0 - *rss = 0 - *vss = 0 +import ( + "fmt" + "os" + "os/exec" + "strings" +) +// ProcUsage returns CPU usage +func ProcUsage(pcpu *float64, rss, vss *int64) error { + pidStr := fmt.Sprintf("%d", os.Getpid()) + out, err := exec.Command("ps", "-o", "pcpu,rss,vsz", "-p", pidStr).Output() + if err != nil { + *rss, *vss = -1, -1 + return fmt.Errorf("ps call failed:%v", err) + } + lines := strings.Split(string(out), "\n") + if len(lines) < 2 { + *rss, *vss = -1, -1 + return fmt.Errorf("no ps output") + } + output := lines[1] + fmt.Sscanf(output, "%f %d %d", pcpu, rss, vss) + *rss *= 1024 // 1k blocks, want bytes. + *vss *= 1024 // 1k blocks, want bytes. return nil } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_wasm.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_wasm.go new file mode 100644 index 0000000..6fcfda7 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_wasm.go @@ -0,0 +1,25 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build wasm + +package pse + +// This is a placeholder for now. +func ProcUsage(pcpu *float64, rss, vss *int64) error { + *pcpu = 0.0 + *rss = 0 + *vss = 0 + + return nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_windows.go index e159ebb..ab0adde 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_windows.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_windows.go @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build windows +//go:build windows package pse @@ -24,10 +24,12 @@ import ( "syscall" "time" "unsafe" + + "golang.org/x/sys/windows" ) var ( - pdh = syscall.NewLazyDLL("pdh.dll") + pdh = windows.NewLazySystemDLL("pdh.dll") winPdhOpenQuery = pdh.NewProc("PdhOpenQuery") winPdhAddCounter = pdh.NewProc("PdhAddCounterW") winPdhCollectQueryData = pdh.NewProc("PdhCollectQueryData") @@ -35,6 +37,20 @@ var ( winPdhGetFormattedCounterArray = pdh.NewProc("PdhGetFormattedCounterArrayW") ) +func init() { + if err := pdh.Load(); err != nil { + panic(err) + } + for _, p := range []*windows.LazyProc{ + winPdhOpenQuery, winPdhAddCounter, winPdhCollectQueryData, + winPdhGetFormattedCounterValue, winPdhGetFormattedCounterArray, + } { + if err := p.Find(); err != nil { + panic(err) + } + } +} + // global performance counter query handle and counters var ( pcHandle PDH_HQUERY diff --git a/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_zos.go b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_zos.go new file mode 100644 index 0000000..8596c49 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/pse/pse_zos.go @@ -0,0 +1,25 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build zos + +package pse + +// This is a placeholder for now. +func ProcUsage(pcpu *float64, rss, vss *int64) error { + *pcpu = 0.0 + *rss = 0 + *vss = 0 + + return nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/raft.go b/vendor/github.com/nats-io/nats-server/v2/server/raft.go new file mode 100644 index 0000000..65c0963 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/raft.go @@ -0,0 +1,4722 @@ +// Copyright 2020-2026 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "crypto/sha256" + "encoding/binary" + "errors" + "fmt" + "math" + "math/rand" + "net" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/antithesishq/antithesis-sdk-go/assert" + "github.com/nats-io/nats-server/v2/internal/fastrand" + + "github.com/minio/highwayhash" +) + +type RaftNode interface { + Propose(entry []byte) error + ProposeMulti(entries []*Entry) error + ForwardProposal(entry []byte) error + InstallSnapshot(snap []byte) error + SendSnapshot(snap []byte) error + NeedSnapshot() bool + Applied(index uint64) (entries uint64, bytes uint64) + State() RaftState + Size() (entries, bytes uint64) + Progress() (index, commit, applied uint64) + Leader() bool + LeaderSince() *time.Time + Quorum() bool + Current() bool + Healthy() bool + Term() uint64 + Leaderless() bool + GroupLeader() string + HadPreviousLeader() bool + StepDown(preferred ...string) error + SetObserver(isObserver bool) + IsObserver() bool + Campaign() error + CampaignImmediately() error + ID() string + Group() string + Peers() []*Peer + ProposeKnownPeers(knownPeers []string) + UpdateKnownPeers(knownPeers []string) + ProposeAddPeer(peer string) error + ProposeRemovePeer(peer string) error + MembershipChangeInProgress() bool + AdjustClusterSize(csz int) error + AdjustBootClusterSize(csz int) error + ClusterSize() int + ApplyQ() *ipQueue[*CommittedEntry] + PauseApply() error + ResumeApply() + DrainAndReplaySnapshot() bool + LeadChangeC() <-chan bool + QuitC() <-chan struct{} + Created() time.Time + Stop() + WaitForStop() + Delete() + IsDeleted() bool + RecreateInternalSubs() error + IsSystemAccount() bool + GetTrafficAccountName() string +} + +type WAL interface { + Type() StorageType + StoreMsg(subj string, hdr, msg []byte, ttl int64) (uint64, int64, error) + LoadMsg(index uint64, sm *StoreMsg) (*StoreMsg, error) + RemoveMsg(index uint64) (bool, error) + Compact(index uint64) (uint64, error) + Purge() (uint64, error) + PurgeEx(subject string, seq, keep uint64) (uint64, error) + Truncate(seq uint64) error + State() StreamState + FastState(*StreamState) + Stop() error + Delete() error +} + +type Peer struct { + ID string + Current bool + Last time.Time + Lag uint64 +} + +type RaftState uint8 + +// Allowable states for a NATS Consensus Group. +const ( + Follower RaftState = iota + Leader + Candidate + Closed +) + +func (state RaftState) String() string { + switch state { + case Follower: + return "FOLLOWER" + case Candidate: + return "CANDIDATE" + case Leader: + return "LEADER" + case Closed: + return "CLOSED" + } + return "UNKNOWN" +} + +type raft struct { + sync.RWMutex + + created time.Time // Time that the group was created + accName string // Account name of the asset this raft group is for + acc *Account // Account that NRG traffic will be sent/received in + group string // Raft group + sd string // Store directory + id string // Node ID + wg sync.WaitGroup // Wait for running goroutines to exit on shutdown + + wal WAL // WAL store (filestore or memstore) + wtype StorageType // WAL type, e.g. FileStorage or MemoryStorage + bytes uint64 // Total amount of bytes stored in the WAL. (Saves us from needing to call wal.FastState very often) + werr error // Last write error + + state atomic.Int32 // RaftState + leaderState atomic.Bool // Is in (complete) leader state. + leaderSince atomic.Pointer[time.Time] // How long since becoming leader. + hh *highwayhash.Digest64 // Highwayhash, used for snapshots + snapfile string // Snapshot filename + + csz int // Cluster size + qn int // Number of nodes needed to establish quorum + peers map[string]*lps // Other peers in the Raft group + + removed map[string]time.Time // Peers that were removed from the group + acks map[uint64]map[string]struct{} // Append entry responses/acks, map of entry index -> peer ID + pae map[uint64]*appendEntry // Pending append entries + + elect *time.Timer // Election timer, normally accessed via electTimer + etlr time.Time // Election timer last reset time, for unit tests only + active time.Time // Last activity time, i.e. for heartbeats + llqrt time.Time // Last quorum lost time + lsut time.Time // Last scale-up time + + term uint64 // The current vote term + pterm uint64 // Previous term from the last snapshot + pindex uint64 // Previous index from the last snapshot + commit uint64 // Index of the most recent commit + applied uint64 // Index of the most recently applied commit + papplied uint64 // First sequence of our log, matches when we last installed a snapshot. + + aflr uint64 // Index when to signal initial messages have been applied after becoming leader. 0 means signaling is disabled. + + leader string // The ID of the leader + vote string // Our current vote state + + s *Server // Reference to top-level server + c *client // Internal client for subscriptions + js *jetStream // JetStream, if running, to see if we are out of resources + + hasleader atomic.Bool // Is there a group leader right now? + pleader atomic.Bool // Has the group ever had a leader? + isSysAcc atomic.Bool // Are we utilizing the system account? + + extSt extensionState // Extension state + + track bool // Whether out of resources checking is enabled. + dflag bool // Debug flag + + psubj string // Proposals subject + rpsubj string // Remove peers subject + vsubj string // Vote requests subject + vreply string // Vote responses subject + asubj string // Append entries subject + areply string // Append entries responses subject + + sq *sendq // Send queue for outbound RPC messages + aesub *subscription // Subscription for handleAppendEntry callbacks + + wtv []byte // Term and vote to be written + wps []byte // Peer state to be written + + catchup *catchupState // For when we need to catch up as a follower. + progress map[string]*ipQueue[uint64] // For leader or server catching up a follower. + + hcommit uint64 // The commit at the time that applies were paused + + prop *ipQueue[*proposedEntry] // Proposals + entry *ipQueue[*appendEntry] // Append entries + resp *ipQueue[*appendEntryResponse] // Append entries responses + apply *ipQueue[*CommittedEntry] // Apply queue (committed entries to be passed to upper layer) + reqs *ipQueue[*voteRequest] // Vote requests + votes *ipQueue[*voteResponse] // Vote responses + leadc chan bool // Leader changes + quit chan struct{} // Raft group shutdown + + lxfer bool // Are we doing a leadership transfer? + hcbehind bool // Were we falling behind at the last health check? (see: isCurrent) + maybeLeader bool // The group had a preferred leader. And is maybe already acting as leader prior to scale up. + paused bool // Whether or not applies are paused + observer bool // The node is observing, i.e. not able to become leader + pobserver bool // Were we previously an observer? + membChanging bool // There is a membership change proposal in progress + deleted bool // If the node was deleted. +} + +type proposedEntry struct { + *Entry + reply string // Optional, to respond once proposal handled +} + +// cacthupState structure that holds our subscription, and catchup term and index +// as well as starting term and index and how many updates we have seen. +type catchupState struct { + sub *subscription // Subscription that catchup messages will arrive on + cterm uint64 // Catchup term + cindex uint64 // Catchup index + pterm uint64 // Starting term + pindex uint64 // Starting index + active time.Time // Last time we received a message for this catchup +} + +// lps holds peer state of last time and last index replicated. +type lps struct { + ts time.Time // Last timestamp + li uint64 // Last index replicated + kp bool // Known peer +} + +const ( + minElectionTimeoutDefault = 4 * time.Second + maxElectionTimeoutDefault = 9 * time.Second + minCampaignTimeoutDefault = 100 * time.Millisecond + maxCampaignTimeoutDefault = 8 * minCampaignTimeoutDefault + hbIntervalDefault = 1 * time.Second + lostQuorumIntervalDefault = hbIntervalDefault * 10 // 10 seconds + lostQuorumCheckIntervalDefault = hbIntervalDefault * 10 // 10 seconds + observerModeIntervalDefault = 48 * time.Hour + peerRemoveTimeoutDefault = 5 * time.Minute +) + +var ( + minElectionTimeout = minElectionTimeoutDefault + maxElectionTimeout = maxElectionTimeoutDefault + minCampaignTimeout = minCampaignTimeoutDefault + maxCampaignTimeout = maxCampaignTimeoutDefault + hbInterval = hbIntervalDefault + lostQuorumInterval = lostQuorumIntervalDefault + lostQuorumCheck = lostQuorumCheckIntervalDefault + observerModeInterval = observerModeIntervalDefault + peerRemoveTimeout = peerRemoveTimeoutDefault +) + +type RaftConfig struct { + Name string + Store string + Log WAL + Track bool + Observer bool +} + +var ( + errNotLeader = errors.New("raft: not leader") + errAlreadyLeader = errors.New("raft: already leader") + errNilCfg = errors.New("raft: no config given") + errCorruptPeers = errors.New("raft: corrupt peer state") + errEntryLoadFailed = errors.New("raft: could not load entry from WAL") + errEntryStoreFailed = errors.New("raft: could not store entry to WAL") + errNodeClosed = errors.New("raft: node is closed") + errNodeRemoved = errors.New("raft: peer was removed") + errBadSnapName = errors.New("raft: snapshot name could not be parsed") + errNoSnapAvailable = errors.New("raft: no snapshot available") + errCatchupsRunning = errors.New("raft: snapshot can not be installed while catchups running") + errSnapshotCorrupt = errors.New("raft: snapshot corrupt") + errTooManyPrefs = errors.New("raft: stepdown requires at most one preferred new leader") + errNoPeerState = errors.New("raft: no peerstate") + errAdjustBootCluster = errors.New("raft: can not adjust boot peer size on established group") + errLeaderLen = fmt.Errorf("raft: leader should be exactly %d bytes", idLen) + errTooManyEntries = errors.New("raft: append entry can contain a max of 64k entries") + errBadAppendEntry = errors.New("raft: append entry corrupt") + errNoInternalClient = errors.New("raft: no internal client") + errMembershipChange = errors.New("raft: membership change in progress") + errRemoveLastNode = errors.New("raft: cannot remove the last peer") +) + +// This will bootstrap a raftNode by writing its config into the store directory. +func (s *Server) bootstrapRaftNode(cfg *RaftConfig, knownPeers []string, allPeersKnown bool) error { + if cfg == nil { + return errNilCfg + } + // Check validity of peers if presented. + for _, p := range knownPeers { + if len(p) != idLen { + return fmt.Errorf("raft: illegal peer: %q", p) + } + } + expected := len(knownPeers) + // We need to adjust this is all peers are not known. + if !allPeersKnown { + s.Debugf("Determining expected peer size for JetStream meta group") + if expected < 2 { + expected = 2 + } + opts := s.getOpts() + nrs := len(opts.Routes) + + cn := s.ClusterName() + ngwps := 0 + for _, gw := range opts.Gateway.Gateways { + // Ignore our own cluster if specified. + if gw.Name == cn { + continue + } + for _, u := range gw.URLs { + host := u.Hostname() + // If this is an IP just add one. + if net.ParseIP(host) != nil { + ngwps++ + } else { + addrs, _ := net.LookupHost(host) + ngwps += len(addrs) + } + } + } + + if expected < nrs+ngwps { + expected = nrs + ngwps + s.Debugf("Adjusting expected peer set size to %d with %d known", expected, len(knownPeers)) + } + } + + // Check the store directory. If we have a memory based WAL we need to make sure the directory is setup. + if stat, err := os.Stat(cfg.Store); os.IsNotExist(err) { + if err := os.MkdirAll(cfg.Store, defaultDirPerms); err != nil { + return fmt.Errorf("raft: could not create storage directory - %v", err) + } + } else if stat == nil || !stat.IsDir() { + return fmt.Errorf("raft: storage directory is not a directory") + } + tmpfile, err := os.CreateTemp(cfg.Store, "_test_") + if err != nil { + return fmt.Errorf("raft: storage directory is not writable") + } + tmpfile.Close() + os.Remove(tmpfile.Name()) + + return writePeerState(cfg.Store, &peerState{knownPeers, expected, extUndetermined}) +} + +// initRaftNode will initialize the raft node, to be used by startRaftNode or when testing to not run the Go routine. +func (s *Server) initRaftNode(accName string, cfg *RaftConfig, labels pprofLabels) (*raft, error) { + if cfg == nil { + return nil, errNilCfg + } + s.mu.RLock() + if s.sys == nil { + s.mu.RUnlock() + return nil, ErrNoSysAccount + } + hash := s.sys.shash + s.mu.RUnlock() + + // Do this here to process error quicker. + ps, err := readPeerState(cfg.Store) + if err != nil { + return nil, err + } + if ps == nil { + return nil, errNoPeerState + } + + qpfx := fmt.Sprintf("[ACC:%s] RAFT '%s' ", accName, cfg.Name) + n := &raft{ + created: time.Now(), + id: hash[:idLen], + group: cfg.Name, + sd: cfg.Store, + wal: cfg.Log, + wtype: cfg.Log.Type(), + track: cfg.Track, + csz: ps.clusterSize, + qn: ps.clusterSize/2 + 1, + peers: make(map[string]*lps), + acks: make(map[uint64]map[string]struct{}), + pae: make(map[uint64]*appendEntry), + s: s, + js: s.getJetStream(), + quit: make(chan struct{}), + reqs: newIPQueue[*voteRequest](s, qpfx+"vreq"), + votes: newIPQueue[*voteResponse](s, qpfx+"vresp"), + prop: newIPQueue[*proposedEntry](s, qpfx+"entry"), + entry: newIPQueue[*appendEntry](s, qpfx+"appendEntry"), + resp: newIPQueue[*appendEntryResponse](s, qpfx+"appendEntryResponse"), + apply: newIPQueue[*CommittedEntry](s, qpfx+"committedEntry"), + accName: accName, + leadc: make(chan bool, 32), + observer: cfg.Observer, + extSt: ps.domainExt, + } + + // Setup our internal subscriptions for proposals, votes and append entries. + // If we fail to do this for some reason then this is fatal — we cannot + // continue setting up or the Raft node may be partially/totally isolated. + if err := n.RecreateInternalSubs(); err != nil { + n.shutdown() + return nil, err + } + + if atomic.LoadInt32(&s.logging.debug) > 0 { + n.dflag = true + } + + // Set up the highwayhash for the snapshots. + key := sha256.Sum256([]byte(n.group)) + n.hh, _ = highwayhash.NewDigest64(key[:]) + + // If we have a term and vote file (tav.idx on the filesystem) then read in + // what we think the term and vote was. It's possible these are out of date + // so a catch-up may be required. + if term, vote, err := n.readTermVote(); err == nil && term > 0 { + n.term = term + n.vote = vote + } + + // Can't recover snapshots if memory based since wal will be reset. + // We will inherit from the current leader. + n.papplied = 0 + if _, ok := n.wal.(*memStore); ok { + _ = os.RemoveAll(filepath.Join(n.sd, snapshotsDir)) + } else { + // See if we have any snapshots and if so load and process on startup. + n.setupLastSnapshot() + } + + // Make sure that the snapshots directory exists. + if err := os.MkdirAll(filepath.Join(n.sd, snapshotsDir), defaultDirPerms); err != nil { + return nil, fmt.Errorf("could not create snapshots directory - %v", err) + } + + truncateAndErr := func(index uint64) { + if err := n.wal.Truncate(index); err != nil { + n.setWriteErr(err) + } + } + + // Retrieve the stream state from the WAL. If there are pending append + // entries that were committed but not applied before we last shut down, + // we will try to replay them and process them here. + var state StreamState + n.wal.FastState(&state) + n.bytes = state.Bytes + + if state.Msgs > 0 { + n.debug("Replaying state of %d entries", state.Msgs) + if first, err := n.loadFirstEntry(); err == nil { + n.pterm, n.pindex = first.pterm, first.pindex + if first.commit > 0 && first.commit > n.commit { + n.commit = first.commit + } + } + + // This process will queue up entries on our applied queue but prior to the upper + // state machine running. So we will monitor how much we have queued and if we + // reach a limit will pause the apply queue and resume inside of run() go routine. + const maxQsz = 32 * 1024 * 1024 // 32MB max + + // It looks like there are entries we have committed but not applied + // yet. Replay them. + for index, qsz := state.FirstSeq, 0; index <= state.LastSeq; index++ { + ae, err := n.loadEntry(index) + if err != nil { + n.warn("Could not load %d from WAL [%+v]: %v", index, state, err) + // Truncate to the previous correct entry. + truncateAndErr(index - 1) + break + } + if ae.pindex != index-1 { + n.warn("Corrupt WAL, will truncate") + // Truncate to the previous correct entry. + truncateAndErr(index - 1) + break + } + n.processAppendEntry(ae, nil) + // Check how much we have queued up so far to determine if we should pause. + for _, e := range ae.entries { + qsz += len(e.Data) + if qsz > maxQsz && !n.paused { + n.PauseApply() + } + } + } + } + + // Make sure to track ourselves. + n.peers[n.id] = &lps{time.Now(), 0, true} + + // Track known peers + for _, peer := range ps.knownPeers { + if peer != n.id { + // Set these to 0 to start but mark as known peer. + n.peers[peer] = &lps{time.Time{}, 0, true} + } + } + + n.debug("Started") + + // Check if we need to start in observer mode due to lame duck status. + // This will stop us from taking on the leader role when we're about to + // shutdown anyway. + if s.isLameDuckMode() { + n.debug("Will start in observer mode due to lame duck status") + n.SetObserver(true) + } + + // Set the election timer and lost quorum timers to now, so that we + // won't accidentally trigger either state without knowing the real state + // of the other nodes. + n.Lock() + n.resetElectionTimeout() + n.llqrt = time.Now() + n.Unlock() + + // Register the Raft group. + labels["group"] = n.group + s.registerRaftNode(n.group, n) + + return n, nil +} + +// startRaftNode will start the raft node. +func (s *Server) startRaftNode(accName string, cfg *RaftConfig, labels pprofLabels) (RaftNode, error) { + n, err := s.initRaftNode(accName, cfg, labels) + if err != nil { + return nil, err + } + + // Start the run goroutine for the Raft state machine. + n.wg.Add(1) + s.startGoRoutine(n.run, labels) + + return n, nil +} + +// Returns whether peers within this group claim to support +// moving NRG traffic into the asset account. +// Lock must be held. +func (n *raft) checkAccountNRGStatus() bool { + if !n.s.accountNRGAllowed.Load() { + return false + } + enabled := true + for pn := range n.peers { + if si, ok := n.s.nodeToInfo.Load(pn); ok && si != nil { + enabled = enabled && si.(nodeInfo).accountNRG + } + } + return enabled +} + +// Whether we are using the system account or not. +func (n *raft) IsSystemAccount() bool { + return n.isSysAcc.Load() +} + +// GetTrafficAccountName returns the account name of the account used for replication traffic. +func (n *raft) GetTrafficAccountName() string { + n.RLock() + defer n.RUnlock() + return n.acc.GetName() +} + +func (n *raft) RecreateInternalSubs() error { + n.Lock() + defer n.Unlock() + return n.recreateInternalSubsLocked() +} + +func (n *raft) recreateInternalSubsLocked() error { + // Sanity check for system account, as it can disappear when + // the system is shutting down. + if n.s == nil { + return fmt.Errorf("server not found") + } + n.s.mu.RLock() + sys := n.s.sys + n.s.mu.RUnlock() + if sys == nil { + return fmt.Errorf("system account not found") + } + + // Default is the system account. + nrgAcc := sys.account + n.isSysAcc.Store(true) + + // Is account NRG enabled in this account and do all group + // peers claim to also support account NRG? + if n.checkAccountNRGStatus() { + // Check whether the account that the asset belongs to + // has volunteered a different NRG account. + target := nrgAcc.Name + if a, _ := n.s.lookupAccount(n.accName); a != nil { + a.mu.RLock() + if a.js != nil { + target = a.nrgAccount + } + a.mu.RUnlock() + } + + // If the target account exists, then we'll use that. + if target != _EMPTY_ { + if a, _ := n.s.lookupAccount(target); a != nil { + nrgAcc = a + if a != sys.account { + n.isSysAcc.Store(false) + } + } + } + } + if n.aesub != nil && n.acc == nrgAcc { + // Subscriptions already exist and the account NRG state + // hasn't changed. + return nil + } + + // Need to cancel any in-progress catch-ups, otherwise the + // inboxes are about to be pulled out from underneath it in + // the next step... + n.cancelCatchup() + + // If we have an existing client then tear down any existing + // subscriptions and close the internal client. + if c := n.c; c != nil { + c.mu.Lock() + subs := make([]*subscription, 0, len(c.subs)) + for _, sub := range c.subs { + subs = append(subs, sub) + } + c.mu.Unlock() + for _, sub := range subs { + n.unsubscribe(sub) + } + c.closeConnection(InternalClient) + } + + if n.acc != nrgAcc { + n.debug("Subscribing in '%s'", nrgAcc.GetName()) + } + + c := n.s.createInternalSystemClient() + c.registerWithAccount(nrgAcc) + if nrgAcc.sq == nil { + nrgAcc.sq = n.s.newSendQ(nrgAcc) + } + n.c = c + n.sq = nrgAcc.sq + n.acc = nrgAcc + + // Recreate any internal subscriptions for voting, append + // entries etc in the new account. + return n.createInternalSubs() +} + +// outOfResources checks to see if we are out of resources. +func (n *raft) outOfResources() bool { + js := n.js + if !n.track || js == nil { + return false + } + return js.limitsExceeded(n.wtype) +} + +// Maps node names back to server names. +func (s *Server) serverNameForNode(node string) string { + if si, ok := s.nodeToInfo.Load(node); ok && si != nil { + return si.(nodeInfo).name + } + return _EMPTY_ +} + +// Maps node names back to cluster names. +func (s *Server) clusterNameForNode(node string) string { + if si, ok := s.nodeToInfo.Load(node); ok && si != nil { + return si.(nodeInfo).cluster + } + return _EMPTY_ +} + +// Registers the Raft node with the server, as it will track all of the Raft +// nodes. +func (s *Server) registerRaftNode(group string, n RaftNode) { + s.rnMu.Lock() + defer s.rnMu.Unlock() + if s.raftNodes == nil { + s.raftNodes = make(map[string]RaftNode) + } + s.raftNodes[group] = n +} + +// Unregisters the Raft node from the server, i.e. at shutdown. +func (s *Server) unregisterRaftNode(group string) { + s.rnMu.Lock() + defer s.rnMu.Unlock() + if s.raftNodes != nil { + delete(s.raftNodes, group) + } +} + +// Returns how many Raft nodes are running in this server instance. +func (s *Server) numRaftNodes() int { + s.rnMu.RLock() + defer s.rnMu.RUnlock() + return len(s.raftNodes) +} + +// Finds the Raft node for a given Raft group, if any. If there is no Raft node +// running for this group then it can return nil. +func (s *Server) lookupRaftNode(group string) RaftNode { + s.rnMu.RLock() + defer s.rnMu.RUnlock() + var n RaftNode + if s.raftNodes != nil { + n = s.raftNodes[group] + } + return n +} + +// Reloads the debug state for all running Raft nodes. This is necessary when +// the configuration has been reloaded and the debug log level has changed. +func (s *Server) reloadDebugRaftNodes(debug bool) { + if s == nil { + return + } + s.rnMu.RLock() + for _, ni := range s.raftNodes { + n := ni.(*raft) + n.Lock() + n.dflag = debug + n.Unlock() + } + s.rnMu.RUnlock() +} + +// Requests that all Raft nodes on this server step down and place them into +// observer mode. This is called when the server is shutting down. +func (s *Server) stepdownRaftNodes() { + if s == nil { + return + } + s.rnMu.RLock() + if len(s.raftNodes) == 0 { + s.rnMu.RUnlock() + return + } + s.Debugf("Stepping down all leader raft nodes") + nodes := make([]RaftNode, 0, len(s.raftNodes)) + for _, n := range s.raftNodes { + nodes = append(nodes, n) + } + s.rnMu.RUnlock() + + for _, node := range nodes { + node.StepDown() + node.SetObserver(true) + } +} + +// Shuts down all Raft nodes on this server. This is called either when the +// server is either entering lame duck mode, shutting down or when JetStream +// has been disabled. +func (s *Server) shutdownRaftNodes() { + if s == nil { + return + } + s.rnMu.RLock() + if len(s.raftNodes) == 0 { + s.rnMu.RUnlock() + return + } + nodes := make([]RaftNode, 0, len(s.raftNodes)) + s.Debugf("Shutting down all raft nodes") + for _, n := range s.raftNodes { + nodes = append(nodes, n) + } + s.rnMu.RUnlock() + + for _, node := range nodes { + node.Stop() + } +} + +// Used in lameduck mode to move off the leaders. +// We also put all nodes in observer mode so new leaders +// can not be placed on this server. +func (s *Server) transferRaftLeaders() bool { + if s == nil { + return false + } + s.rnMu.RLock() + if len(s.raftNodes) == 0 { + s.rnMu.RUnlock() + return false + } + nodes := make([]RaftNode, 0, len(s.raftNodes)) + for _, n := range s.raftNodes { + nodes = append(nodes, n) + } + s.rnMu.RUnlock() + + var didTransfer bool + for _, node := range nodes { + if err := node.StepDown(); err == nil { + didTransfer = true + } + node.SetObserver(true) + } + return didTransfer +} + +// Formal API + +// Propose will propose a new entry to the group. +// This should only be called on the leader. +func (n *raft) Propose(data []byte) error { + n.Lock() + defer n.Unlock() + // Check state under lock, we might not be leader anymore. + if state := n.State(); state != Leader { + n.debug("Proposal ignored, not leader (state: %v)", state) + return errNotLeader + } + + // Error if we had a previous write error. + if werr := n.werr; werr != nil { + return werr + } + n.prop.push(newProposedEntry(newEntry(EntryNormal, data), _EMPTY_)) + return nil +} + +// ProposeDirect will propose multiple entries at once. +// This should only be called on the leader. +func (n *raft) ProposeMulti(entries []*Entry) error { + n.Lock() + defer n.Unlock() + // Check state under lock, we might not be leader anymore. + if state := n.State(); state != Leader { + n.debug("Direct proposal ignored, not leader (state: %v)", state) + return errNotLeader + } + + // Error if we had a previous write error. + if werr := n.werr; werr != nil { + return werr + } + for _, e := range entries { + n.prop.push(newProposedEntry(e, _EMPTY_)) + } + return nil +} + +// ForwardProposal will forward the proposal to the leader if known. +// If we are the leader this is the same as calling propose. +func (n *raft) ForwardProposal(entry []byte) error { + if n.State() == Leader { + return n.Propose(entry) + } + + // TODO: Currently we do not set a reply subject, even though we are + // now capable of responding. Do this once enough time has passed, + // i.e. maybe in 2.12. + n.sendRPC(n.psubj, _EMPTY_, entry) + return nil +} + +// ProposeAddPeer is called to add a peer to the group. +func (n *raft) ProposeAddPeer(peer string) error { + n.Lock() + // Check state under lock, we might not be leader anymore. + if n.State() != Leader { + n.Unlock() + return errNotLeader + } + // Error if we had a previous write error. + if werr := n.werr; werr != nil { + n.Unlock() + return werr + } + if n.membChanging { + n.Unlock() + return errMembershipChange + } + prop := n.prop + n.membChanging = true + n.Unlock() + + prop.push(newProposedEntry(newEntry(EntryAddPeer, []byte(peer)), _EMPTY_)) + return nil +} + +// ProposeRemovePeer is called to remove a peer from the group. +func (n *raft) ProposeRemovePeer(peer string) error { + n.Lock() + + // Error if we had a previous write error. + if werr := n.werr; werr != nil { + n.Unlock() + return werr + } + + if n.State() != Leader { + subj := n.rpsubj + n.Unlock() + + // Forward the proposal to the leader + n.sendRPC(subj, _EMPTY_, []byte(peer)) + return nil + } + + if n.membChanging { + n.Unlock() + return errMembershipChange + } + + if len(n.peers) <= 1 { + n.Unlock() + return errRemoveLastNode + } + + prop := n.prop + n.membChanging = true + n.Unlock() + + prop.push(newProposedEntry(newEntry(EntryRemovePeer, []byte(peer)), _EMPTY_)) + return nil +} + +func (n *raft) MembershipChangeInProgress() bool { + n.RLock() + defer n.RUnlock() + return n.membChanging +} + +// ClusterSize reports back the total cluster size. +// This effects quorum etc. +func (n *raft) ClusterSize() int { + n.Lock() + defer n.Unlock() + return n.csz +} + +// AdjustBootClusterSize can be called to adjust the boot cluster size. +// Will error if called on a group with a leader or a previous leader. +// This can be helpful in mixed mode. +func (n *raft) AdjustBootClusterSize(csz int) error { + n.Lock() + defer n.Unlock() + + if n.leader != noLeader || n.pleader.Load() { + return errAdjustBootCluster + } + // Same floor as bootstrap. + if csz < 2 { + csz = 2 + } + // Adjust the cluster size and the number of nodes needed to establish + // a quorum. + n.csz = csz + n.qn = n.csz/2 + 1 + + return nil +} + +// AdjustClusterSize will change the cluster set size. +// Must be the leader. +func (n *raft) AdjustClusterSize(csz int) error { + n.Lock() + defer n.Unlock() + + // Check state under lock, we might not be leader anymore. + if n.State() != Leader { + return errNotLeader + } + // Same floor as bootstrap. + if csz < 2 { + csz = 2 + } + + // Adjust the cluster size and the number of nodes needed to establish + // a quorum. + n.csz = csz + n.qn = n.csz/2 + 1 + + n.sendPeerState() + return nil +} + +// PauseApply will allow us to pause processing of append entries onto our +// external apply queue. In effect this means that the upper layer will no longer +// receive any new entries from the Raft group. +func (n *raft) PauseApply() error { + if n.State() == Leader { + return errAlreadyLeader + } + n.Lock() + defer n.Unlock() + n.pauseApplyLocked() + return nil +} + +func (n *raft) pauseApplyLocked() { + // If we are currently a candidate make sure we step down. + if n.State() == Candidate { + n.stepdownLocked(noLeader) + } + + n.debug("Pausing our apply channel") + n.paused = true + if n.hcommit < n.commit { + n.hcommit = n.commit + } + // Also prevent us from trying to become a leader while paused and catching up. + n.pobserver, n.observer = n.observer, true + n.resetElect(observerModeInterval) +} + +// ResumeApply will resume sending applies to the external apply queue. This +// means that we will start sending new entries to the upper layer. +func (n *raft) ResumeApply() { + n.Lock() + defer n.Unlock() + + if !n.paused { + return + } + + n.debug("Resuming our apply channel") + + // Reset before we start. + n.resetElectionTimeout() + + // Run catchup.. + if n.hcommit > n.commit { + n.debug("Resuming %d replays", n.hcommit+1-n.commit) + for index := n.commit + 1; index <= n.hcommit; index++ { + if err := n.applyCommit(index); err != nil { + n.warn("Got error on apply commit during replay: %v", err) + break + } + // We want to unlock here to allow the upper layers to call Applied() without blocking. + n.Unlock() + // Give hint to let other Go routines run. + // Might not be necessary but seems to make it more fine grained interleaving. + runtime.Gosched() + // Simply re-acquire + n.Lock() + // Need to check if we got closed. + if n.State() == Closed { + return + } + } + } + + // Clear our observer and paused state after we apply. + n.observer, n.pobserver = n.pobserver, false + n.paused = false + n.hcommit = 0 + + // If we had been selected to be the next leader campaign here now that we have resumed. + if n.lxfer { + n.xferCampaign() + } else { + n.resetElectionTimeout() + } +} + +// DrainAndReplaySnapshot will drain the apply queue and replay the snapshot. +// Our highest known commit will be preserved by pausing applies. The caller +// should make sure to call ResumeApply() when handling the snapshot from the +// queue, which will populate the rest of the committed entries in the queue. +func (n *raft) DrainAndReplaySnapshot() bool { + n.Lock() + defer n.Unlock() + snap, err := n.loadLastSnapshot() + if err != nil { + return false + } + n.warn("Draining and replaying snapshot") + n.pauseApplyLocked() + n.apply.drain() + n.commit = snap.lastIndex + n.apply.push(newCommittedEntry(n.commit, []*Entry{{EntrySnapshot, snap.data}})) + return true +} + +// Applied is a callback that must be called by the upper layer when it +// has successfully applied the committed entries that it received from the +// apply queue. It will return the number of entries and an estimation of the +// byte size that could be removed with a snapshot/compact. +func (n *raft) Applied(index uint64) (entries uint64, bytes uint64) { + n.Lock() + defer n.Unlock() + + // Ignore if not applicable. This can happen during a reset. + if index > n.commit { + return 0, 0 + } + + // Ignore if already applied. + if index > n.applied { + n.applied = index + } + + // If it was set, and we reached the minimum applied index, reset and send signal to upper layer. + if n.aflr > 0 && index >= n.aflr { + n.aflr = 0 + // Quick sanity-check to confirm we're still leader. + // In which case we must signal, since switchToLeader would not have done so already. + if n.State() == Leader { + if !n.leaderState.Swap(true) { + // Only update timestamp if leader state actually changed. + nowts := time.Now().UTC() + n.leaderSince.Store(&nowts) + } + n.updateLeadChange(true) + } + } + + // Calculate the number of entries and estimate the byte size that + // we can now remove with a compaction/snapshot. + if n.applied > n.papplied { + entries = n.applied - n.papplied + } + if msgs := n.pindex - n.papplied; msgs > 0 { + bytes = entries * n.bytes / msgs + } + return entries, bytes +} + +// For capturing data needed by snapshot. +type snapshot struct { + lastTerm uint64 + lastIndex uint64 + peerstate []byte + data []byte +} + +const minSnapshotLen = 28 + +// Encodes a snapshot into a buffer for storage. +// Lock should be held. +func (n *raft) encodeSnapshot(snap *snapshot) []byte { + if snap == nil { + return nil + } + var le = binary.LittleEndian + buf := make([]byte, minSnapshotLen+len(snap.peerstate)+len(snap.data)) + le.PutUint64(buf[0:], snap.lastTerm) + le.PutUint64(buf[8:], snap.lastIndex) + // Peer state + le.PutUint32(buf[16:], uint32(len(snap.peerstate))) + wi := 20 + copy(buf[wi:], snap.peerstate) + wi += len(snap.peerstate) + // data itself. + copy(buf[wi:], snap.data) + wi += len(snap.data) + + // Now do the hash for the end. + n.hh.Reset() + n.hh.Write(buf[:wi]) + var hb [highwayhash.Size64]byte + checksum := n.hh.Sum(hb[:0]) + copy(buf[wi:], checksum) + wi += len(checksum) + return buf[:wi] +} + +// SendSnapshot will send the latest snapshot as a normal AE. +// Should only be used when the upper layers know this is most recent. +// Used when restoring streams, moving a stream from R1 to R>1, etc. +func (n *raft) SendSnapshot(data []byte) error { + n.Lock() + defer n.Unlock() + // Don't check if we're leader before sending and storing, this is used on scaleup. + n.sendAppendEntryLocked([]*Entry{{EntrySnapshot, data}}, false) + return nil +} + +// Used to install a snapshot for the given term and applied index. This will release +// all of the log entries up to and including index. This should not be called with +// entries that have been applied to the FSM but have not been applied to the raft state. +func (n *raft) InstallSnapshot(data []byte) error { + if n.State() == Closed { + return errNodeClosed + } + + n.Lock() + defer n.Unlock() + + // If a write error has occurred already then stop here. + if werr := n.werr; werr != nil { + return werr + } + + // Check that a catchup isn't already taking place. If it is then we won't + // allow installing snapshots until it is done. + if len(n.progress) > 0 || n.paused { + return errCatchupsRunning + } + + if n.applied == 0 { + n.debug("Not snapshotting as there are no applied entries") + return errNoSnapAvailable + } + + var term uint64 + if ae, _ := n.loadEntry(n.applied); ae != nil { + term = ae.term + } else { + n.debug("Not snapshotting as entry %d is not available", n.applied) + return errNoSnapAvailable + } + + n.debug("Installing snapshot of %d bytes [%d:%d]", len(data), term, n.applied) + + return n.installSnapshot(&snapshot{ + lastTerm: term, + lastIndex: n.applied, + peerstate: encodePeerState(&peerState{n.peerNames(), n.csz, n.extSt}), + data: data, + }) +} + +// Install the snapshot. +// Lock should be held. +func (n *raft) installSnapshot(snap *snapshot) error { + snapDir := filepath.Join(n.sd, snapshotsDir) + sn := fmt.Sprintf(snapFileT, snap.lastTerm, snap.lastIndex) + sfile := filepath.Join(snapDir, sn) + + if err := writeFileWithSync(sfile, n.encodeSnapshot(snap), defaultFilePerms); err != nil { + // We could set write err here, but if this is a temporary situation, too many open files etc. + // we want to retry and snapshots are not fatal. + return err + } + + // Delete our previous snapshot file if it exists. + if n.snapfile != _EMPTY_ && n.snapfile != sfile { + os.Remove(n.snapfile) + } + // Remember our latest snapshot file. + n.snapfile = sfile + if _, err := n.wal.Compact(snap.lastIndex + 1); err != nil { + n.setWriteErrLocked(err) + return err + } + + var state StreamState + n.wal.FastState(&state) + n.papplied = snap.lastIndex + n.bytes = state.Bytes + return nil +} + +// NeedSnapshot returns true if it is necessary to try to install a snapshot, i.e. +// after we have finished recovering/replaying at startup, on a regular interval or +// as a part of cleaning up when shutting down. +func (n *raft) NeedSnapshot() bool { + n.RLock() + defer n.RUnlock() + return n.snapfile == _EMPTY_ && n.applied > 1 +} + +const ( + snapshotsDir = "snapshots" + snapFileT = "snap.%d.%d" +) + +// termAndIndexFromSnapfile tries to load the snapshot file and returns the term +// and index from that snapshot. +func termAndIndexFromSnapFile(sn string) (term, index uint64, err error) { + if sn == _EMPTY_ { + return 0, 0, errBadSnapName + } + fn := filepath.Base(sn) + if n, err := fmt.Sscanf(fn, snapFileT, &term, &index); err != nil || n != 2 { + return 0, 0, errBadSnapName + } + return term, index, nil +} + +// setupLastSnapshot is called at startup to try and recover the last snapshot from +// the disk if possible. We will try to recover the term, index and commit/applied +// indices and then notify the upper layer what we found. Compacts the WAL if needed. +func (n *raft) setupLastSnapshot() { + snapDir := filepath.Join(n.sd, snapshotsDir) + psnaps, err := os.ReadDir(snapDir) + if err != nil { + return + } + + var lterm, lindex uint64 + var latest string + for _, sf := range psnaps { + sfile := filepath.Join(snapDir, sf.Name()) + var term, index uint64 + term, index, err := termAndIndexFromSnapFile(sf.Name()) + if err == nil { + if term > lterm { + lterm, lindex = term, index + latest = sfile + } else if term == lterm && index > lindex { + lindex = index + latest = sfile + } + } else { + // Clean this up, can't parse the name. + // TODO(dlc) - We could read in and check actual contents. + n.debug("Removing snapshot, can't parse name: %q", sf.Name()) + os.Remove(sfile) + } + } + + // Now cleanup any old entries + for _, sf := range psnaps { + sfile := filepath.Join(snapDir, sf.Name()) + if sfile != latest { + n.debug("Removing old snapshot: %q", sfile) + os.Remove(sfile) + } + } + + if latest == _EMPTY_ { + return + } + + // Set latest snapshot we have. + n.Lock() + defer n.Unlock() + + n.snapfile = latest + snap, err := n.loadLastSnapshot() + if err != nil { + // We failed to recover the last snapshot for some reason, so we will + // assume it has been corrupted and will try to delete it. + if n.snapfile != _EMPTY_ { + os.Remove(n.snapfile) + n.snapfile = _EMPTY_ + } + return + } + + // We successfully recovered the last snapshot from the disk. + // Recover state from the snapshot and then notify the upper layer. + // Compact the WAL when we're done if needed. + n.pindex = snap.lastIndex + n.pterm = snap.lastTerm + // Explicitly only set commit, and not applied. + // Applied will move up when the snapshot is actually applied. + n.commit = snap.lastIndex + n.papplied = snap.lastIndex + n.apply.push(newCommittedEntry(n.commit, []*Entry{{EntrySnapshot, snap.data}})) + if _, err := n.wal.Compact(snap.lastIndex + 1); err != nil { + n.setWriteErrLocked(err) + } +} + +// loadLastSnapshot will load and return our last snapshot. +// Lock should be held. +func (n *raft) loadLastSnapshot() (*snapshot, error) { + if n.snapfile == _EMPTY_ { + return nil, errNoSnapAvailable + } + + <-dios + buf, err := os.ReadFile(n.snapfile) + dios <- struct{}{} + + if err != nil { + n.warn("Error reading snapshot: %v", err) + os.Remove(n.snapfile) + n.snapfile = _EMPTY_ + return nil, err + } + if len(buf) < minSnapshotLen { + n.warn("Snapshot corrupt, too short") + os.Remove(n.snapfile) + n.snapfile = _EMPTY_ + return nil, errSnapshotCorrupt + } + + // Check to make sure hash is consistent. + hoff := len(buf) - 8 + lchk := buf[hoff:] + n.hh.Reset() + n.hh.Write(buf[:hoff]) + var hb [highwayhash.Size64]byte + if !bytes.Equal(lchk[:], n.hh.Sum(hb[:0])) { + n.warn("Snapshot corrupt, checksums did not match") + os.Remove(n.snapfile) + n.snapfile = _EMPTY_ + return nil, errSnapshotCorrupt + } + + var le = binary.LittleEndian + lps := le.Uint32(buf[16:]) + snap := &snapshot{ + lastTerm: le.Uint64(buf[0:]), + lastIndex: le.Uint64(buf[8:]), + peerstate: buf[20 : 20+lps], + data: buf[20+lps : hoff], + } + + // We had a bug in 2.9.12 that would allow snapshots on last index of 0. + // Detect that here and return err. + if snap.lastIndex == 0 { + n.warn("Snapshot with last index 0 is invalid, cleaning up") + os.Remove(n.snapfile) + n.snapfile = _EMPTY_ + return nil, errSnapshotCorrupt + } + + return snap, nil +} + +// Leader returns if we are the leader for our group. +// We use an atomic here now vs acquiring the read lock. +func (n *raft) Leader() bool { + if n == nil { + return false + } + return n.leaderState.Load() +} + +// LeaderSince returns how long we have been leader for, +// if applicable. +func (n *raft) LeaderSince() *time.Time { + if n == nil { + return nil + } + return n.leaderSince.Load() +} + +// stepdown immediately steps down the Raft node to the +// follower state. This will take the lock itself. +func (n *raft) stepdown(newLeader string) { + n.Lock() + defer n.Unlock() + n.stepdownLocked(newLeader) +} + +// stepdownLocked immediately steps down the Raft node to the +// follower state. This requires the lock is already held. +func (n *raft) stepdownLocked(newLeader string) { + n.debug("Stepping down") + n.switchToFollowerLocked(newLeader) +} + +// isCatchingUp returns true if a catchup is currently taking place. +func (n *raft) isCatchingUp() bool { + n.RLock() + defer n.RUnlock() + return n.catchup != nil +} + +// isCurrent is called from the healthchecks and returns true if we believe +// that the upper layer is current with the Raft layer, i.e. that it has applied +// all of the commits that we have given it. +// Optionally we can also check whether or not we're making forward progress if we +// aren't current, in which case this function may block for up to ~10ms to find out. +// Lock should be held. +func (n *raft) isCurrent(includeForwardProgress bool) bool { + // Check if we are closed. + if n.State() == Closed { + n.debug("Not current, node is closed") + return false + } + + // Check whether we've made progress on any state, 0 is invalid so not healthy. + if n.commit == 0 { + n.debug("Not current, no commits") + return false + } + + // If we were previously logging about falling behind, also log when the problem + // was cleared. + clearBehindState := func() { + if n.hcbehind { + n.warn("Health check OK, no longer falling behind") + n.hcbehind = false + } + } + + // Make sure we are the leader or we know we have heard from the leader recently. + if n.State() == Leader { + clearBehindState() + return true + } + + // Check to see that we have heard from the current leader lately. + if n.leader != noLeader && n.leader != n.id && n.catchup == nil { + okInterval := hbInterval * 2 + if ps := n.peers[n.leader]; ps == nil || time.Since(ps.ts) > okInterval { + n.debug("Not current, no recent leader contact") + return false + } + } + if cs := n.catchup; cs != nil { + // We're actively catching up, can't mark current even if commit==applied. + n.debug("Not current, still catching up pindex=%d, cindex=%d", n.pindex, cs.cindex) + return false + } + + if n.paused && n.hcommit > n.commit { + // We're currently paused, waiting to be resumed to apply pending commits. + n.debug("Not current, waiting to resume applies commit=%d, hcommit=%d", n.commit, n.hcommit) + return false + } + + if n.commit == n.applied { + // At this point if we are current, we can return saying so. + clearBehindState() + return true + } else if !includeForwardProgress { + // Otherwise, if we aren't allowed to include forward progress + // (i.e. we are checking "current" instead of "healthy") then + // give up now. + return false + } + + // Otherwise, wait for a short period of time and see if we are making any + // forward progress. + if startDelta := n.commit - n.applied; startDelta > 0 { + for i := 0; i < 10; i++ { // 10ms, in 1ms increments + n.Unlock() + time.Sleep(time.Millisecond) + n.Lock() + if n.commit-n.applied < startDelta { + // The gap is getting smaller, so we're making forward progress. + clearBehindState() + return true + } + } + } + + n.hcbehind = true + n.warn("Falling behind in health check, commit %d != applied %d", n.commit, n.applied) + return false +} + +// Current returns if we are the leader for our group or an up to date follower. +func (n *raft) Current() bool { + if n == nil { + return false + } + n.Lock() + defer n.Unlock() + return n.isCurrent(false) +} + +// Healthy returns if we are the leader for our group and nearly up-to-date. +func (n *raft) Healthy() bool { + if n == nil { + return false + } + n.Lock() + defer n.Unlock() + return n.isCurrent(true) +} + +// HadPreviousLeader indicates if this group ever had a leader. +func (n *raft) HadPreviousLeader() bool { + return n.pleader.Load() +} + +// GroupLeader returns the current leader of the group. +func (n *raft) GroupLeader() string { + if n == nil { + return noLeader + } + n.RLock() + defer n.RUnlock() + return n.leader +} + +// Leaderless is a lockless way of finding out if the group has a +// leader or not. Use instead of GroupLeader in hot paths. +func (n *raft) Leaderless() bool { + if n == nil { + return true + } + // Negated because we want the default state of hasLeader to be + // false until the first setLeader() call. + return !n.hasleader.Load() +} + +// Guess the best next leader. Stepdown will check more thoroughly. +// Lock should be held. +func (n *raft) selectNextLeader() string { + nextLeader, hli := noLeader, uint64(0) + for peer, ps := range n.peers { + if peer == n.id || ps.li <= hli { + continue + } + hli = ps.li + nextLeader = peer + } + return nextLeader +} + +// StepDown will have a leader stepdown and optionally do a leader transfer. +func (n *raft) StepDown(preferred ...string) error { + n.Lock() + // Check state under lock, we might not be leader anymore. + if n.State() != Leader { + n.Unlock() + return errNotLeader + } + if len(preferred) > 1 { + n.Unlock() + return errTooManyPrefs + } + + n.debug("Being asked to stepdown") + + // See if we have up to date followers. + maybeLeader := noLeader + if len(preferred) > 0 { + if preferred[0] != _EMPTY_ { + maybeLeader = preferred[0] + } else { + preferred = nil + } + } + + // Can't pick ourselves. + if maybeLeader == n.id { + maybeLeader = noLeader + preferred = nil + } + + // If we have a preferred check it first. + if maybeLeader != noLeader { + var isHealthy bool + if ps, ok := n.peers[maybeLeader]; ok { + si, ok := n.s.nodeToInfo.Load(maybeLeader) + isHealthy = ok && !si.(nodeInfo).offline && time.Since(ps.ts) < hbInterval*3 + } + if !isHealthy { + maybeLeader = noLeader + } + } + + // If we do not have a preferred at this point pick the first healthy one. + // Make sure not ourselves. + if maybeLeader == noLeader { + for peer, ps := range n.peers { + if peer == n.id { + continue + } + si, ok := n.s.nodeToInfo.Load(peer) + isHealthy := ok && !si.(nodeInfo).offline && time.Since(ps.ts) < hbInterval*3 + if isHealthy { + maybeLeader = peer + break + } + } + } + n.Unlock() + + if len(preferred) > 0 && maybeLeader == noLeader { + n.debug("Can not transfer to preferred peer %q", preferred[0]) + } + + // If we have a new leader selected, transfer over to them. + // Send the append entry directly rather than via the proposals queue, + // as we will switch to follower state immediately and will blow away + // the contents of the proposal queue in the process. + if maybeLeader != noLeader { + n.debug("Selected %q for new leader, stepping down due to leadership transfer", maybeLeader) + ae := newEntry(EntryLeaderTransfer, []byte(maybeLeader)) + n.sendAppendEntry([]*Entry{ae}) + } + + // Force us to stepdown here. + n.stepdown(noLeader) + + return nil +} + +// Campaign will have our node start a leadership vote. +func (n *raft) Campaign() error { + n.Lock() + defer n.Unlock() + return n.campaign(randCampaignTimeout()) +} + +// CampaignImmediately will have our node start a leadership vote after minimal delay. +func (n *raft) CampaignImmediately() error { + n.Lock() + defer n.Unlock() + n.maybeLeader = true + return n.campaign(minCampaignTimeout / 2) +} + +func randCampaignTimeout() time.Duration { + delta := rand.Int63n(int64(maxCampaignTimeout - minCampaignTimeout)) + return (minCampaignTimeout + time.Duration(delta)) +} + +// Campaign will have our node start a leadership vote. +// Lock should be held. +func (n *raft) campaign(et time.Duration) error { + n.debug("Starting campaign") + if n.State() == Leader { + return errAlreadyLeader + } + n.resetElect(et) + return nil +} + +// xferCampaign will have our node start an immediate leadership vote. +// Lock should be held. +func (n *raft) xferCampaign() error { + n.debug("Starting transfer campaign") + if n.State() == Leader { + n.lxfer = false + return errAlreadyLeader + } + n.resetElect(10 * time.Millisecond) + return nil +} + +// State returns the current state for this node. +// Upper layers should not check State to check if we're Leader, use n.Leader() instead. +func (n *raft) State() RaftState { + return RaftState(n.state.Load()) +} + +// Progress returns the current index, commit and applied values. +func (n *raft) Progress() (index, commit, applied uint64) { + n.RLock() + defer n.RUnlock() + return n.pindex, n.commit, n.applied +} + +// Size returns number of entries and total bytes for our WAL. +func (n *raft) Size() (entries uint64, bytes uint64) { + n.RLock() + entries = n.pindex - n.papplied + bytes = n.bytes + n.RUnlock() + return entries, bytes +} + +func (n *raft) ID() string { + if n == nil { + return _EMPTY_ + } + // Lock not needed as n.id is never changed after creation. + return n.id +} + +func (n *raft) Group() string { + // Lock not needed as n.group is never changed after creation. + return n.group +} + +func (n *raft) Peers() []*Peer { + n.RLock() + defer n.RUnlock() + + var peers []*Peer + for id, ps := range n.peers { + var lag uint64 + if n.commit > ps.li { + lag = n.commit - ps.li + } + p := &Peer{ + ID: id, + Current: id == n.leader || ps.li >= n.applied, + Last: ps.ts, + Lag: lag, + } + peers = append(peers, p) + } + return peers +} + +// Update and propose our known set of peers. +func (n *raft) ProposeKnownPeers(knownPeers []string) { + n.Lock() + defer n.Unlock() + // If we are the leader update and send this update out. + if n.State() != Leader { + return + } + n.updateKnownPeersLocked(knownPeers) + n.sendPeerState() +} + +// Update our known set of peers. +func (n *raft) UpdateKnownPeers(knownPeers []string) { + n.Lock() + n.updateKnownPeersLocked(knownPeers) + n.Unlock() +} + +func (n *raft) updateKnownPeersLocked(knownPeers []string) { + // Process like peer state update. + ps := &peerState{knownPeers, len(knownPeers), n.extSt} + n.processPeerState(ps) +} + +// ApplyQ returns the apply queue that new commits will be sent to for the +// upper layer to apply. +func (n *raft) ApplyQ() *ipQueue[*CommittedEntry] { return n.apply } + +// LeadChangeC returns the leader change channel, notifying when the Raft +// leader role has moved. +func (n *raft) LeadChangeC() <-chan bool { return n.leadc } + +// QuitC returns the quit channel, notifying when the Raft group has shut down. +func (n *raft) QuitC() <-chan struct{} { return n.quit } + +func (n *raft) Created() time.Time { + // Lock not needed as n.created is never changed after creation. + return n.created +} + +func (n *raft) Stop() { + n.shutdown() +} + +func (n *raft) WaitForStop() { + if n.state.Load() == int32(Closed) { + n.wg.Wait() + } +} + +func (n *raft) Delete() { + n.shutdown() + n.wg.Wait() + + n.Lock() + defer n.Unlock() + + n.deleted = true + if wal := n.wal; wal != nil { + wal.Delete() + } + os.RemoveAll(n.sd) + n.debug("Deleted") +} + +func (n *raft) IsDeleted() bool { + n.RLock() + defer n.RUnlock() + return n.deleted +} + +func (n *raft) shutdown() { + // First call to Stop or Delete should close the quit chan + // to notify the runAs goroutines to stop what they're doing. + if n.state.Swap(int32(Closed)) != int32(Closed) { + n.leaderState.Store(false) + n.leaderSince.Store(nil) + close(n.quit) + } +} + +const ( + raftAllSubj = "$NRG.>" + raftVoteSubj = "$NRG.V.%s" + raftAppendSubj = "$NRG.AE.%s" + raftPropSubj = "$NRG.P.%s" + raftRemovePeerSubj = "$NRG.RP.%s" + raftReply = "$NRG.R.%s" + raftCatchupReply = "$NRG.CR.%s" +) + +// Lock should be held (due to use of random generator) +func (n *raft) newCatchupInbox() string { + var b [replySuffixLen]byte + rn := fastrand.Uint64() + for i, l := 0, rn; i < len(b); i++ { + b[i] = digits[l%base] + l /= base + } + return fmt.Sprintf(raftCatchupReply, b[:]) +} + +func (n *raft) newInbox() string { + var b [replySuffixLen]byte + rn := fastrand.Uint64() + for i, l := 0, rn; i < len(b); i++ { + b[i] = digits[l%base] + l /= base + } + return fmt.Sprintf(raftReply, b[:]) +} + +// Our internal subscribe. +// Lock should be held. +func (n *raft) subscribe(subject string, cb msgHandler) (*subscription, error) { + if n.c == nil { + return nil, errNoInternalClient + } + return n.s.systemSubscribe(subject, _EMPTY_, false, n.c, cb) +} + +// Lock should be held. +func (n *raft) unsubscribe(sub *subscription) { + if n.c != nil && sub != nil { + n.c.processUnsub(sub.sid) + } +} + +// Lock should be held. +func (n *raft) createInternalSubs() error { + n.vsubj, n.vreply = fmt.Sprintf(raftVoteSubj, n.group), n.newInbox() + n.asubj, n.areply = fmt.Sprintf(raftAppendSubj, n.group), n.newInbox() + n.psubj = fmt.Sprintf(raftPropSubj, n.group) + n.rpsubj = fmt.Sprintf(raftRemovePeerSubj, n.group) + + // Votes + if _, err := n.subscribe(n.vreply, n.handleVoteResponse); err != nil { + return err + } + if _, err := n.subscribe(n.vsubj, n.handleVoteRequest); err != nil { + return err + } + // AppendEntry + if _, err := n.subscribe(n.areply, n.handleAppendEntryResponse); err != nil { + return err + } + if sub, err := n.subscribe(n.asubj, n.handleAppendEntry); err != nil { + return err + } else { + n.aesub = sub + } + + return nil +} + +func randElectionTimeout() time.Duration { + delta := rand.Int63n(int64(maxElectionTimeout - minElectionTimeout)) + return (minElectionTimeout + time.Duration(delta)) +} + +// Lock should be held. +func (n *raft) resetElectionTimeout() { + n.resetElect(randElectionTimeout()) +} + +func (n *raft) resetElectionTimeoutWithLock() { + n.resetElectWithLock(randElectionTimeout()) +} + +// Lock should be held. +func (n *raft) resetElect(et time.Duration) { + n.etlr = time.Now() + if n.elect == nil { + n.elect = time.NewTimer(et) + } else { + if !n.elect.Stop() { + select { + case <-n.elect.C: + default: + } + } + n.elect.Reset(et) + } +} + +func (n *raft) resetElectWithLock(et time.Duration) { + n.Lock() + n.resetElect(et) + n.Unlock() +} + +// run is the top-level runner for the Raft state machine. Depending on the +// state of the node (leader, follower, candidate, observer), this will call +// through to other functions. It is expected that this function will run for +// the entire life of the Raft node once started. +func (n *raft) run() { + s := n.s + defer s.grWG.Done() + defer n.wg.Done() + + // We want to wait for some routing to be enabled, so we will wait for + // at least a route, leaf or gateway connection to be established before + // starting the run loop. + for gw := s.gateway; ; { + s.mu.RLock() + ready, gwEnabled := s.numRemotes()+len(s.leafs) > 0, gw.enabled + s.mu.RUnlock() + if !ready && gwEnabled { + gw.RLock() + ready = len(gw.out)+len(gw.in) > 0 + gw.RUnlock() + } + if !ready { + select { + case <-s.quitCh: + return + case <-time.After(100 * time.Millisecond): + s.RateLimitWarnf("Waiting for routing to be established...") + } + } else { + break + } + } + + // We may have paused adding entries to apply queue, resume here. + // No-op if not paused. + n.ResumeApply() + + // Send nil entry to signal the upper layers we are done doing replay/restore. + n.apply.push(nil) + +runner: + for { + switch n.State() { + case Follower: + n.runAsFollower() + case Candidate: + n.runAsCandidate() + case Leader: + n.runAsLeader() + case Closed: + break runner + } + } + + // If we've reached this point then we're shutting down, either because + // the server is stopping or because the Raft group is closing/closed. + n.Lock() + defer n.Unlock() + + if c := n.c; c != nil { + var subs []*subscription + c.mu.Lock() + for _, sub := range c.subs { + subs = append(subs, sub) + } + c.mu.Unlock() + for _, sub := range subs { + n.unsubscribe(sub) + } + c.closeConnection(InternalClient) + n.c = nil + } + + // Unregistering ipQueues do not prevent them from push/pop + // just will remove them from the central monitoring map + queues := []interface { + unregister() + drain() int + }{n.reqs, n.votes, n.prop, n.entry, n.resp, n.apply} + for _, q := range queues { + q.drain() + q.unregister() + } + + n.s.unregisterRaftNode(n.group) + + if wal := n.wal; wal != nil { + wal.Stop() + } + + n.debug("Shutdown") +} + +func (n *raft) debug(format string, args ...any) { + if n.dflag { + nf := fmt.Sprintf("RAFT [%s - %s] %s", n.id, n.group, format) + n.s.Debugf(nf, args...) + } +} + +func (n *raft) warn(format string, args ...any) { + nf := fmt.Sprintf("RAFT [%s - %s] %s", n.id, n.group, format) + n.s.RateLimitWarnf(nf, args...) +} + +func (n *raft) error(format string, args ...any) { + nf := fmt.Sprintf("RAFT [%s - %s] %s", n.id, n.group, format) + n.s.Errorf(nf, args...) +} + +func (n *raft) electTimer() *time.Timer { + n.RLock() + defer n.RUnlock() + return n.elect +} + +func (n *raft) IsObserver() bool { + n.RLock() + defer n.RUnlock() + return n.observer +} + +// Sets the state to observer only. +func (n *raft) SetObserver(isObserver bool) { + n.setObserver(isObserver, extUndetermined) +} + +func (n *raft) setObserver(isObserver bool, extSt extensionState) { + n.Lock() + defer n.Unlock() + + if n.paused { + // Applies are paused so we're already in observer state. + // Resuming the applies will set the state back to whatever + // is in "pobserver", so update that instead. + n.pobserver = isObserver + return + } + + wasObserver := n.observer + n.observer = isObserver + n.extSt = extSt + + // If we're leaving observer state then reset the election timer or + // we might end up waiting for up to the observerModeInterval. + if wasObserver && !isObserver { + n.resetElect(randCampaignTimeout()) + } +} + +// processAppendEntries is called by the Raft state machine when there are +// new append entries to be committed and sent to the upper state machine. +func (n *raft) processAppendEntries() { + canProcess := true + if n.isClosed() { + n.debug("AppendEntry not processing inbound, closed") + canProcess = false + } + if n.outOfResources() { + n.debug("AppendEntry not processing inbound, no resources") + canProcess = false + } + // Always pop the entries, but check if we can process them. If we can't + // then the entries are effectively dropped. + aes := n.entry.pop() + if canProcess { + for _, ae := range aes { + n.processAppendEntry(ae, ae.sub) + } + } + n.entry.recycle(&aes) +} + +// runAsFollower is called by run and will block for as long as the node is +// running in the follower state. +func (n *raft) runAsFollower() { + for n.State() == Follower { + elect := n.electTimer() + + select { + case <-n.entry.ch: + // New append entries have arrived over the network. + n.processAppendEntries() + case <-n.s.quitCh: + // The server is shutting down. + return + case <-n.quit: + // The Raft node is shutting down. + return + case <-elect.C: + // The election timer has fired so we think it's time to call an election. + // If we are out of resources we just want to stay in this state for the moment. + if n.outOfResources() { + n.resetElectionTimeoutWithLock() + n.debug("Not switching to candidate, no resources") + } else if n.IsObserver() { + n.resetElectWithLock(observerModeInterval) + n.debug("Not switching to candidate, observer only") + } else if n.isCatchingUp() { + n.debug("Not switching to candidate, catching up") + // Check to see if our catchup has stalled. + n.Lock() + if n.catchupStalled() { + n.cancelCatchup() + } + n.resetElectionTimeout() + n.Unlock() + } else { + n.switchToCandidate() + return + } + case <-n.votes.ch: + // We're receiving votes from the network, probably because we have only + // just stepped down and they were already in flight. Ignore them. + n.debug("Ignoring old vote response, we have stepped down") + n.votes.popOne() + case <-n.resp.ch: + // Ignore append entry responses received from before the state change. + n.resp.drain() + case <-n.prop.ch: + // Ignore proposals received from before the state change. + n.prop.drain() + case <-n.reqs.ch: + // We've just received a vote request from the network. + // Because of drain() it is possible that we get nil from popOne(). + if voteReq, ok := n.reqs.popOne(); ok { + n.processVoteRequest(voteReq) + } + } + } +} + +// Pool for CommittedEntry re-use. +var cePool = sync.Pool{ + New: func() any { + return &CommittedEntry{} + }, +} + +// CommittedEntry is handed back to the user to apply a commit to their upper layer. +type CommittedEntry struct { + Index uint64 + Entries []*Entry +} + +// Create a new CommittedEntry. When the returned entry is no longer needed, it +// should be returned to the pool by calling ReturnToPool. +func newCommittedEntry(index uint64, entries []*Entry) *CommittedEntry { + ce := cePool.Get().(*CommittedEntry) + ce.Index, ce.Entries = index, entries + return ce +} + +// ReturnToPool returns the CommittedEntry to the pool, after which point it is +// no longer safe to reuse. +func (ce *CommittedEntry) ReturnToPool() { + if ce == nil { + return + } + if len(ce.Entries) > 0 { + for _, e := range ce.Entries { + entryPool.Put(e) + } + } + ce.Index, ce.Entries = 0, nil + cePool.Put(ce) +} + +// Pool for Entry re-use. +var entryPool = sync.Pool{ + New: func() any { + return &Entry{} + }, +} + +// Helper to create new entries. When the returned entry is no longer needed, it +// should be returned to the entryPool pool. +func newEntry(t EntryType, data []byte) *Entry { + entry := entryPool.Get().(*Entry) + entry.Type, entry.Data = t, data + return entry +} + +// Pool for appendEntry re-use. +var aePool = sync.Pool{ + New: func() any { + return &appendEntry{} + }, +} + +// appendEntry is the main struct that is used to sync raft peers. +type appendEntry struct { + leader string // The leader that this append entry came from. + term uint64 // The term when this entry was stored. + commit uint64 // The commit index of the leader when this append entry was sent. + pterm uint64 // The previous term, for checking consistency. + pindex uint64 // The previous commit index, for checking consistency. + entries []*Entry // Entries to process. + // Below fields are for internal use only: + lterm uint64 // The highest term for catchups only, as the leader understands it. (If lterm=0, use term instead) + reply string // Reply subject to respond to once committed. + sub *subscription // The subscription that the append entry came in on. + buf []byte +} + +// Create a new appendEntry. +func newAppendEntry(leader string, term, commit, pterm, pindex uint64, entries []*Entry) *appendEntry { + ae := aePool.Get().(*appendEntry) + ae.leader, ae.term, ae.commit, ae.pterm, ae.pindex, ae.entries = leader, term, commit, pterm, pindex, entries + ae.lterm, ae.reply, ae.sub, ae.buf = 0, _EMPTY_, nil, nil + return ae +} + +// Will return this append entry, and its interior entries to their respective pools. +func (ae *appendEntry) returnToPool() { + ae.entries, ae.buf, ae.sub, ae.reply = nil, nil, nil, _EMPTY_ + aePool.Put(ae) +} + +// Pool for proposedEntry re-use. +var pePool = sync.Pool{ + New: func() any { + return &proposedEntry{} + }, +} + +// Create a new proposedEntry. +func newProposedEntry(entry *Entry, reply string) *proposedEntry { + pe := pePool.Get().(*proposedEntry) + pe.Entry, pe.reply = entry, reply + return pe +} + +// Will return this proosed entry. +func (pe *proposedEntry) returnToPool() { + pe.Entry, pe.reply = nil, _EMPTY_ + pePool.Put(pe) +} + +type EntryType uint8 + +const ( + EntryNormal EntryType = iota + EntryOldSnapshot + EntryPeerState + EntryAddPeer + EntryRemovePeer + EntryLeaderTransfer + EntrySnapshot +) + +func (t EntryType) String() string { + switch t { + case EntryNormal: + return "Normal" + case EntryOldSnapshot: + return "OldSnapshot" + case EntryPeerState: + return "PeerState" + case EntryAddPeer: + return "AddPeer" + case EntryRemovePeer: + return "RemovePeer" + case EntryLeaderTransfer: + return "LeaderTransfer" + case EntrySnapshot: + return "Snapshot" + } + return fmt.Sprintf("Unknown [%d]", uint8(t)) +} + +type Entry struct { + Type EntryType + Data []byte +} + +func (e *Entry) ChangesMembership() bool { + switch e.Type { + case EntryAddPeer, EntryRemovePeer: + return true + default: + return false + } +} + +func (ae *appendEntry) String() string { + return fmt.Sprintf("&{leader:%s term:%d commit:%d pterm:%d pindex:%d entries: %d}", + ae.leader, ae.term, ae.commit, ae.pterm, ae.pindex, len(ae.entries)) +} + +const appendEntryBaseLen = idLen + 4*8 + 2 + +func (ae *appendEntry) encode(b []byte) ([]byte, error) { + if ll := len(ae.leader); ll != idLen && ll != 0 { + return nil, errLeaderLen + } + if len(ae.entries) > math.MaxUint16 { + return nil, errTooManyEntries + } + + var elen uint64 + for _, e := range ae.entries { + // MaxInt32 instead of MaxUint32 deliberate here to stop int + // overflow on 32-bit platforms, still gives us ~2GB limit. + ulen := uint64(len(e.Data)) + if ulen > math.MaxInt32 { + return nil, errBadAppendEntry + } + elen += ulen + 1 + 4 // 1 is type, 4 is for size. + } + // Uvarint for lterm can be a maximum 10 bytes for a uint64. + var _lterm [10]byte + lterm := _lterm[:binary.PutUvarint(_lterm[:], ae.lterm)] + tlen := appendEntryBaseLen + elen + uint64(len(lterm)) + + var buf []byte + if uint64(cap(b)) >= tlen { + buf = b[:idLen] + } else { + buf = make([]byte, idLen, tlen) + } + + var le = binary.LittleEndian + copy(buf[:idLen], ae.leader) + buf = le.AppendUint64(buf, ae.term) + buf = le.AppendUint64(buf, ae.commit) + buf = le.AppendUint64(buf, ae.pterm) + buf = le.AppendUint64(buf, ae.pindex) + buf = le.AppendUint16(buf, uint16(len(ae.entries))) + for _, e := range ae.entries { + // The +1 is safe here as we've already checked len(e.Data) + // is not greater than MaxInt32, which is less than MaxUint32. + buf = le.AppendUint32(buf, uint32(1+len(e.Data))) + buf = append(buf, byte(e.Type)) + buf = append(buf, e.Data...) + } + // This is safe because old nodes will ignore bytes after the + // encoded messages. Nodes that are aware of this will decode + // it correctly. + buf = append(buf, lterm...) + return buf, nil +} + +// This can not be used post the wire level callback since we do not copy. +func decodeAppendEntry(msg []byte, sub *subscription, reply string) (*appendEntry, error) { + if len(msg) < appendEntryBaseLen { + return nil, errBadAppendEntry + } + + var le = binary.LittleEndian + + ae := newAppendEntry(string(msg[:idLen]), le.Uint64(msg[8:]), le.Uint64(msg[16:]), le.Uint64(msg[24:]), le.Uint64(msg[32:]), nil) + ae.reply, ae.sub = reply, sub + + // Decode Entries. + ne, ri := int(le.Uint16(msg[40:])), uint64(42) + for i, max := 0, uint64(len(msg)); i < ne; i++ { + if ri >= max-1 { + return nil, errBadAppendEntry + } + ml := uint64(le.Uint32(msg[ri:])) + ri += 4 + if ml <= 0 || ri+ml > max { + return nil, errBadAppendEntry + } + entry := newEntry(EntryType(msg[ri]), msg[ri+1:ri+ml]) + ae.entries = append(ae.entries, entry) + ri += ml + } + if len(msg[ri:]) > 0 { + if lterm, n := binary.Uvarint(msg[ri:]); n > 0 { + ae.lterm = lterm + } + } + ae.buf = msg + return ae, nil +} + +// Pool for appendEntryResponse re-use. +var arPool = sync.Pool{ + New: func() any { + return &appendEntryResponse{} + }, +} + +// We want to make sure this does not change from system changing length of syshash. +const idLen = 8 +const appendEntryResponseLen = 24 + 1 + +// appendEntryResponse is our response to a received appendEntry. +type appendEntryResponse struct { + term uint64 + index uint64 + peer string + reply string // internal usage. + success bool +} + +// Create a new appendEntryResponse. +func newAppendEntryResponse(term, index uint64, peer string, success bool) *appendEntryResponse { + ar := arPool.Get().(*appendEntryResponse) + ar.term, ar.index, ar.peer, ar.success = term, index, peer, success + // Always empty out. + ar.reply = _EMPTY_ + return ar +} + +func (ar *appendEntryResponse) encode(b []byte) []byte { + var buf []byte + if cap(b) >= appendEntryResponseLen { + buf = b[:appendEntryResponseLen] + } else { + buf = make([]byte, appendEntryResponseLen) + } + var le = binary.LittleEndian + le.PutUint64(buf[0:], ar.term) + le.PutUint64(buf[8:], ar.index) + copy(buf[16:16+idLen], ar.peer) + if ar.success { + buf[24] = 1 + } else { + buf[24] = 0 + } + return buf[:appendEntryResponseLen] +} + +// Track all peers we may have ever seen to use an string interns for appendEntryResponse decoding. +var peers sync.Map + +func decodeAppendEntryResponse(msg []byte) *appendEntryResponse { + if len(msg) != appendEntryResponseLen { + return nil + } + var le = binary.LittleEndian + ar := arPool.Get().(*appendEntryResponse) + ar.term = le.Uint64(msg[0:]) + ar.index = le.Uint64(msg[8:]) + + peer, ok := peers.Load(string(msg[16 : 16+idLen])) + if !ok { + // We missed so store inline here. + peer = string(msg[16 : 16+idLen]) + peers.Store(peer, peer) + } + ar.peer = peer.(string) + ar.success = msg[24] == 1 + return ar +} + +// Called when a remove peer proposal has been forwarded +func (n *raft) handleForwardedRemovePeerProposal(sub *subscription, c *client, _ *Account, _, reply string, msg []byte) { + n.debug("Received forwarded remove peer proposal: %q", msg) + + if len(msg) != idLen { + n.warn("Received invalid peer name for remove proposal: %q", msg) + return + } + + n.RLock() + // Check state under lock, we might not be leader anymore. + if n.State() != Leader { + n.debug("Ignoring forwarded peer removal proposal, not leader") + n.RUnlock() + return + } + prop, werr := n.prop, n.werr + n.RUnlock() + + // Ignore if we have had a write error previous. + if werr != nil { + return + } + + // Need to copy since this is underlying client/route buffer. + peer := copyBytes(msg) + prop.push(newProposedEntry(newEntry(EntryRemovePeer, peer), reply)) +} + +// Called when a peer has forwarded a proposal. +func (n *raft) handleForwardedProposal(sub *subscription, c *client, _ *Account, _, reply string, msg []byte) { + // Need to copy since this is underlying client/route buffer. + msg = copyBytes(msg) + + n.RLock() + // Check state under lock, we might not be leader anymore. + if n.State() != Leader { + n.debug("Ignoring forwarded proposal, not leader") + n.RUnlock() + return + } + prop, werr := n.prop, n.werr + n.RUnlock() + + // Ignore if we have had a write error previous. + if werr != nil { + return + } + + prop.push(newProposedEntry(newEntry(EntryNormal, msg), reply)) +} + +// Adds peer with the given id to our membership, +// and adjusts cluster size and quorum accordingly. +// Lock should be held. +func (n *raft) addPeer(peer string) { + // If we were on the removed list reverse that here. + if n.removed != nil { + delete(n.removed, peer) + } + + if lp, ok := n.peers[peer]; !ok { + // We are not tracking this one automatically so we need + // to bump cluster size. + n.peers[peer] = &lps{time.Time{}, 0, true} + } else { + // Mark as added. + lp.kp = true + } + + // Adjust cluster size and quorum if needed. + n.adjustClusterSizeAndQuorum() + // Write out our new state. + n.writePeerState(&peerState{n.peerNames(), n.csz, n.extSt}) +} + +// Remove the peer with the given id from our membership, +// and adjusts cluster size and quorum accordingly. +// Lock should be held. +func (n *raft) removePeer(peer string) { + if n.removed == nil { + n.removed = map[string]time.Time{} + } + n.removed[peer] = time.Now() + if _, ok := n.peers[peer]; ok { + delete(n.peers, peer) + n.adjustClusterSizeAndQuorum() + n.writePeerState(&peerState{n.peerNames(), n.csz, n.extSt}) + } +} + +// Build and send appendEntry request for the given entry that changes +// membership (EntryAddPeer / EntryRemovePeer). +// Returns true if the entry made it to the WAL and was sent to the followers +func (n *raft) sendMembershipChange(e *Entry) bool { + n.Lock() + defer n.Unlock() + + // Only makes sense to call this with entries that change membership + if !e.ChangesMembership() { + return false + } + + err := n.sendAppendEntryLocked([]*Entry{e}, true) + if err != nil { + n.membChanging = false + return false + } + + if e.Type == EntryAddPeer { + n.addPeer(string(e.Data)) + } + + if e.Type == EntryRemovePeer { + n.removePeer(string(e.Data)) + if n.csz == 1 { + n.tryCommit(n.pindex) + return true + } + } + return true +} + +// logContainsUncommittedMembershipChange returns true if the +// log contains uncommitted entries that change membership. +// Lock should be held. +func (n *raft) logContainsUncommittedMembershipChange() (bool, error) { + for i := n.commit + 1; i <= n.pindex; i++ { + ae, err := n.loadEntry(i) + if err != nil { + return false, err + } + if len(ae.entries) > 0 && ae.entries[0].ChangesMembership() { + ae.returnToPool() + return true, nil + } + ae.returnToPool() + } + return false, nil +} + +func (n *raft) runAsLeader() { + if n.State() == Closed { + return + } + + n.Lock() + psubj, rpsubj := n.psubj, n.rpsubj + + // Check if there are any uncommitted membership changes. + // If so, we need to make sure we don't propose any new + // ones until those are committed. + found, err := n.logContainsUncommittedMembershipChange() + if err != nil { + n.warn("Error while looking for membership changes in WAL: %v", err) + n.stepdownLocked(noLeader) + n.Unlock() + return + + } + if found { + n.membChanging = true + n.debug("Log contains uncommitted membership change") + } + + // For forwarded proposals, both normal and remove peer proposals. + fsub, err := n.subscribe(psubj, n.handleForwardedProposal) + if err != nil { + n.warn("Error subscribing to forwarded proposals: %v", err) + n.stepdownLocked(noLeader) + n.Unlock() + return + } + rpsub, err := n.subscribe(rpsubj, n.handleForwardedRemovePeerProposal) + if err != nil { + n.warn("Error subscribing to forwarded remove peer proposals: %v", err) + n.unsubscribe(fsub) + n.stepdownLocked(noLeader) + n.Unlock() + return + } + + // Cleanup our subscription when we leave. + defer func() { + n.Lock() + n.unsubscribe(fsub) + n.unsubscribe(rpsub) + n.Unlock() + }() + n.Unlock() + + hb := time.NewTicker(hbInterval) + defer hb.Stop() + + lq := time.NewTicker(lostQuorumCheck) + defer lq.Stop() + + for n.State() == Leader { + select { + case <-n.s.quitCh: + return + case <-n.quit: + return + case <-n.resp.ch: + ars := n.resp.pop() + for _, ar := range ars { + n.processAppendEntryResponse(ar) + } + n.resp.recycle(&ars) + case <-n.prop.ch: + const maxBatch = 256 * 1024 + const maxEntries = 512 + var entries []*Entry + + es, sz := n.prop.pop(), 0 + for _, b := range es { + if b.ChangesMembership() { + n.sendMembershipChange(b.Entry) + continue + } + entries = append(entries, b.Entry) + // Increment size. + sz += len(b.Data) + 1 + // If below thresholds go ahead and send. + if sz < maxBatch && len(entries) < maxEntries { + continue + } + n.sendAppendEntry(entries) + // Reset our sz and entries. + // We need to re-create `entries` because there is a reference + // to it in the node's pae map. + sz, entries = 0, nil + } + if len(entries) > 0 { + n.sendAppendEntry(entries) + } + // Respond to any proposals waiting for a confirmation. + for _, pe := range es { + if pe.reply != _EMPTY_ { + n.sendReply(pe.reply, nil) + } + pe.returnToPool() + } + n.prop.recycle(&es) + + case <-hb.C: + if n.notActive() { + n.sendHeartbeat() + } + case <-lq.C: + if n.lostQuorum() { + n.stepdown(noLeader) + return + } + case <-n.votes.ch: + // Because of drain() it is possible that we get nil from popOne(). + vresp, ok := n.votes.popOne() + if !ok { + continue + } + if vresp.term > n.Term() { + n.stepdown(noLeader) + return + } + case <-n.reqs.ch: + // Because of drain() it is possible that we get nil from popOne(). + if voteReq, ok := n.reqs.popOne(); ok { + n.processVoteRequest(voteReq) + } + case <-n.entry.ch: + n.processAppendEntries() + } + } +} + +// Quorum reports the quorum status. Will be called on former leaders. +func (n *raft) Quorum() bool { + n.RLock() + defer n.RUnlock() + + nc := 0 + for id, peer := range n.peers { + if id == n.id || time.Since(peer.ts) < lostQuorumInterval { + if nc++; nc >= n.qn { + return true + } + } + } + return false +} + +func (n *raft) lostQuorum() bool { + n.RLock() + defer n.RUnlock() + return n.lostQuorumLocked() +} + +func (n *raft) lostQuorumLocked() bool { + // In order to avoid false positives that can happen in heavily loaded systems + // make sure nothing is queued up that we have not processed yet. + // Also make sure we let any scale up actions settle before deciding. + if n.resp.len() != 0 || (!n.lsut.IsZero() && time.Since(n.lsut) < lostQuorumInterval) { + return false + } + + nc := 0 + for id, peer := range n.peers { + if id == n.id || time.Since(peer.ts) < lostQuorumInterval { + if nc++; nc >= n.qn { + return false + } + } + } + return true +} + +// Check for being not active in terms of sending entries. +// Used in determining if we need to send a heartbeat. +func (n *raft) notActive() bool { + n.RLock() + defer n.RUnlock() + return time.Since(n.active) > hbInterval +} + +// Return our current term. +func (n *raft) Term() uint64 { + n.RLock() + defer n.RUnlock() + return n.term +} + +// Lock should be held. +func (n *raft) loadFirstEntry() (ae *appendEntry, err error) { + var state StreamState + n.wal.FastState(&state) + return n.loadEntry(state.FirstSeq) +} + +func (n *raft) runCatchup(ar *appendEntryResponse, indexUpdatesQ *ipQueue[uint64]) { + n.RLock() + s, reply := n.s, n.areply + peer, subj, term, pterm, last := ar.peer, ar.reply, n.term, n.pterm, n.pindex + leader := n.State() == Leader // Grab while holding lock, to not race. + n.RUnlock() + + defer s.grWG.Done() + defer arPool.Put(ar) + + defer func() { + n.Lock() + delete(n.progress, peer) + if len(n.progress) == 0 { + n.progress = nil + } + // Check if this is a new peer and if so go ahead and propose adding them. + _, exists := n.peers[peer] + n.Unlock() + if !exists { + n.debug("Catchup done for %q, will add into peers", peer) + n.ProposeAddPeer(peer) + } + indexUpdatesQ.unregister() + }() + + if !leader { + n.debug("Canceling catchup for %q, not leader anymore", peer) + return + } + n.debug("Running catchup for %q [%d:%d] to [%d:%d]", peer, ar.term, ar.index, pterm, last) + + const maxOutstanding = 2 * 1024 * 1024 // 2MB for now. + next, total, om := uint64(0), 0, make(map[uint64]int) + + sendNext := func() bool { + for total <= maxOutstanding { + next++ + if next > last { + return true + } + ae, err := n.loadEntry(next) + if err != nil { + if err != ErrStoreEOF { + n.warn("Got an error loading %d index: %v", next, err) + } + return true + } + // Re-encode with the lterm if needed + if ae.lterm != term { + ae.lterm = term + if ae.buf, err = ae.encode(ae.buf[:0]); err != nil { + n.warn("Got an error re-encoding append entry: %v", err) + return true + } + } + // Update our tracking total. + om[next] = len(ae.buf) + total += len(ae.buf) + n.sendRPC(subj, reply, ae.buf) + } + return false + } + + const activityInterval = 2 * time.Second + timeout := time.NewTimer(activityInterval) + defer timeout.Stop() + + stepCheck := time.NewTicker(100 * time.Millisecond) + defer stepCheck.Stop() + + // Run as long as we are leader and still not caught up. + for n.State() == Leader { + select { + case <-n.s.quitCh: + return + case <-n.quit: + return + case <-stepCheck.C: + if n.State() != Leader { + n.debug("Catching up canceled, no longer leader") + return + } + case <-timeout.C: + n.debug("Catching up for %q stalled", peer) + return + case <-indexUpdatesQ.ch: + if index, ok := indexUpdatesQ.popOne(); ok { + // Update our activity timer. + timeout.Reset(activityInterval) + // Update outstanding total. + total -= om[index] + delete(om, index) + if next == 0 { + next = index + } + // Check if we are done. + if index > last || sendNext() { + n.debug("Finished catching up") + return + } + } + } + } +} + +// Lock should be held. +func (n *raft) sendSnapshotToFollower(subject string) (uint64, error) { + snap, err := n.loadLastSnapshot() + if err != nil { + // We need to stepdown here when this happens. + n.stepdownLocked(noLeader) + // We need to reset our state here as well. + n.resetWAL() + return 0, err + } + // Go ahead and send the snapshot and peerstate here as first append entry to the catchup follower. + ae := n.buildAppendEntry([]*Entry{{EntrySnapshot, snap.data}, {EntryPeerState, snap.peerstate}}) + ae.pterm, ae.pindex = snap.lastTerm, snap.lastIndex + var state StreamState + n.wal.FastState(&state) + + fpIndex := state.FirstSeq - 1 + if snap.lastIndex < fpIndex && state.FirstSeq != 0 { + snap.lastIndex = fpIndex + ae.pindex = fpIndex + } + + encoding, err := ae.encode(nil) + if err != nil { + return 0, err + } + n.sendRPC(subject, n.areply, encoding) + return snap.lastIndex, nil +} + +func (n *raft) catchupFollower(ar *appendEntryResponse) { + n.debug("Being asked to catch up follower: %q", ar.peer) + n.Lock() + if n.progress == nil { + n.progress = make(map[string]*ipQueue[uint64]) + } else if q, ok := n.progress[ar.peer]; ok { + n.debug("Will cancel existing entry for catching up %q", ar.peer) + delete(n.progress, ar.peer) + q.push(n.pindex) + } + + // Check to make sure we have this entry. + start := ar.index + 1 + var state StreamState + n.wal.FastState(&state) + + if start < state.FirstSeq || (state.Msgs == 0 && start <= state.LastSeq) { + n.debug("Need to send snapshot to follower") + if lastIndex, err := n.sendSnapshotToFollower(ar.reply); err != nil { + n.error("Error sending snapshot to follower [%s]: %v", ar.peer, err) + n.Unlock() + arPool.Put(ar) + return + } else { + start = lastIndex + 1 + // If no other entries, we can just return here. + if state.Msgs == 0 || start > state.LastSeq { + n.debug("Finished catching up") + n.Unlock() + arPool.Put(ar) + return + } + n.debug("Snapshot sent, reset first catchup entry to %d", lastIndex) + } + } + + ae, err := n.loadEntry(start) + if err != nil { + n.warn("Request from follower for entry at index [%d] errored for state %+v - %v", start, state, err) + if err == ErrStoreEOF { + // If we are here we are seeing a request for an item beyond our state, meaning we should stepdown. + n.stepdownLocked(noLeader) + n.Unlock() + arPool.Put(ar) + return + } + ae, err = n.loadFirstEntry() + } + if err != nil || ae == nil { + n.warn("Could not find a starting entry for catchup request: %v", err) + // If we are here we are seeing a request for an item we do not have, meaning we should stepdown. + // This is possible on a reset of our WAL but the other side has a snapshot already. + // If we do not stepdown this can cycle. + n.stepdownLocked(noLeader) + n.Unlock() + arPool.Put(ar) + return + } + if ae.pindex != ar.index || ae.pterm != ar.term { + n.debug("Our first entry [%d:%d] does not match request from follower [%d:%d]", ae.pterm, ae.pindex, ar.term, ar.index) + } + // Create a queue for delivering updates from responses. + indexUpdates := newIPQueue[uint64](n.s, fmt.Sprintf("[ACC:%s] RAFT '%s' indexUpdates", n.accName, n.group)) + indexUpdates.push(ae.pindex) + n.progress[ar.peer] = indexUpdates + n.Unlock() + + n.wg.Add(1) + n.s.startGoRoutine(func() { + defer n.wg.Done() + n.runCatchup(ar, indexUpdates) + }) +} + +func (n *raft) loadEntry(index uint64) (*appendEntry, error) { + var smp StoreMsg + sm, err := n.wal.LoadMsg(index, &smp) + if err != nil { + return nil, err + } + return decodeAppendEntry(sm.msg, nil, _EMPTY_) +} + +// applyCommit will update our commit index and apply the entry to the apply queue. +// lock should be held. +func (n *raft) applyCommit(index uint64) error { + if n.State() == Closed { + return errNodeClosed + } + if index <= n.commit { + n.debug("Ignoring apply commit for %d, already processed", index) + return nil + } + + if n.State() == Leader { + delete(n.acks, index) + } + + ae := n.pae[index] + if ae == nil { + if index < n.papplied { + return nil + } + var err error + if ae, err = n.loadEntry(index); err != nil { + if err != ErrStoreClosed && err != ErrStoreEOF { + n.warn("Got an error loading %d index: %v - will reset", index, err) + if n.State() == Leader { + n.stepdownLocked(n.selectNextLeader()) + } + // Reset and cancel any catchup. + n.resetWAL() + n.cancelCatchup() + } + return errEntryLoadFailed + } + } else { + defer delete(n.pae, index) + } + + n.commit = index + ae.buf = nil + var committed []*Entry + + defer func() { + // Pass to the upper layers if we have normal entries. It is + // entirely possible that 'committed' might be an empty slice here, + // which will happen if we've processed updates inline (like peer + // states). In which case the upper layer will just call down with + // Applied() with no further action. + n.apply.push(newCommittedEntry(index, committed)) + // Place back in the pool. + ae.returnToPool() + }() + + for _, e := range ae.entries { + switch e.Type { + case EntryNormal: + committed = append(committed, e) + case EntryOldSnapshot: + // For old snapshots in our WAL. + committed = append(committed, newEntry(EntrySnapshot, e.Data)) + case EntrySnapshot: + committed = append(committed, e) + // If we have no snapshot, install the leader's snapshot as our own. + if len(ae.entries) == 1 && n.snapfile == _EMPTY_ && ae.commit > 0 { + n.installSnapshot(&snapshot{ + lastTerm: ae.pterm, + lastIndex: ae.commit, + peerstate: encodePeerState(&peerState{n.peerNames(), n.csz, n.extSt}), + data: e.Data, + }) + } + case EntryPeerState: + if n.State() != Leader { + if ps, err := decodePeerState(e.Data); err == nil { + n.processPeerState(ps) + } + } + case EntryAddPeer: + newPeer := string(e.Data) + n.debug("Added peer %q", newPeer) + + // Store our peer in our global peer map for all peers. + peers.LoadOrStore(newPeer, newPeer) + + n.addPeer(newPeer) + + // We pass these up as well. + committed = append(committed, e) + + // We are done with this membership change + n.membChanging = false + + case EntryRemovePeer: + peer := string(e.Data) + n.debug("Removing peer %q", peer) + + n.removePeer(peer) + + // Remove from string intern map. + peers.Delete(peer) + + // We pass these up as well. + committed = append(committed, e) + + // We are done with this membership change + n.membChanging = false + + // If this is us and we are the leader signal the caller + // to attempt to stepdown. + if peer == n.id && n.State() == Leader { + return errNodeRemoved + } + } + } + return nil +} + +// Check if there is a quorum for the given index, and if +// so, commit the corresponding entry. +// Return true if the index was committed, false otherwise. +// Lock should be held. +func (n *raft) tryCommit(index uint64) (bool, error) { + acks := len(n.acks[index]) + // Count the leader if it's still part of membership + if n.peers[n.ID()] != nil { + acks += 1 + } + if acks < n.qn { + return false, nil + } + // We have a quorum + for i := n.commit + 1; i <= index; i++ { + if err := n.applyCommit(i); err != nil { + if err != errNodeClosed && err != errNodeRemoved { + n.error("Got an error applying commit for %d: %v", i, err) + } + return false, err + } + } + return true, nil +} + +// Used to track a success response. Returns true if the +// response was tracked, false if the response was ignored +// (the response is old, the index is already committed, ...) +// Lock should be held. +func (n *raft) trackResponse(ar *appendEntryResponse) bool { + // Check state under lock, we might not be leader anymore. + if n.State() != Leader { + return false + } + + ps := n.peers[ar.peer] + + // Update peer's last index. + if ps != nil && ar.index > ps.li { + ps.li = ar.index + } + + // If we are tracking this peer as a catchup follower, update that here. + if indexUpdateQ := n.progress[ar.peer]; indexUpdateQ != nil { + indexUpdateQ.push(ar.index) + } + + // Ignore items already committed. + if ar.index <= n.commit { + return false + } + + // Not a peer, can't count this message towards quorum + if ps == nil { + return false + } + + // Keep track of the response + results := n.acks[ar.index] + if results == nil { + results = make(map[string]struct{}) + n.acks[ar.index] = results + } + results[ar.peer] = struct{}{} + + return true +} + +// Used to adjust cluster size and peer count based on added official peers. +// lock should be held. +func (n *raft) adjustClusterSizeAndQuorum() { + pcsz, ncsz := n.csz, 0 + for _, peer := range n.peers { + if peer.kp { + ncsz++ + } + } + n.csz = ncsz + n.qn = n.csz/2 + 1 + + if ncsz > pcsz { + n.debug("Expanding our clustersize: %d -> %d", pcsz, ncsz) + n.lsut = time.Now() + } else if ncsz < pcsz { + n.debug("Decreasing our clustersize: %d -> %d", pcsz, ncsz) + if n.State() == Leader { + go n.sendHeartbeat() + } + } + if ncsz != pcsz { + n.recreateInternalSubsLocked() + } +} + +// Track interactions with this peer. +func (n *raft) trackPeer(peer string) error { + n.Lock() + var needPeerAdd, isRemoved bool + var rts time.Time + if n.removed != nil { + rts, isRemoved = n.removed[peer] + // Removed peers can rejoin after timeout. + if isRemoved && time.Since(rts) >= peerRemoveTimeout { + isRemoved = false + } + } + if n.State() == Leader { + if lp, ok := n.peers[peer]; !ok || !lp.kp { + // Check if this peer had been removed previously. + needPeerAdd = !isRemoved + } + } + if ps := n.peers[peer]; ps != nil { + ps.ts = time.Now() + } + n.Unlock() + + if needPeerAdd { + n.ProposeAddPeer(peer) + } + return nil +} + +func (n *raft) runAsCandidate() { + n.Lock() + // Drain old responses. + n.votes.drain() + n.Unlock() + + // Send out our request for votes. + n.requestVote() + + // We vote for ourselves. + n.votes.push(&voteResponse{term: n.term, peer: n.ID(), granted: true}) + + votes := map[string]struct{}{} + + for n.State() == Candidate { + elect := n.electTimer() + select { + case <-n.entry.ch: + n.processAppendEntries() + case <-n.resp.ch: + // Ignore append entry responses received from before the state change. + n.resp.drain() + case <-n.prop.ch: + // Ignore proposals received from before the state change. + n.prop.drain() + case <-n.s.quitCh: + return + case <-n.quit: + return + case <-elect.C: + n.switchToCandidate() + return + case <-n.votes.ch: + // Because of drain() it is possible that we get nil from popOne(). + vresp, ok := n.votes.popOne() + if !ok { + continue + } + n.RLock() + nterm := n.term + n.RUnlock() + + if vresp.granted && nterm == vresp.term { + // only track peers that would be our followers + n.trackPeer(vresp.peer) + votes[vresp.peer] = struct{}{} + if n.wonElection(len(votes)) { + // Become LEADER if we have won and gotten a quorum with everyone we should hear from. + n.switchToLeader() + return + } + } else if vresp.term > nterm { + // if we observe a bigger term, we should start over again or risk forming a quorum fully knowing + // someone with a better term exists. This is even the right thing to do if won == true. + n.Lock() + n.debug("Stepping down from candidate, detected higher term: %d vs %d", vresp.term, n.term) + n.term = vresp.term + n.vote = noVote + n.writeTermVote() + n.lxfer = false + n.stepdownLocked(noLeader) + n.Unlock() + } + case <-n.reqs.ch: + // Because of drain() it is possible that we get nil from popOne(). + if voteReq, ok := n.reqs.popOne(); ok { + n.processVoteRequest(voteReq) + } + } + } +} + +// handleAppendEntry handles an append entry from the wire. This function +// is an internal callback from the "asubj" append entry subscription. +func (n *raft) handleAppendEntry(sub *subscription, c *client, _ *Account, _, reply string, msg []byte) { + msg = copyBytes(msg) + if ae, err := decodeAppendEntry(msg, sub, reply); err == nil { + // Push to the new entry channel. From here one of the worker + // goroutines (runAsLeader, runAsFollower, runAsCandidate) will + // pick it up. + n.entry.push(ae) + } else { + n.warn("AppendEntry failed to be placed on internal channel: corrupt entry") + } +} + +// cancelCatchup will stop an in-flight catchup by unsubscribing from the +// catchup subscription. +// Lock should be held. +func (n *raft) cancelCatchup() { + n.debug("Canceling catchup subscription since we are now up to date") + + if n.catchup != nil && n.catchup.sub != nil { + n.unsubscribe(n.catchup.sub) + } + n.catchup = nil +} + +// catchupStalled will try to determine if we are stalled. This is called +// on a new entry from our leader. +// Lock should be held. +func (n *raft) catchupStalled() bool { + if n.catchup == nil { + return false + } + if n.catchup.pindex == n.pindex { + return time.Since(n.catchup.active) > 2*time.Second + } + n.catchup.pindex = n.pindex + n.catchup.active = time.Now() + return false +} + +// createCatchup will create the state needed to track a catchup as it +// runs. It then creates a unique inbox for this catchup and subscribes +// to it. The remote side will stream entries to that subject. +// Lock should be held. +func (n *raft) createCatchup(ae *appendEntry) string { + // Cleanup any old ones. + if n.catchup != nil && n.catchup.sub != nil { + n.unsubscribe(n.catchup.sub) + } + // Snapshot term and index. + n.catchup = &catchupState{ + cterm: ae.pterm, + cindex: ae.pindex, + pterm: n.pterm, + pindex: n.pindex, + active: time.Now(), + } + inbox := n.newCatchupInbox() + sub, _ := n.subscribe(inbox, n.handleAppendEntry) + n.catchup.sub = sub + + return inbox +} + +// Truncate our WAL and reset. +// Lock should be held. +func (n *raft) truncateWAL(term, index uint64) { + n.debug("Truncating and repairing WAL to Term %d Index %d", term, index) + + if term == 0 && index == 0 { + if n.commit > 0 { + n.warn("Resetting WAL state") + } else { + n.debug("Clearing WAL state (no commits)") + } + } + if index < n.commit { + assert.Unreachable("WAL truncate lost commits", map[string]any{ + "n.accName": n.accName, + "n.group": n.group, + "n.id": n.id, + "term": term, + "index": index, + "commit": n.commit, + "applied": n.applied, + }) + } + + defer func() { + // Check to see if we invalidated any snapshots that might have held state + // from the entries we are truncating. + if snap, _ := n.loadLastSnapshot(); snap != nil && snap.lastIndex > index { + os.Remove(n.snapfile) + n.snapfile = _EMPTY_ + } + // Make sure to reset commit and applied if above + if n.commit > n.pindex { + n.commit = n.pindex + } + if n.applied > n.commit { + n.applied = n.commit + } + if n.papplied > n.applied { + n.papplied = n.applied + } + // Refresh bytes count after truncate. + var state StreamState + n.wal.FastState(&state) + n.bytes = state.Bytes + }() + + if err := n.wal.Truncate(index); err != nil { + n.warn("Error truncating WAL: %v", err) + n.setWriteErrLocked(err) + return + } + // Set after we know we have truncated properly. + n.pterm, n.pindex = term, index +} + +// Reset our WAL. This is equivalent to truncating all data from the log. +// Lock should be held. +func (n *raft) resetWAL() { + n.truncateWAL(0, 0) +} + +// Lock should be held +func (n *raft) updateLeader(newLeader string) { + wasLeader := n.leader == n.id + n.leader = newLeader + n.hasleader.Store(newLeader != _EMPTY_) + if !n.pleader.Load() && newLeader != noLeader { + n.pleader.Store(true) + // If we were preferred to become the first leader, but didn't end up successful. + // Ensure to call lead change. When scaling from R1 to R3 we've optimized for a scale up + // not flipping leader/non-leader/leader status if the leader remains the same. But we need to + // correct that if the first leader turns out to be different. + if n.maybeLeader { + n.maybeLeader = false + if n.id != newLeader { + n.updateLeadChange(false) + } + } + } + // Reset last seen timestamps. + // If we are (or were) the leader we track(ed) everyone, and don't reset. + // But if we're a follower we only track the leader, and reset all others. + if newLeader != n.id && !wasLeader { + for peer, ps := range n.peers { + if peer == newLeader { + continue + } + ps.ts = time.Time{} + } + } +} + +// processAppendEntry will process an appendEntry. This is called either +// during recovery or from processAppendEntries when there are new entries +// to be committed. +func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) { + n.Lock() + // Don't reset here if we have been asked to assume leader position. + if !n.lxfer { + n.resetElectionTimeout() + } + + // Just return if closed or we had previous write error. + if n.State() == Closed || n.werr != nil { + n.Unlock() + return + } + + // Scratch buffer for responses. + var scratch [appendEntryResponseLen]byte + arbuf := scratch[:] + + // Grab term from append entry. But if leader explicitly defined its term, use that instead. + // This is required during catchup if the leader catches us up on older items from previous terms. + // While still allowing us to confirm they're matching our highest known term. + lterm := ae.term + if ae.lterm != 0 { + lterm = ae.lterm + } + + // Are we receiving from another leader. + if n.State() == Leader { + if lterm >= n.term { + // If the append entry term is newer than the current term, erase our + // vote. + if lterm > n.term { + n.term = lterm + n.vote = noVote + n.writeTermVote() + } else { + assert.Unreachable( + "Two leaders using the same term", + map[string]any{ + "n.accName": n.accName, + "n.group": n.group, + "n.id": n.id, + "n.term": n.term, + "ae.leader": ae.leader, + "ae.term": ae.term, + "ae.lterm": ae.lterm, + }) + } + n.debug("Received append entry from another leader, stepping down to %q", ae.leader) + n.stepdownLocked(ae.leader) + } else { + // Let them know we are the leader. + ar := newAppendEntryResponse(n.term, n.pindex, n.id, false) + n.debug("AppendEntry ignoring old term from another leader") + n.sendRPC(ae.reply, _EMPTY_, ar.encode(arbuf)) + arPool.Put(ar) + n.Unlock() + return + } + } + + // If we received an append entry as a candidate then it would appear that + // another node has taken on the leader role already, so we should convert + // to a follower of that node instead. + if n.State() == Candidate { + // If we have a leader in the current term or higher, we should stepdown, + // write the term and vote if the term of the request is higher. + if lterm >= n.term { + // If the append entry term is newer than the current term, erase our + // vote. + if lterm > n.term { + n.term = lterm + n.vote = noVote + n.writeTermVote() + } + n.debug("Received append entry in candidate state from %q, converting to follower", ae.leader) + n.stepdownLocked(ae.leader) + } + } + + // Catching up state. + catchingUp := n.catchup != nil + // Is this a new entry? New entries will be delivered on the append entry + // sub, rather than a catch-up sub. + isNew := sub != nil && sub == n.aesub + + // If we are/were catching up ignore old catchup subs, but only if catching up from an older server + // that doesn't send the leader term when catching up or if we would truncate as a result. + // We can reject old catchups from newer subs later, just by checking the append entry is on the correct term. + if !isNew && sub != nil && (ae.lterm == 0 || ae.pindex < n.pindex) && (!catchingUp || sub != n.catchup.sub) { + n.Unlock() + n.debug("AppendEntry ignoring old entry from previous catchup") + return + } + + // If this term is greater than ours. + if lterm > n.term { + n.term = lterm + n.vote = noVote + if isNew { + n.writeTermVote() + } + if n.State() != Follower { + n.debug("Term higher than ours and we are not a follower: %v, stepping down to %q", n.State(), ae.leader) + n.stepdownLocked(ae.leader) + } + } else if lterm < n.term && sub != nil && (isNew || ae.lterm != 0) { + // Anything that's below our expected highest term needs to be rejected. + // Unless we're replaying (sub=nil), in which case we'll always continue. + // For backward-compatibility we shouldn't reject if we're being caught up by an old server. + if !isNew { + n.debug("AppendEntry ignoring old entry from previous catchup") + n.Unlock() + return + } + n.debug("Rejected AppendEntry from a leader (%s) with term %d which is less than ours", ae.leader, lterm) + ar := newAppendEntryResponse(n.term, n.pindex, n.id, false) + n.Unlock() + n.sendRPC(ae.reply, _EMPTY_, ar.encode(arbuf)) + arPool.Put(ar) + return + } + + // Check state if we are catching up. + if catchingUp { + if cs := n.catchup; cs != nil && n.pterm >= cs.cterm && n.pindex >= cs.cindex { + // If we are here we are good, so if we have a catchup pending we can cancel. + n.cancelCatchup() + // Reset our notion of catching up. + catchingUp = false + } else if isNew { + var ar *appendEntryResponse + var inbox string + // Check to see if we are stalled. If so recreate our catchup state and resend response. + if n.catchupStalled() { + n.debug("Catchup may be stalled, will request again") + inbox = n.createCatchup(ae) + ar = newAppendEntryResponse(n.pterm, n.pindex, n.id, false) + } + n.Unlock() + if ar != nil { + n.sendRPC(ae.reply, inbox, ar.encode(arbuf)) + arPool.Put(ar) + } + // Ignore new while catching up or replaying. + return + } + } + + if isNew && n.leader != ae.leader && n.State() == Follower { + n.debug("AppendEntry updating leader to %q", ae.leader) + n.updateLeader(ae.leader) + n.writeTermVote() + n.resetElectionTimeout() + n.updateLeadChange(false) + } + + // Track leader directly + // But, do so after all consistency checks so we don't track an old leader. + if isNew && ae.leader != noLeader && ae.leader == n.leader { + if ps := n.peers[ae.leader]; ps != nil { + ps.ts = time.Now() + } + } + + if ae.pterm != n.pterm || ae.pindex != n.pindex { + // Check if this is a lower or equal index than what we were expecting. + if ae.pindex <= n.pindex { + n.debug("AppendEntry detected pindex less than/equal to ours: [%d:%d] vs [%d:%d]", ae.pterm, ae.pindex, n.pterm, n.pindex) + var success bool + + if ae.pindex < n.commit { + // If we have already committed this entry, just mark success. + success = true + n.debug("AppendEntry pindex %d below commit %d, marking success", ae.pindex, n.commit) + } else if eae, _ := n.loadEntry(ae.pindex); eae == nil { + // If terms are equal, and we are not catching up, we have simply already processed this message. + // This can happen on server restarts based on timings of snapshots. + if ae.pterm == n.pterm && isNew { + success = true + n.debug("AppendEntry pindex %d already processed, marking success", ae.pindex) + } else if ae.pindex == n.pindex { + // Check if only our terms do not match here. + // Make sure pterms match and we take on the leader's. + // This prevents constant spinning. + n.truncateWAL(ae.pterm, ae.pindex) + } else { + snap, err := n.loadLastSnapshot() + if err == nil && snap.lastIndex == ae.pindex && snap.lastTerm == ae.pterm { + // Entry can't be found, this is normal because we have a snapshot at this index. + // Truncate back to where we've created the snapshot. + n.truncateWAL(snap.lastTerm, snap.lastIndex) + // Only continue if truncation was successful, and we ended up such that we can safely continue. + if ae.pterm == n.pterm && ae.pindex == n.pindex { + goto CONTINUE + } + } else { + // Otherwise, something has gone very wrong and we need to reset. + n.resetWAL() + } + } + } else if eae.term == ae.pterm { + // If terms match we can delete all entries past this one, and then continue storing the current entry. + n.truncateWAL(ae.pterm, ae.pindex) + // Only continue if truncation was successful, and we ended up such that we can safely continue. + if ae.pterm == n.pterm && ae.pindex == n.pindex { + goto CONTINUE + } + } else { + // If terms mismatched, delete that entry and all others past it. + // Make sure to cancel any catchups in progress. + // Truncate will reset our pterm and pindex. Only do so if we have an entry. + n.truncateWAL(eae.pterm, eae.pindex) + } + // Cancel regardless if unsuccessful. + if !success { + n.cancelCatchup() + } + // Intentionally not responding. Otherwise, we could erroneously report "success". Reporting + // non-success is not needed either, and would only be wasting messages. + // For example, if we got partial catchup, and then the "real-time" messages came in very delayed. + // If we reported "success" on those "real-time" messages, we'd wrongfully be providing + // quorum while not having an up-to-date log. + n.Unlock() + return + } + + // Check if we are catching up. If we are here we know the leader did not have all of the entries + // so make sure this is a snapshot entry. If it is not start the catchup process again since it + // means we may have missed additional messages. + if catchingUp { + // This means we already entered into a catchup state but what the leader sent us did not match what we expected. + // Snapshots and peerstate will always be together when a leader is catching us up in this fashion. + if len(ae.entries) != 2 || ae.entries[0].Type != EntrySnapshot || ae.entries[1].Type != EntryPeerState { + n.warn("Expected first catchup entry to be a snapshot and peerstate, will retry") + n.cancelCatchup() + n.Unlock() + return + } + + if ps, err := decodePeerState(ae.entries[1].Data); err == nil { + n.processPeerState(ps) + // Also need to copy from client's buffer. + ae.entries[0].Data = copyBytes(ae.entries[0].Data) + } else { + n.warn("Could not parse snapshot peerstate correctly") + n.cancelCatchup() + n.Unlock() + return + } + + // Inherit state from appendEntry with the leader's snapshot. + n.pindex = ae.pindex + n.pterm = ae.pterm + n.commit = ae.pindex + + snap := &snapshot{ + lastTerm: n.pterm, + lastIndex: n.pindex, + peerstate: encodePeerState(&peerState{n.peerNames(), n.csz, n.extSt}), + data: ae.entries[0].Data, + } + // Install the leader's snapshot as our own. + if err := n.installSnapshot(snap); err != nil { + n.setWriteErrLocked(err) + n.Unlock() + return + } + + // Now send snapshot to upper levels. Only send the snapshot, not the peerstate entry. + n.apply.push(newCommittedEntry(n.commit, ae.entries[:1])) + n.Unlock() + return + } + + // Setup our state for catching up. + n.debug("AppendEntry did not match [%d:%d] with [%d:%d]", ae.pterm, ae.pindex, n.pterm, n.pindex) + inbox := n.createCatchup(ae) + ar := newAppendEntryResponse(n.pterm, n.pindex, n.id, false) + n.Unlock() + n.sendRPC(ae.reply, inbox, ar.encode(arbuf)) + arPool.Put(ar) + return + } + +CONTINUE: + // Save to our WAL if we have entries. + if ae.shouldStore() { + // Only store if an original which will have sub != nil + if sub != nil { + if err := n.storeToWAL(ae); err != nil { + if err != ErrStoreClosed { + n.warn("Error storing entry to WAL: %v", err) + } + n.Unlock() + return + } + n.cachePendingEntry(ae) + } else { + // This is a replay on startup so just take the appendEntry version. + n.pterm = ae.term + n.pindex = ae.pindex + 1 + } + } + + // Check to see if we have any related entries to process here. + for _, e := range ae.entries { + switch e.Type { + case EntryLeaderTransfer: + // Only process these if they are new, so no replays or catchups. + if isNew { + maybeLeader := string(e.Data) + // This is us. We need to check if we can become the leader. + if maybeLeader == n.id { + // If not an observer and not paused we are good to go. + if !n.observer && !n.paused { + n.lxfer = true + n.xferCampaign() + } else if n.paused && !n.pobserver { + // Here we can become a leader but need to wait for resume of the apply queue. + n.lxfer = true + } + } + } + case EntryAddPeer: + if newPeer := string(e.Data); len(newPeer) == idLen { + // Track directly, but wait for commit to be official + if _, ok := n.peers[newPeer]; !ok { + n.peers[newPeer] = &lps{time.Time{}, 0, false} + } + // Store our peer in our global peer map for all peers. + peers.LoadOrStore(newPeer, newPeer) + } + } + } + + // Make a copy of these values, as the AppendEntry might be cached and returned to the pool in applyCommit. + aeCommit := ae.commit + aeReply := ae.reply + + // Apply anything we need here. + if aeCommit > n.commit { + if n.paused { + n.hcommit = aeCommit + n.debug("Paused, not applying %d", aeCommit) + } else { + for index := n.commit + 1; index <= aeCommit; index++ { + if err := n.applyCommit(index); err != nil { + break + } + } + } + } + + // Only ever respond to new entries. + // Never respond to catchup messages, because providing quorum based on this is unsafe. + // The only way for the leader to receive "success" MUST be through this path. + var ar *appendEntryResponse + if sub != nil && isNew { + ar = newAppendEntryResponse(n.pterm, n.pindex, n.id, true) + } + n.Unlock() + + // Success. Send our response. + if ar != nil { + n.sendRPC(aeReply, _EMPTY_, ar.encode(arbuf)) + arPool.Put(ar) + } +} + +// processPeerState is called when a peer state entry is received +// over the wire or when we're updating known peers. +// Lock should be held. +func (n *raft) processPeerState(ps *peerState) { + // Update our version of peers to that of the leader. Calculate + // the number of nodes needed to establish a quorum. + n.csz = ps.clusterSize + n.qn = n.csz/2 + 1 + + old := n.peers + n.peers = make(map[string]*lps) + for _, peer := range ps.knownPeers { + if lp := old[peer]; lp != nil { + lp.kp = true + n.peers[peer] = lp + } else { + n.peers[peer] = &lps{time.Time{}, 0, true} + } + } + n.debug("Update peers from leader to %+v", n.peers) + n.writePeerState(ps) +} + +// processAppendEntryResponse is called when we receive an append entry +// response from another node. They will send a confirmation to tell us +// whether they successfully committed the entry or not. +func (n *raft) processAppendEntryResponse(ar *appendEntryResponse) { + n.trackPeer(ar.peer) + + if ar.success { + // The remote node successfully committed the append entry. + // They agree with our leadership and are happy with the state of the log. + // In this case ar.term doesn't matter. + var err error + var committed bool + + n.Lock() + if n.trackResponse(ar) { + committed, err = n.tryCommit(ar.index) + } + n.Unlock() + + // Leader was peer-removed. Attempt a step-down to + // a new leader before shutting down. + if err == errNodeRemoved { + n.StepDown() + n.Stop() + } + + // Send a heartbeat if there is no other message lined + // up, so that followers can apply without waiting for + // the next message. + if committed && n.prop.len() == 0 { + n.sendHeartbeat() + } + + arPool.Put(ar) + } else if ar.reply != _EMPTY_ { + // The remote node didn't commit the append entry, and they believe they + // are behind and have specified a reply subject, so let's try to catch them up. + // In this case ar.term was populated with the remote's pterm. + n.catchupFollower(ar) + } else if ar.term > n.term { + // The remote node didn't commit the append entry, it looks like + // they are on a newer term than we are. Step down. + // In this case ar.term was populated with the remote's term. + n.Lock() + n.term = ar.term + n.vote = noVote + n.writeTermVote() + n.warn("Detected another leader with higher term, will stepdown") + n.stepdownLocked(noLeader) + n.Unlock() + arPool.Put(ar) + } else { + // Ignore, but return back to pool. + arPool.Put(ar) + } +} + +// handleAppendEntryResponse processes responses to append entries. +func (n *raft) handleAppendEntryResponse(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + ar := decodeAppendEntryResponse(msg) + ar.reply = reply + n.resp.push(ar) +} + +func (n *raft) buildAppendEntry(entries []*Entry) *appendEntry { + return newAppendEntry(n.id, n.term, n.commit, n.pterm, n.pindex, entries) +} + +// Determine if we should store an entry. This stops us from storing +// heartbeat messages. +func (ae *appendEntry) shouldStore() bool { + return ae != nil && len(ae.entries) > 0 +} + +// Store our append entry to our WAL. +// lock should be held. +func (n *raft) storeToWAL(ae *appendEntry) error { + if ae == nil { + return fmt.Errorf("raft: Missing append entry for storage") + } + if n.werr != nil { + return n.werr + } + + seq, _, err := n.wal.StoreMsg(_EMPTY_, nil, ae.buf, 0) + if err != nil { + n.setWriteErrLocked(err) + return err + } + + // Sanity checking for now. + if index := ae.pindex + 1; index != seq { + n.warn("Wrong index, ae is %+v, index stored was %d, n.pindex is %d, will reset", ae, seq, n.pindex) + if n.State() == Leader { + n.stepdownLocked(n.selectNextLeader()) + } + // Reset and cancel any catchup. + n.resetWAL() + n.cancelCatchup() + return errEntryStoreFailed + } + + var sz uint64 + if n.wtype == FileStorage { + sz = fileStoreMsgSize(_EMPTY_, nil, ae.buf) + } else { + sz = memStoreMsgSize(_EMPTY_, nil, ae.buf) + } + n.bytes += sz + n.pterm = ae.term + n.pindex = seq + return nil +} + +const ( + paeDropThreshold = 20_000 + paeWarnThreshold = 10_000 + paeWarnModulo = 5_000 +) + +func (n *raft) sendAppendEntry(entries []*Entry) { + n.Lock() + defer n.Unlock() + n.sendAppendEntryLocked(entries, true) +} + +// Returns nil if an appendEntry was appended to our WAL and sent to followers, +// an error otherwise. +func (n *raft) sendAppendEntryLocked(entries []*Entry, checkLeader bool) error { + // Safeguard against sending an append entry right after a stepdown from a different goroutine. + // Specifically done while holding the lock to not race. + if checkLeader && n.State() != Leader { + n.debug("Not sending append entry, not leader") + return errNotLeader + } + ae := n.buildAppendEntry(entries) + + var err error + var scratch [1024]byte + ae.buf, err = ae.encode(scratch[:]) + if err != nil { + return err + } + + // If we have entries store this in our wal. + shouldStore := ae.shouldStore() + if shouldStore { + if err := n.storeToWAL(ae); err != nil { + return err + } + n.active = time.Now() + n.cachePendingEntry(ae) + } + n.sendRPC(n.asubj, n.areply, ae.buf) + if !shouldStore { + ae.returnToPool() + } + if n.csz == 1 { + n.tryCommit(n.pindex) + } + return nil +} + +// cachePendingEntry saves append entries in memory for faster processing during applyCommit. +// Only save so many however to avoid memory bloat. +func (n *raft) cachePendingEntry(ae *appendEntry) { + if l := len(n.pae); l < paeDropThreshold { + n.pae[n.pindex], l = ae, l+1 + if l >= paeWarnThreshold && l%paeWarnModulo == 0 { + n.warn("%d append entries pending", len(n.pae)) + } + } else { + // Invalidate cache entry at this index, we might have + // stored it previously with a different value. + delete(n.pae, n.pindex) + } +} + +type extensionState uint16 + +const ( + extUndetermined = extensionState(iota) + extExtended + extNotExtended +) + +type peerState struct { + knownPeers []string + clusterSize int + domainExt extensionState +} + +func peerStateBufSize(ps *peerState) int { + return 4 + 4 + (idLen * len(ps.knownPeers)) + 2 +} + +func encodePeerState(ps *peerState) []byte { + var le = binary.LittleEndian + buf := make([]byte, peerStateBufSize(ps)) + le.PutUint32(buf[0:], uint32(ps.clusterSize)) + le.PutUint32(buf[4:], uint32(len(ps.knownPeers))) + wi := 8 + for _, peer := range ps.knownPeers { + copy(buf[wi:], peer) + wi += idLen + } + le.PutUint16(buf[wi:], uint16(ps.domainExt)) + return buf +} + +func decodePeerState(buf []byte) (*peerState, error) { + if len(buf) < 8 { + return nil, errCorruptPeers + } + var le = binary.LittleEndian + ps := &peerState{clusterSize: int(le.Uint32(buf[0:]))} + expectedPeers := int(le.Uint32(buf[4:])) + buf = buf[8:] + ri := 0 + for i, n := 0, expectedPeers; i < n && ri < len(buf); i++ { + ps.knownPeers = append(ps.knownPeers, string(buf[ri:ri+idLen])) + ri += idLen + } + if len(ps.knownPeers) != expectedPeers { + return nil, errCorruptPeers + } + if len(buf[ri:]) >= 2 { + ps.domainExt = extensionState(le.Uint16(buf[ri:])) + } + return ps, nil +} + +// Lock should be held. +func (n *raft) peerNames() []string { + var peers []string + for name, peer := range n.peers { + if peer.kp { + peers = append(peers, name) + } + } + return peers +} + +func (n *raft) currentPeerState() *peerState { + n.RLock() + ps := n.currentPeerStateLocked() + n.RUnlock() + return ps +} + +func (n *raft) currentPeerStateLocked() *peerState { + return &peerState{n.peerNames(), n.csz, n.extSt} +} + +// sendPeerState will send our current peer state to the cluster. +// Lock should be held. +func (n *raft) sendPeerState() { + n.sendAppendEntryLocked([]*Entry{{EntryPeerState, encodePeerState(n.currentPeerStateLocked())}}, true) +} + +// Send a heartbeat. +func (n *raft) sendHeartbeat() { + n.sendAppendEntry(nil) +} + +type voteRequest struct { + term uint64 + lastTerm uint64 + lastIndex uint64 + candidate string + // internal only. + reply string +} + +const voteRequestLen = 24 + idLen + +func (vr *voteRequest) encode() []byte { + var buf [voteRequestLen]byte + var le = binary.LittleEndian + le.PutUint64(buf[0:], vr.term) + le.PutUint64(buf[8:], vr.lastTerm) + le.PutUint64(buf[16:], vr.lastIndex) + copy(buf[24:24+idLen], vr.candidate) + + return buf[:voteRequestLen] +} + +func decodeVoteRequest(msg []byte, reply string) *voteRequest { + if len(msg) != voteRequestLen { + return nil + } + + var le = binary.LittleEndian + return &voteRequest{ + term: le.Uint64(msg[0:]), + lastTerm: le.Uint64(msg[8:]), + lastIndex: le.Uint64(msg[16:]), + candidate: string(copyBytes(msg[24 : 24+idLen])), + reply: reply, + } +} + +const peerStateFile = "peers.idx" + +// Lock should be held. +func (n *raft) writePeerState(ps *peerState) { + pse := encodePeerState(ps) + if bytes.Equal(n.wps, pse) { + return + } + // Stamp latest and write the peer state file. + n.wps = pse + if err := writePeerState(n.sd, ps); err != nil && !n.isClosed() { + n.setWriteErrLocked(err) + n.warn("Error writing peer state file for %q: %v", n.group, err) + } +} + +// Writes out our peer state outside of a specific raft context. +func writePeerState(sd string, ps *peerState) error { + psf := filepath.Join(sd, peerStateFile) + if _, err := os.Stat(psf); err != nil && !os.IsNotExist(err) { + return err + } + return writeFileWithSync(psf, encodePeerState(ps), defaultFilePerms) +} + +func readPeerState(sd string) (ps *peerState, err error) { + <-dios + buf, err := os.ReadFile(filepath.Join(sd, peerStateFile)) + dios <- struct{}{} + + if err != nil { + return nil, err + } + return decodePeerState(buf) +} + +const termVoteFile = "tav.idx" +const termLen = 8 // uint64 +const termVoteLen = idLen + termLen + +// Writes out our term & vote outside of a specific raft context. +func writeTermVote(sd string, wtv []byte) error { + psf := filepath.Join(sd, termVoteFile) + if _, err := os.Stat(psf); err != nil && !os.IsNotExist(err) { + return err + } + return writeFileWithSync(psf, wtv, defaultFilePerms) +} + +// readTermVote will read the largest term and who we voted from to stable storage. +// Lock should be held. +func (n *raft) readTermVote() (term uint64, voted string, err error) { + <-dios + buf, err := os.ReadFile(filepath.Join(n.sd, termVoteFile)) + dios <- struct{}{} + + if err != nil { + return 0, noVote, err + } + if len(buf) < termLen { + // Not enough bytes for the uint64 below, so avoid a panic. + return 0, noVote, nil + } + var le = binary.LittleEndian + term = le.Uint64(buf[0:]) + if len(buf) < termVoteLen { + return term, noVote, nil + } + voted = string(buf[8:]) + return term, voted, nil +} + +// Lock should be held. +func (n *raft) setWriteErrLocked(err error) { + // Check if we are closed already. + if n.State() == Closed { + return + } + // Ignore if already set. + if n.werr == err || err == nil { + return + } + // Ignore non-write errors. + if err == ErrStoreClosed || + err == ErrStoreEOF || + err == ErrStoreMsgNotFound || + err == errNoPending || + err == errPartialCache { + return + } + // If this is a not found report but do not disable. + if os.IsNotExist(err) { + n.error("Resource not found: %v", err) + return + } + n.error("Critical write error: %v", err) + n.werr = err + + if isPermissionError(err) { + go n.s.handleWritePermissionError() + } + + if isOutOfSpaceErr(err) { + // For now since this can be happening all under the covers, we will call up and disable JetStream. + go n.s.handleOutOfSpace(nil) + } +} + +// Helper to check if we are closed when we do not hold a lock already. +func (n *raft) isClosed() bool { + return n.State() == Closed +} + +// Capture our write error if any and hold. +func (n *raft) setWriteErr(err error) { + n.Lock() + defer n.Unlock() + n.setWriteErrLocked(err) +} + +// writeTermVote will record the largest term and who we voted for to stable storage. +// Lock should be held. +func (n *raft) writeTermVote() { + var buf [termVoteLen]byte + var le = binary.LittleEndian + le.PutUint64(buf[0:], n.term) + copy(buf[8:], n.vote) + b := buf[:8+len(n.vote)] + + // If the term and vote hasn't changed then don't rewrite to disk. + if bytes.Equal(n.wtv, b) { + return + } + // Stamp latest and write the term & vote file. + n.wtv = b + if err := writeTermVote(n.sd, n.wtv); err != nil && !n.isClosed() { + // Clear wtv since we failed. + n.wtv = nil + n.setWriteErrLocked(err) + n.warn("Error writing term and vote file for %q: %v", n.group, err) + } +} + +// voteResponse is a response to a vote request. +type voteResponse struct { + term uint64 + peer string + granted bool +} + +const voteResponseLen = 8 + 8 + 1 + +func (vr *voteResponse) encode() []byte { + var buf [voteResponseLen]byte + var le = binary.LittleEndian + le.PutUint64(buf[0:], vr.term) + copy(buf[8:], vr.peer) + if vr.granted { + buf[16] = 1 + } else { + buf[16] = 0 + } + return buf[:voteResponseLen] +} + +func decodeVoteResponse(msg []byte) *voteResponse { + if len(msg) != voteResponseLen { + return nil + } + var le = binary.LittleEndian + vr := &voteResponse{term: le.Uint64(msg[0:]), peer: string(msg[8:16])} + vr.granted = msg[16] == 1 + return vr +} + +func (n *raft) handleVoteResponse(sub *subscription, c *client, _ *Account, _, reply string, msg []byte) { + vr := decodeVoteResponse(msg) + n.debug("Received a voteResponse %+v", vr) + if vr == nil { + n.error("Received malformed vote response for %q", n.group) + return + } + + if state := n.State(); state != Candidate && state != Leader { + n.debug("Ignoring old vote response, we have stepped down") + return + } + + n.votes.push(vr) +} + +func (n *raft) processVoteRequest(vr *voteRequest) error { + // To simplify calling code, we can possibly pass `nil` to this function. + // If that is the case, does not consider it an error. + if vr == nil { + return nil + } + n.debug("Received a voteRequest %+v", vr) + + n.Lock() + + vresp := &voteResponse{n.term, n.id, false} + defer n.debug("Sending a voteResponse %+v -> %q", vresp, vr.reply) + + // Ignore if we are newer. This is important so that we don't accidentally process + // votes from a previous term if they were still in flight somewhere. + if vr.term < n.term { + n.Unlock() + n.sendReply(vr.reply, vresp.encode()) + return nil + } + + // If this is a higher term go ahead and stepdown. + if vr.term > n.term { + if n.State() != Follower { + n.debug("Stepping down from %s, detected higher term: %d vs %d", + strings.ToLower(n.State().String()), vr.term, n.term) + n.stepdownLocked(noLeader) + } + n.cancelCatchup() + n.term = vr.term + n.vote = noVote + n.writeTermVote() + } + + // Only way we get to yes is through here. + voteOk := n.vote == noVote || n.vote == vr.candidate + if voteOk && (vr.lastTerm > n.pterm || vr.lastTerm == n.pterm && vr.lastIndex >= n.pindex) { + vresp.granted = true + n.term = vr.term + n.vote = vr.candidate + n.writeTermVote() + n.resetElectionTimeout() + } else if n.vote == noVote && n.State() != Candidate { + // We have a more up-to-date log, and haven't voted yet. + // Start campaigning earlier, but only if not candidate already, as that would short-circuit us. + n.resetElect(randCampaignTimeout()) + } + + // Term might have changed, make sure response has the most current + vresp.term = n.term + + n.Unlock() + + n.sendReply(vr.reply, vresp.encode()) + + return nil +} + +func (n *raft) handleVoteRequest(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { + vr := decodeVoteRequest(msg, reply) + if vr == nil { + n.error("Received malformed vote request for %q", n.group) + return + } + n.reqs.push(vr) +} + +func (n *raft) requestVote() { + n.Lock() + if n.State() != Candidate { + n.Unlock() + return + } + n.vote = n.id + n.writeTermVote() + vr := voteRequest{n.term, n.pterm, n.pindex, n.id, _EMPTY_} + subj, reply := n.vsubj, n.vreply + n.Unlock() + + n.debug("Sending out voteRequest %+v", vr) + + // Now send it out. + n.sendRPC(subj, reply, vr.encode()) +} + +func (n *raft) sendRPC(subject, reply string, msg []byte) { + if n.sq != nil { + n.sq.send(subject, reply, nil, msg) + } +} + +func (n *raft) sendReply(subject string, msg []byte) { + if n.sq != nil { + n.sq.send(subject, _EMPTY_, nil, msg) + } +} + +func (n *raft) wonElection(votes int) bool { + return votes >= n.quorumNeeded() +} + +// Return the quorum size for a given cluster config. +func (n *raft) quorumNeeded() int { + n.RLock() + qn := n.qn + n.RUnlock() + return qn +} + +// Lock should be held. +func (n *raft) updateLeadChange(isLeader bool) { + // We don't care about values that have not been consumed (transitory states), + // so we dequeue any state that is pending and push the new one. + for { + select { + case n.leadc <- isLeader: + return + default: + select { + case <-n.leadc: + default: + // May have been consumed by the "reader" go routine, so go back + // to the top of the loop and try to send again. + } + } + } +} + +// Lock should be held. +func (n *raft) switchState(state RaftState) bool { +retry: + pstate := n.State() + if pstate == Closed { + return false + } + + // Set our state. If something else has changed our state + // then retry, this will either be a Stop or Delete call. + if !n.state.CompareAndSwap(int32(pstate), int32(state)) { + goto retry + } + + // Reset the election timer. + n.resetElectionTimeout() + + var leadChange bool + if pstate == Leader && state != Leader { + leadChange = true + n.updateLeadChange(false) + // Drain the append entry response and proposal queues. + n.resp.drain() + n.prop.drain() + } else if state == Leader && pstate != Leader { + // Don't updateLeadChange here, it will be done in switchToLeader or after initial messages are applied. + leadChange = true + if len(n.pae) > 0 { + n.pae = make(map[uint64]*appendEntry) + } + } + + n.writeTermVote() + return leadChange +} + +const ( + noLeader = _EMPTY_ + noVote = _EMPTY_ +) + +func (n *raft) switchToFollower(leader string) { + n.Lock() + defer n.Unlock() + + n.switchToFollowerLocked(leader) +} + +func (n *raft) switchToFollowerLocked(leader string) { + if n.State() == Closed { + return + } + + n.debug("Switching to follower") + + n.aflr = 0 + n.leaderState.Store(false) + n.leaderSince.Store(nil) + n.lxfer = false + n.membChanging = false + + // Reset acks, we can't assume acks from a previous term are still valid in another term. + if len(n.acks) > 0 { + n.acks = make(map[uint64]map[string]struct{}) + } + n.updateLeader(leader) + n.switchState(Follower) +} + +func (n *raft) switchToCandidate() { + if n.State() == Closed { + return + } + + n.Lock() + defer n.Unlock() + + // If we are catching up or are in observer mode we can not switch. + // Avoid petitioning to become leader if we're behind on applies. + if n.observer || n.paused || n.applied < n.commit { + n.resetElect(minElectionTimeout / 4) + return + } + + if n.State() != Candidate { + n.debug("Switching to candidate") + } else { + if n.lostQuorumLocked() && time.Since(n.llqrt) > 20*time.Second { + // We signal to the upper layers such that can alert on quorum lost. + n.updateLeadChange(false) + n.llqrt = time.Now() + } + } + // Increment the term. + n.term++ + // Clear current Leader. + n.updateLeader(noLeader) + n.switchState(Candidate) +} + +func (n *raft) switchToLeader() { + if n.State() == Closed { + return + } + + n.Lock() + defer n.Unlock() + + n.debug("Switching to leader") + + n.lxfer = false + n.updateLeader(n.id) + n.switchState(Leader) + + // To send out our initial peer state. + // In our implementation this is equivalent to sending a NOOP-entry upon becoming leader. + // Wait for this message (and potentially more) to be applied. + // It's important to wait signaling we're leader if we're not up-to-date yet, as that + // would mean we're in a consistent state compared with the previous leader. + n.sendPeerState() + n.aflr = n.pindex +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/rate_counter.go b/vendor/github.com/nats-io/nats-server/v2/server/rate_counter.go new file mode 100644 index 0000000..0988b83 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/rate_counter.go @@ -0,0 +1,65 @@ +// Copyright 2021-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "sync" + "time" +) + +type rateCounter struct { + limit int64 + count int64 + blocked uint64 + end time.Time + interval time.Duration + mu sync.Mutex +} + +func newRateCounter(limit int64) *rateCounter { + return &rateCounter{ + limit: limit, + interval: time.Second, + } +} + +func (r *rateCounter) allow() bool { + now := time.Now() + + r.mu.Lock() + + if now.After(r.end) { + r.count = 0 + r.end = now.Add(r.interval) + } else { + r.count++ + } + allow := r.count < r.limit + if !allow { + r.blocked++ + } + + r.mu.Unlock() + + return allow +} + +func (r *rateCounter) countBlocked() uint64 { + r.mu.Lock() + blocked := r.blocked + r.blocked = 0 + r.mu.Unlock() + + return blocked +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/reload.go b/vendor/github.com/nats-io/nats-server/v2/server/reload.go index 790bb80..cce223b 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/reload.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/reload.go @@ -1,4 +1,4 @@ -// Copyright 2017-2020 The NATS Authors +// Copyright 2017-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,17 +14,21 @@ package server import ( + "cmp" "crypto/tls" "errors" "fmt" "net/url" "reflect" - "sort" + "slices" "strings" "sync/atomic" "time" + "github.com/klauspost/compress/s2" + "github.com/nats-io/jwt/v2" + "github.com/nats-io/nuid" ) // FlagSnapshot captures the server options as specified by CLI flags at @@ -50,13 +54,23 @@ type option interface { // IsAuthChange indicates if this option requires reloading authorization. IsAuthChange() bool + // IsTLSChange indicates if this option requires reloading TLS. + IsTLSChange() bool + // IsClusterPermsChange indicates if this option requires reloading // cluster permissions. IsClusterPermsChange() bool + // IsClusterPoolSizeOrAccountsChange indicates if this option requires + // special handling for changes in cluster's pool size or accounts list. + IsClusterPoolSizeOrAccountsChange() bool + // IsJetStreamChange inidicates a change in the servers config for JetStream. // Account changes will be handled separately in reloadAuthorization. IsJetStreamChange() bool + + // Indicates a change in the server that requires publishing the server's statz + IsStatszChange() bool } // noopOption is a base struct that provides default no-op behaviors. @@ -74,14 +88,26 @@ func (n noopOption) IsAuthChange() bool { return false } +func (n noopOption) IsTLSChange() bool { + return false +} + func (n noopOption) IsClusterPermsChange() bool { return false } +func (n noopOption) IsClusterPoolSizeOrAccountsChange() bool { + return false +} + func (n noopOption) IsJetStreamChange() bool { return false } +func (n noopOption) IsStatszChange() bool { + return false +} + // loggingOption is a base struct that provides default option behaviors for // logging-related options. type loggingOption struct { @@ -113,7 +139,7 @@ func (t *traceOption) Apply(server *Server) { server.Noticef("Reloaded: trace = %v", t.newValue) } -// traceOption implements the option interface for the `trace` setting. +// traceVersboseOption implements the option interface for the `trace_verbose` setting. type traceVerboseOption struct { traceLevelOption newValue bool @@ -124,15 +150,28 @@ func (t *traceVerboseOption) Apply(server *Server) { server.Noticef("Reloaded: trace_verbose = %v", t.newValue) } +// traceHeadersOption implements the option interface for the `trace_headers` setting. +type traceHeadersOption struct { + traceLevelOption + newValue bool +} + +// Apply is a no-op because logging will be reloaded after options are applied. +func (t *traceHeadersOption) Apply(server *Server) { + server.Noticef("Reloaded: trace_headers = %v", t.newValue) +} + // debugOption implements the option interface for the `debug` setting. type debugOption struct { loggingOption newValue bool } -// Apply is a no-op because logging will be reloaded after options are applied. +// Apply is mostly a no-op because logging will be reloaded after options are applied. +// However we will kick the raft nodes if they exist to reload. func (d *debugOption) Apply(server *Server) { server.Noticef("Reloaded: debug = %v", d.newValue) + server.reloadDebugRaftNodes(d.newValue) } // logtimeOption implements the option interface for the `logtime` setting. @@ -146,6 +185,17 @@ func (l *logtimeOption) Apply(server *Server) { server.Noticef("Reloaded: logtime = %v", l.newValue) } +// logtimeUTCOption implements the option interface for the `logtime_utc` setting. +type logtimeUTCOption struct { + loggingOption + newValue bool +} + +// Apply is a no-op because logging will be reloaded after options are applied. +func (l *logtimeUTCOption) Apply(server *Server) { + server.Noticef("Reloaded: logtime_utc = %v", l.newValue) +} + // logfileOption implements the option interface for the `log_file` setting. type logfileOption struct { loggingOption @@ -190,7 +240,7 @@ type tlsOption struct { func (t *tlsOption) Apply(server *Server) { server.mu.Lock() tlsRequired := t.newValue != nil - server.info.TLSRequired = tlsRequired + server.info.TLSRequired = tlsRequired && !server.getOpts().AllowNonTLS message := "disabled" if tlsRequired { server.info.TLSVerify = (t.newValue.ClientAuth == tls.RequireAndVerifyClientCert) @@ -200,6 +250,10 @@ func (t *tlsOption) Apply(server *Server) { server.Noticef("Reloaded: tls = %s", message) } +func (t *tlsOption) IsTLSChange() bool { + return true +} + // tlsTimeoutOption implements the option interface for the tls `timeout` // setting. type tlsTimeoutOption struct { @@ -213,6 +267,39 @@ func (t *tlsTimeoutOption) Apply(server *Server) { server.Noticef("Reloaded: tls timeout = %v", t.newValue) } +// tlsPinnedCertOption implements the option interface for the tls `pinned_certs` setting. +type tlsPinnedCertOption struct { + noopOption + newValue PinnedCertSet +} + +// Apply is a no-op because the pinned certs will be reloaded after options are applied. +func (t *tlsPinnedCertOption) Apply(server *Server) { + server.Noticef("Reloaded: %d pinned_certs", len(t.newValue)) +} + +// tlsHandshakeFirst implements the option interface for the tls `handshake first` setting. +type tlsHandshakeFirst struct { + noopOption + newValue bool +} + +// Apply is a no-op because the timeout will be reloaded after options are applied. +func (t *tlsHandshakeFirst) Apply(server *Server) { + server.Noticef("Reloaded: Client TLS handshake first: %v", t.newValue) +} + +// tlsHandshakeFirstFallback implements the option interface for the tls `handshake first fallback delay` setting. +type tlsHandshakeFirstFallback struct { + noopOption + newValue time.Duration +} + +// Apply is a no-op because the timeout will be reloaded after options are applied. +func (t *tlsHandshakeFirstFallback) Apply(server *Server) { + server.Noticef("Reloaded: Client TLS handshake first fallback delay: %v", t.newValue) +} + // authOption is a base struct that provides default option behaviors. type authOption struct { noopOption @@ -269,6 +356,19 @@ func (a *authTimeoutOption) Apply(server *Server) { server.Noticef("Reloaded: authorization timeout = %v", a.newValue) } +// tagsOption implements the option interface for the `tags` setting. +type tagsOption struct { + noopOption // Not authOption because this is a no-op; will be reloaded with options. +} + +func (u *tagsOption) Apply(server *Server) { + server.Noticef("Reloaded: tags") +} + +func (u *tagsOption) IsStatszChange() bool { + return true +} + // usersOption implements the option interface for the authorization `users` // setting. type usersOption struct { @@ -292,8 +392,12 @@ func (u *nkeysOption) Apply(server *Server) { // clusterOption implements the option interface for the `cluster` setting. type clusterOption struct { authOption - newValue ClusterOpts - permsChanged bool + newValue ClusterOpts + permsChanged bool + accsAdded []string + accsRemoved []string + poolSizeChanged bool + compressChanged bool } // Apply the cluster change. @@ -312,10 +416,44 @@ func (c *clusterOption) Apply(s *Server) { s.routeInfo.WSConnectURLs = s.websocket.connectURLs } s.setRouteInfoHostPortAndIP() + var routes []*client + if c.compressChanged { + co := &s.getOpts().Cluster.Compression + newMode := co.Mode + s.forEachRoute(func(r *client) { + r.mu.Lock() + // Skip routes that are "not supported" (because they will never do + // compression) or the routes that have already the new compression + // mode. + if r.route.compression == CompressionNotSupported || r.route.compression == newMode { + r.mu.Unlock() + return + } + // We need to close the route if it had compression "off" or the new + // mode is compression "off", or if the new mode is "accept", because + // these require negotiation. + if r.route.compression == CompressionOff || newMode == CompressionOff || newMode == CompressionAccept { + routes = append(routes, r) + } else if newMode == CompressionS2Auto { + // If the mode is "s2_auto", we need to check if there is really + // need to change, and at any rate, we want to save the actual + // compression level here, not s2_auto. + r.updateS2AutoCompressionLevel(co, &r.route.compression) + } else { + // Simply change the compression writer + r.out.cw = s2.NewWriter(nil, s2WriterOptions(newMode)...) + r.route.compression = newMode + } + r.mu.Unlock() + }) + } s.mu.Unlock() if c.newValue.Name != "" && c.newValue.Name != s.ClusterName() { s.setClusterName(c.newValue.Name) } + for _, r := range routes { + r.closeConnection(ClientClosed) + } s.Noticef("Reloaded: cluster") if tlsRequired && c.newValue.TLSConfig.InsecureSkipVerify { s.Warnf(clusterTLSInsecureWarning) @@ -326,6 +464,32 @@ func (c *clusterOption) IsClusterPermsChange() bool { return c.permsChanged } +func (c *clusterOption) IsClusterPoolSizeOrAccountsChange() bool { + return c.poolSizeChanged || len(c.accsAdded) > 0 || len(c.accsRemoved) > 0 +} + +func (c *clusterOption) diffPoolAndAccounts(old *ClusterOpts) { + c.poolSizeChanged = c.newValue.PoolSize != old.PoolSize +addLoop: + for _, na := range c.newValue.PinnedAccounts { + for _, oa := range old.PinnedAccounts { + if na == oa { + continue addLoop + } + } + c.accsAdded = append(c.accsAdded, na) + } +removeLoop: + for _, oa := range old.PinnedAccounts { + for _, na := range c.newValue.PinnedAccounts { + if oa == na { + continue removeLoop + } + } + c.accsRemoved = append(c.accsRemoved, oa) + } +} + // routesOption implements the option interface for the cluster `routes` // setting. type routesOption struct { @@ -337,12 +501,12 @@ type routesOption struct { // Apply the route changes by adding and removing the necessary routes. func (r *routesOption) Apply(server *Server) { server.mu.Lock() - routes := make([]*client, len(server.routes)) + routes := make([]*client, server.numRoutes()) i := 0 - for _, client := range server.routes { - routes[i] = client + server.forEachRoute(func(r *client) { + routes[i] = r i++ - } + }) // If there was a change, notify monitoring code that it should // update the route URLs if /varz endpoint is inspected. if len(r.add)+len(r.remove) > 0 { @@ -369,7 +533,9 @@ func (r *routesOption) Apply(server *Server) { } // Add routes. - server.solicitRoutes(r.add) + server.mu.Lock() + server.solicitRoutes(r.add, server.getOpts().Cluster.PinnedAccounts) + server.mu.Unlock() server.Noticef("Reloaded: cluster routes") } @@ -551,13 +717,44 @@ type jetStreamOption struct { } func (a *jetStreamOption) Apply(s *Server) { - s.Noticef("Reloaded: jetstream") + s.Noticef("Reloaded: JetStream") } func (jso jetStreamOption) IsJetStreamChange() bool { return true } +func (jso jetStreamOption) IsStatszChange() bool { + return true +} + +type defaultSentinelOption struct { + noopOption + newValue string +} + +func (so *defaultSentinelOption) Apply(s *Server) { + s.Noticef("Reloaded: default_sentinel = %s", so.newValue) +} + +type ocspOption struct { + tlsOption + newValue *OCSPConfig +} + +func (a *ocspOption) Apply(s *Server) { + s.Noticef("Reloaded: OCSP") +} + +type ocspResponseCacheOption struct { + tlsOption + newValue *OCSPResponseCacheConfig +} + +func (a *ocspResponseCacheOption) Apply(s *Server) { + s.Noticef("Reloaded OCSP peer cache") +} + // connectErrorReports implements the option interface for the `connect_error_reports` // setting. type connectErrorReports struct { @@ -615,30 +812,234 @@ func (o *mqttMaxAckPendingReload) Apply(s *Server) { s.Noticef("Reloaded: MQTT max_ack_pending = %v", o.newValue) } -// Reload reads the current configuration file and applies any supported -// changes. This returns an error if the server was not started with a config -// file or an option which doesn't support hot-swapping was changed. -func (s *Server) Reload() error { - s.mu.Lock() +type mqttStreamReplicasReload struct { + noopOption + newValue int +} - s.reloading = true - defer func() { - s.mu.Lock() - s.reloading = false - s.mu.Unlock() - }() +func (o *mqttStreamReplicasReload) Apply(s *Server) { + s.Noticef("Reloaded: MQTT stream_replicas = %v", o.newValue) +} - if s.configFile == "" { - s.mu.Unlock() +type mqttConsumerReplicasReload struct { + noopOption + newValue int +} + +func (o *mqttConsumerReplicasReload) Apply(s *Server) { + s.Noticef("Reloaded: MQTT consumer_replicas = %v", o.newValue) +} + +type mqttConsumerMemoryStorageReload struct { + noopOption + newValue bool +} + +func (o *mqttConsumerMemoryStorageReload) Apply(s *Server) { + s.Noticef("Reloaded: MQTT consumer_memory_storage = %v", o.newValue) +} + +type mqttInactiveThresholdReload struct { + noopOption + newValue time.Duration +} + +func (o *mqttInactiveThresholdReload) Apply(s *Server) { + s.Noticef("Reloaded: MQTT consumer_inactive_threshold = %v", o.newValue) +} + +type profBlockRateReload struct { + noopOption + newValue int +} + +func (o *profBlockRateReload) Apply(s *Server) { + s.setBlockProfileRate(o.newValue) + s.Noticef("Reloaded: prof_block_rate = %v", o.newValue) +} + +type leafNodeOption struct { + noopOption + tlsFirstChanged bool + compressionChanged bool +} + +func (l *leafNodeOption) Apply(s *Server) { + opts := s.getOpts() + if l.tlsFirstChanged { + s.Noticef("Reloaded: LeafNode TLS HandshakeFirst value is: %v", opts.LeafNode.TLSHandshakeFirst) + s.Noticef("Reloaded: LeafNode TLS HandshakeFirstFallback value is: %v", opts.LeafNode.TLSHandshakeFirstFallback) + for _, r := range opts.LeafNode.Remotes { + s.Noticef("Reloaded: LeafNode Remote to %v TLS HandshakeFirst value is: %v", r.URLs, r.TLSHandshakeFirst) + } + } + if l.compressionChanged { + var leafs []*client + acceptSideCompOpts := &opts.LeafNode.Compression + + s.mu.RLock() + // First, update our internal leaf remote configurations with the new + // compress options. + // Since changing the remotes (as in adding/removing) is currently not + // supported, we know that we should have the same number in Options + // than in leafRemoteCfgs, but to be sure, use the max size. + max := len(opts.LeafNode.Remotes) + if l := len(s.leafRemoteCfgs); l < max { + max = l + } + for i := 0; i < max; i++ { + lr := s.leafRemoteCfgs[i] + lr.Lock() + lr.Compression = opts.LeafNode.Remotes[i].Compression + lr.Unlock() + } + + for _, l := range s.leafs { + var co *CompressionOpts + + l.mu.Lock() + if r := l.leaf.remote; r != nil { + co = &r.Compression + } else { + co = acceptSideCompOpts + } + newMode := co.Mode + // Skip leaf connections that are "not supported" (because they + // will never do compression) or the ones that have already the + // new compression mode. + if l.leaf.compression == CompressionNotSupported || l.leaf.compression == newMode { + l.mu.Unlock() + continue + } + // We need to close the connections if it had compression "off" or the new + // mode is compression "off", or if the new mode is "accept", because + // these require negotiation. + if l.leaf.compression == CompressionOff || newMode == CompressionOff || newMode == CompressionAccept { + leafs = append(leafs, l) + } else if newMode == CompressionS2Auto { + // If the mode is "s2_auto", we need to check if there is really + // need to change, and at any rate, we want to save the actual + // compression level here, not s2_auto. + l.updateS2AutoCompressionLevel(co, &l.leaf.compression) + } else { + // Simply change the compression writer + l.out.cw = s2.NewWriter(nil, s2WriterOptions(newMode)...) + l.leaf.compression = newMode + } + l.mu.Unlock() + } + s.mu.RUnlock() + // Close the connections for which negotiation is required. + for _, l := range leafs { + l.closeConnection(ClientClosed) + } + s.Noticef("Reloaded: LeafNode compression settings") + } +} + +type noFastProdStallReload struct { + noopOption + noStall bool +} + +func (l *noFastProdStallReload) Apply(s *Server) { + var not string + if l.noStall { + not = "not " + } + s.Noticef("Reloaded: fast producers will %sbe stalled", not) +} + +// Compares options and disconnects clients that are no longer listed in pinned certs. Lock must not be held. +func (s *Server) recheckPinnedCerts(curOpts *Options, newOpts *Options) { + s.mu.Lock() + disconnectClients := []*client{} + protoToPinned := map[int]PinnedCertSet{} + if !reflect.DeepEqual(newOpts.TLSPinnedCerts, curOpts.TLSPinnedCerts) { + protoToPinned[NATS] = curOpts.TLSPinnedCerts + } + if !reflect.DeepEqual(newOpts.MQTT.TLSPinnedCerts, curOpts.MQTT.TLSPinnedCerts) { + protoToPinned[MQTT] = curOpts.MQTT.TLSPinnedCerts + } + if !reflect.DeepEqual(newOpts.Websocket.TLSPinnedCerts, curOpts.Websocket.TLSPinnedCerts) { + protoToPinned[WS] = curOpts.Websocket.TLSPinnedCerts + } + for _, c := range s.clients { + if c.kind != CLIENT { + continue + } + if pinned, ok := protoToPinned[c.clientType()]; ok { + if !c.matchesPinnedCert(pinned) { + disconnectClients = append(disconnectClients, c) + } + } + } + checkClients := func(kind int, clients map[uint64]*client, set PinnedCertSet) { + for _, c := range clients { + if c.kind == kind && !c.matchesPinnedCert(set) { + disconnectClients = append(disconnectClients, c) + } + } + } + if !reflect.DeepEqual(newOpts.LeafNode.TLSPinnedCerts, curOpts.LeafNode.TLSPinnedCerts) { + checkClients(LEAF, s.leafs, newOpts.LeafNode.TLSPinnedCerts) + } + if !reflect.DeepEqual(newOpts.Cluster.TLSPinnedCerts, curOpts.Cluster.TLSPinnedCerts) { + s.forEachRoute(func(c *client) { + if !c.matchesPinnedCert(newOpts.Cluster.TLSPinnedCerts) { + disconnectClients = append(disconnectClients, c) + } + }) + } + if s.gateway.enabled && reflect.DeepEqual(newOpts.Gateway.TLSPinnedCerts, curOpts.Gateway.TLSPinnedCerts) { + gw := s.gateway + gw.RLock() + for _, c := range gw.out { + if !c.matchesPinnedCert(newOpts.Gateway.TLSPinnedCerts) { + disconnectClients = append(disconnectClients, c) + } + } + checkClients(GATEWAY, gw.in, newOpts.Gateway.TLSPinnedCerts) + gw.RUnlock() + } + s.mu.Unlock() + if len(disconnectClients) > 0 { + s.Noticef("Disconnect %d clients due to pinned certs reload", len(disconnectClients)) + for _, c := range disconnectClients { + c.closeConnection(TLSHandshakeError) + } + } +} + +// Reload reads the current configuration file and calls out to ReloadOptions +// to apply the changes. This returns an error if the server was not started +// with a config file or an option which doesn't support hot-swapping was changed. +func (s *Server) Reload() error { + s.mu.Lock() + configFile := s.configFile + s.mu.Unlock() + if configFile == "" { return errors.New("can only reload config when a file is provided using -c or --config") } - newOpts, err := ProcessConfigFile(s.configFile) + newOpts, err := ProcessConfigFile(configFile) if err != nil { - s.mu.Unlock() // TODO: Dump previous good config to a .bak file? return err } + return s.ReloadOptions(newOpts) +} + +// ReloadOptions applies any supported options from the provided Options +// type. This returns an error if an option which doesn't support +// hot-swapping was changed. +// The provided Options type should not be re-used afterwards. +// Either use Options.Clone() to pass a copy, or make a new one. +func (s *Server) ReloadOptions(newOpts *Options) error { + s.reloadMu.Lock() + defer s.reloadMu.Unlock() + + s.mu.Lock() curOpts := s.getOpts() @@ -656,6 +1057,13 @@ func (s *Server) Reload() error { s.mu.Unlock() + // In case "-cluster ..." was provided through the command line, this will + // properly set the Cluster.Host/Port etc... + if l := curOpts.Cluster.ListenStr; l != _EMPTY_ { + newOpts.Cluster.ListenStr = l + overrideCluster(newOpts) + } + // Apply flags over config file settings. newOpts = MergeOptions(newOpts, FlagSnapshot) @@ -692,13 +1100,15 @@ func (s *Server) Reload() error { if err := s.reloadOptions(curOpts, newOpts); err != nil { return err } + + s.recheckPinnedCerts(curOpts, newOpts) + s.mu.Lock() - s.configTime = time.Now() + s.configTime = time.Now().UTC() s.updateVarzConfigReloadableFields(s.varz) s.mu.Unlock() return nil } - func applyBoolFlags(newOpts, flagOpts *Options) { // Reset fields that may have been set to `true` in // MergeOptions() when some of the flags default to `true` @@ -753,44 +1163,33 @@ func (s *Server) reloadOptions(curOpts, newOpts *Options) error { } // For the purpose of comparing, impose a order on slice data types where order does not matter -func imposeOrder(value interface{}) error { +func imposeOrder(value any) error { switch value := value.(type) { case []*Account: - sort.Slice(value, func(i, j int) bool { - return value[i].Name < value[j].Name - }) + slices.SortFunc(value, func(i, j *Account) int { return cmp.Compare(i.Name, j.Name) }) for _, a := range value { - sort.Slice(a.imports.streams, func(i, j int) bool { - return a.imports.streams[i].acc.Name < a.imports.streams[j].acc.Name - }) + slices.SortFunc(a.imports.streams, func(i, j *streamImport) int { return cmp.Compare(i.acc.Name, j.acc.Name) }) } case []*User: - sort.Slice(value, func(i, j int) bool { - return value[i].Username < value[j].Username - }) + slices.SortFunc(value, func(i, j *User) int { return cmp.Compare(i.Username, j.Username) }) case []*NkeyUser: - sort.Slice(value, func(i, j int) bool { - return value[i].Nkey < value[j].Nkey - }) + slices.SortFunc(value, func(i, j *NkeyUser) int { return cmp.Compare(i.Nkey, j.Nkey) }) case []*url.URL: - sort.Slice(value, func(i, j int) bool { - return value[i].String() < value[j].String() - }) + slices.SortFunc(value, func(i, j *url.URL) int { return cmp.Compare(i.String(), j.String()) }) case []string: - sort.Strings(value) + slices.Sort(value) case []*jwt.OperatorClaims: - sort.Slice(value, func(i, j int) bool { - return value[i].Issuer < value[j].Issuer - }) + slices.SortFunc(value, func(i, j *jwt.OperatorClaims) int { return cmp.Compare(i.Issuer, j.Issuer) }) case GatewayOpts: - sort.Slice(value.Gateways, func(i, j int) bool { - return value.Gateways[i].Name < value.Gateways[j].Name - }) + slices.SortFunc(value.Gateways, func(i, j *RemoteGatewayOpts) int { return cmp.Compare(i.Name, j.Name) }) case WebsocketOpts: - sort.Strings(value.AllowedOrigins) - case string, bool, int, int32, int64, time.Duration, float64, nil, - LeafNodeOpts, ClusterOpts, *tls.Config, *URLAccResolver, *MemAccResolver, *DirAccResolver, *CacheDirAccResolver, Authentication, MQTTOpts: + slices.Sort(value.AllowedOrigins) + case string, bool, uint8, uint16, uint64, int, int32, int64, time.Duration, float64, nil, LeafNodeOpts, ClusterOpts, *tls.Config, PinnedCertSet, + *URLAccResolver, *MemAccResolver, *DirAccResolver, *CacheDirAccResolver, Authentication, MQTTOpts, jwt.TagList, + *OCSPConfig, map[string]string, JSLimitOpts, StoreCipher, *OCSPResponseCacheConfig, WriteTimeoutPolicy: // explicitly skipped types + case *AuthCallout: + case JSTpmOpts: default: // this will fail during unit tests return fmt.Errorf("OnReload, sort or explicitly skip type: %s", @@ -807,12 +1206,20 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { oldConfig = reflect.ValueOf(s.getOpts()).Elem() newConfig = reflect.ValueOf(newOpts).Elem() diffOpts = []option{} + + // Need to keep track of whether JS is being disabled + // to prevent changing limits at runtime. + jsEnabled = s.JetStreamEnabled() + disableJS bool + jsMemLimitsChanged bool + jsFileLimitsChanged bool + jsStoreDirChanged bool ) for i := 0; i < oldConfig.NumField(); i++ { field := oldConfig.Type().Field(i) // field.PkgPath is empty for exported fields, and is not for unexported ones. // We skip the unexported fields. - if field.PkgPath != "" { + if field.PkgPath != _EMPTY_ { continue } var ( @@ -825,18 +1232,35 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { if err := imposeOrder(newValue); err != nil { return nil, err } - if changed := !reflect.DeepEqual(oldValue, newValue); !changed { - continue + + optName := strings.ToLower(field.Name) + // accounts and users (referencing accounts) will always differ as accounts + // contain internal state, say locks etc..., so we don't bother here. + // This also avoids races with atomic stats counters + if optName != "accounts" && optName != "users" { + if changed := !reflect.DeepEqual(oldValue, newValue); !changed { + // Check to make sure we are running JetStream if we think we should be. + if optName == "jetstream" && newValue.(bool) { + if !jsEnabled { + diffOpts = append(diffOpts, &jetStreamOption{newValue: true}) + } + } + continue + } } - switch strings.ToLower(field.Name) { + switch optName { case "traceverbose": diffOpts = append(diffOpts, &traceVerboseOption{newValue: newValue.(bool)}) + case "traceheaders": + diffOpts = append(diffOpts, &traceHeadersOption{newValue: newValue.(bool)}) case "trace": diffOpts = append(diffOpts, &traceOption{newValue: newValue.(bool)}) case "debug": diffOpts = append(diffOpts, &debugOption{newValue: newValue.(bool)}) case "logtime": diffOpts = append(diffOpts, &logtimeOption{newValue: newValue.(bool)}) + case "logtimeutc": + diffOpts = append(diffOpts, &logtimeUTCOption{newValue: newValue.(bool)}) case "logfile": diffOpts = append(diffOpts, &logfileOption{newValue: newValue.(string)}) case "syslog": @@ -847,10 +1271,18 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { diffOpts = append(diffOpts, &tlsOption{newValue: newValue.(*tls.Config)}) case "tlstimeout": diffOpts = append(diffOpts, &tlsTimeoutOption{newValue: newValue.(float64)}) + case "tlspinnedcerts": + diffOpts = append(diffOpts, &tlsPinnedCertOption{newValue: newValue.(PinnedCertSet)}) + case "tlshandshakefirst": + diffOpts = append(diffOpts, &tlsHandshakeFirst{newValue: newValue.(bool)}) + case "tlshandshakefirstfallback": + diffOpts = append(diffOpts, &tlsHandshakeFirstFallback{newValue: newValue.(time.Duration)}) case "username": diffOpts = append(diffOpts, &usernameOption{}) case "password": diffOpts = append(diffOpts, &passwordOption{}) + case "tags": + diffOpts = append(diffOpts, &tagsOption{}) case "authorization": diffOpts = append(diffOpts, &authorizationOption{}) case "authtimeout": @@ -865,8 +1297,28 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { if err := validateClusterOpts(oldClusterOpts, newClusterOpts); err != nil { return nil, err } - permsChanged := !reflect.DeepEqual(newClusterOpts.Permissions, oldClusterOpts.Permissions) - diffOpts = append(diffOpts, &clusterOption{newValue: newClusterOpts, permsChanged: permsChanged}) + co := &clusterOption{ + newValue: newClusterOpts, + permsChanged: !reflect.DeepEqual(newClusterOpts.Permissions, oldClusterOpts.Permissions), + compressChanged: !reflect.DeepEqual(oldClusterOpts.Compression, newClusterOpts.Compression), + } + co.diffPoolAndAccounts(&oldClusterOpts) + // If there are added accounts, first make sure that we can look them up. + // If we can't let's fail the reload. + for _, acc := range co.accsAdded { + if _, err := s.LookupAccount(acc); err != nil { + return nil, fmt.Errorf("unable to add account %q to the list of dedicated routes: %v", acc, err) + } + } + // If pool_size has been set to negative (but was not before), then let's + // add the system account to the list of removed accounts (we don't have + // to check if already there, duplicates are ok in that case). + if newClusterOpts.PoolSize < 0 && oldClusterOpts.PoolSize >= 0 { + if sys := s.SystemAccount(); sys != nil { + co.accsRemoved = append(co.accsRemoved, sys.GetName()) + } + } + diffOpts = append(diffOpts, co) case "routes": add, remove := diffRoutes(oldValue.([]*url.URL), newValue.([]*url.URL)) diffOpts = append(diffOpts, &routesOption{add: add, remove: remove}) @@ -916,6 +1368,15 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { tmpNew := newValue.(GatewayOpts) tmpOld.TLSConfig = nil tmpNew.TLSConfig = nil + tmpOld.tlsConfigOpts = nil + tmpNew.tlsConfigOpts = nil + + // Need to do the same for remote gateways' TLS configs. + // But we can't just set remotes' TLSConfig to nil otherwise this + // would lose the real TLS configuration. + tmpOld.Gateways = copyRemoteGWConfigsWithoutTLSConfig(tmpOld.Gateways) + tmpNew.Gateways = copyRemoteGWConfigsWithoutTLSConfig(tmpNew.Gateways) + // If there is really a change prevents reload. if !reflect.DeepEqual(tmpOld, tmpNew) { // See TODO(ik) note below about printing old/new values. @@ -928,18 +1389,64 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { tmpNew := newValue.(LeafNodeOpts) tmpOld.TLSConfig = nil tmpNew.TLSConfig = nil + tmpOld.tlsConfigOpts = nil + tmpNew.tlsConfigOpts = nil + // We will allow TLSHandshakeFirst to be config reloaded. First, + // we just want to detect if there was a change in the leafnodes{} + // block, and if not, we will check the remotes. + handshakeFirstChanged := tmpOld.TLSHandshakeFirst != tmpNew.TLSHandshakeFirst || + tmpOld.TLSHandshakeFirstFallback != tmpNew.TLSHandshakeFirstFallback + // If changed, set them (in the temporary variables) to false so that the + // rest of the comparison does not fail. + if handshakeFirstChanged { + tmpOld.TLSHandshakeFirst, tmpNew.TLSHandshakeFirst = false, false + tmpOld.TLSHandshakeFirstFallback, tmpNew.TLSHandshakeFirstFallback = 0, 0 + } else if len(tmpOld.Remotes) == len(tmpNew.Remotes) { + // Since we don't support changes in the remotes, we will do a + // simple pass to see if there was a change of this field. + for i := 0; i < len(tmpOld.Remotes); i++ { + if tmpOld.Remotes[i].TLSHandshakeFirst != tmpNew.Remotes[i].TLSHandshakeFirst { + handshakeFirstChanged = true + break + } + } + } + // We also support config reload for compression. Check if it changed before + // blanking them out for the deep-equal check at the end. + compressionChanged := !reflect.DeepEqual(tmpOld.Compression, tmpNew.Compression) + if compressionChanged { + tmpOld.Compression, tmpNew.Compression = CompressionOpts{}, CompressionOpts{} + } else if len(tmpOld.Remotes) == len(tmpNew.Remotes) { + // Same that for tls first check, do the remotes now. + for i := 0; i < len(tmpOld.Remotes); i++ { + if !reflect.DeepEqual(tmpOld.Remotes[i].Compression, tmpNew.Remotes[i].Compression) { + compressionChanged = true + break + } + } + } + + // Need to do the same for remote leafnodes' TLS configs. + // But we can't just set remotes' TLSConfig to nil otherwise this + // would lose the real TLS configuration. + tmpOld.Remotes = copyRemoteLNConfigForReloadCompare(tmpOld.Remotes) + tmpNew.Remotes = copyRemoteLNConfigForReloadCompare(tmpNew.Remotes) // Special check for leafnode remotes changes which are not supported right now. leafRemotesChanged := func(a, b LeafNodeOpts) bool { - if len(tmpOld.Remotes) != len(tmpNew.Remotes) { + if len(a.Remotes) != len(b.Remotes) { return true } // Check whether all remotes URLs are still the same. - for _, oldRemote := range tmpOld.Remotes { + for _, oldRemote := range a.Remotes { var found bool - for _, newRemote := range tmpNew.Remotes { + if oldRemote.LocalAccount == _EMPTY_ { + oldRemote.LocalAccount = globalAccountName + } + + for _, newRemote := range b.Remotes { // Bind to global account in case not defined. if newRemote.LocalAccount == _EMPTY_ { newRemote.LocalAccount = globalAccountName @@ -950,7 +1457,6 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { break } } - if !found { return true } @@ -966,30 +1472,117 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { tmpNew.Remotes = nil } + // Special check for auth users to detect changes. + // If anything is off will fall through and fail below. + // If we detect they are semantically the same we nil them out + // to pass the check below. + if tmpOld.Users != nil || tmpNew.Users != nil { + if len(tmpOld.Users) == len(tmpNew.Users) { + oua := make(map[string]*User, len(tmpOld.Users)) + nua := make(map[string]*User, len(tmpOld.Users)) + for _, u := range tmpOld.Users { + oua[u.Username] = u + } + for _, u := range tmpNew.Users { + nua[u.Username] = u + } + same := true + for uname, u := range oua { + // If we can not find new one with same name, drop through to fail. + nu, ok := nua[uname] + if !ok { + same = false + break + } + // If username or password or account different break. + if u.Username != nu.Username || u.Password != nu.Password || u.Account.GetName() != nu.Account.GetName() { + same = false + break + } + } + // We can nil out here. + if same { + tmpOld.Users, tmpNew.Users = nil, nil + } + } + } + // If there is really a change prevents reload. if !reflect.DeepEqual(tmpOld, tmpNew) { // See TODO(ik) note below about printing old/new values. return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", field.Name, oldValue, newValue) } - case "storedir": - return nil, fmt.Errorf("config reload not supported for jetstream storage directory") + + diffOpts = append(diffOpts, &leafNodeOption{ + tlsFirstChanged: handshakeFirstChanged, + compressionChanged: compressionChanged, + }) case "jetstream": new := newValue.(bool) old := oldValue.(bool) if new != old { diffOpts = append(diffOpts, &jetStreamOption{newValue: new}) } - case "jetstreammaxmemory": - return nil, fmt.Errorf("config reload not supported for jetstream max memory") - case "jetstreammaxstore": - return nil, fmt.Errorf("config reload not supported for jetstream max storage") + + // Mark whether JS will be disabled. + disableJS = !new + case "storedir": + new := newValue.(string) + old := oldValue.(string) + modified := new != old + + // Check whether JS is being disabled and/or storage dir attempted to change. + if jsEnabled && modified { + if new == _EMPTY_ { + // This means that either JS is being disabled or it is using an temp dir. + // Allow the change but error in case JS was not disabled. + jsStoreDirChanged = true + } else { + return nil, fmt.Errorf("config reload not supported for jetstream storage directory") + } + } + case "jetstreammaxmemory", "jetstreammaxstore": + old := oldValue.(int64) + new := newValue.(int64) + + // Check whether JS is being disabled and/or limits are being changed. + var ( + modified = new != old + fromUnset = old == -1 + fromSet = !fromUnset + toUnset = new == -1 + toSet = !toUnset + ) + if jsEnabled && modified { + // Cannot change limits from dynamic storage at runtime. + switch { + case fromSet && toUnset: + // Limits changed but it may mean that JS is being disabled, + // keep track of the change and error in case it is not. + switch optName { + case "jetstreammaxmemory": + jsMemLimitsChanged = true + case "jetstreammaxstore": + jsFileLimitsChanged = true + default: + return nil, fmt.Errorf("config reload not supported for jetstream max memory and store") + } + case fromUnset && toSet: + // Prevent changing from dynamic max memory / file at runtime. + return nil, fmt.Errorf("config reload not supported for jetstream dynamic max memory and store") + default: + return nil, fmt.Errorf("config reload not supported for jetstream max memory and store") + } + } + case "jetstreammetacompact", "jetstreammetacompactsize": + // Allowed at runtime but monitorCluster looks at s.opts directly, so no further work needed here. case "websocket": // Similar to gateways tmpOld := oldValue.(WebsocketOpts) tmpNew := newValue.(WebsocketOpts) - tmpOld.TLSConfig = nil - tmpNew.TLSConfig = nil + tmpOld.TLSConfig, tmpOld.tlsConfigOpts = nil, nil + tmpNew.TLSConfig, tmpNew.tlsConfigOpts = nil, nil // If there is really a change prevents reload. if !reflect.DeepEqual(tmpOld, tmpNew) { // See TODO(ik) note below about printing old/new values. @@ -999,17 +1592,31 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { case "mqtt": diffOpts = append(diffOpts, &mqttAckWaitReload{newValue: newValue.(MQTTOpts).AckWait}) diffOpts = append(diffOpts, &mqttMaxAckPendingReload{newValue: newValue.(MQTTOpts).MaxAckPending}) + diffOpts = append(diffOpts, &mqttStreamReplicasReload{newValue: newValue.(MQTTOpts).StreamReplicas}) + diffOpts = append(diffOpts, &mqttConsumerReplicasReload{newValue: newValue.(MQTTOpts).ConsumerReplicas}) + diffOpts = append(diffOpts, &mqttConsumerMemoryStorageReload{newValue: newValue.(MQTTOpts).ConsumerMemoryStorage}) + diffOpts = append(diffOpts, &mqttInactiveThresholdReload{newValue: newValue.(MQTTOpts).ConsumerInactiveThreshold}) + // Nil out/set to 0 the options that we allow to be reloaded so that // we only fail reload if some that we don't support are changed. tmpOld := oldValue.(MQTTOpts) tmpNew := newValue.(MQTTOpts) - tmpOld.TLSConfig, tmpOld.AckWait, tmpOld.MaxAckPending = nil, 0, 0 - tmpNew.TLSConfig, tmpNew.AckWait, tmpNew.MaxAckPending = nil, 0, 0 + tmpOld.TLSConfig, tmpOld.tlsConfigOpts, tmpOld.AckWait, tmpOld.MaxAckPending, tmpOld.StreamReplicas, tmpOld.ConsumerReplicas, tmpOld.ConsumerMemoryStorage = nil, nil, 0, 0, 0, 0, false + tmpOld.ConsumerInactiveThreshold = 0 + tmpNew.TLSConfig, tmpNew.tlsConfigOpts, tmpNew.AckWait, tmpNew.MaxAckPending, tmpNew.StreamReplicas, tmpNew.ConsumerReplicas, tmpNew.ConsumerMemoryStorage = nil, nil, 0, 0, 0, 0, false + tmpNew.ConsumerInactiveThreshold = 0 + if !reflect.DeepEqual(tmpOld, tmpNew) { // See TODO(ik) note below about printing old/new values. return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", field.Name, oldValue, newValue) } + tmpNew.AckWait = newValue.(MQTTOpts).AckWait + tmpNew.MaxAckPending = newValue.(MQTTOpts).MaxAckPending + tmpNew.StreamReplicas = newValue.(MQTTOpts).StreamReplicas + tmpNew.ConsumerReplicas = newValue.(MQTTOpts).ConsumerReplicas + tmpNew.ConsumerMemoryStorage = newValue.(MQTTOpts).ConsumerMemoryStorage + tmpNew.ConsumerInactiveThreshold = newValue.(MQTTOpts).ConsumerInactiveThreshold case "connecterrorreports": diffOpts = append(diffOpts, &connectErrorReports{newValue: newValue.(int)}) case "reconnecterrorreports": @@ -1030,6 +1637,41 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { continue } fallthrough + case "noauthuser": + if oldValue != _EMPTY_ && newValue == _EMPTY_ { + for _, user := range newOpts.Users { + if user.Username == oldValue { + return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", + field.Name, oldValue, newValue) + } + } + } else { + return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", + field.Name, oldValue, newValue) + } + case "defaultsentinel": + diffOpts = append(diffOpts, &defaultSentinelOption{newValue: newValue.(string)}) + case "systemaccount": + if oldValue != DEFAULT_SYSTEM_ACCOUNT || newValue != _EMPTY_ { + return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", + field.Name, oldValue, newValue) + } + case "ocspconfig": + diffOpts = append(diffOpts, &ocspOption{newValue: newValue.(*OCSPConfig)}) + case "ocspcacheconfig": + diffOpts = append(diffOpts, &ocspResponseCacheOption{newValue: newValue.(*OCSPResponseCacheConfig)}) + case "profblockrate": + new := newValue.(int) + old := oldValue.(int) + if new != old { + diffOpts = append(diffOpts, &profBlockRateReload{newValue: new}) + } + case "configdigest": + // skip changes in config digest, this is handled already while + // processing the config. + continue + case "nofastproducerstall": + diffOpts = append(diffOpts, &noFastProdStallReload{noStall: newValue.(bool)}) default: // TODO(ik): Implement String() on those options to have a nice print. // %v is difficult to figure what's what, %+v print private fields and @@ -1042,15 +1684,68 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) { } } + // If not disabling JS but limits have changed then it is an error. + if !disableJS { + if jsMemLimitsChanged || jsFileLimitsChanged { + return nil, fmt.Errorf("config reload not supported for jetstream max memory and max store") + } + if jsStoreDirChanged { + return nil, fmt.Errorf("config reload not supported for jetstream storage dir") + } + } + return diffOpts, nil } +func copyRemoteGWConfigsWithoutTLSConfig(current []*RemoteGatewayOpts) []*RemoteGatewayOpts { + l := len(current) + if l == 0 { + return nil + } + rgws := make([]*RemoteGatewayOpts, 0, l) + for _, rcfg := range current { + cp := *rcfg + cp.TLSConfig = nil + cp.tlsConfigOpts = nil + rgws = append(rgws, &cp) + } + return rgws +} + +func copyRemoteLNConfigForReloadCompare(current []*RemoteLeafOpts) []*RemoteLeafOpts { + l := len(current) + if l == 0 { + return nil + } + rlns := make([]*RemoteLeafOpts, 0, l) + for _, rcfg := range current { + cp := *rcfg + cp.TLSConfig = nil + cp.tlsConfigOpts = nil + cp.TLSHandshakeFirst = false + // This is set only when processing a CONNECT, so reset here so that we + // don't fail the DeepEqual comparison. + cp.TLS = false + // For now, remove DenyImports/Exports since those get modified at runtime + // to add JS APIs. + cp.DenyImports, cp.DenyExports = nil, nil + // Remove compression mode + cp.Compression = CompressionOpts{} + rlns = append(rlns, &cp) + } + return rlns +} + func (s *Server) applyOptions(ctx *reloadContext, opts []option) { var ( reloadLogging = false reloadAuth = false reloadClusterPerms = false reloadClientTrcLvl = false + reloadJetstream = false + jsEnabled = false + isStatszChange = false + co *clusterOption ) for _, opt := range opts { opt.Apply(s) @@ -1063,9 +1758,19 @@ func (s *Server) applyOptions(ctx *reloadContext, opts []option) { if opt.IsAuthChange() { reloadAuth = true } + if opt.IsClusterPoolSizeOrAccountsChange() { + co = opt.(*clusterOption) + } if opt.IsClusterPermsChange() { reloadClusterPerms = true } + if opt.IsJetStreamChange() { + reloadJetstream = true + jsEnabled = opt.(*jetStreamOption).newValue + } + if opt.IsStatszChange() { + isStatszChange = true + } } if reloadLogging { @@ -1080,8 +1785,60 @@ func (s *Server) applyOptions(ctx *reloadContext, opts []option) { if reloadClusterPerms { s.reloadClusterPermissions(ctx.oldClusterPerms) } + newOpts := s.getOpts() + // If we need to reload cluster pool/per-account, then co will be not nil + if co != nil { + s.reloadClusterPoolAndAccounts(co, newOpts) + } + if reloadJetstream { + if !jsEnabled { + s.DisableJetStream() + } else if !s.JetStreamEnabled() { + if err := s.restartJetStream(); err != nil { + s.Warnf("Can't start JetStream: %v", err) + } + } + // Make sure to reset the internal loop's version of JS. + s.resetInternalLoopInfo() + } + if isStatszChange { + s.sendStatszUpdate() + } - s.Noticef("Reloaded server configuration") + // For remote gateways and leafnodes, make sure that their TLS configuration + // is updated (since the config is "captured" early and changes would otherwise + // not be visible). + if s.gateway.enabled { + s.gateway.updateRemotesTLSConfig(newOpts) + } + if len(newOpts.LeafNode.Remotes) > 0 { + s.updateRemoteLeafNodesTLSConfig(newOpts) + } + + // Always restart OCSP monitoring on reload. + if err := s.reloadOCSP(); err != nil { + s.Warnf("Can't restart OCSP features: %v", err) + } + var cd string + if newOpts.configDigest != "" { + cd = fmt.Sprintf("(%s)", newOpts.configDigest) + } + s.Noticef("Reloaded server configuration %s", cd) +} + +// This will send a reset to the internal send loop. +func (s *Server) resetInternalLoopInfo() { + var resetCh chan struct{} + s.mu.Lock() + if s.sys != nil { + // can't hold the lock as go routine reading it may be waiting for lock as well + resetCh = s.sys.resetCh + } + s.mu.Unlock() + + if resetCh != nil { + resetCh <- struct{}{} + } } // Update all cached debug and trace settings for every client @@ -1096,7 +1853,7 @@ func (s *Server) reloadClientTraceLevel() { // Update their trace level when not holding server or gateway lock s.mu.Lock() - clientCnt := 1 + len(s.clients) + len(s.grTmpClients) + len(s.routes) + len(s.leafs) + clientCnt := 1 + len(s.clients) + len(s.grTmpClients) + s.numRoutes() + len(s.leafs) s.mu.Unlock() s.gateway.RLock() @@ -1110,12 +1867,15 @@ func (s *Server) reloadClientTraceLevel() { clients = append(clients, s.sys.client) } - cMaps := []map[uint64]*client{s.clients, s.grTmpClients, s.routes, s.leafs} + cMaps := []map[uint64]*client{s.clients, s.grTmpClients, s.leafs} for _, m := range cMaps { for _, c := range m { clients = append(clients, c) } } + s.forEachRoute(func(c *client) { + clients = append(clients, c) + }) s.mu.Unlock() s.gateway.RLock() @@ -1139,78 +1899,44 @@ func (s *Server) reloadClientTraceLevel() { func (s *Server) reloadAuthorization() { // This map will contain the names of accounts that have their streams // import configuration changed. - awcsti := make(map[string]struct{}) + var awcsti map[string]struct{} checkJetStream := false + opts := s.getOpts() s.mu.Lock() + deletedAccounts := make(map[string]*Account) + // This can not be changed for now so ok to check server's trustedKeys unlocked. // If plain configured accounts, process here. if s.trustedKeys == nil { - // We need to drain the old accounts here since we have something - // new configured. We do not want s.accounts to change since that would - // mean adding a lock to lookupAccount which is what we are trying to - // optimize for with the change from a map to a sync.Map. - oldAccounts := make(map[string]*Account) - s.accounts.Range(func(k, v interface{}) bool { - acc := v.(*Account) - acc.mu.RLock() - oldAccounts[acc.Name] = acc - acc.mu.RUnlock() - s.accounts.Delete(k) - return true - }) - s.gacc = nil - s.configureAccounts() - s.configureAuthorization() - s.mu.Unlock() - - s.accounts.Range(func(k, v interface{}) bool { - newAcc := v.(*Account) - if acc, ok := oldAccounts[newAcc.Name]; ok { - // If account exist in latest config, "transfer" the account's - // sublist and client map to the new account. - acc.mu.RLock() - newAcc.mu.Lock() - if len(acc.clients) > 0 { - newAcc.clients = make(map[*client]struct{}, len(acc.clients)) - for c := range acc.clients { - newAcc.clients[c] = struct{}{} - } - } - - newAcc.sl = acc.sl - newAcc.rm = acc.rm - newAcc.js = acc.js - - if len(acc.imports.rrMap) > 0 { - newAcc.imports.rrMap = make(map[string][]*serviceRespEntry) - for k, v := range acc.imports.rrMap { - newAcc.imports.rrMap[k] = v - } - } - newAcc.mu.Unlock() - acc.mu.RUnlock() - - // Check if current and new config of this account are same - // in term of stream imports. - if !acc.checkStreamImportsEqual(newAcc) { - awcsti[newAcc.Name] = struct{}{} - } - - // We need to remove all old service import subs. - acc.removeAllServiceImportSubs() - newAcc.addAllServiceImportSubs() + // Make a map of the configured account names so we figure out the accounts + // that should be removed later on. + configAccs := make(map[string]struct{}, len(opts.Accounts)) + for _, acc := range opts.Accounts { + configAccs[acc.GetName()] = struct{}{} + } + // Now range over existing accounts and keep track of the ones deleted + // so some cleanup can be made after releasing the server lock. + s.accounts.Range(func(k, v any) bool { + an, acc := k.(string), v.(*Account) + // Exclude default and system account from this test since those + // may not actually be in opts.Accounts. + if an == DEFAULT_GLOBAL_ACCOUNT || an == DEFAULT_SYSTEM_ACCOUNT { + return true + } + // Check check if existing account is still in opts.Accounts. + if _, ok := configAccs[an]; !ok { + deletedAccounts[an] = acc + s.accounts.Delete(k) } return true }) - s.mu.Lock() - // Check if we had a default system account. - if s.sys != nil && s.sys.account != nil && !s.opts.NoSystemAccount { - s.accounts.Store(s.sys.account.Name, s.sys.account) - } + // This will update existing and add new ones. + awcsti, _ = s.configureAccounts(true) + s.configureAuthorization() // Double check any JetStream configs. - checkJetStream = true - } else if s.opts.AccountResolver != nil { + checkJetStream = s.getJetStream() != nil + } else if opts.AccountResolver != nil { s.configureResolver() if _, ok := s.accResolver.(*MemAccResolver); ok { // Check preloads so we can issue warnings etc if needed. @@ -1218,7 +1944,7 @@ func (s *Server) reloadAuthorization() { // With a memory resolver we want to do something similar to configured accounts. // We will walk the accounts and delete them if they are no longer present via fetch. // If they are present we will force a claim update to process changes. - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) // Skip global account. if acc == s.gacc { @@ -1229,8 +1955,7 @@ func (s *Server) reloadAuthorization() { s.mu.Unlock() accClaims, claimJWT, _ := s.fetchAccountClaims(accName) if accClaims != nil { - err := s.updateAccountWithClaimJWT(acc, claimJWT) - if err != nil && err != ErrAccountResolverSameClaims { + if err := s.updateAccountWithClaimJWT(acc, claimJWT); err != nil { s.Noticef("Reloaded: deleting account [bad claims]: %q", accName) s.accounts.Delete(k) } @@ -1245,8 +1970,6 @@ func (s *Server) reloadAuthorization() { } } - // Gather clients that changed accounts. We will close them and they - // will reconnect, doing the right thing. var ( cclientsa [64]*client cclients = cclientsa[:0] @@ -1255,6 +1978,9 @@ func (s *Server) reloadAuthorization() { routesa [64]*client routes = routesa[:0] ) + + // Gather clients that changed accounts. We will close them and they + // will reconnect, doing the right thing. for _, client := range s.clients { if s.clientHasMovedToDifferentAccount(client) { cclients = append(cclients, client) @@ -1262,18 +1988,48 @@ func (s *Server) reloadAuthorization() { clients = append(clients, client) } } - for _, route := range s.routes { + s.forEachRoute(func(route *client) { routes = append(routes, route) - } + }) + // Check here for any system/internal clients which will not be in the servers map of normal clients. + if s.sys != nil && s.sys.account != nil && !opts.NoSystemAccount { + s.accounts.Store(s.sys.account.Name, s.sys.account) + } + + s.accounts.Range(func(k, v any) bool { + acc := v.(*Account) + acc.mu.RLock() + // Check for sysclients accounting, ignore the system account. + if acc.sysclients > 0 && (s.sys == nil || s.sys.account != acc) { + for c := range acc.clients { + if c.kind != CLIENT && c.kind != LEAF { + clients = append(clients, c) + } + } + } + acc.mu.RUnlock() + return true + }) + var resetCh chan struct{} if s.sys != nil { // can't hold the lock as go routine reading it may be waiting for lock as well resetCh = s.sys.resetCh } - // Check that publish retained messages sources are still allowed to publish. - s.mqttCheckPubRetainedPerms() s.mu.Unlock() + // Clear some timers and remove service import subs for deleted accounts. + for _, acc := range deletedAccounts { + acc.mu.Lock() + clearTimer(&acc.etmr) + clearTimer(&acc.ctmr) + for _, se := range acc.exports.services { + se.clearResponseThresholdTimer() + } + acc.mu.Unlock() + acc.removeAllServiceImportSubs() + } + if resetCh != nil { resetCh <- struct{}{} } @@ -1283,16 +2039,17 @@ func (s *Server) reloadAuthorization() { client.closeConnection(ClientClosed) } - for _, client := range clients { + for _, c := range clients { // Disconnect any unauthorized clients. - if !s.isClientAuthorized(client) { - client.authViolation() + // Ignore internal clients. + if (c.kind == CLIENT || c.kind == LEAF) && !s.isClientAuthorized(c) { + c.authViolation() continue } // Check to make sure account is correct. - client.swapAccountAfterReload() + c.swapAccountAfterReload() // Remove any unauthorized subscriptions and check for account imports. - client.processSubsOnConfigReload(awcsti) + c.processSubsOnConfigReload(awcsti) } for _, route := range routes { @@ -1306,23 +2063,20 @@ func (s *Server) reloadAuthorization() { } } + if res := s.AccountResolver(); res != nil { + res.Reload() + } + // We will double check all JetStream configs on a reload. if checkJetStream { - var err error - s.getJetStream().clearResources() - if s.globalAccountOnly() { - err = s.GlobalAccount().EnableJetStream(nil) - } else { - err = s.configAllJetStreamAccounts() - } - if err != nil { + if err := s.enableJetStreamAccounts(); err != nil { s.Errorf(err.Error()) } } - if res := s.AccountResolver(); res != nil { - res.Reload() - } + // Check that publish retained messages sources are still allowed to publish. + // Do this after dealing with JetStream. + s.mqttCheckPubRetainedPerms() } // Returns true if given client current account has changed (or user @@ -1334,11 +2088,13 @@ func (s *Server) clientHasMovedToDifferentAccount(c *client) bool { nu *NkeyUser u *User ) - if c.opts.Nkey != "" { + c.mu.Lock() + defer c.mu.Unlock() + if c.opts.Nkey != _EMPTY_ { if s.nkeys != nil { nu = s.nkeys[c.opts.Nkey] } - } else if c.opts.Username != "" { + } else if c.opts.Username != _EMPTY_ { if s.users != nil { u = s.users[c.opts.Username] } @@ -1346,12 +2102,10 @@ func (s *Server) clientHasMovedToDifferentAccount(c *client) bool { return false } // Get the current account name - c.mu.Lock() var curAccName string if c.acc != nil { curAccName = c.acc.Name } - c.mu.Unlock() if nu != nil && nu.Account != nil { return curAccName != nu.Account.Name } else if u != nil && u.Account != nil { @@ -1368,22 +2122,14 @@ func (s *Server) clientHasMovedToDifferentAccount(c *client) bool { // import subjects. func (s *Server) reloadClusterPermissions(oldPerms *RoutePermissions) { s.mu.Lock() - var ( - infoJSON []byte - newPerms = s.opts.Cluster.Permissions - routes = make(map[uint64]*client, len(s.routes)) - withNewProto int - ) + newPerms := s.getOpts().Cluster.Permissions + routes := make(map[uint64]*client, s.numRoutes()) // Get all connected routes - for i, route := range s.routes { - // Count the number of routes that can understand receiving INFO updates. + s.forEachRoute(func(route *client) { route.mu.Lock() - if route.opts.Protocol >= RouteProtoInfo { - withNewProto++ - } + routes[route.cid] = route route.mu.Unlock() - routes[i] = route - } + }) // If new permissions is nil, then clear routeInfo import/export if newPerms == nil { s.routeInfo.Import = nil @@ -1392,23 +2138,23 @@ func (s *Server) reloadClusterPermissions(oldPerms *RoutePermissions) { s.routeInfo.Import = newPerms.Import s.routeInfo.Export = newPerms.Export } - // Regenerate route INFO - s.generateRouteInfoJSON() - infoJSON = s.routeInfoJSON - gacc := s.gacc + infoJSON := generateInfoJSON(&s.routeInfo) s.mu.Unlock() - // If there were no route, we are done - if len(routes) == 0 { - return - } - - // If only older servers, simply close all routes and they will do the right - // thing on reconnect. - if withNewProto == 0 { - for _, route := range routes { + // Close connections for routes that don't understand async INFO. + for _, route := range routes { + route.mu.Lock() + close := route.opts.Protocol < RouteProtoInfo + cid := route.cid + route.mu.Unlock() + if close { route.closeConnection(RouteRemoved) + delete(routes, cid) } + } + + // If there are no route left, we are done + if len(routes) == 0 { return } @@ -1420,66 +2166,333 @@ func (s *Server) reloadClusterPermissions(oldPerms *RoutePermissions) { var ( _localSubs [4096]*subscription - localSubs = _localSubs[:0] - subsNeedSUB []*subscription - subsNeedUNSUB []*subscription + subsNeedSUB = map[*client][]*subscription{} + subsNeedUNSUB = map[*client][]*subscription{} deleteRoutedSubs []*subscription ) - // FIXME(dlc) - Change for accounts. - gacc.sl.localSubs(&localSubs) - - // Go through all local subscriptions - for _, sub := range localSubs { - // Get all subs that can now be imported - subj := string(sub.subject) - couldImportThen := oldPermsTester.canImport(subj) - canImportNow := newPermsTester.canImport(subj) - if canImportNow { - // If we could not before, then will need to send a SUB protocol. - if !couldImportThen { - subsNeedSUB = append(subsNeedSUB, sub) + + getRouteForAccount := func(accName string, poolIdx int) *client { + for _, r := range routes { + r.mu.Lock() + ok := (poolIdx >= 0 && poolIdx == r.route.poolIdx) || (string(r.route.accName) == accName) || r.route.noPool + r.mu.Unlock() + if ok { + return r } - } else if couldImportThen { - // We were previously able to import this sub, but now - // we can't so we need to send an UNSUB protocol - subsNeedUNSUB = append(subsNeedUNSUB, sub) } + return nil } + // First set the new permissions on all routes. for _, route := range routes { route.mu.Lock() - // If route is to older server, simply close connection. - if route.opts.Protocol < RouteProtoInfo { - route.mu.Unlock() - route.closeConnection(RouteRemoved) - continue - } route.setRoutePermissions(newPerms) - for _, sub := range route.subs { + route.mu.Unlock() + } + + // Then, go over all accounts and gather local subscriptions that need to be + // sent over as SUB or removed as UNSUB, and routed subscriptions that need + // to be dropped due to export permissions. + s.accounts.Range(func(_, v any) bool { + acc := v.(*Account) + acc.mu.RLock() + accName, sl, poolIdx := acc.Name, acc.sl, acc.routePoolIdx + acc.mu.RUnlock() + // Get the route handling this account. If no route or sublist, bail out. + route := getRouteForAccount(accName, poolIdx) + if route == nil || sl == nil { + return true + } + localSubs := _localSubs[:0] + sl.localSubs(&localSubs, false) + + // Go through all local subscriptions + for _, sub := range localSubs { + // Get all subs that can now be imported + subj := string(sub.subject) + couldImportThen := oldPermsTester.canImport(subj) + canImportNow := newPermsTester.canImport(subj) + if canImportNow { + // If we could not before, then will need to send a SUB protocol. + if !couldImportThen { + subsNeedSUB[route] = append(subsNeedSUB[route], sub) + } + } else if couldImportThen { + // We were previously able to import this sub, but now + // we can't so we need to send an UNSUB protocol + subsNeedUNSUB[route] = append(subsNeedUNSUB[route], sub) + } + } + deleteRoutedSubs = deleteRoutedSubs[:0] + route.mu.Lock() + pa, _, hasSubType := route.getRoutedSubKeyInfo() + for key, sub := range route.subs { + // If this is not a pinned-account route, we need to get the + // account name from the key to see if we collect this sub. + if !pa { + if an := getAccNameFromRoutedSubKey(sub, key, hasSubType); an != accName { + continue + } + } // If we can't export, we need to drop the subscriptions that // we have on behalf of this route. + // Need to make a string cast here since canExport call sl.Match() subj := string(sub.subject) if !route.canExport(subj) { - delete(route.subs, string(sub.sid)) + // We can use bytesToString() here. + delete(route.subs, bytesToString(sub.sid)) deleteRoutedSubs = append(deleteRoutedSubs, sub) } } - // Send an update INFO, which will allow remote server to show - // our current route config in monitoring and resend subscriptions - // that we now possibly allow with a change of Export permissions. + route.mu.Unlock() + // Remove as a batch all the subs that we have removed from each route. + sl.RemoveBatch(deleteRoutedSubs) + return true + }) + + // Send an update INFO, which will allow remote server to show + // our current route config in monitoring and resend subscriptions + // that we now possibly allow with a change of Export permissions. + for _, route := range routes { + route.mu.Lock() route.enqueueProto(infoJSON) // Now send SUB and UNSUB protocols as needed. - route.sendRouteSubProtos(subsNeedSUB, false, nil) - route.sendRouteUnSubProtos(subsNeedUNSUB, false, nil) + if subs, ok := subsNeedSUB[route]; ok && len(subs) > 0 { + route.sendRouteSubProtos(subs, false, nil) + } + if unsubs, ok := subsNeedUNSUB[route]; ok && len(unsubs) > 0 { + route.sendRouteUnSubProtos(unsubs, false, nil) + } route.mu.Unlock() } - // Remove as a batch all the subs that we have removed from each route. - // FIXME(dlc) - Change for accounts. - gacc.sl.RemoveBatch(deleteRoutedSubs) } -// validateClusterOpts ensures the new ClusterOpts does not change host or -// port, which do not support reload. +func (s *Server) reloadClusterPoolAndAccounts(co *clusterOption, opts *Options) { + s.mu.Lock() + // Prevent adding new routes until we are ready to do so. + s.routesReject = true + var ch chan struct{} + // For accounts that have been added to the list of dedicated routes, + // send a protocol to their current assigned routes to allow the + // other side to prepare for the changes. + if len(co.accsAdded) > 0 { + protosSent := 0 + s.accAddedReqID = nuid.Next() + for _, an := range co.accsAdded { + if s.accRoutes == nil { + s.accRoutes = make(map[string]map[string]*client) + } + // In case a config reload was first done on another server, + // we may have already switched this account to a dedicated route. + // But we still want to send the protocol over the routes that + // would have otherwise handled it. + if _, ok := s.accRoutes[an]; !ok { + s.accRoutes[an] = make(map[string]*client) + } + if a, ok := s.accounts.Load(an); ok { + acc := a.(*Account) + acc.mu.Lock() + sl := acc.sl + // Get the current route pool index before calling setRouteInfo. + rpi := acc.routePoolIdx + // Switch to per-account route if not already done. + if rpi >= 0 { + s.setRouteInfo(acc) + } else { + // If it was transitioning, make sure we set it to the state + // that indicates that it has a dedicated route + if rpi == accTransitioningToDedicatedRoute { + acc.routePoolIdx = accDedicatedRoute + } + // Otherwise get the route pool index it would have been before + // the move so we can send the protocol to those routes. + rpi = computeRoutePoolIdx(s.routesPoolSize, acc.Name) + } + acc.mu.Unlock() + // Generate the INFO protocol to send indicating that this account + // is being moved to a dedicated route. + ri := Info{ + RoutePoolSize: s.routesPoolSize, + RouteAccount: an, + RouteAccReqID: s.accAddedReqID, + } + proto := generateInfoJSON(&ri) + // Since v2.11.0, we support remotes with a different pool size + // (for rolling upgrades), so we need to use the remote route + // pool index (based on the remote configured pool size) since + // the remote subscriptions will be attached to the route at + // that index, not at our account's route pool index. However, + // we are going to send the protocol through the route that + // handles this account from our pool size perspective (that + // would be the route at index `rpi`). + removeSubsAndSendProto := func(r *client, doSubs, doProto bool) { + r.mu.Lock() + defer r.mu.Unlock() + // Exclude routes to servers that don't support pooling. + if r.route.noPool { + return + } + if doSubs { + if subs := r.removeRemoteSubsForAcc(an); len(subs) > 0 { + sl.RemoveBatch(subs) + } + } + if doProto { + r.enqueueProto(proto) + protosSent++ + } + } + for remote, conns := range s.routes { + r := conns[rpi] + // The route connection at this index is currently not up, + // so we won't be able to send the protocol, so move to the + // next remote. + if r == nil { + continue + } + doSubs := true + // Check the remote's route pool size and if different than + // ours, remove the subs on that other route. + remotePoolSize, ok := s.remoteRoutePoolSize[remote] + if ok && remotePoolSize != s.routesPoolSize { + // This is the remote's route pool index for this account + rrpi := computeRoutePoolIdx(remotePoolSize, an) + if rr := conns[rrpi]; rr != nil { + removeSubsAndSendProto(rr, true, false) + // Indicate that we have already remove the subs. + doSubs = false + } + } + // Now send the protocol from the route that handles the + // account from this server perspective. + removeSubsAndSendProto(r, doSubs, true) + } + } + } + if protosSent > 0 { + s.accAddedCh = make(chan struct{}, protosSent) + ch = s.accAddedCh + } + } + // Collect routes that need to be closed. + routes := make(map[*client]struct{}) + // Collect the per-account routes that need to be closed. + if len(co.accsRemoved) > 0 { + for _, an := range co.accsRemoved { + if remotes, ok := s.accRoutes[an]; ok && remotes != nil { + for _, r := range remotes { + if r != nil { + r.setNoReconnect() + routes[r] = struct{}{} + } + } + } + } + } + // If the pool size has changed, we need to close all pooled routes. + if co.poolSizeChanged { + s.forEachNonPerAccountRoute(func(r *client) { + routes[r] = struct{}{} + }) + } + // If there are routes to close, we need to release the server lock. + // Same if we need to wait on responses from the remotes when + // processing new per-account routes. + if len(routes) > 0 || len(ch) > 0 { + s.mu.Unlock() + + for done := false; !done && len(ch) > 0; { + select { + case <-ch: + case <-time.After(2 * time.Second): + s.Warnf("Timed out waiting for confirmation from all routes regarding per-account routes changes") + done = true + } + } + + for r := range routes { + r.closeConnection(RouteRemoved) + } + + s.mu.Lock() + } + // Clear the accAddedCh/ReqID fields in case they were set. + s.accAddedReqID, s.accAddedCh = _EMPTY_, nil + // Now that per-account routes that needed to be closed are closed, + // remove them from s.accRoutes. Doing so before would prevent + // removeRoute() to do proper cleanup because the route would not + // be found in s.accRoutes. + for _, an := range co.accsRemoved { + delete(s.accRoutes, an) + // Do not lookup and call setRouteInfo() on the accounts here. + // We need first to set the new s.routesPoolSize value and + // anyway, there is no need to do here if the pool size has + // changed (since it will be called for all accounts). + } + // We have already added the accounts to s.accRoutes that needed to + // be added. + + // We should always have at least the system account with a dedicated route, + // but in case we have a configuration that disables pooling and without + // a system account, possibly set the accRoutes to nil. + if len(opts.Cluster.PinnedAccounts) == 0 { + s.accRoutes = nil + } + // Now deal with pool size updates. + if ps := opts.Cluster.PoolSize; ps > 0 { + s.routesPoolSize = ps + s.routeInfo.RoutePoolSize = ps + } else { + s.routesPoolSize = 1 + s.routeInfo.RoutePoolSize = 0 + } + // If the pool size has changed, we need to recompute all accounts' route + // pool index. Note that the added/removed accounts will be reset there + // too, but that's ok (we could use a map to exclude them, but not worth it). + if co.poolSizeChanged { + s.accounts.Range(func(_, v any) bool { + acc := v.(*Account) + acc.mu.Lock() + s.setRouteInfo(acc) + acc.mu.Unlock() + return true + }) + } else if len(co.accsRemoved) > 0 { + // For accounts that no longer have a dedicated route, we need to send + // the subsriptions on the existing pooled routes for those accounts. + for _, an := range co.accsRemoved { + if a, ok := s.accounts.Load(an); ok { + acc := a.(*Account) + acc.mu.Lock() + // First call this which will assign a new route pool index. + s.setRouteInfo(acc) + // Get the value so we can send the subscriptions interest + // on all routes with this pool index. + rpi := acc.routePoolIdx + acc.mu.Unlock() + s.forEachRouteIdx(rpi, func(r *client) bool { + // We have the guarantee that if the route exists, it + // is not a new one that would have been created when + // we released the server lock if some routes needed + // to be closed, because we have set s.routesReject + // to `true` at the top of this function. + s.sendSubsToRoute(r, rpi, an) + return true + }) + } + } + } + // Allow routes to be accepted now. + s.routesReject = false + // If there is a pool size change or added accounts, solicit routes now. + if co.poolSizeChanged || len(co.accsAdded) > 0 { + s.solicitRoutes(opts.Routes, co.accsAdded) + } + s.mu.Unlock() +} + +// validateClusterOpts ensures the new ClusterOpts does not change some of the +// fields that do not support reload. func validateClusterOpts(old, new ClusterOpts) error { if old.Host != new.Host { return fmt.Errorf("config reload not supported for cluster host: old=%s, new=%s", diff --git a/vendor/github.com/nats-io/nats-server/v2/server/ring.go b/vendor/github.com/nats-io/nats-server/v2/server/ring.go index 2673a17..2cfa05f 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/ring.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/ring.go @@ -1,4 +1,4 @@ -// Copyright 2018 The NATS Authors +// Copyright 2018-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/nats-io/nats-server/v2/server/route.go b/vendor/github.com/nats-io/nats-server/v2/server/route.go index 9ad5242..871506e 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/route.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/route.go @@ -1,4 +1,4 @@ -// Copyright 2013-2020 The NATS Authors +// Copyright 2013-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18,14 +18,18 @@ import ( "crypto/tls" "encoding/json" "fmt" + "hash/fnv" "math/rand" "net" "net/url" + "reflect" "runtime" "strconv" "strings" "sync/atomic" "time" + + "github.com/klauspost/compress/s2" ) // RouteType designates the router type @@ -39,17 +43,6 @@ const ( Explicit ) -const ( - // RouteProtoZero is the original Route protocol from 2009. - // http://nats.io/documentation/internals/nats-protocol/ - RouteProtoZero = iota - // RouteProtoInfo signals a route can receive more then the original INFO block. - // This can be used to update remote cluster permissions, etc... - RouteProtoInfo - // RouteProtoV2 is the new route/cluster protocol that provides account support. - RouteProtoV2 -) - // Include the space for the proto var ( aSubBytes = []byte{'A', '+', ' '} @@ -60,29 +53,60 @@ var ( lUnsubBytes = []byte{'L', 'S', '-', ' '} ) -// Used by tests -func setRouteProtoForTest(wantedProto int) int { - return (wantedProto + 1) * -1 -} - type route struct { remoteID string remoteName string didSolicit bool retry bool lnoc bool + lnocu bool routeType RouteType url *url.URL authRequired bool tlsRequired bool + jetstream bool connectURLs []string wsConnURLs []string - replySubs map[*subscription]*time.Timer gatewayURL string leafnodeURL string hash string + idHash string + // Location of the route in the slice: s.routes[remoteID][]*client. + // Initialized to -1 on creation, as to indicate that it is not + // added to the list. + poolIdx int + // If this is set, it means that the route is dedicated for this + // account and the account name will not be included in protocols. + accName []byte + // This is set to true if this is a route connection to an old + // server or a server that has pooling completely disabled. + noPool bool + // Selected compression mode, which may be different from the + // server configured mode. + compression string + // Transient value used to set the Info.GossipMode when initiating + // an implicit route and sending to the remote. + gossipMode byte + // This will be set in case of pooling so that a route can trigger + // the creation of the next after receiving the first PONG, ensuring + // that authentication did not fail. + startNewRoute *routeInfo +} + +// This contains the information required to create a new route. +type routeInfo struct { + url *url.URL + rtype RouteType + gossipMode byte } +// Do not change the values/order since they are exchanged between servers. +const ( + gossipDefault = byte(iota) + gossipDisabled + gossipOverride +) + type connectInfo struct { Echo bool `json:"echo"` Verbose bool `json:"verbose"` @@ -95,6 +119,7 @@ type connectInfo struct { Cluster string `json:"cluster"` Dynamic bool `json:"cluster_dynamic,omitempty"` LNOC bool `json:"lnoc,omitempty"` + LNOCU bool `json:"lnocu,omitempty"` // Support for LS- with origin cluster name Gateway string `json:"gateway,omitempty"` } @@ -105,16 +130,21 @@ const ( ) const ( - // Used to decide if the sending of the route SUBs list should be - // done in place or in separate go routine. - sendRouteSubsInGoRoutineThreshold = 1024 * 1024 // 1MB - // Warning when user configures cluster TLS insecure clusterTLSInsecureWarning = "TLS certificate chain and hostname of solicited routes will not be verified. DO NOT USE IN PRODUCTION!" + + // The default ping interval is set to 2 minutes, which is fine for client + // connections, etc.. but for route compression, the CompressionS2Auto + // mode uses RTT measurements (ping/pong) to decide which compression level + // to use, we want the interval to not be that high. + defaultRouteMaxPingInterval = 30 * time.Second ) // Can be changed for tests -var routeConnectDelay = DEFAULT_ROUTE_CONNECT +var ( + routeConnectDelay = DEFAULT_ROUTE_CONNECT + routeMaxPingInterval = defaultRouteMaxPingInterval +) // removeReplySub is called when we trip the max on remoteReply subs. func (c *client) removeReplySub(sub *subscription) { @@ -124,41 +154,25 @@ func (c *client) removeReplySub(sub *subscription) { // Lookup the account based on sub.sid. if i := bytes.Index(sub.sid, []byte(" ")); i > 0 { // First part of SID for route is account name. - if v, ok := c.srv.accounts.Load(string(sub.sid[:i])); ok { + if v, ok := c.srv.accounts.Load(bytesToString(sub.sid[:i])); ok { (v.(*Account)).sl.Remove(sub) } c.mu.Lock() - c.removeReplySubTimeout(sub) - delete(c.subs, string(sub.sid)) + delete(c.subs, bytesToString(sub.sid)) c.mu.Unlock() } } -// removeReplySubTimeout will remove a timer if it exists. -// Lock should be held upon entering. -func (c *client) removeReplySubTimeout(sub *subscription) { - // Remove any reply sub timer if it exists. - if c.route == nil || c.route.replySubs == nil { - return - } - if t, ok := c.route.replySubs[sub]; ok { - t.Stop() - delete(c.route.replySubs, sub) - } -} - func (c *client) processAccountSub(arg []byte) error { - accName := string(arg) if c.kind == GATEWAY { - return c.processGatewayAccountSub(accName) + return c.processGatewayAccountSub(string(arg)) } return nil } func (c *client) processAccountUnsub(arg []byte) { - accName := string(arg) if c.kind == GATEWAY { - c.processGatewayAccountUnsub(accName) + c.processGatewayAccountUnsub(string(arg)) } } @@ -186,6 +200,13 @@ func (c *client) processRoutedOriginClusterMsgArgs(arg []byte) error { args = append(args, arg[start:]) } + var an []byte + if c.kind == ROUTER { + if an = c.route.accName; len(an) > 0 && len(args) > 2 { + args = append(args[:2], args[1:]...) + args[1] = an + } + } c.pa.arg = arg switch len(args) { case 0, 1, 2, 3, 4: @@ -247,8 +268,11 @@ func (c *client) processRoutedOriginClusterMsgArgs(arg []byte) error { c.pa.origin = args[0] c.pa.account = args[1] c.pa.subject = args[2] - c.pa.pacache = arg[len(args[0])+1 : len(args[0])+len(args[1])+len(args[2])+2] - + if len(an) > 0 { + c.pa.pacache = c.pa.subject + } else { + c.pa.pacache = arg[len(args[0])+1 : len(args[0])+len(args[1])+len(args[2])+2] + } return nil } @@ -257,6 +281,12 @@ func (c *client) processRoutedHeaderMsgArgs(arg []byte) error { // Unroll splitArgs to avoid runtime/heap issues a := [MAX_HMSG_ARGS][]byte{} args := a[:0] + var an []byte + if c.kind == ROUTER { + if an = c.route.accName; len(an) > 0 { + args = append(args, an) + } + } start := -1 for i, b := range arg { switch b { @@ -335,7 +365,11 @@ func (c *client) processRoutedHeaderMsgArgs(arg []byte) error { // Common ones processed after check for arg length c.pa.account = args[0] c.pa.subject = args[1] - c.pa.pacache = arg[:len(args[0])+len(args[1])+1] + if len(an) > 0 { + c.pa.pacache = c.pa.subject + } else { + c.pa.pacache = arg[:len(args[0])+len(args[1])+1] + } return nil } @@ -344,6 +378,12 @@ func (c *client) processRoutedMsgArgs(arg []byte) error { // Unroll splitArgs to avoid runtime/heap issues a := [MAX_RMSG_ARGS][]byte{} args := a[:0] + var an []byte + if c.kind == ROUTER { + if an = c.route.accName; len(an) > 0 { + args = append(args, an) + } + } start := -1 for i, b := range arg { switch b { @@ -407,16 +447,21 @@ func (c *client) processRoutedMsgArgs(arg []byte) error { // Common ones processed after check for arg length c.pa.account = args[0] c.pa.subject = args[1] - c.pa.pacache = arg[:len(args[0])+len(args[1])+1] + if len(an) > 0 { + c.pa.pacache = c.pa.subject + } else { + c.pa.pacache = arg[:len(args[0])+len(args[1])+1] + } return nil } -// processInboundRouteMsg is called to process an inbound msg from a route. +// processInboundRoutedMsg is called to process an inbound msg from a route. func (c *client) processInboundRoutedMsg(msg []byte) { // Update statistics c.in.msgs++ // The msg includes the CR_LF, so pull back out for accounting. - c.in.bytes += int32(len(msg) - LEN_CR_LF) + size := len(msg) - LEN_CR_LF + c.in.bytes += int32(size) if c.opts.Verbose { c.sendOK() @@ -439,6 +484,13 @@ func (c *client) processInboundRoutedMsg(msg []byte) { return } + acc.stats.Lock() + acc.stats.inMsgs++ + acc.stats.inBytes += int64(size) + acc.stats.rt.inMsgs++ + acc.stats.rt.inBytes += int64(size) + acc.stats.Unlock() + // Check for no interest, short circuit if so. // This is the fanout scale. if len(r.psubs)+len(r.qsubs) > 0 { @@ -477,17 +529,23 @@ func (c *client) sendRouteConnect(clusterName string, tlsRequired bool) error { return nil } +// Returns a route pool index for this account based on the given pool size. +// If `poolSize` is smaller or equal to 1, the returned value will always +// be 0, regardless of the account name. If not, the returned value will +// be in the range [0..poolSize-1]. The value for a given account name +// is constant and same on all servers (given the same `poolSize` value). +func computeRoutePoolIdx(poolSize int, an string) int { + if poolSize <= 1 { + return 0 + } + h := fnv.New32a() + h.Write([]byte(an)) + sum32 := h.Sum32() + return int((sum32 % uint32(poolSize))) +} + // Process the info message if we are a route. func (c *client) processRouteInfo(info *Info) { - // We may need to update route permissions and will need the account - // sublist. Since getting the account requires server lock, do the - // lookup now. - - // FIXME(dlc) - Add account scoping. - gacc := c.srv.globalAccount() - gacc.mu.RLock() - sl := gacc.sl - gacc.mu.RUnlock() supportsHeaders := c.srv.supportsHeaders() clusterName := c.srv.ClusterName() @@ -519,7 +577,7 @@ func (c *client) processRouteInfo(info *Info) { // Use other if remote is non dynamic or their name is "bigger" if s.isClusterNameDynamic() && (!info.Dynamic || (strings.Compare(clusterName, info.Cluster) < 0)) { s.setClusterName(info.Cluster) - s.removeAllRoutesExcept(c) + s.removeAllRoutesExcept(info.ID) c.mu.Lock() } else { c.closeConnection(ClusterNameConflict) @@ -527,12 +585,99 @@ func (c *client) processRouteInfo(info *Info) { } } + opts := s.getOpts() + + didSolicit := c.route.didSolicit + // If this is an async INFO from an existing route... if c.flags.isSet(infoReceived) { remoteID := c.route.remoteID + // Check if this is an INFO about adding a per-account route during + // a configuration reload. + if info.RouteAccReqID != _EMPTY_ { + c.mu.Unlock() + + // If there is an account name, then the remote server is telling + // us that this account will now have its dedicated route. + if an := info.RouteAccount; an != _EMPTY_ { + acc, err := s.LookupAccount(an) + if err != nil { + s.Errorf("Error looking up account %q: %v", an, err) + return + } + s.mu.Lock() + // If running without system account and adding a dedicated + // route for an account for the first time, it could be that + // the map is nil. If so, create it. + if s.accRoutes == nil { + s.accRoutes = make(map[string]map[string]*client) + } + if _, ok := s.accRoutes[an]; !ok { + s.accRoutes[an] = make(map[string]*client) + } + acc.mu.Lock() + sl := acc.sl + rpi := acc.routePoolIdx + // Make sure that the account was not already switched. + if rpi >= 0 { + s.setRouteInfo(acc) + // Change the route pool index to indicate that this + // account is actually transitioning. This will be used + // to suppress possible remote subscription interest coming + // in while the transition is happening. + acc.routePoolIdx = accTransitioningToDedicatedRoute + } + acc.mu.Unlock() + // Since v2.11.0, we support remotes with a different pool size + // (for rolling upgrades), so we need to use the remote route + // pool index (based on the remote configured pool size) since + // the remote subscriptions will be attached to the route at + // that index, not at our account's route pool index. But we + // need to compute only if rpi is negative or the pool sizes + // are different. + if rpi <= 0 || info.RoutePoolSize != s.routesPoolSize { + rpi = computeRoutePoolIdx(info.RoutePoolSize, an) + } + // Go over each remote's route at pool index `rpi` and remove + // remote subs for this account. + s.forEachRouteIdx(rpi, func(r *client) bool { + r.mu.Lock() + // Exclude routes to servers that don't support pooling. + if !r.route.noPool { + if subs := r.removeRemoteSubsForAcc(an); len(subs) > 0 { + sl.RemoveBatch(subs) + } + } + r.mu.Unlock() + return true + }) + // Respond to the remote by clearing the RouteAccount field. + info.RouteAccount = _EMPTY_ + proto := generateInfoJSON(info) + c.mu.Lock() + c.enqueueProto(proto) + c.mu.Unlock() + s.mu.Unlock() + } else { + // If no account name is specified, this is a response from the + // remote. Simply send to the communication channel, if the + // request ID matches the current one. + s.mu.Lock() + if info.RouteAccReqID == s.accAddedReqID && s.accAddedCh != nil { + select { + case s.accAddedCh <- struct{}{}: + default: + } + } + s.mu.Unlock() + } + // In both cases, we are done here. + return + } + // Check if this is an INFO for gateways... - if info.Gateway != "" { + if info.Gateway != _EMPTY_ { c.mu.Unlock() // If this server has no gateway configured, report error and return. if !s.gateway.enabled { @@ -541,54 +686,122 @@ func (c *client) processRouteInfo(info *Info) { info.Gateway, remoteID) return } - s.processGatewayInfoFromRoute(info, remoteID, c) + s.processGatewayInfoFromRoute(info, remoteID) return } // We receive an INFO from a server that informs us about another server, // so the info.ID in the INFO protocol does not match the ID of this route. - if remoteID != "" && remoteID != info.ID { + if remoteID != _EMPTY_ && remoteID != info.ID { + // We want to know if the existing route supports pooling/pinned-account + // or not when processing the implicit route. + noPool := c.route.noPool c.mu.Unlock() // Process this implicit route. We will check that it is not an explicit // route and/or that it has not been connected already. - s.processImplicitRoute(info) + s.processImplicitRoute(info, noPool) return } var connectURLs []string var wsConnectURLs []string + var updateRoutePerms bool // If we are notified that the remote is going into LDM mode, capture route's connectURLs. if info.LameDuckMode { connectURLs = c.route.connectURLs wsConnectURLs = c.route.wsConnURLs } else { - // If this is an update due to config reload on the remote server, - // need to possibly send local subs to the remote server. - c.updateRemoteRoutePerms(sl, info) + // Update only if we detect a difference + updateRoutePerms = !reflect.DeepEqual(c.opts.Import, info.Import) || !reflect.DeepEqual(c.opts.Export, info.Export) } c.mu.Unlock() + if updateRoutePerms { + s.updateRemoteRoutePerms(c, info) + } + // If the remote is going into LDM and there are client connect URLs // associated with this route and we are allowed to advertise, remove // those URLs and update our clients. - if (len(connectURLs) > 0 || len(wsConnectURLs) > 0) && !s.getOpts().Cluster.NoAdvertise { + if (len(connectURLs) > 0 || len(wsConnectURLs) > 0) && !opts.Cluster.NoAdvertise { + s.mu.Lock() s.removeConnectURLsAndSendINFOToClients(connectURLs, wsConnectURLs) + s.mu.Unlock() } return } // Check if remote has same server name than this server. - if !c.route.didSolicit && info.Name == srvName { - // For now simply report as a warning. - c.Warnf("Remote server has a duplicate name: %q", info.Name) + if !didSolicit && info.Name == srvName { + c.mu.Unlock() + // This is now an error and we close the connection. We need unique names for JetStream clustering. + c.Errorf("Remote server has a duplicate name: %q", info.Name) + c.closeConnection(DuplicateServerName) + return + } + + var sendDelayedInfo bool + + // First INFO, check if this server is configured for compression because + // if that is the case, we need to negotiate it with the remote server. + if needsCompression(opts.Cluster.Compression.Mode) { + accName := bytesToString(c.route.accName) + // If we did not yet negotiate... + compNeg := c.flags.isSet(compressionNegotiated) + if !compNeg { + // Prevent from getting back here. + c.flags.set(compressionNegotiated) + // Release client lock since following function will need server lock. + c.mu.Unlock() + compress, err := s.negotiateRouteCompression(c, didSolicit, accName, info.Compression, opts) + if err != nil { + c.sendErrAndErr(err.Error()) + c.closeConnection(ProtocolViolation) + return + } + if compress { + // Done for now, will get back another INFO protocol... + return + } + // No compression because one side does not want/can't, so proceed. + c.mu.Lock() + // Check that the connection did not close if the lock was released. + if c.isClosed() { + c.mu.Unlock() + return + } + } + // We can set the ping timer after we just negotiated compression above, + // or for solicited routes if we already negotiated. + if !compNeg || didSolicit { + c.setFirstPingTimer() + } + // When compression is configured, we delay the initial INFO for any + // solicited route. So we need to send the delayed INFO simply based + // on the didSolicit boolean. + sendDelayedInfo = didSolicit + } else { + // Coming from an old server, the Compression field would be the empty + // string. For servers that are configured with CompressionNotSupported, + // this makes them behave as old servers. + if info.Compression == _EMPTY_ || opts.Cluster.Compression.Mode == CompressionNotSupported { + c.route.compression = CompressionNotSupported + } else { + c.route.compression = CompressionOff + } + // When compression is not configured, we delay the initial INFO only + // for solicited pooled routes, so use the same check that we did when + // we decided to delay in createRoute(). + sendDelayedInfo = didSolicit && routeShouldDelayInfo(bytesToString(c.route.accName), opts) } // Mark that the INFO protocol has been received, so we can detect updates. c.flags.set(infoReceived) - // Get the route's proto version + // Get the route's proto version. It will be used to check if the connection + // supports certain features, such as message tracing. c.opts.Protocol = info.Proto // Headers @@ -601,13 +814,19 @@ func (c *client) processRouteInfo(info *Info) { c.route.gatewayURL = info.GatewayURL c.route.remoteName = info.Name c.route.lnoc = info.LNOC + c.route.lnocu = info.LNOCU + c.route.jetstream = info.JetStream // When sent through route INFO, if the field is set, it should be of size 1. if len(info.LeafNodeURLs) == 1 { c.route.leafnodeURL = info.LeafNodeURLs[0] } - // Compute the hash of this route based on remoteID - c.route.hash = string(getHash(info.ID)) + // Compute the hash of this route based on remote server name + c.route.hash = getHash(info.Name) + // Same with remote server ID (used for GW mapped replies routing). + // Use getGWHash since we don't use the same hash len for that + // for backward compatibility. + c.route.idHash = string(getGWHash(info.ID)) // Copy over permissions as well. c.opts.Import = info.Import @@ -627,57 +846,111 @@ func (c *client) processRouteInfo(info *Info) { } c.route.url = url } + // The incoming INFO from the route will have IP set + // if it has Cluster.Advertise. In that case, use that + // otherwise construct it from the remote TCP address. + if info.IP == _EMPTY_ { + // Need to get the remote IP address. + switch conn := c.nc.(type) { + case *net.TCPConn, *tls.Conn: + addr := conn.RemoteAddr().(*net.TCPAddr) + info.IP = fmt.Sprintf("nats-route://%s/", net.JoinHostPort(addr.IP.String(), + strconv.Itoa(info.Port))) + default: + info.IP = c.route.url.String() + } + } + // For accounts that are configured to have their own route: + // If this is a solicited route, we already have c.route.accName set in createRoute. + // For non solicited route (the accept side), we will set the account name that + // is present in the INFO protocol. + if didSolicit && len(c.route.accName) > 0 { + // Set it in the info.RouteAccount so that addRoute can use that + // and we properly gossip that this is a route for an account. + info.RouteAccount = string(c.route.accName) + } else if !didSolicit && info.RouteAccount != _EMPTY_ { + c.route.accName = []byte(info.RouteAccount) + } + accName := string(c.route.accName) + + // Capture the noGossip value and reset it here. + gossipMode := c.route.gossipMode + c.route.gossipMode = 0 // Check to see if we have this remote already registered. // This can happen when both servers have routes to each other. c.mu.Unlock() - if added, sendInfo := s.addRoute(c, info); added { - c.Debugf("Registering remote route %q", info.ID) + if added := s.addRoute(c, didSolicit, sendDelayedInfo, gossipMode, info, accName); added { + if accName != _EMPTY_ { + c.Debugf("Registering remote route %q for account %q", info.ID, accName) + } else { + c.Debugf("Registering remote route %q", info.ID) + } + } else { + c.Debugf("Detected duplicate remote route %q", info.ID) + c.closeConnection(DuplicateRoute) + } +} - // Send our subs to the other side. - s.sendSubsToRoute(c) +func (s *Server) negotiateRouteCompression(c *client, didSolicit bool, accName, infoCompression string, opts *Options) (bool, error) { + // Negotiate the appropriate compression mode (or no compression) + cm, err := selectCompressionMode(opts.Cluster.Compression.Mode, infoCompression) + if err != nil { + return false, err + } + c.mu.Lock() + // For "auto" mode, set the initial compression mode based on RTT + if cm == CompressionS2Auto { + if c.rttStart.IsZero() { + c.rtt = computeRTT(c.start) + } + cm = selectS2AutoModeBasedOnRTT(c.rtt, opts.Cluster.Compression.RTTThresholds) + } + // Keep track of the negotiated compression mode. + c.route.compression = cm + c.mu.Unlock() - // Send info about the known gateways to this route. - s.sendGatewayConfigsToRoute(c) + // If we end-up doing compression... + if needsCompression(cm) { + // Generate an INFO with the chosen compression mode. + s.mu.Lock() + infoProto := s.generateRouteInitialInfoJSON(accName, cm, 0, gossipDefault) + s.mu.Unlock() - // sendInfo will be false if the route that we just accepted - // is the only route there is. - if sendInfo { - // The incoming INFO from the route will have IP set - // if it has Cluster.Advertise. In that case, use that - // otherwise contruct it from the remote TCP address. - if info.IP == "" { - // Need to get the remote IP address. - c.mu.Lock() - switch conn := c.nc.(type) { - case *net.TCPConn, *tls.Conn: - addr := conn.RemoteAddr().(*net.TCPAddr) - info.IP = fmt.Sprintf("nats-route://%s/", net.JoinHostPort(addr.IP.String(), - strconv.Itoa(info.Port))) - default: - info.IP = c.route.url.String() - } - c.mu.Unlock() + // If we solicited, then send this INFO protocol BEFORE switching + // to compression writer. However, if we did not, we send it after. + c.mu.Lock() + if didSolicit { + c.enqueueProto(infoProto) + // Make sure it is completely flushed (the pending bytes goes to + // 0) before proceeding. + for c.out.pb > 0 && !c.isClosed() { + c.flushOutbound() } - // Now let the known servers know about this new route - s.forwardNewRouteInfoToKnownServers(info) - } - // Unless disabled, possibly update the server's INFO protocol - // and send to clients that know how to handle async INFOs. - if !s.getOpts().Cluster.NoAdvertise { - s.addConnectURLsAndSendINFOToClients(info.ClientConnectURLs, info.WSConnectURLs) } - } else { - c.Debugf("Detected duplicate remote route %q", info.ID) - c.closeConnection(DuplicateRoute) + // This is to notify the readLoop that it should switch to a + // (de)compression reader. + c.in.flags.set(switchToCompression) + // Create the compress writer before queueing the INFO protocol for + // a route that did not solicit. It will make sure that that proto + // is sent with compression on. + c.out.cw = s2.NewWriter(nil, s2WriterOptions(cm)...) + if !didSolicit { + c.enqueueProto(infoProto) + } + // We can now set the ping timer. + c.setFirstPingTimer() + c.mu.Unlock() + return true, nil } + return false, nil } // Possibly sends local subscriptions interest to this route // based on changes in the remote's Export permissions. -// Lock assumed held on entry -func (c *client) updateRemoteRoutePerms(sl *Sublist, info *Info) { +func (s *Server) updateRemoteRoutePerms(c *client, info *Info) { + c.mu.Lock() // Interested only on Export permissions for the remote server. // Create "fake" clients that we will use to check permissions // using the old permissions... @@ -692,13 +965,38 @@ func (c *client) updateRemoteRoutePerms(sl *Sublist, info *Info) { c.opts.Import = info.Import c.opts.Export = info.Export + routeAcc, poolIdx, noPool := bytesToString(c.route.accName), c.route.poolIdx, c.route.noPool + c.mu.Unlock() + var ( _localSubs [4096]*subscription - localSubs = _localSubs[:0] + _allSubs [4096]*subscription + allSubs = _allSubs[:0] ) - sl.localSubs(&localSubs) - c.sendRouteSubProtos(localSubs, false, func(sub *subscription) bool { + s.accounts.Range(func(_, v any) bool { + acc := v.(*Account) + acc.mu.RLock() + accName, sl, accPoolIdx := acc.Name, acc.sl, acc.routePoolIdx + acc.mu.RUnlock() + + // Do this only for accounts handled by this route + if (accPoolIdx >= 0 && accPoolIdx == poolIdx) || (routeAcc == accName) || noPool { + localSubs := _localSubs[:0] + sl.localSubs(&localSubs, false) + if len(localSubs) > 0 { + allSubs = append(allSubs, localSubs...) + } + } + return true + }) + + if len(allSubs) == 0 { + return + } + + c.mu.Lock() + c.sendRouteSubProtos(allSubs, false, func(sub *subscription) bool { subj := string(sub.subject) // If the remote can now export but could not before, and this server can import this // subject, then send SUB protocol. @@ -707,6 +1005,7 @@ func (c *client) updateRemoteRoutePerms(sl *Sublist, info *Info) { } return false }) + c.mu.Unlock() } // sendAsyncInfoToClients sends an INFO protocol to all @@ -715,7 +1014,7 @@ func (c *client) updateRemoteRoutePerms(sl *Sublist, info *Info) { func (s *Server) sendAsyncInfoToClients(regCli, wsCli bool) { // If there are no clients supporting async INFO protocols, we are done. // Also don't send if we are shutting down... - if s.cproto == 0 || s.shutdown { + if s.cproto == 0 || s.isShuttingDown() { return } info := s.copyInfo() @@ -740,7 +1039,7 @@ func (s *Server) sendAsyncInfoToClients(regCli, wsCli bool) { // This will process implicit route information received from another server. // We will check to see if we have configured or are already connected, // and if so we will ignore. Otherwise we will attempt to connect. -func (s *Server) processImplicitRoute(info *Info) { +func (s *Server) processImplicitRoute(info *Info, routeNoPool bool) { remoteID := info.ID s.mu.Lock() @@ -750,8 +1049,22 @@ func (s *Server) processImplicitRoute(info *Info) { if remoteID == s.info.ID { return } + + // Snapshot server options. + opts := s.getOpts() + // Check if this route already exists - if _, exists := s.remotes[remoteID]; exists { + if accName := info.RouteAccount; accName != _EMPTY_ { + // If we don't support pooling/pinned account, bail. + if opts.Cluster.PoolSize <= 0 { + return + } + if remotes, ok := s.accRoutes[accName]; ok { + if r := remotes[remoteID]; r != nil { + return + } + } + } else if _, exists := s.routes[remoteID]; exists { return } // Check if we have this route as a configured route @@ -766,50 +1079,144 @@ func (s *Server) processImplicitRoute(info *Info) { return } - // Snapshot server options. - opts := s.getOpts() - if info.AuthRequired { r.User = url.UserPassword(opts.Cluster.Username, opts.Cluster.Password) } - s.startGoRoutine(func() { s.connectToRoute(r, false, true) }) + s.startGoRoutine(func() { s.connectToRoute(r, Implicit, true, info.GossipMode, info.RouteAccount) }) + // If we are processing an implicit route from a route that does not + // support pooling/pinned-accounts, we won't receive an INFO for each of + // the pinned-accounts that we would normally receive. In that case, just + // initiate routes for all our configured pinned accounts. + if routeNoPool && info.RouteAccount == _EMPTY_ && len(opts.Cluster.PinnedAccounts) > 0 { + // Copy since we are going to pass as closure to a go routine. + rURL := r + for _, an := range opts.Cluster.PinnedAccounts { + accName := an + s.startGoRoutine(func() { s.connectToRoute(rURL, Implicit, true, info.GossipMode, accName) }) + } + } } // hasThisRouteConfigured returns true if info.Host:info.Port is present // in the server's opts.Routes, false otherwise. // Server lock is assumed to be held by caller. func (s *Server) hasThisRouteConfigured(info *Info) bool { - urlToCheckExplicit := strings.ToLower(net.JoinHostPort(info.Host, strconv.Itoa(info.Port))) - for _, ri := range s.getOpts().Routes { - if strings.ToLower(ri.Host) == urlToCheckExplicit { + routes := s.getOpts().Routes + if len(routes) == 0 { + return false + } + // This could possibly be a 0.0.0.0 host so we will also construct a second + // url with the host section of the `info.IP` (if present). + sPort := strconv.Itoa(info.Port) + urlOne := strings.ToLower(net.JoinHostPort(info.Host, sPort)) + var urlTwo string + if info.IP != _EMPTY_ { + if u, _ := url.Parse(info.IP); u != nil { + urlTwo = strings.ToLower(net.JoinHostPort(u.Hostname(), sPort)) + // Ignore if same than the first + if urlTwo == urlOne { + urlTwo = _EMPTY_ + } + } + } + for _, ri := range routes { + rHost := strings.ToLower(ri.Host) + if rHost == urlOne { + return true + } + if urlTwo != _EMPTY_ && rHost == urlTwo { return true } } return false } -// forwardNewRouteInfoToKnownServers sends the INFO protocol of the new route -// to all routes known by this server. In turn, each server will contact this -// new route. -func (s *Server) forwardNewRouteInfoToKnownServers(info *Info) { - s.mu.Lock() - defer s.mu.Unlock() +// forwardNewRouteInfoToKnownServers possibly sends the INFO protocol of the +// new route to all routes known by this server. In turn, each server will +// contact this new route. +// Server lock held on entry. +func (s *Server) forwardNewRouteInfoToKnownServers(info *Info, rtype RouteType, didSolicit bool, localGossipMode byte) { + // Determine if this connection is resulting from a gossip notification. + fromGossip := didSolicit && rtype == Implicit + // If from gossip (but we are not overriding it) or if the remote disabled gossip, bail out. + if (fromGossip && localGossipMode != gossipOverride) || info.GossipMode == gossipDisabled { + return + } // Note: nonce is not used in routes. // That being said, the info we get is the initial INFO which // contains a nonce, but we now forward this to existing routes, // so clear it now. info.Nonce = _EMPTY_ - b, _ := json.Marshal(info) - infoJSON := []byte(fmt.Sprintf(InfoProto, b)) - for _, r := range s.routes { + var ( + infoGMDefault []byte + infoGMDisabled []byte + infoGMOverride []byte + ) + + generateJSON := func(gm byte) []byte { + info.GossipMode = gm + b, _ := json.Marshal(info) + return []byte(fmt.Sprintf(InfoProto, b)) + } + + getJSON := func(r *client) []byte { + if (!didSolicit && r.route.routeType == Explicit) || (didSolicit && rtype == Explicit) { + if infoGMOverride == nil { + infoGMOverride = generateJSON(gossipOverride) + } + return infoGMOverride + } else if !didSolicit { + if infoGMDisabled == nil { + infoGMDisabled = generateJSON(gossipDisabled) + } + return infoGMDisabled + } + if infoGMDefault == nil { + infoGMDefault = generateJSON(0) + } + return infoGMDefault + } + + var accRemotes map[string]*client + pinnedAccount := info.RouteAccount != _EMPTY_ + // If this is for a pinned account, we will try to send the gossip + // through our pinned account routes, but fall back to the other + // routes in case we don't have one for a given remote. + if pinnedAccount { + var ok bool + if accRemotes, ok = s.accRoutes[info.RouteAccount]; ok { + for remoteID, r := range accRemotes { + if r == nil { + continue + } + r.mu.Lock() + // Do not send to a remote that does not support pooling/pinned-accounts. + if remoteID != info.ID && !r.route.noPool { + r.enqueueProto(getJSON(r)) + } + r.mu.Unlock() + } + } + } + + s.forEachRemote(func(r *client) { r.mu.Lock() - if r.route.remoteID != info.ID { - r.enqueueProto(infoJSON) + remoteID := r.route.remoteID + if pinnedAccount { + if _, processed := accRemotes[remoteID]; processed { + r.mu.Unlock() + return + } + } + // If this is a new route for a given account, do not send to a server + // that does not support pooling/pinned-accounts. + if remoteID != info.ID && (!pinnedAccount || !r.route.noPool) { + r.enqueueProto(getJSON(r)) } r.mu.Unlock() - } + }) } // canImport is whether or not we will send a SUB for interest to the other side. @@ -818,7 +1225,7 @@ func (s *Server) forwardNewRouteInfoToKnownServers(info *Info) { func (c *client) canImport(subject string) bool { // Use pubAllowed() since this checks Publish permissions which // is what Import maps to. - return c.pubAllowedFullCheck(subject, false) + return c.pubAllowedFullCheck(subject, false, true) } // canExport is whether or not we will accept a SUB from the remote for a given subject. @@ -857,6 +1264,36 @@ type asubs struct { subs []*subscription } +// Returns the account name from the subscription's key. +// This is invoked knowing that the key contains an account name, so for a sub +// that is not from a pinned-account route. +// The `keyHasSubType` boolean indicates that the key starts with the indicator +// for leaf or regular routed subscriptions. +func getAccNameFromRoutedSubKey(sub *subscription, key string, keyHasSubType bool) string { + var accIdx int + if keyHasSubType { + // Start after the sub type indicator. + accIdx = 1 + // But if there is an origin, bump its index. + if len(sub.origin) > 0 { + accIdx = 2 + } + } + return strings.Fields(key)[accIdx] +} + +// Returns if the route is dedicated to an account, its name, and a boolean +// that indicates if this route uses the routed subscription indicator at +// the beginning of the subscription key. +// Lock held on entry. +func (c *client) getRoutedSubKeyInfo() (bool, string, bool) { + var accName string + if an := c.route.accName; len(an) > 0 { + accName = string(an) + } + return accName != _EMPTY_, accName, c.route.lnocu +} + // removeRemoteSubs will walk the subs and remove them from the appropriate account. func (c *client) removeRemoteSubs() { // We need to gather these on a per account basis. @@ -865,64 +1302,129 @@ func (c *client) removeRemoteSubs() { c.mu.Lock() srv := c.srv subs := c.subs - c.subs = make(map[string]*subscription) + c.subs = nil + pa, accountName, hasSubType := c.getRoutedSubKeyInfo() c.mu.Unlock() for key, sub := range subs { c.mu.Lock() sub.max = 0 c.mu.Unlock() - // Grab the account - accountName := strings.Fields(key)[0] + // If not a pinned-account route, we need to find the account + // name from the sub's key. + if !pa { + accountName = getAccNameFromRoutedSubKey(sub, key, hasSubType) + } ase := as[accountName] if ase == nil { if v, ok := srv.accounts.Load(accountName); ok { - as[accountName] = &asubs{acc: v.(*Account), subs: []*subscription{sub}} + ase = &asubs{acc: v.(*Account), subs: []*subscription{sub}} + as[accountName] = ase } else { continue } } else { ase.subs = append(ase.subs, sub) } + delta := int32(1) + if len(sub.queue) > 0 { + delta = sub.qw + } if srv.gateway.enabled { - srv.gatewayUpdateSubInterest(accountName, sub, -1) + srv.gatewayUpdateSubInterest(accountName, sub, -delta) } + ase.acc.updateLeafNodes(sub, -delta) } // Now remove the subs by batch for each account sublist. for _, ase := range as { c.Debugf("Removing %d subscriptions for account %q", len(ase.subs), ase.acc.Name) + ase.acc.mu.Lock() ase.acc.sl.RemoveBatch(ase.subs) + ase.acc.mu.Unlock() + } +} + +// Removes (and returns) the subscriptions from this route's subscriptions map +// that belong to the given account. +// Lock is held on entry +func (c *client) removeRemoteSubsForAcc(name string) []*subscription { + var subs []*subscription + _, _, hasSubType := c.getRoutedSubKeyInfo() + for key, sub := range c.subs { + an := getAccNameFromRoutedSubKey(sub, key, hasSubType) + if an == name { + sub.max = 0 + subs = append(subs, sub) + delete(c.subs, key) + } } + return subs } -func (c *client) parseUnsubProto(arg []byte) (string, []byte, []byte, error) { +func (c *client) parseUnsubProto(arg []byte, accInProto, hasOrigin bool) ([]byte, string, []byte, []byte, error) { // Indicate any activity, so pub and sub or unsubs. c.in.subs++ args := splitArg(arg) - var queue []byte + + var ( + origin []byte + accountName string + queue []byte + subjIdx int + ) + // If `hasOrigin` is true, then it means this is a LS- with origin in proto. + if hasOrigin { + // We would not be here if there was not at least 1 field. + origin = args[0] + subjIdx = 1 + } + // If there is an account in the protocol, bump the subject index. + if accInProto { + subjIdx++ + } switch len(args) { - case 2: - case 3: - queue = args[2] + case subjIdx + 1: + case subjIdx + 2: + queue = args[subjIdx+1] default: - return "", nil, nil, fmt.Errorf("parse error: '%s'", arg) + return nil, _EMPTY_, nil, nil, fmt.Errorf("parse error: '%s'", arg) } - return string(args[0]), args[1], queue, nil + if accInProto { + // If there is an account in the protocol, it is before the subject. + accountName = string(args[subjIdx-1]) + } + return origin, accountName, args[subjIdx], queue, nil } // Indicates no more interest in the given account/subject for the remote side. -func (c *client) processRemoteUnsub(arg []byte) (err error) { +func (c *client) processRemoteUnsub(arg []byte, leafUnsub bool) (err error) { srv := c.srv if srv == nil { return nil } - accountName, subject, _, err := c.parseUnsubProto(arg) + + var accountName string + // Assume the account will be in the protocol. + accInProto := true + + c.mu.Lock() + originSupport := c.route.lnocu + if c.route != nil && len(c.route.accName) > 0 { + accountName, accInProto = string(c.route.accName), false + } + c.mu.Unlock() + + hasOrigin := leafUnsub && originSupport + _, accNameFromProto, subject, _, err := c.parseUnsubProto(arg, accInProto, hasOrigin) if err != nil { return fmt.Errorf("processRemoteUnsub %s", err.Error()) } + if accInProto { + accountName = accNameFromProto + } // Lookup the account var acc *Account if v, ok := srv.accounts.Load(accountName); ok { @@ -938,25 +1440,44 @@ func (c *client) processRemoteUnsub(arg []byte) (err error) { return nil } - updateGWs := false - // We store local subs by account and subject and optionally queue name. - // RS- will have the arg exactly as the key. - key := string(arg) + _keya := [128]byte{} + _key := _keya[:0] + + var key string + if !originSupport { + // If it is an LS- or RS-, we use the protocol as-is as the key. + key = bytesToString(arg) + } else { + // We need to prefix with the sub type. + if leafUnsub { + _key = append(_key, keyRoutedLeafSubByte) + } else { + _key = append(_key, keyRoutedSubByte) + } + _key = append(_key, ' ') + _key = append(_key, arg...) + key = bytesToString(_key) + } + delta := int32(1) sub, ok := c.subs[key] if ok { delete(c.subs, key) acc.sl.Remove(sub) - c.removeReplySubTimeout(sub) - updateGWs = srv.gateway.enabled + if len(sub.queue) > 0 { + delta = sub.qw + } } c.mu.Unlock() - if updateGWs { - srv.gatewayUpdateSubInterest(accountName, sub, -1) - } + // Update gateways and leaf nodes only if the subscription was found. + if ok { + if srv.gateway.enabled { + srv.gatewayUpdateSubInterest(accountName, sub, -delta) + } - // Now check on leafnode updates. - srv.updateLeafNodes(acc, sub, -1) + // Now check on leafnode updates. + acc.updateLeafNodes(sub, -delta) + } if c.opts.Verbose { c.sendOK() @@ -973,33 +1494,129 @@ func (c *client) processRemoteSub(argo []byte, hasOrigin bool) (err error) { return nil } - // Copy so we do not reference a potentially large buffer - arg := make([]byte, len(argo)) - copy(arg, argo) + // We copy `argo` to not reference the read buffer. However, we will + // prefix with a code that says if the remote sub is for a leaf + // (hasOrigin == true) or not to prevent key collisions. Imagine: + // "RS+ foo bar baz 1\r\n" => "foo bar baz" (a routed queue sub) + // "LS+ foo bar baz\r\n" => "foo bar baz" (a route leaf sub on "baz", + // for account "bar" with origin "foo"). + // + // The sub.sid/key will be set respectively to "R foo bar baz" and + // "L foo bar baz". + // + // We also no longer add the account if it was not present (due to + // pinned-account route) since there is no need really. + // + // For routes to older server, we will still create the "arg" with + // the above layout, but we will create the sub.sid/key as before, + // that is, not including the origin for LS+ because older server + // only send LS- without origin, so we would not be able to find + // the sub in the map. + c.mu.Lock() + accountName := string(c.route.accName) + oldStyle := !c.route.lnocu + c.mu.Unlock() - args := splitArg(arg) - sub := &subscription{client: c} + // Indicate if the account name should be in the protocol. It would be the + // case if accountName is empty. + accInProto := accountName == _EMPTY_ - var off int + // Copy so we do not reference a potentially large buffer. + // Add 2 more bytes for the routed sub type. + arg := make([]byte, 0, 2+len(argo)) if hasOrigin { - off = 1 - sub.origin = args[0] + arg = append(arg, keyRoutedLeafSubByte) + } else { + arg = append(arg, keyRoutedSubByte) + } + arg = append(arg, ' ') + arg = append(arg, argo...) + + // Now split to get all fields. Unroll splitArgs to avoid runtime/heap issues. + a := [MAX_RSUB_ARGS][]byte{} + args := a[:0] + start := -1 + for i, b := range arg { + switch b { + case ' ', '\t', '\r', '\n': + if start >= 0 { + args = append(args, arg[start:i]) + start = -1 + } + default: + if start < 0 { + start = i + } + } + } + if start >= 0 { + args = append(args, arg[start:]) } + delta := int32(1) + sub := &subscription{client: c} + + // There will always be at least a subject, but its location will depend + // on if there is an origin, an account name, etc.. Since we know that + // we have added the sub type indicator as the first field, the subject + // position will be at minimum at index 1. + subjIdx := 1 + if hasOrigin { + subjIdx++ + } + if accInProto { + subjIdx++ + } switch len(args) { - case 2 + off: + case subjIdx + 1: sub.queue = nil - case 4 + off: - sub.queue = args[2+off] - sub.qw = int32(parseSize(args[3+off])) + case subjIdx + 3: + sub.queue = args[subjIdx+1] + sub.qw = int32(parseSize(args[subjIdx+2])) + // TODO: (ik) We should have a non empty queue name and a queue + // weight >= 1. For 2.11, we may want to return an error if that + // is not the case, but for now just overwrite `delta` if queue + // weight is greater than 1 (it is possible after a reconnect/ + // server restart to receive a queue weight > 1 for a new sub). + if sub.qw > 1 { + delta = sub.qw + } default: return fmt.Errorf("processRemoteSub Parse Error: '%s'", arg) } - sub.subject = args[1+off] + // We know that the number of fields is correct. So we can access args[] based + // on where we expect the fields to be. + + // If there is an origin, it will be at index 1. + if hasOrigin { + sub.origin = args[1] + } + // For subject, use subjIdx. + sub.subject = args[subjIdx] + // If the account name is in the protocol, it will be before the subject. + if accInProto { + accountName = bytesToString(args[subjIdx-1]) + } + // Now set the sub.sid from the arg slice. However, we will have a different + // one if we use the origin or not. + start = 0 + end := len(arg) + if sub.queue != nil { + // Remove the ' ' from the arg length. + end -= 1 + len(args[subjIdx+2]) + } + if oldStyle { + // We will start at the account (if present) or at the subject. + // We first skip the "R " or "L " + start = 2 + // And if there is an origin skip that. + if hasOrigin { + start += len(sub.origin) + 1 + } + // Here we are pointing at the account (if present), or at the subject. + } + sub.sid = arg[start:end] - // Lookup the account - // FIXME(dlc) - This may start having lots of contention? - accountName := string(args[0+off]) // Lookup account while avoiding fetch. // A slow fetch delays subsequent remote messages. It also avoids the expired check (see below). // With all but memory resolver lookup can be delayed or fail. @@ -1019,22 +1636,19 @@ func (c *client) processRemoteSub(argo []byte, hasOrigin bool) (err error) { acc = v.(*Account) } if acc == nil { - expire := false - isNew := false - if !srv.NewAccountsAllowed() { - // if the option of retrieving accounts later exists, create an expired one. - // When a client comes along, expiration will prevent it from being used, - // cause a fetch and update the account to what is should be. - if staticResolver { - c.Errorf("Unknown account %q for remote subject %q", accountName, sub.subject) - return - } - c.Debugf("Unknown account %q for remote subject %q", accountName, sub.subject) - expire = true + // if the option of retrieving accounts later exists, create an expired one. + // When a client comes along, expiration will prevent it from being used, + // cause a fetch and update the account to what is should be. + if staticResolver { + c.Errorf("Unknown account %q for remote subject %q", accountName, sub.subject) + return } - if acc, isNew = srv.LookupOrRegisterAccount(accountName); isNew && expire { + c.Debugf("Unknown account %q for remote subject %q", accountName, sub.subject) + + var isNew bool + if acc, isNew = srv.LookupOrRegisterAccount(accountName); isNew { acc.mu.Lock() - acc.expired = true + acc.expired.Store(true) acc.incomplete = true acc.mu.Unlock() } @@ -1047,7 +1661,7 @@ func (c *client) processRemoteSub(argo []byte, hasOrigin bool) (err error) { } // Check permissions if applicable. - if !c.canExport(string(sub.subject)) { + if c.perms != nil && !c.canExport(string(sub.subject)) { c.mu.Unlock() c.Debugf("Can not export %q, ignoring remote subscription request", sub.subject) return nil @@ -1060,41 +1674,48 @@ func (c *client) processRemoteSub(argo []byte, hasOrigin bool) (err error) { return nil } - // We store local subs by account and subject and optionally queue name. - // If we have a queue it will have a trailing weight which we do not want. - if sub.queue != nil { - sub.sid = arg[:len(arg)-len(args[3+off])-1] - } else { - sub.sid = arg + acc.mu.RLock() + // For routes (this can be called by leafnodes), check if the account is + // transitioning (from pool to dedicated route) and this route is not a + // per-account route (route.poolIdx >= 0). If so, ignore this subscription. + // Exclude "no pool" routes from this check. + if c.kind == ROUTER && !c.route.noPool && + acc.routePoolIdx == accTransitioningToDedicatedRoute && c.route.poolIdx >= 0 { + acc.mu.RUnlock() + c.mu.Unlock() + // Do not return an error, which would cause the connection to be closed. + return nil } - key := string(sub.sid) + sl := acc.sl + acc.mu.RUnlock() + // We use the sub.sid for the key of the c.subs map. + key := bytesToString(sub.sid) osub := c.subs[key] - updateGWs := false if osub == nil { c.subs[key] = sub // Now place into the account sl. - if err = acc.sl.Insert(sub); err != nil { + if err = sl.Insert(sub); err != nil { delete(c.subs, key) c.mu.Unlock() c.Errorf("Could not insert subscription: %v", err) c.sendErr("Invalid Subscription") return nil } - updateGWs = srv.gateway.enabled } else if sub.queue != nil { // For a queue we need to update the weight. + delta = sub.qw - atomic.LoadInt32(&osub.qw) atomic.StoreInt32(&osub.qw, sub.qw) - acc.sl.UpdateRemoteQSub(osub) + sl.UpdateRemoteQSub(osub) } c.mu.Unlock() - if updateGWs { - srv.gatewayUpdateSubInterest(acc.Name, sub, 1) + if srv.gateway.enabled { + srv.gatewayUpdateSubInterest(acc.Name, sub, delta) } // Now check on leafnode updates. - srv.updateLeafNodes(acc, sub, 1) + acc.updateLeafNodes(sub, delta) if c.opts.Verbose { c.sendOK() @@ -1103,80 +1724,152 @@ func (c *client) processRemoteSub(argo []byte, hasOrigin bool) (err error) { return nil } -// sendSubsToRoute will send over our subject interest to -// the remote side. For each account we will send the +// Lock is held on entry +func (c *client) addRouteSubOrUnsubProtoToBuf(buf []byte, accName string, sub *subscription, isSubProto bool) []byte { + // If we have an origin cluster and the other side supports leafnode origin clusters + // send an LS+/LS- version instead. + if len(sub.origin) > 0 && c.route.lnoc { + if isSubProto { + buf = append(buf, lSubBytes...) + buf = append(buf, sub.origin...) + buf = append(buf, ' ') + } else { + buf = append(buf, lUnsubBytes...) + if c.route.lnocu { + buf = append(buf, sub.origin...) + buf = append(buf, ' ') + } + } + } else { + if isSubProto { + buf = append(buf, rSubBytes...) + } else { + buf = append(buf, rUnsubBytes...) + } + } + if len(c.route.accName) == 0 { + buf = append(buf, accName...) + buf = append(buf, ' ') + } + buf = append(buf, sub.subject...) + if len(sub.queue) > 0 { + buf = append(buf, ' ') + buf = append(buf, sub.queue...) + // Send our weight if we are a sub proto + if isSubProto { + buf = append(buf, ' ') + var b [12]byte + var i = len(b) + for l := sub.qw; l > 0; l /= 10 { + i-- + b[i] = digits[l%10] + } + buf = append(buf, b[i:]...) + } + } + buf = append(buf, CR_LF...) + return buf +} + +// sendSubsToRoute will send over our subject interest to +// the remote side. For each account we will send the // complete interest for all subjects, both normal as a binary // and queue group weights. -func (s *Server) sendSubsToRoute(route *client) { - s.mu.Lock() +// +// Server lock held on entry. +func (s *Server) sendSubsToRoute(route *client, idx int, account string) { + var noPool bool + if idx >= 0 { + // We need to check if this route is "no_pool" in which case we + // need to select all accounts. + route.mu.Lock() + noPool = route.route.noPool + route.mu.Unlock() + } // Estimated size of all protocols. It does not have to be accurate at all. - eSize := 0 + var eSize int + estimateProtosSize := func(a *Account, addAccountName bool) { + if ns := len(a.rm); ns > 0 { + var accSize int + if addAccountName { + accSize = len(a.Name) + 1 + } + // Proto looks like: "RS+ [ ][ ]\r\n" + eSize += ns * (len(rSubBytes) + 1 + accSize) + for key := range a.rm { + // Key contains "[ ]" + eSize += len(key) + // In case this is a queue, just add some bytes for the queue weight. + // If we want to be accurate, would have to check if "key" has a space, + // if so, then figure out how many bytes we need to represent the weight. + eSize += 5 + } + } + } // Send over our account subscriptions. - // copy accounts into array first - accs := make([]*Account, 0, 32) - s.accounts.Range(func(k, v interface{}) bool { - a := v.(*Account) - accs = append(accs, a) - a.mu.RLock() - // Proto looks like: "RS+ [ ]\r\n" - // If we wanted to have better estimates (or even accurate), we would - // collect the subs here instead of capturing the accounts and then - // later going over each account. - eSize += len(a.rm) * (4 + len(a.Name) + 256) - a.mu.RUnlock() - return true - }) - s.mu.Unlock() - - sendSubs := func(accs []*Account) { - var raw [32]*subscription - - route.mu.Lock() - for _, a := range accs { - subs := raw[:0] - + accs := make([]*Account, 0, 1024) + if idx < 0 || account != _EMPTY_ { + if ai, ok := s.accounts.Load(account); ok { + a := ai.(*Account) a.mu.RLock() - c := a.randomClient() - if c == nil { - nsubs := len(a.rm) - accName := a.Name - a.mu.RUnlock() - if nsubs > 0 { - route.Warnf("Ignoring account %q with %d subs, no clients", accName, nsubs) - } - continue - } - for key, n := range a.rm { - // FIXME(dlc) - Just pass rme around. - // Construct a sub on the fly. We need to place - // a client (or im) to properly set the account. - var subj, qn []byte - s := strings.Split(key, " ") - subj = []byte(s[0]) - if len(s) > 1 { - qn = []byte(s[1]) - } - // TODO(dlc) - This code needs to change, but even if left alone could be more - // efficient with these tmp subs. - sub := &subscription{client: c, subject: subj, queue: qn, qw: n} - subs = append(subs, sub) + // Estimate size and add account name in protocol if idx is not -1 + estimateProtosSize(a, idx >= 0) + accs = append(accs, a) + a.mu.RUnlock() + } + } else { + s.accounts.Range(func(k, v any) bool { + a := v.(*Account) + a.mu.RLock() + // We are here for regular or pooled routes (not per-account). + // So we collect all accounts whose routePoolIdx matches the + // one for this route, or only the account provided, or all + // accounts if dealing with a "no pool" route. + if a.routePoolIdx == idx || noPool { + estimateProtosSize(a, true) + accs = append(accs, a) } a.mu.RUnlock() + return true + }) + } + + buf := make([]byte, 0, eSize) - route.sendRouteSubProtos(subs, false, route.importFilter) + route.mu.Lock() + for _, a := range accs { + a.mu.RLock() + for key, n := range a.rm { + var origin, qn []byte + s := strings.Fields(key) + // Subject will always be the second field (index 1). + subj := stringToBytes(s[1]) + // Check if the key is for a leaf (will be field 0). + forLeaf := s[0] == keyRoutedLeafSub + // For queue, if not for a leaf, we need 3 fields "R foo bar", + // but if for a leaf, we need 4 fields "L foo bar leaf_origin". + if l := len(s); (!forLeaf && l == 3) || (forLeaf && l == 4) { + qn = stringToBytes(s[2]) + } + if forLeaf { + // The leaf origin will be the last field. + origin = stringToBytes(s[len(s)-1]) + } + // s[1] is the subject and already as a string, so use that + // instead of converting back `subj` to a string. + if !route.canImport(s[1]) { + continue + } + sub := subscription{origin: origin, subject: subj, queue: qn, qw: n} + buf = route.addRouteSubOrUnsubProtoToBuf(buf, a.Name, &sub, true) } - route.mu.Unlock() - route.Debugf("Sent local subscriptions to route") + a.mu.RUnlock() } - // Decide if we call above function in go routine or in place. - if eSize > sendRouteSubsInGoRoutineThreshold { - s.startGoRoutine(func() { - sendSubs(accs) - s.grWG.Done() - }) - } else { - sendSubs(accs) + if len(buf) > 0 { + route.enqueueProto(buf) + route.Debugf("Sent local subscriptions to route") } + route.mu.Unlock() } // Sends SUBs protocols for the given subscriptions. If a filter is specified, it is @@ -1230,79 +1923,42 @@ func (c *client) sendRouteSubOrUnSubProtos(subs []*subscription, isSubProto, tra } as := len(buf) - - // If we have an origin cluster and the other side supports leafnode origin clusters - // send an LS+/LS- version instead. - if len(sub.origin) > 0 && c.route.lnoc { - if isSubProto { - buf = append(buf, lSubBytes...) - buf = append(buf, sub.origin...) - } else { - buf = append(buf, lUnsubBytes...) - } - buf = append(buf, ' ') - } else { - if isSubProto { - buf = append(buf, rSubBytes...) - } else { - buf = append(buf, rUnsubBytes...) - } - } - buf = append(buf, accName...) - buf = append(buf, ' ') - buf = append(buf, sub.subject...) - if len(sub.queue) > 0 { - buf = append(buf, ' ') - buf = append(buf, sub.queue...) - // Send our weight if we are a sub proto - if isSubProto { - buf = append(buf, ' ') - var b [12]byte - var i = len(b) - for l := sub.qw; l > 0; l /= 10 { - i-- - b[i] = digits[l%10] - } - buf = append(buf, b[i:]...) - } - } + buf = c.addRouteSubOrUnsubProtoToBuf(buf, accName, sub, isSubProto) if trace { - c.traceOutOp("", buf[as:]) + c.traceOutOp("", buf[as:len(buf)-LEN_CR_LF]) } - buf = append(buf, CR_LF...) } - c.enqueueProto(buf) } -func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { +func (s *Server) createRoute(conn net.Conn, rURL *url.URL, rtype RouteType, gossipMode byte, accName string) *client { // Snapshot server options. opts := s.getOpts() didSolicit := rURL != nil - r := &route{didSolicit: didSolicit} - for _, route := range opts.Routes { - if rURL != nil && (strings.EqualFold(rURL.Host, route.Host)) { - r.routeType = Explicit - } - } + r := &route{routeType: rtype, didSolicit: didSolicit, poolIdx: -1, gossipMode: gossipMode} + + c := &client{srv: s, nc: conn, opts: ClientOpts{}, kind: ROUTER, msubs: -1, mpay: -1, route: r, start: time.Now()} - c := &client{srv: s, nc: conn, opts: clientOpts{}, kind: ROUTER, msubs: -1, mpay: -1, route: r} + // Is the server configured for compression? + compressionConfigured := needsCompression(opts.Cluster.Compression.Mode) - // Grab server variables + var infoJSON []byte + // Grab server variables and generates route INFO Json. Note that we set + // and reset some of s.routeInfo fields when that happens, so we need + // the server write lock. s.mu.Lock() - // New proto wants a nonce (although not used in routes, that is, not signed in CONNECT) - var raw [nonceLen]byte - nonce := raw[:] - s.generateNonce(nonce) - s.routeInfo.Nonce = string(nonce) - s.generateRouteInfoJSON() - // Clear now that it has been serialized. Will prevent nonce to be included in async INFO that we may send. - s.routeInfo.Nonce = _EMPTY_ - infoJSON := s.routeInfoJSON + // If we are creating a pooled connection and this is the server soliciting + // the connection, we will delay sending the INFO after we have processed + // the incoming INFO from the remote. Also delay if configured for compression. + delayInfo := didSolicit && (compressionConfigured || routeShouldDelayInfo(accName, opts)) + if !delayInfo { + infoJSON = s.generateRouteInitialInfoJSON(accName, opts.Cluster.Compression.Mode, 0, gossipMode) + } authRequired := s.routeInfo.AuthRequired tlsRequired := s.routeInfo.TLSRequired clusterName := s.info.Cluster + tlsName := s.routeTLSName s.mu.Unlock() // Grab lock @@ -1315,53 +1971,26 @@ func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { // Do this before the TLS code, otherwise, in case of failure // and if route is explicit, it would try to reconnect to 'nil'... r.url = rURL + r.accName = []byte(accName) } else { c.flags.set(expectConnect) } // Check for TLS if tlsRequired { - // Copy off the config to add in ServerName if we need to. - tlsConfig := opts.Cluster.TLSConfig.Clone() - - // If we solicited, we will act like the client, otherwise the server. + tlsConfig := opts.Cluster.TLSConfig if didSolicit { - c.Debugf("Starting TLS route client handshake") - // Specify the ServerName we are expecting. - host, _, _ := net.SplitHostPort(rURL.Host) - tlsConfig.ServerName = host - c.nc = tls.Client(c.nc, tlsConfig) - } else { - c.Debugf("Starting TLS route server handshake") - c.nc = tls.Server(c.nc, tlsConfig) + // Copy off the config to add in ServerName if we need to. + tlsConfig = tlsConfig.Clone() } - - conn := c.nc.(*tls.Conn) - - // Setup the timeout - ttl := secondsToDuration(opts.Cluster.TLSTimeout) - time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) - conn.SetReadDeadline(time.Now().Add(ttl)) - - c.mu.Unlock() - if err := conn.Handshake(); err != nil { - c.Errorf("TLS route handshake error: %v", err) - c.sendErr("Secure Connection - TLS Required") - c.closeConnection(TLSHandshakeError) - return nil - } - // Reset the read deadline - conn.SetReadDeadline(time.Time{}) - - // Re-Grab lock - c.mu.Lock() - - // To be consistent with client, set this flag to indicate that handshake is done - c.flags.set(handshakeComplete) - - // Verify that the connection did not go away while we released the lock. - if c.isClosed() { + // Perform (server or client side) TLS handshake. + if resetTLSName, err := c.doTLSHandshake("route", didSolicit, rURL, tlsConfig, tlsName, opts.Cluster.TLSTimeout, opts.Cluster.TLSPinnedCerts); err != nil { c.mu.Unlock() + if resetTLSName { + s.mu.Lock() + s.routeTLSName = _EMPTY_ + s.mu.Unlock() + } return nil } } @@ -1376,8 +2005,25 @@ func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { c.setRoutePermissions(opts.Cluster.Permissions) } - // Set the Ping timer - s.setFirstPingTimer(c) + // We can't safely send the pings until we have negotiated compression + // with the remote, but we want to protect against a connection that + // does not perform the handshake. We will start a timer that will close + // the connection as stale based on the ping interval and max out values, + // but without actually sending pings. + if compressionConfigured { + pingInterval := opts.PingInterval + pingMax := opts.MaxPingsOut + if opts.Cluster.PingInterval > 0 { + pingInterval = opts.Cluster.PingInterval + } + if opts.Cluster.MaxPingsOut > 0 { + pingMax = opts.MaxPingsOut + } + c.watchForStaleConnection(adjustPingInterval(ROUTER, pingInterval), pingMax) + } else { + // Set the Ping timer + c.setFirstPingTimer() + } // For routes, the "client" is added to s.routes only when processing // the INFO protocol, that is much later. @@ -1421,103 +2067,449 @@ func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { } } - // Send our info to the other side. - // Our new version requires dynamic information for accounts and a nonce. - c.enqueueProto(infoJSON) + if !delayInfo { + // Send our info to the other side. + // Our new version requires dynamic information for accounts and a nonce. + c.enqueueProto(infoJSON) + } c.mu.Unlock() c.Noticef("Route connection created") return c } +func routeShouldDelayInfo(accName string, opts *Options) bool { + return accName == _EMPTY_ && opts.Cluster.PoolSize >= 1 +} + +// Generates a nonce and set some route info's fields before marshal'ing into JSON. +// To be used only when a route is created (to send the initial INFO protocol). +// +// Server lock held on entry. +func (s *Server) generateRouteInitialInfoJSON(accName, compression string, poolIdx int, gossipMode byte) []byte { + // New proto wants a nonce (although not used in routes, that is, not signed in CONNECT) + var raw [nonceLen]byte + nonce := raw[:] + s.generateNonce(nonce) + ri := &s.routeInfo + // Override compression with s2_auto instead of actual compression level. + if s.getOpts().Cluster.Compression.Mode == CompressionS2Auto { + compression = CompressionS2Auto + } + ri.Nonce, ri.RouteAccount, ri.RoutePoolIdx, ri.Compression, ri.GossipMode = string(nonce), accName, poolIdx, compression, gossipMode + infoJSON := generateInfoJSON(&s.routeInfo) + // Clear now that it has been serialized. Will prevent nonce to be included in async INFO that we may send. + // Same for some other fields. + ri.Nonce, ri.RouteAccount, ri.RoutePoolIdx, ri.Compression, ri.GossipMode = _EMPTY_, _EMPTY_, 0, _EMPTY_, 0 + return infoJSON +} + const ( _CRLF_ = "\r\n" _EMPTY_ = "" ) -func (s *Server) addRoute(c *client, info *Info) (bool, bool) { - id := c.route.remoteID - sendInfo := false +func (s *Server) addRoute(c *client, didSolicit, sendDelayedInfo bool, gossipMode byte, info *Info, accName string) bool { + id := info.ID + + var acc *Account + if accName != _EMPTY_ { + var err error + acc, err = s.LookupAccount(accName) + if err != nil { + c.sendErrAndErr(fmt.Sprintf("Unable to lookup account %q: %v", accName, err)) + c.closeConnection(MissingAccount) + return false + } + } s.mu.Lock() - if !s.running { + if !s.isRunning() || s.routesReject { s.mu.Unlock() - return false, false + return false + } + var invProtoErr string + + opts := s.getOpts() + + // Assume we are in pool mode if info.RoutePoolSize is set. We may disable + // in some cases. + pool := info.RoutePoolSize > 0 + // This is used to prevent a server with pooling to constantly trying + // to connect to a server with no pooling (for instance old server) after + // the first connection is established. + var noReconnectForOldServer bool + + // To allow rolling updates, we now allow servers with different pool sizes + // so we will use as the effective pool size here, the max between our + // configured size and the size we receive in the info protocol. + effectivePoolSize := max(s.routesPoolSize, info.RoutePoolSize) + + // If the remote is an old server, info.RoutePoolSize will be 0, or if + // this server's Cluster.PoolSize is negative, we will behave as an old + // server and need to handle things differently. + if info.RoutePoolSize <= 0 || opts.Cluster.PoolSize < 0 { + if accName != _EMPTY_ { + invProtoErr = fmt.Sprintf("Not possible to have a dedicated route for account %q between those servers", accName) + // In this case, make sure this route does not attempt to reconnect + c.setNoReconnect() + } else { + // We will accept, but treat this remote has "no pool" + pool, noReconnectForOldServer = false, true + c.mu.Lock() + c.route.poolIdx = 0 + c.route.noPool = true + c.mu.Unlock() + // Keep track of number of routes like that. We will use that when + // sending subscriptions over routes. + s.routesNoPool++ + } + } else if didSolicit { + // For solicited route, the incoming's RoutePoolIdx should not be set. + if info.RoutePoolIdx != 0 { + invProtoErr = fmt.Sprintf("Route pool index should not be set but is set to %v", info.RoutePoolIdx) + } + } else if info.RoutePoolIdx < 0 || info.RoutePoolIdx >= effectivePoolSize { + // For non solicited routes, if the remote sends a RoutePoolIdx, make + // sure it is a valid one (in range of the pool size). + invProtoErr = fmt.Sprintf("Invalid route pool index: %v - pool size is %v", info.RoutePoolIdx, info.RoutePoolSize) } - remote, exists := s.remotes[id] + if invProtoErr != _EMPTY_ { + s.mu.Unlock() + c.sendErrAndErr(invProtoErr) + c.closeConnection(ProtocolViolation) + return false + } + // If accName is set, we are dealing with a per-account connection. + if accName != _EMPTY_ { + // When an account has its own route, it will be an error if the given + // account name is not found in s.accRoutes map. + conns, exists := s.accRoutes[accName] + if !exists { + s.mu.Unlock() + c.sendErrAndErr(fmt.Sprintf("No route for account %q", accName)) + c.closeConnection(ProtocolViolation) + return false + } + remote, exists := conns[id] + if !exists { + conns[id] = c + c.mu.Lock() + idHash := c.route.idHash + cid := c.cid + rtype := c.route.routeType + if sendDelayedInfo { + cm := compressionModeForInfoProtocol(&opts.Cluster.Compression, c.route.compression) + c.enqueueProto(s.generateRouteInitialInfoJSON(accName, cm, 0, gossipMode)) + } + if c.last.IsZero() { + c.last = time.Now() + } + if acc != nil { + c.acc = acc + } + c.mu.Unlock() + + // Store this route with key being the route id hash + account name + s.storeRouteByHash(idHash+accName, c) + + // Now that we have registered the route, we can remove from the temp map. + s.removeFromTempClients(cid) + + // We don't need to send if the only route is the one we just accepted. + if len(conns) > 1 { + s.forwardNewRouteInfoToKnownServers(info, rtype, didSolicit, gossipMode) + } + + // Send subscription interest + s.sendSubsToRoute(c, -1, accName) + } else { + handleDuplicateRoute(remote, c, true) + } + s.mu.Unlock() + return !exists + } + var remote *client + // That will be the position of the connection in the slice, we initialize + // to -1 to indicate that no space was found. + idx := -1 + // This will be the size (or number of connections) in a given slice. + sz := 0 + // Check if we know about the remote server + conns, exists := s.routes[id] if !exists { - s.routes[c.cid] = c - s.remotes[id] = c + // Now, create a slice for route connections of the size of the pool + // or 1 when not in pool mode. + conns = make([]*client, effectivePoolSize) + // Track this slice for this remote server. + s.routes[id] = conns + // Set the index to info.RoutePoolIdx because if this is a solicited + // route, this value will be 0, which is what we want, otherwise, we + // will use whatever index the remote has chosen. + idx = info.RoutePoolIdx + } else if pool { + // The remote could have done a config reload and increased the pool size. + // It will close the connections before soliciting again, however, if + // on this side, one of the route is not yet fully removed, but the + // first one is, it would accept the new connection (with a greater pool + // size) and we would not go through the phase of `!exists` above creating + // the slice with the right size. So we need to check here and add new empty + // entries to complete the effective pool size. + if n := effectivePoolSize - len(conns); n > 0 { + for range n { + conns = append(conns, nil) + } + s.routes[id] = conns + } + // The remote was found. If this is a non solicited route, we will place + // the connection in the pool at the index given by info.RoutePoolIdx. + // But if there is already one, close this incoming connection as a + // duplicate. + if !didSolicit { + idx = info.RoutePoolIdx + if remote = conns[idx]; remote != nil { + handleDuplicateRoute(remote, c, false) + s.mu.Unlock() + return false + } + // Look if there is a solicited route in the pool. If there is one, + // they should all be, so stop at the first. + if url, rtype, hasSolicited := hasSolicitedRoute(conns); hasSolicited { + upgradeRouteToSolicited(c, url, rtype) + } + } else { + // If we solicit, upgrade to solicited all non-solicited routes that + // we may have registered. + c.mu.Lock() + url := c.route.url + rtype := c.route.routeType + c.mu.Unlock() + for _, r := range conns { + upgradeRouteToSolicited(r, url, rtype) + } + } + // For all cases (solicited and not) we need to count how many connections + // we already have, and for solicited route, we will find a free spot in + // the slice. + for i, r := range conns { + if idx == -1 && r == nil { + idx = i + } else if r != nil { + sz++ + } + } + } else { + remote = conns[0] + } + // If there is a spot, idx will be greater or equal to 0. + if idx >= 0 { c.mu.Lock() c.route.connectURLs = info.ClientConnectURLs c.route.wsConnURLs = info.WSConnectURLs + c.route.poolIdx = idx + rtype := c.route.routeType cid := c.cid - hash := string(c.route.hash) + idHash := c.route.idHash + rHash := c.route.hash + rn := c.route.remoteName + url := c.route.url + if sendDelayedInfo { + cm := compressionModeForInfoProtocol(&opts.Cluster.Compression, c.route.compression) + c.enqueueProto(s.generateRouteInitialInfoJSON(_EMPTY_, cm, idx, gossipMode)) + } + if c.last.IsZero() { + c.last = time.Now() + } c.mu.Unlock() + // With pooling, we keep track of the remote's configured route pool size. + // We do so when adding the connection in the first slot, not when `sz == 1` + // because there could be situations where we have old connections that have + // not yet been removed and so we would not have `sz == `. However, we will + // always have the condition where we are adding the new connection at `idx==0` + // so use that as the condition to store the remote pool size. + if pool && idx == 0 { + if s.remoteRoutePoolSize == nil { + s.remoteRoutePoolSize = make(map[string]int) + } + s.remoteRoutePoolSize[id] = info.RoutePoolSize + } + + // Add to the slice and bump the count of connections for this remote + conns[idx] = c + sz++ + // This boolean will indicate that we are registering the only + // connection in non pooled situation or we stored the very first + // connection for a given remote server. + doOnce := !pool || sz == 1 + if doOnce { + // check to be consistent and future proof. but will be same domain + if s.sameDomain(info.Domain) { + s.nodeToInfo.Store(rHash, nodeInfo{ + name: rn, + version: s.info.Version, + cluster: s.info.Cluster, + domain: info.Domain, + id: id, + tags: nil, + cfg: nil, + stats: nil, + offline: false, + js: info.JetStream, + binarySnapshots: true, // Updated default to true. Versions 2.10.0+ support it. + accountNRG: false, + }) + } + } + // Store this route using the hash as the key - s.routesByHash.Store(hash, c) + if pool { + idHash += strconv.Itoa(idx) + } + s.storeRouteByHash(idHash, c) // Now that we have registered the route, we can remove from the temp map. s.removeFromTempClients(cid) - // we don't need to send if the only route is the one we just accepted. - sendInfo = len(s.routes) > 1 + if doOnce { + // If the INFO contains a Gateway URL, add it to the list for our cluster. + if info.GatewayURL != _EMPTY_ && s.addGatewayURL(info.GatewayURL) { + s.sendAsyncGatewayInfo() + } + + // We don't need to send if the only route is the one we just accepted. + if len(s.routes) > 1 { + s.forwardNewRouteInfoToKnownServers(info, rtype, didSolicit, gossipMode) + } + + // Send info about the known gateways to this route. + s.sendGatewayConfigsToRoute(c) - // If the INFO contains a Gateway URL, add it to the list for our cluster. - if info.GatewayURL != "" && s.addGatewayURL(info.GatewayURL) { - s.sendAsyncGatewayInfo() + // Unless disabled, possibly update the server's INFO protocol + // and send to clients that know how to handle async INFOs. + if !opts.Cluster.NoAdvertise { + s.addConnectURLsAndSendINFOToClients(info.ClientConnectURLs, info.WSConnectURLs) + } + + // Add the remote's leafnodeURL to our list of URLs and send the update + // to all LN connections. (Note that when coming from a route, LeafNodeURLs + // is an array of size 1 max). + if len(info.LeafNodeURLs) == 1 && s.addLeafNodeURL(info.LeafNodeURLs[0]) { + s.sendAsyncLeafNodeInfo() + } } - // Add the remote's leafnodeURL to our list of URLs and send the update - // to all LN connections. (Note that when coming from a route, LeafNodeURLs - // is an array of size 1 max). - if len(info.LeafNodeURLs) == 1 && s.addLeafNodeURL(info.LeafNodeURLs[0]) { - s.sendAsyncLeafNodeInfo() + // Send the subscriptions interest. + s.sendSubsToRoute(c, idx, _EMPTY_) + + // In pool mode, if we did not yet reach the cap, try to connect a new connection, + // but do so only after receiving the first PONG to our PING, which will ensure + // that we have proper authentication. + if pool && didSolicit && sz != effectivePoolSize { + c.mu.Lock() + c.route.startNewRoute = &routeInfo{ + url: url, + rtype: rtype, + gossipMode: gossipMode, + } + c.sendPing() + c.mu.Unlock() } } s.mu.Unlock() - + if pool { + if idx == -1 { + // Was full, so need to close connection + c.Debugf("Route pool size reached, closing extra connection to %q", id) + handleDuplicateRoute(nil, c, true) + return false + } + return true + } + // This is for non-pool mode at this point. if exists { - var r *route + handleDuplicateRoute(remote, c, noReconnectForOldServer) + } - c.mu.Lock() - // upgrade to solicited? - if c.route.didSolicit { - // Make a copy - rs := *c.route - r = &rs - } - // Since this duplicate route is going to be removed, make sure we clear - // c.route.leafnodeURL, otherwise, when processing the disconnect, this - // would cause the leafnode URL for that remote server to be removed - // from our list. - c.route.leafnodeURL = _EMPTY_ - // Same for the route hash otherwise it would be removed from s.routesByHash. - c.route.hash = _EMPTY_ - c.mu.Unlock() + return !exists +} - remote.mu.Lock() - // r will be not nil if c.route.didSolicit was true - if r != nil { - // If we upgrade to solicited, we still want to keep the remote's - // connectURLs. So transfer those. - r.connectURLs = remote.route.connectURLs - r.wsConnURLs = remote.route.wsConnURLs - remote.route = r +func hasSolicitedRoute(conns []*client) (*url.URL, RouteType, bool) { + var url *url.URL + var rtype RouteType + for _, r := range conns { + if r == nil { + continue + } + r.mu.Lock() + if r.route.didSolicit { + url = r.route.url + rtype = r.route.routeType + } + r.mu.Unlock() + if url != nil { + return url, rtype, true } - // This is to mitigate the issue where both sides add the route - // on the opposite connection, and therefore end-up with both - // connections being dropped. - remote.route.retry = true - remote.mu.Unlock() } + return nil, 0, false +} - return !exists, sendInfo +func upgradeRouteToSolicited(r *client, url *url.URL, rtype RouteType) { + if r == nil { + return + } + r.mu.Lock() + if !r.route.didSolicit { + r.route.didSolicit = true + r.route.url = url + } + if rtype == Explicit { + r.route.routeType = Explicit + } + r.mu.Unlock() +} + +func handleDuplicateRoute(remote, c *client, setNoReconnect bool) { + // We used to clear some fields when closing a duplicate connection + // to prevent sending INFO protocols for the remotes to update + // their leafnode/gateway URLs. This is no longer needed since + // removeRoute() now does the right thing of doing that only when + // the closed connection was an added route connection. + c.mu.Lock() + didSolicit := c.route.didSolicit + url := c.route.url + rtype := c.route.routeType + if setNoReconnect { + c.flags.set(noReconnect) + } + c.mu.Unlock() + + if remote == nil { + return + } + + remote.mu.Lock() + if didSolicit && !remote.route.didSolicit { + remote.route.didSolicit = true + remote.route.url = url + } + // The extra route might be an configured explicit route + // so keep the state that the remote was configured. + if rtype == Explicit { + remote.route.routeType = rtype + } + // This is to mitigate the issue where both sides add the route + // on the opposite connection, and therefore end-up with both + // connections being dropped. + remote.route.retry = true + remote.mu.Unlock() } // Import filter check. func (c *client) importFilter(sub *subscription) bool { + if c.perms == nil { + return true + } return c.canImport(string(sub.subject)) } @@ -1533,6 +2525,10 @@ func (s *Server) updateRouteSubscriptionMap(acc *Account, sub *subscription, del return } + if sub.si { + return + } + // Copy to hold outside acc lock. var n int32 var ok bool @@ -1565,8 +2561,9 @@ func (s *Server) updateRouteSubscriptionMap(acc *Account, sub *subscription, del return } - // Create the fast key which will use the subject or 'subjectqueue' for queue subscribers. - key := keyFromSub(sub) + // Create the subscription key which will prevent collisions between regular + // and leaf routed subscriptions. See keyFromSubWithOrigin() for details. + key := keyFromSubWithOrigin(sub) // Decide whether we need to send an update out to all the routes. update := isq @@ -1611,12 +2608,49 @@ func (s *Server) updateRouteSubscriptionMap(acc *Account, sub *subscription, del var _routes [32]*client routes := _routes[:0] - s.mu.Lock() - for _, route := range s.routes { - routes = append(routes, route) + s.mu.RLock() + // The account's routePoolIdx field is set/updated under the server lock + // (but also the account's lock). So we don't need to acquire the account's + // lock here to get the value. + if poolIdx := acc.routePoolIdx; poolIdx < 0 { + if conns, ok := s.accRoutes[acc.Name]; ok { + for _, r := range conns { + routes = append(routes, r) + } + } + if s.routesNoPool > 0 { + // We also need to look for "no pool" remotes (that is, routes to older + // servers or servers that have explicitly disabled pooling). + s.forEachRemote(func(r *client) { + r.mu.Lock() + if r.route.noPool { + routes = append(routes, r) + } + r.mu.Unlock() + }) + } + } else { + // We can't use s.forEachRouteIdx here since we want to check/get the + // "no pool" route ONLY if we don't find a route at the given `poolIdx`. + for _, conns := range s.routes { + if r := conns[poolIdx]; r != nil { + routes = append(routes, r) + } else if s.routesNoPool > 0 { + // Check if we have a "no pool" route at index 0, and if so, it + // means that for this remote, we have a single connection because + // that server does not have pooling. + if r := conns[0]; r != nil { + r.mu.Lock() + if r.route.noPool { + routes = append(routes, r) + } + r.mu.Unlock() + } + } + } } trace := atomic.LoadInt32(&s.logging.trace) == 1 - s.mu.Unlock() + s.mu.RUnlock() // If we are a queue subscriber we need to make sure our updates are serialized from // potential multiple connections. We want to make sure that the order above is preserved @@ -1636,7 +2670,7 @@ func (s *Server) updateRouteSubscriptionMap(acc *Account, sub *subscription, del if ls, ok := lqws[key]; ok && ls == n { acc.mu.Unlock() return - } else { + } else if n > 0 { lqws[key] = n } acc.mu.Unlock() @@ -1659,6 +2693,10 @@ func (s *Server) updateRouteSubscriptionMap(acc *Account, sub *subscription, del // is detected that the server has already been shutdown. // It will also start soliciting explicit routes. func (s *Server) startRouteAcceptLoop() { + if s.isShuttingDown() { + return + } + // Snapshot server options. opts := s.getOpts() @@ -1673,10 +2711,6 @@ func (s *Server) startRouteAcceptLoop() { clusterName := s.ClusterName() s.mu.Lock() - if s.shutdown { - s.mu.Unlock() - return - } s.Noticef("Cluster name is %s", clusterName) if s.isClusterNameDynamic() { s.Warnf("Cluster name was dynamically generated, consider setting one") @@ -1684,6 +2718,7 @@ func (s *Server) startRouteAcceptLoop() { hp := net.JoinHostPort(opts.Cluster.Host, strconv.Itoa(port)) l, e := natsListen("tcp", hp) + s.routeListenerErr = e if e != nil { s.mu.Unlock() s.Fatalf("Error listening on router port: %d - %v", opts.Cluster.Port, e) @@ -1692,17 +2727,6 @@ func (s *Server) startRouteAcceptLoop() { s.Noticef("Listening for route connections on %s", net.JoinHostPort(opts.Cluster.Host, strconv.Itoa(l.Addr().(*net.TCPAddr).Port))) - proto := RouteProtoV2 - // For tests, we want to be able to make this server behave - // as an older server so check this option to see if we should override - if opts.routeProto < 0 { - // We have a private option that allows test to override the route - // protocol. We want this option initial value to be 0, however, - // since original proto is RouteProtoZero, tests call setRouteProtoForTest(), - // which sets as negative value the (desired proto + 1) * -1. - // Here we compute back the real value. - proto = (opts.routeProto * -1) - 1 - } // Check for TLSConfig tlsReq := opts.Cluster.TLSConfig != nil info := Info{ @@ -1714,12 +2738,23 @@ func (s *Server) startRouteAcceptLoop() { TLSRequired: tlsReq, TLSVerify: tlsReq, MaxPayload: s.info.MaxPayload, - Proto: proto, + JetStream: s.info.JetStream, + Proto: s.getServerProto(), GatewayURL: s.getGatewayURL(), Headers: s.supportsHeaders(), Cluster: s.info.Cluster, + Domain: s.info.Domain, Dynamic: s.isClusterNameDynamic(), LNOC: true, + LNOCU: true, + } + // For tests that want to simulate old servers, do not set the compression + // on the INFO protocol if configured with CompressionNotSupported. + if cm := opts.Cluster.Compression.Mode; cm != CompressionNotSupported { + info.Compression = cm + } + if ps := opts.Cluster.PoolSize; ps > 0 { + info.RoutePoolSize = ps } // Set this if only if advertise is not disabled if !opts.Cluster.NoAdvertise { @@ -1751,7 +2786,7 @@ func (s *Server) startRouteAcceptLoop() { s.routeInfo = info // Possibly override Host/Port and set IP based on Cluster.Advertise if err := s.setRouteInfoHostPortAndIP(); err != nil { - s.Fatalf("Error setting route INFO with Cluster.Advertise value of %s, err=%v", s.opts.Cluster.Advertise, err) + s.Fatalf("Error setting route INFO with Cluster.Advertise value of %s, err=%v", opts.Cluster.Advertise, err) l.Close() s.mu.Unlock() return @@ -1781,18 +2816,19 @@ func (s *Server) startRouteAcceptLoop() { } // Start the accept loop in a different go routine. - go s.acceptConnections(l, "Route", func(conn net.Conn) { s.createRoute(conn, nil) }, nil) + go s.acceptConnections(l, "Route", func(conn net.Conn) { s.createRoute(conn, nil, Implicit, gossipDefault, _EMPTY_) }, nil) // Solicit Routes if applicable. This will not block. - s.solicitRoutes(opts.Routes) + s.solicitRoutes(opts.Routes, opts.Cluster.PinnedAccounts) s.mu.Unlock() } // Similar to setInfoHostPortAndGenerateJSON, but for routeInfo. func (s *Server) setRouteInfoHostPortAndIP() error { - if s.opts.Cluster.Advertise != "" { - advHost, advPort, err := parseHostPort(s.opts.Cluster.Advertise, s.opts.Cluster.Port) + opts := s.getOpts() + if opts.Cluster.Advertise != _EMPTY_ { + advHost, advPort, err := parseHostPort(opts.Cluster.Advertise, opts.Cluster.Port) if err != nil { return err } @@ -1800,12 +2836,10 @@ func (s *Server) setRouteInfoHostPortAndIP() error { s.routeInfo.Port = advPort s.routeInfo.IP = fmt.Sprintf("nats-route://%s/", net.JoinHostPort(advHost, strconv.Itoa(advPort))) } else { - s.routeInfo.Host = s.opts.Cluster.Host - s.routeInfo.Port = s.opts.Cluster.Port + s.routeInfo.Host = opts.Cluster.Host + s.routeInfo.Port = opts.Cluster.Port s.routeInfo.IP = "" } - // (re)generate the routeInfoJSON byte array - s.generateRouteInfoJSON() return nil } @@ -1814,7 +2848,7 @@ func (s *Server) setRouteInfoHostPortAndIP() error { func (s *Server) StartRouting(clientListenReady chan struct{}) { defer s.grWG.Done() - // Wait for the client and and leafnode listen ports to be opened, + // Wait for the client and leafnode listen ports to be opened, // and the possible ephemeral ports to be selected. <-clientListenReady @@ -1823,15 +2857,14 @@ func (s *Server) StartRouting(clientListenReady chan struct{}) { } -func (s *Server) reConnectToRoute(rURL *url.URL, rtype RouteType) { - tryForEver := rtype == Explicit +func (s *Server) reConnectToRoute(rURL *url.URL, rtype RouteType, accName string) { // If A connects to B, and B to A (regardless if explicit or // implicit - due to auto-discovery), and if each server first // registers the route on the opposite TCP connection, the // two connections will end-up being closed. // Add some random delay to reduce risk of repeated failures. delay := time.Duration(rand.Intn(100)) * time.Millisecond - if tryForEver { + if rtype == Explicit { delay += DEFAULT_ROUTE_RECONNECT } select { @@ -1840,7 +2873,7 @@ func (s *Server) reConnectToRoute(rURL *url.URL, rtype RouteType) { s.grWG.Done() return } - s.connectToRoute(rURL, tryForEver, false) + s.connectToRoute(rURL, rtype, false, gossipDefault, accName) } // Checks to make sure the route is still valid. @@ -1853,23 +2886,38 @@ func (s *Server) routeStillValid(rURL *url.URL) bool { return false } -func (s *Server) connectToRoute(rURL *url.URL, tryForEver, firstConnect bool) { +func (s *Server) connectToRoute(rURL *url.URL, rtype RouteType, firstConnect bool, gossipMode byte, accName string) { + defer s.grWG.Done() + if rURL == nil { + return + } + // For explicit routes, we will try to connect until we succeed. For implicit + // we will try only based on the number of ConnectRetries optin. + tryForEver := rtype == Explicit + // Snapshot server options. opts := s.getOpts() - defer s.grWG.Done() - const connErrFmt = "Error trying to connect to route (attempt %v): %v" - s.mu.Lock() + s.mu.RLock() resolver := s.routeResolver excludedAddresses := s.routesToSelf - s.mu.Unlock() + s.mu.RUnlock() - attempts := 0 - for s.isRunning() && rURL != nil { - if tryForEver && !s.routeStillValid(rURL) { - return + for attempts := 0; s.isRunning(); { + if tryForEver { + if !s.routeStillValid(rURL) { + return + } + if accName != _EMPTY_ { + s.mu.RLock() + _, valid := s.accRoutes[accName] + s.mu.RUnlock() + if !valid { + return + } + } } var conn net.Conn address, err := s.getRandomIP(resolver, rURL.Host, excludedAddresses) @@ -1911,7 +2959,7 @@ func (s *Server) connectToRoute(rURL *url.URL, tryForEver, firstConnect bool) { // We have a route connection here. // Go ahead and create it and exit this func. - s.createRoute(conn, rURL) + s.createRoute(conn, rURL, rtype, gossipMode, accName) return } } @@ -1922,10 +2970,32 @@ func (c *client) isSolicitedRoute() bool { return c.kind == ROUTER && c.route != nil && c.route.didSolicit } -func (s *Server) solicitRoutes(routes []*url.URL) { +// Save the first hostname found in route URLs. This will be used in gossip mode +// when trying to create a TLS connection by setting the tlsConfig.ServerName. +// Lock is held on entry +func (s *Server) saveRouteTLSName(routes []*url.URL) { + for _, u := range routes { + if s.routeTLSName == _EMPTY_ && net.ParseIP(u.Hostname()) == nil { + s.routeTLSName = u.Hostname() + } + } +} + +// Start connection process to provided routes. Each route connection will +// be started in a dedicated go routine. +// Lock is held on entry +func (s *Server) solicitRoutes(routes []*url.URL, accounts []string) { + s.saveRouteTLSName(routes) for _, r := range routes { route := r - s.startGoRoutine(func() { s.connectToRoute(route, true, true) }) + s.startGoRoutine(func() { s.connectToRoute(route, Explicit, true, gossipDefault, _EMPTY_) }) + } + // Now go over possible per-account routes and create them. + for _, an := range accounts { + for _, r := range routes { + route, accName := r, an + s.startGoRoutine(func() { s.connectToRoute(route, Explicit, true, gossipDefault, accName) }) + } } } @@ -1952,11 +3022,12 @@ func (c *client) processRouteConnect(srv *Server, arg []byte, lang string) error c.closeConnection(WrongGateway) return ErrWrongGateway } - var perms *RoutePermissions - if srv != nil { - perms = srv.getOpts().Cluster.Permissions + + if srv == nil { + return ErrServerNotRunning } + perms := srv.getOpts().Cluster.Permissions clusterName := srv.ClusterName() // If we have a cluster name set, make sure it matches ours. @@ -1968,14 +3039,19 @@ func (c *client) processRouteConnect(srv *Server, arg []byte, lang string) error // We will take on their name since theirs is configured or higher then ours. srv.setClusterName(proto.Cluster) if !proto.Dynamic { - srv.getOpts().Cluster.Name = proto.Cluster + srv.optsMu.Lock() + srv.opts.Cluster.Name = proto.Cluster + srv.optsMu.Unlock() } - srv.removeAllRoutesExcept(c) + c.mu.Lock() + remoteID := c.opts.Name + c.mu.Unlock() + srv.removeAllRoutesExcept(remoteID) shouldReject = false } } if shouldReject { - errTxt := fmt.Sprintf("Rejecting connection, cluster name %q does not match %q", proto.Cluster, srv.info.Cluster) + errTxt := fmt.Sprintf("Rejecting connection, cluster name %q does not match %q", proto.Cluster, clusterName) c.Errorf(errTxt) c.sendErr(errTxt) c.closeConnection(ClusterNameConflict) @@ -1989,6 +3065,7 @@ func (c *client) processRouteConnect(srv *Server, arg []byte, lang string) error c.mu.Lock() c.route.remoteID = c.opts.Name c.route.lnoc = proto.LNOC + c.route.lnocu = proto.LNOCU c.setRoutePermissions(perms) c.headers = supportsHeaders && proto.Headers c.mu.Unlock() @@ -1996,11 +3073,24 @@ func (c *client) processRouteConnect(srv *Server, arg []byte, lang string) error } // Called when we update our cluster name during negotiations with remotes. -func (s *Server) removeAllRoutesExcept(c *client) { +func (s *Server) removeAllRoutesExcept(remoteID string) { s.mu.Lock() - routes := make([]*client, 0, len(s.routes)) - for _, r := range s.routes { - if r != c { + routes := make([]*client, 0, s.numRoutes()) + for rID, conns := range s.routes { + if rID == remoteID { + continue + } + for _, r := range conns { + if r != nil { + routes = append(routes, r) + } + } + } + for _, conns := range s.accRoutes { + for rID, r := range conns { + if rID == remoteID { + continue + } routes = append(routes, r) } } @@ -2012,40 +3102,204 @@ func (s *Server) removeAllRoutesExcept(c *client) { } func (s *Server) removeRoute(c *client) { - var rID string - var lnURL string - var gwURL string - var hash string + s.mu.Lock() + defer s.mu.Unlock() + + var ( + rID string + lnURL string + gwURL string + idHash string + accName string + poolIdx = -1 + connectURLs []string + wsConnectURLs []string + opts = s.getOpts() + rURL *url.URL + noPool bool + rtype RouteType + ) c.mu.Lock() cid := c.cid r := c.route if r != nil { rID = r.remoteID lnURL = r.leafnodeURL - hash = r.hash + idHash = r.idHash gwURL = r.gatewayURL + poolIdx = r.poolIdx + accName = bytesToString(r.accName) + if r.noPool { + s.routesNoPool-- + noPool = true + } + connectURLs = r.connectURLs + wsConnectURLs = r.wsConnURLs + rURL = r.url + rtype = r.routeType } c.mu.Unlock() - s.mu.Lock() - delete(s.routes, cid) - if r != nil { - rc, ok := s.remotes[rID] - // Only delete it if it is us.. - if ok && c == rc { - delete(s.remotes, rID) + if accName != _EMPTY_ { + if conns, ok := s.accRoutes[accName]; ok { + if r := conns[rID]; r == c { + s.removeRouteByHash(idHash + accName) + delete(conns, rID) + // Do not remove or set to nil when all remotes have been + // removed from the map. The configured accounts must always + // be in the accRoutes map and addRoute expects "conns" map + // to be created. + } + } + } + // If this is still -1, it means that it was not added to the routes + // so simply remove from temp clients and we are done. + if poolIdx == -1 || accName != _EMPTY_ { + s.removeFromTempClients(cid) + return + } + if conns, ok := s.routes[rID]; ok { + // If this route was not the one stored, simply remove from the + // temporary map and be done. + if conns[poolIdx] != c { + s.removeFromTempClients(cid) + return } - // Remove the remote's gateway URL from our list and - // send update to inbound Gateway connections. - if gwURL != _EMPTY_ && s.removeGatewayURL(gwURL) { - s.sendAsyncGatewayInfo() + conns[poolIdx] = nil + // Now check if this was the last connection to be removed. + empty := true + for _, c := range conns { + if c != nil { + empty = false + break + } } - // Remove the remote's leafNode URL from - // our list and send update to LN connections. - if lnURL != _EMPTY_ && s.removeLeafNodeURL(lnURL) { - s.sendAsyncLeafNodeInfo() + // This was the last route for this remote. Remove the remote entry + // and possibly send some async INFO protocols regarding gateway + // and leafnode URLs. + if empty { + delete(s.routes, rID) + + // Since this is the last route for this remote, possibly update + // the client connect URLs and send an update to connected + // clients. + if (len(connectURLs) > 0 || len(wsConnectURLs) > 0) && !opts.Cluster.NoAdvertise { + s.removeConnectURLsAndSendINFOToClients(connectURLs, wsConnectURLs) + } + // Remove the remote's gateway URL from our list and + // send update to inbound Gateway connections. + if gwURL != _EMPTY_ && s.removeGatewayURL(gwURL) { + s.sendAsyncGatewayInfo() + } + // Remove the remote's leafNode URL from + // our list and send update to LN connections. + if lnURL != _EMPTY_ && s.removeLeafNodeURL(lnURL) { + s.sendAsyncLeafNodeInfo() + } + // We can remove the configured route pool size of this remote. + delete(s.remoteRoutePoolSize, rID) + // If this server has pooling/pinned accounts and the route for + // this remote was a "no pool" route, attempt to reconnect. + if noPool { + if s.routesPoolSize > 1 { + s.startGoRoutine(func() { s.connectToRoute(rURL, rtype, true, gossipDefault, _EMPTY_) }) + } + if len(opts.Cluster.PinnedAccounts) > 0 { + for _, an := range opts.Cluster.PinnedAccounts { + accName := an + s.startGoRoutine(func() { s.connectToRoute(rURL, rtype, true, gossipDefault, accName) }) + } + } + } + } + // This is for gateway code. Remove this route from a map that uses + // the route hash in combination with the pool index as the key. + if s.routesPoolSize > 1 { + idHash += strconv.Itoa(poolIdx) } - s.routesByHash.Delete(hash) + s.removeRouteByHash(idHash) } s.removeFromTempClients(cid) - s.mu.Unlock() +} + +func (s *Server) isDuplicateServerName(name string) bool { + if name == _EMPTY_ { + return false + } + s.mu.RLock() + defer s.mu.RUnlock() + + if s.info.Name == name { + return true + } + for _, conns := range s.routes { + for _, r := range conns { + if r != nil { + r.mu.Lock() + duplicate := r.route.remoteName == name + r.mu.Unlock() + if duplicate { + return true + } + break + } + } + } + return false +} + +// Goes over each non-nil route connection for all remote servers +// and invokes the function `f`. It does not go over per-account +// routes. +// Server lock is held on entry. +func (s *Server) forEachNonPerAccountRoute(f func(r *client)) { + for _, conns := range s.routes { + for _, r := range conns { + if r != nil { + f(r) + } + } + } +} + +// Goes over each non-nil route connection for all remote servers +// and invokes the function `f`. This also includes the per-account +// routes. +// Server lock is held on entry. +func (s *Server) forEachRoute(f func(r *client)) { + s.forEachNonPerAccountRoute(f) + for _, conns := range s.accRoutes { + for _, r := range conns { + f(r) + } + } +} + +// Goes over each non-nil route connection at the given pool index +// location in the slice and invokes the function `f`. If the +// callback returns `true`, this function moves to the next remote. +// Otherwise, the iteration over removes stops. +// This does not include per-account routes. +// Server lock is held on entry. +func (s *Server) forEachRouteIdx(idx int, f func(r *client) bool) { + for _, conns := range s.routes { + if r := conns[idx]; r != nil { + if !f(r) { + return + } + } + } +} + +// Goes over each remote and for the first non nil route connection, +// invokes the function `f`. +// Server lock is held on entry. +func (s *Server) forEachRemote(f func(r *client)) { + for _, conns := range s.routes { + for _, r := range conns { + if r != nil { + f(r) + break + } + } + } } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sdm.go b/vendor/github.com/nats-io/nats-server/v2/server/sdm.go new file mode 100644 index 0000000..dfb2a75 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/sdm.go @@ -0,0 +1,80 @@ +// Copyright 2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "bytes" + "time" +) + +// SDMMeta holds pending/proposed data for subject delete markers or message removals. +type SDMMeta struct { + totals map[string]uint64 + pending map[uint64]SDMBySeq +} + +// SDMBySeq holds data for a message with a specific sequence. +type SDMBySeq struct { + last bool // Whether the message for this sequence was the last for this subject. + ts int64 // Last timestamp we proposed a removal/sdm. +} + +func newSDMMeta() *SDMMeta { + return &SDMMeta{ + totals: make(map[string]uint64, 1), + pending: make(map[uint64]SDMBySeq, 1), + } +} + +// isSubjectDeleteMarker returns whether the headers indicate this message is a subject delete marker. +// Either it's a usual marker with JSMarkerReason, or it's a KV Purge marker as the KVOperation. +func isSubjectDeleteMarker(hdr []byte) bool { + return len(sliceHeader(JSMarkerReason, hdr)) != 0 || bytes.Equal(sliceHeader(KVOperation, hdr), KVOperationValuePurge) +} + +// empty clears all data. +func (sdm *SDMMeta) empty() { + if sdm == nil { + return + } + clear(sdm.totals) + clear(sdm.pending) +} + +// trackPending caches the given seq and subj and whether it's the last message for that subject. +func (sdm *SDMMeta) trackPending(seq uint64, subj string, last bool) bool { + if p, ok := sdm.pending[seq]; ok { + return p.last + } + sdm.pending[seq] = SDMBySeq{last, time.Now().UnixNano()} + sdm.totals[subj]++ + return last +} + +// removeSeqAndSubject clears the seq and subj from the cache. +func (sdm *SDMMeta) removeSeqAndSubject(seq uint64, subj string) { + if sdm == nil { + return + } + if _, ok := sdm.pending[seq]; ok { + delete(sdm.pending, seq) + if msgs, ok := sdm.totals[subj]; ok { + if msgs <= 1 { + delete(sdm.totals, subj) + } else { + sdm.totals[subj] = msgs - 1 + } + } + } +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sendq.go b/vendor/github.com/nats-io/nats-server/v2/server/sendq.go new file mode 100644 index 0000000..9cde157 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/sendq.go @@ -0,0 +1,118 @@ +// Copyright 2020-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "strconv" + "sync" +) + +type outMsg struct { + subj string + rply string + hdr []byte + msg []byte +} + +type sendq struct { + mu sync.Mutex + q *ipQueue[*outMsg] + s *Server + a *Account +} + +func (s *Server) newSendQ(acc *Account) *sendq { + sq := &sendq{s: s, q: newIPQueue[*outMsg](s, "SendQ"), a: acc} + s.startGoRoutine(sq.internalLoop) + return sq +} + +func (sq *sendq) internalLoop() { + sq.mu.Lock() + s, q := sq.s, sq.q + sq.mu.Unlock() + + defer s.grWG.Done() + + c := s.createInternalSystemClient() + c.registerWithAccount(sq.a) + c.noIcb = true + + defer c.closeConnection(ClientClosed) + + // To optimize for not converting a string to a []byte slice. + var ( + subj [256]byte + rply [256]byte + szb [10]byte + hdb [10]byte + _msg [4096]byte + msg = _msg[:0] + ) + + for s.isRunning() { + select { + case <-s.quitCh: + return + case <-q.ch: + pms := q.pop() + for _, pm := range pms { + c.pa.subject = append(subj[:0], pm.subj...) + c.pa.size = len(pm.msg) + len(pm.hdr) + c.pa.szb = append(szb[:0], strconv.Itoa(c.pa.size)...) + if len(pm.rply) > 0 { + c.pa.reply = append(rply[:0], pm.rply...) + } else { + c.pa.reply = nil + } + msg = msg[:0] + if len(pm.hdr) > 0 { + c.pa.hdr = len(pm.hdr) + c.pa.hdb = append(hdb[:0], strconv.Itoa(c.pa.hdr)...) + msg = append(msg, pm.hdr...) + msg = append(msg, pm.msg...) + msg = append(msg, _CRLF_...) + } else { + c.pa.hdr = -1 + c.pa.hdb = nil + msg = append(msg, pm.msg...) + msg = append(msg, _CRLF_...) + } + c.processInboundClientMsg(msg) + c.pa.szb = nil + outMsgPool.Put(pm) + } + // TODO: should this be in the for-loop instead? + c.flushClients(0) + q.recycle(&pms) + } + } +} + +var outMsgPool = sync.Pool{ + New: func() any { + return &outMsg{} + }, +} + +func (sq *sendq) send(subj, rply string, hdr, msg []byte) { + if sq == nil { + return + } + out := outMsgPool.Get().(*outMsg) + out.subj, out.rply = subj, rply + out.hdr = append(out.hdr[:0], hdr...) + out.msg = append(out.msg[:0], msg...) + sq.q.push(out) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/server.go b/vendor/github.com/nats-io/nats-server/v2/server/server.go index d64cddd..97d173a 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/server.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/server.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,34 +16,40 @@ package server import ( "bytes" "context" + "crypto/fips140" "crypto/tls" "encoding/json" "errors" "flag" "fmt" "io" - "io/ioutil" + "log" "math/rand" "net" "net/http" - - // Allow dynamic profiling. - _ "net/http/pprof" + "net/url" "os" "path" "path/filepath" + "regexp" "runtime" + "runtime/pprof" "strconv" "strings" "sync" "sync/atomic" "time" + // Allow dynamic profiling. + _ "net/http/pprof" + + "expvar" + + "github.com/klauspost/compress/s2" "github.com/nats-io/jwt/v2" + "github.com/nats-io/nats-server/v2/logger" "github.com/nats-io/nkeys" "github.com/nats-io/nuid" - - "github.com/nats-io/nats-server/v2/logger" ) const ( @@ -54,6 +60,49 @@ const ( firstClientPingInterval = 2 * time.Second ) +// These are protocol versions sent between server connections: ROUTER, LEAF and +// GATEWAY. We may have protocol versions that have a meaning only for a certain +// type of connections, but we don't have to have separate enums for that. +// However, it is CRITICAL to not change the order of those constants since they +// are exchanged between servers. When adding a new protocol version, add to the +// end of the list, don't try to group them by connection types. +const ( + // RouteProtoZero is the original Route protocol from 2009. + // http://nats.io/documentation/internals/nats-protocol/ + RouteProtoZero = iota + // RouteProtoInfo signals a route can receive more then the original INFO block. + // This can be used to update remote cluster permissions, etc... + RouteProtoInfo + // RouteProtoV2 is the new route/cluster protocol that provides account support. + RouteProtoV2 + // MsgTraceProto indicates that this server understands distributed message tracing. + MsgTraceProto +) + +// Will return the latest server-to-server protocol versions, unless the +// option to override it is set. +func (s *Server) getServerProto() int { + opts := s.getOpts() + // Initialize with the latest protocol version. + proto := MsgTraceProto + // For tests, we want to be able to make this server behave + // as an older server so check this option to see if we should override. + if opts.overrideProto < 0 { + // The option overrideProto is set to 0 by default (when creating an + // Options structure). Since this is the same value than the original + // proto RouteProtoZero, tests call setServerProtoForTest() with the + // desired protocol level, which sets it as negative value equal to: + // (wantedProto + 1) * -1. Here we compute back the real value. + proto = (opts.overrideProto * -1) - 1 + } + return proto +} + +// Used by tests. +func setServerProtoForTest(wantedProto int) int { + return (wantedProto + 1) * -1 +} + // Info is the information sent to clients, routes, gateways, and leaf nodes, // to help them understand information about this server. type Info struct { @@ -78,14 +127,24 @@ type Info struct { Nonce string `json:"nonce,omitempty"` Cluster string `json:"cluster,omitempty"` Dynamic bool `json:"cluster_dynamic,omitempty"` + Domain string `json:"domain,omitempty"` ClientConnectURLs []string `json:"connect_urls,omitempty"` // Contains URLs a client can connect to. WSConnectURLs []string `json:"ws_connect_urls,omitempty"` // Contains URLs a ws client can connect to. LameDuckMode bool `json:"ldm,omitempty"` + Compression string `json:"compression,omitempty"` // Route Specific - Import *SubjectPermission `json:"import,omitempty"` - Export *SubjectPermission `json:"export,omitempty"` - LNOC bool `json:"lnoc,omitempty"` + Import *SubjectPermission `json:"import,omitempty"` + Export *SubjectPermission `json:"export,omitempty"` + LNOC bool `json:"lnoc,omitempty"` + LNOCU bool `json:"lnocu,omitempty"` + InfoOnConnect bool `json:"info_on_connect,omitempty"` // When true the server will respond to CONNECT with an INFO + ConnectInfo bool `json:"connect_info,omitempty"` // When true this is the server INFO response to CONNECT + RoutePoolSize int `json:"route_pool_size,omitempty"` + RoutePoolIdx int `json:"route_pool_idx,omitempty"` + RouteAccount string `json:"route_account,omitempty"` + RouteAccReqID string `json:"route_acc_add_reqid,omitempty"` + GossipMode byte `json:"gossip_mode,omitempty"` // Gateways Specific Gateway string `json:"gateway,omitempty"` // Name of the origin Gateway (sent by gateway's INFO) @@ -94,65 +153,91 @@ type Info struct { GatewayCmd byte `json:"gateway_cmd,omitempty"` // Command code for the receiving server to know what to do GatewayCmdPayload []byte `json:"gateway_cmd_payload,omitempty"` // Command payload when needed GatewayNRP bool `json:"gateway_nrp,omitempty"` // Uses new $GNR. prefix for mapped replies + GatewayIOM bool `json:"gateway_iom,omitempty"` // Indicate that all accounts will be switched to InterestOnly mode "right away" // LeafNode Specific - LeafNodeURLs []string `json:"leafnode_urls,omitempty"` // LeafNode URLs that the server can reconnect to. + LeafNodeURLs []string `json:"leafnode_urls,omitempty"` // LeafNode URLs that the server can reconnect to. + RemoteAccount string `json:"remote_account,omitempty"` // Lets the other side know the remote account that they bind to. + + XKey string `json:"xkey,omitempty"` // Public server's x25519 key. } // Server is our main struct. type Server struct { + // Fields accessed with atomic operations need to be 64-bit aligned gcid uint64 + // How often user logon fails due to the issuer account not being pinned. + pinnedAccFail uint64 stats - mu sync.Mutex - kp nkeys.KeyPair - prand *rand.Rand - info Info - configFile string - optsMu sync.RWMutex - opts *Options - running bool - shutdown bool - reloading bool - listener net.Listener - gacc *Account - sys *internal - js *jetStream - accounts sync.Map - tmpAccounts sync.Map // Temporarily stores accounts that are being built - activeAccounts int32 - accResolver AccountResolver - clients map[uint64]*client - routes map[uint64]*client - routesByHash sync.Map - hash []byte - remotes map[string]*client - leafs map[uint64]*client - users map[string]*User - nkeys map[string]*NkeyUser - totalClients uint64 - closed *closedRingBuffer - done chan bool - start time.Time - http net.Listener - httpHandler http.Handler - httpBasePath string - profiler net.Listener - httpReqStats map[string]uint64 - routeListener net.Listener - routeInfo Info - routeInfoJSON []byte - routeResolver netResolver - routesToSelf map[string]struct{} - leafNodeListener net.Listener - leafNodeInfo Info - leafNodeInfoJSON []byte - leafURLsMap refCountedUrlSet - leafNodeOpts struct { + scStats + mu sync.RWMutex + reloadMu sync.RWMutex // Write-locked when a config reload is taking place ONLY + kp nkeys.KeyPair + xkp nkeys.KeyPair + xpub string + info Info + configFile string + optsMu sync.RWMutex + opts *Options + running atomic.Bool + shutdown atomic.Bool + listener net.Listener + listenerErr error + gacc *Account + sys *internal + sysAcc atomic.Pointer[Account] + js atomic.Pointer[jetStream] + isMetaLeader atomic.Bool + jsClustered atomic.Bool + accounts sync.Map + tmpAccounts sync.Map // Temporarily stores accounts that are being built + activeAccounts int32 + accResolver AccountResolver + clients map[uint64]*client + routes map[string][]*client + remoteRoutePoolSize map[string]int // Map for remote's configure route pool size + routesPoolSize int // Configured pool size + routesReject bool // During reload, we may want to reject adding routes until some conditions are met + routesNoPool int // Number of routes that don't use pooling (connecting to older server for instance) + accRoutes map[string]map[string]*client // Key is account name, value is key=remoteID/value=route connection + accRouteByHash sync.Map // Key is account name, value is nil or a pool index + accAddedCh chan struct{} + accAddedReqID string + leafs map[uint64]*client + users map[string]*User + nkeys map[string]*NkeyUser + totalClients uint64 + closed *closedRingBuffer + done chan bool + start time.Time + http net.Listener + httpHandler http.Handler + httpBasePath string + profiler net.Listener + httpReqStats map[string]uint64 + routeListener net.Listener + routeListenerErr error + routeInfo Info + routeResolver netResolver + routesToSelf map[string]struct{} + routeTLSName string + leafNodeListener net.Listener + leafNodeListenerErr error + leafNodeInfo Info + leafNodeInfoJSON []byte + leafURLsMap refCountedUrlSet + leafNodeOpts struct { resolver netResolver dialTimeout time.Duration } + leafRemoteCfgs []*leafNodeCfg + leafRemoteAccounts sync.Map + leafNodeEnabled bool + leafDisableConnect bool // Used in test only + leafNoCluster bool // Indicate that this server has only remotes and no cluster defined quitCh chan struct{} + startupComplete chan struct{} shutdownComplete chan struct{} // Tracking Go routines @@ -180,8 +265,9 @@ type Server struct { lastCURLsUpdate int64 // For Gateways - gatewayListener net.Listener // Accept listener - gateway *srvGateway + gatewayListener net.Listener // Accept listener + gatewayListenerErr error + gateway *srvGateway // Used by tests to check that http.Servers do // not set any timeout. @@ -194,6 +280,8 @@ type Server struct { // Trusted public operator keys. trustedKeys []string + // map of trusted keys to operator setting StrictSigningKeyUsage + strictSigningKeyUsage map[string]struct{} // We use this to minimize mem copies for requests to monitoring // endpoint /varz (when it comes from http). @@ -225,15 +313,85 @@ type Server struct { // MQTT structure mqtt srvMQTT + // OCSP monitoring + ocsps []*OCSPMonitor + + // OCSP peer verification (at least one TLS block) + ocspPeerVerify bool + + // OCSP response cache + ocsprc OCSPResponseCache + // exporting account name the importer experienced issues with incompleteAccExporterMap sync.Map // Holds cluster name under different lock for mapping cnMu sync.RWMutex cn string + + // For registering raft nodes with the server. + rnMu sync.RWMutex + raftNodes map[string]RaftNode + + // For mapping from a raft node name back to a server name and cluster. Node has to be in the same domain. + nodeToInfo sync.Map + + // For out of resources to not log errors too fast. + rerrMu sync.Mutex + rerrLast time.Time + + connRateCounter *rateCounter + + // If there is a system account configured, to still support the $G account, + // the server will create a fake user and add it to the list of users. + // Keep track of what that user name is for config reload purposes. + sysAccOnlyNoAuthUser string + + // IPQueues map + ipQueues sync.Map + + // To limit logging frequency + rateLimitLogging sync.Map + rateLimitLoggingCh chan time.Duration + + // Total outstanding catchup bytes in flight. + gcbMu sync.RWMutex + gcbOut int64 + gcbOutMax int64 // Taken from JetStreamMaxCatchup or defaultMaxTotalCatchupOutBytes + // A global chanel to kick out stalled catchup sequences. + gcbKick chan struct{} + + // Total outbound syncRequests + syncOutSem chan struct{} + + // Queue to process JS API requests that come from routes (or gateways) + jsAPIRoutedReqs *ipQueue[*jsAPIRoutedReq] + + // Delayed API responses. + delayedAPIResponses *ipQueue[*delayedAPIResponse] + + // Whether moving NRG traffic into accounts is permitted on this server. + // Controls whether or not the account NRG capability is set in statsz. + // Currently used by unit tests to simulate nodes not supporting account NRG. + accountNRGAllowed atomic.Bool +} + +// For tracking JS nodes. +type nodeInfo struct { + name string + version string + cluster string + domain string + id string + tags jwt.TagList + cfg *JetStreamConfig + stats *JetStreamStats + offline bool + js bool + binarySnapshots bool + accountNRG bool } -// Make sure all are 64bits for atomic use type stats struct { inMsgs int64 outMsgs int64 @@ -242,6 +400,256 @@ type stats struct { slowConsumers int64 } +// scStats includes the total and per connection counters of Slow Consumers. +type scStats struct { + clients atomic.Uint64 + routes atomic.Uint64 + leafs atomic.Uint64 + gateways atomic.Uint64 +} + +// This is used by tests so we can run all server tests with a default route +// or leafnode compression mode. For instance: +// go test -race -v ./server -cluster_compression=fast +var ( + testDefaultClusterCompression string + testDefaultLeafNodeCompression string +) + +// Compression modes. +const ( + CompressionNotSupported = "not supported" + CompressionOff = "off" + CompressionAccept = "accept" + CompressionS2Auto = "s2_auto" + CompressionS2Uncompressed = "s2_uncompressed" + CompressionS2Fast = "s2_fast" + CompressionS2Better = "s2_better" + CompressionS2Best = "s2_best" +) + +// defaultCompressionS2AutoRTTThresholds is the default of RTT thresholds for +// the CompressionS2Auto mode. +var defaultCompressionS2AutoRTTThresholds = []time.Duration{ + // [0..10ms] -> CompressionS2Uncompressed + 10 * time.Millisecond, + // ]10ms..50ms] -> CompressionS2Fast + 50 * time.Millisecond, + // ]50ms..100ms] -> CompressionS2Better + 100 * time.Millisecond, + // ]100ms..] -> CompressionS2Best +} + +// For a given user provided string, matches to one of the compression mode +// constant and updates the provided string to that constant. Returns an +// error if the provided compression mode is not known. +// The parameter `chosenModeForOn` indicates which compression mode to use +// when the user selects "on" (or enabled, true, etc..). This is because +// we may have different defaults depending on where the compression is used. +func validateAndNormalizeCompressionOption(c *CompressionOpts, chosenModeForOn string) error { + if c == nil { + return nil + } + cmtl := strings.ToLower(c.Mode) + // First, check for the "on" case so that we set to the default compression + // mode for that. The other switch/case will finish setup if needed (for + // instance if the default mode is s2Auto). + switch cmtl { + case "on", "enabled", "true": + cmtl = chosenModeForOn + default: + } + // Check (again) with the proper mode. + switch cmtl { + case "not supported", "not_supported": + c.Mode = CompressionNotSupported + case "disabled", "off", "false": + c.Mode = CompressionOff + case "accept": + c.Mode = CompressionAccept + case "auto", "s2_auto": + var rtts []time.Duration + if len(c.RTTThresholds) == 0 { + rtts = defaultCompressionS2AutoRTTThresholds + } else { + for _, n := range c.RTTThresholds { + // Do not error on negative, but simply set to 0 + if n < 0 { + n = 0 + } + // Make sure they are properly ordered. However, it is possible + // to have a "0" anywhere in the list to indicate that this + // compression level should not be used. + if l := len(rtts); l > 0 && n != 0 { + for _, v := range rtts { + if n < v { + return fmt.Errorf("RTT threshold values %v should be in ascending order", c.RTTThresholds) + } + } + } + rtts = append(rtts, n) + } + if len(rtts) > 0 { + // Trim 0 that are at the end. + stop := -1 + for i := len(rtts) - 1; i >= 0; i-- { + if rtts[i] != 0 { + stop = i + break + } + } + rtts = rtts[:stop+1] + } + if len(rtts) > 4 { + // There should be at most values for "uncompressed", "fast", + // "better" and "best" (when some 0 are present). + return fmt.Errorf("compression mode %q should have no more than 4 RTT thresholds: %v", c.Mode, c.RTTThresholds) + } else if len(rtts) == 0 { + // But there should be at least 1 if the user provided the slice. + // We would be here only if it was provided by say with values + // being a single or all zeros. + return fmt.Errorf("compression mode %q requires at least one RTT threshold", c.Mode) + } + } + c.Mode = CompressionS2Auto + c.RTTThresholds = rtts + case "fast", "s2_fast": + c.Mode = CompressionS2Fast + case "better", "s2_better": + c.Mode = CompressionS2Better + case "best", "s2_best": + c.Mode = CompressionS2Best + default: + return fmt.Errorf("unsupported compression mode %q", c.Mode) + } + return nil +} + +// Returns `true` if the compression mode `m` indicates that the server +// will negotiate compression with the remote server, `false` otherwise. +// Note that the provided compression mode is assumed to have been +// normalized and validated. +func needsCompression(m string) bool { + return m != _EMPTY_ && m != CompressionOff && m != CompressionNotSupported +} + +// Compression is asymmetric, meaning that one side can have a different +// compression level than the other. However, we need to check for cases +// when this server `scm` or the remote `rcm` do not support compression +// (say older server, or test to make it behave as it is not), or have +// the compression off. +// Note that `scm` is assumed to not be "off" or "not supported". +func selectCompressionMode(scm, rcm string) (mode string, err error) { + if rcm == CompressionNotSupported || rcm == _EMPTY_ { + return CompressionNotSupported, nil + } + switch rcm { + case CompressionOff: + // If the remote explicitly disables compression, then we won't + // use compression. + return CompressionOff, nil + case CompressionAccept: + // If the remote is ok with compression (but is not initiating it), + // and if we too are in this mode, then it means no compression. + if scm == CompressionAccept { + return CompressionOff, nil + } + // Otherwise use our compression mode. + return scm, nil + case CompressionS2Auto, CompressionS2Uncompressed, CompressionS2Fast, CompressionS2Better, CompressionS2Best: + // This case is here to make sure that if we don't recognize a + // compression setting, we error out. + if scm == CompressionAccept { + // If our compression mode is "accept", then we will use the remote + // compression mode, except if it is "auto", in which case we will + // default to "fast". This is not a configuration (auto in one + // side and accept in the other) that would be recommended. + if rcm == CompressionS2Auto { + return CompressionS2Fast, nil + } + // Use their compression mode. + return rcm, nil + } + // Otherwise use our compression mode. + return scm, nil + default: + return _EMPTY_, fmt.Errorf("unsupported route compression mode %q", rcm) + } +} + +// If the configured compression mode is "auto" then will return that, +// otherwise will return the given `cm` compression mode. +func compressionModeForInfoProtocol(co *CompressionOpts, cm string) string { + if co.Mode == CompressionS2Auto { + return CompressionS2Auto + } + return cm +} + +// Given a connection RTT and a list of thresholds durations, this +// function will return an S2 compression level such as "uncompressed", +// "fast", "better" or "best". For instance, with the following slice: +// [5ms, 10ms, 15ms, 20ms], a RTT of up to 5ms will result +// in the compression level "uncompressed", ]5ms..10ms] will result in +// "fast" compression, etc.. +// However, the 0 value allows for disabling of some compression levels. +// For instance, the following slice: [0, 0, 20, 30] means that a RTT of +// [0..20ms] would result in the "better" compression - effectively disabling +// the use of "uncompressed" and "fast", then anything above 20ms would +// result in the use of "best" level (the 30 in the list has no effect +// and the list could have been simplified to [0, 0, 20]). +func selectS2AutoModeBasedOnRTT(rtt time.Duration, rttThresholds []time.Duration) string { + var idx int + var found bool + for i, d := range rttThresholds { + if rtt <= d { + idx = i + found = true + break + } + } + if !found { + // If we did not find but we have all levels, then use "best", + // otherwise use the last one in array. + if l := len(rttThresholds); l >= 3 { + idx = 3 + } else { + idx = l - 1 + } + } + switch idx { + case 0: + return CompressionS2Uncompressed + case 1: + return CompressionS2Fast + case 2: + return CompressionS2Better + } + return CompressionS2Best +} + +// Returns an array of s2 WriterOption based on the route compression mode. +// So far we return a single option, but this way we can call s2.NewWriter() +// with a nil []s2.WriterOption, but not with a nil s2.WriterOption, so +// this is more versatile. +func s2WriterOptions(cm string) []s2.WriterOption { + _opts := [2]s2.WriterOption{} + opts := append( + _opts[:0], + s2.WriterConcurrency(1), // Stop asynchronous flushing in separate goroutines + ) + switch cm { + case CompressionS2Uncompressed: + return append(opts, s2.WriterUncompressed()) + case CompressionS2Best: + return append(opts, s2.WriterBestCompression()) + case CompressionS2Better: + return append(opts, s2.WriterBetterCompression()) + default: + return nil + } +} + // New will setup a new server struct after parsing the options. // DEPRECATED: Use NewServer(opts) func New(opts *Options) *Server { @@ -251,6 +659,8 @@ func New(opts *Options) *Server { // NewServer will setup a new server struct after parsing the options. // Could return an error if options can not be validated. +// The provided Options type should not be re-used afterwards. +// Either use Options.Clone() to pass a copy, or make a new one. func NewServer(opts *Options) (*Server, error) { setBaselineOptions(opts) @@ -258,12 +668,20 @@ func NewServer(opts *Options) (*Server, error) { tlsReq := opts.TLSConfig != nil verify := (tlsReq && opts.TLSConfig.ClientAuth == tls.RequireAndVerifyClientCert) - // Created server's nkey identity. + // Create our server's nkey identity. kp, _ := nkeys.CreateServer() pub, _ := kp.PublicKey() + // Create an xkey for encrypting messages from this server. + var xkp nkeys.KeyPair + var xpub string + if !fips140.Enabled() { + xkp, _ = nkeys.CreateCurveKeys() + xpub, _ = xkp.PublicKey() + } + serverName := pub - if opts.ServerName != "" { + if opts.ServerName != _EMPTY_ { serverName = opts.ServerName } @@ -279,6 +697,7 @@ func NewServer(opts *Options) (*Server, error) { info := Info{ ID: pub, + XKey: xpub, Version: VERSION, Proto: PROTO, GitCommit: gitCommit, @@ -293,6 +712,7 @@ func NewServer(opts *Options) (*Server, error) { JetStream: opts.JetStream, Headers: !opts.NoHeaderSupport, Cluster: opts.Cluster.Name, + Domain: opts.JetStreamDomain, } if tlsReq && !info.TLSRequired { @@ -302,18 +722,41 @@ func NewServer(opts *Options) (*Server, error) { now := time.Now() s := &Server{ - kp: kp, - configFile: opts.ConfigFile, - info: info, - prand: rand.New(rand.NewSource(time.Now().UnixNano())), - opts: opts, - done: make(chan bool, 1), - start: now, - configTime: now, - gwLeafSubs: NewSublistWithCache(), - httpBasePath: httpBasePath, - eventIds: nuid.New(), - routesToSelf: make(map[string]struct{}), + kp: kp, + xkp: xkp, + xpub: xpub, + configFile: opts.ConfigFile, + info: info, + opts: opts, + done: make(chan bool, 1), + start: now, + configTime: now, + gwLeafSubs: NewSublistWithCache(), + httpBasePath: httpBasePath, + eventIds: nuid.New(), + routesToSelf: make(map[string]struct{}), + httpReqStats: make(map[string]uint64), // Used to track HTTP requests + rateLimitLoggingCh: make(chan time.Duration, 1), + leafNodeEnabled: opts.LeafNode.Port != 0 || len(opts.LeafNode.Remotes) > 0, + syncOutSem: make(chan struct{}, maxConcurrentSyncRequests), + } + + // Delayed API response queue. Create regardless if JetStream is configured + // or not (since it can be enabled/disabled with config reload, we want this + // queue to exist at all times). + s.delayedAPIResponses = newIPQueue[*delayedAPIResponse](s, "delayed API responses") + + // By default we'll allow account NRG. + s.accountNRGAllowed.Store(true) + + // Fill up the maximum in flight syncRequests for this server. + // Used in JetStream catchup semantics. + for i := 0; i < maxConcurrentSyncRequests; i++ { + s.syncOutSem <- struct{}{} + } + + if opts.TLSRateLimit > 0 { + s.connRateCounter = newRateCounter(opts.tlsConfigOpts.RateLimit) } // Trusted root operator keys. @@ -321,9 +764,42 @@ func NewServer(opts *Options) (*Server, error) { return nil, fmt.Errorf("Error processing trusted operator keys") } + // If we have solicited leafnodes but no clustering and no clustername. + // However we may need a stable clustername so use the server name. + if len(opts.LeafNode.Remotes) > 0 && opts.Cluster.Port == 0 && opts.Cluster.Name == _EMPTY_ { + s.leafNoCluster = true + opts.Cluster.Name = opts.ServerName + } + + if opts.Cluster.Name != _EMPTY_ { + // Also place into mapping cn with cnMu lock. + s.cnMu.Lock() + s.cn = opts.Cluster.Name + s.cnMu.Unlock() + } + s.mu.Lock() defer s.mu.Unlock() + // Place ourselves in the JetStream nodeInfo if needed. + if opts.JetStream { + ourNode := getHash(serverName) + s.nodeToInfo.Store(ourNode, nodeInfo{ + name: serverName, + version: VERSION, + cluster: opts.Cluster.Name, + domain: opts.JetStreamDomain, + id: info.ID, + tags: opts.Tags, + cfg: &JetStreamConfig{MaxMemory: opts.JetStreamMaxMemory, MaxStore: opts.JetStreamMaxStore, CompressOK: true}, + stats: nil, + offline: false, + js: true, + binarySnapshots: true, + accountNRG: true, + }) + } + s.routeResolver = opts.Cluster.resolver if s.routeResolver == nil { s.routeResolver = net.DefaultResolver @@ -337,6 +813,12 @@ func NewServer(opts *Options) (*Server, error) { // Ensure that non-exported options (used in tests) are properly set. s.setLeafNodeNonExportedOptions() + // Setup OCSP Stapling and OCSP Peer. This will abort server from starting if there + // are no valid staples and OCSP Stapling policy is set to Always or MustStaple. + if err := s.enableOCSP(); err != nil { + return nil, err + } + // Call this even if there is no gateway defined. It will // initialize the structure so we don't have to check for // it to be nil or not in various places in the code. @@ -345,8 +827,11 @@ func NewServer(opts *Options) (*Server, error) { } // If we have a cluster definition but do not have a cluster name, create one. - if opts.Cluster.Port != 0 && opts.Cluster.Name == "" { + if opts.Cluster.Port != 0 && opts.Cluster.Name == _EMPTY_ { s.info.Cluster = nuid.Next() + } else if opts.Cluster.Name != _EMPTY_ { + // Likewise here if we have a cluster name set. + s.info.Cluster = opts.Cluster.Name } // This is normally done in the AcceptLoop, once the @@ -366,8 +851,7 @@ func NewServer(opts *Options) (*Server, error) { s.grTmpClients = make(map[uint64]*client) // For tracking routes and their remote ids - s.routes = make(map[uint64]*client) - s.remotes = make(map[string]*client) + s.initRouteStructures(opts) // For tracking leaf nodes. s.leafs = make(map[uint64]*client) @@ -375,6 +859,11 @@ func NewServer(opts *Options) (*Server, error) { // Used to kick out all go routines possibly waiting on server // to shutdown. s.quitCh = make(chan struct{}) + + // Closed when startup is complete. ReadyForConnections() will block on + // this before checking the presence of listening sockets. + s.startupComplete = make(chan struct{}) + // Closed when Shutdown() is complete. Allows WaitForShutdown() to block // waiting for complete shutdown. s.shutdownComplete = make(chan struct{}) @@ -386,34 +875,36 @@ func NewServer(opts *Options) (*Server, error) { // If there is an URL account resolver, do basic test to see if anyone is home. if ar := opts.AccountResolver; ar != nil { if ur, ok := ar.(*URLAccResolver); ok { - if _, err := ur.Fetch(""); err != nil { + if _, err := ur.Fetch(_EMPTY_); err != nil { return nil, err } } } // For other resolver: // In operator mode, when the account resolver depends on an external system and - // the system account can't fetched, inject a temporary one. + // the system account can't be fetched, inject a temporary one. if ar := s.accResolver; len(opts.TrustedOperators) == 1 && ar != nil && opts.SystemAccount != _EMPTY_ && opts.SystemAccount != DEFAULT_SYSTEM_ACCOUNT { if _, ok := ar.(*MemAccResolver); !ok { s.mu.Unlock() var a *Account // perform direct lookup to avoid warning trace - if _, err := fetchAccount(ar, s.opts.SystemAccount); err == nil { - a, _ = s.fetchAccount(s.opts.SystemAccount) + if _, err := fetchAccount(ar, opts.SystemAccount); err == nil { + a, _ = s.lookupAccount(opts.SystemAccount) } s.mu.Lock() if a == nil { - sac := NewAccount(s.opts.SystemAccount) + sac := NewAccount(opts.SystemAccount) sac.Issuer = opts.TrustedOperators[0].Issuer + sac.signingKeys = map[string]jwt.Scope{} + sac.signingKeys[opts.SystemAccount] = nil s.registerAccountNoLock(sac) } } } // For tracking accounts - if err := s.configureAccounts(); err != nil { + if _, err := s.configureAccounts(false); err != nil { return nil, err } @@ -426,11 +917,49 @@ func NewServer(opts *Options) (*Server, error) { return s, nil } +// Initializes route structures based on pooling and/or per-account routes. +// +// Server lock is held on entry +func (s *Server) initRouteStructures(opts *Options) { + s.routes = make(map[string][]*client) + if ps := opts.Cluster.PoolSize; ps > 0 { + s.routesPoolSize = ps + } else { + s.routesPoolSize = 1 + } + // If we have per-account routes, we create accRoutes and initialize it + // with nil values. The presence of an account as the key will allow us + // to know if a given account is supposed to have dedicated routes. + if l := len(opts.Cluster.PinnedAccounts); l > 0 { + s.accRoutes = make(map[string]map[string]*client, l) + for _, acc := range opts.Cluster.PinnedAccounts { + s.accRoutes[acc] = make(map[string]*client) + } + } +} + +func (s *Server) logRejectedTLSConns() { + defer s.grWG.Done() + t := time.NewTicker(time.Second) + defer t.Stop() + for { + select { + case <-s.quitCh: + return + case <-t.C: + blocked := s.connRateCounter.countBlocked() + if blocked > 0 { + s.Warnf("Rejected %d connections due to TLS rate limiting", blocked) + } + } + } +} + // clusterName returns our cluster name which could be dynamic. func (s *Server) ClusterName() string { - s.mu.Lock() + s.mu.RLock() cn := s.info.Cluster - s.mu.Unlock() + s.mu.RUnlock() return cn } @@ -453,8 +982,6 @@ func (s *Server) setClusterName(name string) { s.info.Cluster = name s.routeInfo.Cluster = name - // Regenerate the info byte array - s.generateRouteInfoJSON() // Need to close solicited leaf nodes. The close has to be done outside of the server lock. var leafs []*client for _, c := range s.leafs { @@ -482,30 +1009,91 @@ func (s *Server) setClusterName(name string) { // Return whether the cluster name is dynamic. func (s *Server) isClusterNameDynamic() bool { - return s.getOpts().Cluster.Name == "" + // We need to lock the whole "Cluster.Name" check and not use s.getOpts() + // because otherwise this could cause a data race with setting the name in + // route.go's processRouteConnect(). + s.optsMu.RLock() + dynamic := s.opts.Cluster.Name == _EMPTY_ + s.optsMu.RUnlock() + return dynamic +} + +// Returns our configured serverName. +func (s *Server) serverName() string { + return s.getOpts().ServerName } -// ClientURL returns the URL used to connect clients. Helpful in testing -// when we designate a random client port (-1). +// ClientURL returns the URL used to connect clients. +// Helpful in tests and with in-process servers using a random client port (-1). func (s *Server) ClientURL() string { // FIXME(dlc) - should we add in user and pass if defined single? opts := s.getOpts() - scheme := "nats://" + var u url.URL + u.Scheme = "nats" if opts.TLSConfig != nil { - scheme = "tls://" + u.Scheme = "tls" + } + u.Host = net.JoinHostPort(opts.Host, fmt.Sprintf("%d", opts.Port)) + return u.String() +} + +// WebsocketURL returns the URL used to connect websocket clients. +// Helpful in tests and with in-process servers using a random websocket port (-1). +func (s *Server) WebsocketURL() string { + opts := s.getOpts() + var u url.URL + u.Scheme = "ws" + if opts.Websocket.TLSConfig != nil { + u.Scheme = "wss" } - return fmt.Sprintf("%s%s:%d", scheme, opts.Host, opts.Port) + u.Host = net.JoinHostPort(opts.Websocket.Host, fmt.Sprintf("%d", opts.Websocket.Port)) + return u.String() } -func validateClusterName(o *Options) error { +func validateCluster(o *Options) error { + if o.Cluster.Name != _EMPTY_ && strings.Contains(o.Cluster.Name, " ") { + return ErrClusterNameHasSpaces + } + if o.Cluster.Compression.Mode != _EMPTY_ { + if err := validateAndNormalizeCompressionOption(&o.Cluster.Compression, CompressionS2Fast); err != nil { + return err + } + } + if err := validatePinnedCerts(o.Cluster.TLSPinnedCerts); err != nil { + return fmt.Errorf("cluster: %v", err) + } // Check that cluster name if defined matches any gateway name. - if o.Gateway.Name != "" && o.Gateway.Name != o.Cluster.Name { - if o.Cluster.Name != "" { + // Note that we have already verified that the gateway name does not have spaces. + if o.Gateway.Name != _EMPTY_ && o.Gateway.Name != o.Cluster.Name { + if o.Cluster.Name != _EMPTY_ { return ErrClusterNameConfigConflict } // Set this here so we do not consider it dynamic. o.Cluster.Name = o.Gateway.Name } + if l := len(o.Cluster.PinnedAccounts); l > 0 { + if o.Cluster.PoolSize < 0 { + return fmt.Errorf("pool_size cannot be negative if pinned accounts are specified") + } + m := make(map[string]struct{}, l) + for _, a := range o.Cluster.PinnedAccounts { + if _, exists := m[a]; exists { + return fmt.Errorf("found duplicate account name %q in pinned accounts list %q", a, o.Cluster.PinnedAccounts) + } + m[a] = struct{}{} + } + } + return nil +} + +func validatePinnedCerts(pinned PinnedCertSet) error { + re := regexp.MustCompile("^[a-f0-9]{64}$") + for certId := range pinned { + entry := strings.ToLower(certId) + if !re.MatchString(entry) { + return fmt.Errorf("error parsing 'pinned_certs' key %s does not look like lower case hex-encoded sha256 of DER encoded SubjectPublicKeyInfo", entry) + } + } return nil } @@ -514,6 +1102,13 @@ func validateOptions(o *Options) error { return fmt.Errorf("lame duck grace period (%v) should be strictly lower than lame duck duration (%v)", o.LameDuckGracePeriod, o.LameDuckDuration) } + if int64(o.MaxPayload) > o.MaxPending { + return fmt.Errorf("max_payload (%v) cannot be higher than max_pending (%v)", + o.MaxPayload, o.MaxPending) + } + if o.ServerName != _EMPTY_ && strings.Contains(o.ServerName, " ") { + return errors.New("server name cannot contain spaces") + } // Check that the trust configuration is correct. if err := validateTrustedOperators(o); err != nil { return err @@ -533,12 +1128,15 @@ func validateOptions(o *Options) error { return err } // Check that cluster name if defined matches any gateway name. - if err := validateClusterName(o); err != nil { + if err := validateCluster(o); err != nil { return err } if err := validateMQTTOptions(o); err != nil { return err } + if err := validateJetStreamOptions(o); err != nil { + return err + } // Finally check websocket options. return validateWebsocketOptions(o) } @@ -557,42 +1155,131 @@ func (s *Server) setOpts(opts *Options) { } func (s *Server) globalAccount() *Account { - s.mu.Lock() + s.mu.RLock() gacc := s.gacc - s.mu.Unlock() + s.mu.RUnlock() return gacc } -// Used to setup Accounts. -// Lock is held upon entry. -func (s *Server) configureAccounts() error { +// Used to setup or update Accounts. +// Returns a map that indicates which accounts have had their stream imports +// changed (in case of an update in configuration reload). +// Lock is held upon entry, but will be released/reacquired in this function. +func (s *Server) configureAccounts(reloading bool) (map[string]struct{}, error) { + awcsti := make(map[string]struct{}) + // Create the global account. if s.gacc == nil { s.gacc = NewAccount(globalAccountName) s.registerAccountNoLock(s.gacc) } - opts := s.opts + opts := s.getOpts() + + // We need to track service imports since we can not swap them out (unsub and re-sub) + // until the proper server struct accounts have been swapped in properly. Doing it in + // place could lead to data loss or server panic since account under new si has no real + // account and hence no sublist, so will panic on inbound message. + siMap := make(map[*Account][][]byte) // Check opts and walk through them. We need to copy them here // so that we do not keep a real one sitting in the options. - for _, acc := range s.opts.Accounts { + for _, acc := range opts.Accounts { var a *Account - if acc.Name == globalAccountName { - a = s.gacc - } else { - a = acc.shallowCopy() + create := true + // For the global account, we want to skip the reload process + // and fall back into the "create" case which will in that + // case really be just an update (shallowCopy will make sure + // that mappings are copied over). + if reloading && acc.Name != globalAccountName { + if ai, ok := s.accounts.Load(acc.Name); ok { + a = ai.(*Account) + // Before updating the account, check if stream imports have changed. + if !a.checkStreamImportsEqual(acc) { + awcsti[acc.Name] = struct{}{} + } + a.mu.Lock() + // Collect the sids for the service imports since we are going to + // replace with new ones. + var sids [][]byte + for _, sis := range a.imports.services { + for _, si := range sis { + if si.sid != nil { + sids = append(sids, si.sid) + } + } + } + // Setup to process later if needed. + if len(sids) > 0 || len(acc.imports.services) > 0 { + siMap[a] = sids + } + + // Now reset all export/imports fields since they are going to be + // filled in shallowCopy() + a.imports.streams, a.imports.services = nil, nil + a.exports.streams, a.exports.services = nil, nil + // We call shallowCopy from the account `acc` (the one in Options) + // and pass `a` (our existing account) to get it updated. + acc.shallowCopy(a) + a.mu.Unlock() + create = false + } + } + // Track old mappings if global account. + var oldGMappings []*mapping + if create { + if acc.Name == globalAccountName { + a = s.gacc + a.mu.Lock() + oldGMappings = append(oldGMappings, a.mappings...) + a.mu.Unlock() + } else { + a = NewAccount(acc.Name) + } + // Locking matters in the case of an update of the global account + a.mu.Lock() + acc.shallowCopy(a) + a.mu.Unlock() + // Will be a no-op in case of the global account since it is already registered. + s.registerAccountNoLock(a) + } + + // The `acc` account is stored in options, not in the server, and these can be cleared. + acc.sl, acc.clients, acc.mappings = nil, nil, nil + + // Check here if we have been reloaded and we have a global account with mappings that may have changed. + // If we have leafnodes they need to be updated. + if reloading && a == s.gacc { + a.mu.Lock() + mappings := make(map[string]*mapping) + if len(a.mappings) > 0 && a.nleafs > 0 { + for _, em := range a.mappings { + mappings[em.src] = em + } + } + a.mu.Unlock() + if len(mappings) > 0 || len(oldGMappings) > 0 { + a.lmu.RLock() + for _, lc := range a.lleafs { + for _, em := range mappings { + lc.forceAddToSmap(em.src) + } + // Remove any old ones if needed. + for _, em := range oldGMappings { + // Only remove if not in the new ones. + if _, ok := mappings[em.src]; !ok { + lc.forceRemoveFromSmap(em.src) + } + } + } + a.lmu.RUnlock() + } } - if acc.hasMappings() { - // For now just move and wipe from opts.Accounts version. - a.mappings = acc.mappings - acc.mappings = nil - // We use this for selecting between multiple weighted destinations. - a.prand = rand.New(rand.NewSource(time.Now().UnixNano())) + + // If we see an account defined using $SYS we will make sure that is set as system account. + if acc.Name == DEFAULT_SYSTEM_ACCOUNT && opts.SystemAccount == _EMPTY_ { + opts.SystemAccount = DEFAULT_SYSTEM_ACCOUNT } - acc.sl = nil - acc.clients = nil - s.registerAccountNoLock(a) } // Now that we have this we need to remap any referenced accounts in @@ -606,8 +1293,11 @@ func (s *Server) configureAccounts() error { ea.approved[sub] = acc } } - s.accounts.Range(func(k, v interface{}) bool { + var numAccounts int + s.accounts.Range(func(k, v any) bool { + numAccounts++ acc := v.(*Account) + acc.mu.Lock() // Exports for _, se := range acc.exports.streams { if se != nil { @@ -631,22 +1321,52 @@ func (s *Server) configureAccounts() error { si.acc = v.(*Account) } } - for _, si := range acc.imports.services { - if v, ok := s.accounts.Load(si.acc.Name); ok { - si.acc = v.(*Account) - si.se = si.acc.getServiceExport(si.to) + for _, sis := range acc.imports.services { + for _, si := range sis { + if v, ok := s.accounts.Load(si.acc.Name); ok { + si.acc = v.(*Account) + + // It is possible to allow for latency tracking inside your + // own account, so lock only when not the same account. + if si.acc == acc { + si.se = si.acc.getServiceExport(si.to) + continue + } + si.acc.mu.RLock() + si.se = si.acc.getServiceExport(si.to) + si.acc.mu.RUnlock() + } } } // Make sure the subs are running, but only if not reloading. - if len(acc.imports.services) > 0 && acc.ic == nil && !s.reloading { + if len(acc.imports.services) > 0 && acc.ic == nil && !reloading { acc.ic = s.createInternalAccountClient() acc.ic.acc = acc + // Need to release locks to invoke this function. + acc.mu.Unlock() + s.mu.Unlock() acc.addAllServiceImportSubs() + s.mu.Lock() + acc.mu.Lock() } acc.updated = time.Now() + acc.mu.Unlock() return true }) + // Check if we need to process service imports pending from above. + // This processing needs to be after we swap in the real accounts above. + for acc, sids := range siMap { + c := acc.ic + for _, sid := range sids { + c.processUnsub(sid) + } + acc.addAllServiceImportSubs() + s.mu.Unlock() + s.registerSystemImports(acc) + s.mu.Lock() + } + // Set the system account if it was configured. // Otherwise create a default one. if opts.SystemAccount != _EMPTY_ { @@ -657,21 +1377,50 @@ func (s *Server) configureAccounts() error { if err == nil && s.sys != nil && acc != s.sys.account { // sys.account.clients (including internal client)/respmap/etc... are transferred separately s.sys.account = acc - s.mu.Unlock() - // acquires server lock separately - s.addSystemAccountExports(acc) - s.mu.Lock() + s.sysAcc.Store(acc) } if err != nil { - return fmt.Errorf("error resolving system account: %v", err) + return awcsti, fmt.Errorf("error resolving system account: %v", err) + } + + // If we have defined a system account here check to see if its just us and the $G account. + // We would do this to add user/pass to the system account. If this is the case add in + // no-auth-user for $G. + // Only do this if non-operator mode and we did not have an authorization block defined. + if len(opts.TrustedOperators) == 0 && numAccounts == 2 && opts.NoAuthUser == _EMPTY_ && !opts.authBlockDefined { + // If we come here from config reload, let's not recreate the fake user name otherwise + // it will cause currently clients to be disconnected. + uname := s.sysAccOnlyNoAuthUser + if uname == _EMPTY_ { + // Create a unique name so we do not collide. + var b [8]byte + rn := rand.Int63() + for i, l := 0, rn; i < len(b); i++ { + b[i] = digits[l%base] + l /= base + } + uname = fmt.Sprintf("nats-%s", b[:]) + s.sysAccOnlyNoAuthUser = uname + } + opts.Users = append(opts.Users, &User{Username: uname, Password: uname[6:], Account: s.gacc}) + opts.NoAuthUser = uname } } - return nil + // Add any required exports from system account. + if s.sys != nil { + sysAcc := s.sys.account + s.mu.Unlock() + s.addSystemAccountExports(sysAcc) + s.mu.Lock() + } + + return awcsti, nil } // Setup the account resolver. For memory resolver, make sure the JWTs are // properly formed but do not enforce expiration etc. +// Lock is held on entry, but may be released/reacquired during this call. func (s *Server) configureResolver() error { opts := s.getOpts() s.accResolver = opts.AccountResolver @@ -686,7 +1435,12 @@ func (s *Server) configureResolver() error { } } if len(opts.resolverPreloads) > 0 { - if s.accResolver.IsReadOnly() { + // Lock ordering is account resolver -> server, so we need to release + // the lock and reacquire it when done with account resolver's calls. + ar := s.accResolver + s.mu.Unlock() + defer s.mu.Lock() + if ar.IsReadOnly() { return fmt.Errorf("resolver preloads only available for writeable resolver types MEM/DIR/CACHE_DIR") } for k, v := range opts.resolverPreloads { @@ -694,7 +1448,7 @@ func (s *Server) configureResolver() error { if err != nil { return fmt.Errorf("preload account error for %q: %v", k, err) } - s.accResolver.Store(k, v) + ar.Store(k, v) } } } @@ -710,6 +1464,7 @@ func (s *Server) checkResolvePreloads() { claims, err := jwt.DecodeAccountClaims(v) if err != nil { s.Errorf("Preloaded account [%s] not valid", k) + continue } // Check if it is expired. vr := jwt.CreateValidationResults() @@ -723,22 +1478,16 @@ func (s *Server) checkResolvePreloads() { } } -func (s *Server) generateRouteInfoJSON() { - b, _ := json.Marshal(s.routeInfo) - pcs := [][]byte{[]byte("INFO"), b, []byte(CR_LF)} - s.routeInfoJSON = bytes.Join(pcs, []byte(" ")) -} - // Determines if we are in pre NATS 2.0 setup with no accounts. func (s *Server) globalAccountOnly() bool { var hasOthers bool - if len(s.trustedKeys) > 0 { + if s.trustedKeys != nil { return false } - s.mu.Lock() - s.accounts.Range(func(k, v interface{}) bool { + s.mu.RLock() + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) // Ignore global and system if acc == s.gacc || (s.sys != nil && acc == s.sys.account) { @@ -747,24 +1496,40 @@ func (s *Server) globalAccountOnly() bool { hasOthers = true return false }) - s.mu.Unlock() + s.mu.RUnlock() return !hasOthers } -// Determines if this server is in standalone mode, meaning no routes or gateways or leafnodes. +// Determines if this server is in standalone mode, meaning no routes or gateways. func (s *Server) standAloneMode() bool { opts := s.getOpts() - return opts.Cluster.Port == 0 && opts.LeafNode.Port == 0 && opts.Gateway.Port == 0 + return opts.Cluster.Port == 0 && opts.Gateway.Port == 0 +} + +func (s *Server) configuredRoutes() int { + return len(s.getOpts().Routes) +} + +// activePeers is used in bootstrapping raft groups like the JetStream meta controller. +func (s *Server) ActivePeers() (peers []string) { + s.nodeToInfo.Range(func(k, v any) bool { + si := v.(nodeInfo) + if !si.offline { + peers = append(peers, k.(string)) + } + return true + }) + return peers } // isTrustedIssuer will check that the issuer is a trusted public key. // This is used to make sure an account was signed by a trusted operator. func (s *Server) isTrustedIssuer(issuer string) bool { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() // If we are not running in trusted mode and there is no issuer, that is ok. - if len(s.trustedKeys) == 0 && issuer == "" { + if s.trustedKeys == nil && issuer == _EMPTY_ { return true } for _, tk := range s.trustedKeys { @@ -778,15 +1543,25 @@ func (s *Server) isTrustedIssuer(issuer string) bool { // processTrustedKeys will process binary stamped and // options-based trusted nkeys. Returns success. func (s *Server) processTrustedKeys() bool { - if trustedKeys != "" && !s.initStampedTrustedKeys() { + s.strictSigningKeyUsage = map[string]struct{}{} + opts := s.getOpts() + if trustedKeys != _EMPTY_ && !s.initStampedTrustedKeys() { return false - } else if s.opts.TrustedKeys != nil { - for _, key := range s.opts.TrustedKeys { + } else if opts.TrustedKeys != nil { + for _, key := range opts.TrustedKeys { if !nkeys.IsValidPublicOperatorKey(key) { return false } } - s.trustedKeys = s.opts.TrustedKeys + s.trustedKeys = append([]string(nil), opts.TrustedKeys...) + for _, claim := range opts.TrustedOperators { + if !claim.StrictSigningKeyUsage { + continue + } + for _, key := range claim.SigningKeys { + s.strictSigningKeyUsage[key] = struct{}{} + } + } } return true } @@ -812,7 +1587,7 @@ func checkTrustedKeyString(keys string) []string { // it succeeded or not. func (s *Server) initStampedTrustedKeys() bool { // Check to see if we have an override in options, which will cause us to fail. - if len(s.opts.TrustedKeys) > 0 { + if len(s.getOpts().TrustedKeys) > 0 { return false } tks := checkTrustedKeyString(trustedKeys) @@ -854,24 +1629,19 @@ func ProcessCommandLineArgs(cmd *flag.FlagSet) (showVersion bool, showHelp bool, return false, false, nil } +// Public version. +func (s *Server) Running() bool { + return s.isRunning() +} + // Protected check on running state func (s *Server) isRunning() bool { - s.mu.Lock() - running := s.running - s.mu.Unlock() - return running + return s.running.Load() } func (s *Server) logPid() error { pidStr := strconv.Itoa(os.Getpid()) - return ioutil.WriteFile(s.getOpts().PidFile, []byte(pidStr), 0660) -} - -// NewAccountsAllowed returns whether or not new accounts can be created on the fly. -func (s *Server) NewAccountsAllowed() bool { - s.mu.Lock() - defer s.mu.Unlock() - return s.opts.AllowNewAccounts + return os.WriteFile(s.getOpts().PidFile, []byte(pidStr), defaultFilePerms) } // numReservedAccounts will return the number of reserved accounts configured in the server. @@ -899,12 +1669,12 @@ func (s *Server) decActiveAccounts() { // range over all accounts in the sync.Map to count. func (s *Server) numAccounts() int { count := 0 - s.mu.Lock() - s.accounts.Range(func(k, v interface{}) bool { + s.mu.RLock() + s.accounts.Range(func(k, v any) bool { count++ return true }) - s.mu.Unlock() + s.mu.RUnlock() return count } @@ -964,20 +1734,14 @@ func (s *Server) SetSystemAccount(accName string) error { // SystemAccount returns the system account if set. func (s *Server) SystemAccount() *Account { - var sacc *Account - s.mu.Lock() - if s.sys != nil { - sacc = s.sys.account - } - s.mu.Unlock() - return sacc + return s.sysAcc.Load() } // GlobalAccount returns the global account. // Default clients will use the global account. func (s *Server) GlobalAccount() *Account { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.gacc } @@ -990,9 +1754,6 @@ func (s *Server) SetDefaultSystemAccount() error { return s.SetSystemAccount(DEFAULT_SYSTEM_ACCOUNT) } -// For internal sends. -const internalSendQLen = 8192 - // Assign a system account. Should only be called once. // This sets up a server to send and receive messages from // inside the server itself. @@ -1021,7 +1782,7 @@ func (s *Server) setSystemAccount(acc *Account) error { // locks on fast path for inbound messages and checking service imports. acc.mu.Lock() if acc.imports.services == nil { - acc.imports.services = make(map[string]*serviceImport) + acc.imports.services = make(map[string][]*serviceImport) } acc.mu.Unlock() @@ -1032,15 +1793,22 @@ func (s *Server) setSystemAccount(acc *Account) error { sid: 1, servers: make(map[string]*serverUpdate), replies: make(map[string]msgHandler), - sendq: make(chan *pubMsg, internalSendQLen), + sendq: newIPQueue[*pubMsg](s, "System sendQ"), + recvq: newIPQueue[*inSysMsg](s, "System recvQ"), + recvqp: newIPQueue[*inSysMsg](s, "System recvQ Pings"), resetCh: make(chan struct{}), - statsz: eventsHBInterval, + sq: s.newSendQ(acc), + statsz: statsHBInterval, orphMax: 5 * eventsHBInterval, chkOrph: 3 * eventsHBInterval, } + recvq, recvqp := s.sys.recvq, s.sys.recvqp s.sys.wg.Add(1) s.mu.Unlock() + // Store in atomic for fast lookup. + s.sysAcc.Store(acc) + // Register with the account. s.sys.client.registerWithAccount(acc) @@ -1050,6 +1818,11 @@ func (s *Server) setSystemAccount(acc *Account) error { // We do our own wg here since we will stop first during shutdown. go s.internalSendLoop(&s.sys.wg) + // Start the internal loop for inbound messages. + go s.internalReceiveLoop(recvq) + // Start the internal loop for inbound STATSZ/Ping messages. + go s.internalReceiveLoop(recvqp) + // Start up our general subscriptions s.initEventTracking() @@ -1061,7 +1834,7 @@ func (s *Server) setSystemAccount(acc *Account) error { // If we have existing accounts make sure we enable account tracking. s.mu.Lock() - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) s.enableAccountTracking(acc) return true @@ -1086,9 +1859,9 @@ func (s *Server) createInternalAccountClient() *client { return s.createInternalClient(ACCOUNT) } -// Internal clients. kind should be SYSTEM or JETSTREAM +// Internal clients. kind should be SYSTEM, JETSTREAM or ACCOUNT func (s *Server) createInternalClient(kind int) *client { - if kind != SYSTEM && kind != JETSTREAM && kind != ACCOUNT { + if !isInternalClient(kind) { return nil } now := time.Now() @@ -1104,7 +1877,8 @@ func (s *Server) createInternalClient(kind int) *client { // efficient propagation. // Lock should be held on entry. func (s *Server) shouldTrackSubscriptions() bool { - return (s.opts.Cluster.Port != 0 || s.opts.Gateway.Port != 0) + opts := s.getOpts() + return (opts.Cluster.Port != 0 || opts.Gateway.Port != 0) } // Invokes registerAccountNoLock under the protection of the server lock. @@ -1144,6 +1918,8 @@ func (s *Server) registerAccountNoLock(acc *Account) *Account { // Finish account setup and store. s.setAccountSublist(acc) + acc.mu.Lock() + s.setRouteInfo(acc) if acc.clients == nil { acc.clients = make(map[*client]struct{}) } @@ -1153,7 +1929,6 @@ func (s *Server) registerAccountNoLock(acc *Account) *Account { // During config reload, it is possible that account was // already created (global account), so use locking and // make sure we create only if needed. - acc.mu.Lock() // TODO(dlc)- Double check that we need this for GWs. if acc.rm == nil && s.opts != nil && s.shouldTrackSubscriptions() { acc.rm = make(map[string]int32) @@ -1161,13 +1936,71 @@ func (s *Server) registerAccountNoLock(acc *Account) *Account { } acc.srv = s acc.updated = time.Now() + accName := acc.Name + jsEnabled := len(acc.jsLimits) > 0 acc.mu.Unlock() + + if opts := s.getOpts(); opts != nil && len(opts.JsAccDefaultDomain) > 0 { + if defDomain, ok := opts.JsAccDefaultDomain[accName]; ok { + if jsEnabled { + s.Warnf("Skipping Default Domain %q, set for JetStream enabled account %q", defDomain, accName) + } else if defDomain != _EMPTY_ { + for src, dest := range generateJSMappingTable(defDomain) { + // flip src and dest around so the domain is inserted + s.Noticef("Adding default domain mapping %q -> %q to account %q %p", dest, src, accName, acc) + if err := acc.AddMapping(dest, src); err != nil { + s.Errorf("Error adding JetStream default domain mapping: %v", err) + } + } + } + } + } + s.accounts.Store(acc.Name, acc) s.tmpAccounts.Delete(acc.Name) s.enableAccountTracking(acc) + + // Can not have server lock here. + s.mu.Unlock() + s.registerSystemImports(acc) + // Starting 2.9.0, we are phasing out the optimistic mode, so change + // the account to interest-only mode (except if instructed not to do + // it in some tests). + if s.gateway.enabled && !gwDoNotForceInterestOnlyMode { + s.switchAccountToInterestMode(acc.GetName()) + } + s.mu.Lock() + return nil } +// Sets the account's routePoolIdx depending on presence or not of +// pooling or per-account routes. Also updates a map used by +// gateway code to retrieve a route based on some route hash. +// +// Both Server and Account lock held on entry. +func (s *Server) setRouteInfo(acc *Account) { + // If there is a dedicated route configured for this account + if _, ok := s.accRoutes[acc.Name]; ok { + // We want the account name to be in the map, but we don't + // need a value (we could store empty string) + s.accRouteByHash.Store(acc.Name, nil) + // Set the route pool index to -1 so that it is easy when + // ranging over accounts to exclude those accounts when + // trying to get accounts for a given pool index. + acc.routePoolIdx = accDedicatedRoute + } else { + // If pool size more than 1, we will compute a hash code and + // use modulo to assign to an index of the pool slice. For 1 + // and below, all accounts will be bound to the single connection + // at index 0. + acc.routePoolIdx = computeRoutePoolIdx(s.routesPoolSize, acc.Name) + if s.routesPoolSize > 1 { + s.accRouteByHash.Store(acc.Name, acc.routePoolIdx) + } + } +} + // lookupAccount is a function to return the account structure // associated with an account name. // Lock MUST NOT be held upon entry. @@ -1194,7 +2027,7 @@ func (s *Server) lookupAccount(name string) (*Account, error) { } // If we have a resolver see if it can fetch the account. if s.AccountResolver() == nil { - return nil, ErrNoAccountResolver + return nil, ErrMissingAccount } return s.fetchAccount(name) } @@ -1208,11 +2041,14 @@ func (s *Server) LookupAccount(name string) (*Account, error) { // This will fetch new claims and if found update the account with new claims. // Lock MUST NOT be held upon entry. func (s *Server) updateAccount(acc *Account) error { + acc.mu.RLock() // TODO(dlc) - Make configurable if !acc.incomplete && time.Since(acc.updated) < time.Second { + acc.mu.RUnlock() s.Debugf("Requested account update for [%s] ignored, too soon", acc.Name) return ErrAccountResolverUpdateTooSoon } + acc.mu.RUnlock() claimJWT, err := s.fetchRawAccountClaims(acc.Name) if err != nil { return err @@ -1226,23 +2062,30 @@ func (s *Server) updateAccountWithClaimJWT(acc *Account, claimJWT string) error if acc == nil { return ErrMissingAccount } - if acc.claimJWT != "" && acc.claimJWT == claimJWT && !acc.incomplete { + acc.mu.RLock() + sameClaim := acc.claimJWT != _EMPTY_ && acc.claimJWT == claimJWT && !acc.incomplete + acc.mu.RUnlock() + if sameClaim { s.Debugf("Requested account update for [%s], same claims detected", acc.Name) - return ErrAccountResolverSameClaims + return nil } accClaims, _, err := s.verifyAccountClaims(claimJWT) if err == nil && accClaims != nil { acc.mu.Lock() - if acc.Issuer == "" { - acc.Issuer = accClaims.Issuer - } + // if an account is updated with a different operator signing key, we want to + // show a consistent issuer. + acc.Issuer = accClaims.Issuer if acc.Name != accClaims.Subject { acc.mu.Unlock() return ErrAccountValidation } - acc.claimJWT = claimJWT acc.mu.Unlock() s.UpdateAccountClaims(acc, accClaims) + acc.mu.Lock() + // needs to be set after update completed. + // This causes concurrent calls to return with sameClaim=true if the change is effective. + acc.claimJWT = claimJWT + acc.mu.Unlock() return nil } return err @@ -1253,7 +2096,7 @@ func (s *Server) updateAccountWithClaimJWT(acc *Account, claimJWT string) error func (s *Server) fetchRawAccountClaims(name string) (string, error) { accResolver := s.AccountResolver() if accResolver == nil { - return "", ErrNoAccountResolver + return _EMPTY_, ErrNoAccountResolver } // Need to do actual Fetch start := time.Now() @@ -1311,58 +2154,113 @@ func (s *Server) fetchAccount(name string) (*Account, error) { return nil, err } acc := s.buildInternalAccount(accClaims) - acc.claimJWT = claimJWT // Due to possible race, if registerAccount() returns a non // nil account, it means the same account was already // registered and we should use this one. if racc := s.registerAccount(acc); racc != nil { // Update with the new claims in case they are new. - // Following call will ignore ErrAccountResolverSameClaims - // if claims are the same. - err = s.updateAccountWithClaimJWT(racc, claimJWT) - if err != nil && err != ErrAccountResolverSameClaims { + if err = s.updateAccountWithClaimJWT(racc, claimJWT); err != nil { return nil, err } return racc, nil } // The sub imports may have been setup but will not have had their // subscriptions properly setup. Do that here. - if len(acc.imports.services) > 0 && acc.ic == nil { - acc.ic = s.createInternalAccountClient() - acc.ic.acc = acc + var needImportSubs bool + + acc.mu.Lock() + acc.claimJWT = claimJWT + if len(acc.imports.services) > 0 { + if acc.ic == nil { + acc.ic = s.createInternalAccountClient() + acc.ic.acc = acc + } + needImportSubs = true + } + acc.mu.Unlock() + + // Do these outside the lock. + if needImportSubs { acc.addAllServiceImportSubs() } + return acc, nil } -// Start up the server, this will block. -// Start via a Go routine if needed. +// Start up the server, this will not block. +// +// WaitForShutdown can be used to block and wait for the server to shutdown properly if needed +// after calling s.Shutdown() func (s *Server) Start() { - s.Noticef("Starting nats-server version %s", VERSION) - s.Debugf("Go build version %s", s.info.GoVersion) + s.Noticef("Starting nats-server") + gc := gitCommit - if gc == "" { + if gc == _EMPTY_ { gc = "not set" } - s.Noticef("Git commit [%s]", gc) + + // Snapshot server options. + opts := s.getOpts() + + // Capture if this server is a leaf that has no cluster, so we don't + // display the cluster name if that is the case. + s.mu.RLock() + leafNoCluster := s.leafNoCluster + s.mu.RUnlock() + + var clusterName string + if !leafNoCluster { + clusterName = s.ClusterName() + } + + s.Noticef(" Version: %s", VERSION) + s.Noticef(" Git: [%s]", gc) + s.Debugf(" Go build: %s", s.info.GoVersion) + if clusterName != _EMPTY_ { + s.Noticef(" Cluster: %s", clusterName) + } + s.Noticef(" Name: %s", s.info.Name) + if opts.JetStream { + s.Noticef(" Node: %s", getHash(s.info.Name)) + } + s.Noticef(" ID: %s", s.info.ID) + + defer s.Noticef("Server is ready") // Check for insecure configurations. s.checkAuthforWarnings() // Avoid RACE between Start() and Shutdown() + s.running.Store(true) s.mu.Lock() - s.running = true + // Update leafNodeEnabled in case options have changed post NewServer() + // and before Start() (we should not be able to allow that, but server has + // direct reference to user-provided options - at least before a Reload() is + // performed. + s.leafNodeEnabled = opts.LeafNode.Port != 0 || len(opts.LeafNode.Remotes) > 0 s.mu.Unlock() s.grMu.Lock() s.grRunning = true s.grMu.Unlock() - // Snapshot server options. - opts := s.getOpts() + s.startRateLimitLogExpiration() + + // Pprof http endpoint for the profiler. + if opts.ProfPort != 0 { + s.StartProfiler() + } else { + // It's still possible to access this profile via a SYS endpoint, so set + // this anyway. (Otherwise StartProfiler would have called it.) + s.setBlockProfileRate(opts.ProfBlockRate) + } if opts.ConfigFile != _EMPTY_ { - s.Noticef("Using configuration file: %s", opts.ConfigFile) + var cd string + if opts.configDigest != "" { + cd = fmt.Sprintf("(%s)", opts.configDigest) + } + s.Noticef("Using configuration file: %s %s", opts.ConfigFile, cd) } hasOperators := len(opts.TrustedOperators) > 0 @@ -1373,11 +2271,24 @@ func (s *Server) Start() { s.Noticef(" System : %q", opc.Audience) s.Noticef(" Operator: %q", opc.Name) s.Noticef(" Issued : %v", time.Unix(opc.IssuedAt, 0)) - s.Noticef(" Expires : %v", time.Unix(opc.Expires, 0)) + switch opc.Expires { + case 0: + s.Noticef(" Expires : Never") + default: + s.Noticef(" Expires : %v", time.Unix(opc.Expires, 0)) + } } if hasOperators && opts.SystemAccount == _EMPTY_ { s.Warnf("Trusted Operators should utilize a System Account") } + if opts.MaxPayload > MAX_PAYLOAD_MAX_SIZE { + s.Warnf("Maximum payloads over %v are generally discouraged and could lead to poor performance", + friendlyBytes(int64(MAX_PAYLOAD_MAX_SIZE))) + } + + if len(opts.JsAccDefaultDomain) > 0 { + s.Warnf("The option `default_js_domain` is a temporary backwards compatibility measure and will be removed") + } // If we have a memory resolver, check the accounts here for validation exceptions. // This allows them to be logged right away vs when they are accessed via a client. @@ -1385,7 +2296,7 @@ func (s *Server) Start() { s.checkResolvePreloads() } - // Log the pid to a file + // Log the pid to a file. if opts.PidFile != _EMPTY_ { if err := s.logPid(); err != nil { s.Fatalf("Could not write pidfile: %v", err) @@ -1404,17 +2315,25 @@ func (s *Server) Start() { s.SetDefaultSystemAccount() } - // start up resolver machinery + // Start monitoring before enabling other subsystems of the + // server to be able to monitor during startup. + if err := s.StartMonitoring(); err != nil { + s.Fatalf("Can't start monitoring: %v", err) + return + } + + // Start up resolver machinery. if ar := s.AccountResolver(); ar != nil { if err := ar.Start(s); err != nil { s.Fatalf("Could not start resolver: %v", err) return } // In operator mode, when the account resolver depends on an external system and - // the system account is the bootstrapping account, start fetching it + // the system account is the bootstrapping account, start fetching it. if len(opts.TrustedOperators) == 1 && opts.SystemAccount != _EMPTY_ && opts.SystemAccount != DEFAULT_SYSTEM_ACCOUNT { + opts := s.getOpts() _, isMemResolver := ar.(*MemAccResolver) - if v, ok := s.accounts.Load(s.opts.SystemAccount); !isMemResolver && ok && v.(*Account).claimJWT == "" { + if v, ok := s.accounts.Load(opts.SystemAccount); !isMemResolver && ok && v.(*Account).claimJWT == _EMPTY_ { s.Noticef("Using bootstrapping system account") s.startGoRoutine(func() { defer s.grWG.Done() @@ -1425,10 +2344,10 @@ func (s *Server) Start() { case <-s.quitCh: return case <-t.C: - if _, err := fetchAccount(ar, s.opts.SystemAccount); err != nil { + sacc := s.SystemAccount() + if claimJWT, err := fetchAccount(ar, opts.SystemAccount); err != nil { continue - } - if _, err := s.fetchAccount(s.opts.SystemAccount); err != nil { + } else if err = s.updateAccountWithClaimJWT(sacc, claimJWT); err != nil { continue } s.Noticef("System account fetched and updated") @@ -1449,39 +2368,71 @@ func (s *Server) Start() { // own system account if one is not present. if opts.JetStream { // Make sure someone is not trying to enable on the system account. - if sa := s.SystemAccount(); sa != nil && sa.jsLimits != nil { + if sa := s.SystemAccount(); sa != nil && len(sa.jsLimits) > 0 { s.Fatalf("Not allowed to enable JetStream on the system account") } cfg := &JetStreamConfig{ - StoreDir: opts.StoreDir, - MaxMemory: opts.JetStreamMaxMemory, - MaxStore: opts.JetStreamMaxStore, + StoreDir: opts.StoreDir, + SyncInterval: opts.SyncInterval, + SyncAlways: opts.SyncAlways, + Strict: opts.JetStreamStrict, + MaxMemory: opts.JetStreamMaxMemory, + MaxStore: opts.JetStreamMaxStore, + Domain: opts.JetStreamDomain, + CompressOK: true, + UniqueTag: opts.JetStreamUniqueTag, } if err := s.EnableJetStream(cfg); err != nil { s.Fatalf("Can't start JetStream: %v", err) return } } else { - // Check to see if any configured accounts have JetStream enabled - // and warn if they do. - s.accounts.Range(func(k, v interface{}) bool { + // Check to see if any configured accounts have JetStream enabled. + sa, ga := s.SystemAccount(), s.GlobalAccount() + var hasSys, hasGlobal bool + var total int + + s.accounts.Range(func(k, v any) bool { + total++ acc := v.(*Account) + if acc == sa { + hasSys = true + } else if acc == ga { + hasGlobal = true + } acc.mu.RLock() - hasJs := acc.jsLimits != nil - name := acc.Name + hasJs := len(acc.jsLimits) > 0 acc.mu.RUnlock() if hasJs { - s.Warnf("Account [%q] has JetStream configuration but JetStream not enabled", name) + s.checkJetStreamExports() + acc.enableAllJetStreamServiceImportsAndMappings() } return true }) + // If we only have the system account and the global account and we are not standalone, + // go ahead and enable JS on $G in case we are in simple mixed mode setup. + if total == 2 && hasSys && hasGlobal && !s.standAloneMode() { + ga.mu.Lock() + ga.jsLimits = map[string]JetStreamAccountLimits{ + _EMPTY_: dynamicJSAccountLimits, + } + ga.mu.Unlock() + s.checkJetStreamExports() + ga.enableAllJetStreamServiceImportsAndMappings() + } } - // Start monitoring if needed - if err := s.StartMonitoring(); err != nil { - s.Fatalf("Can't start monitoring: %v", err) - return - } + // Delayed API response handling. Start regardless of JetStream being + // currently configured or not (since it can be enabled/disabled with + // configuration reload). + s.startGoRoutine(s.delayedAPIResponder) + + // Start OCSP Stapling monitoring for TLS certificates if enabled. Hook TLS handshake for + // OCSP check on peers (LEAF and CLIENT kind) if enabled. + s.startOCSPMonitoring() + + // Configure OCSP Response Cache for peer OCSP checks if enabled. + s.initOCSPResponseCache() // Start up gateway if needed. Do this before starting the routes, because // we want to resolve the gateway host:port so that this information can @@ -1490,6 +2441,13 @@ func (s *Server) Start() { s.startGateways() } + // Start websocket server if needed. Do this before starting the routes, and + // leaf node because we want to resolve the gateway host:port so that this + // information can be sent to other routes. + if opts.Websocket.Port != 0 { + s.startWebsocketServer() + } + // Start up listen if we want to accept leaf node connections. if opts.LeafNode.Port != 0 { // Will resolve or assign the advertise address for the leafnode listener. @@ -1515,13 +2473,6 @@ func (s *Server) Start() { // port to be opened and potential ephemeral port selected. clientListenReady := make(chan struct{}) - // Start websocket server if needed. Do this before starting the routes, - // because we want to resolve the gateway host:port so that this information - // can be sent to other routes. - if opts.Websocket.Port != 0 { - s.startWebsocketServer() - } - // MQTT if opts.MQTT.Port != 0 { s.startMQTT() @@ -1534,51 +2485,79 @@ func (s *Server) Start() { }) } - // Pprof http endpoint for the profiler. - if opts.ProfPort != 0 { - s.StartProfiler() - } - if opts.PortsFileDir != _EMPTY_ { s.logPorts() } + if opts.TLSRateLimit > 0 { + s.startGoRoutine(s.logRejectedTLSConns) + } + + // We've finished starting up. + close(s.startupComplete) + // Wait for clients. - s.AcceptLoop(clientListenReady) + if !opts.DontListen { + s.AcceptLoop(clientListenReady) + } + + // Bring OSCP Response cache online after accept loop started in anticipation of NATS-enabled cache types + s.startOCSPResponseCache() +} + +func (s *Server) isShuttingDown() bool { + return s.shutdown.Load() } // Shutdown will shutdown the server instance by kicking out the AcceptLoop // and closing all associated clients. func (s *Server) Shutdown() { + if s == nil { + return + } + // This is for JetStream R1 Pull Consumers to allow signaling + // that pending pull requests are invalid. + s.signalPullConsumers() + + // Transfer off any raft nodes that we are a leader by stepping them down. + s.stepdownRaftNodes() + // Shutdown the eventing system as needed. // This is done first to send out any messages for // account status. We will also clean up any // eventing items associated with accounts. s.shutdownEventing() - // Now check jetstream. - s.shutdownJetStream() - - s.mu.Lock() // Prevent issues with multiple calls. - if s.shutdown { - s.mu.Unlock() + if s.isShuttingDown() { return } + + s.mu.Lock() s.Noticef("Initiating Shutdown...") - if s.accResolver != nil { - s.accResolver.Close() - } + accRes := s.accResolver opts := s.getOpts() - s.shutdown = true - s.running = false + s.shutdown.Store(true) + s.running.Store(false) s.grMu.Lock() s.grRunning = false s.grMu.Unlock() + s.mu.Unlock() + + if accRes != nil { + accRes.Close() + } + + // Now check and shutdown jetstream. + s.shutdownJetStream() + // Now shutdown the nodes + s.shutdownRaftNodes() + + s.mu.Lock() conns := make(map[uint64]*client) // Copy off the clients @@ -1593,9 +2572,11 @@ func (s *Server) Shutdown() { } s.grMu.Unlock() // Copy off the routes - for i, r := range s.routes { - conns[i] = r - } + s.forEachRoute(func(r *client) { + r.mu.Lock() + conns[r.cid] = r + r.mu.Unlock() + }) // Copy off the gateways s.getAllGatewayConnections(conns) @@ -1615,12 +2596,7 @@ func (s *Server) Shutdown() { } // Kick websocket server - if s.websocket.server != nil { - doneExpected++ - s.websocket.server.Close() - s.websocket.server = nil - s.websocket.listener = nil - } + doneExpected += s.closeWebsocketServer() // Kick MQTT accept loop if s.mqtt.listener != nil { @@ -1688,6 +2664,12 @@ func (s *Server) Shutdown() { } s.Noticef("Server Exiting..") + + // Stop OCSP Response Cache + if s.ocsprc != nil { + s.ocsprc.Stop(s) + } + // Close logger if applicable. It allows tests on Windows // to be able to do proper cleanup (delete log file). s.logging.RLock() @@ -1702,6 +2684,24 @@ func (s *Server) Shutdown() { close(s.shutdownComplete) } +// Close the websocket server if running. If so, returns 1, else 0. +// Server lock held on entry. +func (s *Server) closeWebsocketServer() int { + ws := &s.websocket + ws.mu.Lock() + hs := ws.server + if hs != nil { + ws.server = nil + ws.listener = nil + } + ws.mu.Unlock() + if hs != nil { + hs.Close() + return 1 + } + return 0 +} + // WaitForShutdown will block until the server has been fully shutdown. func (s *Server) WaitForShutdown() { <-s.shutdownComplete @@ -1717,17 +2717,18 @@ func (s *Server) AcceptLoop(clr chan struct{}) { } }() + if s.isShuttingDown() { + return + } + // Snapshot server options. opts := s.getOpts() // Setup state that can enable shutdown s.mu.Lock() - if s.shutdown { - s.mu.Unlock() - return - } hp := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port)) - l, e := natsListen("tcp", hp) + l, e := s.getServerListener(hp) + s.listenerErr = e if e != nil { s.mu.Unlock() s.Fatalf("Error listening on port: %s, %q", hp, e) @@ -1739,12 +2740,11 @@ func (s *Server) AcceptLoop(clr chan struct{}) { // Alert of TLS enabled. if opts.TLSConfig != nil { s.Noticef("TLS required for client connections") + if opts.TLSHandshakeFirst && opts.TLSHandshakeFirstFallback == 0 { + s.Warnf("Clients that are not using \"TLS Handshake First\" option will fail to connect") + } } - s.Noticef("Server id is %s", s.info.ID) - s.Noticef("Server name is %s", s.info.Name) - s.Noticef("Server is ready") - // If server was started with RANDOM_PORT (-1), opts.Port would be equal // to 0 at the beginning this function. So we need to get the actual port if opts.Port == 0 { @@ -1756,7 +2756,7 @@ func (s *Server) AcceptLoop(clr chan struct{}) { // server's info Host/Port with either values from Options or // ClientAdvertise. if err := s.setInfoHostPort(); err != nil { - s.Fatalf("Error setting server INFO with ClientAdvertise value of %s, err=%v", s.opts.ClientAdvertise, err) + s.Fatalf("Error setting server INFO with ClientAdvertise value of %s, err=%v", opts.ClientAdvertise, err) l.Close() s.mu.Unlock() return @@ -1783,6 +2783,35 @@ func (s *Server) AcceptLoop(clr chan struct{}) { clr = nil } +// getServerListener returns a network listener for the given host-port address. +// If the Server already has an active listener (s.listener), it returns that listener +// along with any previous error (s.listenerErr). Otherwise, it creates and returns +// a new TCP listener on the specified address using natsListen. +func (s *Server) getServerListener(hp string) (net.Listener, error) { + if s.listener != nil { + return s.listener, s.listenerErr + } + + return natsListen("tcp", hp) +} + +// InProcessConn returns an in-process connection to the server, +// avoiding the need to use a TCP listener for local connectivity +// within the same process. This can be used regardless of the +// state of the DontListen option. +func (s *Server) InProcessConn() (net.Conn, error) { + pl, pr := net.Pipe() + if !s.startGoRoutine(func() { + s.createClientInProcess(pl) + s.grWG.Done() + }) { + pl.Close() + pr.Close() + return nil, fmt.Errorf("failed to create connection") + } + return pr, nil +} + func (s *Server) acceptConnections(l net.Listener, acceptName string, createFunc func(conn net.Conn), errFunc func(err error) bool) { tmpDelay := ACCEPT_MIN_SLEEP @@ -1799,7 +2828,9 @@ func (s *Server) acceptConnections(l net.Listener, acceptName string, createFunc } tmpDelay = ACCEPT_MIN_SLEEP if !s.startGoRoutine(func() { + s.reloadMu.RLock() createFunc(conn) + s.reloadMu.RUnlock() s.grWG.Done() }) { conn.Close() @@ -1817,22 +2848,27 @@ func (s *Server) setInfoHostPort() error { // When this function is called, opts.Port is set to the actual listen // port (if option was originally set to RANDOM), even during a config // reload. So use of s.opts.Port is safe. - if s.opts.ClientAdvertise != "" { - h, p, err := parseHostPort(s.opts.ClientAdvertise, s.opts.Port) + opts := s.getOpts() + if opts.ClientAdvertise != _EMPTY_ { + h, p, err := parseHostPort(opts.ClientAdvertise, opts.Port) if err != nil { return err } s.info.Host = h s.info.Port = p } else { - s.info.Host = s.opts.Host - s.info.Port = s.opts.Port + s.info.Host = opts.Host + s.info.Port = opts.Port } return nil } // StartProfiler is called to enable dynamic profiling. func (s *Server) StartProfiler() { + if s.isShuttingDown() { + return + } + // Snapshot server options. opts := s.getOpts() @@ -1844,40 +2880,32 @@ func (s *Server) StartProfiler() { } s.mu.Lock() - if s.shutdown { - s.mu.Unlock() - return - } hp := net.JoinHostPort(opts.Host, strconv.Itoa(port)) - l, err := net.Listen("tcp", hp) - s.Noticef("profiling port: %d", l.Addr().(*net.TCPAddr).Port) if err != nil { s.mu.Unlock() s.Fatalf("error starting profiler: %s", err) return } + s.Noticef("profiling port: %d", l.Addr().(*net.TCPAddr).Port) srv := &http.Server{ Addr: hp, Handler: http.DefaultServeMux, MaxHeaderBytes: 1 << 20, + ReadTimeout: time.Second * 5, } s.profiler = l s.profilingServer = srv - // Enable blocking profile - runtime.SetBlockProfileRate(1) + s.setBlockProfileRate(opts.ProfBlockRate) go func() { // if this errors out, it's probably because the server is being shutdown err := srv.Serve(l) if err != nil { - s.mu.Lock() - shutdown := s.shutdown - s.mu.Unlock() - if !shutdown { + if !s.isShuttingDown() { s.Fatalf("error starting profiler: %s", err) } } @@ -1887,6 +2915,15 @@ func (s *Server) StartProfiler() { s.mu.Unlock() } +func (s *Server) setBlockProfileRate(rate int) { + // Passing i ProfBlockRate <= 0 here will disable or > 0 will enable. + runtime.SetBlockProfileRate(rate) + + if rate > 0 { + s.Warnf("Block profiling is enabled (rate %d), this may have a performance impact", rate) + } +} + // StartHTTPMonitoring will enable the HTTP monitoring port. // DEPRECATED: Should use StartMonitoring. func (s *Server) StartHTTPMonitoring() { @@ -1922,36 +2959,68 @@ func (s *Server) StartMonitoring() error { // HTTP endpoints const ( - RootPath = "/" - VarzPath = "/varz" - ConnzPath = "/connz" - RoutezPath = "/routez" - GatewayzPath = "/gatewayz" - LeafzPath = "/leafz" - SubszPath = "/subsz" - StackszPath = "/stacksz" - AccountzPath = "/accountz" + RootPath = "/" + VarzPath = "/varz" + ConnzPath = "/connz" + RoutezPath = "/routez" + GatewayzPath = "/gatewayz" + LeafzPath = "/leafz" + SubszPath = "/subsz" + StackszPath = "/stacksz" + AccountzPath = "/accountz" + AccountStatzPath = "/accstatz" + JszPath = "/jsz" + HealthzPath = "/healthz" + IPQueuesPath = "/ipqueuesz" + RaftzPath = "/raftz" + ExpvarzPath = "/debug/vars" ) func (s *Server) basePath(p string) string { return path.Join(s.httpBasePath, p) } +type captureHTTPServerLog struct { + s *Server + prefix string +} + +func (cl *captureHTTPServerLog) Write(p []byte) (int, error) { + var buf [128]byte + var b = buf[:0] + + b = append(b, []byte(cl.prefix)...) + offset := 0 + if bytes.HasPrefix(p, []byte("http:")) { + offset = 6 + } + b = append(b, p[offset:]...) + cl.s.Errorf(string(b)) + return len(p), nil +} + +// The TLS configuration is passed to the listener when the monitoring +// "server" is setup. That prevents TLS configuration updates on reload +// from being used. By setting this function in tls.Config.GetConfigForClient +// we instruct the TLS handshake to ask for the tls configuration to be +// used for a specific client. We don't care which client, we always use +// the same TLS configuration. +func (s *Server) getMonitoringTLSConfig(_ *tls.ClientHelloInfo) (*tls.Config, error) { + opts := s.getOpts() + tc := opts.TLSConfig.Clone() + tc.ClientAuth = tls.NoClientCert + return tc, nil +} + // Start the monitoring server func (s *Server) startMonitoring(secure bool) error { + if s.isShuttingDown() { + return nil + } + // Snapshot server options. opts := s.getOpts() - // Used to track HTTP requests - s.httpReqStats = map[string]uint64{ - RootPath: 0, - VarzPath: 0, - ConnzPath: 0, - RoutezPath: 0, - GatewayzPath: 0, - SubszPath: 0, - } - var ( hp string err error @@ -1969,7 +3038,10 @@ func (s *Server) startMonitoring(secure bool) error { } hp = net.JoinHostPort(opts.HTTPHost, strconv.Itoa(port)) config := opts.TLSConfig.Clone() - config.ClientAuth = tls.NoClientCert + if !s.ocspPeerVerify { + config.GetConfigForClient = s.getMonitoringTLSConfig + config.ClientAuth = tls.NoClientCert + } httpListener, err = tls.Listen("tcp", hp, config) } else { @@ -1985,8 +3057,8 @@ func (s *Server) startMonitoring(secure bool) error { return fmt.Errorf("can't listen to the monitor port: %v", err) } - s.Noticef("Starting %s monitor on %s", monitorProtocol, - net.JoinHostPort(opts.HTTPHost, strconv.Itoa(httpListener.Addr().(*net.TCPAddr).Port))) + rport := httpListener.Addr().(*net.TCPAddr).Port + s.Noticef("Starting %s monitor on %s", monitorProtocol, net.JoinHostPort(opts.HTTPHost, strconv.Itoa(rport))) mux := http.NewServeMux() @@ -2010,21 +3082,30 @@ func (s *Server) startMonitoring(secure bool) error { mux.HandleFunc(s.basePath(StackszPath), s.HandleStacksz) // Accountz mux.HandleFunc(s.basePath(AccountzPath), s.HandleAccountz) + // Accstatz + mux.HandleFunc(s.basePath(AccountStatzPath), s.HandleAccountStatz) + // Jsz + mux.HandleFunc(s.basePath(JszPath), s.HandleJsz) + // Healthz + mux.HandleFunc(s.basePath(HealthzPath), s.HandleHealthz) + // IPQueuesz + mux.HandleFunc(s.basePath(IPQueuesPath), s.HandleIPQueuesz) + // Raftz + mux.HandleFunc(s.basePath(RaftzPath), s.HandleRaftz) + // Expvarz + mux.Handle(s.basePath(ExpvarzPath), expvar.Handler()) // Do not set a WriteTimeout because it could cause cURL/browser // to return empty response or unable to display page if the // server needs more time to build the response. srv := &http.Server{ - Addr: hp, - Handler: mux, - MaxHeaderBytes: 1 << 20, + Addr: hp, + Handler: mux, + MaxHeaderBytes: 1 << 20, + ErrorLog: log.New(&captureHTTPServerLog{s, "monitoring: "}, _EMPTY_, 0), + ReadHeaderTimeout: time.Second * 5, } s.mu.Lock() - if s.shutdown { - httpListener.Close() - s.mu.Unlock() - return nil - } s.http = httpListener s.httpHandler = mux s.monitoringServer = srv @@ -2032,15 +3113,11 @@ func (s *Server) startMonitoring(secure bool) error { go func() { if err := srv.Serve(httpListener); err != nil { - s.mu.Lock() - shutdown := s.shutdown - s.mu.Unlock() - if !shutdown { + if !s.isShuttingDown() { s.Fatalf("Error starting monitor on %q: %v", hp, err) } } srv.Close() - srv.Handler = nil s.mu.Lock() s.httpHandler = nil s.mu.Unlock() @@ -2092,6 +3169,14 @@ func (c *tlsMixConn) Read(b []byte) (int, error) { } func (s *Server) createClient(conn net.Conn) *client { + return s.createClientEx(conn, false) +} + +func (s *Server) createClientInProcess(conn net.Conn) *client { + return s.createClientEx(conn, true) +} + +func (s *Server) createClientEx(conn net.Conn, inProcess bool) *client { // Snapshot server options. opts := s.getOpts() @@ -2103,7 +3188,16 @@ func (s *Server) createClient(conn net.Conn) *client { } now := time.Now() - c := &client{srv: s, nc: conn, opts: defaultOpts, mpay: maxPay, msubs: maxSubs, start: now, last: now} + c := &client{ + srv: s, + nc: conn, + opts: defaultOpts, + mpay: maxPay, + msubs: maxSubs, + start: now, + last: now, + iproc: inProcess, + } c.registerWithAccount(s.globalAccount()) @@ -2123,6 +3217,19 @@ func (s *Server) createClient(conn net.Conn) *client { c.nonce = []byte(info.Nonce) authRequired = info.AuthRequired + // Check to see if we have auth_required set but we also have a no_auth_user. + // If so set back to false. + if info.AuthRequired && opts.NoAuthUser != _EMPTY_ && opts.NoAuthUser != s.sysAccOnlyNoAuthUser { + info.AuthRequired = false + } + + // Check to see if this is an in-process connection with tls_required. + // If so, set as not required, but available. + if inProcess && info.TLSRequired { + info.TLSRequired = false + info.TLSAvailable = true + } + s.totalClients++ s.mu.Unlock() @@ -2137,10 +3244,37 @@ func (s *Server) createClient(conn net.Conn) *client { c.Debugf("Client connection created") - // Send our information. - // Need to be sent in place since writeLoop cannot be started until - // TLS handshake is done (if applicable). - c.sendProtoNow(c.generateClientInfoJSON(info)) + // Save info.TLSRequired value since we may neeed to change it back and forth. + orgInfoTLSReq := info.TLSRequired + + var tlsFirstFallback time.Duration + // Check if we should do TLS first. + tlsFirst := opts.TLSConfig != nil && opts.TLSHandshakeFirst + if tlsFirst { + // Make sure info.TLSRequired is set to true (it could be false + // if AllowNonTLS is enabled). + info.TLSRequired = true + // Get the fallback delay value if applicable. + if f := opts.TLSHandshakeFirstFallback; f > 0 { + tlsFirstFallback = f + } else if inProcess { + // For in-process connection, we will always have a fallback + // delay. It allows support for non-TLS, TLS and "TLS First" + // in-process clients to successfully connect. + tlsFirstFallback = DEFAULT_TLS_HANDSHAKE_FIRST_FALLBACK_DELAY + } + } + + // Decide if we are going to require TLS or not and generate INFO json. + tlsRequired := info.TLSRequired + infoBytes := c.generateClientInfoJSON(info) + + // Send our information, except if TLS and TLSHandshakeFirst is requested. + if !tlsFirst { + // Need to be sent in place since writeLoop cannot be started until + // TLS handshake is done (if applicable). + c.sendProtoNow(infoBytes) + } // Unlock to register c.mu.Unlock() @@ -2151,13 +3285,13 @@ func (s *Server) createClient(conn net.Conn) *client { // list of connections to close. It won't contain this one, so we need // to bail out now otherwise the readLoop started down there would not // be interrupted. Skip also if in lame duck mode. - if !s.running || s.ldm { + if !s.isRunning() || s.ldm { // There are some tests that create a server but don't start it, // and use "async" clients and perform the parsing manually. Such // clients would branch here (since server is not running). However, // when a server was really running and has been shutdown, we must // close this connection. - if s.shutdown { + if s.isShuttingDown() { conn.Close() } s.mu.Unlock() @@ -2173,19 +3307,50 @@ func (s *Server) createClient(conn net.Conn) *client { } s.clients[c.cid] = c - tlsRequired := info.TLSRequired s.mu.Unlock() // Re-Grab lock c.mu.Lock() - // Connection could have been closed while sending the INFO proto. isClosed := c.isClosed() - var pre []byte + // We need first to check for "TLS First" fallback delay. + if !isClosed && tlsFirstFallback > 0 { + // We wait and see if we are getting any data. Since we did not send + // the INFO protocol yet, only clients that use TLS first should be + // sending data (the TLS handshake). We don't really check the content: + // if it is a rogue agent and not an actual client performing the + // TLS handshake, the error will be detected when performing the + // handshake on our side. + pre = make([]byte, 4) + c.nc.SetReadDeadline(time.Now().Add(tlsFirstFallback)) + n, _ := io.ReadFull(c.nc, pre[:]) + c.nc.SetReadDeadline(time.Time{}) + // If we get any data (regardless of possible timeout), we will proceed + // with the TLS handshake. + if n > 0 { + pre = pre[:n] + } else { + // We did not get anything so we will send the INFO protocol. + pre = nil + + // Restore the original info.TLSRequired value if it is + // different that the current value and regenerate infoBytes. + if orgInfoTLSReq != info.TLSRequired { + info.TLSRequired = orgInfoTLSReq + infoBytes = c.generateClientInfoJSON(info) + } + c.sendProtoNow(infoBytes) + // Set the boolean to false for the rest of the function. + tlsFirst = false + // Check closed status again + isClosed = c.isClosed() + } + } // If we have both TLS and non-TLS allowed we need to see which - // one the client wants. - if !isClosed && opts.TLSConfig != nil && opts.AllowNonTLS { + // one the client wants. We'll always allow this for in-process + // connections. + if !isClosed && !tlsFirst && opts.TLSConfig != nil && (inProcess || opts.AllowNonTLS) { pre = make([]byte, 4) c.nc.SetReadDeadline(time.Now().Add(secondsToDuration(opts.TLSTimeout))) n, _ := io.ReadFull(c.nc, pre[:]) @@ -2200,48 +3365,38 @@ func (s *Server) createClient(conn net.Conn) *client { // Check for TLS if !isClosed && tlsRequired { - c.Debugf("Starting TLS client connection handshake") + if s.connRateCounter != nil && !s.connRateCounter.allow() { + c.mu.Unlock() + c.sendErr("Connection throttling is active. Please try again later.") + c.closeConnection(MaxConnectionsExceeded) + return nil + } + // If we have a prebuffer create a multi-reader. if len(pre) > 0 { c.nc = &tlsMixConn{c.nc, bytes.NewBuffer(pre)} // Clear pre so it is not parsed. pre = nil } - - c.nc = tls.Server(c.nc, opts.TLSConfig) - conn := c.nc.(*tls.Conn) - - // Setup the timeout - ttl := secondsToDuration(opts.TLSTimeout) - time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) - conn.SetReadDeadline(time.Now().Add(ttl)) - - // Force handshake - c.mu.Unlock() - if err := conn.Handshake(); err != nil { - c.Errorf("TLS handshake error: %v", err) - c.closeConnection(TLSHandshakeError) + // Performs server-side TLS handshake. + if err := c.doTLSServerHandshake(_EMPTY_, opts.TLSConfig, opts.TLSTimeout, opts.TLSPinnedCerts); err != nil { + c.mu.Unlock() return nil } - // Reset the read deadline - conn.SetReadDeadline(time.Time{}) - - // Re-Grab lock - c.mu.Lock() - - // Indicate that handshake is complete (used in monitoring) - c.flags.set(handshakeComplete) + } - // The connection may have been closed + // Now, send the INFO if it was delayed + if !isClosed && tlsFirst { + c.flags.set(didTLSFirst) + c.sendProtoNow(infoBytes) + // Check closed status isClosed = c.isClosed() } - // If connection is marked as closed, bail out. + // Connection could have been closed while sending the INFO proto. if isClosed { c.mu.Unlock() - // Connection could have been closed due to TLS timeout or while trying - // to send the INFO protocol. We need to call closeConnection() to make - // sure that proper cleanup is done. + // We need to call closeConnection() to make sure that proper cleanup is done. c.closeConnection(WriteError) return nil } @@ -2277,7 +3432,7 @@ func (s *Server) createClient(conn net.Conn) *client { // This will save off a closed client in a ring buffer such that // /connz can inspect. Useful for debugging, etc. -func (s *Server) saveClosedClient(c *client, nc net.Conn, reason ClosedState) { +func (s *Server) saveClosedClient(c *client, nc net.Conn, subs map[string]*subscription, reason ClosedState) { now := time.Now() s.accountDisconnectEvent(c, now, reason.String()) @@ -2285,23 +3440,30 @@ func (s *Server) saveClosedClient(c *client, nc net.Conn, reason ClosedState) { c.mu.Lock() cc := &closedClient{} - cc.fill(c, nc, now) + cc.fill(c, nc, now, false) + // Note that cc.fill is using len(c.subs), which may have been set to nil by now, + // so replace cc.NumSubs with len(subs). + cc.NumSubs = uint32(len(subs)) cc.Stop = &now cc.Reason = reason.String() // Do subs, do not place by default in main ConnInfo - if len(c.subs) > 0 { - cc.subs = make([]SubDetail, 0, len(c.subs)) - for _, sub := range c.subs { + if len(subs) > 0 { + cc.subs = make([]SubDetail, 0, len(subs)) + for _, sub := range subs { cc.subs = append(cc.subs, newSubDetail(sub)) } } // Hold user as well. - cc.user = c.opts.Username + cc.user = c.getRawAuthUser() // Hold account name if not the global account. if c.acc != nil && c.acc.Name != globalAccountName { cc.acc = c.acc.Name } + cc.JWT = c.opts.JWT + cc.IssuerKey = issuerForClient(c) + cc.Tags = c.tags + cc.NameTag = c.nameTag c.mu.Unlock() // Place in the ring buffer @@ -2315,6 +3477,7 @@ func (s *Server) saveClosedClient(c *client, nc net.Conn, reason ClosedState) { // Adds to the list of client and websocket clients connect URLs. // If there was a change, an INFO protocol is sent to registered clients // that support async INFO protocols. +// Server lock held on entry. func (s *Server) addConnectURLsAndSendINFOToClients(curls, wsurls []string) { s.updateServerINFOAndSendINFOToClients(curls, wsurls, true) } @@ -2322,16 +3485,15 @@ func (s *Server) addConnectURLsAndSendINFOToClients(curls, wsurls []string) { // Removes from the list of client and websocket clients connect URLs. // If there was a change, an INFO protocol is sent to registered clients // that support async INFO protocols. +// Server lock held on entry. func (s *Server) removeConnectURLsAndSendINFOToClients(curls, wsurls []string) { s.updateServerINFOAndSendINFOToClients(curls, wsurls, false) } // Updates the list of client and websocket clients connect URLs and if any change // sends an async INFO update to clients that support it. +// Server lock held on entry. func (s *Server) updateServerINFOAndSendINFOToClients(curls, wsurls []string, add bool) { - s.mu.Lock() - defer s.mu.Unlock() - remove := !add // Will return true if we need alter the server's Info object. updateMap := func(urls []string, m refCountedUrlSet) bool { @@ -2404,6 +3566,20 @@ func tlsVersion(ver uint16) string { return fmt.Sprintf("Unknown [0x%x]", ver) } +func tlsVersionFromString(ver string) (uint16, error) { + switch ver { + case "1.0": + return tls.VersionTLS10, nil + case "1.1": + return tls.VersionTLS11, nil + case "1.2": + return tls.VersionTLS12, nil + case "1.3": + return tls.VersionTLS13, nil + } + return 0, fmt.Errorf("unknown version: %v", ver) +} + // We use hex here so we don't need multiple versions func tlsCipher(cs uint16) string { name, present := cipherMapByID[cs] @@ -2431,11 +3607,7 @@ func (s *Server) removeClient(c *client) { if updateProtoInfoCount { s.cproto-- } - mqtt := c.isMqtt() s.mu.Unlock() - if mqtt { - s.mqttHandleClosedClient(c) - } case ROUTER: s.removeRoute(c) case GATEWAY: @@ -2468,30 +3640,45 @@ func (s *Server) addToTempClients(cid uint64, c *client) bool { // NumRoutes will report the number of registered routes. func (s *Server) NumRoutes() int { - s.mu.Lock() - nr := len(s.routes) - s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() + return s.numRoutes() +} + +// numRoutes will report the number of registered routes. +// Server lock held on entry +func (s *Server) numRoutes() int { + var nr int + s.forEachRoute(func(c *client) { + nr++ + }) return nr } // NumRemotes will report number of registered remotes. func (s *Server) NumRemotes() int { - s.mu.Lock() - defer s.mu.Unlock() - return len(s.remotes) + s.mu.RLock() + defer s.mu.RUnlock() + return s.numRemotes() +} + +// numRemotes will report number of registered remotes. +// Server lock held on entry +func (s *Server) numRemotes() int { + return len(s.routes) } // NumLeafNodes will report number of leaf node connections. func (s *Server) NumLeafNodes() int { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return len(s.leafs) } // NumClients will report the number of registered clients. func (s *Server) NumClients() int { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return len(s.clients) } @@ -2502,22 +3689,22 @@ func (s *Server) GetClient(cid uint64) *client { // getClient will return the client associated with cid. func (s *Server) getClient(cid uint64) *client { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.clients[cid] } // GetLeafNode returns the leafnode associated with the cid. func (s *Server) GetLeafNode(cid uint64) *client { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.leafs[cid] } // NumSubscriptions will report how many subscriptions are active. func (s *Server) NumSubscriptions() uint32 { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.numSubscriptions() } @@ -2525,11 +3712,9 @@ func (s *Server) NumSubscriptions() uint32 { // Lock should be held. func (s *Server) numSubscriptions() uint32 { var subs int - s.accounts.Range(func(k, v interface{}) bool { + s.accounts.Range(func(k, v any) bool { acc := v.(*Account) - if acc.sl != nil { - subs += acc.TotalSubs() - } + subs += acc.TotalSubs() return true }) return uint32(subs) @@ -2540,17 +3725,37 @@ func (s *Server) NumSlowConsumers() int64 { return atomic.LoadInt64(&s.slowConsumers) } +// NumSlowConsumersClients will report the number of slow consumers clients. +func (s *Server) NumSlowConsumersClients() uint64 { + return s.scStats.clients.Load() +} + +// NumSlowConsumersRoutes will report the number of slow consumers routes. +func (s *Server) NumSlowConsumersRoutes() uint64 { + return s.scStats.routes.Load() +} + +// NumSlowConsumersGateways will report the number of slow consumers leafs. +func (s *Server) NumSlowConsumersGateways() uint64 { + return s.scStats.gateways.Load() +} + +// NumSlowConsumersLeafs will report the number of slow consumers leafs. +func (s *Server) NumSlowConsumersLeafs() uint64 { + return s.scStats.leafs.Load() +} + // ConfigTime will report the last time the server configuration was loaded. func (s *Server) ConfigTime() time.Time { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.configTime } // Addr will return the net.Addr object for the current listener. func (s *Server) Addr() net.Addr { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() if s.listener == nil { return nil } @@ -2559,8 +3764,8 @@ func (s *Server) Addr() net.Addr { // MonitorAddr will return the net.Addr object for the monitoring listener. func (s *Server) MonitorAddr() *net.TCPAddr { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() if s.http == nil { return nil } @@ -2569,8 +3774,8 @@ func (s *Server) MonitorAddr() *net.TCPAddr { // ClusterAddr returns the net.Addr object for the route listener. func (s *Server) ClusterAddr() *net.TCPAddr { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() if s.routeListener == nil { return nil } @@ -2579,36 +3784,83 @@ func (s *Server) ClusterAddr() *net.TCPAddr { // ProfilerAddr returns the net.Addr object for the profiler listener. func (s *Server) ProfilerAddr() *net.TCPAddr { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() if s.profiler == nil { return nil } return s.profiler.Addr().(*net.TCPAddr) } -// ReadyForConnections returns `true` if the server is ready to accept clients -// and, if routing is enabled, route connections. If after the duration -// `dur` the server is still not ready, returns `false`. -func (s *Server) ReadyForConnections(dur time.Duration) bool { +func (s *Server) readyForConnections(d time.Duration) error { // Snapshot server options. opts := s.getOpts() - end := time.Now().Add(dur) + type info struct { + ok bool + err error + } + chk := make(map[string]info) + + end := time.Now().Add(d) for time.Now().Before(end) { - s.mu.Lock() - ok := s.listener != nil && - (opts.Cluster.Port == 0 || s.routeListener != nil) && - (opts.Gateway.Name == "" || s.gatewayListener != nil) && - (opts.LeafNode.Port == 0 || s.leafNodeListener != nil) && - (opts.Websocket.Port == 0 || s.websocket.listener != nil) - s.mu.Unlock() - if ok { - return true + s.mu.RLock() + chk["server"] = info{ok: s.listener != nil || opts.DontListen, err: s.listenerErr} + chk["route"] = info{ok: (opts.Cluster.Port == 0 || s.routeListener != nil), err: s.routeListenerErr} + chk["gateway"] = info{ok: (opts.Gateway.Name == _EMPTY_ || s.gatewayListener != nil), err: s.gatewayListenerErr} + chk["leafnode"] = info{ok: (opts.LeafNode.Port == 0 || s.leafNodeListener != nil), err: s.leafNodeListenerErr} + chk["websocket"] = info{ok: (opts.Websocket.Port == 0 || s.websocket.listener != nil), err: s.websocket.listenerErr} + chk["mqtt"] = info{ok: (opts.MQTT.Port == 0 || s.mqtt.listener != nil), err: s.mqtt.listenerErr} + s.mu.RUnlock() + + var numOK int + for _, inf := range chk { + if inf.ok { + numOK++ + } + } + if numOK == len(chk) { + // In the case of DontListen option (no accept loop), we still want + // to make sure that Start() has done all the work, so we wait on + // that. + if opts.DontListen { + select { + case <-s.startupComplete: + case <-time.After(d): + return fmt.Errorf("failed to be ready for connections after %s: startup did not complete", d) + } + } + return nil + } + if d > 25*time.Millisecond { + time.Sleep(25 * time.Millisecond) } - time.Sleep(25 * time.Millisecond) } - return false + + failed := make([]string, 0, len(chk)) + for name, inf := range chk { + if inf.ok && inf.err != nil { + failed = append(failed, fmt.Sprintf("%s(ok, but %s)", name, inf.err)) + } + if !inf.ok && inf.err == nil { + failed = append(failed, name) + } + if !inf.ok && inf.err != nil { + failed = append(failed, fmt.Sprintf("%s(%s)", name, inf.err)) + } + } + + return fmt.Errorf( + "failed to be ready for connections after %s: %s", + d, strings.Join(failed, ", "), + ) +} + +// ReadyForConnections returns `true` if the server is ready to accept clients +// and, if routing is enabled, route connections. If after the duration +// `dur` the server is still not ready, returns `false`. +func (s *Server) ReadyForConnections(dur time.Duration) bool { + return s.readyForConnections(dur) == nil } // Quick utility to function to tell if the server supports headers. @@ -2621,45 +3873,69 @@ func (s *Server) supportsHeaders() bool { // ID returns the server's ID func (s *Server) ID() string { - s.mu.Lock() - defer s.mu.Unlock() return s.info.ID } +// NodeName returns the node name for this server. +func (s *Server) NodeName() string { + return getHash(s.info.Name) +} + // Name returns the server's name. This will be the same as the ID if it was not set. func (s *Server) Name() string { - s.mu.Lock() - defer s.mu.Unlock() return s.info.Name } -func (s *Server) startGoRoutine(f func()) bool { +func (s *Server) String() string { + return s.info.Name +} + +type pprofLabels map[string]string + +func setGoRoutineLabels(tags ...pprofLabels) { + var labels []string + for _, m := range tags { + for k, v := range m { + labels = append(labels, k, v) + } + } + if len(labels) > 0 { + pprof.SetGoroutineLabels( + pprof.WithLabels(context.Background(), pprof.Labels(labels...)), + ) + } +} + +func (s *Server) startGoRoutine(f func(), tags ...pprofLabels) bool { var started bool s.grMu.Lock() + defer s.grMu.Unlock() if s.grRunning { s.grWG.Add(1) - go f() + go func() { + setGoRoutineLabels(tags...) + f() + }() started = true } - s.grMu.Unlock() return started } func (s *Server) numClosedConns() int { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.closed.len() } func (s *Server) totalClosedConns() uint64 { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.closed.totalConns() } func (s *Server) closedClients() []*closedClient { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.closed.closedClients() } @@ -2811,7 +4087,7 @@ func (s *Server) PortsInfo(maxWait time.Duration) *Ports { if s.readyForListeners(maxWait) { opts := s.getOpts() - s.mu.Lock() + s.mu.RLock() tls := s.info.TLSRequired listener := s.listener httpListener := s.http @@ -2819,7 +4095,7 @@ func (s *Server) PortsInfo(maxWait time.Duration) *Ports { profileListener := s.profiler wsListener := s.websocket.listener wss := s.websocket.tls - s.mu.Unlock() + s.mu.RUnlock() ports := Ports{} @@ -2852,9 +4128,9 @@ func (s *Server) PortsInfo(maxWait time.Duration) *Ports { } if wsListener != nil { - protocol := "ws" + protocol := wsSchemePrefix if wss { - protocol = "wss" + protocol = wsSchemePrefixTLS } ports.WebSocket = formatURL(protocol, wsListener) } @@ -2907,7 +4183,7 @@ func (s *Server) logPorts() { s.Errorf("Error marshaling ports file: %v", err) return } - if err := ioutil.WriteFile(portsFile, data, 0666); err != nil { + if err := os.WriteFile(portsFile, data, 0666); err != nil { s.Errorf("Error writing ports file (%s): %v", portsFile, err) return } @@ -2920,9 +4196,9 @@ func (s *Server) logPorts() { func (s *Server) readyForListeners(dur time.Duration) bool { end := time.Now().Add(dur) for time.Now().Before(end) { - s.mu.Lock() + s.mu.RLock() listeners := s.serviceListeners() - s.mu.Unlock() + s.mu.RUnlock() if len(listeners) == 0 { return false } @@ -2970,31 +4246,38 @@ func (s *Server) serviceListeners() []net.Listener { // Returns true if in lame duck mode. func (s *Server) isLameDuckMode() bool { - s.mu.Lock() - defer s.mu.Unlock() + s.mu.RLock() + defer s.mu.RUnlock() return s.ldm } +// LameDuckShutdown will perform a lame duck shutdown of NATS, whereby +// the client listener is closed, existing client connections are +// kicked, Raft leaderships are transferred, JetStream is shutdown +// and then finally shutdown the the NATS Server itself. +// This function blocks and will not return until the NATS Server +// has completed the entire shutdown operation. +func (s *Server) LameDuckShutdown() { + s.lameDuckMode() +} + // This function will close the client listener then close the clients -// at some interval to avoid a reconnecting storm. +// at some interval to avoid a reconnect storm. +// We will also transfer any raft leaders and shutdown JetStream. func (s *Server) lameDuckMode() { s.mu.Lock() // Check if there is actually anything to do - if s.shutdown || s.ldm || s.listener == nil { + if s.isShuttingDown() || s.ldm || s.listener == nil { s.mu.Unlock() return } s.Noticef("Entering lame duck mode, stop accepting new clients") s.ldm = true + s.sendLDMShutdownEventLocked() expected := 1 s.listener.Close() s.listener = nil - if s.websocket.server != nil { - expected++ - s.websocket.server.Close() - s.websocket.server = nil - s.websocket.listener = nil - } + expected += s.closeWebsocketServer() s.ldmCh = make(chan bool, expected) opts := s.getOpts() gp := opts.LameDuckGracePeriod @@ -3006,6 +4289,22 @@ func (s *Server) lameDuckMode() { } s.mu.Unlock() + // If we are running any raftNodes transfer leaders. + if hadTransfers := s.transferRaftLeaders(); hadTransfers { + // They will transfer leadership quickly, but wait here for a second. + select { + case <-time.After(time.Second): + case <-s.quitCh: + return + } + } + + // Now check and shutdown jetstream. + s.shutdownJetStream() + + // Now shutdown the nodes + s.shutdownRaftNodes() + // Wait for accept loops to be done to make sure that no new // client can connect for i := 0; i < expected; i++ { @@ -3014,7 +4313,7 @@ func (s *Server) lameDuckMode() { s.mu.Lock() // Need to recheck few things - if s.shutdown || len(s.clients) == 0 { + if s.isShuttingDown() || len(s.clients) == 0 { s.mu.Unlock() // If there is no client, we need to call Shutdown() to complete // the LDMode. If server has been shutdown while lock was released, @@ -3030,7 +4329,10 @@ func (s *Server) lameDuckMode() { numClients := int64(len(s.clients)) batch := 1 // Sleep interval between each client connection close. - si := dur / numClients + var si int64 + if numClients != 0 { + si = dur / numClients + } if si < 1 { // Should not happen (except in test with very small LD duration), but // if there are too many clients, batch the number of close and @@ -3088,18 +4390,19 @@ func (s *Server) lameDuckMode() { } } s.Shutdown() + s.WaitForShutdown() } // Send an INFO update to routes with the indication that this server is in LDM mode. // Server lock is held on entry. func (s *Server) sendLDMToRoutes() { s.routeInfo.LameDuckMode = true - s.generateRouteInfoJSON() - for _, r := range s.routes { + infoJSON := generateInfoJSON(&s.routeInfo) + s.forEachRemote(func(r *client) { r.mu.Lock() - r.enqueueProto(s.routeInfoJSON) + r.enqueueProto(infoJSON) r.mu.Unlock() - } + }) // Clear now so that we notify only once, should we have to send other INFOs. s.routeInfo.LameDuckMode = false } @@ -3144,7 +4447,8 @@ func (s *Server) acceptError(acceptName string, err error, tmpDelay time.Duratio if !s.isRunning() { return -1 } - if ne, ok := err.(net.Error); ok && ne.Temporary() { + //lint:ignore SA1019 We want to retry on a bunch of errors here. + if ne, ok := err.(net.Error); ok && ne.Temporary() { // nolint:staticcheck s.Errorf("Temporary %s Accept Error(%v), sleeping %dms", acceptName, ne, tmpDelay/time.Millisecond) select { case <-time.After(tmpDelay): @@ -3228,28 +4532,89 @@ func (s *Server) shouldReportConnectErr(firstConnect bool, attempts int) bool { return false } -// Invoked for route, leaf and gateway connections. Set the very first -// PING to a lower interval to capture the initial RTT. -// After that the PING interval will be set to the user defined value. -// Client lock should be held. -func (s *Server) setFirstPingTimer(c *client) { - opts := s.getOpts() - d := opts.PingInterval +func (s *Server) updateRemoteSubscription(acc *Account, sub *subscription, delta int32) { + s.updateRouteSubscriptionMap(acc, sub, delta) + if s.gateway.enabled { + s.gatewayUpdateSubInterest(acc.Name, sub, delta) + } - if !opts.DisableShortFirstPing { - if c.kind != CLIENT { - if d > firstPingInterval { - d = firstPingInterval - } - if c.kind == GATEWAY { - d = adjustPingIntervalForGateway(d) + acc.updateLeafNodes(sub, delta) +} + +func (s *Server) startRateLimitLogExpiration() { + interval := time.Second + s.startGoRoutine(func() { + defer s.grWG.Done() + + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for { + select { + case <-s.quitCh: + return + case interval = <-s.rateLimitLoggingCh: + ticker.Reset(interval) + case <-ticker.C: + s.rateLimitLogging.Range(func(k, v any) bool { + start := v.(time.Time) + if time.Since(start) >= interval { + s.rateLimitLogging.Delete(k) + } + return true + }) } - } else if d > firstClientPingInterval { - d = firstClientPingInterval } + }) +} + +func (s *Server) changeRateLimitLogInterval(d time.Duration) { + if d <= 0 { + return + } + select { + case s.rateLimitLoggingCh <- d: + default: + } +} + +// DisconnectClientByID disconnects a client by connection ID +func (s *Server) DisconnectClientByID(id uint64) error { + if s == nil { + return ErrServerNotRunning + } + if client := s.getClient(id); client != nil { + client.closeConnection(Kicked) + return nil + } else if client = s.GetLeafNode(id); client != nil { + client.closeConnection(Kicked) + return nil + } + return errors.New("no such client or leafnode id") +} + +// LDMClientByID sends a Lame Duck Mode info message to a client by connection ID +func (s *Server) LDMClientByID(id uint64) error { + if s == nil { + return ErrServerNotRunning + } + s.mu.RLock() + c := s.clients[id] + if c == nil { + s.mu.RUnlock() + return errors.New("no such client id") + } + info := s.copyInfo() + info.LameDuckMode = true + s.mu.RUnlock() + c.mu.Lock() + defer c.mu.Unlock() + if c.opts.Protocol >= ClientProtoInfo && c.flags.isSet(firstPongSent) { + // sendInfo takes care of checking if the connection is still + // valid or not, so don't duplicate tests here. + c.Debugf("Sending Lame Duck Mode info to client") + c.enqueueProto(c.generateClientInfoJSON(info)) + return nil + } else { + return errors.New("client does not support Lame Duck Mode or is not ready to receive the notification") } - // We randomize the first one by an offset up to 20%, e.g. 2m ~= max 24s. - addDelay := rand.Int63n(int64(d / 5)) - d += time.Duration(addDelay) - c.ping.tmr = time.AfterFunc(d, c.processPingTimer) } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/service.go b/vendor/github.com/nats-io/nats-server/v2/server/service.go index a44cbac..fe39419 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/service.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/service.go @@ -1,4 +1,4 @@ -// Copyright 2012-2018 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +//go:build !windows package server diff --git a/vendor/github.com/nats-io/nats-server/v2/server/service_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/service_windows.go index d24f641..62a6c00 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/service_windows.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/service_windows.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -42,6 +42,7 @@ type winServiceWrapper struct { } var dockerized = false +var startupDelay = 10 * time.Second func init() { if v, exists := os.LookupEnv("NATS_DOCKERIZED"); exists && v == "1" { @@ -66,8 +67,15 @@ func (w *winServiceWrapper) Execute(args []string, changes <-chan svc.ChangeRequ status <- svc.Status{State: svc.StartPending} go w.server.Start() + if v, exists := os.LookupEnv("NATS_STARTUP_DELAY"); exists { + if delay, err := time.ParseDuration(v); err == nil { + startupDelay = delay + } else { + w.server.Errorf("Failed to parse \"%v\" as a duration for startup: %s", v, err) + } + } // Wait for accept loop(s) to be started - if !w.server.ReadyForConnections(10 * time.Second) { + if !w.server.ReadyForConnections(startupDelay) { // Failed to start. return false, 1 } @@ -109,11 +117,11 @@ func Run(server *Server) error { server.Start() return nil } - isInteractive, err := svc.IsAnInteractiveSession() + isWindowsService, err := svc.IsWindowsService() if err != nil { return err } - if isInteractive { + if !isWindowsService { server.Start() return nil } @@ -125,6 +133,6 @@ func isWindowsService() bool { if dockerized { return false } - isInteractive, _ := svc.IsAnInteractiveSession() - return !isInteractive + isWindowsService, _ := svc.IsWindowsService() + return isWindowsService } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/signal.go b/vendor/github.com/nats-io/nats-server/v2/server/signal.go index 254e3ec..aef50a5 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/signal.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/signal.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +//go:build !windows && !wasm package server @@ -40,17 +40,29 @@ func (s *Server) handleSignals() { } c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP) go func() { for { select { case sig := <-c: - s.Debugf("Trapped %q signal", sig) + s.Noticef("Trapped %q signal", sig) switch sig { case syscall.SIGINT: s.Shutdown() + s.WaitForShutdown() os.Exit(0) + case syscall.SIGTERM: + // Shutdown unless graceful shutdown already in progress. + s.mu.Lock() + ldm := s.ldm + s.mu.Unlock() + + if !ldm { + s.Shutdown() + s.WaitForShutdown() + os.Exit(0) + } case syscall.SIGUSR1: // File log re-open for rotating file logs. s.ReOpenLogFile() @@ -71,52 +83,82 @@ func (s *Server) handleSignals() { // ProcessSignal sends the given signal command to the given process. If pidStr // is empty, this will send the signal to the single running instance of -// nats-server. If multiple instances are running, it returns an error. This returns -// an error if the given process is not running or the command is invalid. -func ProcessSignal(command Command, pidStr string) error { - var pid int - if pidStr == "" { - pids, err := resolvePids() - if err != nil { +// nats-server. If multiple instances are running, pidStr can be a globular +// expression ending with '*'. This returns an error if the given process is +// not running or the command is invalid. +func ProcessSignal(command Command, pidExpr string) error { + var ( + err error + errStr string + pids = make([]int, 1) + pidStr = strings.TrimSuffix(pidExpr, "*") + isGlob = strings.HasSuffix(pidExpr, "*") + ) + + // Validate input if given + if pidStr != "" { + if pids[0], err = strconv.Atoi(pidStr); err != nil { + return fmt.Errorf("invalid pid: %s", pidStr) + } + } + // Gather all PIDs unless the input is specific + if pidStr == "" || isGlob { + if pids, err = resolvePids(); err != nil { return err } - if len(pids) == 0 { - return fmt.Errorf("no %s processes running", processName) + } + // Multiple instances are running and the input is not an expression + if len(pids) > 1 && !isGlob { + errStr = fmt.Sprintf("multiple %s processes running:", processName) + for _, p := range pids { + errStr += fmt.Sprintf("\n%d", p) } - if len(pids) > 1 { - errStr := fmt.Sprintf("multiple %s processes running:\n", processName) - prefix := "" - for _, p := range pids { - errStr += fmt.Sprintf("%s%d", prefix, p) - prefix = "\n" + return errors.New(errStr) + } + // No instances are running + if len(pids) == 0 { + return fmt.Errorf("no %s processes running", processName) + } + + var signum syscall.Signal + if signum, err = CommandToSignal(command); err != nil { + return err + } + + for _, pid := range pids { + if _pidStr := strconv.Itoa(pid); _pidStr != pidStr && pidStr != "" { + if !isGlob || !strings.HasPrefix(_pidStr, pidStr) { + continue } - return errors.New(errStr) } - pid = pids[0] - } else { - p, err := strconv.Atoi(pidStr) - if err != nil { - return fmt.Errorf("invalid pid: %s", pidStr) + if err = kill(pid, signum); err != nil { + errStr += fmt.Sprintf("\nsignal %q %d: %s", command, pid, err) } - pid = p } + if errStr != "" { + return errors.New(errStr) + } + return nil +} - var err error +// Translates a command to a signal number +func CommandToSignal(command Command) (syscall.Signal, error) { switch command { case CommandStop: - err = kill(pid, syscall.SIGKILL) + return syscall.SIGKILL, nil case CommandQuit: - err = kill(pid, syscall.SIGINT) + return syscall.SIGINT, nil case CommandReopen: - err = kill(pid, syscall.SIGUSR1) + return syscall.SIGUSR1, nil case CommandReload: - err = kill(pid, syscall.SIGHUP) + return syscall.SIGHUP, nil case commandLDMode: - err = kill(pid, syscall.SIGUSR2) + return syscall.SIGUSR2, nil + case commandTerm: + return syscall.SIGTERM, nil default: - err = fmt.Errorf("unknown signal %q", command) + return 0, fmt.Errorf("unknown signal %q", command) } - return err } // resolvePids returns the pids for all running nats-server processes. diff --git a/vendor/github.com/nats-io/nats-server/v2/server/signal_wasm.go b/vendor/github.com/nats-io/nats-server/v2/server/signal_wasm.go new file mode 100644 index 0000000..7ee34e4 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/signal_wasm.go @@ -0,0 +1,24 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build wasm + +package server + +func (s *Server) handleSignals() { + +} + +func ProcessSignal(command Command, service string) error { + return nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/signal_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/signal_windows.go index a3667c8..1ecabed 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/signal_windows.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/signal_windows.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,6 +17,7 @@ import ( "fmt" "os" "os/signal" + "syscall" "time" "golang.org/x/sys/windows/svc" @@ -30,13 +31,18 @@ func (s *Server) handleSignals() { } c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { - for sig := range c { - s.Debugf("Trapped %q signal", sig) - s.Shutdown() - os.Exit(0) + for { + select { + case sig := <-c: + s.Debugf("Trapped %q signal", sig) + s.Shutdown() + os.Exit(0) + case <-s.quitCh: + return + } } }() } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/store.go b/vendor/github.com/nats-io/nats-server/v2/server/store.go index 943c6a5..b408bc9 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/store.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/store.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,22 +14,29 @@ package server import ( - "encoding/json" + "encoding/binary" "errors" "fmt" "io" + "os" "strings" "time" + "unsafe" + + "github.com/nats-io/nats-server/v2/server/avl" + "github.com/nats-io/nats-server/v2/server/gsl" ) // StorageType determines how messages are stored for retention. type StorageType int const ( + // File specifies on disk, designated by the JetStream config StoreDir. + FileStorage = StorageType(22) // MemoryStorage specifies in memory only. - MemoryStorage StorageType = iota - // FileStorage specifies on disk, designated by the JetStream config StoreDir. - FileStorage + MemoryStorage = StorageType(33) + // Any is for internals. + AnyStorage = StorageType(44) ) var ( @@ -38,44 +45,92 @@ var ( // ErrStoreMsgNotFound when message was not found but was expected to be. ErrStoreMsgNotFound = errors.New("no message found") // ErrStoreEOF is returned when message seq is greater than the last sequence. - ErrStoreEOF = errors.New("stream EOF") - // ErrMaxMsgs is returned when we have discard new as a policy and we reached - // the message limit. + ErrStoreEOF = errors.New("stream store EOF") + // ErrMaxMsgs is returned when we have discard new as a policy and we reached the message limit. ErrMaxMsgs = errors.New("maximum messages exceeded") - // ErrMaxBytes is returned when we have discard new as a policy and we reached - // the bytes limit. + // ErrMaxBytes is returned when we have discard new as a policy and we reached the bytes limit. ErrMaxBytes = errors.New("maximum bytes exceeded") + // ErrMaxMsgsPerSubject is returned when we have discard new as a policy and we reached the message limit per subject. + ErrMaxMsgsPerSubject = errors.New("maximum messages per subject exceeded") // ErrStoreSnapshotInProgress is returned when RemoveMsg or EraseMsg is called // while a snapshot is in progress. ErrStoreSnapshotInProgress = errors.New("snapshot in progress") - // ErrMsgTooBig is returned when a message is considered too large. - ErrMsgTooLarge = errors.New("message to large") + // ErrMsgTooLarge is returned when a message is considered too large. + ErrMsgTooLarge = errors.New("message too large") // ErrStoreWrongType is for when you access the wrong storage type. ErrStoreWrongType = errors.New("wrong storage type") // ErrNoAckPolicy is returned when trying to update a consumer's acks with no ack policy. ErrNoAckPolicy = errors.New("ack policy is none") + // ErrSequenceMismatch is returned when storing a raw message and the expected sequence is wrong. + ErrSequenceMismatch = errors.New("expected sequence does not match store") + // ErrCorruptStreamState + ErrCorruptStreamState = errors.New("stream state snapshot is corrupt") + // ErrTooManyResults + ErrTooManyResults = errors.New("too many matching results for request") ) +// StoreMsg is the stored message format for messages that are retained by the Store layer. +type StoreMsg struct { + subj string + hdr []byte + msg []byte + buf []byte + seq uint64 + ts int64 +} + // Used to call back into the upper layers to report on changes in storage resources. // For the cases where its a single message we will also supply sequence number and subject. type StorageUpdateHandler func(msgs, bytes int64, seq uint64, subj string) +// Used to call back into the upper layers to remove a message. +type StorageRemoveMsgHandler func(seq uint64) + +// Used to call back into the upper layers to report on newly created subject delete markers. +type SubjectDeleteMarkerUpdateHandler func(*inMsg) + type StreamStore interface { - StoreMsg(subj string, hdr, msg []byte) (uint64, int64, error) - SkipMsg() uint64 - LoadMsg(seq uint64) (subj string, hdr, msg []byte, ts int64, err error) + StoreMsg(subject string, hdr, msg []byte, ttl int64) (uint64, int64, error) + StoreRawMsg(subject string, hdr, msg []byte, seq uint64, ts int64, ttl int64) error + SkipMsg(seq uint64) (uint64, error) + SkipMsgs(seq uint64, num uint64) error + LoadMsg(seq uint64, sm *StoreMsg) (*StoreMsg, error) + LoadNextMsg(filter string, wc bool, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) + LoadNextMsgMulti(sl *gsl.SimpleSublist, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) + LoadLastMsg(subject string, sm *StoreMsg) (*StoreMsg, error) + LoadPrevMsg(start uint64, smp *StoreMsg) (sm *StoreMsg, err error) + LoadPrevMsgMulti(sl *gsl.SimpleSublist, start uint64, smp *StoreMsg) (sm *StoreMsg, skip uint64, err error) RemoveMsg(seq uint64) (bool, error) EraseMsg(seq uint64) (bool, error) Purge() (uint64, error) + PurgeEx(subject string, seq, keep uint64) (uint64, error) Compact(seq uint64) (uint64, error) + Truncate(seq uint64) error GetSeqFromTime(t time.Time) uint64 + FilteredState(seq uint64, subject string) SimpleState + SubjectsState(filterSubject string) map[string]SimpleState + SubjectsTotals(filterSubject string) map[string]uint64 + AllLastSeqs() ([]uint64, error) + MultiLastSeqs(filters []string, maxSeq uint64, maxAllowed int) ([]uint64, error) + SubjectForSeq(seq uint64) (string, error) + NumPending(sseq uint64, filter string, lastPerSubject bool) (total, validThrough uint64) + NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPerSubject bool) (total, validThrough uint64) State() StreamState + FastState(*StreamState) + EncodedStreamState(failed uint64) (enc []byte, err error) + SyncDeleted(dbs DeleteBlocks) + Type() StorageType RegisterStorageUpdates(StorageUpdateHandler) + RegisterStorageRemoveMsg(handler StorageRemoveMsgHandler) + RegisterSubjectDeleteMarkerUpdates(SubjectDeleteMarkerUpdateHandler) UpdateConfig(cfg *StreamConfig) error Delete() error Stop() error ConsumerStore(name string, cfg *ConsumerConfig) (ConsumerStore, error) + AddConsumer(o ConsumerStore) error + RemoveConsumer(o ConsumerStore) error Snapshot(deadline time.Duration, includeConsumers, checkMsgs bool) (*SnapshotResult, error) + Utilization() (total, reported uint64, err error) } // RetentionPolicy determines how messages in a set are retained. @@ -85,7 +140,7 @@ const ( // LimitsPolicy (default) means that messages are retained until any given limit is reached. // This could be one of MaxMsgs, MaxBytes, or MaxAge. LimitsPolicy RetentionPolicy = iota - // InterestPolicy specifies that when all known observables have acknowledged a message it can be removed. + // InterestPolicy specifies that when all known consumers have acknowledged a message it can be removed. InterestPolicy // WorkQueuePolicy specifies that when the first worker or subscriber acknowledges the message it can be removed. WorkQueuePolicy @@ -98,36 +153,222 @@ type DiscardPolicy int const ( // DiscardOld will remove older messages to return to the limits. DiscardOld = iota - //DiscardNew will error on a StoreMsg call + // DiscardNew will error on a StoreMsg call DiscardNew ) -// StreamStats is information about the given stream. +// StreamState is information about the given stream. type StreamState struct { - Msgs uint64 `json:"messages"` - Bytes uint64 `json:"bytes"` - FirstSeq uint64 `json:"first_seq"` - FirstTime time.Time `json:"first_ts"` - LastSeq uint64 `json:"last_seq"` - LastTime time.Time `json:"last_ts"` - Consumers int `json:"consumer_count"` + Msgs uint64 `json:"messages"` + Bytes uint64 `json:"bytes"` + FirstSeq uint64 `json:"first_seq"` + FirstTime time.Time `json:"first_ts"` + LastSeq uint64 `json:"last_seq"` + LastTime time.Time `json:"last_ts"` + NumSubjects int `json:"num_subjects,omitempty"` + Subjects map[string]uint64 `json:"subjects,omitempty"` + NumDeleted int `json:"num_deleted,omitempty"` + Deleted []uint64 `json:"deleted,omitempty"` + Lost *LostStreamData `json:"lost,omitempty"` + Consumers int `json:"consumer_count"` +} + +// SimpleState for filtered subject specific state. +type SimpleState struct { + Msgs uint64 `json:"messages"` + First uint64 `json:"first_seq"` + Last uint64 `json:"last_seq"` + + // Internal usage for when the first needs to be updated before use. + firstNeedsUpdate bool + // Internal usage for when the last needs to be updated before use. + lastNeedsUpdate bool +} + +// LostStreamData indicates msgs that have been lost. +type LostStreamData struct { + Msgs []uint64 `json:"msgs"` + Bytes uint64 `json:"bytes"` } // SnapshotResult contains information about the snapshot. type SnapshotResult struct { - Reader io.ReadCloser - BlkSize int - NumBlks int + Reader io.ReadCloser + State StreamState + errCh chan string +} + +const ( + // Magic is used to identify stream state encodings. + streamStateMagic = uint8(42) + // Version + streamStateVersion = uint8(1) + // Magic / Identifier for run length encodings. + runLengthMagic = uint8(33) + // Magic / Identifier for AVL seqsets. + seqSetMagic = uint8(22) +) + +// Interface for DeleteBlock. +// These will be of three types: +// 1. AVL seqsets. +// 2. Run length encoding of a deleted range. +// 3. Legacy []uint64 +type DeleteBlock interface { + State() (first, last, num uint64) + Range(f func(uint64) bool) +} + +type DeleteBlocks []DeleteBlock + +// StreamReplicatedState represents what is encoded in a binary stream snapshot used +// for stream replication in an NRG. +type StreamReplicatedState struct { + Msgs uint64 + Bytes uint64 + FirstSeq uint64 + LastSeq uint64 + Failed uint64 + Deleted DeleteBlocks +} + +// Determine if this is an encoded stream state. +func IsEncodedStreamState(buf []byte) bool { + return len(buf) >= hdrLen && buf[0] == streamStateMagic && buf[1] == streamStateVersion +} + +var ErrBadStreamStateEncoding = errors.New("bad stream state encoding") + +func DecodeStreamState(buf []byte) (*StreamReplicatedState, error) { + ss := &StreamReplicatedState{} + if len(buf) < hdrLen || buf[0] != streamStateMagic || buf[1] != streamStateVersion { + return nil, ErrBadStreamStateEncoding + } + var bi = hdrLen + + readU64 := func() uint64 { + if bi < 0 || bi >= len(buf) { + bi = -1 + return 0 + } + num, n := binary.Uvarint(buf[bi:]) + if n <= 0 { + bi = -1 + return 0 + } + bi += n + return num + } + + parserFailed := func() bool { + return bi < 0 + } + + ss.Msgs = readU64() + ss.Bytes = readU64() + ss.FirstSeq = readU64() + ss.LastSeq = readU64() + ss.Failed = readU64() + + if parserFailed() { + return nil, ErrCorruptStreamState + } + + if numDeleted := readU64(); numDeleted > 0 { + // If we have some deleted blocks. + for l := len(buf); l > bi; { + switch buf[bi] { + case seqSetMagic: + dmap, n, err := avl.Decode(buf[bi:]) + if err != nil { + return nil, ErrCorruptStreamState + } + bi += n + ss.Deleted = append(ss.Deleted, dmap) + case runLengthMagic: + bi++ + var rl DeleteRange + rl.First = readU64() + rl.Num = readU64() + if parserFailed() { + return nil, ErrCorruptStreamState + } + ss.Deleted = append(ss.Deleted, &rl) + default: + return nil, ErrCorruptStreamState + } + } + } + + return ss, nil +} + +// DeleteRange is a run length encoded delete range. +type DeleteRange struct { + First uint64 + Num uint64 +} + +func (dr *DeleteRange) State() (first, last, num uint64) { + deletesAfterFirst := dr.Num + if deletesAfterFirst > 0 { + deletesAfterFirst-- + } + return dr.First, dr.First + deletesAfterFirst, dr.Num +} + +// Range will range over all the deleted sequences represented by this block. +func (dr *DeleteRange) Range(f func(uint64) bool) { + for seq := dr.First; seq < dr.First+dr.Num; seq++ { + if !f(seq) { + return + } + } +} + +// Legacy []uint64 +type DeleteSlice []uint64 + +func (ds DeleteSlice) State() (first, last, num uint64) { + if len(ds) == 0 { + return 0, 0, 0 + } + return ds[0], ds[len(ds)-1], uint64(len(ds)) +} + +// Range will range over all the deleted sequences represented by this []uint64. +func (ds DeleteSlice) Range(f func(uint64) bool) { + for _, seq := range ds { + if !f(seq) { + return + } + } +} + +func (dbs DeleteBlocks) NumDeleted() (total uint64) { + for _, db := range dbs { + _, _, num := db.State() + total += num + } + return total } // ConsumerStore stores state on consumers for streams. type ConsumerStore interface { + SetStarting(sseq uint64) error + UpdateStarting(sseq uint64) + HasState() bool UpdateDelivered(dseq, sseq, dc uint64, ts int64) error UpdateAcks(dseq, sseq uint64) error + UpdateConfig(cfg *ConsumerConfig) error Update(*ConsumerState) error State() (*ConsumerState, error) + BorrowState() (*ConsumerState, error) + EncodedState() ([]byte, error) + Type() StorageType Stop() error Delete() error + StreamDelete() error } // SequencePair has both the consumer and the stream sequence. They point to same message. @@ -145,9 +386,72 @@ type ConsumerState struct { // These are both in stream sequence context. // Pending is for all messages pending and the timestamp for the delivered time. // This will only be present when the AckPolicy is ExplicitAck. - Pending map[uint64]*Pending `json:"pending"` + Pending map[uint64]*Pending `json:"pending,omitempty"` // This is for messages that have been redelivered, so count > 1. - Redelivered map[uint64]uint64 `json:"redelivered"` + Redelivered map[uint64]uint64 `json:"redelivered,omitempty"` +} + +// Encode consumer state. +func encodeConsumerState(state *ConsumerState) []byte { + var hdr [seqsHdrSize]byte + var buf []byte + + maxSize := seqsHdrSize + if lp := len(state.Pending); lp > 0 { + maxSize += lp*(3*binary.MaxVarintLen64) + binary.MaxVarintLen64 + } + if lr := len(state.Redelivered); lr > 0 { + maxSize += lr*(2*binary.MaxVarintLen64) + binary.MaxVarintLen64 + } + if maxSize == seqsHdrSize { + buf = hdr[:seqsHdrSize] + } else { + buf = make([]byte, maxSize) + } + + // Write header + buf[0] = magic + buf[1] = 2 + + n := hdrLen + n += binary.PutUvarint(buf[n:], state.AckFloor.Consumer) + n += binary.PutUvarint(buf[n:], state.AckFloor.Stream) + n += binary.PutUvarint(buf[n:], state.Delivered.Consumer) + n += binary.PutUvarint(buf[n:], state.Delivered.Stream) + n += binary.PutUvarint(buf[n:], uint64(len(state.Pending))) + + asflr := state.AckFloor.Stream + adflr := state.AckFloor.Consumer + + // These are optional, but always write len. This is to avoid a truncate inline. + if len(state.Pending) > 0 { + // To save space we will use now rounded to seconds to be our base timestamp. + mints := time.Now().Round(time.Second).Unix() + // Write minimum timestamp we found from above. + n += binary.PutVarint(buf[n:], mints) + + for k, v := range state.Pending { + n += binary.PutUvarint(buf[n:], k-asflr) + n += binary.PutUvarint(buf[n:], v.Sequence-adflr) + // Downsample to seconds to save on space. + // Subsecond resolution not needed for recovery etc. + ts := v.Timestamp / int64(time.Second) + n += binary.PutVarint(buf[n:], mints-ts) + } + } + + // We always write the redelivered len. + n += binary.PutUvarint(buf[n:], uint64(len(state.Redelivered))) + + // We expect these to be small. + if len(state.Redelivered) > 0 { + for k, v := range state.Redelivered { + n += binary.PutUvarint(buf[n:], k-asflr) + n += binary.PutUvarint(buf[n:], v) + } + } + + return buf[:n] } // Represents a pending message for explicit ack or ack all. @@ -159,18 +463,20 @@ type Pending struct { // TemplateStore stores templates. type TemplateStore interface { - Store(*StreamTemplate) error - Delete(*StreamTemplate) error -} - -func jsonString(s string) string { - return "\"" + s + "\"" + Store(*streamTemplate) error + Delete(*streamTemplate) error } const ( - limitsPolicyString = "limits" - interestPolicyString = "interest" - workQueuePolicyString = "workqueue" + limitsPolicyJSONString = `"limits"` + interestPolicyJSONString = `"interest"` + workQueuePolicyJSONString = `"workqueue"` +) + +var ( + limitsPolicyJSONBytes = []byte(limitsPolicyJSONString) + interestPolicyJSONBytes = []byte(interestPolicyJSONString) + workQueuePolicyJSONBytes = []byte(workQueuePolicyJSONString) ) func (rp RetentionPolicy) String() string { @@ -189,11 +495,11 @@ func (rp RetentionPolicy) String() string { func (rp RetentionPolicy) MarshalJSON() ([]byte, error) { switch rp { case LimitsPolicy: - return json.Marshal(limitsPolicyString) + return limitsPolicyJSONBytes, nil case InterestPolicy: - return json.Marshal(interestPolicyString) + return interestPolicyJSONBytes, nil case WorkQueuePolicy: - return json.Marshal(workQueuePolicyString) + return workQueuePolicyJSONBytes, nil default: return nil, fmt.Errorf("can not marshal %v", rp) } @@ -201,11 +507,11 @@ func (rp RetentionPolicy) MarshalJSON() ([]byte, error) { func (rp *RetentionPolicy) UnmarshalJSON(data []byte) error { switch string(data) { - case jsonString(limitsPolicyString): + case limitsPolicyJSONString: *rp = LimitsPolicy - case jsonString(interestPolicyString): + case interestPolicyJSONString: *rp = InterestPolicy - case jsonString(workQueuePolicyString): + case workQueuePolicyJSONString: *rp = WorkQueuePolicy default: return fmt.Errorf("can not unmarshal %q", data) @@ -227,9 +533,9 @@ func (dp DiscardPolicy) String() string { func (dp DiscardPolicy) MarshalJSON() ([]byte, error) { switch dp { case DiscardOld: - return json.Marshal("old") + return []byte(`"old"`), nil case DiscardNew: - return json.Marshal("new") + return []byte(`"new"`), nil default: return nil, fmt.Errorf("can not marshal %v", dp) } @@ -237,9 +543,9 @@ func (dp DiscardPolicy) MarshalJSON() ([]byte, error) { func (dp *DiscardPolicy) UnmarshalJSON(data []byte) error { switch strings.ToLower(string(data)) { - case jsonString("old"): + case `"old"`: *dp = DiscardOld - case jsonString("new"): + case `"new"`: *dp = DiscardNew default: return fmt.Errorf("can not unmarshal %q", data) @@ -248,16 +554,25 @@ func (dp *DiscardPolicy) UnmarshalJSON(data []byte) error { } const ( - memoryStorageString = "memory" - fileStorageString = "file" + memoryStorageJSONString = `"memory"` + fileStorageJSONString = `"file"` + anyStorageJSONString = `"any"` +) + +var ( + memoryStorageJSONBytes = []byte(memoryStorageJSONString) + fileStorageJSONBytes = []byte(fileStorageJSONString) + anyStorageJSONBytes = []byte(anyStorageJSONString) ) func (st StorageType) String() string { switch st { case MemoryStorage: - return strings.Title(memoryStorageString) + return "Memory" case FileStorage: - return strings.Title(fileStorageString) + return "File" + case AnyStorage: + return "Any" default: return "Unknown Storage Type" } @@ -266,9 +581,11 @@ func (st StorageType) String() string { func (st StorageType) MarshalJSON() ([]byte, error) { switch st { case MemoryStorage: - return json.Marshal(memoryStorageString) + return memoryStorageJSONBytes, nil case FileStorage: - return json.Marshal(fileStorageString) + return fileStorageJSONBytes, nil + case AnyStorage: + return anyStorageJSONBytes, nil default: return nil, fmt.Errorf("can not marshal %v", st) } @@ -276,10 +593,12 @@ func (st StorageType) MarshalJSON() ([]byte, error) { func (st *StorageType) UnmarshalJSON(data []byte) error { switch string(data) { - case jsonString(memoryStorageString): + case memoryStorageJSONString: *st = MemoryStorage - case jsonString(fileStorageString): + case fileStorageJSONString: *st = FileStorage + case anyStorageJSONString: + *st = AnyStorage default: return fmt.Errorf("can not unmarshal %q", data) } @@ -287,19 +606,25 @@ func (st *StorageType) UnmarshalJSON(data []byte) error { } const ( - ackNonePolicyString = "none" - ackAllPolicyString = "all" - ackExplicitPolicyString = "explicit" + ackNonePolicyJSONString = `"none"` + ackAllPolicyJSONString = `"all"` + ackExplicitPolicyJSONString = `"explicit"` +) + +var ( + ackNonePolicyJSONBytes = []byte(ackNonePolicyJSONString) + ackAllPolicyJSONBytes = []byte(ackAllPolicyJSONString) + ackExplicitPolicyJSONBytes = []byte(ackExplicitPolicyJSONString) ) func (ap AckPolicy) MarshalJSON() ([]byte, error) { switch ap { case AckNone: - return json.Marshal(ackNonePolicyString) + return ackNonePolicyJSONBytes, nil case AckAll: - return json.Marshal(ackAllPolicyString) + return ackAllPolicyJSONBytes, nil case AckExplicit: - return json.Marshal(ackExplicitPolicyString) + return ackExplicitPolicyJSONBytes, nil default: return nil, fmt.Errorf("can not marshal %v", ap) } @@ -307,11 +632,11 @@ func (ap AckPolicy) MarshalJSON() ([]byte, error) { func (ap *AckPolicy) UnmarshalJSON(data []byte) error { switch string(data) { - case jsonString(ackNonePolicyString): + case ackNonePolicyJSONString: *ap = AckNone - case jsonString(ackAllPolicyString): + case ackAllPolicyJSONString: *ap = AckAll - case jsonString(ackExplicitPolicyString): + case ackExplicitPolicyJSONString: *ap = AckExplicit default: return fmt.Errorf("can not unmarshal %q", data) @@ -320,16 +645,21 @@ func (ap *AckPolicy) UnmarshalJSON(data []byte) error { } const ( - replayInstantPolicyString = "instant" - replayOriginalPolicyString = "original" + replayInstantPolicyJSONString = `"instant"` + replayOriginalPolicyJSONString = `"original"` +) + +var ( + replayInstantPolicyJSONBytes = []byte(replayInstantPolicyJSONString) + replayOriginalPolicyJSONBytes = []byte(replayOriginalPolicyJSONString) ) func (rp ReplayPolicy) MarshalJSON() ([]byte, error) { switch rp { case ReplayInstant: - return json.Marshal(replayInstantPolicyString) + return replayInstantPolicyJSONBytes, nil case ReplayOriginal: - return json.Marshal(replayOriginalPolicyString) + return replayOriginalPolicyJSONBytes, nil default: return nil, fmt.Errorf("can not marshal %v", rp) } @@ -337,9 +667,9 @@ func (rp ReplayPolicy) MarshalJSON() ([]byte, error) { func (rp *ReplayPolicy) UnmarshalJSON(data []byte) error { switch string(data) { - case jsonString(replayInstantPolicyString): + case replayInstantPolicyJSONString: *rp = ReplayInstant - case jsonString(replayOriginalPolicyString): + case replayOriginalPolicyJSONString: *rp = ReplayOriginal default: return fmt.Errorf("can not unmarshal %q", data) @@ -348,25 +678,38 @@ func (rp *ReplayPolicy) UnmarshalJSON(data []byte) error { } const ( - deliverAllPolicyString = "all" - deliverLastPolicyString = "last" - deliverNewPolicyString = "new" - deliverByStartSequenceString = "by_start_sequence" - deliverByStartTimeString = "by_start_time" - deliverUndefinedString = "undefined" + deliverAllPolicyJSONString = `"all"` + deliverLastPolicyJSONString = `"last"` + deliverNewPolicyJSONString = `"new"` + deliverByStartSequenceJSONString = `"by_start_sequence"` + deliverByStartTimeJSONString = `"by_start_time"` + deliverLastPerPolicyJSONString = `"last_per_subject"` + deliverUndefinedJSONString = `"undefined"` +) + +var ( + deliverAllPolicyJSONBytes = []byte(deliverAllPolicyJSONString) + deliverLastPolicyJSONBytes = []byte(deliverLastPolicyJSONString) + deliverNewPolicyJSONBytes = []byte(deliverNewPolicyJSONString) + deliverByStartSequenceJSONBytes = []byte(deliverByStartSequenceJSONString) + deliverByStartTimeJSONBytes = []byte(deliverByStartTimeJSONString) + deliverLastPerPolicyJSONBytes = []byte(deliverLastPerPolicyJSONString) + deliverUndefinedJSONBytes = []byte(deliverUndefinedJSONString) ) func (p *DeliverPolicy) UnmarshalJSON(data []byte) error { switch string(data) { - case jsonString(deliverAllPolicyString), jsonString(deliverUndefinedString): + case deliverAllPolicyJSONString, deliverUndefinedJSONString: *p = DeliverAll - case jsonString(deliverLastPolicyString): + case deliverLastPolicyJSONString: *p = DeliverLast - case jsonString(deliverNewPolicyString): + case deliverLastPerPolicyJSONString: + *p = DeliverLastPerSubject + case deliverNewPolicyJSONString: *p = DeliverNew - case jsonString(deliverByStartSequenceString): + case deliverByStartSequenceJSONString: *p = DeliverByStartSequence - case jsonString(deliverByStartTimeString): + case deliverByStartTimeJSONString: *p = DeliverByStartTime default: return fmt.Errorf("can not unmarshal %q", data) @@ -378,16 +721,83 @@ func (p *DeliverPolicy) UnmarshalJSON(data []byte) error { func (p DeliverPolicy) MarshalJSON() ([]byte, error) { switch p { case DeliverAll: - return json.Marshal(deliverAllPolicyString) + return deliverAllPolicyJSONBytes, nil case DeliverLast: - return json.Marshal(deliverLastPolicyString) + return deliverLastPolicyJSONBytes, nil + case DeliverLastPerSubject: + return deliverLastPerPolicyJSONBytes, nil case DeliverNew: - return json.Marshal(deliverNewPolicyString) + return deliverNewPolicyJSONBytes, nil case DeliverByStartSequence: - return json.Marshal(deliverByStartSequenceString) + return deliverByStartSequenceJSONBytes, nil case DeliverByStartTime: - return json.Marshal(deliverByStartTimeString) + return deliverByStartTimeJSONBytes, nil default: - return json.Marshal(deliverUndefinedString) + return deliverUndefinedJSONBytes, nil } } + +func isOutOfSpaceErr(err error) bool { + return err != nil && (strings.Contains(err.Error(), "no space left")) +} + +// For when our upper layer catchup detects its missing messages from the beginning of the stream. +var errFirstSequenceMismatch = errors.New("first sequence mismatch") + +func isClusterResetErr(err error) bool { + return err == errLastSeqMismatch || err == ErrStoreEOF || err == errFirstSequenceMismatch || errors.Is(err, errCatchupAbortedNoLeader) || err == errCatchupTooManyRetries +} + +// Copy all fields. +func (smo *StoreMsg) copy(sm *StoreMsg) { + if sm.buf != nil { + sm.buf = sm.buf[:0] + } + sm.buf = append(sm.buf, smo.buf...) + // We set cap on header in case someone wants to expand it. + sm.hdr, sm.msg = sm.buf[:len(smo.hdr):len(smo.hdr)], sm.buf[len(smo.hdr):] + sm.subj, sm.seq, sm.ts = smo.subj, smo.seq, smo.ts +} + +// Clear all fields except underlying buffer but reset that if present to [:0]. +func (sm *StoreMsg) clear() { + if sm == nil { + return + } + *sm = StoreMsg{_EMPTY_, nil, nil, sm.buf, 0, 0} + if len(sm.buf) > 0 { + sm.buf = sm.buf[:0] + } +} + +// Note this will avoid a copy of the data used for the string, but it will also reference the existing slice's data pointer. +// So this should be used sparingly when we know the encompassing byte slice's lifetime is the same. +func bytesToString(b []byte) string { + if len(b) == 0 { + return _EMPTY_ + } + p := unsafe.SliceData(b) + return unsafe.String(p, len(b)) +} + +// Same in reverse. Used less often. +func stringToBytes(s string) []byte { + if len(s) == 0 { + return nil + } + p := unsafe.StringData(s) + b := unsafe.Slice(p, len(s)) + return b +} + +// Forces a copy of a string, for use in the case that you might have been passed a value when bytesToString was used, +// but now you need a separate copy of it to store for longer-term use. +func copyString(s string) string { + b := make([]byte, len(s)) + copy(b, s) + return bytesToString(b) +} + +func isPermissionError(err error) bool { + return err != nil && os.IsPermission(err) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stream.go b/vendor/github.com/nats-io/nats-server/v2/server/stream.go index fa9ab96..3456f09 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/stream.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/stream.go @@ -1,4 +1,4 @@ -// Copyright 2019-2020 The NATS Authors +// Copyright 2019-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,50 +16,156 @@ package server import ( "archive/tar" "bytes" - "compress/gzip" "encoding/json" "errors" "fmt" "io" - "io/ioutil" "math" + "math/rand" "os" - "path" "path/filepath" "reflect" + "slices" "strconv" + "strings" "sync" + "sync/atomic" "time" + "github.com/klauspost/compress/s2" + "github.com/nats-io/nats-server/v2/server/gsl" "github.com/nats-io/nuid" ) +// StreamConfigRequest is used to create or update a stream. +type StreamConfigRequest struct { + StreamConfig + // This is not part of the StreamConfig, because its scoped to request, + // and not to the stream itself. + Pedantic bool `json:"pedantic,omitempty"` +} + // StreamConfig will determine the name, subjects and retention policy // for a given stream. If subjects is empty the name will be used. type StreamConfig struct { - Name string `json:"name"` - Subjects []string `json:"subjects,omitempty"` - Retention RetentionPolicy `json:"retention"` - MaxConsumers int `json:"max_consumers"` - MaxMsgs int64 `json:"max_msgs"` - MaxBytes int64 `json:"max_bytes"` - Discard DiscardPolicy `json:"discard"` - MaxAge time.Duration `json:"max_age"` - MaxMsgSize int32 `json:"max_msg_size,omitempty"` - Storage StorageType `json:"storage"` - Replicas int `json:"num_replicas"` - NoAck bool `json:"no_ack,omitempty"` - Template string `json:"template_owner,omitempty"` - Duplicates time.Duration `json:"duplicate_window,omitempty"` - - // These are non public configuration options. - // If you add new options, check fileStreamInfoJSON in order for them to - // be properly persisted/recovered, if needed. - internal bool - allowNoSubject bool -} - -const JSApiPubAckResponseType = "io.nats.jetstream.api.v1.pub_ack_response" + Name string `json:"name"` + Description string `json:"description,omitempty"` + Subjects []string `json:"subjects,omitempty"` + Retention RetentionPolicy `json:"retention"` + MaxConsumers int `json:"max_consumers"` + MaxMsgs int64 `json:"max_msgs"` + MaxBytes int64 `json:"max_bytes"` + MaxAge time.Duration `json:"max_age"` + MaxMsgsPer int64 `json:"max_msgs_per_subject"` + MaxMsgSize int32 `json:"max_msg_size,omitempty"` + Discard DiscardPolicy `json:"discard"` + Storage StorageType `json:"storage"` + Replicas int `json:"num_replicas"` + NoAck bool `json:"no_ack,omitempty"` + Template string `json:"template_owner,omitempty"` + Duplicates time.Duration `json:"duplicate_window,omitempty"` + Placement *Placement `json:"placement,omitempty"` + Mirror *StreamSource `json:"mirror,omitempty"` + Sources []*StreamSource `json:"sources,omitempty"` + Compression StoreCompression `json:"compression"` + FirstSeq uint64 `json:"first_seq,omitempty"` + + // Allow applying a subject transform to incoming messages before doing anything else + SubjectTransform *SubjectTransformConfig `json:"subject_transform,omitempty"` + + // Allow republish of the message after being sequenced and stored. + RePublish *RePublish `json:"republish,omitempty"` + + // Allow higher performance, direct access to get individual messages. E.g. KeyValue + AllowDirect bool `json:"allow_direct"` + // Allow higher performance and unified direct access for mirrors as well. + MirrorDirect bool `json:"mirror_direct"` + + // Allow KV like semantics to also discard new on a per subject basis + DiscardNewPer bool `json:"discard_new_per_subject,omitempty"` + + // Optional qualifiers. These can not be modified after set to true. + + // Sealed will seal a stream so no messages can get out or in. + Sealed bool `json:"sealed"` + // DenyDelete will restrict the ability to delete messages. + DenyDelete bool `json:"deny_delete"` + // DenyPurge will restrict the ability to purge messages. + DenyPurge bool `json:"deny_purge"` + // AllowRollup allows messages to be placed into the system and purge + // all older messages using a special msg header. + AllowRollup bool `json:"allow_rollup_hdrs"` + + // The following defaults will apply to consumers when created against + // this stream, unless overridden manually. + // TODO(nat): Can/should we name these better? + ConsumerLimits StreamConsumerLimits `json:"consumer_limits"` + + // AllowMsgTTL allows header initiated per-message TTLs. If disabled, + // then the `NATS-TTL` header will be ignored. + AllowMsgTTL bool `json:"allow_msg_ttl"` + + // SubjectDeleteMarkerTTL sets the TTL of delete marker messages left behind by + // subject delete markers. + SubjectDeleteMarkerTTL time.Duration `json:"subject_delete_marker_ttl,omitempty"` + + // Metadata is additional metadata for the Stream. + Metadata map[string]string `json:"metadata,omitempty"` +} + +// clone performs a deep copy of the StreamConfig struct, returning a new clone with +// all values copied. +func (cfg *StreamConfig) clone() *StreamConfig { + clone := *cfg + if cfg.Placement != nil { + placement := *cfg.Placement + clone.Placement = &placement + } + if cfg.Mirror != nil { + mirror := *cfg.Mirror + clone.Mirror = &mirror + } + if len(cfg.Sources) > 0 { + clone.Sources = make([]*StreamSource, len(cfg.Sources)) + for i, cfgSource := range cfg.Sources { + source := *cfgSource + clone.Sources[i] = &source + } + } + if cfg.SubjectTransform != nil { + transform := *cfg.SubjectTransform + clone.SubjectTransform = &transform + } + if cfg.RePublish != nil { + rePublish := *cfg.RePublish + clone.RePublish = &rePublish + } + if cfg.Metadata != nil { + clone.Metadata = make(map[string]string, len(cfg.Metadata)) + for k, v := range cfg.Metadata { + clone.Metadata[k] = v + } + } + return &clone +} + +type StreamConsumerLimits struct { + InactiveThreshold time.Duration `json:"inactive_threshold,omitempty"` + MaxAckPending int `json:"max_ack_pending,omitempty"` +} + +// SubjectTransformConfig is for applying a subject transform (to matching messages) before doing anything else when a new message is received +type SubjectTransformConfig struct { + Source string `json:"src"` + Destination string `json:"dest"` +} + +// RePublish is for republishing messages once committed to a stream. +type RePublish struct { + Source string `json:"src,omitempty"` + Destination string `json:"dest"` + HeadersOnly bool `json:"headers_only,omitempty"` +} // JSPubAckResponse is a formal response to a publish operation. type JSPubAckResponse struct { @@ -67,98 +173,433 @@ type JSPubAckResponse struct { *PubAck } +// ToError checks if the response has a error and if it does converts it to an error +// avoiding the pitfalls described by https://yourbasic.org/golang/gotcha-why-nil-error-not-equal-nil/ +func (r *JSPubAckResponse) ToError() error { + if r.Error == nil { + return nil + } + return r.Error +} + // PubAck is the detail you get back from a publish to a stream that was successful. // e.g. +OK {"stream": "Orders", "seq": 22} type PubAck struct { Stream string `json:"stream"` Sequence uint64 `json:"seq"` + Domain string `json:"domain,omitempty"` Duplicate bool `json:"duplicate,omitempty"` } // StreamInfo shows config and current state for this stream. type StreamInfo struct { - Config StreamConfig `json:"config"` - Created time.Time `json:"created"` - State StreamState `json:"state"` + Config StreamConfig `json:"config"` + Created time.Time `json:"created"` + State StreamState `json:"state"` + Domain string `json:"domain,omitempty"` + Cluster *ClusterInfo `json:"cluster,omitempty"` + Mirror *StreamSourceInfo `json:"mirror,omitempty"` + Sources []*StreamSourceInfo `json:"sources,omitempty"` + Alternates []StreamAlternate `json:"alternates,omitempty"` + // TimeStamp indicates when the info was gathered + TimeStamp time.Time `json:"ts"` +} + +// streamInfoClusterResponse is a response used in a cluster to communicate the stream info +// back to the meta leader as part of a stream list request. +type streamInfoClusterResponse struct { + StreamInfo + OfflineReason string `json:"offline_reason,omitempty"` // Reporting when a stream is offline. +} + +type StreamAlternate struct { + Name string `json:"name"` + Domain string `json:"domain,omitempty"` + Cluster string `json:"cluster"` +} + +// ClusterInfo shows information about the underlying set of servers +// that make up the stream or consumer. +type ClusterInfo struct { + Name string `json:"name,omitempty"` + RaftGroup string `json:"raft_group,omitempty"` + Leader string `json:"leader,omitempty"` + LeaderSince *time.Time `json:"leader_since,omitempty"` + SystemAcc bool `json:"system_account,omitempty"` + TrafficAcc string `json:"traffic_account,omitempty"` + Replicas []*PeerInfo `json:"replicas,omitempty"` +} + +// PeerInfo shows information about all the peers in the cluster that +// are supporting the stream or consumer. +type PeerInfo struct { + Name string `json:"name"` // Name is the unique name for the peer + Current bool `json:"current"` // Current indicates if it was seen recently and fully caught up + Offline bool `json:"offline,omitempty"` // Offline indicates if it has not been seen recently + Active time.Duration `json:"active"` // Active is the timestamp it was last active + Lag uint64 `json:"lag,omitempty"` // Lag is how many operations behind it is + Peer string `json:"peer"` // Peer is the unique ID for the peer + // For migrations. + cluster string +} + +// StreamSourceInfo shows information about an upstream stream source. +type StreamSourceInfo struct { + Name string `json:"name"` + External *ExternalStream `json:"external,omitempty"` + Lag uint64 `json:"lag"` + Active time.Duration `json:"active"` + Error *ApiError `json:"error,omitempty"` + FilterSubject string `json:"filter_subject,omitempty"` + SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"` +} + +// StreamSource dictates how streams can source from other streams. +type StreamSource struct { + Name string `json:"name"` + OptStartSeq uint64 `json:"opt_start_seq,omitempty"` + OptStartTime *time.Time `json:"opt_start_time,omitempty"` + FilterSubject string `json:"filter_subject,omitempty"` + SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"` + External *ExternalStream `json:"external,omitempty"` + + // Internal + iname string // For indexing when stream names are the same for multiple sources. +} + +// ExternalStream allows you to qualify access to a stream source in another account or domain. +type ExternalStream struct { + ApiPrefix string `json:"api"` + DeliverPrefix string `json:"deliver"` +} + +// Will return the domain for this external stream. +func (ext *ExternalStream) Domain() string { + if ext == nil || ext.ApiPrefix == _EMPTY_ { + return _EMPTY_ + } + return tokenAt(ext.ApiPrefix, 2) } +// For managing stream ingest. +const ( + streamDefaultMaxQueueMsgs = 10_000 + streamDefaultMaxQueueBytes = 1024 * 1024 * 128 +) + // Stream is a jetstream stream of messages. When we receive a message internally destined -// for a Stream we will direct link from the client to this Stream structure. -type Stream struct { - mu sync.RWMutex - jsa *jsAccount - client *client - sid int - pubAck []byte - sendq chan *jsPubMsg - store StreamStore - lseq uint64 - lmsgId string - consumers map[string]*Consumer - numFilter int - config StreamConfig - created time.Time - ddmap map[string]*ddentry - ddarr []*ddentry - ddindex int - ddtmr *time.Timer +// for a Stream we will direct link from the client to this structure. +type stream struct { + mu sync.RWMutex // Read/write lock for the stream. + js *jetStream // The internal *jetStream for the account. + jsa *jsAccount // The JetStream account-level information. + acc *Account // The account this stream is defined in. + srv *Server // The server we are running in. + client *client // The internal JetStream client. + sysc *client // The internal JetStream system client. + + // The current last subscription ID for the subscriptions through `client`. + // Those subscriptions are for the subjects filters being listened to and captured by the stream. + sid atomic.Uint64 + + pubAck []byte // The template (prefix) to generate the pubAck responses for this stream quickly. + outq *jsOutQ // Queue of *jsPubMsg for sending messages. + msgs *ipQueue[*inMsg] // Intra-process queue for the ingress of messages. + gets *ipQueue[*directGetReq] // Intra-process queue for the direct get requests. + store StreamStore // The storage for this stream. + ackq *ipQueue[uint64] // Intra-process queue for acks. + lseq uint64 // The sequence number of the last message stored in the stream. + lmsgId string // The de-duplication message ID of the last message stored in the stream. + consumers map[string]*consumer // The consumers for this stream. + numFilter int // The number of filtered consumers. + cfg StreamConfig // The stream's config. + cfgMu sync.RWMutex // Config mutex used to solve some races with consumer code + created time.Time // Time the stream was created. + stype StorageType // The storage type. + tier string // The tier is the number of replicas for the stream (e.g. "R1" or "R3"). + ddmap map[string]*ddentry // The dedupe map. + ddarr []*ddentry // The dedupe array. + ddindex int // The dedupe index. + ddtmr *time.Timer // The dedupe timer. + qch chan struct{} // The quit channel. + mqch chan struct{} // The monitor's quit channel. + active bool // Indicates that there are active internal subscriptions (for the subject filters) + // and/or mirror/sources consumers are scheduled to be established or already started. + ddloaded bool // set to true when the deduplication structures are been built. + closed atomic.Bool // Set to true when stop() is called on the stream. + cisrun atomic.Bool // Indicates one checkInterestState is already running. + + // Mirror + mirror *sourceInfo + + // Sources + sources map[string]*sourceInfo + sourceSetupSchedules map[string]*time.Timer + sourcesConsumerSetup *time.Timer + smsgs *ipQueue[*inMsg] // Intra-process queue for all incoming sourced messages. + + // Indicates we have direct consumers. + directs int + + // For input subject transform. + itr *subjectTransform + + // For republishing. + tr *subjectTransform + + // For processing consumers without main stream lock. + clsMu sync.RWMutex + cList []*consumer // Consumer list. + sch chan struct{} // Channel to signal consumers. + sigq *ipQueue[*cMsg] // Intra-process queue for the messages to signal to the consumers. + csl *gsl.GenericSublist[*consumer] // Consumer subscription list. + + // Leader will store seq/msgTrace in clustering mode. Used in applyStreamEntries + // to know if trace event should be sent after processing. + mt map[uint64]*msgTrace + + // For non limits policy streams when they process an ack before the actual msg. + // Can happen in stretch clusters, multi-cloud, or during catchup for a restarted server. + preAcks map[uint64]map[*consumer]struct{} + + // TODO(dlc) - Hide everything below behind two pointers. + // Clustered mode. + sa *streamAssignment // What the meta controller uses to assign streams to peers. + node RaftNode // Our RAFT node for the stream's group. + catchup atomic.Bool // Used to signal we are in catchup mode. + catchups map[string]uint64 // The number of messages that need to be caught per peer. + syncSub *subscription // Internal subscription for sync messages (on "$JSC.SYNC"). + infoSub *subscription // Internal subscription for stream info requests. + clMu sync.Mutex // The mutex for clseq and clfs. + clseq uint64 // The current last seq being proposed to the NRG layer. + clfs uint64 // The count (offset) of the number of failed NRG sequences used to compute clseq. + inflight map[uint64]uint64 // Inflight message sizes per clseq. + lqsent time.Time // The time at which the last lost quorum advisory was sent. Used to rate limit. + uch chan struct{} // The channel to signal updates to the monitor routine. + inMonitor bool // True if the monitor routine has been started. + + expectedPerSubjectSequence map[uint64]string // Inflight 'expected per subject' subjects per clseq. + expectedPerSubjectInProcess map[string]struct{} // Current 'expected per subject' subjects in process. + + // Direct get subscription. + directSub *subscription + lastBySub *subscription + + monitorWg sync.WaitGroup // Wait group for the monitor routine. + + // If standalone/single-server, the offline reason needs to be stored directly in the stream. + // Otherwise, if clustered it will be part of the stream assignment. + offlineReason string +} + +type sourceInfo struct { + name string // The name of the stream being sourced. + iname string // The unique index name of this particular source. + cname string // The name of the current consumer for this source. + sub *subscription // The subscription to the consumer. + + // (mirrors only) The subscription to the direct get request subject for + // the source stream's name on the `_sys_` queue group. + dsub *subscription + + // (mirrors only) The subscription to the direct get last per subject request subject for + // the source stream's name on the `_sys_` queue group. + lbsub *subscription + + msgs *ipQueue[*inMsg] // Intra-process queue for incoming messages. + sseq uint64 // Last stream message sequence number seen from the source. + dseq uint64 // Last delivery (i.e. consumer's) sequence number. + lag uint64 // 0 or number of messages pending (as last reported by the consumer) - 1. + err *ApiError // The API error that caused the last consumer setup to fail. + fails int // The number of times trying to setup the consumer failed. + last atomic.Int64 // Time the consumer was created or of last message it received. + lreq time.Time // The last time setupMirrorConsumer/setupSourceConsumer was called. + qch chan struct{} // Quit channel. + sip bool // Setup in progress. + wg sync.WaitGroup // WaitGroup for the consumer's go routine. + sf string // The subject filter. + sfs []string // The subject filters. + trs []*subjectTransform // The subject transforms. } +// For mirrors and direct get +const ( + dgetGroup = sysGroup + dgetCaughtUpThresh = 10 +) + // Headers for published messages. const ( - JSMsgId = "Nats-Msg-Id" - JSExpectedStream = "Nats-Expected-Stream" - JSExpectedLastSeq = "Nats-Expected-Last-Sequence" - JSExpectedLastMsgId = "Nats-Expected-Last-Msg-Id" + JSMsgId = "Nats-Msg-Id" + JSExpectedStream = "Nats-Expected-Stream" + JSExpectedLastSeq = "Nats-Expected-Last-Sequence" + JSExpectedLastSubjSeq = "Nats-Expected-Last-Subject-Sequence" + JSExpectedLastSubjSeqSubj = "Nats-Expected-Last-Subject-Sequence-Subject" + JSExpectedLastMsgId = "Nats-Expected-Last-Msg-Id" + JSStreamSource = "Nats-Stream-Source" + JSLastConsumerSeq = "Nats-Last-Consumer" + JSLastStreamSeq = "Nats-Last-Stream" + JSConsumerStalled = "Nats-Consumer-Stalled" + JSMsgRollup = "Nats-Rollup" + JSMsgSize = "Nats-Msg-Size" + JSResponseType = "Nats-Response-Type" + JSMessageTTL = "Nats-TTL" + JSMarkerReason = "Nats-Marker-Reason" +) + +// Headers for published KV messages. +var ( + KVOperation = "KV-Operation" + KVOperationValuePurge = []byte("PURGE") +) + +// Headers for republished messages and direct gets. +const ( + JSStream = "Nats-Stream" + JSSequence = "Nats-Sequence" + JSTimeStamp = "Nats-Time-Stamp" + JSSubject = "Nats-Subject" + JSLastSequence = "Nats-Last-Sequence" + JSNumPending = "Nats-Num-Pending" + JSUpToSequence = "Nats-UpTo-Sequence" +) + +// Rollups, can be subject only or all messages. +const ( + JSMsgRollupSubject = "sub" + JSMsgRollupAll = "all" +) + +// Applied limits in the Nats-Applied-Limit header. +const ( + JSMarkerReasonMaxAge = "MaxAge" + JSMarkerReasonPurge = "Purge" + JSMarkerReasonRemove = "Remove" +) + +const ( + jsCreateResponse = "create" ) // Dedupe entry type ddentry struct { - id string - seq uint64 - ts int64 + id string // The unique message ID provided by the client. + seq uint64 // The sequence number of the message. + ts int64 // The timestamp of the message. } // Replicas Range -const ( - StreamDefaultReplicas = 1 - StreamMaxReplicas = 7 -) +const StreamMaxReplicas = 5 // AddStream adds a stream for the given account. -func (a *Account) AddStream(config *StreamConfig) (*Stream, error) { - return a.AddStreamWithStore(config, nil) +func (a *Account) addStream(config *StreamConfig) (*stream, error) { + return a.addStreamWithAssignment(config, nil, nil, false) } // AddStreamWithStore adds a stream for the given account with custome store config options. -func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*Stream, error) { +func (a *Account) addStreamWithStore(config *StreamConfig, fsConfig *FileStoreConfig) (*stream, error) { + return a.addStreamWithAssignment(config, fsConfig, nil, false) +} + +func (a *Account) addStreamPedantic(config *StreamConfig, pedantic bool) (*stream, error) { + return a.addStreamWithAssignment(config, nil, nil, pedantic) +} + +func (a *Account) addStreamWithAssignment(config *StreamConfig, fsConfig *FileStoreConfig, sa *streamAssignment, pedantic bool) (*stream, error) { s, jsa, err := a.checkForJetStream() if err != nil { return nil, err } + // If we do not have the stream currently assigned to us in cluster mode we will proceed but warn. + // This can happen on startup with restored state where on meta replay we still do not have + // the assignment. Running in single server mode this always returns true. + if !jsa.streamAssigned(config.Name) { + s.Debugf("Stream '%s > %s' does not seem to be assigned to this server", a.Name, config.Name) + } + // Sensible defaults. - cfg, err := checkStreamCfg(config) - if err != nil { - return nil, err + ccfg, apiErr := s.checkStreamCfg(config, a, pedantic) + if apiErr != nil { + return nil, apiErr + } + cfg := &ccfg + + singleServerMode := !s.JetStreamIsClustered() && s.standAloneMode() + if singleServerMode && cfg.Replicas > 1 { + return nil, ApiErrors[JSStreamReplicasNotSupportedErr] + } + + // Make sure we are ok when these are done in parallel. + // We used to call Add(1) in the "else" clause of the "if loaded" + // statement. This caused a data race because it was possible + // that one go routine stores (with count==0) and another routine + // gets "loaded==true" and calls wg.Wait() while the other routine + // then calls wg.Add(1). It also could mean that two routines execute + // the rest of the code concurrently. + swg := &sync.WaitGroup{} + swg.Add(1) + v, loaded := jsa.inflight.LoadOrStore(cfg.Name, swg) + wg := v.(*sync.WaitGroup) + if loaded { + wg.Wait() + // This waitgroup is "thrown away" (since there was an existing one). + swg.Done() + } else { + defer func() { + jsa.inflight.Delete(cfg.Name) + wg.Done() + }() } + js, isClustered := jsa.jetStreamAndClustered() jsa.mu.Lock() if mset, ok := jsa.streams[cfg.Name]; ok { jsa.mu.Unlock() // Check to see if configs are same. - ocfg := mset.Config() - if reflect.DeepEqual(ocfg, cfg) { + ocfg := mset.config() + + // set the index name on cfg since it would not contain a value for iname while the return from mset.config() does to ensure the DeepEqual works + for _, s := range cfg.Sources { + s.setIndexName() + } + + // Hold lock, because we'll be reading from and writing to a shared object. + js.mu.Lock() + copyStreamMetadata(cfg, &ocfg) + deepEqual := reflect.DeepEqual(cfg, &ocfg) + js.mu.Unlock() + if deepEqual { + if sa != nil { + mset.setStreamAssignment(sa) + } return mset, nil } else { - return nil, fmt.Errorf("stream name already in use") + return nil, ApiErrors[JSStreamNameExistErr] } } - // Check for limits. - if err := jsa.checkLimits(&cfg); err != nil { - jsa.mu.Unlock() + jsa.usageMu.RLock() + selected, tier, hasTier := jsa.selectLimits(cfg.Replicas) + jsa.usageMu.RUnlock() + reserved := int64(0) + if !isClustered { + reserved = jsa.tieredReservation(tier, cfg) + } + jsa.mu.Unlock() + + if !hasTier { + return nil, NewJSNoLimitsError() + } + js.mu.RLock() + if isClustered { + _, reserved = tieredStreamAndReservationCount(js.cluster.streams[a.Name], tier, cfg) + } + if err := js.checkAllLimits(&selected, cfg, reserved, 0); err != nil { + js.mu.RUnlock() return nil, err } + js.mu.RUnlock() + jsa.mu.Lock() // Check for template ownership if present. if cfg.Template != _EMPTY_ && jsa.account != nil { if !jsa.checkTemplateOwnership(cfg.Template, cfg.Name) { @@ -167,22 +608,151 @@ func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreCo } } - // Check for overlapping subjects. These are not allowed for now. - if jsa.subjectsOverlap(cfg.Subjects) { + // If mirror, check if the transforms (if any) are valid. + if cfg.Mirror != nil { + if len(cfg.Mirror.SubjectTransforms) == 0 { + if cfg.Mirror.FilterSubject != _EMPTY_ && !IsValidSubject(cfg.Mirror.FilterSubject) { + jsa.mu.Unlock() + return nil, fmt.Errorf("subject filter '%s' for the mirror %w", cfg.Mirror.FilterSubject, ErrBadSubject) + } + } else { + for _, st := range cfg.Mirror.SubjectTransforms { + if st.Source != _EMPTY_ && !IsValidSubject(st.Source) { + jsa.mu.Unlock() + return nil, fmt.Errorf("invalid subject transform source '%s' for the mirror: %w", st.Source, ErrBadSubject) + } + // check the transform, if any, is valid + if st.Destination != _EMPTY_ { + if _, err = NewSubjectTransform(st.Source, st.Destination); err != nil { + jsa.mu.Unlock() + return nil, fmt.Errorf("subject transform from '%s' to '%s' for the mirror: %w", st.Source, st.Destination, err) + } + } + } + } + } + + // Setup our internal indexed names here for sources and check if the transforms (if any) are valid. + for _, ssi := range cfg.Sources { + if len(ssi.SubjectTransforms) == 0 { + // check the filter, if any, is valid + if ssi.FilterSubject != _EMPTY_ && !IsValidSubject(ssi.FilterSubject) { + jsa.mu.Unlock() + return nil, fmt.Errorf("subject filter '%s' for the source: %w", ssi.FilterSubject, ErrBadSubject) + } + } else { + for _, st := range ssi.SubjectTransforms { + if st.Source != _EMPTY_ && !IsValidSubject(st.Source) { + jsa.mu.Unlock() + return nil, fmt.Errorf("subject filter '%s' for the source: %w", st.Source, ErrBadSubject) + } + // check the transform, if any, is valid + if st.Destination != _EMPTY_ { + if _, err = NewSubjectTransform(st.Source, st.Destination); err != nil { + jsa.mu.Unlock() + return nil, fmt.Errorf("subject transform from '%s' to '%s' for the source: %w", st.Source, st.Destination, err) + } + } + } + } + } + + // Check for overlapping subjects with other streams. + // These are not allowed for now. + if jsa.subjectsOverlap(cfg.Subjects, nil) { + jsa.mu.Unlock() + return nil, NewJSStreamSubjectOverlapError() + } + + if !hasTier { jsa.mu.Unlock() - return nil, fmt.Errorf("subjects overlap with an existing stream") + return nil, fmt.Errorf("no applicable tier found") } - // Setup the internal client. + // Setup the internal clients. c := s.createInternalJetStreamClient() - mset := &Stream{jsa: jsa, config: cfg, client: c, consumers: make(map[string]*Consumer)} + ic := s.createInternalJetStreamClient() + + // Work out the stream ingest limits. + mlen := s.opts.StreamMaxBufferedMsgs + msz := uint64(s.opts.StreamMaxBufferedSize) + if mlen == 0 { + mlen = streamDefaultMaxQueueMsgs + } + if msz == 0 { + msz = streamDefaultMaxQueueBytes + } + + qpfx := fmt.Sprintf("[ACC:%s] stream '%s' ", a.Name, config.Name) + mset := &stream{ + acc: a, + jsa: jsa, + cfg: *cfg, + js: js, + srv: s, + client: c, + sysc: ic, + tier: tier, + stype: cfg.Storage, + consumers: make(map[string]*consumer), + msgs: newIPQueue[*inMsg](s, qpfx+"messages", + ipqSizeCalculation(func(msg *inMsg) uint64 { + return uint64(len(msg.hdr) + len(msg.msg) + len(msg.rply) + len(msg.subj)) + }), + ipqLimitByLen[*inMsg](mlen), + ipqLimitBySize[*inMsg](msz), + ), + gets: newIPQueue[*directGetReq](s, qpfx+"direct gets"), + qch: make(chan struct{}), + mqch: make(chan struct{}), + uch: make(chan struct{}, 4), + sch: make(chan struct{}, 1), + created: time.Now().UTC(), + } + + // Add created timestamp used for the store, must match that of the stream assignment if it exists. + if sa != nil { + // The following assignment does not require mutex + // protection: sa.Created is immutable. + mset.created = sa.Created + } + + // Start our signaling routine to process consumers. + mset.sigq = newIPQueue[*cMsg](s, qpfx+"obs") // of *cMsg + go mset.signalConsumersLoop() + + // For no-ack consumers when we are interest retention. + if cfg.Retention != LimitsPolicy { + mset.ackq = newIPQueue[uint64](s, qpfx+"acks") + } + + // Check for input subject transform + if cfg.SubjectTransform != nil { + tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination) + if err != nil { + jsa.mu.Unlock() + return nil, fmt.Errorf("stream subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err) + } + mset.itr = tr + } - jsa.streams[cfg.Name] = mset - storeDir := path.Join(jsa.storeDir, streamsDir, cfg.Name) + // Check for RePublish. + if cfg.RePublish != nil { + tr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination) + if err != nil { + jsa.mu.Unlock() + return nil, fmt.Errorf("stream republish transform from '%s' to '%s': %w", cfg.RePublish.Source, cfg.RePublish.Destination, err) + } + // Assign our transform for republishing. + mset.tr = tr + } + storeDir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name) jsa.mu.Unlock() - // Bind to the account. + // Bind to the user account. c.registerWithAccount(a) + // Bind to the system account. + ic.registerWithAccount(s.SystemAccount()) // Create the appropriate storage fsCfg := fsConfig @@ -195,37 +765,323 @@ func (a *Account) AddStreamWithStore(config *StreamConfig, fsConfig *FileStoreCo } } fsCfg.StoreDir = storeDir + fsCfg.AsyncFlush = false + // Grab configured sync interval. + fsCfg.SyncInterval = s.getOpts().SyncInterval + fsCfg.SyncAlways = s.getOpts().SyncAlways + fsCfg.Compression = config.Compression + if err := mset.setupStore(fsCfg); err != nil { - mset.Delete() - return nil, err + mset.stop(true, false) + return nil, NewJSStreamStoreFailedError(err) } + + // Create our pubAck template here. Better than json marshal each time on success. + if domain := s.getOpts().JetStreamDomain; domain != _EMPTY_ { + mset.pubAck = []byte(fmt.Sprintf("{%q:%q, %q:%q, %q:", "stream", cfg.Name, "domain", domain, "seq")) + } else { + mset.pubAck = []byte(fmt.Sprintf("{%q:%q, %q:", "stream", cfg.Name, "seq")) + } + end := len(mset.pubAck) + mset.pubAck = mset.pubAck[:end:end] + + // Set our known last sequence. + var state StreamState + mset.store.FastState(&state) + + // Possible race with consumer.setLeader during recovery. + mset.mu.Lock() + mset.lseq = state.LastSeq + mset.mu.Unlock() + + // If no msgs (new stream), set dedupe state loaded to true. + if state.Msgs == 0 { + mset.ddloaded = true + } + + // Set our stream assignment if in clustered mode. + reserveResources := true + if sa != nil { + mset.setStreamAssignment(sa) + + // If the stream is resetting we must not double-account resources, they were already accounted for. + js.mu.Lock() + if sa.resetting { + reserveResources, sa.resetting = false, false + } + js.mu.Unlock() + } + // Setup our internal send go routine. mset.setupSendCapabilities() - // Create our pubAck template here. Better than json marshal each time on success. - b, _ := json.Marshal(&JSPubAckResponse{PubAck: &PubAck{Stream: cfg.Name, Sequence: math.MaxUint64}}) - end := bytes.Index(b, []byte(strconv.FormatUint(math.MaxUint64, 10))) - // We need to force cap here to make sure this is a copy when sending a response. - mset.pubAck = b[:end:end] + // Reserve resources if MaxBytes present. + if reserveResources { + mset.js.reserveStreamResources(&mset.cfg) + } - // Rebuild dedupe as needed. - mset.rebuildDedupe() + // Call directly to set leader if not in clustered mode. + // This can be called though before we actually setup clustering, so check both. + if singleServerMode { + if err := mset.setLeader(true); err != nil { + mset.stop(true, false) + return nil, err + } + } - // Setup subscriptions - if err := mset.subscribeToStream(); err != nil { - mset.Delete() - return nil, err + // This is always true in single server mode. + if mset.IsLeader() { + // Send advisory. + var suppress bool + if !s.standAloneMode() && sa == nil { + if cfg.Replicas > 1 { + suppress = true + } + } else if sa != nil { + suppress = sa.responded + } + if !suppress { + mset.sendCreateAdvisory() + } } - // Send advisory. - mset.sendCreateAdvisory() + // Register with our account last. + jsa.mu.Lock() + jsa.streams[cfg.Name] = mset + jsa.mu.Unlock() return mset, nil } +// Composes the index name. Contains the stream name, subject filter, and transform destination +// when the stream is external we will use the api prefix as part of the index name +// (as the same stream name could be used in multiple JS domains) +func (ssi *StreamSource) composeIName() string { + var iName = ssi.Name + + if ssi.External != nil { + iName = iName + ":" + getHash(ssi.External.ApiPrefix) + } + + source := ssi.FilterSubject + destination := fwcs + + if len(ssi.SubjectTransforms) == 0 { + // normalize filter and destination in case they are empty + if source == _EMPTY_ { + source = fwcs + } + if destination == _EMPTY_ { + destination = fwcs + } + } else { + var sources, destinations []string + + for _, tr := range ssi.SubjectTransforms { + trsrc, trdest := tr.Source, tr.Destination + if trsrc == _EMPTY_ { + trsrc = fwcs + } + if trdest == _EMPTY_ { + trdest = fwcs + } + sources = append(sources, trsrc) + destinations = append(destinations, trdest) + } + source = strings.Join(sources, "\f") + destination = strings.Join(destinations, "\f") + } + + return strings.Join([]string{iName, source, destination}, " ") +} + +// Sets the index name. +func (ssi *StreamSource) setIndexName() { + ssi.iname = ssi.composeIName() +} + +func (mset *stream) streamAssignment() *streamAssignment { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.sa +} + +func (mset *stream) setStreamAssignment(sa *streamAssignment) { + var node RaftNode + var peers []string + + mset.mu.RLock() + js := mset.js + mset.mu.RUnlock() + + if js != nil { + js.mu.RLock() + if sa.Group != nil { + node = sa.Group.node + peers = sa.Group.Peers + } + js.mu.RUnlock() + } + + mset.mu.Lock() + defer mset.mu.Unlock() + + mset.sa = sa + if sa == nil { + return + } + + // Set our node. + mset.node = node + if mset.node != nil { + mset.node.UpdateKnownPeers(peers) + } + + // Setup our info sub here as well for all stream members. This is now by design. + if mset.infoSub == nil { + isubj := fmt.Sprintf(clusterStreamInfoT, mset.jsa.acc(), mset.cfg.Name) + // Note below the way we subscribe here is so that we can send requests to ourselves. + mset.infoSub, _ = mset.srv.systemSubscribe(isubj, _EMPTY_, false, mset.sysc, mset.handleClusterStreamInfoRequest) + } + + // Trigger update chan. + select { + case mset.uch <- struct{}{}: + default: + } +} + +func (mset *stream) monitorQuitC() <-chan struct{} { + if mset == nil { + return nil + } + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.mqch +} + +// signalMonitorQuit signals to exit the monitor loop. If there's no Raft node, +// this will be the only way to stop the monitor goroutine. +func (mset *stream) signalMonitorQuit() { + mset.mu.Lock() + defer mset.mu.Unlock() + if mset.mqch != nil { + close(mset.mqch) + mset.mqch = nil + } +} + +func (mset *stream) updateC() <-chan struct{} { + if mset == nil { + return nil + } + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.uch +} + +// IsLeader will return if we are the current leader. +func (mset *stream) IsLeader() bool { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.isLeader() +} + +// Lock should be held. +func (mset *stream) isLeader() bool { + if mset.isClustered() { + return mset.node.Leader() + } + return true +} + +// isLeaderNodeState should NOT be used normally, use isLeader instead. +// Returns whether the node thinks it is the leader, regardless of whether applies are up-to-date yet +// (unlike isLeader, which requires applies to be caught up). +// May be used to respond to clients after a leader change, when applying entries from a former leader. +// Lock should be held. +func (mset *stream) isLeaderNodeState() bool { + if mset.isClustered() { + return mset.node.State() == Leader + } + return true +} + +// TODO(dlc) - Check to see if we can accept being the leader or we should step down. +func (mset *stream) setLeader(isLeader bool) error { + mset.mu.Lock() + // If we are here we have a change in leader status. + if isLeader { + // Make sure we are listening for sync requests. + // TODO(dlc) - Original design was that all in sync members of the group would do DQ. + if mset.isClustered() { + mset.startClusterSubs() + } + + // Setup subscriptions if we were not already the leader. + if err := mset.subscribeToStream(); err != nil { + if mset.isClustered() { + // Stepdown since we have an error. + mset.node.StepDown() + } + mset.mu.Unlock() + return err + } + } else { + // cancel timer to create the source consumers if not fired yet + if mset.sourcesConsumerSetup != nil { + mset.sourcesConsumerSetup.Stop() + mset.sourcesConsumerSetup = nil + } else { + // Stop any source consumers + mset.stopSourceConsumers() + } + + // Stop responding to sync requests. + mset.stopClusterSubs() + // Unsubscribe from direct stream. + mset.unsubscribeToStream(false) + // Clear catchup state + mset.clearAllCatchupPeers() + } + mset.mu.Unlock() + + // If we are interest based make sure to check consumers. + // This is to make sure we process any outstanding acks. + mset.checkInterestState() + + return nil +} + +// Lock should be held. +func (mset *stream) startClusterSubs() { + if mset.syncSub == nil { + mset.syncSub, _ = mset.srv.systemSubscribe(mset.sa.Sync, _EMPTY_, false, mset.sysc, mset.handleClusterSyncRequest) + } +} + +// Lock should be held. +func (mset *stream) stopClusterSubs() { + if mset.syncSub != nil { + mset.srv.sysUnsubscribe(mset.syncSub) + mset.syncSub = nil + } +} + +// account gets the account for this stream. +func (mset *stream) account() *Account { + mset.mu.RLock() + jsa := mset.jsa + mset.mu.RUnlock() + if jsa == nil { + return nil + } + return jsa.acc() +} + // Helper to determine the max msg size for this stream if file based. -func (mset *Stream) maxMsgSize() uint64 { - maxMsgSize := mset.config.MaxMsgSize +func (mset *stream) maxMsgSize() uint64 { + maxMsgSize := mset.cfg.MaxMsgSize if maxMsgSize <= 0 { // Pull from the account. if mset.jsa != nil { @@ -242,7 +1098,7 @@ func (mset *Stream) maxMsgSize() uint64 { } // Now determine an estimation for the subjects etc. maxSubject := -1 - for _, subj := range mset.config.Subjects { + for _, subj := range mset.cfg.Subjects { if subjectIsLiteral(subj) { if len(subj) > maxSubject { maxSubject = len(subj) @@ -260,15 +1116,18 @@ func (mset *Stream) maxMsgSize() uint64 { // If we are file based and the file storage config was not explicitly set // we can autotune block sizes to better match. Our target will be to store 125% // of the theoretical limit. We will round up to nearest 100 bytes as well. -func (mset *Stream) autoTuneFileStorageBlockSize(fsCfg *FileStoreConfig) { +func (mset *stream) autoTuneFileStorageBlockSize(fsCfg *FileStoreConfig) { var totalEstSize uint64 // MaxBytes will take precedence for now. - if mset.config.MaxBytes > 0 { - totalEstSize = uint64(mset.config.MaxBytes) - } else if mset.config.MaxMsgs > 0 { + if mset.cfg.MaxBytes > 0 { + totalEstSize = uint64(mset.cfg.MaxBytes) + } else if mset.cfg.MaxMsgs > 0 { // Determine max message size to estimate. - totalEstSize = mset.maxMsgSize() * uint64(mset.config.MaxMsgs) + totalEstSize = mset.maxMsgSize() * uint64(mset.cfg.MaxMsgs) + } else if mset.cfg.MaxMsgsPer > 0 { + fsCfg.BlockSize = uint64(defaultKVBlockSize) + return } else { // If nothing set will let underlying filestore determine blkSize. return @@ -279,34 +1138,47 @@ func (mset *Stream) autoTuneFileStorageBlockSize(fsCfg *FileStoreConfig) { if m := blkSize % 100; m != 0 { blkSize += 100 - m } - if blkSize < FileStoreMinBlkSize { + if blkSize <= FileStoreMinBlkSize { blkSize = FileStoreMinBlkSize - } - if blkSize > FileStoreMaxBlkSize { + } else if blkSize >= FileStoreMaxBlkSize { blkSize = FileStoreMaxBlkSize + } else { + blkSize = defaultMediumBlockSize } fsCfg.BlockSize = uint64(blkSize) } // rebuildDedupe will rebuild any dedupe structures needed after recovery of a stream. +// Will be called lazily to avoid penalizing startup times. // TODO(dlc) - Might be good to know if this should be checked at all for streams with no // headers and msgId in them. Would need signaling from the storage layer. -func (mset *Stream) rebuildDedupe() { - state := mset.store.State() - mset.lseq = state.LastSeq +// Lock should be held. +func (mset *stream) rebuildDedupe() { + if mset.ddloaded { + return + } + + mset.ddloaded = true // We have some messages. Lookup starting sequence by duplicate time window. - sseq := mset.store.GetSeqFromTime(time.Now().Add(-mset.config.Duplicates)) + sseq := mset.store.GetSeqFromTime(time.Now().Add(-mset.cfg.Duplicates)) if sseq == 0 { return } + var smv StoreMsg + var state StreamState + mset.store.FastState(&state) + for seq := sseq; seq <= state.LastSeq; seq++ { - _, hdr, _, ts, err := mset.store.LoadMsg(seq) - var msgId string - if err == nil && len(hdr) > 0 { - if msgId = getMsgId(hdr); msgId != _EMPTY_ { - mset.storeMsgId(&ddentry{msgId, seq, ts}) + sm, err := mset.store.LoadMsg(seq, &smv) + if err != nil { + continue + } + var msgId string + if len(sm.hdr) > 0 { + if msgId = getMsgId(sm.hdr); msgId != _EMPTY_ { + mset.storeMsgIdLocked(&ddentry{msgId, sm.seq, sm.ts}) } } if seq == state.LastSeq { @@ -315,14 +1187,46 @@ func (mset *Stream) rebuildDedupe() { } } -func (mset *Stream) sendCreateAdvisory() { - mset.mu.Lock() - name := mset.config.Name - template := mset.config.Template - sendq := mset.sendq - mset.mu.Unlock() +func (mset *stream) lastSeqAndCLFS() (uint64, uint64) { + return mset.lastSeq(), mset.getCLFS() +} + +func (mset *stream) getCLFS() uint64 { + if mset == nil { + return 0 + } + mset.clMu.Lock() + defer mset.clMu.Unlock() + return mset.clfs +} + +func (mset *stream) setCLFS(clfs uint64) { + mset.clMu.Lock() + mset.clfs = clfs + mset.clMu.Unlock() +} + +func (mset *stream) lastSeq() uint64 { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.lseq +} - if sendq == nil { +// Set last seq. +// Write lock should be held. +func (mset *stream) setLastSeq(lseq uint64) { + mset.lseq = lseq +} + +func (mset *stream) sendCreateAdvisory() { + mset.mu.RLock() + name := mset.cfg.Name + template := mset.cfg.Template + outq := mset.outq + srv := mset.srv + mset.mu.RUnlock() + + if outq == nil { return } @@ -336,17 +1240,20 @@ func (mset *Stream) sendCreateAdvisory() { Stream: name, Action: CreateEvent, Template: template, + Domain: srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(m, "", " ") - if err == nil { - subj := JSAdvisoryStreamCreatedPre + "." + name - sendq <- &jsPubMsg{subj, subj, _EMPTY_, nil, j, nil, 0} + j, err := json.Marshal(m) + if err != nil { + return } + + subj := JSAdvisoryStreamCreatedPre + "." + name + outq.sendMsg(subj, j) } -func (mset *Stream) sendDeleteAdvisoryLocked() { - if mset.sendq == nil { +func (mset *stream) sendDeleteAdvisoryLocked() { + if mset.outq == nil { return } @@ -356,20 +1263,21 @@ func (mset *Stream) sendDeleteAdvisoryLocked() { ID: nuid.Next(), Time: time.Now().UTC(), }, - Stream: mset.config.Name, + Stream: mset.cfg.Name, Action: DeleteEvent, - Template: mset.config.Template, + Template: mset.cfg.Template, + Domain: mset.srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(m, "", " ") + j, err := json.Marshal(m) if err == nil { - subj := JSAdvisoryStreamDeletedPre + "." + mset.config.Name - mset.sendq <- &jsPubMsg{subj, subj, _EMPTY_, nil, j, nil, 0} + subj := JSAdvisoryStreamDeletedPre + "." + mset.cfg.Name + mset.outq.sendMsg(subj, j) } } -func (mset *Stream) sendUpdateAdvisoryLocked() { - if mset.sendq == nil { +func (mset *stream) sendUpdateAdvisoryLocked() { + if mset.outq == nil { return } @@ -379,19 +1287,20 @@ func (mset *Stream) sendUpdateAdvisoryLocked() { ID: nuid.Next(), Time: time.Now().UTC(), }, - Stream: mset.config.Name, + Stream: mset.cfg.Name, Action: ModifyEvent, + Domain: mset.srv.getOpts().JetStreamDomain, } - j, err := json.MarshalIndent(m, "", " ") + j, err := json.Marshal(m) if err == nil { - subj := JSAdvisoryStreamUpdatedPre + "." + mset.config.Name - mset.sendq <- &jsPubMsg{subj, subj, _EMPTY_, nil, j, nil, 0} + subj := JSAdvisoryStreamUpdatedPre + "." + mset.cfg.Name + mset.outq.sendMsg(subj, j) } } // Created returns created time. -func (mset *Stream) Created() time.Time { +func (mset *stream) createdTime() time.Time { mset.mu.RLock() created := mset.created mset.mu.RUnlock() @@ -399,17 +1308,21 @@ func (mset *Stream) Created() time.Time { } // Internal to allow creation time to be restored. -func (mset *Stream) setCreated(created time.Time) { +func (mset *stream) setCreatedTime(created time.Time) { mset.mu.Lock() mset.created = created mset.mu.Unlock() } -// Check to see if these subjects overlap with existing subjects. -// Lock should be held. -func (jsa *jsAccount) subjectsOverlap(subjects []string) bool { +// subjectsOverlap to see if these subjects overlap with existing subjects. +// Use only for non-clustered JetStream +// RLock minimum should be held. +func (jsa *jsAccount) subjectsOverlap(subjects []string, self *stream) bool { for _, mset := range jsa.streams { - for _, subj := range mset.config.Subjects { + if self != nil && mset == self { + continue + } + for _, subj := range mset.cfg.Subjects { for _, tsubj := range subjects { if SubjectsCollide(tsubj, subj) { return true @@ -420,35 +1333,54 @@ func (jsa *jsAccount) subjectsOverlap(subjects []string) bool { return false } -// Default duplicates window. +// StreamDefaultDuplicatesWindow default duplicates window. const StreamDefaultDuplicatesWindow = 2 * time.Minute -func checkStreamCfg(config *StreamConfig) (StreamConfig, error) { +func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account, pedantic bool) (StreamConfig, *ApiError) { + lim := &s.getOpts().JetStreamLimits + if config == nil { - return StreamConfig{}, fmt.Errorf("stream configuration invalid") + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration invalid")) } if !isValidName(config.Name) { - return StreamConfig{}, fmt.Errorf("stream name is required and can not contain '.', '*', '>'") + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream name is required and can not contain '.', '*', '>'")) } if len(config.Name) > JSMaxNameLen { - return StreamConfig{}, fmt.Errorf("stream name is too long, maximum allowed is %d", JSMaxNameLen) + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream name is too long, maximum allowed is %d", JSMaxNameLen)) + } + if len(config.Description) > JSMaxDescriptionLen { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream description is too long, maximum allowed is %d", JSMaxDescriptionLen)) + } + + var metadataLen int + for k, v := range config.Metadata { + metadataLen += len(k) + len(v) + } + if metadataLen > JSMaxMetadataLen { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream metadata exceeds maximum size of %d bytes", JSMaxMetadataLen)) } + cfg := *config - // TODO(dlc) - check config for conflicts, e.g replicas > 1 in single server mode. + // Make file the default. + if cfg.Storage == 0 { + cfg.Storage = FileStorage + } if cfg.Replicas == 0 { cfg.Replicas = 1 } - // TODO(dlc) - Remove when clustering happens. - if cfg.Replicas > 1 { - return StreamConfig{}, fmt.Errorf("maximum replicas is 1") - } if cfg.Replicas > StreamMaxReplicas { - return cfg, fmt.Errorf("maximum replicas is %d", StreamMaxReplicas) + return cfg, NewJSStreamInvalidConfigError(fmt.Errorf("maximum replicas is %d", StreamMaxReplicas)) + } + if cfg.Replicas < 0 { + return cfg, NewJSReplicasCountCannotBeNegativeError() } if cfg.MaxMsgs == 0 { cfg.MaxMsgs = -1 } + if cfg.MaxMsgsPer == 0 { + cfg.MaxMsgsPer = -1 + } if cfg.MaxBytes == 0 { cfg.MaxBytes = -1 } @@ -458,50 +1390,460 @@ func checkStreamCfg(config *StreamConfig) (StreamConfig, error) { if cfg.MaxConsumers == 0 { cfg.MaxConsumers = -1 } - if cfg.Duplicates == 0 { - if cfg.MaxAge != 0 && cfg.MaxAge < StreamDefaultDuplicatesWindow { + if cfg.Duplicates == 0 && cfg.Mirror == nil { + maxWindow := StreamDefaultDuplicatesWindow + if lim.Duplicates > 0 && maxWindow > lim.Duplicates { + if pedantic { + return StreamConfig{}, NewJSPedanticError(fmt.Errorf("pedantic mode: duplicate window limits are higher than current limits")) + } + maxWindow = lim.Duplicates + } + if cfg.MaxAge != 0 && cfg.MaxAge < maxWindow { + if pedantic { + return StreamConfig{}, NewJSPedanticError(fmt.Errorf("pedantic mode: duplicate window cannot be bigger than max age")) + } cfg.Duplicates = cfg.MaxAge } else { - cfg.Duplicates = StreamDefaultDuplicatesWindow + cfg.Duplicates = maxWindow } - } else if cfg.Duplicates < 0 { - return StreamConfig{}, fmt.Errorf("duplicates window can not be negative") + } + if cfg.MaxAge > 0 && cfg.MaxAge < 100*time.Millisecond { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("max age needs to be >= 100ms")) + } + if cfg.Duplicates < 0 { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window can not be negative")) } // Check that duplicates is not larger then age if set. if cfg.MaxAge != 0 && cfg.Duplicates > cfg.MaxAge { - return StreamConfig{}, fmt.Errorf("duplicates window can not be larger then max age") + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window can not be larger then max age")) + } + if lim.Duplicates > 0 && cfg.Duplicates > lim.Duplicates { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window can not be larger then server limit of %v", + lim.Duplicates.String())) + } + if cfg.Duplicates > 0 && cfg.Duplicates < 100*time.Millisecond { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicates window needs to be >= 100ms")) + } + + if cfg.DenyPurge && cfg.AllowRollup { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("roll-ups require the purge permission")) + } + + // Check for new discard new per subject, we require the discard policy to also be new. + if cfg.DiscardNewPer { + if cfg.Discard != DiscardNew { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires discard new policy to be set")) + } + if cfg.MaxMsgsPer <= 0 { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires max msgs per subject > 0")) + } + } + + if cfg.SubjectDeleteMarkerTTL > 0 { + if cfg.SubjectDeleteMarkerTTL < time.Second { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker TTL must be at least 1 second")) + } + if !cfg.AllowMsgTTL { + if pedantic { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker cannot be set if message TTLs are disabled")) + } + cfg.AllowMsgTTL = true + } + if !cfg.AllowRollup { + if pedantic { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker cannot be set if roll-ups are disabled")) + } + cfg.AllowRollup, cfg.DenyPurge = true, false + } + } else if cfg.SubjectDeleteMarkerTTL < 0 { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete marker TTL must not be negative")) + } + + getStream := func(streamName string) (bool, StreamConfig) { + var exists bool + var cfg StreamConfig + if s.JetStreamIsClustered() { + if js, _ := s.getJetStreamCluster(); js != nil { + js.mu.RLock() + if sa := js.streamAssignment(acc.Name, streamName); sa != nil { + cfg = *sa.Config.clone() + exists = true + } + js.mu.RUnlock() + } + } else if mset, err := acc.lookupStream(streamName); err == nil { + cfg = mset.cfg + exists = true + } + return exists, cfg + } + + hasStream := func(streamName string) (bool, int32, []string) { + exists, cfg := getStream(streamName) + return exists, cfg.MaxMsgSize, cfg.Subjects + } + + var streamSubs []string + var deliveryPrefixes []string + var apiPrefixes []string + + // Do some pre-checking for mirror config to avoid cycles in clustered mode. + if cfg.Mirror != nil { + if cfg.FirstSeq > 0 { + return StreamConfig{}, NewJSMirrorWithFirstSeqError() + } + if len(cfg.Subjects) > 0 { + return StreamConfig{}, NewJSMirrorWithSubjectsError() + } + if len(cfg.Sources) > 0 { + return StreamConfig{}, NewJSMirrorWithSourcesError() + } + if cfg.Mirror.FilterSubject != _EMPTY_ && len(cfg.Mirror.SubjectTransforms) != 0 { + return StreamConfig{}, NewJSMirrorMultipleFiltersNotAllowedError() + } + if cfg.SubjectDeleteMarkerTTL > 0 { + // Delete markers cannot be configured on a mirror as it would result in new + // tombstones which would use up sequence numbers, diverging from the origin + // stream. + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject delete markers forbidden on mirrors")) + } + // Check subject filters overlap. + for outer, tr := range cfg.Mirror.SubjectTransforms { + if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) { + return StreamConfig{}, NewJSMirrorInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source)) + } + + err := ValidateMapping(tr.Source, tr.Destination) + if err != nil { + return StreamConfig{}, NewJSMirrorInvalidTransformDestinationError(err) + } + + for inner, innertr := range cfg.Mirror.SubjectTransforms { + if inner != outer && SubjectsCollide(tr.Source, innertr.Source) { + return StreamConfig{}, NewJSMirrorOverlappingSubjectFiltersError() + } + } + } + // Do not perform checks if External is provided, as it could lead to + // checking against itself (if sourced stream name is the same on different JetStream) + if cfg.Mirror.External == nil { + if !isValidName(cfg.Mirror.Name) { + return StreamConfig{}, NewJSMirrorInvalidStreamNameError() + } + // We do not require other stream to exist anymore, but if we can see it check payloads. + exists, maxMsgSize, subs := hasStream(cfg.Mirror.Name) + if len(subs) > 0 { + streamSubs = append(streamSubs, subs...) + } + if exists { + if cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize { + return StreamConfig{}, NewJSMirrorMaxMessageSizeTooBigError() + } + } + // Determine if we are inheriting direct gets. + if exists, ocfg := getStream(cfg.Mirror.Name); exists { + if pedantic && cfg.MirrorDirect != ocfg.AllowDirect { + return StreamConfig{}, NewJSPedanticError(fmt.Errorf("origin stream has direct get set, mirror has it disabled")) + } + cfg.MirrorDirect = ocfg.AllowDirect + } else if js := s.getJetStream(); js != nil && js.isClustered() { + // Could not find it here. If we are clustered we can look it up. + js.mu.RLock() + if cc := js.cluster; cc != nil { + if as := cc.streams[acc.Name]; as != nil { + if sa := as[cfg.Mirror.Name]; sa != nil { + if pedantic && cfg.MirrorDirect != sa.Config.AllowDirect { + js.mu.RUnlock() + return StreamConfig{}, NewJSPedanticError(fmt.Errorf("origin stream has direct get set, mirror has it disabled")) + } + cfg.MirrorDirect = sa.Config.AllowDirect + } + } + } + js.mu.RUnlock() + } + } else { + if cfg.Mirror.External.DeliverPrefix != _EMPTY_ { + deliveryPrefixes = append(deliveryPrefixes, cfg.Mirror.External.DeliverPrefix) + } + + if cfg.Mirror.External.ApiPrefix != _EMPTY_ { + apiPrefixes = append(apiPrefixes, cfg.Mirror.External.ApiPrefix) + } + } + } + + // check for duplicates + var iNames = make(map[string]struct{}) + for _, src := range cfg.Sources { + if src == nil || !isValidName(src.Name) { + return StreamConfig{}, NewJSSourceInvalidStreamNameError() + } + if _, ok := iNames[src.composeIName()]; !ok { + iNames[src.composeIName()] = struct{}{} + } else { + return StreamConfig{}, NewJSSourceDuplicateDetectedError() + } + // Do not perform checks if External is provided, as it could lead to + // checking against itself (if sourced stream name is the same on different JetStream) + if src.External == nil { + exists, maxMsgSize, subs := hasStream(src.Name) + if len(subs) > 0 { + streamSubs = append(streamSubs, subs...) + } + if exists { + if cfg.MaxMsgSize > 0 && maxMsgSize > 0 && cfg.MaxMsgSize < maxMsgSize { + return StreamConfig{}, NewJSSourceMaxMessageSizeTooBigError() + } + } + + if src.FilterSubject != _EMPTY_ && len(src.SubjectTransforms) != 0 { + return StreamConfig{}, NewJSSourceMultipleFiltersNotAllowedError() + } + + for _, tr := range src.SubjectTransforms { + if tr.Source != _EMPTY_ && !IsValidSubject(tr.Source) { + return StreamConfig{}, NewJSSourceInvalidSubjectFilterError(fmt.Errorf("%w %s", ErrBadSubject, tr.Source)) + } + + err := ValidateMapping(tr.Source, tr.Destination) + if err != nil { + return StreamConfig{}, NewJSSourceInvalidTransformDestinationError(err) + } + } + + // Check subject filters overlap. + for outer, tr := range src.SubjectTransforms { + for inner, innertr := range src.SubjectTransforms { + if inner != outer && subjectIsSubsetMatch(tr.Source, innertr.Source) { + return StreamConfig{}, NewJSSourceOverlappingSubjectFiltersError() + } + } + } + continue + } else { + if src.External.DeliverPrefix != _EMPTY_ { + deliveryPrefixes = append(deliveryPrefixes, src.External.DeliverPrefix) + } + if src.External.ApiPrefix != _EMPTY_ { + apiPrefixes = append(apiPrefixes, src.External.ApiPrefix) + } + } + } + + // check prefix overlap with subjects + for _, pfx := range deliveryPrefixes { + if !IsValidPublishSubject(pfx) { + return StreamConfig{}, NewJSStreamInvalidExternalDeliverySubjError(pfx) + } + for _, sub := range streamSubs { + if SubjectsCollide(sub, fmt.Sprintf("%s.%s", pfx, sub)) { + return StreamConfig{}, NewJSStreamExternalDelPrefixOverlapsError(pfx, sub) + } + } + } + // check if api prefixes overlap + for _, apiPfx := range apiPrefixes { + if !IsValidPublishSubject(apiPfx) { + return StreamConfig{}, NewJSStreamInvalidConfigError( + fmt.Errorf("stream external api prefix %q must be a valid subject without wildcards", apiPfx)) + } + if SubjectsCollide(apiPfx, JSApiPrefix) { + return StreamConfig{}, NewJSStreamExternalApiOverlapError(apiPfx, JSApiPrefix) + } + } + + // cycle check for source cycle + toVisit := []*StreamConfig{&cfg} + visited := make(map[string]struct{}) + overlaps := func(subjects []string, filter string) bool { + if filter == _EMPTY_ { + return true + } + for _, subject := range subjects { + if SubjectsCollide(subject, filter) { + return true + } + } + return false + } + + for len(toVisit) > 0 { + cfg := toVisit[0] + toVisit = toVisit[1:] + visited[cfg.Name] = struct{}{} + for _, src := range cfg.Sources { + if src.External != nil { + continue + } + // We can detect a cycle between streams, but let's double check that the + // subjects actually form a cycle. + if _, ok := visited[src.Name]; ok { + if overlaps(cfg.Subjects, src.FilterSubject) { + return StreamConfig{}, NewJSStreamInvalidConfigError(errors.New("detected cycle")) + } + } else if exists, cfg := getStream(src.Name); exists { + toVisit = append(toVisit, &cfg) + } + } + // Avoid cycles hiding behind mirrors + if m := cfg.Mirror; m != nil { + if m.External == nil { + if _, ok := visited[m.Name]; ok { + return StreamConfig{}, NewJSStreamInvalidConfigError(errors.New("detected cycle")) + } + if exists, cfg := getStream(m.Name); exists { + toVisit = append(toVisit, &cfg) + } + } + } } if len(cfg.Subjects) == 0 { - if !cfg.allowNoSubject { + if cfg.Mirror == nil && len(cfg.Sources) == 0 { cfg.Subjects = append(cfg.Subjects, cfg.Name) } } else { - // We can allow overlaps, but don't allow direct duplicates. + if cfg.Mirror != nil { + return StreamConfig{}, NewJSMirrorWithSubjectsError() + } + + // Check for literal duplication of subject interest in config + // and no overlap with any JS or SYS API subject space. dset := make(map[string]struct{}, len(cfg.Subjects)) for _, subj := range cfg.Subjects { + // Make sure the subject is valid. Check this first. + if !IsValidSubject(subj) { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("invalid subject")) + } if _, ok := dset[subj]; ok { - return StreamConfig{}, fmt.Errorf("duplicate subjects detected") + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("duplicate subjects detected")) + } + // Check for trying to capture everything. + if subj == fwcs { + if !cfg.NoAck { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("capturing all subjects requires no-ack to be true")) + } + // Capturing everything also will require R1. + if cfg.Replicas != 1 { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("capturing all subjects requires replicas of 1")) + } } // Also check to make sure we do not overlap with our $JS API subjects. - if subjectIsSubsetMatch(subj, "$JS.API.>") { - return StreamConfig{}, fmt.Errorf("subjects overlap with jetstream api") + if !cfg.NoAck { + for _, namespace := range []string{"$JS.>", "$JSC.>", "$NRG.>"} { + if SubjectsCollide(subj, namespace) { + // We allow an exception for $JS.EVENT.> since these could have been created in the past. + if !subjectIsSubsetMatch(subj, "$JS.EVENT.>") { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subjects that overlap with jetstream api require no-ack to be true")) + } + } + } + if SubjectsCollide(subj, "$SYS.>") { + if !subjectIsSubsetMatch(subj, "$SYS.ACCOUNT.>") { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subjects that overlap with system api require no-ack to be true")) + } + } } - + // Mark for duplicate check. dset[subj] = struct{}{} } } + + if len(cfg.Subjects) == 0 && len(cfg.Sources) == 0 && cfg.Mirror == nil { + return StreamConfig{}, NewJSStreamInvalidConfigError( + fmt.Errorf("stream needs at least one configured subject or be a source/mirror")) + } + + // Check for MaxBytes required and it's limit + if required, limit := acc.maxBytesLimits(&cfg); required && cfg.MaxBytes <= 0 { + return StreamConfig{}, NewJSStreamMaxBytesRequiredError() + } else if limit > 0 && cfg.MaxBytes > limit { + return StreamConfig{}, NewJSStreamMaxStreamBytesExceededError() + } + + // Now check if we have multiple subjects they we do not overlap ourselves + // which would cause duplicate entries (assuming no MsgID). + if len(cfg.Subjects) > 1 { + for _, subj := range cfg.Subjects { + for _, tsubj := range cfg.Subjects { + if tsubj != subj && SubjectsCollide(tsubj, subj) { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("subject %q overlaps with %q", subj, tsubj)) + } + } + } + } + + // Check the subject transform if any + if cfg.SubjectTransform != nil { + if cfg.SubjectTransform.Source != _EMPTY_ && !IsValidSubject(cfg.SubjectTransform.Source) { + return StreamConfig{}, NewJSStreamTransformInvalidSourceError(fmt.Errorf("%w %s", ErrBadSubject, cfg.SubjectTransform.Source)) + } + + err := ValidateMapping(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination) + if err != nil { + return StreamConfig{}, NewJSStreamTransformInvalidDestinationError(err) + } + } + + // If we have a republish directive check if we can create a transform here. + if cfg.RePublish != nil { + // Check to make sure source is a valid subset of the subjects we have. + // Also make sure it does not form a cycle. + // Empty same as all. + if cfg.RePublish.Source == _EMPTY_ { + if pedantic { + return StreamConfig{}, NewJSPedanticError(fmt.Errorf("pedantic mode: republish source can not be empty")) + } + cfg.RePublish.Source = fwcs + } + // A RePublish from '>' to '>' could be used, normally this would form a cycle with the stream subjects. + // But if this aligns to a different subject based on the transform, we allow it still. + // The RePublish will be implicit based on the transform, but only if the transform's source + // is the only stream subject. + if cfg.RePublish.Destination == fwcs && cfg.RePublish.Source == fwcs && cfg.SubjectTransform != nil && + len(cfg.Subjects) == 1 && cfg.SubjectTransform.Source == cfg.Subjects[0] { + if pedantic { + return StreamConfig{}, NewJSPedanticError(fmt.Errorf("implicit republish based on subject transform")) + } + // RePublish all messages with the transformed subject. + cfg.RePublish.Source, cfg.RePublish.Destination = cfg.SubjectTransform.Destination, cfg.SubjectTransform.Destination + } + var formsCycle bool + for _, subj := range cfg.Subjects { + if SubjectsCollide(cfg.RePublish.Destination, subj) { + formsCycle = true + break + } + } + if formsCycle { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for republish destination forms a cycle")) + } + if _, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination); err != nil { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration for republish with transform from '%s' to '%s' not valid", cfg.RePublish.Source, cfg.RePublish.Destination)) + } + } + + // Remove placement if it's an empty object. + if cfg.Placement != nil && reflect.DeepEqual(cfg.Placement, &Placement{}) { + cfg.Placement = nil + } + // For now don't allow preferred server in placement. + if cfg.Placement != nil && cfg.Placement.Preferred != _EMPTY_ { + return StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf("preferred server not permitted in placement")) + } + return cfg, nil } // Config returns the stream's configuration. -func (mset *Stream) Config() StreamConfig { - mset.mu.Lock() - defer mset.mu.Unlock() - return mset.config +func (mset *stream) config() StreamConfig { + mset.cfgMu.RLock() + defer mset.cfgMu.RUnlock() + return mset.cfg } -func (mset *Stream) FileStoreConfig() (FileStoreConfig, error) { +func (mset *stream) fileStoreConfig() (FileStoreConfig, error) { mset.mu.Lock() defer mset.mu.Unlock() fs, ok := mset.store.(*fileStore) @@ -511,948 +1853,4821 @@ func (mset *Stream) FileStoreConfig() (FileStoreConfig, error) { return fs.fileStoreConfig(), nil } -// Delete deletes a stream from the owning account. -func (mset *Stream) Delete() error { - mset.mu.Lock() - jsa := mset.jsa - mset.mu.Unlock() - if jsa == nil { - return ErrJetStreamNotEnabledForAccount - } - jsa.mu.Lock() - delete(jsa.streams, mset.config.Name) - jsa.mu.Unlock() - - return mset.delete() -} - -// Update will allow certain configuration properties of an existing stream to be updated. -func (mset *Stream) Update(config *StreamConfig) error { - cfg, err := checkStreamCfg(config) - if err != nil { - return err +// Do not hold jsAccount or jetStream lock +func (jsa *jsAccount) configUpdateCheck(old, new *StreamConfig, s *Server, pedantic bool) (*StreamConfig, error) { + cfg, apiErr := s.checkStreamCfg(new, jsa.acc(), pedantic) + if apiErr != nil { + return nil, apiErr } - o_cfg := mset.Config() // Name must match. - if cfg.Name != o_cfg.Name { - return fmt.Errorf("stream configuration name must match original") + if cfg.Name != old.Name { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration name must match original")) } // Can't change MaxConsumers for now. - if cfg.MaxConsumers != o_cfg.MaxConsumers { - return fmt.Errorf("stream configuration update can not change MaxConsumers") + if cfg.MaxConsumers != old.MaxConsumers { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change MaxConsumers")) } // Can't change storage types. - if cfg.Storage != o_cfg.Storage { - return fmt.Errorf("stream configuration update can not change storage type") + if cfg.Storage != old.Storage { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change storage type")) } - // Can't change retention. - if cfg.Retention != o_cfg.Retention { - return fmt.Errorf("stream configuration update can not change retention policy") + // Can only change retention from limits to interest or back, not to/from work queue for now. + if cfg.Retention != old.Retention { + if old.Retention == WorkQueuePolicy || cfg.Retention == WorkQueuePolicy { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change retention policy to/from workqueue")) + } } // Can not have a template owner for now. - if o_cfg.Template != "" { - return fmt.Errorf("stream configuration update not allowed on template owned stream") + if old.Template != _EMPTY_ { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update not allowed on template owned stream")) + } + if cfg.Template != _EMPTY_ { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not be owned by a template")) } - if cfg.Template != "" { - return fmt.Errorf("stream configuration update can not be owned by a template") + // Can not change from true to false. + if !cfg.Sealed && old.Sealed { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not unseal a sealed stream")) } - - // Check limits. - mset.mu.Lock() - jsa := mset.jsa - mset.mu.Unlock() - - jsa.mu.Lock() - if cfg.MaxConsumers > 0 && cfg.MaxConsumers > jsa.limits.MaxConsumers { - jsa.mu.Unlock() - return fmt.Errorf("stream configuration maximum consumers exceeds account limit") + // Can not change from true to false. + if !cfg.DenyDelete && old.DenyDelete { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not cancel deny message deletes")) } - if cfg.MaxBytes > 0 && cfg.MaxBytes > o_cfg.MaxBytes { - if err := jsa.checkBytesLimits(cfg.MaxBytes*int64(cfg.Replicas), cfg.Storage); err != nil { - jsa.mu.Unlock() - return err - } + // Can not change from true to false. + if !cfg.DenyPurge && old.DenyPurge { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not cancel deny purge")) } - jsa.mu.Unlock() - - // Now check for subject interest differences. - current := make(map[string]struct{}, len(o_cfg.Subjects)) - for _, s := range o_cfg.Subjects { - current[s] = struct{}{} + // Check for mirror changes which are not allowed. + if !reflect.DeepEqual(cfg.Mirror, old.Mirror) { + return nil, NewJSStreamMirrorNotUpdatableError() } - // Update config with new values. The store update will enforce any stricter limits. - mset.mu.Lock() - // Now walk new subjects. All of these need to be added, but we will check - // the originals first, since if it is in there we can skip, already added. - for _, s := range cfg.Subjects { - if _, ok := current[s]; !ok { - if _, err := mset.subscribeInternal(s, mset.processInboundJetStreamMsg); err != nil { - mset.mu.Unlock() - return err - } + // Check on new discard new per subject. + if cfg.DiscardNewPer { + if cfg.Discard != DiscardNew { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires discard new policy to be set")) } - delete(current, s) - } - // What is left in current needs to be deleted. - for s := range current { - if err := mset.unsubscribeInternal(s); err != nil { - mset.mu.Unlock() - return err + if cfg.MaxMsgsPer <= 0 { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("discard new per subject requires max msgs per subject > 0")) } } - // Check for the Duplicates - if cfg.Duplicates != o_cfg.Duplicates && mset.ddtmr != nil { - // Let it fire right away, it will adjust properly on purge. - mset.ddtmr.Reset(time.Microsecond) + // Check on the allowed message TTL status. + if old.AllowMsgTTL && !cfg.AllowMsgTTL { + return nil, NewJSStreamInvalidConfigError(fmt.Errorf("message TTL status can not be disabled")) } - // Now update config and store's version of our config. - mset.config = cfg - mset.sendUpdateAdvisoryLocked() - mset.mu.Unlock() - mset.store.UpdateConfig(&cfg) + // Do some adjustments for being sealed. + // Pedantic mode will allow those changes to be made, as they are deterministic and important to get a sealed stream. + if cfg.Sealed { + cfg.MaxAge = 0 + cfg.Discard = DiscardNew + cfg.DenyDelete, cfg.DenyPurge = true, true + cfg.AllowRollup = false + } - return nil -} + // Check limits. We need some extra handling to allow updating MaxBytes. -// Purge will remove all messages from the stream and underlying store. -func (mset *Stream) Purge() (uint64, error) { - mset.mu.Lock() - if mset.client == nil { - mset.mu.Unlock() - return 0, errors.New("stream closed") + // First, let's calculate the difference between the new and old MaxBytes. + maxBytesDiff := max(cfg.MaxBytes, 0) - max(old.MaxBytes, 0) + if maxBytesDiff < 0 { + // If we're updating to a lower MaxBytes (maxBytesDiff is negative), + // then set to zero so checkBytesLimits doesn't set addBytes to 1. + maxBytesDiff = 0 } - // Purge dedupe. - mset.ddmap = nil - var _obs [4]*Consumer - obs := _obs[:0] - for _, o := range mset.consumers { - obs = append(obs, o) - } - mset.mu.Unlock() + // If maxBytesDiff == 0, then that means MaxBytes didn't change. + // If maxBytesDiff > 0, then we want to reserve additional bytes. - purged, err := mset.store.Purge() - if err != nil { - return purged, err + // Save the user configured MaxBytes. + newMaxBytes := cfg.MaxBytes + maxBytesOffset := int64(0) + + // We temporarily set cfg.MaxBytes to maxBytesDiff because checkAllLimits + // adds cfg.MaxBytes to the current reserved limit and checks if we've gone + // over. However, we don't want an addition cfg.MaxBytes, we only want to + // reserve the difference between the new and the old values. + cfg.MaxBytes = maxBytesDiff + + // Check limits. + js, isClustered := jsa.jetStreamAndClustered() + jsa.mu.RLock() + acc := jsa.account + jsa.usageMu.RLock() + selected, tier, hasTier := jsa.selectLimits(cfg.Replicas) + if !hasTier && old.Replicas != cfg.Replicas { + selected, tier, hasTier = jsa.selectLimits(old.Replicas) + } + jsa.usageMu.RUnlock() + reserved := int64(0) + if !isClustered { + reserved = jsa.tieredReservation(tier, &cfg) + } + jsa.mu.RUnlock() + if !hasTier { + return nil, NewJSNoLimitsError() + } + js.mu.RLock() + defer js.mu.RUnlock() + if isClustered { + _, reserved = tieredStreamAndReservationCount(js.cluster.streams[acc.Name], tier, &cfg) + } + // reservation does not account for this stream, hence add the old value + if tier == _EMPTY_ && old.Replicas > 1 { + reserved += old.MaxBytes * int64(old.Replicas) + } else { + reserved += old.MaxBytes } - stats := mset.store.State() - for _, o := range obs { - o.purge(stats.FirstSeq) + if err := js.checkAllLimits(&selected, &cfg, reserved, maxBytesOffset); err != nil { + return nil, err } - return purged, nil + // Restore the user configured MaxBytes. + cfg.MaxBytes = newMaxBytes + return &cfg, nil } -// RemoveMsg will remove a message from a stream. -// FIXME(dlc) - Should pick one and be consistent. -func (mset *Stream) RemoveMsg(seq uint64) (bool, error) { - return mset.removeMsg(seq, false) +// Update will allow certain configuration properties of an existing stream to be updated. +func (mset *stream) update(config *StreamConfig) error { + return mset.updateWithAdvisory(config, true, false) } -// DeleteMsg will remove a message from a stream. -func (mset *Stream) DeleteMsg(seq uint64) (bool, error) { - return mset.removeMsg(seq, false) +func (mset *stream) updatePedantic(config *StreamConfig, pedantic bool) error { + return mset.updateWithAdvisory(config, true, pedantic) } -// EraseMsg will securely remove a message and rewrite the data with random data. -func (mset *Stream) EraseMsg(seq uint64) (bool, error) { - return mset.removeMsg(seq, true) -} +// Update will allow certain configuration properties of an existing stream to be updated. +func (mset *stream) updateWithAdvisory(config *StreamConfig, sendAdvisory bool, pedantic bool) error { + _, jsa, err := mset.acc.checkForJetStream() + if err != nil { + return err + } -func (mset *Stream) removeMsg(seq uint64, secure bool) (bool, error) { mset.mu.RLock() - if mset.client == nil { - mset.mu.RUnlock() - return false, fmt.Errorf("invalid stream") - } + ocfg := mset.cfg + s := mset.srv mset.mu.RUnlock() - if secure { - return mset.store.EraseMsg(seq) - } else { - return mset.store.RemoveMsg(seq) - } -} -// Will create internal subscriptions for the msgSet. -// Lock should be held. -func (mset *Stream) subscribeToStream() error { - for _, subject := range mset.config.Subjects { - if _, err := mset.subscribeInternal(subject, mset.processInboundJetStreamMsg); err != nil { - return err + cfg, err := mset.jsa.configUpdateCheck(&ocfg, config, s, pedantic) + if err != nil { + return NewJSStreamInvalidConfigError(err, Unless(err)) + } + + // In the event that some of the stream-level limits have changed, yell appropriately + // if any of the consumers exceed that limit. + updateLimits := ocfg.ConsumerLimits.InactiveThreshold != cfg.ConsumerLimits.InactiveThreshold || + ocfg.ConsumerLimits.MaxAckPending != cfg.ConsumerLimits.MaxAckPending + if updateLimits { + var errorConsumers []string + consumers := map[string]*ConsumerConfig{} + if mset.js.isClustered() { + for _, c := range mset.sa.consumers { + consumers[c.Name] = c.Config + } + } else { + for _, c := range mset.consumers { + consumers[c.name] = &c.cfg + } + } + for name, ccfg := range consumers { + if ccfg.InactiveThreshold > cfg.ConsumerLimits.InactiveThreshold || + ccfg.MaxAckPending > cfg.ConsumerLimits.MaxAckPending { + errorConsumers = append(errorConsumers, name) + } + } + if len(errorConsumers) > 0 { + // TODO(nat): Return a parsable error so that we can surface something + // sensible through the JS API. + return fmt.Errorf("change to limits violates consumers: %s", strings.Join(errorConsumers, ", ")) } } - return nil -} - -// FIXME(dlc) - This only works in single server mode for the moment. Need to fix as we expand to clusters. -// Lock should be held. -func (mset *Stream) subscribeInternal(subject string, cb msgHandler) (*subscription, error) { - c := mset.client - if c == nil { - return nil, fmt.Errorf("invalid stream") - } - if !c.srv.eventsEnabled() { - return nil, ErrNoSysAccount - } - if cb == nil { - return nil, fmt.Errorf("undefined message handler") - } - - mset.sid++ - // Now create the subscription - return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(mset.sid)), cb, false) -} + jsa.mu.RLock() + if jsa.subjectsOverlap(cfg.Subjects, mset) { + jsa.mu.RUnlock() + return NewJSStreamSubjectOverlapError() + } + jsa.mu.RUnlock() -// Helper for unlocked stream. -func (mset *Stream) subscribeInternalUnlocked(subject string, cb msgHandler) (*subscription, error) { mset.mu.Lock() - defer mset.mu.Unlock() - return mset.subscribeInternal(subject, cb) -} + if mset.isLeader() { + // Now check for subject interest differences. + current := make(map[string]struct{}, len(ocfg.Subjects)) + for _, s := range ocfg.Subjects { + current[s] = struct{}{} + } + // Update config with new values. The store update will enforce any stricter limits. + + // Now walk new subjects. All of these need to be added, but we will check + // the originals first, since if it is in there we can skip, already added. + for _, s := range cfg.Subjects { + if _, ok := current[s]; !ok { + if _, err := mset.subscribeInternal(s, mset.processInboundJetStreamMsg); err != nil { + mset.mu.Unlock() + return err + } + } + delete(current, s) + } + // What is left in current needs to be deleted. + for s := range current { + if err := mset.unsubscribeInternal(s); err != nil { + mset.mu.Unlock() + return err + } + } -// This will unsubscribe us from the exact subject given. -// We do not currently track the subs so do not have the sid. -// This should be called only on an update. -// Lock should be held. -func (mset *Stream) unsubscribeInternal(subject string) error { - c := mset.client - if c == nil { - return fmt.Errorf("invalid stream") - } - if !c.srv.eventsEnabled() { - return ErrNoSysAccount - } + // Check for the Duplicates + if cfg.Duplicates != ocfg.Duplicates && mset.ddtmr != nil { + // Let it fire right away, it will adjust properly on purge. + mset.ddtmr.Reset(time.Microsecond) + } - var sid []byte + // Check for Sources. + if len(cfg.Sources) > 0 || len(ocfg.Sources) > 0 { + currentIName := make(map[string]struct{}) + needsStartingSeqNum := make(map[string]struct{}) - c.mu.Lock() - for _, sub := range c.subs { - if subject == string(sub.subject) { - sid = sub.sid - break + for _, s := range ocfg.Sources { + currentIName[s.iname] = struct{}{} + } + for _, s := range cfg.Sources { + s.setIndexName() + if _, ok := currentIName[s.iname]; !ok { + // new source + if mset.sources == nil { + mset.sources = make(map[string]*sourceInfo) + } + mset.cfg.Sources = append(mset.cfg.Sources, s) + + var si *sourceInfo + + if len(s.SubjectTransforms) == 0 { + si = &sourceInfo{name: s.Name, iname: s.iname, sf: s.FilterSubject} + } else { + si = &sourceInfo{name: s.Name, iname: s.iname} + si.trs = make([]*subjectTransform, len(s.SubjectTransforms)) + si.sfs = make([]string, len(s.SubjectTransforms)) + for i := range s.SubjectTransforms { + // err can be ignored as already validated in config check + si.sfs[i] = s.SubjectTransforms[i].Source + var err error + si.trs[i], err = NewSubjectTransform(s.SubjectTransforms[i].Source, s.SubjectTransforms[i].Destination) + if err != nil { + mset.mu.Unlock() + return fmt.Errorf("unable to get subject transform for source: %v", err) + } + } + } + + mset.sources[s.iname] = si + needsStartingSeqNum[s.iname] = struct{}{} + } else { + // source already exists + delete(currentIName, s.iname) + } + } + // What is left in currentIName needs to be deleted. + for iName := range currentIName { + mset.cancelSourceConsumer(iName) + delete(mset.sources, iName) + } + neededCopy := make(map[string]struct{}, len(needsStartingSeqNum)) + for iName := range needsStartingSeqNum { + neededCopy[iName] = struct{}{} + } + mset.setStartingSequenceForSources(needsStartingSeqNum) + for iName := range neededCopy { + mset.setupSourceConsumer(iName, mset.sources[iName].sseq+1, time.Time{}) + } } } - c.mu.Unlock() - if sid != nil { - return c.processUnsub(sid) + // Check for a change in allow direct status. + // These will run on all members, so just update as appropriate here. + // We do make sure we are caught up under monitorStream() during initial startup. + if cfg.AllowDirect != ocfg.AllowDirect { + if cfg.AllowDirect { + mset.subscribeToDirect() + } else { + mset.unsubscribeToDirect() + } } - return nil -} -// Lock should be held. -func (mset *Stream) unsubscribe(sub *subscription) { - if sub == nil || mset.client == nil { - return + // Check for changes to RePublish. + if cfg.RePublish != nil { + // Empty same as all. + if cfg.RePublish.Source == _EMPTY_ { + cfg.RePublish.Source = fwcs + } + if cfg.RePublish.Destination == _EMPTY_ { + cfg.RePublish.Destination = fwcs + } + tr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination) + if err != nil { + mset.mu.Unlock() + return fmt.Errorf("stream configuration for republish from '%s' to '%s': %w", cfg.RePublish.Source, cfg.RePublish.Destination, err) + } + // Assign our transform for republishing. + mset.tr = tr + } else { + mset.tr = nil } - mset.client.unsubscribe(mset.client.acc, sub, true, true) -} - -func (mset *Stream) unsubscribeUnlocked(sub *subscription) { - mset.mu.Lock() - mset.unsubscribe(sub) - mset.mu.Unlock() -} - -func (mset *Stream) setupStore(fsCfg *FileStoreConfig) error { - mset.mu.Lock() - mset.created = time.Now().UTC() - switch mset.config.Storage { - case MemoryStorage: - ms, err := newMemStore(&mset.config) + // Check for changes to subject transform + if ocfg.SubjectTransform == nil && cfg.SubjectTransform != nil { + tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination) if err != nil { mset.mu.Unlock() - return err + return fmt.Errorf("stream configuration for subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err) } - mset.store = ms - case FileStorage: - fs, err := newFileStoreWithCreated(*fsCfg, mset.config, mset.created) + mset.itr = tr + } else if ocfg.SubjectTransform != nil && cfg.SubjectTransform != nil && + (ocfg.SubjectTransform.Source != cfg.SubjectTransform.Source || ocfg.SubjectTransform.Destination != cfg.SubjectTransform.Destination) { + tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination) if err != nil { mset.mu.Unlock() - return err + return fmt.Errorf("stream configuration for subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err) } - mset.store = fs + mset.itr = tr + } else if ocfg.SubjectTransform != nil && cfg.SubjectTransform == nil { + mset.itr = nil + } + + js := mset.js + + if targetTier := tierName(cfg.Replicas); mset.tier != targetTier { + // In cases such as R1->R3, only one update is needed + jsa.usageMu.RLock() + _, ok := jsa.limits[targetTier] + jsa.usageMu.RUnlock() + if ok { + // error never set + _, reported, _ := mset.store.Utilization() + jsa.updateUsage(mset.tier, mset.stype, -int64(reported)) + jsa.updateUsage(targetTier, mset.stype, int64(reported)) + mset.tier = targetTier + } + // else in case the new tier does not exist (say on move), keep the old tier around + // a subsequent update to an existing tier will then move from existing past tier to existing new tier } - mset.mu.Unlock() - mset.store.RegisterStorageUpdates(mset.storeUpdates) - - return nil -} + if mset.isLeader() && mset.sa != nil && ocfg.Retention != cfg.Retention && cfg.Retention == InterestPolicy { + // Before we can update the retention policy for the consumer, we need + // the replica count of all consumers to match the stream. + for _, c := range mset.sa.consumers { + if c.Config.Replicas > 0 && c.Config.Replicas != cfg.Replicas { + mset.mu.Unlock() + return fmt.Errorf("consumer %q replica count must be %d", c.Name, cfg.Replicas) + } + } + } -// Called for any updates to the underlying stream. We pass through the bytes to the -// jetstream account. We do local processing for stream pending for consumers, but only -// for removals. -// Lock should not be held. -func (mset *Stream) storeUpdates(md, bd int64, seq uint64, subj string) { - // If we have a single negative update then we will process our consumers for stream pending. - // Purge and Store handled separately inside individual calls. - if md == -1 && seq > 0 { - mset.mu.RLock() - for _, o := range mset.consumers { - o.decStreamPending(seq, subj) + // Now update config and store's version of our config. + // Although we are under the stream write lock, we will also assign the new + // configuration under mset.cfgMu lock. This is so that in places where + // mset.mu cannot be acquired (like many cases in consumer.go where code + // is under the consumer's lock), and the stream's configuration needs to + // be inspected, one can use mset.cfgMu's read lock to do that safely. + mset.cfgMu.Lock() + mset.cfg = *cfg + mset.cfgMu.Unlock() + + // If we're changing retention and haven't errored because of consumer + // replicas by now, whip through and update the consumer retention. + if ocfg.Retention != cfg.Retention { + toUpdate := make([]*consumer, 0, len(mset.consumers)) + for _, c := range mset.consumers { + toUpdate = append(toUpdate, c) } - mset.mu.RUnlock() + var ss StreamState + mset.store.FastState(&ss) + mset.mu.Unlock() + for _, c := range toUpdate { + c.mu.Lock() + c.retention = cfg.Retention + c.mu.Unlock() + if c.retention == InterestPolicy { + // If we're switching to interest, force a check of the + // interest of existing stream messages. + c.checkStateForInterestStream(&ss) + } + } + mset.mu.Lock() } - if mset.jsa != nil { - mset.jsa.updateUsage(mset.config.Storage, bd) + // If we are the leader never suppress update advisory, simply send. + if mset.isLeader() && sendAdvisory { + mset.sendUpdateAdvisoryLocked() + } + mset.mu.Unlock() + + if js != nil { + maxBytesDiff := max(cfg.MaxBytes, 0) - max(ocfg.MaxBytes, 0) + if maxBytesDiff > 0 { + // Reserve the difference + js.reserveStreamResources(&StreamConfig{ + MaxBytes: maxBytesDiff, + Storage: cfg.Storage, + }) + } else if maxBytesDiff < 0 { + // Release the difference + js.releaseStreamResources(&StreamConfig{ + MaxBytes: -maxBytesDiff, + Storage: ocfg.Storage, + }) + } } + + mset.store.UpdateConfig(cfg) + + return nil } -// NumMsgIds returns the number of message ids being tracked for duplicate suppression. -func (mset *Stream) NumMsgIds() int { - mset.mu.RLock() - defer mset.mu.RUnlock() - return len(mset.ddmap) +// Small helper to return the Name field from mset.cfg, protected by +// the mset.cfgMu mutex. This is simply because we have several places +// in consumer.go where we need it. +func (mset *stream) getCfgName() string { + mset.cfgMu.RLock() + defer mset.cfgMu.RUnlock() + return mset.cfg.Name } -// checkMsgId will process and check for duplicates. -// Lock should be held. -func (mset *Stream) checkMsgId(id string) *ddentry { - if id == "" || mset.ddmap == nil { - return nil +// Purge will remove all messages from the stream and underlying store based on the request. +func (mset *stream) purge(preq *JSApiStreamPurgeRequest) (purged uint64, err error) { + mset.mu.RLock() + if mset.closed.Load() { + mset.mu.RUnlock() + return 0, errStreamClosed } - return mset.ddmap[id] -} + if mset.cfg.Sealed { + mset.mu.RUnlock() + return 0, errors.New("sealed stream") + } + store, mlseq := mset.store, mset.lseq + mset.mu.RUnlock() + + if preq != nil { + purged, err = mset.store.PurgeEx(preq.Subject, preq.Sequence, preq.Keep) + } else { + purged, err = mset.store.Purge() + } + if err != nil { + return purged, err + } + + // Grab our stream state. + var state StreamState + store.FastState(&state) + fseq, lseq := state.FirstSeq, state.LastSeq -// Will purge the entries that are past the window. -// Should be called from a timer. -func (mset *Stream) purgeMsgIds() { mset.mu.Lock() - defer mset.mu.Unlock() + // Check if our last has moved past what our original last sequence was, if so reset. + if lseq > mlseq { + mset.setLastSeq(lseq) + } - now := time.Now().UnixNano() - tmrNext := mset.config.Duplicates - window := int64(tmrNext) + // Clear any pending acks below first seq. + mset.clearAllPreAcksBelowFloor(fseq) + mset.mu.Unlock() - for i, dde := range mset.ddarr[mset.ddindex:] { - if now-dde.ts >= window { - delete(mset.ddmap, dde.id) - } else { - mset.ddindex += i - // Check if we should garbage collect here if we are 1/3 total size. - if cap(mset.ddarr) > 3*(len(mset.ddarr)-mset.ddindex) { - mset.ddarr = append([]*ddentry(nil), mset.ddarr[mset.ddindex:]...) - mset.ddindex = 0 - } - tmrNext = time.Duration(window - (now - dde.ts)) - break + // Purge consumers. + // Check for filtered purge. + if preq != nil && preq.Subject != _EMPTY_ { + ss := store.FilteredState(fseq, preq.Subject) + fseq = ss.First + } + + // Take a copy of cList to avoid o.purge() potentially taking the stream lock and + // violating the lock ordering. + mset.clsMu.RLock() + cList := slices.Clone(mset.cList) + mset.clsMu.RUnlock() + for _, o := range cList { + start := fseq + o.mu.RLock() + // we update consumer sequences if: + // no subject was specified, we can purge all consumers sequences + doPurge := preq == nil || + preq.Subject == _EMPTY_ || + // consumer filter subject is equal to purged subject + // or consumer filter subject is subset of purged subject, + // but not the other way around. + o.isEqualOrSubsetMatch(preq.Subject) + // Check if a consumer has a wider subject space than what we purged + var isWider bool + if !doPurge && preq != nil && o.isFilteredMatch(preq.Subject) { + doPurge, isWider = true, true + start = state.FirstSeq } - } - if len(mset.ddmap) > 0 { - // Make sure to not fire too quick - const minFire = 50 * time.Millisecond - if tmrNext < minFire { - tmrNext = minFire + o.mu.RUnlock() + if doPurge { + o.purge(start, lseq, isWider) } - mset.ddtmr.Reset(tmrNext) - } else { - mset.ddtmr.Stop() - mset.ddtmr = nil } + + return purged, nil } -// storeMsgId will store the message id for duplicate detection. -func (mset *Stream) storeMsgId(dde *ddentry) { - mset.mu.Lock() - if mset.ddmap == nil { - mset.ddmap = make(map[string]*ddentry) +// RemoveMsg will remove a message from a stream. +// FIXME(dlc) - Should pick one and be consistent. +func (mset *stream) removeMsg(seq uint64) (bool, error) { + return mset.deleteMsg(seq) +} + +// DeleteMsg will remove a message from a stream. +func (mset *stream) deleteMsg(seq uint64) (bool, error) { + if mset.closed.Load() { + return false, errStreamClosed } - if mset.ddtmr == nil { - mset.ddtmr = time.AfterFunc(mset.config.Duplicates, mset.purgeMsgIds) + removed, err := mset.store.RemoveMsg(seq) + if err != nil { + return removed, err } - mset.ddmap[dde.id] = dde - mset.ddarr = append(mset.ddarr, dde) + mset.mu.Lock() + mset.clearAllPreAcks(seq) mset.mu.Unlock() + return removed, err } -// Will return the value for the header denoted by key or nil if it does not exists. -// This function ignores errors and tries to achieve speed and no additional allocations. -func getHdrVal(key string, hdr []byte) []byte { - index := bytes.Index(hdr, []byte(key)) - if index < 0 { - return nil +// EraseMsg will securely remove a message and rewrite the data with random data. +func (mset *stream) eraseMsg(seq uint64) (bool, error) { + if mset.closed.Load() { + return false, errStreamClosed } - var value []byte - for i := index + len(key) + 2; i > 0 && i < len(hdr); i++ { - if hdr[i] == '\r' && i < len(hdr)-1 && hdr[i+1] == '\n' { - break - } - value = append(value, hdr[i]) + removed, err := mset.store.EraseMsg(seq) + if err != nil { + return removed, err } - return value -} - -// Fast lookup of msgId. -func getMsgId(hdr []byte) string { - return string(getHdrVal(JSMsgId, hdr)) + mset.mu.Lock() + mset.clearAllPreAcks(seq) + mset.mu.Unlock() + return removed, err } -// Fast lookup of expected last msgId. -func getExpectedLastMsgId(hdr []byte) string { - return string(getHdrVal(JSExpectedLastMsgId, hdr)) +// Are we a mirror? +func (mset *stream) isMirror() bool { + mset.cfgMu.RLock() + defer mset.cfgMu.RUnlock() + return mset.cfg.Mirror != nil } -// Fast lookup of expected stream. -func getExpectedStream(hdr []byte) string { - return string(getHdrVal(JSExpectedStream, hdr)) +func (mset *stream) sourcesInfo() (sis []*StreamSourceInfo) { + mset.mu.RLock() + defer mset.mu.RUnlock() + sis = make([]*StreamSourceInfo, 0, len(mset.sources)) + for _, si := range mset.sources { + sis = append(sis, mset.sourceInfo(si)) + } + return sis } -// Fast lookup of expected stream. -func getExpectedLastSeq(hdr []byte) uint64 { - bseq := getHdrVal(JSExpectedLastSeq, hdr) - if len(bseq) == 0 { - return 0 +// Lock should be held +func (mset *stream) sourceInfo(si *sourceInfo) *StreamSourceInfo { + if si == nil { + return nil } - return uint64(parseInt64(bseq)) -} -// processInboundJetStreamMsg handles processing messages bound for a stream. -func (mset *Stream) processInboundJetStreamMsg(_ *subscription, pc *client, subject, reply string, msg []byte) { - mset.mu.Lock() - store := mset.store - c := mset.client - var accName string - if c != nil && c.acc != nil { - accName = c.acc.Name + var ssi = StreamSourceInfo{Name: si.name, Lag: si.lag, Error: si.err, FilterSubject: si.sf} + + trConfigs := make([]SubjectTransformConfig, len(si.sfs)) + for i := range si.sfs { + var destination string + if si.trs[i] != nil { + destination = si.trs[i].dest + } + trConfigs[i] = SubjectTransformConfig{si.sfs[i], destination} } - doAck := !mset.config.NoAck - pubAck := mset.pubAck - jsa := mset.jsa - stype := mset.config.Storage - name := mset.config.Name - maxMsgSize := int(mset.config.MaxMsgSize) - numConsumers := len(mset.consumers) - interestRetention := mset.config.Retention == InterestPolicy + ssi.SubjectTransforms = trConfigs - var resp = &JSPubAckResponse{} + // If we have not heard from the source, set Active to -1. + if last := si.last.Load(); last == 0 { + ssi.Active = -1 + } else { + ssi.Active = time.Since(time.Unix(0, last)) + } - // Process msg headers if present. - var msgId string - if pc != nil && pc.pa.hdr > 0 { - hdr := msg[:pc.pa.hdr] - msgId = getMsgId(hdr) - sendq := mset.sendq - if dde := mset.checkMsgId(msgId); dde != nil { - mset.mu.Unlock() - if doAck && len(reply) > 0 { - response := append(pubAck, strconv.FormatUint(dde.seq, 10)...) - response = append(response, ",\"duplicate\": true}"...) - sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, response, nil, 0} - } - return + var ext *ExternalStream + if mset.cfg.Mirror != nil { + ext = mset.cfg.Mirror.External + } else if ss := mset.streamSource(si.iname); ss != nil && ss.External != nil { + ext = ss.External + } + if ext != nil { + ssi.External = &ExternalStream{ + ApiPrefix: ext.ApiPrefix, + DeliverPrefix: ext.DeliverPrefix, } - // Expected stream. - if sname := getExpectedStream(hdr); sname != _EMPTY_ && sname != name { - mset.mu.Unlock() - if doAck && len(reply) > 0 { - resp.PubAck = &PubAck{Stream: name} - resp.Error = &ApiError{Code: 400, Description: "expected stream does not match"} - b, _ := json.Marshal(resp) - sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, b, nil, 0} - } - return + } + return &ssi +} + +// Return our source info for our mirror. +func (mset *stream) mirrorInfo() *StreamSourceInfo { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.sourceInfo(mset.mirror) +} + +// retryDisconnectedSyncConsumers() will check if we have any disconnected +// sync consumers for either mirror or a source and will reset and retry to connect. +func (mset *stream) retryDisconnectedSyncConsumers() { + mset.mu.Lock() + defer mset.mu.Unlock() + + // Only applicable if we are the stream leader. + if !mset.isLeader() { + return + } + + shouldRetry := func(si *sourceInfo) bool { + if si != nil && (si.sip || si.sub == nil || (si.sub.client != nil && si.sub.client.isClosed())) { + // Need to reset + si.fails, si.sip = 0, false + mset.cancelSourceInfo(si) + return true } - // Expected last sequence. - if seq := getExpectedLastSeq(hdr); seq > 0 && seq != mset.lseq { - lseq := mset.lseq - mset.mu.Unlock() - if doAck && len(reply) > 0 { - resp.PubAck = &PubAck{Stream: name} - resp.Error = &ApiError{Code: 400, Description: fmt.Sprintf("wrong last sequence: %d", lseq)} - b, _ := json.Marshal(resp) - sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, b, nil, 0} - } - return + return false + } + + // Check mirrors first. + if si := mset.mirror; si != nil { + if shouldRetry(si) { + mset.scheduleSetupMirrorConsumerRetry() } - // Expected last msgId. - if lmsgId := getExpectedLastMsgId(hdr); lmsgId != _EMPTY_ && lmsgId != mset.lmsgId { - last := mset.lmsgId - mset.mu.Unlock() - if doAck && len(reply) > 0 { - resp.PubAck = &PubAck{Stream: name} - resp.Error = &ApiError{Code: 400, Description: fmt.Sprintf("wrong last msg ID: %s", last)} - b, _ := json.Marshal(resp) - sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, b, nil, 0} + } else { + for _, si := range mset.sources { + if shouldRetry(si) { + mset.setupSourceConsumer(si.iname, si.sseq+1, time.Time{}) } - return } } +} + +const ( + // Our consumer HB interval. + sourceHealthHB = 1 * time.Second + // How often we check and our stalled interval. + sourceHealthCheckInterval = 10 * time.Second +) + +// Will run as a Go routine to process mirror consumer messages. +func (mset *stream) processMirrorMsgs(mirror *sourceInfo, ready *sync.WaitGroup) { + s := mset.srv + defer func() { + mirror.wg.Done() + s.grWG.Done() + }() + + // Grab stream quit channel. + mset.mu.Lock() + msgs, qch, siqch := mirror.msgs, mset.qch, mirror.qch + // Set the last seen as now so that we don't fail at the first check. + mirror.last.Store(time.Now().UnixNano()) + mset.mu.Unlock() - if c == nil { + // Signal the caller that we have captured the above fields. + ready.Done() + + // Make sure we have valid ipq for msgs. + if msgs == nil { + mset.mu.Lock() + mset.cancelMirrorConsumer() mset.mu.Unlock() return } - // Response Ack. - var ( - response []byte - seq uint64 - err error - ts int64 - ) + t := time.NewTicker(sourceHealthCheckInterval) + defer t.Stop() + + for { + select { + case <-s.quitCh: + return + case <-qch: + return + case <-siqch: + return + case <-msgs.ch: + ims := msgs.pop() + for _, im := range ims { + if !mset.processInboundMirrorMsg(im) { + break + } + im.returnToPool() + } + msgs.recycle(&ims) + case <-t.C: + mset.mu.RLock() + var stalled bool + if mset.mirror != nil { + stalled = time.Since(time.Unix(0, mset.mirror.last.Load())) > sourceHealthCheckInterval + } + isLeader := mset.isLeader() + mset.mu.RUnlock() + // No longer leader. + if !isLeader { + mset.mu.Lock() + mset.cancelMirrorConsumer() + mset.mu.Unlock() + return + } + // We are stalled. + if stalled { + mset.retryMirrorConsumer() + } + } + } +} - // Header support. - var hdr []byte +// Checks that the message is from our current direct consumer. We can not depend on sub comparison +// since cross account imports break. +func (si *sourceInfo) isCurrentSub(reply string) bool { + return si.cname != _EMPTY_ && strings.HasPrefix(reply, jsAckPre) && si.cname == tokenAt(reply, 4) +} - // Check to see if we are over the max msg size. - if maxMsgSize >= 0 && len(msg) > maxMsgSize { +// processInboundMirrorMsg handles processing messages bound for a stream. +func (mset *stream) processInboundMirrorMsg(m *inMsg) bool { + mset.mu.Lock() + if mset.mirror == nil { mset.mu.Unlock() - if doAck && len(reply) > 0 { - resp.PubAck = &PubAck{Stream: name} - resp.Error = &ApiError{Code: 400, Description: "message size exceeds maximum allowed"} - b, _ := json.Marshal(resp) - mset.sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, b, nil, 0} + return false + } + if !mset.isLeader() { + mset.cancelMirrorConsumer() + mset.mu.Unlock() + return false + } + + isControl := m.isControlMsg() + + // Ignore from old subscriptions. + // The reason we can not just compare subs is that on cross account imports they will not match. + if !mset.mirror.isCurrentSub(m.rply) && !isControl { + mset.mu.Unlock() + return false + } + + // Check for heartbeats and flow control messages. + if isControl { + var needsRetry bool + // Flow controls have reply subjects. + if m.rply != _EMPTY_ { + mset.handleFlowControl(m) + } else { + // For idle heartbeats make sure we did not miss anything and check if we are considered stalled. + if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != mset.mirror.dseq { + needsRetry = true + } else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 { + // Other side thinks we are stalled, so send flow control reply. + mset.outq.sendMsg(string(fcReply), nil) + } } - return + mset.mu.Unlock() + if needsRetry { + mset.retryMirrorConsumer() + } + return !needsRetry } - var noInterest bool + sseq, dseq, dc, ts, pending := replyInfo(m.rply) - // If we are interest based retention and have no consumers then we can skip. - if interestRetention { - if numConsumers == 0 { - noInterest = true - } else if mset.numFilter > 0 { - // Assume none. - noInterest = true - for _, o := range mset.consumers { - if o.config.FilterSubject != _EMPTY_ && subjectIsSubsetMatch(subject, o.config.FilterSubject) { - noInterest = false + if dc > 1 { + mset.mu.Unlock() + return false + } + + // Mirror info tracking. + olag, osseq, odseq := mset.mirror.lag, mset.mirror.sseq, mset.mirror.dseq + if sseq == mset.mirror.sseq+1 { + mset.mirror.dseq = dseq + mset.mirror.sseq++ + } else if sseq <= mset.mirror.sseq { + // Ignore older messages. + mset.mu.Unlock() + return true + } else if mset.mirror.cname == _EMPTY_ { + mset.mirror.cname = tokenAt(m.rply, 4) + mset.mirror.dseq, mset.mirror.sseq = dseq, sseq + } else { + // If the deliver sequence matches then the upstream stream has expired or deleted messages. + if dseq == mset.mirror.dseq+1 { + mset.skipMsgs(mset.mirror.sseq+1, sseq-1) + mset.mirror.dseq++ + mset.mirror.sseq = sseq + } else { + mset.mu.Unlock() + mset.retryMirrorConsumer() + return false + } + } + + if pending == 0 { + mset.mirror.lag = 0 + } else { + mset.mirror.lag = pending - 1 + } + + // Check if we allow mirror direct here. If so check they we have mostly caught up. + // The reason we do not require 0 is if the source is active we may always be slightly behind. + if mset.cfg.MirrorDirect && mset.mirror.dsub == nil && pending < dgetCaughtUpThresh { + if err := mset.subscribeToMirrorDirect(); err != nil { + // Disable since we had problems above. + mset.cfg.MirrorDirect = false + } + } + + // Do the subject transform if there's one + if len(mset.mirror.trs) > 0 { + for _, tr := range mset.mirror.trs { + if tr == nil { + continue + } else { + tsubj, err := tr.Match(m.subj) + if err == nil { + m.subj = tsubj break } } } } - // Skip msg here. - if noInterest { - mset.lseq = store.SkipMsg() - mset.lmsgId = msgId - mset.mu.Unlock() + s, js, stype := mset.srv, mset.js, mset.cfg.Storage + node := mset.node + mset.mu.Unlock() - if doAck && len(reply) > 0 { - response = append(pubAck, strconv.FormatUint(mset.lseq, 10)...) - response = append(response, '}') - mset.sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, response, nil, 0} + var err error + if node != nil { + if js.limitsExceeded(stype) { + s.resourcesExceededError() + err = ApiErrors[JSInsufficientResourcesErr] + } else { + err = node.Propose(encodeStreamMsg(m.subj, _EMPTY_, m.hdr, m.msg, sseq-1, ts, true)) } - // If we have a msgId make sure to save. - if msgId != _EMPTY_ { - mset.storeMsgId(&ddentry{msgId, seq, time.Now().UnixNano()}) + } else { + err = mset.processJetStreamMsg(m.subj, _EMPTY_, m.hdr, m.msg, sseq-1, ts, nil, true) + } + if err != nil { + if strings.Contains(err.Error(), "no space left") { + s.Errorf("JetStream out of space, will be DISABLED") + s.DisableJetStream() + return false + } + if err != errLastSeqMismatch { + mset.mu.RLock() + accName, sname := mset.acc.Name, mset.cfg.Name + mset.mu.RUnlock() + s.RateLimitWarnf("Error processing inbound mirror message for '%s' > '%s': %v", + accName, sname, err) + } else { + // We may have missed messages, restart. + if sseq <= mset.lastSeq() { + mset.mu.Lock() + mset.mirror.lag = olag + mset.mirror.sseq = osseq + mset.mirror.dseq = odseq + mset.mu.Unlock() + return false + } else { + mset.mu.Lock() + mset.mirror.dseq = odseq + mset.mirror.sseq = osseq + mset.mu.Unlock() + mset.retryMirrorConsumer() + } } + } + return err == nil +} + +func (mset *stream) setMirrorErr(err *ApiError) { + mset.mu.Lock() + if mset.mirror != nil { + mset.mirror.err = err + } + mset.mu.Unlock() +} + +// Cancels a mirror consumer. +// +// Lock held on entry +func (mset *stream) cancelMirrorConsumer() { + if mset.mirror == nil { return } + mset.cancelSourceInfo(mset.mirror) +} + +// Similar to setupMirrorConsumer except that it will print a debug statement +// indicating that there is a retry. +// +// Lock is acquired in this function +func (mset *stream) retryMirrorConsumer() error { + mset.mu.Lock() + defer mset.mu.Unlock() + mset.srv.Debugf("Retrying mirror consumer for '%s > %s'", mset.acc.Name, mset.cfg.Name) + mset.cancelMirrorConsumer() + return mset.setupMirrorConsumer() +} - // If here we will attempt to store the message. - // Check for headers. - if pc != nil && pc.pa.hdr > 0 { - hdr = msg[:pc.pa.hdr] - msg = msg[pc.pa.hdr:] +// Lock should be held. +func (mset *stream) skipMsgs(start, end uint64) { + node, store := mset.node, mset.store + // If we are not clustered we can short circuit now with store.SkipMsgs + if node == nil { + store.SkipMsgs(start, end-start+1) + mset.lseq = end + return } - // Assume this will succeed. - olseq, olmsgId := mset.lseq, mset.lmsgId - mset.lseq++ - mset.lmsgId = msgId + // FIXME (dlc) - We should allow proposals of DeleteRange, but would need to make sure all peers support. + // With syncRequest was easy to add bool into request. + var entries []*Entry + for seq := start; seq <= end; seq++ { + entries = append(entries, newEntry(EntryNormal, encodeStreamMsg(_EMPTY_, _EMPTY_, nil, nil, seq-1, 0, false))) + // So a single message does not get too big. + if len(entries) > 10_000 { + node.ProposeMulti(entries) + // We need to re-create `entries` because there is a reference + // to it in the node's pae map. + entries = entries[:0] + } + } + // Send all at once. + if len(entries) > 0 { + node.ProposeMulti(entries) + } +} - // We hold the lock to this point to make sure nothing gets between us since we check for pre-conditions. - mset.mu.Unlock() +const ( + // Base retry backoff duration. + retryBackOff = 5 * time.Second + // Maximum amount we will wait. + retryMaximum = 2 * time.Minute +) - // Store actual msg. - seq, ts, err = store.StoreMsg(subject, hdr, msg) +// Calculate our backoff based on number of failures. +func calculateRetryBackoff(fails int) time.Duration { + backoff := time.Duration(retryBackOff) * time.Duration(fails*2) + if backoff > retryMaximum { + backoff = retryMaximum + } + return backoff +} - // If we did not succeed put those values back. - if err != nil || seq == 0 { +// This will schedule a call to setupMirrorConsumer, taking into account the last +// time it was retried and determine the soonest setupMirrorConsumer can be called +// without tripping the sourceConsumerRetryThreshold. We will also take into account +// number of failures and will back off our retries. +// The mset.mirror pointer has been verified to be not nil by the caller. +// +// Lock held on entry +func (mset *stream) scheduleSetupMirrorConsumerRetry() { + // We are trying to figure out how soon we can retry. setupMirrorConsumer will reject + // a retry if last was done less than "sourceConsumerRetryThreshold" ago. + next := sourceConsumerRetryThreshold - time.Since(mset.mirror.lreq) + if next < 0 { + // It means that we have passed the threshold and so we are ready to go. + next = 0 + } + // Take into account failures here. + next += calculateRetryBackoff(mset.mirror.fails) + + // Add some jitter. + next += time.Duration(rand.Intn(int(100*time.Millisecond))) + 100*time.Millisecond + + time.AfterFunc(next, func() { mset.mu.Lock() - mset.lseq = olseq - mset.lmsgId = olmsgId + mset.setupMirrorConsumer() mset.mu.Unlock() + }) +} + +// How long we wait for a response from a consumer create request for a source or mirror. +var srcConsumerWaitTime = 30 * time.Second + +// Setup our mirror consumer. +// Lock should be held. +func (mset *stream) setupMirrorConsumer() error { + if mset.closed.Load() { + return errStreamClosed + } + if mset.outq == nil { + return errors.New("outq required") + } + // We use to prevent update of a mirror configuration in cluster + // mode but not in standalone. This is now fixed. However, without + // rejecting the update, it could be that if the source stream was + // removed and then later the mirrored stream config changed to + // remove mirror configuration, this function would panic when + // accessing mset.cfg.Mirror fields. Adding this protection in case + // we allow in the future the mirror config to be changed (removed). + if mset.cfg.Mirror == nil { + return errors.New("invalid mirror configuration") + } + + // If this is the first time + if mset.mirror == nil { + mset.mirror = &sourceInfo{name: mset.cfg.Mirror.Name} + } else { + mset.cancelSourceInfo(mset.mirror) + mset.mirror.sseq = mset.lseq + } + + // If we are no longer the leader stop trying. + if !mset.isLeader() { + return nil + } + + mirror := mset.mirror + + // We want to throttle here in terms of how fast we request new consumers, + // or if the previous is still in progress. + if last := time.Since(mirror.lreq); last < sourceConsumerRetryThreshold || mirror.sip { + mset.scheduleSetupMirrorConsumerRetry() + return nil + } + mirror.lreq = time.Now() + + // Determine subjects etc. + var deliverSubject string + ext := mset.cfg.Mirror.External + + if ext != nil && ext.DeliverPrefix != _EMPTY_ { + deliverSubject = strings.ReplaceAll(ext.DeliverPrefix+syncSubject(".M"), "..", ".") + } else { + deliverSubject = syncSubject("$JS.M") + } + + // Now send off request to create/update our consumer. This will be all API based even in single server mode. + // We calculate durable names apriori so we do not need to save them off. + + var state StreamState + mset.store.FastState(&state) + + req := &CreateConsumerRequest{ + Stream: mset.cfg.Mirror.Name, + Config: ConsumerConfig{ + DeliverSubject: deliverSubject, + DeliverPolicy: DeliverByStartSequence, + OptStartSeq: state.LastSeq + 1, + AckPolicy: AckNone, + AckWait: 22 * time.Hour, + MaxDeliver: 1, + Heartbeat: sourceHealthHB, + FlowControl: true, + Direct: true, + InactiveThreshold: sourceHealthCheckInterval, + }, + } + + // Only use start optionals on first time. + if state.Msgs == 0 && state.FirstSeq == 0 { + req.Config.OptStartSeq = 0 + if mset.cfg.Mirror.OptStartSeq > 0 { + req.Config.OptStartSeq = mset.cfg.Mirror.OptStartSeq + } else if mset.cfg.Mirror.OptStartTime != nil { + req.Config.OptStartTime = mset.cfg.Mirror.OptStartTime + req.Config.DeliverPolicy = DeliverByStartTime + } + } + if req.Config.OptStartSeq == 0 && req.Config.OptStartTime == nil { + // If starting out and lastSeq is 0. + req.Config.DeliverPolicy = DeliverAll + } + + // Filters + if mset.cfg.Mirror.FilterSubject != _EMPTY_ { + req.Config.FilterSubject = mset.cfg.Mirror.FilterSubject + mirror.sf = mset.cfg.Mirror.FilterSubject + } + + if lst := len(mset.cfg.Mirror.SubjectTransforms); lst > 0 { + sfs := make([]string, lst) + trs := make([]*subjectTransform, lst) + + for i, tr := range mset.cfg.Mirror.SubjectTransforms { + // will not fail as already checked before that the transform will work + subjectTransform, err := NewSubjectTransform(tr.Source, tr.Destination) + if err != nil { + mset.srv.Errorf("Unable to get transform for mirror consumer: %v", err) + } + sfs[i] = tr.Source + trs[i] = subjectTransform + } + mirror.sfs = sfs + mirror.trs = trs + // If there was no explicit FilterSubject defined and we have a single + // subject transform, use Config.FilterSubject instead of FilterSubjects + // so that we can use the extended consumer create API down below. + if req.Config.FilterSubject == _EMPTY_ && len(sfs) == 1 { + req.Config.FilterSubject = sfs[0] + } else { + req.Config.FilterSubjects = sfs + } } + respCh := make(chan *JSApiConsumerCreateResponse, 1) + reply := infoReplySubject() + crSub, err := mset.subscribeInternal(reply, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + mset.unsubscribe(sub) + _, msg := c.msgParts(rmsg) + + var ccr JSApiConsumerCreateResponse + if err := json.Unmarshal(msg, &ccr); err != nil { + c.Warnf("JetStream bad mirror consumer create response: %q", msg) + mset.setMirrorErr(ApiErrors[JSInvalidJSONErr]) + return + } + select { + case respCh <- &ccr: + default: + } + }) if err != nil { - if err != ErrStoreClosed { - c.Errorf("JetStream failed to store a msg on account: %q stream: %q - %v", accName, name, err) + mirror.err = NewJSMirrorConsumerSetupFailedError(err, Unless(err)) + mset.scheduleSetupMirrorConsumerRetry() + return nil + } + + var subject string + if req.Config.FilterSubject != _EMPTY_ { + req.Config.Name = fmt.Sprintf("mirror-%s", createConsumerName()) + subject = fmt.Sprintf(JSApiConsumerCreateExT, mset.cfg.Mirror.Name, req.Config.Name, req.Config.FilterSubject) + } else { + subject = fmt.Sprintf(JSApiConsumerCreateT, mset.cfg.Mirror.Name) + } + if ext != nil { + subject = strings.Replace(subject, JSApiPrefix, ext.ApiPrefix, 1) + subject = strings.ReplaceAll(subject, "..", ".") + } + + // Marshal now that we are done with `req`. + b, _ := json.Marshal(req) + + // Reset + mirror.msgs = nil + mirror.err = nil + mirror.sip = true + + // Send the consumer create request + mset.outq.send(newJSPubMsg(subject, _EMPTY_, reply, nil, b, nil, 0)) + + go func() { + + var retry bool + defer func() { + mset.mu.Lock() + // Check that this is still valid and if so, clear the "setup in progress" flag. + if mset.mirror != nil { + mset.mirror.sip = false + // If we need to retry, schedule now + // If sub is not nil means we re-established somewhere else so do not re-attempt here. + if retry && mset.mirror.sub == nil { + mset.mirror.fails++ + // Cancel here since we can not do anything with this consumer at this point. + mset.cancelSourceInfo(mset.mirror) + mset.scheduleSetupMirrorConsumerRetry() + } else { + // Clear on success. + mset.mirror.fails = 0 + } + } + mset.mu.Unlock() + }() + + // Wait for previous processMirrorMsgs go routine to be completely done. + // If none is running, this will not block. + mset.mu.Lock() + if mset.mirror == nil { + // Mirror config has been removed. + mset.mu.Unlock() + return + } else { + wg := &mset.mirror.wg + mset.mu.Unlock() + wg.Wait() } - if doAck && len(reply) > 0 { - resp.PubAck = &PubAck{Stream: name} - resp.Error = &ApiError{Code: 400, Description: err.Error()} - response, _ = json.Marshal(resp) + + select { + case ccr := <-respCh: + mset.mu.Lock() + // Mirror config has been removed. + if mset.mirror == nil { + mset.mu.Unlock() + return + } + ready := sync.WaitGroup{} + mirror := mset.mirror + mirror.err = nil + if ccr.Error != nil || ccr.ConsumerInfo == nil { + mset.srv.Warnf("JetStream error response for create mirror consumer: %+v", ccr.Error) + mirror.err = ccr.Error + // Let's retry as soon as possible, but we are gated by sourceConsumerRetryThreshold + retry = true + mset.mu.Unlock() + return + } else { + // Setup actual subscription to process messages from our source. + qname := fmt.Sprintf("[ACC:%s] stream mirror '%s' of '%s' msgs", mset.acc.Name, mset.cfg.Name, mset.cfg.Mirror.Name) + // Create a new queue each time + mirror.msgs = newIPQueue[*inMsg](mset.srv, qname) + msgs := mirror.msgs + sub, err := mset.subscribeInternal(deliverSubject, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy. + if len(hdr) > 0 { + // Remove any Nats-Expected- headers as we don't want to validate them. + hdr = removeHeaderIfPrefixPresent(hdr, "Nats-Expected-") + } + mset.queueInbound(msgs, subject, reply, hdr, msg, nil, nil) + mirror.last.Store(time.Now().UnixNano()) + }) + if err != nil { + mirror.err = NewJSMirrorConsumerSetupFailedError(err, Unless(err)) + retry = true + mset.mu.Unlock() + return + } + // Save our sub. + mirror.sub = sub + + // When an upstream stream expires messages or in general has messages that we want + // that are no longer available we need to adjust here. + var state StreamState + mset.store.FastState(&state) + + // Check if we need to skip messages. + if state.LastSeq != ccr.ConsumerInfo.Delivered.Stream { + // Check to see if delivered is past our last and we have no msgs. This will help the + // case when mirroring a stream that has a very high starting sequence number. + if state.Msgs == 0 && ccr.ConsumerInfo.Delivered.Stream > state.LastSeq { + mset.store.PurgeEx(_EMPTY_, ccr.ConsumerInfo.Delivered.Stream+1, 0) + mset.lseq = ccr.ConsumerInfo.Delivered.Stream + } else { + mset.skipMsgs(state.LastSeq+1, ccr.ConsumerInfo.Delivered.Stream) + } + } + + // Capture consumer name. + mirror.cname = ccr.ConsumerInfo.Name + mirror.dseq = 0 + mirror.sseq = ccr.ConsumerInfo.Delivered.Stream + mirror.qch = make(chan struct{}) + mirror.wg.Add(1) + ready.Add(1) + if !mset.srv.startGoRoutine( + func() { mset.processMirrorMsgs(mirror, &ready) }, + pprofLabels{ + "type": "mirror", + "account": mset.acc.Name, + "stream": mset.cfg.Name, + "consumer": mirror.cname, + }, + ) { + ready.Done() + } + } + mset.mu.Unlock() + ready.Wait() + case <-time.After(srcConsumerWaitTime): + mset.unsubscribe(crSub) + // We already waited 30 seconds, let's retry now. + retry = true } - } else if jsa.limitsExceeded(stype) { - c.Warnf("JetStream resource limits exceeded for account: %q", accName) - if doAck && len(reply) > 0 { - resp.PubAck = &PubAck{Stream: name} - resp.Error = &ApiError{Code: 400, Description: "resource limits exceeded for account"} - response, _ = json.Marshal(resp) + }() + + return nil +} + +func (mset *stream) streamSource(iname string) *StreamSource { + for _, ssi := range mset.cfg.Sources { + if ssi.iname == iname { + return ssi + } + } + return nil +} + +// Lock should be held. +func (mset *stream) retrySourceConsumerAtSeq(iName string, seq uint64) { + s := mset.srv + + s.Debugf("Retrying source consumer for '%s > %s'", mset.acc.Name, mset.cfg.Name) + + // setupSourceConsumer will check that the source is still configured. + mset.setupSourceConsumer(iName, seq, time.Time{}) +} + +// Lock should be held. +func (mset *stream) cancelSourceConsumer(iname string) { + if si := mset.sources[iname]; si != nil { + mset.cancelSourceInfo(si) + si.sseq, si.dseq = 0, 0 + } +} + +// The `si` has been verified to be not nil. The sourceInfo's sub will +// be unsubscribed and set to nil (if not already done) and the +// cname will be reset. The message processing's go routine quit channel +// will be closed if still opened. +// +// Lock should be held +func (mset *stream) cancelSourceInfo(si *sourceInfo) { + if si.sub != nil { + mset.unsubscribe(si.sub) + si.sub = nil + } + // In case we had a mirror direct subscription. + if si.dsub != nil { + mset.unsubscribe(si.dsub) + si.dsub = nil + } + mset.removeInternalConsumer(si) + if si.qch != nil { + close(si.qch) + si.qch = nil + } + if si.msgs != nil { + si.msgs.drain() + si.msgs.unregister() + } + // If we have a schedule setup go ahead and delete that. + if t := mset.sourceSetupSchedules[si.iname]; t != nil { + t.Stop() + delete(mset.sourceSetupSchedules, si.iname) + } +} + +const sourceConsumerRetryThreshold = 2 * time.Second + +// This is the main function to call when needing to setup a new consumer for the source. +// It actually only does the scheduling of the execution of trySetupSourceConsumer in order to implement retry backoff +// and throttle the number of requests. +// Lock should be held. +func (mset *stream) setupSourceConsumer(iname string, seq uint64, startTime time.Time) { + if mset.sourceSetupSchedules == nil { + mset.sourceSetupSchedules = map[string]*time.Timer{} + } + + if _, ok := mset.sourceSetupSchedules[iname]; ok { + // If there is already a timer scheduled, we don't need to do anything. + return + } + + si := mset.sources[iname] + if si == nil || si.sip { // if sourceInfo was removed or setup is in progress, nothing to do + return + } + + // First calculate the delay until the next time we can + var scheduleDelay time.Duration + + if !si.lreq.IsZero() { // it's not the very first time we are called, compute the delay + // We want to throttle here in terms of how fast we request new consumers + if sinceLast := time.Since(si.lreq); sinceLast < sourceConsumerRetryThreshold { + scheduleDelay = sourceConsumerRetryThreshold - sinceLast + } + // Is it a retry? If so, add a backoff + if si.fails > 0 { + scheduleDelay += calculateRetryBackoff(si.fails) + } + } + + // Always add some jitter + scheduleDelay += time.Duration(rand.Intn(int(100*time.Millisecond))) + 100*time.Millisecond + + // Schedule the call to trySetupSourceConsumer + mset.sourceSetupSchedules[iname] = time.AfterFunc(scheduleDelay, func() { + mset.mu.Lock() + defer mset.mu.Unlock() + + delete(mset.sourceSetupSchedules, iname) + mset.trySetupSourceConsumer(iname, seq, startTime) + }) +} + +// This is where we will actually try to create a new consumer for the source +// Lock should be held. +func (mset *stream) trySetupSourceConsumer(iname string, seq uint64, startTime time.Time) { + // Ignore if closed or not leader. + if mset.closed.Load() || !mset.isLeader() { + return + } + + si := mset.sources[iname] + if si == nil { + return + } + + // Cancel previous instance if applicable + mset.cancelSourceInfo(si) + + ssi := mset.streamSource(iname) + if ssi == nil { + return + } + + si.lreq = time.Now() + + // Determine subjects etc. + var deliverSubject string + ext := ssi.External + + if ext != nil && ext.DeliverPrefix != _EMPTY_ { + deliverSubject = strings.ReplaceAll(ext.DeliverPrefix+syncSubject(".S"), "..", ".") + } else { + deliverSubject = syncSubject("$JS.S") + } + + req := &CreateConsumerRequest{ + Stream: si.name, + Config: ConsumerConfig{ + DeliverSubject: deliverSubject, + AckPolicy: AckNone, + AckWait: 22 * time.Hour, + MaxDeliver: 1, + Heartbeat: sourceHealthHB, + FlowControl: true, + Direct: true, + InactiveThreshold: sourceHealthCheckInterval, + }, + } + + // If starting, check any configs. + if !startTime.IsZero() && seq > 1 { + req.Config.OptStartTime = &startTime + req.Config.DeliverPolicy = DeliverByStartTime + } else if seq <= 1 { + if ssi.OptStartSeq > 0 { + req.Config.OptStartSeq = ssi.OptStartSeq + req.Config.DeliverPolicy = DeliverByStartSequence + } else { + // We have not recovered state so check that configured time is less that our first seq time. + var state StreamState + mset.store.FastState(&state) + if ssi.OptStartTime != nil { + if !state.LastTime.IsZero() && ssi.OptStartTime.Before(state.LastTime) { + req.Config.OptStartTime = &state.LastTime + } else { + req.Config.OptStartTime = ssi.OptStartTime + } + req.Config.DeliverPolicy = DeliverByStartTime + } else if state.FirstSeq > 1 && !state.LastTime.IsZero() { + req.Config.OptStartTime = &state.LastTime + req.Config.DeliverPolicy = DeliverByStartTime + } } - store.RemoveMsg(seq) - seq = 0 + } else { - // If we have a msgId make sure to save. - if msgId != "" { - mset.storeMsgId(&ddentry{msgId, seq, ts}) + req.Config.OptStartSeq = seq + req.Config.DeliverPolicy = DeliverByStartSequence + } + // Filters + if ssi.FilterSubject != _EMPTY_ { + req.Config.FilterSubject = ssi.FilterSubject + } + + var filterSubjects []string + for _, tr := range ssi.SubjectTransforms { + filterSubjects = append(filterSubjects, tr.Source) + } + req.Config.FilterSubjects = filterSubjects + + respCh := make(chan *JSApiConsumerCreateResponse, 1) + reply := infoReplySubject() + crSub, err := mset.subscribeInternal(reply, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + mset.unsubscribe(sub) + _, msg := c.msgParts(rmsg) + var ccr JSApiConsumerCreateResponse + if err := json.Unmarshal(msg, &ccr); err != nil { + c.Warnf("JetStream bad source consumer create response: %q", msg) + return } - if doAck && len(reply) > 0 { - response = append(pubAck, strconv.FormatUint(seq, 10)...) - response = append(response, '}') + select { + case respCh <- &ccr: + default: } + }) + if err != nil { + si.err = NewJSSourceConsumerSetupFailedError(err, Unless(err)) + mset.setupSourceConsumer(iname, seq, startTime) + return + } + + var subject string + if req.Config.FilterSubject != _EMPTY_ { + req.Config.Name = fmt.Sprintf("src-%s", createConsumerName()) + subject = fmt.Sprintf(JSApiConsumerCreateExT, si.name, req.Config.Name, req.Config.FilterSubject) + } else if len(req.Config.FilterSubjects) == 1 { + req.Config.Name = fmt.Sprintf("src-%s", createConsumerName()) + // It is necessary to switch to using FilterSubject here as the extended consumer + // create API checks for it, so as to not accidentally allow multiple filtered subjects. + req.Config.FilterSubject = req.Config.FilterSubjects[0] + req.Config.FilterSubjects = nil + subject = fmt.Sprintf(JSApiConsumerCreateExT, si.name, req.Config.Name, req.Config.FilterSubject) + } else { + subject = fmt.Sprintf(JSApiConsumerCreateT, si.name) + } + if ext != nil { + subject = strings.Replace(subject, JSApiPrefix, ext.ApiPrefix, 1) + subject = strings.ReplaceAll(subject, "..", ".") + } + + // Marshal request. + b, _ := json.Marshal(req) + + // Reset + si.msgs = nil + si.err = nil + si.sip = true + + // Send the consumer create request + mset.outq.send(newJSPubMsg(subject, _EMPTY_, reply, nil, b, nil, 0)) + + go func() { + + var retry bool + defer func() { + mset.mu.Lock() + // Check that this is still valid and if so, clear the "setup in progress" flag. + if si := mset.sources[iname]; si != nil { + si.sip = false + // If we need to retry, schedule now + // If sub is not nil means we re-established somewhere else so do not re-attempt here. + if retry && si.sub == nil { + si.fails++ + // Cancel here since we can not do anything with this consumer at this point. + mset.cancelSourceInfo(si) + mset.setupSourceConsumer(iname, seq, startTime) + } else { + // Clear on success. + si.fails = 0 + } + } + mset.mu.Unlock() + }() + + select { + case ccr := <-respCh: + mset.mu.Lock() + // Check that it has not been removed or canceled (si.sub would be nil) + if si := mset.sources[iname]; si != nil { + si.err = nil + if ccr.Error != nil || ccr.ConsumerInfo == nil { + // Note: this warning can happen a few times when starting up the server when sourcing streams are + // defined, this is normal as the streams are re-created in no particular order and it is possible + // that a stream sourcing another could come up before all of its sources have been recreated. + mset.srv.Warnf("JetStream error response for stream %s create source consumer %s: %+v", mset.cfg.Name, si.name, ccr.Error) + si.err = ccr.Error + // Let's retry as soon as possible, but we are gated by sourceConsumerRetryThreshold + retry = true + mset.mu.Unlock() + return + } else { + // Check if our shared msg queue and go routine is running or not. + if mset.smsgs == nil { + qname := fmt.Sprintf("[ACC:%s] stream sources '%s' msgs", mset.acc.Name, mset.cfg.Name) + mset.smsgs = newIPQueue[*inMsg](mset.srv, qname) + mset.srv.startGoRoutine(func() { mset.processAllSourceMsgs() }, + pprofLabels{ + "type": "source", + "account": mset.acc.Name, + "stream": mset.cfg.Name, + }, + ) + } + + // Setup actual subscription to process messages from our source. + if si.sseq != ccr.ConsumerInfo.Delivered.Stream { + si.sseq = ccr.ConsumerInfo.Delivered.Stream + 1 + } + // Capture consumer name. + si.cname = ccr.ConsumerInfo.Name + + // Do not set si.sseq to seq here. si.sseq will be set in processInboundSourceMsg + si.dseq = 0 + si.qch = make(chan struct{}) + // Set the last seen as now so that we don't fail at the first check. + si.last.Store(time.Now().UnixNano()) + + msgs := mset.smsgs + sub, err := mset.subscribeInternal(deliverSubject, func(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy. + mset.queueInbound(msgs, subject, reply, hdr, msg, si, nil) + si.last.Store(time.Now().UnixNano()) + }) + if err != nil { + si.err = NewJSSourceConsumerSetupFailedError(err, Unless(err)) + retry = true + mset.mu.Unlock() + return + } + // Save our sub. + si.sub = sub + } + } + mset.mu.Unlock() + case <-time.After(srcConsumerWaitTime): + mset.unsubscribe(crSub) + // We already waited 30 seconds, let's retry now. + retry = true + } + }() +} + +// This will process all inbound source msgs. +// We mux them into one go routine to avoid lock contention and high cpu and thread thrashing. +// TODO(dlc) make this more then one and pin sources to one of a group. +func (mset *stream) processAllSourceMsgs() { + s := mset.srv + defer s.grWG.Done() + + mset.mu.RLock() + msgs, qch := mset.smsgs, mset.qch + mset.mu.RUnlock() + + t := time.NewTicker(sourceHealthCheckInterval) + defer t.Stop() + + // When we detect we are no longer leader, we will cleanup. + // Should always return right after this is called. + cleanUp := func() { + mset.mu.Lock() + defer mset.mu.Unlock() + for _, si := range mset.sources { + mset.cancelSourceConsumer(si.iname) + } + mset.smsgs.drain() + mset.smsgs.unregister() + mset.smsgs = nil + } + + for { + select { + case <-s.quitCh: + return + case <-qch: + return + case <-msgs.ch: + ims := msgs.pop() + for _, im := range ims { + if !mset.processInboundSourceMsg(im.si, im) { + // If we are no longer leader bail. + if !mset.IsLeader() { + msgs.recycle(&ims) + cleanUp() + return + } + break + } + im.returnToPool() + } + msgs.recycle(&ims) + case <-t.C: + // If we are no longer leader bail. + if !mset.IsLeader() { + cleanUp() + return + } + + // Check health of all sources. + var stalled []*sourceInfo + mset.mu.RLock() + for _, si := range mset.sources { + if time.Since(time.Unix(0, si.last.Load())) > sourceHealthCheckInterval { + stalled = append(stalled, si) + } + } + numSources := len(mset.sources) + mset.mu.RUnlock() + + // This can happen on an update when no longer have sources. + if numSources == 0 { + cleanUp() + return + } + + // We do not want to block here so do in separate Go routine. + if len(stalled) > 0 { + go func() { + mset.mu.Lock() + defer mset.mu.Unlock() + for _, si := range stalled { + mset.setupSourceConsumer(si.iname, si.sseq+1, time.Time{}) + } + }() + } + } + } +} + +// isControlMsg determines if this is a control message. +func (m *inMsg) isControlMsg() bool { + return len(m.msg) == 0 && len(m.hdr) > 0 && bytes.HasPrefix(m.hdr, []byte("NATS/1.0 100 ")) +} + +// Sends a reply to a flow control request. +func (mset *stream) sendFlowControlReply(reply string) { + mset.mu.RLock() + if mset.isLeader() && mset.outq != nil { + mset.outq.sendMsg(reply, nil) + } + mset.mu.RUnlock() +} + +// handleFlowControl will properly handle flow control messages for both R==1 and R>1. +// Lock should be held. +func (mset *stream) handleFlowControl(m *inMsg) { + // If we are clustered we will send the flow control message through the replication stack. + if mset.isClustered() { + mset.node.Propose(encodeStreamMsg(_EMPTY_, m.rply, m.hdr, nil, 0, 0, false)) + } else { + mset.outq.sendMsg(m.rply, nil) + } +} + +// processInboundSourceMsg handles processing other stream messages bound for this stream. +func (mset *stream) processInboundSourceMsg(si *sourceInfo, m *inMsg) bool { + mset.mu.Lock() + // If we are no longer the leader cancel this subscriber. + if !mset.isLeader() { + mset.cancelSourceConsumer(si.iname) + mset.mu.Unlock() + return false + } + + isControl := m.isControlMsg() + + // Ignore from old subscriptions. + if !si.isCurrentSub(m.rply) && !isControl { + mset.mu.Unlock() + return false + } + + // Check for heartbeats and flow control messages. + if isControl { + var needsRetry bool + // Flow controls have reply subjects. + if m.rply != _EMPTY_ { + mset.handleFlowControl(m) + } else { + // For idle heartbeats make sure we did not miss anything. + if ldseq := parseInt64(getHeader(JSLastConsumerSeq, m.hdr)); ldseq > 0 && uint64(ldseq) != si.dseq { + needsRetry = true + mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1) + } else if fcReply := getHeader(JSConsumerStalled, m.hdr); len(fcReply) > 0 { + // Other side thinks we are stalled, so send flow control reply. + mset.outq.sendMsg(string(fcReply), nil) + } + } + mset.mu.Unlock() + return !needsRetry + } + + sseq, dseq, dc, _, pending := replyInfo(m.rply) + + if dc > 1 { + mset.mu.Unlock() + return false + } + + // Tracking is done here. + if dseq == si.dseq+1 { + si.dseq++ + si.sseq = sseq + } else if dseq > si.dseq { + if si.cname == _EMPTY_ { + si.cname = tokenAt(m.rply, 4) + si.dseq, si.sseq = dseq, sseq + } else { + mset.retrySourceConsumerAtSeq(si.iname, si.sseq+1) + mset.mu.Unlock() + return false + } + } else { + mset.mu.Unlock() + return false + } + + if pending == 0 { + si.lag = 0 + } else { + si.lag = pending - 1 + } + node := mset.node + mset.mu.Unlock() + + hdr, msg := m.hdr, m.msg + + // If we are daisy chained here make sure to remove the original one. + if len(hdr) > 0 { + hdr = removeHeaderIfPresent(hdr, JSStreamSource) + // Remove any Nats-Expected- headers as we don't want to validate them. + hdr = removeHeaderIfPrefixPresent(hdr, "Nats-Expected-") + } + // Hold onto the origin reply which has all the metadata. + hdr = genHeader(hdr, JSStreamSource, si.genSourceHeader(m.rply)) + + // Do the subject transform for the source if there's one + if len(si.trs) > 0 { + for _, tr := range si.trs { + if tr == nil { + continue + } else { + tsubj, err := tr.Match(m.subj) + if err == nil { + m.subj = tsubj + break + } + } + } + } + + var err error + // If we are clustered we need to propose this message to the underlying raft group. + if node != nil { + err = mset.processClusteredInboundMsg(m.subj, _EMPTY_, hdr, msg, nil, true) + } else { + err = mset.processJetStreamMsg(m.subj, _EMPTY_, hdr, msg, 0, 0, nil, true) + } + + if err != nil { + s := mset.srv + if strings.Contains(err.Error(), "no space left") { + s.Errorf("JetStream out of space, will be DISABLED") + s.DisableJetStream() + } else { + mset.mu.RLock() + accName, sname, iName := mset.acc.Name, mset.cfg.Name, si.iname + mset.mu.RUnlock() + + // Can happen temporarily all the time during normal operations when the sourcing stream + // is working queue/interest with a limit and discard new. + // TODO - Improve sourcing to WQ with limit and new to use flow control rather than re-creating the consumer. + if errors.Is(err, ErrMaxMsgs) || errors.Is(err, ErrMaxBytes) { + // Do not need to do a full retry that includes finding the last sequence in the stream + // for that source. Just re-create starting with the seq we couldn't store instead. + mset.mu.Lock() + mset.retrySourceConsumerAtSeq(iName, si.sseq) + mset.mu.Unlock() + } else { + // Log some warning for errors other than errLastSeqMismatch or errMaxMsgs. + if !errors.Is(err, errLastSeqMismatch) { + s.RateLimitWarnf("Error processing inbound source %q for '%s' > '%s': %v", + iName, accName, sname, err) + } + // Retry in all type of errors if we are still leader. + if mset.isLeader() { + // This will make sure the source is still in mset.sources map, + // find the last sequence and then call setupSourceConsumer. + iNameMap := map[string]struct{}{iName: {}} + mset.setStartingSequenceForSources(iNameMap) + mset.mu.Lock() + mset.retrySourceConsumerAtSeq(iName, si.sseq+1) + mset.mu.Unlock() + } + } + } + return false + } + + return true +} + +// Generate a new (2.10) style source header (stream name, sequence number, source filter, source destination transform). +func (si *sourceInfo) genSourceHeader(reply string) string { + var b strings.Builder + iNameParts := strings.Split(si.iname, " ") + + b.WriteString(iNameParts[0]) + b.WriteByte(' ') + // Grab sequence as text here from reply subject. + var tsa [expectedNumReplyTokens]string + start, tokens := 0, tsa[:0] + for i := 0; i < len(reply); i++ { + if reply[i] == btsep { + tokens, start = append(tokens, reply[start:i]), i+1 + } + } + tokens = append(tokens, reply[start:]) + seq := "1" // Default + if len(tokens) == expectedNumReplyTokens && tokens[0] == "$JS" && tokens[1] == "ACK" { + seq = tokens[5] + } + b.WriteString(seq) + + b.WriteByte(' ') + b.WriteString(iNameParts[1]) + b.WriteByte(' ') + b.WriteString(iNameParts[2]) + return b.String() +} + +// Original version of header that stored ack reply direct. +func streamAndSeqFromAckReply(reply string) (string, string, uint64) { + tsa := [expectedNumReplyTokens]string{} + start, tokens := 0, tsa[:0] + for i := 0; i < len(reply); i++ { + if reply[i] == btsep { + tokens, start = append(tokens, reply[start:i]), i+1 + } + } + tokens = append(tokens, reply[start:]) + if len(tokens) != expectedNumReplyTokens || tokens[0] != "$JS" || tokens[1] != "ACK" { + return _EMPTY_, _EMPTY_, 0 + } + return tokens[2], _EMPTY_, uint64(parseAckReplyNum(tokens[5])) +} + +// Extract the stream name, the source index name and the message sequence number from the source header. +// Uses the filter and transform arguments to provide backwards compatibility +func streamAndSeq(shdr string) (string, string, uint64) { + if strings.HasPrefix(shdr, jsAckPre) { + return streamAndSeqFromAckReply(shdr) + } + // New version which is stream index name sequence + fields := strings.Split(shdr, " ") + nFields := len(fields) + + if nFields != 2 && nFields <= 3 { + return _EMPTY_, _EMPTY_, 0 + } + + if nFields >= 4 { + return fields[0], strings.Join([]string{fields[0], fields[2], fields[3]}, " "), uint64(parseAckReplyNum(fields[1])) + } else { + return fields[0], _EMPTY_, uint64(parseAckReplyNum(fields[1])) + } + +} + +// Lock should be held. +func (mset *stream) setStartingSequenceForSources(iNames map[string]struct{}) { + var state StreamState + mset.store.FastState(&state) + + // Do not reset sseq here so we can remember when purge/expiration happens. + if state.Msgs == 0 { + for iName := range iNames { + si := mset.sources[iName] + if si == nil { + continue + } else { + si.dseq = 0 + } + } + return + } + + // From the provided list of sources, we build a sublist that contains + // the interested filters (including transforms). As we figure out the + // starting sequence for each source, we will eliminate the source from + // the map and then refresh the sublist, which in turn makes the sublist + // ideally more specific. This allows LoadPrevMsgsMulti to work most + // effectively. + // Because this is a SimpleSublist we can't just remove the entries per + // source so we have no other option but to rebuild it from scratch, but + // this is cheap enough to do so not the end of the world. + var sl *gsl.SimpleSublist + refreshSublist := func() { + sl = gsl.NewSimpleSublist() + for iName := range iNames { + si := mset.sources[iName] + if si == nil { + continue + } + if si.sf == _EMPTY_ { + sl.Insert(fwcs, struct{}{}) + } else { + sl.Insert(si.sf, struct{}{}) + } + for _, sf := range si.sfs { + if sf == _EMPTY_ { + sl.Insert(fwcs, struct{}{}) + } else { + sl.Insert(sf, struct{}{}) + } + } + } + } + refreshSublist() + + var smv StoreMsg + for last := state.LastSeq; ; { + sm, seq, err := mset.store.LoadPrevMsgMulti(sl, last, &smv) + if err == ErrStoreEOF || err != nil { + break + } + last = seq - 1 + if len(sm.hdr) == 0 { + continue + } + ss := sliceHeader(JSStreamSource, sm.hdr) + if len(ss) == 0 { + continue + } + + streamName, indexName, sseq := streamAndSeq(bytesToString(ss)) + if _, ok := iNames[indexName]; ok { + si := mset.sources[indexName] + si.sseq = sseq + si.dseq = 0 + delete(iNames, indexName) + refreshSublist() + } else if indexName == _EMPTY_ && streamName != _EMPTY_ { + for iName := range iNames { + // TODO streamSource is a linear walk, to optimize later + if si := mset.sources[iName]; si != nil && streamName == si.name || + (mset.streamSource(iName).External != nil && streamName == si.name+":"+getHash(mset.streamSource(iName).External.ApiPrefix)) { + si.sseq = sseq + si.dseq = 0 + delete(iNames, iName) + refreshSublist() + break + } + } + } + if len(iNames) == 0 { + break + } + } +} + +// Resets the SourceInfo for all the sources +// lock should be held. +func (mset *stream) resetSourceInfo() { + // Reset if needed. + mset.stopSourceConsumers() + mset.sources = make(map[string]*sourceInfo) + + for _, ssi := range mset.cfg.Sources { + if ssi.iname == _EMPTY_ { + ssi.setIndexName() + } + + var si *sourceInfo + + if len(ssi.SubjectTransforms) == 0 { + si = &sourceInfo{name: ssi.Name, iname: ssi.iname, sf: ssi.FilterSubject} + } else { + sfs := make([]string, len(ssi.SubjectTransforms)) + trs := make([]*subjectTransform, len(ssi.SubjectTransforms)) + for i, str := range ssi.SubjectTransforms { + tr, err := NewSubjectTransform(str.Source, str.Destination) + if err != nil { + mset.srv.Errorf("Unable to get subject transform for source: %v", err) + } + sfs[i] = str.Source + trs[i] = tr + } + si = &sourceInfo{name: ssi.Name, iname: ssi.iname, sfs: sfs, trs: trs} + } + mset.sources[ssi.iname] = si + } +} + +// This will do a reverse scan on startup or leader election +// searching for the starting sequence number. +// This can be slow in degenerative cases. +// Lock should be held. +func (mset *stream) startingSequenceForSources() { + if len(mset.cfg.Sources) == 0 { + return + } + + // Always reset here. + mset.resetSourceInfo() + + var state StreamState + mset.store.FastState(&state) + + // Bail if no messages, meaning no context. + if state.Msgs == 0 { + return + } + + // For short circuiting return. + expected := len(mset.cfg.Sources) + seqs := make(map[string]uint64) + + // Stamp our si seq records on the way out. + defer func() { + for sname, seq := range seqs { + // Ignore if not set. + if seq == 0 { + continue + } + if si := mset.sources[sname]; si != nil { + si.sseq = seq + si.dseq = 0 + } + } + }() + + // Generate a list of sources and, from that, a sublist that contains + // the interested filters (including transforms). As we figure out the + // starting sequence for each source, we will eliminate the source from + // the map and then refresh the sublist, which in turn makes the sublist + // ideally more specific. This allows LoadPrevMsgsMulti to work most + // effectively. + // Because this is a SimpleSublist we can't just remove the entries per + // source so we have no other option but to rebuild it from scratch, but + // this is cheap enough to do so not the end of the world. + sources := map[string]*StreamSource{} + for _, src := range mset.cfg.Sources { + sources[src.composeIName()] = src + } + var sl *gsl.SimpleSublist + refreshSublist := func() { + sl = gsl.NewSimpleSublist() + for _, src := range sources { + if src.FilterSubject == _EMPTY_ { + sl.Insert(fwcs, struct{}{}) + } else { + sl.Insert(src.FilterSubject, struct{}{}) + } + for _, tr := range src.SubjectTransforms { + if tr.Destination == _EMPTY_ { + sl.Insert(fwcs, struct{}{}) + } else { + sl.Insert(tr.Destination, struct{}{}) + } + } + } + } + refreshSublist() + + update := func(iName string, seq uint64) { + // Only update active in case we have older ones in here that got configured out. + if si := mset.sources[iName]; si != nil { + if _, ok := seqs[iName]; !ok { + seqs[iName] = seq + delete(sources, iName) + refreshSublist() + } + } + } + + var smv StoreMsg + for last := state.LastSeq; ; { + sm, seq, err := mset.store.LoadPrevMsgMulti(sl, last, &smv) + if err == ErrStoreEOF || err != nil { + break + } + last = seq - 1 + if len(sm.hdr) == 0 { + continue + } + ss := sliceHeader(JSStreamSource, sm.hdr) + if len(ss) == 0 { + continue + } + + streamName, iName, sseq := streamAndSeq(bytesToString(ss)) + if iName == _EMPTY_ { // Pre-2.10 message header means it's a match for any source using that stream name + for _, ssi := range mset.cfg.Sources { + if streamName == ssi.Name || (ssi.External != nil && streamName == ssi.Name+":"+getHash(ssi.External.ApiPrefix)) { + update(ssi.iname, sseq) + } + } + } else { + update(iName, sseq) + } + if len(seqs) == expected { + return + } + } +} + +// Setup our source consumers. +// Lock should be held. +func (mset *stream) setupSourceConsumers() error { + if mset.outq == nil { + return errors.New("outq required") + } + // Reset if needed. + for _, si := range mset.sources { + if si.sub != nil { + mset.cancelSourceConsumer(si.iname) + } + } + + // If we are no longer the leader, give up + if !mset.isLeader() { + return nil + } + + mset.startingSequenceForSources() + + // Setup our consumers at the proper starting position. + for _, ssi := range mset.cfg.Sources { + if si := mset.sources[ssi.iname]; si != nil { + mset.setupSourceConsumer(ssi.iname, si.sseq+1, time.Time{}) + } + } + + return nil +} + +// Will create internal subscriptions for the stream. +// Lock should be held. +func (mset *stream) subscribeToStream() error { + if mset.active { + return nil + } + for _, subject := range mset.cfg.Subjects { + if _, err := mset.subscribeInternal(subject, mset.processInboundJetStreamMsg); err != nil { + return err + } + } + // Check if we need to setup mirroring. + if mset.cfg.Mirror != nil { + // setup the initial mirror sourceInfo + mset.mirror = &sourceInfo{name: mset.cfg.Mirror.Name} + sfs := make([]string, len(mset.cfg.Mirror.SubjectTransforms)) + trs := make([]*subjectTransform, len(mset.cfg.Mirror.SubjectTransforms)) + + for i, tr := range mset.cfg.Mirror.SubjectTransforms { + // will not fail as already checked before that the transform will work + subjectTransform, err := NewSubjectTransform(tr.Source, tr.Destination) + if err != nil { + mset.srv.Errorf("Unable to get transform for mirror consumer: %v", err) + } + + sfs[i] = tr.Source + trs[i] = subjectTransform + } + mset.mirror.sfs = sfs + mset.mirror.trs = trs + // delay the actual mirror consumer creation for after a delay + mset.scheduleSetupMirrorConsumerRetry() + } else if len(mset.cfg.Sources) > 0 && mset.sourcesConsumerSetup == nil { + // Setup the initial source infos for the sources + mset.resetSourceInfo() + // Delay the actual source consumer(s) creation(s) for after a delay if a replicated stream. + // If it's an R1, this is done at startup and we will do inline. + if mset.cfg.Replicas == 1 { + mset.setupSourceConsumers() + } else { + mset.sourcesConsumerSetup = time.AfterFunc(time.Duration(rand.Intn(int(500*time.Millisecond)))+100*time.Millisecond, func() { + mset.mu.Lock() + mset.setupSourceConsumers() + mset.mu.Unlock() + }) + } + } + // Check for direct get access. + // We spin up followers for clustered streams in monitorStream(). + if mset.cfg.AllowDirect { + if err := mset.subscribeToDirect(); err != nil { + return err + } + } + + mset.active = true + return nil +} + +// Lock should be held. +func (mset *stream) subscribeToDirect() error { + // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis. + if mset.directSub == nil { + dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.cfg.Name) + if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err == nil { + mset.directSub = sub + } else { + return err + } + } + // Now the one that will have subject appended past stream name. + if mset.lastBySub == nil { + dsubj := fmt.Sprintf(JSDirectGetLastBySubjectT, mset.cfg.Name, fwcs) + // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis. + if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetLastBySubjectRequest); err == nil { + mset.lastBySub = sub + } else { + return err + } + } + + return nil +} + +// Lock should be held. +func (mset *stream) unsubscribeToDirect() { + if mset.directSub != nil { + mset.unsubscribe(mset.directSub) + mset.directSub = nil + } + if mset.lastBySub != nil { + mset.unsubscribe(mset.lastBySub) + mset.lastBySub = nil + } +} + +// Lock should be held. +func (mset *stream) subscribeToMirrorDirect() error { + if mset.mirror == nil { + return nil + } + + // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis. + if mset.mirror.dsub == nil { + dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.mirror.name) + // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis. + if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err == nil { + mset.mirror.dsub = sub + } else { + return err + } + } + // Now the one that will have subject appended past stream name. + if mset.mirror.lbsub == nil { + dsubj := fmt.Sprintf(JSDirectGetLastBySubjectT, mset.mirror.name, fwcs) + // We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis. + if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetLastBySubjectRequest); err == nil { + mset.mirror.lbsub = sub + } else { + return err + } + } + + return nil +} + +// Stop our source consumers. +// Lock should be held. +func (mset *stream) stopSourceConsumers() { + for _, si := range mset.sources { + mset.cancelSourceInfo(si) + } +} + +// Lock should be held. +func (mset *stream) removeInternalConsumer(si *sourceInfo) { + if si == nil || si.cname == _EMPTY_ { + return + } + si.cname = _EMPTY_ +} + +// Will unsubscribe from the stream. +// Lock should be held. +func (mset *stream) unsubscribeToStream(stopping bool) error { + for _, subject := range mset.cfg.Subjects { + mset.unsubscribeInternal(subject) + } + if mset.mirror != nil { + mset.cancelSourceInfo(mset.mirror) + mset.mirror = nil + } + + if len(mset.sources) > 0 { + mset.stopSourceConsumers() + } + + // In case we had a direct get subscriptions. + if stopping { + mset.unsubscribeToDirect() + } + + mset.active = false + return nil +} + +// Lock does NOT need to be held, we set the client on setup and never change it at this point. +func (mset *stream) subscribeInternal(subject string, cb msgHandler) (*subscription, error) { + if mset.closed.Load() { + return nil, errStreamClosed + } + if cb == nil { + return nil, errInvalidMsgHandler + } + c := mset.client + sid := int(mset.sid.Add(1)) + // Now create the subscription + return c.processSub([]byte(subject), nil, []byte(strconv.Itoa(sid)), cb, false) +} + +// Lock does NOT need to be held, we set the client on setup and never change it at this point. +func (mset *stream) queueSubscribeInternal(subject, group string, cb msgHandler) (*subscription, error) { + if mset.closed.Load() { + return nil, errStreamClosed + } + if cb == nil { + return nil, errInvalidMsgHandler + } + c := mset.client + sid := int(mset.sid.Add(1)) + // Now create the subscription + return c.processSub([]byte(subject), []byte(group), []byte(strconv.Itoa(sid)), cb, false) +} + +// This will unsubscribe us from the exact subject given. +// We do not currently track the subs so do not have the sid. +// This should be called only on an update. +// Lock does NOT need to be held, we set the client on setup and never change it at this point. +func (mset *stream) unsubscribeInternal(subject string) error { + if mset.closed.Load() { + return errStreamClosed + } + c := mset.client + var sid []byte + c.mu.Lock() + for _, sub := range c.subs { + if subject == string(sub.subject) { + sid = sub.sid + break + } + } + c.mu.Unlock() + + if sid != nil { + return c.processUnsub(sid) + } + return nil +} + +// Lock should be held. +func (mset *stream) unsubscribe(sub *subscription) { + if sub == nil || mset.closed.Load() { + return + } + mset.client.processUnsub(sub.sid) +} + +func (mset *stream) setupStore(fsCfg *FileStoreConfig) error { + mset.mu.Lock() + mset.created = time.Now().UTC() + + switch mset.cfg.Storage { + case MemoryStorage: + ms, err := newMemStore(&mset.cfg) + if err != nil { + mset.mu.Unlock() + return err + } + mset.store = ms + case FileStorage: + s := mset.srv + prf := s.jsKeyGen(s.getOpts().JetStreamKey, mset.acc.Name) + if prf != nil { + // We are encrypted here, fill in correct cipher selection. + fsCfg.Cipher = s.getOpts().JetStreamCipher + } + oldprf := s.jsKeyGen(s.getOpts().JetStreamOldKey, mset.acc.Name) + cfg := *fsCfg + cfg.srv = s + fs, err := newFileStoreWithCreated(cfg, mset.cfg, mset.created, prf, oldprf) + if err != nil { + mset.mu.Unlock() + return err + } + mset.store = fs + } + // This will fire the callback but we do not require the lock since md will be 0 here. + mset.store.RegisterStorageUpdates(mset.storeUpdates) + mset.store.RegisterStorageRemoveMsg(func(seq uint64) { + if mset.IsClustered() { + if mset.IsLeader() { + mset.mu.RLock() + md := streamMsgDelete{Seq: seq, NoErase: true, Stream: mset.cfg.Name} + mset.node.Propose(encodeMsgDelete(&md)) + mset.mu.RUnlock() + } + } else { + mset.removeMsg(seq) + } + }) + mset.store.RegisterSubjectDeleteMarkerUpdates(func(im *inMsg) { + if mset.IsClustered() { + if mset.IsLeader() { + mset.processClusteredInboundMsg(im.subj, im.rply, im.hdr, im.msg, im.mt, false) + } + } else { + mset.processJetStreamMsg(im.subj, im.rply, im.hdr, im.msg, 0, 0, im.mt, false) + } + }) + mset.mu.Unlock() + + return nil +} + +// Called for any updates to the underlying stream. We pass through the bytes to the +// jetstream account. We do local processing for stream pending for consumers, but only +// for removals. +// Lock should not be held. +func (mset *stream) storeUpdates(md, bd int64, seq uint64, subj string) { + // If we have a single negative update then we will process our consumers for stream pending. + // Purge and Store handled separately inside individual calls. + if md == -1 && seq > 0 && subj != _EMPTY_ { + // We use our consumer list mutex here instead of the main stream lock since it may be held already. + mset.clsMu.RLock() + if mset.csl != nil { + mset.csl.Match(subj, func(o *consumer) { + o.decStreamPending(seq, subj) + }) + } else { + for _, o := range mset.cList { + o.decStreamPending(seq, subj) + } + } + mset.clsMu.RUnlock() + } else if md < 0 { + // Batch decrements we need to force consumers to re-calculate num pending. + mset.clsMu.RLock() + for _, o := range mset.cList { + o.streamNumPendingLocked() + } + mset.clsMu.RUnlock() + } + + if mset.jsa != nil { + mset.jsa.updateUsage(mset.tier, mset.stype, bd) + } +} + +// NumMsgIds returns the number of message ids being tracked for duplicate suppression. +func (mset *stream) numMsgIds() int { + mset.mu.Lock() + defer mset.mu.Unlock() + if !mset.ddloaded { + mset.rebuildDedupe() + } + return len(mset.ddmap) +} + +// checkMsgId will process and check for duplicates. +// Lock should be held. +func (mset *stream) checkMsgId(id string) *ddentry { + if !mset.ddloaded { + mset.rebuildDedupe() + } + if id == _EMPTY_ || len(mset.ddmap) == 0 { + return nil + } + return mset.ddmap[id] +} + +// Will purge the entries that are past the window. +// Should be called from a timer. +func (mset *stream) purgeMsgIds() { + mset.mu.Lock() + defer mset.mu.Unlock() + + now := time.Now().UnixNano() + tmrNext := mset.cfg.Duplicates + window := int64(tmrNext) + + for i, dde := range mset.ddarr[mset.ddindex:] { + if now-dde.ts >= window { + delete(mset.ddmap, dde.id) + } else { + mset.ddindex += i + // Check if we should garbage collect here if we are 1/3 total size. + if cap(mset.ddarr) > 3*(len(mset.ddarr)-mset.ddindex) { + mset.ddarr = append([]*ddentry(nil), mset.ddarr[mset.ddindex:]...) + mset.ddindex = 0 + } + tmrNext = time.Duration(window - (now - dde.ts)) + break + } + } + if len(mset.ddmap) > 0 { + // Make sure to not fire too quick + const minFire = 50 * time.Millisecond + if tmrNext < minFire { + tmrNext = minFire + } + if mset.ddtmr != nil { + mset.ddtmr.Reset(tmrNext) + } else { + mset.ddtmr = time.AfterFunc(tmrNext, mset.purgeMsgIds) + } + } else { + if mset.ddtmr != nil { + mset.ddtmr.Stop() + mset.ddtmr = nil + } + mset.ddmap = nil + mset.ddarr = nil + mset.ddindex = 0 + } +} + +// storeMsgIdLocked will store the message id for duplicate detection. +// Lock should be held. +func (mset *stream) storeMsgIdLocked(dde *ddentry) { + if mset.ddmap == nil { + mset.ddmap = make(map[string]*ddentry) + } + mset.ddmap[dde.id] = dde + mset.ddarr = append(mset.ddarr, dde) + if mset.ddtmr == nil { + mset.ddtmr = time.AfterFunc(mset.cfg.Duplicates, mset.purgeMsgIds) + } +} + +// Fast lookup of msgId. +func getMsgId(hdr []byte) string { + return string(getHeader(JSMsgId, hdr)) +} + +// Fast lookup of expected last msgId. +func getExpectedLastMsgId(hdr []byte) string { + return string(getHeader(JSExpectedLastMsgId, hdr)) +} + +// Fast lookup of expected stream. +func getExpectedStream(hdr []byte) string { + return string(getHeader(JSExpectedStream, hdr)) +} + +// Fast lookup of expected stream. +func getExpectedLastSeq(hdr []byte) (uint64, bool) { + bseq := getHeader(JSExpectedLastSeq, hdr) + if len(bseq) == 0 { + return 0, false + } + return uint64(parseInt64(bseq)), true +} + +// Fast lookup of rollups. +func getRollup(hdr []byte) string { + r := getHeader(JSMsgRollup, hdr) + if len(r) == 0 { + return _EMPTY_ + } + return strings.ToLower(string(r)) +} + +// Fast lookup of expected stream sequence per subject. +func getExpectedLastSeqPerSubject(hdr []byte) (uint64, bool) { + bseq := getHeader(JSExpectedLastSubjSeq, hdr) + if len(bseq) == 0 { + return 0, false + } + return uint64(parseInt64(bseq)), true +} + +// Fast lookup of expected subject for the expected stream sequence per subject. +func getExpectedLastSeqPerSubjectForSubject(hdr []byte) string { + return string(getHeader(JSExpectedLastSubjSeqSubj, hdr)) +} + +// Fast lookup of the message TTL from headers: +// - Positive return value: duration in seconds. +// - Zero return value: no TTL or parse error. +// - Negative return value: never expires. +func getMessageTTL(hdr []byte) (int64, error) { + ttl := getHeader(JSMessageTTL, hdr) + if len(ttl) == 0 { + return 0, nil + } + return parseMessageTTL(bytesToString(ttl)) +} + +// - Positive return value: duration in seconds. +// - Zero return value: no TTL or parse error. +// - Negative return value: never expires. +func parseMessageTTL(ttl string) (int64, error) { + if strings.ToLower(ttl) == "never" { + return -1, nil + } + dur, err := time.ParseDuration(ttl) + if err == nil { + if dur < time.Second { + return 0, NewJSMessageTTLInvalidError() + } + return int64(dur.Seconds()), nil + } + t := parseInt64(stringToBytes(ttl)) + if t < 0 { + // This probably means a parse failure, hence why + // we have a special case "never" for returning -1. + // Otherwise we can't know if it's a genuine TTL + // that says never expire or if it's a parse error. + return 0, NewJSMessageTTLInvalidError() + } + return t, nil +} + +// Signal if we are clustered. Will acquire rlock. +func (mset *stream) IsClustered() bool { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.isClustered() +} + +// Lock should be held. +func (mset *stream) isClustered() bool { + return mset.node != nil +} + +// Used if we have to queue things internally to avoid the route/gw path. +type inMsg struct { + subj string + rply string + hdr []byte + msg []byte + si *sourceInfo + mt *msgTrace +} + +var inMsgPool = sync.Pool{ + New: func() any { + return &inMsg{} + }, +} + +func (im *inMsg) returnToPool() { + im.subj, im.rply, im.hdr, im.msg, im.si, im.mt = _EMPTY_, _EMPTY_, nil, nil, nil, nil + inMsgPool.Put(im) +} + +func (mset *stream) queueInbound(ib *ipQueue[*inMsg], subj, rply string, hdr, msg []byte, si *sourceInfo, mt *msgTrace) { + im := inMsgPool.Get().(*inMsg) + im.subj, im.rply, im.hdr, im.msg, im.si, im.mt = subj, rply, hdr, msg, si, mt + if _, err := ib.push(im); err != nil { + im.returnToPool() + streamName := mset.cfg.Name + mset.srv.RateLimitWarnf("Dropping messages due to excessive stream ingest rate on '%s' > '%s': %s", mset.acc.Name, streamName, err) + if rply != _EMPTY_ { + hdr := []byte("NATS/1.0 429 Too Many Requests\r\n\r\n") + b, _ := json.Marshal(&JSPubAckResponse{PubAck: &PubAck{Stream: streamName}, Error: NewJSStreamTooManyRequestsError()}) + mset.outq.send(newJSPubMsg(rply, _EMPTY_, _EMPTY_, hdr, b, nil, 0)) + } + } +} + +var dgPool = sync.Pool{ + New: func() any { + return &directGetReq{} + }, +} + +// For when we need to not inline the request. +type directGetReq struct { + // Copy of this is correct for this. + req JSApiMsgGetRequest + reply string +} + +// processDirectGetRequest handles direct get request for stream messages. +func (mset *stream) processDirectGetRequest(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if len(reply) == 0 { + return + } + _, msg := c.msgParts(rmsg) + if len(msg) == 0 { + hdr := []byte("NATS/1.0 408 Empty Request\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + var req JSApiMsgGetRequest + err := json.Unmarshal(msg, &req) + if err != nil { + hdr := []byte("NATS/1.0 408 Malformed Request\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + // Check if nothing set. + if req.Seq == 0 && req.LastFor == _EMPTY_ && req.NextFor == _EMPTY_ && len(req.MultiLastFor) == 0 && req.StartTime == nil { + hdr := []byte("NATS/1.0 408 Empty Request\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + // Check we don't have conflicting options set. + // We do not allow batch mode for lastFor requests. + if (req.Seq > 0 && req.LastFor != _EMPTY_) || + (req.Seq > 0 && req.StartTime != nil) || + (req.StartTime != nil && req.LastFor != _EMPTY_) || + (req.LastFor != _EMPTY_ && req.NextFor != _EMPTY_) || + (req.LastFor != _EMPTY_ && req.Batch > 0) || + (req.LastFor != _EMPTY_ && len(req.MultiLastFor) > 0) || + (req.NextFor != _EMPTY_ && len(req.MultiLastFor) > 0) || + (req.UpToSeq > 0 && req.UpToTime != nil) { + hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + + inlineOk := c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF + if !inlineOk { + dg := dgPool.Get().(*directGetReq) + dg.req, dg.reply = req, reply + mset.gets.push(dg) + } else { + mset.getDirectRequest(&req, reply) + } +} + +// This is for direct get by last subject which is part of the subject itself. +func (mset *stream) processDirectGetLastBySubjectRequest(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + if len(reply) == 0 { + return + } + _, msg := c.msgParts(rmsg) + // This version expects no payload. + if len(msg) != 0 { + hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + // Extract the key. + var key string + for i, n := 0, 0; i < len(subject); i++ { + if subject[i] == btsep { + if n == 4 { + if start := i + 1; start < len(subject) { + key = subject[i+1:] + } + break + } + n++ + } + } + if len(key) == 0 { + hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + + req := JSApiMsgGetRequest{LastFor: key} + + inlineOk := c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF + if !inlineOk { + dg := dgPool.Get().(*directGetReq) + dg.req, dg.reply = req, reply + mset.gets.push(dg) + } else { + mset.getDirectRequest(&req, reply) + } +} + +// For direct get batch and multi requests. +const ( + dg = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\n\r\n" + dgb = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\nNats-Num-Pending: %d\r\nNats-Last-Sequence: %d\r\n\r\n" + eob = "NATS/1.0 204 EOB\r\nNats-Num-Pending: %d\r\nNats-Last-Sequence: %d\r\n\r\n" + eobm = "NATS/1.0 204 EOB\r\nNats-Num-Pending: %d\r\nNats-Last-Sequence: %d\r\nNats-UpTo-Sequence: %d\r\n\r\n" +) + +// Handle a multi request. +func (mset *stream) getDirectMulti(req *JSApiMsgGetRequest, reply string) { + // TODO(dlc) - Make configurable? + const maxAllowedResponses = 1024 + + // We hold the lock here to try to avoid changes out from underneath of us. + mset.mu.RLock() + defer mset.mu.RUnlock() + // Grab store and name. + store, name, s := mset.store, mset.cfg.Name, mset.srv + + // Grab MaxBytes + mb := req.MaxBytes + if mb == 0 && s != nil { + // Fill in with the server's MaxPending. + mb = int(s.opts.MaxPending) + } + + upToSeq := req.UpToSeq + // If we have UpToTime set get the proper sequence. + if req.UpToTime != nil { + upToSeq = store.GetSeqFromTime((*req.UpToTime).UTC()) + // Avoid selecting a first sequence that will take us to before the stream first + // sequence, otherwise we can return messages after the supplied UpToTime. + if upToSeq <= mset.state().FirstSeq { + hdr := []byte("NATS/1.0 404 No Results\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + // We need to back off one since this is used to determine start sequence normally, + // whereas here we want it to be the ceiling. + upToSeq-- + } + // If not set, set to the last sequence and remember that for EOB. + if upToSeq == 0 { + var state StreamState + mset.store.FastState(&state) + upToSeq = state.LastSeq + } + + seqs, err := store.MultiLastSeqs(req.MultiLastFor, upToSeq, maxAllowedResponses) + if err != nil { + var hdr []byte + if err == ErrTooManyResults { + hdr = []byte("NATS/1.0 413 Too Many Results\r\n\r\n") + } else { + hdr = []byte(fmt.Sprintf("NATS/1.0 500 %v\r\n\r\n", err)) + } + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + if len(seqs) == 0 { + hdr := []byte("NATS/1.0 404 No Results\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + + np, lseq, sentBytes, sent := uint64(len(seqs)-1), uint64(0), 0, 0 + for _, seq := range seqs { + if seq < req.Seq { + if np > 0 { + np-- + } + continue + } + var svp StoreMsg + sm, err := store.LoadMsg(seq, &svp) + if err != nil { + hdr := []byte("NATS/1.0 404 Message Not Found\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + + hdr := sm.hdr + ts := time.Unix(0, sm.ts).UTC() + + if len(hdr) == 0 { + hdr = fmt.Appendf(nil, dgb, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano), np, lseq) + } else { + hdr = copyBytes(hdr) + hdr = genHeader(hdr, JSStream, name) + hdr = genHeader(hdr, JSSubject, sm.subj) + hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10)) + hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano)) + hdr = genHeader(hdr, JSNumPending, strconv.FormatUint(np, 10)) + hdr = genHeader(hdr, JSLastSequence, strconv.FormatUint(lseq, 10)) + } + // Decrement num pending. This is optimization and we do not continue to look it up for these operations. + if np > 0 { + np-- + } + // Track our lseq + lseq = sm.seq + // Send out our message. + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, sm.msg, nil, 0)) + // Check if we have exceeded max bytes. + sentBytes += len(sm.subj) + len(sm.hdr) + len(sm.msg) + if sentBytes >= mb { + break + } + sent++ + if req.Batch > 0 && sent >= req.Batch { + break + } + } + + // Send out EOB + hdr := fmt.Appendf(nil, eobm, np, lseq, upToSeq) + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) +} + +// Do actual work on a direct msg request. +// This could be called in a Go routine if we are inline for a non-client connection. +func (mset *stream) getDirectRequest(req *JSApiMsgGetRequest, reply string) { + // Handle multi in separate function. + if len(req.MultiLastFor) > 0 { + mset.getDirectMulti(req, reply) + return + } + + mset.mu.RLock() + store, name, s := mset.store, mset.cfg.Name, mset.srv + mset.mu.RUnlock() + + var seq uint64 + // Lookup start seq if AsOfTime is set. + if req.StartTime != nil { + seq = store.GetSeqFromTime(*req.StartTime) + } else { + seq = req.Seq + } + + wc := subjectHasWildcard(req.NextFor) + // For tracking num pending if we are batch. + var np, lseq, validThrough uint64 + var isBatchRequest bool + batch := req.Batch + if batch == 0 { + batch = 1 + } else { + // This is a batch request, capture initial numPending. + isBatchRequest = true + np, validThrough = store.NumPending(seq, req.NextFor, false) + } + + // Grab MaxBytes + mb := req.MaxBytes + if mb == 0 && s != nil { + // Fill in with the server's MaxPending. + mb = int(s.opts.MaxPending) + } + // Track what we have sent. + var sentBytes int + + // Loop over batch, which defaults to 1. + for i := 0; i < batch; i++ { + var ( + svp StoreMsg + sm *StoreMsg + err error + ) + if seq > 0 && req.NextFor == _EMPTY_ { + // Only do direct lookup for a non batch. + if i == 0 && !isBatchRequest { + sm, err = store.LoadMsg(seq, &svp) + } else { + // We want to use load next with fwcs to step over deleted msgs. + sm, seq, err = store.LoadNextMsg(fwcs, true, seq, &svp) + } + // Bump for next loop if applicable. + seq++ + } else if req.NextFor != _EMPTY_ { + sm, seq, err = store.LoadNextMsg(req.NextFor, wc, seq, &svp) + seq++ + } else { + // Batch is not applicable here, this is checked before we get here. + sm, err = store.LoadLastMsg(req.LastFor, &svp) + } + if err != nil { + // For batches, if we stop early we want to do EOB logic below. + if batch > 1 && i > 0 { + break + } + hdr := []byte("NATS/1.0 404 Message Not Found\r\n\r\n") + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + return + } + + hdr := sm.hdr + ts := time.Unix(0, sm.ts).UTC() + + if isBatchRequest { + if len(hdr) == 0 { + hdr = fmt.Appendf(nil, dgb, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano), np, lseq) + } else { + hdr = copyBytes(hdr) + hdr = genHeader(hdr, JSStream, name) + hdr = genHeader(hdr, JSSubject, sm.subj) + hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10)) + hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano)) + hdr = genHeader(hdr, JSNumPending, strconv.FormatUint(np, 10)) + hdr = genHeader(hdr, JSLastSequence, strconv.FormatUint(lseq, 10)) + } + // Decrement num pending. This is optimization and we do not continue to look it up for these operations. + np-- + } else { + if len(hdr) == 0 { + hdr = fmt.Appendf(nil, dg, name, sm.subj, sm.seq, ts.Format(time.RFC3339Nano)) + } else { + hdr = copyBytes(hdr) + hdr = genHeader(hdr, JSStream, name) + hdr = genHeader(hdr, JSSubject, sm.subj) + hdr = genHeader(hdr, JSSequence, strconv.FormatUint(sm.seq, 10)) + hdr = genHeader(hdr, JSTimeStamp, ts.Format(time.RFC3339Nano)) + } + } + // Track our lseq + lseq = sm.seq + // Send out our message. + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, sm.msg, nil, 0)) + // Check if we have exceeded max bytes. + sentBytes += len(sm.subj) + len(sm.hdr) + len(sm.msg) + if sentBytes >= mb { + break + } + } + + // If batch was requested send EOB. + if isBatchRequest { + // Update if the stream's lasts sequence has moved past our validThrough. + if mset.lastSeq() > validThrough { + np, _ = store.NumPending(seq, req.NextFor, false) + } + hdr := fmt.Appendf(nil, eob, np, lseq) + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0)) + } +} + +// processInboundJetStreamMsg handles processing messages bound for a stream. +func (mset *stream) processInboundJetStreamMsg(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + hdr, msg := c.msgParts(copyBytes(rmsg)) // Need to copy. + if mt, traceOnly := c.isMsgTraceEnabled(); mt != nil { + // If message is delivered, we need to disable the message trace headers + // to prevent a trace event to be generated when a stored message + // is delivered to a consumer and routed. + if !traceOnly { + disableTraceHeaders(c, hdr) + } + // This will add the jetstream event while in the client read loop. + // Since the event will be updated in a different go routine, the + // tracing object will have a separate reference to the JS trace + // object. + mt.addJetStreamEvent(mset.name()) + } + mset.queueInbound(mset.msgs, subject, reply, hdr, msg, nil, c.pa.trace) +} + +var ( + errLastSeqMismatch = errors.New("last sequence mismatch") + errMsgIdDuplicate = errors.New("msgid is duplicate") + errStreamClosed = errors.New("stream closed") + errInvalidMsgHandler = errors.New("undefined message handler") + errStreamMismatch = errors.New("expected stream does not match") + errMsgTTLDisabled = errors.New("message TTL disabled") +) + +// processJetStreamMsg is where we try to actually process the stream msg. +func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte, lseq uint64, ts int64, mt *msgTrace, sourced bool) (retErr error) { + if mt != nil { + // Only the leader/standalone will have mt!=nil. On exit, send the + // message trace event. + defer func() { + mt.sendEventFromJetStream(retErr) + }() + } + + if mset.closed.Load() { + return errStreamClosed + } + + mset.mu.Lock() + s, store := mset.srv, mset.store + + traceOnly := mt.traceOnly() + bumpCLFS := func() { + // Do not bump if tracing and not doing message delivery. + if traceOnly { + return + } + mset.clMu.Lock() + mset.clfs++ + mset.clMu.Unlock() + } + + // Apply the input subject transform if any + if mset.itr != nil { + ts, err := mset.itr.Match(subject) + if err == nil { + // no filtering: if the subject doesn't map the source of the transform, don't change it + subject = ts + } + } + + var accName string + if mset.acc != nil { + accName = mset.acc.Name + } + + js, jsa, doAck := mset.js, mset.jsa, !mset.cfg.NoAck + name, stype := mset.cfg.Name, mset.cfg.Storage + maxMsgSize := int(mset.cfg.MaxMsgSize) + numConsumers := len(mset.consumers) + interestRetention := mset.cfg.Retention == InterestPolicy + // Snapshot if we are the leader and if we can respond. + isLeader, isSealed := mset.isLeaderNodeState(), mset.cfg.Sealed + canRespond := doAck && len(reply) > 0 && isLeader + + var resp = &JSPubAckResponse{} + + // Bail here if sealed. + if isSealed { + outq := mset.outq + mset.mu.Unlock() + bumpCLFS() + if canRespond && outq != nil { + resp.PubAck = &PubAck{Stream: name} + resp.Error = ApiErrors[JSStreamSealedErr] + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return ApiErrors[JSStreamSealedErr] + } + + var buf [256]byte + pubAck := append(buf[:0], mset.pubAck...) + + // If this is a non-clustered msg and we are not considered active, meaning no active subscription, do not process. + if lseq == 0 && ts == 0 && !mset.active { + mset.mu.Unlock() + return nil + } + + // For clustering the lower layers will pass our expected lseq. If it is present check for that here. + var clfs uint64 + if lseq > 0 { + clfs = mset.getCLFS() + if lseq != (mset.lseq + clfs) { + isMisMatch := true + // We may be able to recover here if we have no state whatsoever, or we are a mirror. + // See if we have to adjust our starting sequence. + if mset.lseq == 0 || mset.cfg.Mirror != nil { + var state StreamState + mset.store.FastState(&state) + if state.FirstSeq == 0 { + mset.store.Compact(lseq + 1) + mset.lseq = lseq + isMisMatch = false + } + } + // Really is a mismatch. + if isMisMatch { + outq := mset.outq + mset.mu.Unlock() + if canRespond && outq != nil { + resp.PubAck = &PubAck{Stream: name} + resp.Error = ApiErrors[JSStreamSequenceNotMatchErr] + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return errLastSeqMismatch + } + } + } + + // If we have received this message across an account we may have request information attached. + // For now remove. TODO(dlc) - Should this be opt-in or opt-out? + if len(hdr) > 0 { + hdr = removeHeaderIfPresent(hdr, ClientInfoHdr) + } + + // Process additional msg headers if still present. + var msgId string + var rollupSub, rollupAll bool + isClustered := mset.isClustered() + + if len(hdr) > 0 { + outq := mset.outq + + // Certain checks have already been performed if in clustered mode, so only check if not. + // Note, for cluster mode but with message tracing (without message delivery), we need + // to do this check here since it was not done in processClusteredInboundMsg(). + if !isClustered || traceOnly { + // Expected stream. + if sname := getExpectedStream(hdr); sname != _EMPTY_ && sname != name { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamNotMatchError() + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return errStreamMismatch + } + } + + // TTL'd messages are rejected entirely if TTLs are not enabled on the stream. + // Shouldn't happen in clustered mode since we should have already caught this + // in processClusteredInboundMsg, but needed here for non-clustered etc. + if ttl, _ := getMessageTTL(hdr); !sourced && ttl != 0 && !mset.cfg.AllowMsgTTL { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSMessageTTLDisabledError() + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return errMsgTTLDisabled + } + + // Dedupe detection. This is done at the cluster level for dedupe detectiom above the + // lower layers. But we still need to pull out the msgId. + if msgId = getMsgId(hdr); msgId != _EMPTY_ { + // Do real check only if not clustered or traceOnly flag is set. + if !isClustered || traceOnly { + if dde := mset.checkMsgId(msgId); dde != nil { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + response := append(pubAck, strconv.FormatUint(dde.seq, 10)...) + response = append(response, ",\"duplicate\": true}"...) + outq.sendMsg(reply, response) + } + return errMsgIdDuplicate + } + } + } + + // Expected last sequence per subject. + if seq, exists := getExpectedLastSeqPerSubject(hdr); exists { + // Allow override of the subject used for the check. + seqSubj := subject + if optSubj := getExpectedLastSeqPerSubjectForSubject(hdr); optSubj != _EMPTY_ { + seqSubj = optSubj + } + + // TODO(dlc) - We could make a new store func that does this all in one. + var smv StoreMsg + var fseq uint64 + sm, err := store.LoadLastMsg(seqSubj, &smv) + if sm != nil { + fseq = sm.seq + } + if err == ErrStoreMsgNotFound { + if seq == 0 { + fseq, err = 0, nil + } else if mset.isClustered() { + // Do not bump clfs in case message was not found and could have been deleted. + var ss StreamState + store.FastState(&ss) + if seq <= ss.LastSeq { + fseq, err = seq, nil + } + } + } + if err != nil || fseq != seq { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamWrongLastSequenceError(fseq) + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return fmt.Errorf("last sequence by subject mismatch: %d vs %d", seq, fseq) + } + } + + // Expected last sequence. + if seq, exists := getExpectedLastSeq(hdr); exists && seq != mset.lseq { + mlseq := mset.lseq + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamWrongLastSequenceError(mlseq) + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return fmt.Errorf("last sequence mismatch: %d vs %d", seq, mlseq) + } + // Expected last msgId. + if lmsgId := getExpectedLastMsgId(hdr); lmsgId != _EMPTY_ { + if mset.lmsgId == _EMPTY_ && !mset.ddloaded { + mset.rebuildDedupe() + } + if lmsgId != mset.lmsgId { + last := mset.lmsgId + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamWrongLastMsgIDError(last) + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return fmt.Errorf("last msgid mismatch: %q vs %q", lmsgId, last) + } + } + // Check for any rollups. + if rollup := getRollup(hdr); rollup != _EMPTY_ { + if !mset.cfg.AllowRollup || mset.cfg.DenyPurge { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamRollupFailedError(errors.New("rollup not permitted")) + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return errors.New("rollup not permitted") + } + switch rollup { + case JSMsgRollupSubject: + rollupSub = true + case JSMsgRollupAll: + rollupAll = true + default: + mset.mu.Unlock() + bumpCLFS() + err := fmt.Errorf("rollup value invalid: %q", rollup) + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamRollupFailedError(err) + b, _ := json.Marshal(resp) + outq.sendMsg(reply, b) + } + return err + } + } + } + + // Response Ack. + var ( + response []byte + seq uint64 + err error + ) + + // Check to see if we are over the max msg size. + if maxMsgSize >= 0 && (len(hdr)+len(msg)) > maxMsgSize { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamMessageExceedsMaximumError() + response, _ = json.Marshal(resp) + mset.outq.sendMsg(reply, response) + } + return ErrMaxPayload + } + + if len(hdr) > math.MaxUint16 { + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamHeaderExceedsMaximumError() + response, _ = json.Marshal(resp) + mset.outq.sendMsg(reply, response) + } + return ErrMaxPayload + } + + // Check to see if we have exceeded our limits. + if js.limitsExceeded(stype) { + s.resourcesExceededError() + mset.mu.Unlock() + bumpCLFS() + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSInsufficientResourcesError() + response, _ = json.Marshal(resp) + mset.outq.sendMsg(reply, response) + } + // Stepdown regardless. + if node := mset.raftNode(); node != nil { + node.StepDown() + } + return NewJSInsufficientResourcesError() + } + + var noInterest bool + + // If we are interest based retention and have no consumers then we can skip. + if interestRetention { + mset.clsMu.RLock() + noInterest = numConsumers == 0 || mset.csl == nil || !mset.csl.HasInterest(subject) + mset.clsMu.RUnlock() + } + + // Grab timestamp if not already set. + if ts == 0 && lseq > 0 { + ts = time.Now().UnixNano() + } + + mt.updateJetStreamEvent(subject, noInterest) + if traceOnly { + mset.mu.Unlock() + return nil + } + + // Skip msg here. + if noInterest { + mset.lseq, _ = store.SkipMsg(0) + mset.lmsgId = msgId + // If we have a msgId make sure to save. + if msgId != _EMPTY_ { + mset.storeMsgIdLocked(&ddentry{msgId, mset.lseq, ts}) + } + if canRespond { + response = append(pubAck, strconv.FormatUint(mset.lseq, 10)...) + response = append(response, '}') + mset.outq.sendMsg(reply, response) + } + mset.mu.Unlock() + return nil + } + + // Republish state if needed. + var tsubj string + var tlseq uint64 + var thdrsOnly bool + if mset.tr != nil { + tsubj, _ = mset.tr.Match(subject) + if mset.cfg.RePublish != nil { + thdrsOnly = mset.cfg.RePublish.HeadersOnly + } + } + republish := tsubj != _EMPTY_ && isLeader + + // If we are republishing grab last sequence for this exact subject. Aids in gap detection for lightweight clients. + if republish { + var smv StoreMsg + if sm, _ := store.LoadLastMsg(subject, &smv); sm != nil { + tlseq = sm.seq + } + } + + // If clustered this was already checked and we do not want to check here and possibly introduce skew. + if !isClustered { + if exceeded, err := jsa.wouldExceedLimits(stype, mset.tier, mset.cfg.Replicas, subject, hdr, msg); exceeded { + if err == nil { + err = NewJSAccountResourcesExceededError() + } + s.RateLimitWarnf("JetStream resource limits exceeded for account: %q", accName) + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = err + response, _ = json.Marshal(resp) + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + mset.mu.Unlock() + return err + } + } + + // Find the message TTL if any. + ttl, err := getMessageTTL(hdr) + if err != nil { + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSMessageTTLInvalidError() + response, _ = json.Marshal(resp) + mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, response, nil, 0)) + } + mset.mu.Unlock() + return err + } + + // If subject delete markers are used, ensure message TTL is that at minimum. + // Otherwise, subject delete markers could be missed if one already exists for this subject. + // MaxMsgsPer=1 is an exception, because we'll only ever have one message. + if ttl > 0 && mset.cfg.SubjectDeleteMarkerTTL > 0 && mset.cfg.MaxMsgsPer != 1 { + if minTtl := int64(mset.cfg.SubjectDeleteMarkerTTL.Seconds()); ttl < minTtl { + ttl = minTtl + hdr = removeHeaderIfPresent(hdr, JSMessageTTL) + hdr = genHeader(hdr, JSMessageTTL, strconv.FormatInt(ttl, 10)) + } + } + + // Store actual msg. + if lseq == 0 && ts == 0 { + seq, ts, err = store.StoreMsg(subject, hdr, msg, ttl) + } else { + // Make sure to take into account any message assignments that we had to skip (clfs). + seq = lseq + 1 - clfs + // Check for preAcks and the need to clear it. + if mset.hasAllPreAcks(seq, subject) { + mset.clearAllPreAcks(seq) + } + err = store.StoreRawMsg(subject, hdr, msg, seq, ts, ttl) + } + + if err != nil { + if isPermissionError(err) { + mset.mu.Unlock() + // messages in block cache could be lost in the worst case. + // In the clustered mode it is very highly unlikely as a result of replication. + mset.srv.DisableJetStream() + mset.srv.Warnf("Filesystem permission denied while writing msg, disabling JetStream: %v", err) + return err + } + // If we did not succeed increment clfs in case we are clustered. + bumpCLFS() + mset.mu.Unlock() + + switch err { + case ErrMaxMsgs, ErrMaxBytes, ErrMaxMsgsPerSubject, ErrMsgTooLarge: + s.RateLimitDebugf("JetStream failed to store a msg on stream '%s > %s': %v", accName, name, err) + case ErrStoreClosed: + default: + s.Errorf("JetStream failed to store a msg on stream '%s > %s': %v", accName, name, err) + } + + if canRespond { + resp.PubAck = &PubAck{Stream: name} + resp.Error = NewJSStreamStoreFailedError(err, Unless(err)) + response, _ = json.Marshal(resp) + mset.outq.sendMsg(reply, response) + } + return err + } + + // If here we succeeded in storing the message. + mset.lmsgId = msgId + mset.lseq = seq + + // If we have a msgId make sure to save. + // This will replace our estimate from the cluster layer if we are clustered. + if msgId != _EMPTY_ { + if isClustered && isLeader && mset.ddmap != nil { + if dde := mset.ddmap[msgId]; dde != nil { + dde.seq, dde.ts = seq, ts + } else { + mset.storeMsgIdLocked(&ddentry{msgId, seq, ts}) + } + } else { + // R1 or not leader.. + mset.storeMsgIdLocked(&ddentry{msgId, seq, ts}) + } + } + + // If here we succeeded in storing the message. + mset.mu.Unlock() + + // No errors, this is the normal path. + if rollupSub { + mset.purge(&JSApiStreamPurgeRequest{Subject: subject, Keep: 1}) + } else if rollupAll { + mset.purge(&JSApiStreamPurgeRequest{Keep: 1}) + } + + // Check for republish. + if republish { + const ht = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\nNats-Last-Sequence: %d\r\n\r\n" + const htho = "NATS/1.0\r\nNats-Stream: %s\r\nNats-Subject: %s\r\nNats-Sequence: %d\r\nNats-Time-Stamp: %s\r\nNats-Last-Sequence: %d\r\nNats-Msg-Size: %d\r\n\r\n" + // When adding to existing headers, will use the fmt.Append version so this skips the headers from above. + const hoff = 10 + + tsStr := time.Unix(0, ts).UTC().Format(time.RFC3339Nano) + var rpMsg []byte + if len(hdr) == 0 { + if !thdrsOnly { + hdr = fmt.Appendf(nil, ht, name, subject, seq, tsStr, tlseq) + rpMsg = copyBytes(msg) + } else { + hdr = fmt.Appendf(nil, htho, name, subject, seq, tsStr, tlseq, len(msg)) + } + } else { + // use hdr[:end:end] to make sure as we add we copy the original hdr. + end := len(hdr) - LEN_CR_LF + if !thdrsOnly { + hdr = fmt.Appendf(hdr[:end:end], ht[hoff:], name, subject, seq, tsStr, tlseq) + rpMsg = copyBytes(msg) + } else { + hdr = fmt.Appendf(hdr[:end:end], htho[hoff:], name, subject, seq, tsStr, tlseq, len(msg)) + } + } + mset.outq.send(newJSPubMsg(tsubj, _EMPTY_, _EMPTY_, hdr, rpMsg, nil, seq)) + } + + // Send response here. + if canRespond { + response = append(pubAck, strconv.FormatUint(seq, 10)...) + response = append(response, '}') + mset.outq.sendMsg(reply, response) + } + + // Signal consumers for new messages. + if numConsumers > 0 { + mset.sigq.push(newCMsg(subject, seq)) + select { + case mset.sch <- struct{}{}: + default: + } + } + + return nil +} + +// Used to signal inbound message to registered consumers. +type cMsg struct { + seq uint64 + subj string +} + +// Pool to recycle consumer bound msgs. +var cMsgPool sync.Pool + +// Used to queue up consumer bound msgs for signaling. +func newCMsg(subj string, seq uint64) *cMsg { + var m *cMsg + cm := cMsgPool.Get() + if cm != nil { + m = cm.(*cMsg) + } else { + m = new(cMsg) + } + m.subj, m.seq = subj, seq + + return m +} + +func (m *cMsg) returnToPool() { + if m == nil { + return + } + m.subj, m.seq = _EMPTY_, 0 + cMsgPool.Put(m) +} + +// Go routine to signal consumers. +// Offloaded from stream msg processing. +func (mset *stream) signalConsumersLoop() { + mset.mu.RLock() + s, qch, sch, msgs := mset.srv, mset.qch, mset.sch, mset.sigq + mset.mu.RUnlock() + + for { + select { + case <-s.quitCh: + return + case <-qch: + return + case <-sch: + cms := msgs.pop() + for _, m := range cms { + seq, subj := m.seq, m.subj + m.returnToPool() + // Signal all appropriate consumers. + mset.signalConsumers(subj, seq) + } + msgs.recycle(&cms) + } + } +} + +// This will update and signal all consumers that match. +func (mset *stream) signalConsumers(subj string, seq uint64) { + mset.clsMu.RLock() + defer mset.clsMu.RUnlock() + csl := mset.csl + if csl == nil { + return + } + csl.Match(subj, func(o *consumer) { + o.processStreamSignal(seq) + }) +} + +// Internal message for use by jetstream subsystem. +type jsPubMsg struct { + dsubj string // Subject to send to, e.g. _INBOX.xxx + reply string + StoreMsg + o *consumer +} + +var jsPubMsgPool sync.Pool + +func newJSPubMsg(dsubj, subj, reply string, hdr, msg []byte, o *consumer, seq uint64) *jsPubMsg { + var m *jsPubMsg + var buf []byte + pm := jsPubMsgPool.Get() + if pm != nil { + m = pm.(*jsPubMsg) + buf = m.buf[:0] + if hdr != nil { + hdr = append(m.hdr[:0], hdr...) + } + } else { + m = new(jsPubMsg) + } + // When getting something from a pool it is critical that all fields are + // initialized. Doing this way guarantees that if someone adds a field to + // the structure, the compiler will fail the build if this line is not updated. + (*m) = jsPubMsg{dsubj, reply, StoreMsg{subj, hdr, msg, buf, seq, 0}, o} + + return m +} + +// Gets a jsPubMsg from the pool. +func getJSPubMsgFromPool() *jsPubMsg { + pm := jsPubMsgPool.Get() + if pm != nil { + return pm.(*jsPubMsg) + } + return new(jsPubMsg) +} + +func (pm *jsPubMsg) returnToPool() { + if pm == nil { + return + } + pm.subj, pm.dsubj, pm.reply, pm.hdr, pm.msg, pm.o = _EMPTY_, _EMPTY_, _EMPTY_, nil, nil, nil + if len(pm.buf) > 0 { + pm.buf = pm.buf[:0] + } + if len(pm.hdr) > 0 { + pm.hdr = pm.hdr[:0] + } + jsPubMsgPool.Put(pm) +} + +func (pm *jsPubMsg) size() int { + if pm == nil { + return 0 + } + return len(pm.dsubj) + len(pm.reply) + len(pm.hdr) + len(pm.msg) +} + +// Queue of *jsPubMsg for sending internal system messages. +type jsOutQ struct { + *ipQueue[*jsPubMsg] +} + +func (q *jsOutQ) sendMsg(subj string, msg []byte) { + if q != nil { + q.send(newJSPubMsg(subj, _EMPTY_, _EMPTY_, nil, msg, nil, 0)) + } +} + +func (q *jsOutQ) send(msg *jsPubMsg) { + if q == nil || msg == nil { + return + } + q.push(msg) +} + +func (q *jsOutQ) unregister() { + if q == nil { + return + } + q.ipQueue.unregister() +} + +// StoredMsg is for raw access to messages in a stream. +type StoredMsg struct { + Subject string `json:"subject"` + Sequence uint64 `json:"seq"` + Header []byte `json:"hdrs,omitempty"` + Data []byte `json:"data,omitempty"` + Time time.Time `json:"time"` +} + +// This is similar to system semantics but did not want to overload the single system sendq, +// or require system account when doing simple setup with jetstream. +func (mset *stream) setupSendCapabilities() { + mset.mu.Lock() + defer mset.mu.Unlock() + if mset.outq != nil { + return + } + qname := fmt.Sprintf("[ACC:%s] stream '%s' sendQ", mset.acc.Name, mset.cfg.Name) + mset.outq = &jsOutQ{newIPQueue[*jsPubMsg](mset.srv, qname)} + go mset.internalLoop() +} + +// Returns the associated account name. +func (mset *stream) accName() string { + if mset == nil { + return _EMPTY_ + } + mset.mu.RLock() + acc := mset.acc + mset.mu.RUnlock() + return acc.Name +} + +// Name returns the stream name. +func (mset *stream) name() string { + if mset == nil { + return _EMPTY_ + } + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.cfg.Name +} + +func (mset *stream) nameLocked(needLock bool) string { + if mset == nil { + return _EMPTY_ + } + if needLock { + mset.mu.RLock() + defer mset.mu.RUnlock() + } + return mset.cfg.Name +} + +func (mset *stream) internalLoop() { + mset.mu.RLock() + setGoRoutineLabels(pprofLabels{ + "account": mset.acc.Name, + "stream": mset.cfg.Name, + }) + s := mset.srv + c := s.createInternalJetStreamClient() + c.registerWithAccount(mset.acc) + defer c.closeConnection(ClientClosed) + outq, qch, msgs, gets := mset.outq, mset.qch, mset.msgs, mset.gets + + // For the ack msgs queue for interest retention. + var ( + amch chan struct{} + ackq *ipQueue[uint64] + ) + if mset.ackq != nil { + ackq, amch = mset.ackq, mset.ackq.ch + } + mset.mu.RUnlock() + + // Raw scratch buffer. + // This should be rarely used now so can be smaller. + var _r [1024]byte + + // To optimize for not converting a string to a []byte slice. + var ( + subj [256]byte + dsubj [256]byte + rply [256]byte + szb [10]byte + hdb [10]byte + ) + + for { + select { + case <-outq.ch: + pms := outq.pop() + for _, pm := range pms { + c.pa.subject = append(dsubj[:0], pm.dsubj...) + c.pa.deliver = append(subj[:0], pm.subj...) + c.pa.size = len(pm.msg) + len(pm.hdr) + c.pa.szb = append(szb[:0], strconv.Itoa(c.pa.size)...) + if len(pm.reply) > 0 { + c.pa.reply = append(rply[:0], pm.reply...) + } else { + c.pa.reply = nil + } + + // If we have an underlying buf that is the wire contents for hdr + msg, else construct on the fly. + var msg []byte + if len(pm.buf) > 0 { + msg = pm.buf + } else { + if len(pm.hdr) > 0 { + msg = pm.hdr + if len(pm.msg) > 0 { + msg = _r[:0] + msg = append(msg, pm.hdr...) + msg = append(msg, pm.msg...) + } + } else if len(pm.msg) > 0 { + // We own this now from a low level buffer perspective so can use directly here. + msg = pm.msg + } + } + + if len(pm.hdr) > 0 { + c.pa.hdr = len(pm.hdr) + c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr)) + c.pa.hdb = append(hdb[:0], strconv.Itoa(c.pa.hdr)...) + } else { + c.pa.hdr = -1 + c.pa.hdb = nil + } + + msg = append(msg, _CRLF_...) + + didDeliver, _ := c.processInboundClientMsg(msg) + c.pa.szb, c.pa.subject, c.pa.deliver = nil, nil, nil + + // Check to see if this is a delivery for a consumer and + // we failed to deliver the message. If so alert the consumer. + if pm.o != nil && pm.seq > 0 && !didDeliver { + pm.o.didNotDeliver(pm.seq, pm.dsubj) + } + pm.returnToPool() + } + // TODO: Move in the for-loop? + c.flushClients(0) + outq.recycle(&pms) + case <-msgs.ch: + // This can possibly change now so needs to be checked here. + isClustered := mset.IsClustered() + ims := msgs.pop() + for _, im := range ims { + // If we are clustered we need to propose this message to the underlying raft group. + if isClustered { + mset.processClusteredInboundMsg(im.subj, im.rply, im.hdr, im.msg, im.mt, false) + } else { + mset.processJetStreamMsg(im.subj, im.rply, im.hdr, im.msg, 0, 0, im.mt, false) + } + im.returnToPool() + } + msgs.recycle(&ims) + case <-gets.ch: + dgs := gets.pop() + for _, dg := range dgs { + mset.getDirectRequest(&dg.req, dg.reply) + dgPool.Put(dg) + } + gets.recycle(&dgs) + + case <-amch: + seqs := ackq.pop() + for _, seq := range seqs { + mset.ackMsg(nil, seq) + } + ackq.recycle(&seqs) + case <-qch: + return + case <-s.quitCh: + return + } + } +} + +// Used to break consumers out of their monitorConsumer go routines. +func (mset *stream) resetAndWaitOnConsumers() { + mset.mu.RLock() + consumers := make([]*consumer, 0, len(mset.consumers)) + for _, o := range mset.consumers { + consumers = append(consumers, o) + } + mset.mu.RUnlock() + + for _, o := range consumers { + if node := o.raftNode(); node != nil { + node.StepDown() + node.Stop() + } + if o.isMonitorRunning() { + o.signalMonitorQuit() + o.monitorWg.Wait() + } + } +} + +// Internal function to delete a stream. +func (mset *stream) delete() error { + if mset == nil { + return nil + } + return mset.stop(true, true) +} + +// Internal function to stop or delete the stream. +func (mset *stream) stop(deleteFlag, advisory bool) error { + mset.mu.RLock() + js, jsa, name, offlineReason := mset.js, mset.jsa, mset.cfg.Name, mset.offlineReason + mset.mu.RUnlock() + + if jsa == nil { + return NewJSNotEnabledForAccountError() + } + + // Remove from our account map first. + jsa.mu.Lock() + // Preserve in the account if it's marked offline, to have it remain queryable. + if deleteFlag || offlineReason == _EMPTY_ { + delete(jsa.streams, name) + } + accName := jsa.account.Name + jsa.mu.Unlock() + + // Kick monitor and collect consumers first. + mset.mu.Lock() + + // Mark closed. + mset.closed.Store(true) + + // Signal to the monitor loop. + // Can't use qch here. + if mset.mqch != nil { + close(mset.mqch) + mset.mqch = nil + } + + // Stop responding to sync requests. + mset.stopClusterSubs() + // Unsubscribe from direct stream. + mset.unsubscribeToStream(true) + + // Our info sub if we spun it up. + if mset.infoSub != nil { + mset.srv.sysUnsubscribe(mset.infoSub) + mset.infoSub = nil + } + + // Clean up consumers. + var obs []*consumer + for _, o := range mset.consumers { + obs = append(obs, o) + } + // Preserve the consumers if it's marked offline, to have them remain queryable. + if deleteFlag || offlineReason == _EMPTY_ { + mset.clsMu.Lock() + mset.consumers, mset.cList, mset.csl = nil, nil, nil + mset.clsMu.Unlock() + } + + // Check if we are a mirror. + if mset.mirror != nil && mset.mirror.sub != nil { + mset.unsubscribe(mset.mirror.sub) + mset.mirror.sub = nil + mset.removeInternalConsumer(mset.mirror) + } + // Now check for sources. + if len(mset.sources) > 0 { + for _, si := range mset.sources { + mset.cancelSourceConsumer(si.iname) + } + } + mset.mu.Unlock() + + isShuttingDown := js.isShuttingDown() + for _, o := range obs { + if !o.isClosed() { + // Third flag says do not broadcast a signal. + // TODO(dlc) - If we have an err here we don't want to stop + // but should we log? + o.stopWithFlags(deleteFlag, deleteFlag, false, advisory) + if !isShuttingDown { + o.signalMonitorQuit() + o.monitorWg.Wait() + } + } + } + + mset.mu.Lock() + // Send stream delete advisory after the consumers. + if deleteFlag && advisory { + mset.sendDeleteAdvisoryLocked() + } + + // Quit channel, do this after sending the delete advisory + if mset.qch != nil { + close(mset.qch) + mset.qch = nil + } + + // Cluster cleanup + var sa *streamAssignment + if n := mset.node; n != nil { + if deleteFlag { + n.Delete() + sa = mset.sa + } else if !isShuttingDown { + // Stop Raft, unless JetStream is already shutting down, in which case they'll be stopped separately. + n.Stop() + } + } + + // Cleanup duplicate timer if running. + if mset.ddtmr != nil { + mset.ddtmr.Stop() + mset.ddtmr = nil + mset.ddmap = nil + mset.ddarr = nil + mset.ddindex = 0 + } + + sysc := mset.sysc + mset.sysc = nil + + if deleteFlag { + // Unregistering ipQueues do not prevent them from push/pop + // just will remove them from the central monitoring map + mset.msgs.unregister() + mset.ackq.unregister() + mset.outq.unregister() + mset.sigq.unregister() + mset.smsgs.unregister() + } + + // Snapshot store. + store := mset.store + c := mset.client + + // Clustered cleanup. + mset.mu.Unlock() + + // Check if the stream assignment has the group node specified. + // We need this cleared for if the stream gets reassigned here. + if sa != nil { + js.mu.Lock() + if sa.Group != nil { + sa.Group.node = nil + } + js.mu.Unlock() + } + + if c != nil { + c.closeConnection(ClientClosed) + } + + if sysc != nil { + sysc.closeConnection(ClientClosed) + } + + if deleteFlag { + // cleanup directories after the stream + accDir := filepath.Join(js.config.StoreDir, accName) + if store != nil { + // Ignore errors. + store.Delete() + } else { + streamDir := filepath.Join(accDir, streamsDir) + os.RemoveAll(filepath.Join(streamDir, name)) + } + // Release any resources. + js.releaseStreamResources(&mset.cfg) + // Do cleanup in separate go routine similar to how fs will use purge here.. + go func() { + // no op if not empty + os.Remove(filepath.Join(accDir, streamsDir)) + os.Remove(accDir) + }() + } else if store != nil { + // Ignore errors. + store.Stop() + } + + return nil +} + +func (mset *stream) getMsg(seq uint64) (*StoredMsg, error) { + var smv StoreMsg + sm, err := mset.store.LoadMsg(seq, &smv) + if err != nil { + return nil, err + } + // This only used in tests directly so no need to pool etc. + return &StoredMsg{ + Subject: sm.subj, + Sequence: sm.seq, + Header: sm.hdr, + Data: sm.msg, + Time: time.Unix(0, sm.ts).UTC(), + }, nil +} + +// getConsumers will return a copy of all the current consumers for this stream. +func (mset *stream) getConsumers() []*consumer { + mset.clsMu.RLock() + defer mset.clsMu.RUnlock() + return append([]*consumer(nil), mset.cList...) +} + +// Lock should be held for this one. +func (mset *stream) numPublicConsumers() int { + return len(mset.consumers) - mset.directs +} + +// This returns all consumers that are not DIRECT. +func (mset *stream) getPublicConsumers() []*consumer { + mset.clsMu.RLock() + defer mset.clsMu.RUnlock() + + var obs []*consumer + for _, o := range mset.cList { + if !o.cfg.Direct { + obs = append(obs, o) + } + } + return obs +} + +// This returns all consumers that are DIRECT. +func (mset *stream) getDirectConsumers() []*consumer { + mset.clsMu.RLock() + defer mset.clsMu.RUnlock() + + var obs []*consumer + for _, o := range mset.cList { + if o.cfg.Direct { + obs = append(obs, o) + } + } + return obs +} + +// 2 minutes plus up to 30s jitter. +const ( + defaultCheckInterestStateT = 2 * time.Minute + defaultCheckInterestStateJ = 30 +) + +var ( + checkInterestStateT = defaultCheckInterestStateT // Interval + checkInterestStateJ = defaultCheckInterestStateJ // Jitter (secs) +) + +// Will check for interest retention and make sure messages +// that have been acked are processed and removed. +// This will check the ack floors of all consumers, and adjust our first sequence accordingly. +func (mset *stream) checkInterestState() { + if mset == nil || !mset.isInterestRetention() { + // If we are limits based nothing to do. + return + } + + // Ensure only one of these runs at the same time. + if !mset.cisrun.CompareAndSwap(false, true) { + return + } + defer mset.cisrun.Store(false) + + var ss StreamState + mset.store.FastState(&ss) + + asflr := uint64(math.MaxUint64) + for _, o := range mset.getConsumers() { + o.checkStateForInterestStream(&ss) + o.mu.RLock() + chkflr := o.chkflr + o.mu.RUnlock() + asflr = min(asflr, chkflr) + } + + mset.cfgMu.RLock() + rp := mset.cfg.Retention + mset.cfgMu.RUnlock() + // Remove as many messages from the "head" of the stream if there's no interest anymore. + if rp == InterestPolicy && asflr != math.MaxUint64 { + mset.store.Compact(asflr) + } +} + +func (mset *stream) isInterestRetention() bool { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.cfg.Retention != LimitsPolicy +} + +// NumConsumers reports on number of active consumers for this stream. +func (mset *stream) numConsumers() int { + mset.mu.RLock() + defer mset.mu.RUnlock() + return len(mset.consumers) +} + +// Lock should be held. +func (mset *stream) setConsumer(o *consumer) { + mset.consumers[o.name] = o + if len(o.subjf) > 0 { + mset.numFilter++ + } + if o.cfg.Direct { + mset.directs++ } - - // Send response here. - if doAck && len(reply) > 0 { - mset.sendq <- &jsPubMsg{reply, _EMPTY_, _EMPTY_, nil, response, nil, 0} + // Now update consumers list as well + mset.clsMu.Lock() + mset.cList = append(mset.cList, o) + if mset.csl == nil { + mset.csl = gsl.NewSublist[*consumer]() } + for _, sub := range o.signalSubs() { + mset.csl.Insert(sub, o) + } + mset.clsMu.Unlock() +} - if err == nil && seq > 0 && numConsumers > 0 { - var _obs [4]*Consumer - obs := _obs[:0] - - mset.mu.Lock() - for _, o := range mset.consumers { - obs = append(obs, o) +// Lock should be held. +func (mset *stream) removeConsumer(o *consumer) { + if o.cfg.FilterSubject != _EMPTY_ && mset.numFilter > 0 { + mset.numFilter-- + } + if o.cfg.Direct && mset.directs > 0 { + mset.directs-- + } + if mset.consumers != nil { + delete(mset.consumers, o.name) + // Now update consumers list as well + mset.clsMu.Lock() + for i, ol := range mset.cList { + if ol == o { + mset.cList = append(mset.cList[:i], mset.cList[i+1:]...) + break + } } - mset.mu.Unlock() - - for _, o := range obs { - o.incStreamPending(seq, subject) - if !o.deliverCurrentMsg(subject, hdr, msg, seq, ts) { - o.signalNewMessages() + // Always remove from the leader sublist. + if mset.csl != nil { + for _, sub := range o.signalSubs() { + mset.csl.Remove(sub, o) } } + mset.clsMu.Unlock() } } -// Internal message for use by jetstream subsystem. -type jsPubMsg struct { - subj string - dsubj string - reply string - hdr []byte - msg []byte - o *Consumer - seq uint64 -} +// swapSigSubs will update signal Subs for a new subject filter. +// consumer lock should not be held. +func (mset *stream) swapSigSubs(o *consumer, newFilters []string) { + mset.clsMu.Lock() + o.mu.Lock() -// StoredMsg is for raw access to messages in a stream. -type StoredMsg struct { - Subject string `json:"subject"` - Sequence uint64 `json:"seq"` - Header []byte `json:"hdrs,omitempty"` - Data []byte `json:"data,omitempty"` - Time time.Time `json:"time"` -} + if o.closed || o.mset == nil { + o.mu.Unlock() + mset.clsMu.Unlock() + return + } -// TODO(dlc) - Maybe look at onering instead of chan - https://github.com/pltr/onering -const msetSendQSize = 1024 + if o.sigSubs != nil { + if mset.csl != nil { + for _, sub := range o.sigSubs { + mset.csl.Remove(sub, o) + } + } + o.sigSubs = nil + } -// This is similar to system semantics but did not want to overload the single system sendq, -// or require system account when doing simple setup with jetstream. -func (mset *Stream) setupSendCapabilities() { - mset.mu.Lock() - defer mset.mu.Unlock() - if mset.sendq != nil { - return + if mset.csl == nil { + mset.csl = gsl.NewSublist[*consumer]() } - mset.sendq = make(chan *jsPubMsg, msetSendQSize) - go mset.internalSendLoop() -} + // If no filters are present, add fwcs to sublist for that consumer. + if newFilters == nil { + mset.csl.Insert(fwcs, o) + o.sigSubs = append(o.sigSubs, fwcs) + } else { + // If there are filters, add their subjects to sublist. + for _, filter := range newFilters { + mset.csl.Insert(filter, o) + o.sigSubs = append(o.sigSubs, filter) + } + } + o.mu.Unlock() + mset.clsMu.Unlock() -// Name returns the stream name. -func (mset *Stream) Name() string { mset.mu.Lock() defer mset.mu.Unlock() - return mset.config.Name -} -func (mset *Stream) internalSendLoop() { - mset.mu.RLock() - c := mset.client - if c == nil { - mset.mu.RUnlock() - return + if mset.numFilter > 0 && len(o.subjf) > 0 { + mset.numFilter-- } - s := c.srv - sendq := mset.sendq - name := mset.config.Name - mset.mu.RUnlock() - - // Warn when internal send queue is backed up past 75% - warnThresh := 3 * msetSendQSize / 4 - warnFreq := time.Second - last := time.Now().Add(-warnFreq) + if len(newFilters) > 0 { + mset.numFilter++ + } +} - for { - if len(sendq) > warnThresh && time.Since(last) >= warnFreq { - s.Warnf("Jetstream internal send queue > 75%% for account: %q stream: %q", c.acc.Name, name) - last = time.Now() - } - select { - case pm := <-sendq: - if pm == nil { - return - } - c.pa.subject = []byte(pm.subj) - c.pa.deliver = []byte(pm.dsubj) - c.pa.size = len(pm.msg) + len(pm.hdr) - c.pa.szb = []byte(strconv.Itoa(c.pa.size)) - c.pa.reply = []byte(pm.reply) - - var msg []byte - if len(pm.hdr) > 0 { - c.pa.hdr = len(pm.hdr) - c.pa.hdb = []byte(strconv.Itoa(c.pa.hdr)) - msg = append(pm.hdr, pm.msg...) - msg = append(msg, _CRLF_...) - } else { - c.pa.hdr = -1 - c.pa.hdb = nil - msg = append(pm.msg, _CRLF_...) - } +// lookupConsumer will retrieve a consumer by name. +func (mset *stream) lookupConsumer(name string) *consumer { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.consumers[name] +} - didDeliver := c.processInboundClientMsg(msg) - c.pa.szb = nil - c.flushClients(0) +func (mset *stream) numDirectConsumers() (num int) { + mset.clsMu.RLock() + defer mset.clsMu.RUnlock() - // Check to see if this is a delivery for an observable and - // we failed to deliver the message. If so alert the observable. - if pm.o != nil && pm.seq > 0 && !didDeliver { - pm.o.didNotDeliver(pm.seq) - } - case <-s.quitCh: - return + // Consumers that are direct are not recorded at the store level. + for _, o := range mset.cList { + o.mu.RLock() + if o.cfg.Direct { + num++ } + o.mu.RUnlock() } + return num } -// Internal function to delete a stream. -func (mset *Stream) delete() error { - return mset.stop(true) +// State will return the current state for this stream. +func (mset *stream) state() StreamState { + return mset.stateWithDetail(false) } -// Internal function to stop or delete the stream. -func (mset *Stream) stop(delete bool) error { - // Clean up consumers. - mset.mu.Lock() - var obs []*Consumer - for _, o := range mset.consumers { - obs = append(obs, o) +func (mset *stream) stateWithDetail(details bool) StreamState { + // mset.store does not change once set, so ok to reference here directly. + // We do this elsewhere as well. + store := mset.store + if store == nil { + return StreamState{} } - mset.consumers = nil - mset.mu.Unlock() - for _, o := range obs { - // Second flag says do not broadcast to signal. - // TODO(dlc) - If we have an err here we don't want to stop - // but should we log? - o.stop(delete, false, delete) + // Currently rely on store for details. + if details { + return store.State() } + // Here we do the fast version. + var state StreamState + store.FastState(&state) + return state +} - mset.mu.Lock() +func (mset *stream) Store() StreamStore { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.store +} - // Send stream delete advisory after the consumers. - if delete { - mset.sendDeleteAdvisoryLocked() +// Determines if the new proposed partition is unique amongst all consumers. +// Lock should be held. +func (mset *stream) partitionUnique(name string, partitions []string) bool { + for _, partition := range partitions { + for n, o := range mset.consumers { + // Skip the consumer being checked. + if n == name { + continue + } + o.mu.RLock() + if o.subjf == nil { + o.mu.RUnlock() + return false + } + for _, filter := range o.subjf { + if SubjectsCollide(partition, filter.subject) { + o.mu.RUnlock() + return false + } + } + o.mu.RUnlock() + } } + return true +} - if mset.sendq != nil { - mset.sendq <- nil +// Lock should be held. +func (mset *stream) potentialFilteredConsumers() bool { + numSubjects := len(mset.cfg.Subjects) + if len(mset.consumers) == 0 || numSubjects == 0 { + return false } - - c := mset.client - mset.client = nil - if c == nil { - mset.mu.Unlock() - return nil + if numSubjects > 1 || subjectHasWildcard(mset.cfg.Subjects[0]) { + return true } + return false +} - // Cleanup duplicate timer if running. - if mset.ddtmr != nil { - mset.ddtmr.Stop() - mset.ddtmr = nil - mset.ddarr = nil - mset.ddmap = nil - } - mset.mu.Unlock() +// Check if there is no interest in this sequence number across our consumers. +// The consumer passed is optional if we are processing the ack for that consumer. +// Write lock should be held. +func (mset *stream) noInterest(seq uint64, obs *consumer) bool { + return !mset.checkForInterest(seq, obs) +} - c.closeConnection(ClientClosed) +// Check if there is no interest in this sequence number and subject across our consumers. +// The consumer passed is optional if we are processing the ack for that consumer. +// Write lock should be held. +func (mset *stream) noInterestWithSubject(seq uint64, subj string, obs *consumer) bool { + return !mset.checkForInterestWithSubject(seq, subj, obs) +} - if mset.store == nil { - return nil +// Write lock should be held here for the stream to avoid race conditions on state. +func (mset *stream) checkForInterest(seq uint64, obs *consumer) bool { + var subj string + if mset.potentialFilteredConsumers() { + pmsg := getJSPubMsgFromPool() + defer pmsg.returnToPool() + sm, err := mset.store.LoadMsg(seq, &pmsg.StoreMsg) + if err != nil { + if err == ErrStoreEOF { + // Register this as a preAck. + mset.registerPreAck(obs, seq) + return true + } + mset.clearAllPreAcks(seq) + return false + } + subj = sm.subj } + return mset.checkForInterestWithSubject(seq, subj, obs) +} - if delete { - if err := mset.store.Delete(); err != nil { - return err +// Checks for interest given a sequence and subject. +func (mset *stream) checkForInterestWithSubject(seq uint64, subj string, obs *consumer) bool { + for _, o := range mset.consumers { + // If this is us or we have a registered preAck for this consumer continue inspecting. + if o == obs || mset.hasPreAck(o, seq) { + continue + } + // Check if we need an ack. + if o.needAck(seq, subj) { + return true } - } else if err := mset.store.Stop(); err != nil { - return err } - - return nil + mset.clearAllPreAcks(seq) + return false } -func (mset *Stream) GetMsg(seq uint64) (*StoredMsg, error) { - subj, hdr, msg, ts, err := mset.store.LoadMsg(seq) - if err != nil { - return nil, err +// Check if we have a pre-registered ack for this sequence. +// Write lock should be held. +func (mset *stream) hasPreAck(o *consumer, seq uint64) bool { + if o == nil || len(mset.preAcks) == 0 { + return false } - sm := &StoredMsg{ - Subject: subj, - Sequence: seq, - Header: hdr, - Data: msg, - Time: time.Unix(0, ts).UTC(), + consumers := mset.preAcks[seq] + if len(consumers) == 0 { + return false } - return sm, nil + _, found := consumers[o] + return found } -// Consunmers will return all the current consumers for this stream. -func (mset *Stream) Consumers() []*Consumer { - mset.mu.Lock() - defer mset.mu.Unlock() +// Check if we have all consumers pre-acked for this sequence and subject. +// Write lock should be held. +func (mset *stream) hasAllPreAcks(seq uint64, subj string) bool { + if len(mset.preAcks) == 0 || len(mset.preAcks[seq]) == 0 { + return false + } + // Since these can be filtered and mutually exclusive, + // if we have some preAcks we need to check all interest here. + return mset.noInterestWithSubject(seq, subj, nil) +} - var obs []*Consumer - for _, o := range mset.consumers { - obs = append(obs, o) +// Check if we have all consumers pre-acked. +// Write lock should be held. +func (mset *stream) clearAllPreAcks(seq uint64) { + delete(mset.preAcks, seq) +} + +// Clear all preAcks below floor. +// Write lock should be held. +func (mset *stream) clearAllPreAcksBelowFloor(floor uint64) { + for seq := range mset.preAcks { + if seq < floor { + delete(mset.preAcks, seq) + } } - return obs } -// NumConsumers reports on number of active observables for this stream. -func (mset *Stream) NumConsumers() int { +// This will register an ack for a consumer if it arrives before the actual message. +func (mset *stream) registerPreAckLock(o *consumer, seq uint64) { mset.mu.Lock() defer mset.mu.Unlock() - return len(mset.consumers) + mset.registerPreAck(o, seq) } -func (mset *Stream) addConsumer(o *Consumer) { - mset.consumers[o.name] = o - if o.config.FilterSubject != _EMPTY_ { - mset.numFilter++ +// This will register an ack for a consumer if it arrives before +// the actual message. +// Write lock should be held. +func (mset *stream) registerPreAck(o *consumer, seq uint64) { + if o == nil { + return } + if mset.preAcks == nil { + mset.preAcks = make(map[uint64]map[*consumer]struct{}) + } + if mset.preAcks[seq] == nil { + mset.preAcks[seq] = make(map[*consumer]struct{}) + } + mset.preAcks[seq][o] = struct{}{} } -func (mset *Stream) deleteConsumer(o *Consumer) { - if o.config.FilterSubject != _EMPTY_ { - mset.numFilter-- +// This will clear an ack for a consumer. +// Write lock should be held. +func (mset *stream) clearPreAck(o *consumer, seq uint64) { + if o == nil || len(mset.preAcks) == 0 { + return + } + if consumers := mset.preAcks[seq]; len(consumers) > 0 { + delete(consumers, o) + if len(consumers) == 0 { + delete(mset.preAcks, seq) + } } - delete(mset.consumers, o.name) } -// LookupConsumer will retrieve a consumer by name. -func (mset *Stream) LookupConsumer(name string) *Consumer { - mset.mu.Lock() - defer mset.mu.Unlock() - return mset.consumers[name] -} +// ackMsg is called into from a consumer when we have a WorkQueue or Interest Retention Policy. +// Returns whether the message at seq was removed as a result of the ACK. +// (Or should be removed in the case of clustered streams, since it requires a message delete proposal) +func (mset *stream) ackMsg(o *consumer, seq uint64) bool { + if seq == 0 { + return false + } -// State will return the current state for this stream. -func (mset *Stream) State() StreamState { + // Don't make this RLock(). We need to have only 1 running at a time to gauge interest across all consumers. mset.mu.Lock() - c := mset.client - mset.mu.Unlock() - if c == nil { - return StreamState{} + if mset.closed.Load() || mset.cfg.Retention == LimitsPolicy { + mset.mu.Unlock() + return false } - // Currently rely on store. - // TODO(dlc) - This will need to change with clusters. - return mset.store.State() -} -// Determines if the new proposed partition is unique amongst all observables. -// Lock should be held. -func (mset *Stream) partitionUnique(partition string) bool { - for _, o := range mset.consumers { - if o.config.FilterSubject == _EMPTY_ { - return false - } - if subjectIsSubsetMatch(partition, o.config.FilterSubject) { - return false - } + store := mset.store + var state StreamState + store.FastState(&state) + + // If this has arrived before we have processed the message itself. + if seq > state.LastSeq { + mset.registerPreAck(o, seq) + mset.mu.Unlock() + // We have not removed the message, but should still signal so we could retry later + // since we potentially need to remove it then. + return true } - return true -} -// Lock should be held. -func (mset *Stream) checkInterest(seq uint64, obs *Consumer) bool { - for _, o := range mset.consumers { - if o != obs && o.needAck(seq) { - return true - } + // Always clear pre-ack if here. + mset.clearPreAck(o, seq) + + // Make sure this sequence is not below our first sequence. + if seq < state.FirstSeq { + mset.mu.Unlock() + return false } - return false -} -// ackMsg is called into from a consumer when we have a WorkQueue or Interest retention policy. -func (mset *Stream) ackMsg(obs *Consumer, seq uint64) { - switch mset.config.Retention { - case LimitsPolicy: - return + var shouldRemove bool + switch mset.cfg.Retention { case WorkQueuePolicy: - mset.store.RemoveMsg(seq) + // Normally we just remove a message when its ack'd here but if we have direct consumers + // from sources and/or mirrors we need to make sure they have delivered the msg. + shouldRemove = mset.directs <= 0 || mset.noInterest(seq, o) case InterestPolicy: - mset.mu.Lock() - hasInterest := mset.checkInterest(seq, obs) + shouldRemove = mset.noInterest(seq, o) + } + + // If nothing else to do. + if !shouldRemove { + mset.mu.Unlock() + return false + } + + if !mset.isClustered() { + mset.mu.Unlock() + // If we are here we should attempt to remove. + if _, err := store.RemoveMsg(seq); err == ErrStoreEOF { + // This should not happen, but being pedantic. + mset.registerPreAckLock(o, seq) + } + return true + } + + // Only propose message deletion to the stream if we're consumer leader, otherwise all followers would also propose. + // We must be the consumer leader, since we know for sure we've stored the message and don't register as pre-ack. + if o != nil && !o.IsLeader() { + // Currently, interest-based streams can race on "no interest" because consumer creates/updates go over + // the meta layer and published messages go over the stream layer. Some servers could then either store + // or not store some initial set of messages that gained new interest. To get the stream back in sync, + // we allow moving the first sequence up. + // TODO(mvv): later on only the stream leader should determine "no interest" + interestRaiseFirst := mset.cfg.Retention == InterestPolicy && seq == state.FirstSeq mset.mu.Unlock() - if !hasInterest { - mset.store.RemoveMsg(seq) + if interestRaiseFirst { + if _, err := store.RemoveMsg(seq); err == ErrStoreEOF { + // This should not happen, but being pedantic. + mset.registerPreAckLock(o, seq) + } } + // Must still mark as removal if follower. If we become leader later, we must be able to retry the proposal. + return true } + + md := streamMsgDelete{Seq: seq, NoErase: true, Stream: mset.cfg.Name} + mset.node.ForwardProposal(encodeMsgDelete(&md)) + mset.mu.Unlock() + return true } // Snapshot creates a snapshot for the stream and possibly consumers. -func (mset *Stream) Snapshot(deadline time.Duration, checkMsgs, includeConsumers bool) (*SnapshotResult, error) { - mset.mu.Lock() - if mset.client == nil || mset.store == nil { - mset.mu.Unlock() - return nil, fmt.Errorf("invalid stream") +func (mset *stream) snapshot(deadline time.Duration, checkMsgs, includeConsumers bool) (*SnapshotResult, error) { + if mset.closed.Load() { + return nil, errStreamClosed } store := mset.store - mset.mu.Unlock() - return store.Snapshot(deadline, checkMsgs, includeConsumers) } const snapsDir = "__snapshots__" // RestoreStream will restore a stream from a snapshot. -func (a *Account) RestoreStream(stream string, r io.Reader) (*Stream, error) { - _, jsa, err := a.checkForJetStream() +func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error) { + if ncfg == nil { + return nil, errors.New("nil config on stream restore") + } + + s, jsa, err := a.checkForJetStream() if err != nil { return nil, err } + js := jsa.js + if js == nil { + return nil, NewJSNotEnabledForAccountError() + } - sd := path.Join(jsa.storeDir, snapsDir) - defer os.RemoveAll(sd) + cfg, apiErr := s.checkStreamCfg(ncfg, a, false) + if apiErr != nil { + return nil, apiErr + } + sd := filepath.Join(jsa.storeDir, snapsDir) if _, err := os.Stat(sd); os.IsNotExist(err) { - if err := os.MkdirAll(sd, 0755); err != nil { + if err := os.MkdirAll(sd, defaultDirPerms); err != nil { return nil, fmt.Errorf("could not create snapshots directory - %v", err) } } - sdir, err := ioutil.TempDir(sd, "snap-") + sdir, err := os.MkdirTemp(sd, "snap-") if err != nil { return nil, err } if _, err := os.Stat(sdir); os.IsNotExist(err) { - if err := os.MkdirAll(sdir, 0755); err != nil { + if err := os.MkdirAll(sdir, defaultDirPerms); err != nil { return nil, fmt.Errorf("could not create snapshots directory - %v", err) } } + defer os.RemoveAll(sdir) - gzr, err := gzip.NewReader(r) - if err != nil { - return nil, err + logAndReturnError := func() error { + a.mu.RLock() + err := fmt.Errorf("unexpected content (account=%s)", a.Name) + if a.srv != nil { + a.srv.Errorf("Stream restore failed due to %v", err) + } + a.mu.RUnlock() + return err + } + sdirCheck := filepath.Clean(sdir) + string(os.PathSeparator) + + _, isClustered := jsa.jetStreamAndClustered() + jsa.usageMu.RLock() + selected, tier, hasTier := jsa.selectLimits(cfg.Replicas) + jsa.usageMu.RUnlock() + reserved := int64(0) + if hasTier { + if isClustered { + js.mu.RLock() + _, reserved = tieredStreamAndReservationCount(js.cluster.streams[a.Name], tier, &cfg) + js.mu.RUnlock() + } else { + reserved = jsa.tieredReservation(tier, &cfg) + } } - defer gzr.Close() - tr := tar.NewReader(gzr) + var bc int64 + tr := tar.NewReader(s2.NewReader(r)) for { hdr, err := tr.Next() if err == io.EOF { @@ -1461,9 +6676,21 @@ func (a *Account) RestoreStream(stream string, r io.Reader) (*Stream, error) { if err != nil { return nil, err } - fpath := path.Join(sdir, filepath.Clean(hdr.Name)) - pdir := filepath.Dir(fpath) - os.MkdirAll(pdir, 0750) + if hdr.Typeflag != tar.TypeReg { + return nil, logAndReturnError() + } + bc += hdr.Size + js.mu.RLock() + err = js.checkAllLimits(&selected, &cfg, reserved, bc) + js.mu.RUnlock() + if err != nil { + return nil, err + } + fpath := filepath.Join(sdir, filepath.Clean(hdr.Name)) + if !strings.HasPrefix(fpath, sdirCheck) { + return nil, logAndReturnError() + } + os.MkdirAll(filepath.Dir(fpath), defaultDirPerms) fd, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0600) if err != nil { return nil, err @@ -1475,64 +6702,85 @@ func (a *Account) RestoreStream(stream string, r io.Reader) (*Stream, error) { } } - // Check metadata - var cfg FileStreamInfo - b, err := ioutil.ReadFile(path.Join(sdir, JetStreamMetaFile)) + // Check metadata. + // The cfg passed in will be the new identity for the stream. + var fcfg FileStreamInfo + b, err := os.ReadFile(filepath.Join(sdir, JetStreamMetaFile)) if err != nil { return nil, err } - if err := json.Unmarshal(b, &cfg); err != nil { + if err := json.Unmarshal(b, &fcfg); err != nil { return nil, err } - // See if names match - if cfg.Name != stream { - return nil, fmt.Errorf("stream name [%q] does not match snapshot stream [%q]", stream, cfg.Name) + + // Check to make sure names match. + if fcfg.Name != cfg.Name { + return nil, errors.New("stream names do not match") } // See if this stream already exists. - if _, err := a.LookupStream(cfg.Name); err == nil { - return nil, fmt.Errorf("stream [%q] already exists", cfg.Name) + if _, err := a.lookupStream(cfg.Name); err == nil { + return nil, NewJSStreamNameExistRestoreFailedError() } // Move into the correct place here. - ndir := path.Join(jsa.storeDir, streamsDir, cfg.Name) + ndir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name) + // Remove old one if for some reason it is still here. + if _, err := os.Stat(ndir); err == nil { + os.RemoveAll(ndir) + } + // Make sure our destination streams directory exists. + if err := os.MkdirAll(filepath.Join(jsa.storeDir, streamsDir), defaultDirPerms); err != nil { + return nil, err + } + // Move into new location. if err := os.Rename(sdir, ndir); err != nil { return nil, err } + if cfg.Template != _EMPTY_ { if err := jsa.addStreamNameToTemplate(cfg.Template, cfg.Name); err != nil { return nil, err } } - mset, err := a.AddStream(&cfg.StreamConfig) + mset, err := a.addStream(&cfg) if err != nil { + // Make sure to clean up after ourselves here. + os.RemoveAll(ndir) return nil, err } - if !cfg.Created.IsZero() { - mset.setCreated(cfg.Created) + if !fcfg.Created.IsZero() { + mset.setCreatedTime(fcfg.Created) + } + + // Make sure we do an update if the configs have changed. + if !reflect.DeepEqual(fcfg.StreamConfig, cfg) { + if err := mset.update(&cfg); err != nil { + return nil, err + } } // Now do consumers. - odir := path.Join(ndir, consumerDir) - ofis, _ := ioutil.ReadDir(odir) + odir := filepath.Join(ndir, consumerDir) + ofis, _ := os.ReadDir(odir) for _, ofi := range ofis { - metafile := path.Join(odir, ofi.Name(), JetStreamMetaFile) - metasum := path.Join(odir, ofi.Name(), JetStreamMetaFileSum) + metafile := filepath.Join(odir, ofi.Name(), JetStreamMetaFile) + metasum := filepath.Join(odir, ofi.Name(), JetStreamMetaFileSum) if _, err := os.Stat(metafile); os.IsNotExist(err) { - mset.Delete() + mset.stop(true, false) return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err) } - buf, err := ioutil.ReadFile(metafile) + buf, err := os.ReadFile(metafile) if err != nil { - mset.Delete() + mset.stop(true, false) return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err) } if _, err := os.Stat(metasum); os.IsNotExist(err) { - mset.Delete() + mset.stop(true, false) return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err) } var cfg FileConsumerInfo if err := json.Unmarshal(buf, &cfg); err != nil { - mset.Delete() + mset.stop(true, false) return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err) } isEphemeral := !isDurableConsumer(&cfg.ConsumerConfig) @@ -1541,21 +6789,101 @@ func (a *Account) RestoreStream(stream string, r io.Reader) (*Stream, error) { // the consumer can reconnect. We will create it as a durable and switch it. cfg.ConsumerConfig.Durable = ofi.Name() } - obs, err := mset.AddConsumer(&cfg.ConsumerConfig) + obs, err := mset.addConsumer(&cfg.ConsumerConfig) if err != nil { - mset.Delete() + mset.stop(true, false) return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err) } if isEphemeral { obs.switchToEphemeral() } if !cfg.Created.IsZero() { - obs.setCreated(cfg.Created) + obs.setCreatedTime(cfg.Created) } - if err := obs.readStoredState(); err != nil { - mset.Delete() + obs.mu.Lock() + err = obs.readStoredState() + obs.mu.Unlock() + if err != nil { + mset.stop(true, false) return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err) } } return mset, nil } + +// This is to check for dangling messages on interest retention streams. Only called on account enable. +// Issue https://github.com/nats-io/nats-server/issues/3612 +func (mset *stream) checkForOrphanMsgs() { + mset.mu.RLock() + consumers := make([]*consumer, 0, len(mset.consumers)) + for _, o := range mset.consumers { + consumers = append(consumers, o) + } + accName, stream := mset.acc.Name, mset.cfg.Name + + var ss StreamState + mset.store.FastState(&ss) + mset.mu.RUnlock() + + for _, o := range consumers { + if err := o.checkStateForInterestStream(&ss); err == errAckFloorHigherThanLastSeq { + o.mu.RLock() + s, consumer := o.srv, o.name + state, _ := o.store.State() + asflr := state.AckFloor.Stream + o.mu.RUnlock() + // Warn about stream state vs our ack floor. + s.RateLimitWarnf("Detected consumer '%s > %s > %s' ack floor %d is ahead of stream's last sequence %d", + accName, stream, consumer, asflr, ss.LastSeq) + } + } +} + +// Check on startup to make sure that consumers replication matches us. +// Interest retention requires replication matches. +func (mset *stream) checkConsumerReplication() { + mset.mu.RLock() + defer mset.mu.RUnlock() + + if mset.cfg.Retention != InterestPolicy { + return + } + + s, acc := mset.srv, mset.acc + for _, o := range mset.consumers { + o.mu.RLock() + // Consumer replicas 0 can be a legit config for the replicas and we will inherit from the stream + // when this is the case. + if mset.cfg.Replicas != o.cfg.Replicas && o.cfg.Replicas != 0 { + s.Errorf("consumer '%s > %s > %s' MUST match replication (%d vs %d) of stream with interest policy", + acc, mset.cfg.Name, o.cfg.Name, mset.cfg.Replicas, o.cfg.Replicas) + } + o.mu.RUnlock() + } +} + +// Will check if we are running in the monitor already and if not set the appropriate flag. +func (mset *stream) checkInMonitor() bool { + mset.mu.Lock() + defer mset.mu.Unlock() + + if mset.inMonitor { + return true + } + mset.inMonitor = true + return false +} + +// Clear us being in the monitor routine. +func (mset *stream) clearMonitorRunning() { + mset.mu.Lock() + defer mset.mu.Unlock() + mset.inMonitor = false +} + +// Check if our monitor is running. +func (mset *stream) isMonitorRunning() bool { + mset.mu.RLock() + defer mset.mu.RUnlock() + return mset.inMonitor +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/dump.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/dump.go new file mode 100644 index 0000000..12c62f3 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/dump.go @@ -0,0 +1,70 @@ +// Copyright 2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +import ( + "fmt" + "io" + "strings" +) + +// For dumping out a text representation of a tree. +func (t *SubjectTree[T]) Dump(w io.Writer) { + t.dump(w, t.root, 0) + fmt.Fprintln(w) +} + +// Will dump out a node. +func (t *SubjectTree[T]) dump(w io.Writer, n node, depth int) { + if n == nil { + fmt.Fprintf(w, "EMPTY\n") + return + } + if n.isLeaf() { + leaf := n.(*leaf[T]) + fmt.Fprintf(w, "%s LEAF: Suffix: %q Value: %+v\n", dumpPre(depth), leaf.suffix, leaf.value) + n = nil + } else { + // We are a node type here, grab meta portion. + bn := n.base() + fmt.Fprintf(w, "%s %s Prefix: %q\n", dumpPre(depth), n.kind(), bn.prefix) + depth++ + n.iter(func(n node) bool { + t.dump(w, n, depth) + return true + }) + } +} + +// For individual node/leaf dumps. +func (n *leaf[T]) kind() string { return "LEAF" } +func (n *node4) kind() string { return "NODE4" } +func (n *node10) kind() string { return "NODE10" } +func (n *node16) kind() string { return "NODE16" } +func (n *node48) kind() string { return "NODE48" } +func (n *node256) kind() string { return "NODE256" } + +// Calculates the indendation, etc. +func dumpPre(depth int) string { + if depth == 0 { + return "-- " + } else { + var b strings.Builder + for i := 0; i < depth; i++ { + b.WriteString(" ") + } + b.WriteString("|__ ") + return b.String() + } +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/leaf.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/leaf.go new file mode 100644 index 0000000..119837e --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/leaf.go @@ -0,0 +1,51 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +import ( + "bytes" +) + +// Leaf node +// Order of struct fields for best memory alignment (as per govet/fieldalignment) +type leaf[T any] struct { + value T + // This could be the whole subject, but most likely just the suffix portion. + // We will only store the suffix here and assume all prior prefix paths have + // been checked once we arrive at this leafnode. + suffix []byte +} + +func newLeaf[T any](suffix []byte, value T) *leaf[T] { + return &leaf[T]{value, copyBytes(suffix)} +} + +func (n *leaf[T]) isLeaf() bool { return true } +func (n *leaf[T]) base() *meta { return nil } +func (n *leaf[T]) match(subject []byte) bool { return bytes.Equal(subject, n.suffix) } +func (n *leaf[T]) setSuffix(suffix []byte) { n.suffix = copyBytes(suffix) } +func (n *leaf[T]) isFull() bool { return true } +func (n *leaf[T]) matchParts(parts [][]byte) ([][]byte, bool) { return matchParts(parts, n.suffix) } +func (n *leaf[T]) iter(f func(node) bool) {} +func (n *leaf[T]) children() []node { return nil } +func (n *leaf[T]) numChildren() uint16 { return 0 } +func (n *leaf[T]) path() []byte { return n.suffix } + +// Not applicable to leafs and should not be called, so panic if we do. +func (n *leaf[T]) setPrefix(pre []byte) { panic("setPrefix called on leaf") } +func (n *leaf[T]) addChild(_ byte, _ node) { panic("addChild called on leaf") } +func (n *leaf[T]) findChild(_ byte) *node { panic("findChild called on leaf") } +func (n *leaf[T]) grow() node { panic("grow called on leaf") } +func (n *leaf[T]) deleteChild(_ byte) { panic("deleteChild called on leaf") } +func (n *leaf[T]) shrink() node { panic("shrink called on leaf") } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/node.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/node.go new file mode 100644 index 0000000..c8edfe3 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/node.go @@ -0,0 +1,53 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// Internal node interface. +type node interface { + isLeaf() bool + base() *meta + setPrefix(pre []byte) + addChild(c byte, n node) + findChild(c byte) *node + deleteChild(c byte) + isFull() bool + grow() node + shrink() node + matchParts(parts [][]byte) ([][]byte, bool) + kind() string + iter(f func(node) bool) + children() []node + numChildren() uint16 + path() []byte +} + +type meta struct { + prefix []byte + size uint16 +} + +func (n *meta) isLeaf() bool { return false } +func (n *meta) base() *meta { return n } + +func (n *meta) setPrefix(pre []byte) { + n.prefix = append([]byte(nil), pre...) +} + +func (n *meta) numChildren() uint16 { return n.size } +func (n *meta) path() []byte { return n.prefix } + +// Will match parts against our prefix. +func (n *meta) matchParts(parts [][]byte) ([][]byte, bool) { + return matchParts(parts, n.prefix) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/node10.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/node10.go new file mode 100644 index 0000000..37cd2cc --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/node10.go @@ -0,0 +1,106 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// Node with 10 children +// This node size is for the particular case that a part of the subject is numeric +// in nature, i.e. it only needs to satisfy the range 0-9 without wasting bytes +// Order of struct fields for best memory alignment (as per govet/fieldalignment) +type node10 struct { + child [10]node + meta + key [10]byte +} + +func newNode10(prefix []byte) *node10 { + nn := &node10{} + nn.setPrefix(prefix) + return nn +} + +// Currently we do not keep node10 sorted or use bitfields for traversal so just add to the end. +// TODO(dlc) - We should revisit here with more detailed benchmarks. +func (n *node10) addChild(c byte, nn node) { + if n.size >= 10 { + panic("node10 full!") + } + n.key[n.size] = c + n.child[n.size] = nn + n.size++ +} + +func (n *node10) findChild(c byte) *node { + for i := uint16(0); i < n.size; i++ { + if n.key[i] == c { + return &n.child[i] + } + } + return nil +} + +func (n *node10) isFull() bool { return n.size >= 10 } + +func (n *node10) grow() node { + nn := newNode16(n.prefix) + for i := 0; i < 10; i++ { + nn.addChild(n.key[i], n.child[i]) + } + return nn +} + +// Deletes a child from the node. +func (n *node10) deleteChild(c byte) { + for i, last := uint16(0), n.size-1; i < n.size; i++ { + if n.key[i] == c { + // Unsorted so just swap in last one here, else nil if last. + if i < last { + n.key[i] = n.key[last] + n.child[i] = n.child[last] + n.key[last] = 0 + n.child[last] = nil + } else { + n.key[i] = 0 + n.child[i] = nil + } + n.size-- + return + } + } +} + +// Shrink if needed and return new node, otherwise return nil. +func (n *node10) shrink() node { + if n.size > 4 { + return nil + } + nn := newNode4(nil) + for i := uint16(0); i < n.size; i++ { + nn.addChild(n.key[i], n.child[i]) + } + return nn +} + +// Iterate over all children calling func f. +func (n *node10) iter(f func(node) bool) { + for i := uint16(0); i < n.size; i++ { + if !f(n.child[i]) { + return + } + } +} + +// Return our children as a slice. +func (n *node10) children() []node { + return n.child[:n.size] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/node16.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/node16.go new file mode 100644 index 0000000..e2dc979 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/node16.go @@ -0,0 +1,104 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// Node with 16 children +// Order of struct fields for best memory alignment (as per govet/fieldalignment) +type node16 struct { + child [16]node + meta + key [16]byte +} + +func newNode16(prefix []byte) *node16 { + nn := &node16{} + nn.setPrefix(prefix) + return nn +} + +// Currently we do not keep node16 sorted or use bitfields for traversal so just add to the end. +// TODO(dlc) - We should revisit here with more detailed benchmarks. +func (n *node16) addChild(c byte, nn node) { + if n.size >= 16 { + panic("node16 full!") + } + n.key[n.size] = c + n.child[n.size] = nn + n.size++ +} + +func (n *node16) findChild(c byte) *node { + for i := uint16(0); i < n.size; i++ { + if n.key[i] == c { + return &n.child[i] + } + } + return nil +} + +func (n *node16) isFull() bool { return n.size >= 16 } + +func (n *node16) grow() node { + nn := newNode48(n.prefix) + for i := 0; i < 16; i++ { + nn.addChild(n.key[i], n.child[i]) + } + return nn +} + +// Deletes a child from the node. +func (n *node16) deleteChild(c byte) { + for i, last := uint16(0), n.size-1; i < n.size; i++ { + if n.key[i] == c { + // Unsorted so just swap in last one here, else nil if last. + if i < last { + n.key[i] = n.key[last] + n.child[i] = n.child[last] + n.key[last] = 0 + n.child[last] = nil + } else { + n.key[i] = 0 + n.child[i] = nil + } + n.size-- + return + } + } +} + +// Shrink if needed and return new node, otherwise return nil. +func (n *node16) shrink() node { + if n.size > 10 { + return nil + } + nn := newNode10(nil) + for i := uint16(0); i < n.size; i++ { + nn.addChild(n.key[i], n.child[i]) + } + return nn +} + +// Iterate over all children calling func f. +func (n *node16) iter(f func(node) bool) { + for i := uint16(0); i < n.size; i++ { + if !f(n.child[i]) { + return + } + } +} + +// Return our children as a slice. +func (n *node16) children() []node { + return n.child[:n.size] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/node256.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/node256.go new file mode 100644 index 0000000..5d08b14 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/node256.go @@ -0,0 +1,80 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// Node with 256 children +// Order of struct fields for best memory alignment (as per govet/fieldalignment) +type node256 struct { + child [256]node + meta +} + +func newNode256(prefix []byte) *node256 { + nn := &node256{} + nn.setPrefix(prefix) + return nn +} + +func (n *node256) addChild(c byte, nn node) { + n.child[c] = nn + n.size++ +} + +func (n *node256) findChild(c byte) *node { + if n.child[c] != nil { + return &n.child[c] + } + return nil +} + +func (n *node256) isFull() bool { return false } +func (n *node256) grow() node { panic("grow can not be called on node256") } + +// Deletes a child from the node. +func (n *node256) deleteChild(c byte) { + if n.child[c] != nil { + n.child[c] = nil + n.size-- + } +} + +// Shrink if needed and return new node, otherwise return nil. +func (n *node256) shrink() node { + if n.size > 48 { + return nil + } + nn := newNode48(nil) + for c, child := range n.child { + if child != nil { + nn.addChild(byte(c), n.child[c]) + } + } + return nn +} + +// Iterate over all children calling func f. +func (n *node256) iter(f func(node) bool) { + for i := 0; i < 256; i++ { + if n.child[i] != nil { + if !f(n.child[i]) { + return + } + } + } +} + +// Return our children as a slice. +func (n *node256) children() []node { + return n.child[:256] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/node4.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/node4.go new file mode 100644 index 0000000..4eddf11 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/node4.go @@ -0,0 +1,99 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// Node with 4 children +// Order of struct fields for best memory alignment (as per govet/fieldalignment) +type node4 struct { + child [4]node + meta + key [4]byte +} + +func newNode4(prefix []byte) *node4 { + nn := &node4{} + nn.setPrefix(prefix) + return nn +} + +// Currently we do not need to keep sorted for traversal so just add to the end. +func (n *node4) addChild(c byte, nn node) { + if n.size >= 4 { + panic("node4 full!") + } + n.key[n.size] = c + n.child[n.size] = nn + n.size++ +} + +func (n *node4) findChild(c byte) *node { + for i := uint16(0); i < n.size; i++ { + if n.key[i] == c { + return &n.child[i] + } + } + return nil +} + +func (n *node4) isFull() bool { return n.size >= 4 } + +func (n *node4) grow() node { + nn := newNode10(n.prefix) + for i := 0; i < 4; i++ { + nn.addChild(n.key[i], n.child[i]) + } + return nn +} + +// Deletes a child from the node. +func (n *node4) deleteChild(c byte) { + for i, last := uint16(0), n.size-1; i < n.size; i++ { + if n.key[i] == c { + // Unsorted so just swap in last one here, else nil if last. + if i < last { + n.key[i] = n.key[last] + n.child[i] = n.child[last] + n.key[last] = 0 + n.child[last] = nil + } else { + n.key[i] = 0 + n.child[i] = nil + } + n.size-- + return + } + } +} + +// Shrink if needed and return new node, otherwise return nil. +func (n *node4) shrink() node { + if n.size == 1 { + return n.child[0] + } + return nil +} + +// Iterate over all children calling func f. +func (n *node4) iter(f func(node) bool) { + for i := uint16(0); i < n.size; i++ { + if !f(n.child[i]) { + return + } + } +} + +// Return our children as a slice. +func (n *node4) children() []node { + return n.child[:n.size] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/node48.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/node48.go new file mode 100644 index 0000000..7099edd --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/node48.go @@ -0,0 +1,110 @@ +// Copyright 2023-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// Node with 48 children +// Memory saving vs node256 comes from the fact that the child array is 16 bytes +// per `node` entry, so node256's 256*16=4096 vs node48's 256+(48*16)=1024 +// Note that `key` is effectively 1-indexed, as 0 means no entry, so offset by 1 +// Order of struct fields for best memory alignment (as per govet/fieldalignment) +type node48 struct { + child [48]node + meta + key [256]byte +} + +func newNode48(prefix []byte) *node48 { + nn := &node48{} + nn.setPrefix(prefix) + return nn +} + +func (n *node48) addChild(c byte, nn node) { + if n.size >= 48 { + panic("node48 full!") + } + n.child[n.size] = nn + n.key[c] = byte(n.size + 1) // 1-indexed + n.size++ +} + +func (n *node48) findChild(c byte) *node { + i := n.key[c] + if i == 0 { + return nil + } + return &n.child[i-1] +} + +func (n *node48) isFull() bool { return n.size >= 48 } + +func (n *node48) grow() node { + nn := newNode256(n.prefix) + for c := 0; c < len(n.key); c++ { + if i := n.key[byte(c)]; i > 0 { + nn.addChild(byte(c), n.child[i-1]) + } + } + return nn +} + +// Deletes a child from the node. +func (n *node48) deleteChild(c byte) { + i := n.key[c] + if i == 0 { + return + } + i-- // Adjust for 1-indexing + last := byte(n.size - 1) + if i < last { + n.child[i] = n.child[last] + for ic := 0; ic < len(n.key); ic++ { + if n.key[byte(ic)] == last+1 { + n.key[byte(ic)] = i + 1 + break + } + } + } + n.child[last] = nil + n.key[c] = 0 + n.size-- +} + +// Shrink if needed and return new node, otherwise return nil. +func (n *node48) shrink() node { + if n.size > 16 { + return nil + } + nn := newNode16(nil) + for c := 0; c < len(n.key); c++ { + if i := n.key[byte(c)]; i > 0 { + nn.addChild(byte(c), n.child[i-1]) + } + } + return nn +} + +// Iterate over all children calling func f. +func (n *node48) iter(f func(node) bool) { + for _, c := range n.child { + if c != nil && !f(c) { + return + } + } +} + +// Return our children as a slice. +func (n *node48) children() []node { + return n.child[:n.size] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/parts.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/parts.go new file mode 100644 index 0000000..af5dd9c --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/parts.go @@ -0,0 +1,147 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +import ( + "bytes" +) + +// genParts will break a filter subject up into parts. +// We need to break this up into chunks based on wildcards, either pwc '*' or fwc '>'. +// We do not care about other tokens per se, just parts that are separated by wildcards with an optional end fwc. +func genParts(filter []byte, parts [][]byte) [][]byte { + var start int + for i, e := 0, len(filter)-1; i < len(filter); i++ { + if filter[i] == tsep { + // See if next token is pwc. Either internal or end pwc. + if i < e && filter[i+1] == pwc && (i+2 <= e && filter[i+2] == tsep || i+1 == e) { + if i > start { + parts = append(parts, filter[start:i+1]) + } + parts = append(parts, filter[i+1:i+2]) + i++ // Skip pwc + if i+2 <= e { + i++ // Skip next tsep from next part too. + } + start = i + 1 + } else if i < e && filter[i+1] == fwc && i+1 == e { + if i > start { + parts = append(parts, filter[start:i+1]) + } + parts = append(parts, filter[i+1:i+2]) + i++ // Skip fwc + start = i + 1 + } + } else if filter[i] == pwc || filter[i] == fwc { + // Wildcard must be at the start or preceded by tsep. + if prev := i - 1; prev >= 0 && filter[prev] != tsep { + continue + } + // Wildcard must be at the end or followed by tsep. + if next := i + 1; next == e || next < e && filter[next] != tsep { + continue + } + // Full wildcard must be terminal. + if filter[i] == fwc && i < e { + break + } + // We start with a pwc or fwc. + parts = append(parts, filter[i:i+1]) + if i+1 <= e { + i++ // Skip next tsep from next part too. + } + start = i + 1 + } + } + if start < len(filter) { + // Check to see if we need to eat a leading tsep. + if filter[start] == tsep { + start++ + } + parts = append(parts, filter[start:]) + } + return parts +} + +// Match our parts against a fragment, which could be prefix for nodes or a suffix for leafs. +func matchParts(parts [][]byte, frag []byte) ([][]byte, bool) { + lf := len(frag) + if lf == 0 { + return parts, true + } + + var si int + lpi := len(parts) - 1 + + for i, part := range parts { + if si >= lf { + return parts[i:], true + } + lp := len(part) + // Check for pwc or fwc place holders. + if lp == 1 { + if part[0] == pwc { + index := bytes.IndexByte(frag[si:], tsep) + // We are trying to match pwc and did not find our tsep. + // Will need to move to next node from caller. + if index < 0 { + if i == lpi { + return nil, true + } + return parts[i:], true + } + si += index + 1 + continue + } else if part[0] == fwc { + // If we are here we should be good. + return nil, true + } + } + end := min(si+lp, lf) + // If part is bigger then the remaining fragment, adjust to a portion on the part. + if si+lp > end { + // Frag is smaller then part itself. + part = part[:end-si] + } + if !bytes.Equal(part, frag[si:end]) { + return parts, false + } + // If we still have a portion of the fragment left, update and continue. + if end < lf { + si = end + continue + } + // If we matched a partial, do not move past current part + // but update the part to what was consumed. This allows upper layers to continue. + if end < si+lp { + if end >= lf { + // Create a copy before modifying. Reuse slice capacity available at the + // end of the parts slice, since this saves us additional allocations. + lp := len(parts) + parts = append(parts[lp:], parts[:lp]...) + parts[i] = parts[i][lf-si:] + } else { + i++ + } + return parts[i:], true + } + if i == lpi { + return nil, true + } + // If we are here we are not the last part which means we have a wildcard + // gap, so we need to match anything up to next tsep. + si += len(part) + } + return parts, false +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go new file mode 100644 index 0000000..d0cd08a --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go @@ -0,0 +1,510 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +import ( + "bytes" + "slices" + "unsafe" + + "github.com/nats-io/nats-server/v2/server/gsl" +) + +// SubjectTree is an adaptive radix trie (ART) for storing subject information on literal subjects. +// Will use dynamic nodes, path compression and lazy expansion. +// The reason this exists is to not only save some memory in our filestore but to greatly optimize matching +// a wildcard subject to certain members, e.g. consumer NumPending calculations. +type SubjectTree[T any] struct { + root node + size int +} + +// NewSubjectTree creates a new SubjectTree with values T. +func NewSubjectTree[T any]() *SubjectTree[T] { + return &SubjectTree[T]{} +} + +// Size returns the number of elements stored. +func (t *SubjectTree[T]) Size() int { + if t == nil { + return 0 + } + return t.size +} + +// Will empty out the tree, or if tree is nil create a new one. +func (t *SubjectTree[T]) Empty() *SubjectTree[T] { + if t == nil { + return NewSubjectTree[T]() + } + t.root, t.size = nil, 0 + return t +} + +// Insert a value into the tree. Will return if the value was updated and if so the old value. +func (t *SubjectTree[T]) Insert(subject []byte, value T) (*T, bool) { + if t == nil { + return nil, false + } + + // Make sure we never insert anything with a noPivot byte. + if bytes.IndexByte(subject, noPivot) >= 0 { + return nil, false + } + + old, updated := t.insert(&t.root, subject, value, 0) + if !updated { + t.size++ + } + return old, updated +} + +// Find will find the value and return it or false if it was not found. +func (t *SubjectTree[T]) Find(subject []byte) (*T, bool) { + if t == nil { + return nil, false + } + + var si int + for n := t.root; n != nil; { + if n.isLeaf() { + if ln := n.(*leaf[T]); ln.match(subject[si:]) { + return &ln.value, true + } + return nil, false + } + // We are a node type here, grab meta portion. + if bn := n.base(); len(bn.prefix) > 0 { + end := min(si+len(bn.prefix), len(subject)) + if !bytes.Equal(subject[si:end], bn.prefix) { + return nil, false + } + // Increment our subject index. + si += len(bn.prefix) + } + if an := n.findChild(pivot(subject, si)); an != nil { + n = *an + } else { + return nil, false + } + } + return nil, false +} + +// Delete will delete the item and return its value, or not found if it did not exist. +func (t *SubjectTree[T]) Delete(subject []byte) (*T, bool) { + if t == nil { + return nil, false + } + + val, deleted := t.delete(&t.root, subject, 0) + if deleted { + t.size-- + } + return val, deleted +} + +// Match will match against a subject that can have wildcards and invoke the callback func for each matched value. +func (t *SubjectTree[T]) Match(filter []byte, cb func(subject []byte, val *T)) { + if t == nil || t.root == nil || len(filter) == 0 || cb == nil { + return + } + // We need to break this up into chunks based on wildcards, either pwc '*' or fwc '>'. + var raw [16][]byte + parts := genParts(filter, raw[:0]) + var _pre [256]byte + t.match(t.root, parts, _pre[:0], cb) +} + +// IterOrdered will walk all entries in the SubjectTree lexicographically. The callback can return false to terminate the walk. +func (t *SubjectTree[T]) IterOrdered(cb func(subject []byte, val *T) bool) { + if t == nil || t.root == nil { + return + } + var _pre [256]byte + t.iter(t.root, _pre[:0], true, cb) +} + +// IterFast will walk all entries in the SubjectTree with no guarantees of ordering. The callback can return false to terminate the walk. +func (t *SubjectTree[T]) IterFast(cb func(subject []byte, val *T) bool) { + if t == nil || t.root == nil { + return + } + var _pre [256]byte + t.iter(t.root, _pre[:0], false, cb) +} + +// Internal methods + +// Internal call to insert that can be recursive. +func (t *SubjectTree[T]) insert(np *node, subject []byte, value T, si int) (*T, bool) { + n := *np + if n == nil { + *np = newLeaf(subject, value) + return nil, false + } + if n.isLeaf() { + ln := n.(*leaf[T]) + if ln.match(subject[si:]) { + // Replace with new value. + old := ln.value + ln.value = value + return &old, true + } + // Here we need to split this leaf. + cpi := commonPrefixLen(ln.suffix, subject[si:]) + nn := newNode4(subject[si : si+cpi]) + ln.setSuffix(ln.suffix[cpi:]) + si += cpi + // Make sure we have different pivot, normally this will be the case unless we have overflowing prefixes. + if p := pivot(ln.suffix, 0); cpi > 0 && si < len(subject) && p == subject[si] { + // We need to split the original leaf. Recursively call into insert. + t.insert(np, subject, value, si) + // Now add the update version of *np as a child to the new node4. + nn.addChild(p, *np) + } else { + // Can just add this new leaf as a sibling. + nl := newLeaf(subject[si:], value) + nn.addChild(pivot(nl.suffix, 0), nl) + // Add back original. + nn.addChild(pivot(ln.suffix, 0), ln) + } + *np = nn + return nil, false + } + + // Non-leaf nodes. + bn := n.base() + if len(bn.prefix) > 0 { + cpi := commonPrefixLen(bn.prefix, subject[si:]) + if pli := len(bn.prefix); cpi >= pli { + // Move past this node. We look for an existing child node to recurse into. + // If one does not exist we can create a new leaf node. + si += pli + if nn := n.findChild(pivot(subject, si)); nn != nil { + return t.insert(nn, subject, value, si) + } + if n.isFull() { + n = n.grow() + *np = n + } + n.addChild(pivot(subject, si), newLeaf(subject[si:], value)) + return nil, false + } else { + // We did not match the prefix completely here. + // Calculate new prefix for this node. + prefix := subject[si : si+cpi] + si += len(prefix) + // We will insert a new node4 and attach our current node below after adjusting prefix. + nn := newNode4(prefix) + // Shift the prefix for our original node. + n.setPrefix(bn.prefix[cpi:]) + nn.addChild(pivot(bn.prefix[:], 0), n) + // Add in our new leaf. + nn.addChild(pivot(subject[si:], 0), newLeaf(subject[si:], value)) + // Update our node reference. + *np = nn + } + } else { + if nn := n.findChild(pivot(subject, si)); nn != nil { + return t.insert(nn, subject, value, si) + } + // No prefix and no matched child, so add in new leafnode as needed. + if n.isFull() { + n = n.grow() + *np = n + } + n.addChild(pivot(subject, si), newLeaf(subject[si:], value)) + } + + return nil, false +} + +// internal function to recursively find the leaf to delete. Will do compaction if the item is found and removed. +func (t *SubjectTree[T]) delete(np *node, subject []byte, si int) (*T, bool) { + if t == nil || np == nil || *np == nil || len(subject) == 0 { + return nil, false + } + n := *np + if n.isLeaf() { + ln := n.(*leaf[T]) + if ln.match(subject[si:]) { + *np = nil + return &ln.value, true + } + return nil, false + } + // Not a leaf node. + if bn := n.base(); len(bn.prefix) > 0 { + // subject could be shorter and would panic on bad index into subject slice. + if len(subject) < si+len(bn.prefix) { + return nil, false + } + if !bytes.Equal(subject[si:si+len(bn.prefix)], bn.prefix) { + return nil, false + } + // Increment our subject index. + si += len(bn.prefix) + } + p := pivot(subject, si) + nna := n.findChild(p) + if nna == nil { + return nil, false + } + nn := *nna + if nn.isLeaf() { + ln := nn.(*leaf[T]) + if ln.match(subject[si:]) { + n.deleteChild(p) + + if sn := n.shrink(); sn != nil { + bn := n.base() + // Make sure to set cap so we force an append to copy below. + pre := bn.prefix[:len(bn.prefix):len(bn.prefix)] + // Need to fix up prefixes/suffixes. + if sn.isLeaf() { + ln := sn.(*leaf[T]) + // Make sure to set cap so we force an append to copy. + ln.suffix = append(pre, ln.suffix...) + } else { + // We are a node here, we need to add in the old prefix. + if len(pre) > 0 { + bsn := sn.base() + sn.setPrefix(append(pre, bsn.prefix...)) + } + } + *np = sn + } + + return &ln.value, true + } + return nil, false + } + return t.delete(nna, subject, si) +} + +// Internal function which can be called recursively to match all leaf nodes to a given filter subject which +// once here has been decomposed to parts. These parts only care about wildcards, both pwc and fwc. +func (t *SubjectTree[T]) match(n node, parts [][]byte, pre []byte, cb func(subject []byte, val *T)) { + // Capture if we are sitting on a terminal fwc. + var hasFWC bool + if lp := len(parts); lp > 0 && len(parts[lp-1]) > 0 && parts[lp-1][0] == fwc { + hasFWC = true + } + + for n != nil { + nparts, matched := n.matchParts(parts) + // Check if we did not match. + if !matched { + return + } + // We have matched here. If we are a leaf and have exhausted all parts or he have a FWC fire callback. + if n.isLeaf() { + if len(nparts) == 0 || (hasFWC && len(nparts) == 1) { + ln := n.(*leaf[T]) + cb(append(pre, ln.suffix...), &ln.value) + } + return + } + // We have normal nodes here. + // We need to append our prefix + bn := n.base() + if len(bn.prefix) > 0 { + // Note that this append may reallocate, but it doesn't modify "pre" at the "match" callsite. + pre = append(pre, bn.prefix...) + } + + // Check our remaining parts. + if len(nparts) == 0 && !hasFWC { + // We are a node with no parts left and we are not looking at a fwc. + // We could have a leafnode with no suffix which would be a match. + // We could also have a terminal pwc. Check for those here. + var hasTermPWC bool + if lp := len(parts); lp > 0 && len(parts[lp-1]) == 1 && parts[lp-1][0] == pwc { + // If we are sitting on a terminal pwc, put the pwc back and continue. + nparts = parts[len(parts)-1:] + hasTermPWC = true + } + for _, cn := range n.children() { + if cn == nil { + continue + } + if cn.isLeaf() { + ln := cn.(*leaf[T]) + if len(ln.suffix) == 0 { + cb(append(pre, ln.suffix...), &ln.value) + } else if hasTermPWC && bytes.IndexByte(ln.suffix, tsep) < 0 { + cb(append(pre, ln.suffix...), &ln.value) + } + } else if hasTermPWC { + // We have terminal pwc so call into match again with the child node. + t.match(cn, nparts, pre, cb) + } + } + // Return regardless. + return + } + // If we are sitting on a terminal fwc, put back and continue. + if hasFWC && len(nparts) == 0 { + nparts = parts[len(parts)-1:] + } + + // Here we are a node type with a partial match. + // Check if the first part is a wildcard. + fp := nparts[0] + p := pivot(fp, 0) + // Check if we have a pwc/fwc part here. This will cause us to iterate. + if len(fp) == 1 && (p == pwc || p == fwc) { + // We need to iterate over all children here for the current node + // to see if we match further down. + for _, cn := range n.children() { + if cn != nil { + t.match(cn, nparts, pre, cb) + } + } + return + } + // Here we have normal traversal, so find the next child. + nn := n.findChild(p) + if nn == nil { + return + } + n, parts = *nn, nparts + } +} + +// Internal iter function to walk nodes in lexicographical order. +func (t *SubjectTree[T]) iter(n node, pre []byte, ordered bool, cb func(subject []byte, val *T) bool) bool { + if n.isLeaf() { + ln := n.(*leaf[T]) + return cb(append(pre, ln.suffix...), &ln.value) + } + // We are normal node here. + bn := n.base() + // Note that this append may reallocate, but it doesn't modify "pre" at the "iter" callsite. + pre = append(pre, bn.prefix...) + // Not everything requires lexicographical sorting, so support a fast path for iterating in + // whatever order the stree has things stored instead. + if !ordered { + for _, cn := range n.children() { + if cn == nil { + continue + } + if !t.iter(cn, pre, false, cb) { + return false + } + } + return true + } + // Collect nodes since unsorted. + var _nodes [256]node + nodes := _nodes[:0] + for _, cn := range n.children() { + if cn != nil { + nodes = append(nodes, cn) + } + } + // Now sort. + slices.SortStableFunc(nodes, func(a, b node) int { return bytes.Compare(a.path(), b.path()) }) + // Now walk the nodes in order and call into next iter. + for i := range nodes { + if !t.iter(nodes[i], pre, true, cb) { + return false + } + } + return true +} + +// LazyIntersect iterates the smaller of the two provided subject trees and +// looks for matching entries in the other. It is lazy in that it does not +// aggressively optimize against repeated walks, but is considerably faster +// in most cases than intersecting against a potentially large sublist. +func LazyIntersect[TL, TR any](tl *SubjectTree[TL], tr *SubjectTree[TR], cb func([]byte, *TL, *TR)) { + if tl == nil || tr == nil || tl.root == nil || tr.root == nil { + return + } + // Iterate over the smaller tree to reduce the number of rounds. + if tl.Size() <= tr.Size() { + tl.IterFast(func(key []byte, v1 *TL) bool { + if v2, ok := tr.Find(key); ok { + cb(key, v1, v2) + } + return true + }) + } else { + tr.IterFast(func(key []byte, v2 *TR) bool { + if v1, ok := tl.Find(key); ok { + cb(key, v1, v2) + } + return true + }) + } +} + +// IntersectGSL will match all items in the given subject tree that +// have interest expressed in the given sublist. The callback will only be called +// once for each subject, regardless of overlapping subscriptions in the sublist. +func IntersectGSL[T any, SL comparable](t *SubjectTree[T], sl *gsl.GenericSublist[SL], cb func(subject []byte, val *T)) { + if t == nil || t.root == nil || sl == nil { + return + } + var _pre [256]byte + _intersectGSL(t.root, _pre[:0], sl, cb) +} + +func _intersectGSL[T any, SL comparable](n node, pre []byte, sl *gsl.GenericSublist[SL], cb func(subject []byte, val *T)) { + if n.isLeaf() { + ln := n.(*leaf[T]) + subj := append(pre, ln.suffix...) + if sl.HasInterest(bytesToString(subj)) { + cb(subj, &ln.value) + } + return + } + bn := n.base() + pre = append(pre, bn.prefix...) + for _, cn := range n.children() { + if cn == nil { + continue + } + subj := append(pre, cn.path()...) + if !hasInterestForTokens(sl, subj, len(pre)) { + continue + } + _intersectGSL(cn, pre, sl, cb) + } +} + +// The subject tree can return partial tokens so we need to check starting interest +// only from whole tokens when we encounter a tsep. +func hasInterestForTokens[SL comparable](sl *gsl.GenericSublist[SL], subj []byte, since int) bool { + for i := since; i < len(subj); i++ { + if subj[i] == tsep { + if !sl.HasInterestStartingIn(bytesToString(subj[:i])) { + return false + } + } + } + return true +} + +// Note this will avoid a copy of the data used for the string, but it will also reference the existing slice's data pointer. +// So this should be used sparingly when we know the encompassing byte slice's lifetime is the same. +func bytesToString(b []byte) string { + if len(b) == 0 { + return "" + } + p := unsafe.SliceData(b) + return unsafe.String(p, len(b)) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/stree/util.go b/vendor/github.com/nats-io/nats-server/v2/server/stree/util.go new file mode 100644 index 0000000..8cb6224 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/stree/util.go @@ -0,0 +1,57 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stree + +// For subject matching. +const ( + pwc = '*' + fwc = '>' + tsep = '.' +) + +// Determine index of common prefix. No match at all is 0, etc. +func commonPrefixLen(s1, s2 []byte) int { + limit := min(len(s1), len(s2)) + var i int + for ; i < limit; i++ { + if s1[i] != s2[i] { + break + } + } + return i +} + +// Helper to copy bytes. +func copyBytes(src []byte) []byte { + if len(src) == 0 { + return nil + } + dst := make([]byte, len(src)) + copy(dst, src) + return dst +} + +type position interface{ int | uint16 } + +// No pivot available. +const noPivot = byte(127) + +// Can return 127 (DEL) if we have all the subject as prefixes. +// We used to use 0, but when that was in the subject would cause infinite recursion in some situations. +func pivot[N position](subject []byte, pos N) byte { + if int(pos) >= len(subject) { + return noPivot + } + return subject[pos] +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/subject_transform.go b/vendor/github.com/nats-io/nats-server/v2/server/subject_transform.go new file mode 100644 index 0000000..b635261 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/subject_transform.go @@ -0,0 +1,633 @@ +// Copyright 2023-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "fmt" + "hash/fnv" + "regexp" + "slices" + "strconv" + "strings" +) + +// Subject mapping and transform setups. +var ( + commaSeparatorRegEx = regexp.MustCompile(`,\s*`) + partitionMappingFunctionRegEx = regexp.MustCompile(`{{\s*[pP]artition\s*\((.*)\)\s*}}`) + wildcardMappingFunctionRegEx = regexp.MustCompile(`{{\s*[wW]ildcard\s*\((.*)\)\s*}}`) + splitFromLeftMappingFunctionRegEx = regexp.MustCompile(`{{\s*[sS]plit[fF]rom[lL]eft\s*\((.*)\)\s*}}`) + splitFromRightMappingFunctionRegEx = regexp.MustCompile(`{{\s*[sS]plit[fF]rom[rR]ight\s*\((.*)\)\s*}}`) + sliceFromLeftMappingFunctionRegEx = regexp.MustCompile(`{{\s*[sS]lice[fF]rom[lL]eft\s*\((.*)\)\s*}}`) + sliceFromRightMappingFunctionRegEx = regexp.MustCompile(`{{\s*[sS]lice[fF]rom[rR]ight\s*\((.*)\)\s*}}`) + splitMappingFunctionRegEx = regexp.MustCompile(`{{\s*[sS]plit\s*\((.*)\)\s*}}`) + leftMappingFunctionRegEx = regexp.MustCompile(`{{\s*[lL]eft\s*\((.*)\)\s*}}`) + rightMappingFunctionRegEx = regexp.MustCompile(`{{\s*[rR]ight\s*\((.*)\)\s*}}`) +) + +// Enum for the subject mapping subjectTransform function types +const ( + NoTransform int16 = iota + BadTransform + Partition + Wildcard + SplitFromLeft + SplitFromRight + SliceFromLeft + SliceFromRight + Split + Left + Right +) + +// Transforms for arbitrarily mapping subjects from one to another for maps, tees and filters. +// These can also be used for proper mapping on wildcard exports/imports. +// These will be grouped and caching and locking are assumed to be in the upper layers. +type subjectTransform struct { + src, dest string + dtoks []string // destination tokens + stoks []string // source tokens + dtokmftypes []int16 // destination token mapping function types + dtokmftokindexesargs [][]int // destination token mapping function array of source token index arguments + dtokmfintargs []int32 // destination token mapping function int32 arguments + dtokmfstringargs []string // destination token mapping function string arguments +} + +// SubjectTransformer transforms subjects using mappings +// +// This API is not part of the public API and not subject to SemVer protections +type SubjectTransformer interface { + // TODO(dlc) - We could add in client here to allow for things like foo -> foo.$ACCOUNT + Match(string) (string, error) + TransformSubject(subject string) string + TransformTokenizedSubject(tokens []string) string +} + +func NewSubjectTransformWithStrict(src, dest string, strict bool) (*subjectTransform, error) { + // strict = true for import subject mappings that need to be reversible + // (meaning can only use the Wildcard function and must use all the pwcs that are present in the source) + // No source given is equivalent to the source being ">" + + if dest == _EMPTY_ { + return nil, nil + } + + if src == _EMPTY_ { + src = fwcs + } + + // Both entries need to be valid subjects. + sv, stokens, npwcs, hasFwc := subjectInfo(src) + dv, dtokens, dnpwcs, dHasFwc := subjectInfo(dest) + + // Make sure both are valid, match fwc if present and there are no pwcs in the dest subject. + if !sv || !dv || dnpwcs > 0 || hasFwc != dHasFwc { + return nil, ErrBadSubject + } + + var dtokMappingFunctionTypes []int16 + var dtokMappingFunctionTokenIndexes [][]int + var dtokMappingFunctionIntArgs []int32 + var dtokMappingFunctionStringArgs []string + + // If the src has partial wildcards then the dest needs to have the token place markers. + if npwcs > 0 || hasFwc { + // We need to count to make sure that the dest has token holders for the pwcs. + sti := make(map[int]int) + for i, token := range stokens { + if len(token) == 1 && token[0] == pwc { + sti[len(sti)+1] = i + } + } + + nphs := 0 + for _, token := range dtokens { + tranformType, transformArgWildcardIndexes, transfomArgInt, transformArgString, err := indexPlaceHolders(token) + if err != nil { + return nil, err + } + + if strict { + if tranformType != NoTransform && tranformType != Wildcard { + return nil, &mappingDestinationErr{token, ErrMappingDestinationNotSupportedForImport} + } + } + + if npwcs == 0 { + if tranformType != NoTransform { + return nil, &mappingDestinationErr{token, ErrMappingDestinationIndexOutOfRange} + } + } + + if tranformType == NoTransform { + dtokMappingFunctionTypes = append(dtokMappingFunctionTypes, NoTransform) + dtokMappingFunctionTokenIndexes = append(dtokMappingFunctionTokenIndexes, []int{-1}) + dtokMappingFunctionIntArgs = append(dtokMappingFunctionIntArgs, -1) + dtokMappingFunctionStringArgs = append(dtokMappingFunctionStringArgs, _EMPTY_) + } else { + nphs += len(transformArgWildcardIndexes) + // Now build up our runtime mapping from dest to source tokens. + var stis []int + for _, wildcardIndex := range transformArgWildcardIndexes { + if wildcardIndex > npwcs { + return nil, &mappingDestinationErr{fmt.Sprintf("%s: [%d]", token, wildcardIndex), ErrMappingDestinationIndexOutOfRange} + } + stis = append(stis, sti[wildcardIndex]) + } + dtokMappingFunctionTypes = append(dtokMappingFunctionTypes, tranformType) + dtokMappingFunctionTokenIndexes = append(dtokMappingFunctionTokenIndexes, stis) + dtokMappingFunctionIntArgs = append(dtokMappingFunctionIntArgs, transfomArgInt) + dtokMappingFunctionStringArgs = append(dtokMappingFunctionStringArgs, transformArgString) + + } + } + if strict && nphs < npwcs { + // not all wildcards are being used in the destination + return nil, &mappingDestinationErr{dest, ErrMappingDestinationNotUsingAllWildcards} + } + } else { + // no wildcards used in the source: check that no transform functions are used in the destination + for _, token := range dtokens { + tranformType, _, _, _, err := indexPlaceHolders(token) + if err != nil { + return nil, err + } + + if tranformType != NoTransform { + return nil, &mappingDestinationErr{token, ErrMappingDestinationIndexOutOfRange} + } + } + } + + return &subjectTransform{ + src: src, + dest: dest, + dtoks: dtokens, + stoks: stokens, + dtokmftypes: dtokMappingFunctionTypes, + dtokmftokindexesargs: dtokMappingFunctionTokenIndexes, + dtokmfintargs: dtokMappingFunctionIntArgs, + dtokmfstringargs: dtokMappingFunctionStringArgs, + }, nil +} + +func NewSubjectTransform(src, dest string) (*subjectTransform, error) { + return NewSubjectTransformWithStrict(src, dest, false) +} + +func NewSubjectTransformStrict(src, dest string) (*subjectTransform, error) { + return NewSubjectTransformWithStrict(src, dest, true) +} + +func getMappingFunctionArgs(functionRegEx *regexp.Regexp, token string) []string { + commandStrings := functionRegEx.FindStringSubmatch(token) + if len(commandStrings) > 1 { + return commaSeparatorRegEx.Split(commandStrings[1], -1) + } + return nil +} + +// Helper for mapping functions that take a wildcard index and an integer as arguments +func transformIndexIntArgsHelper(token string, args []string, transformType int16) (int16, []int, int32, string, error) { + if len(args) < 2 { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationNotEnoughArgs} + } + if len(args) > 2 { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationTooManyArgs} + } + i, err := strconv.Atoi(strings.Trim(args[0], " ")) + if err != nil { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationInvalidArg} + } + mappingFunctionIntArg, err := strconv.ParseInt(strings.Trim(args[1], " "), 10, 32) + if err != nil { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationInvalidArg} + } + + return transformType, []int{i}, int32(mappingFunctionIntArg), _EMPTY_, nil +} + +// Helper to ingest and index the subjectTransform destination token (e.g. $x or {{}}) in the token +// returns a transformation type, and three function arguments: an array of source subject token indexes, +// and a single number (e.g. number of partitions, or a slice size), and a string (e.g.a split delimiter) +func indexPlaceHolders(token string) (int16, []int, int32, string, error) { + length := len(token) + if length > 1 { + // old $1, $2, etc... mapping format still supported to maintain backwards compatibility + if token[0] == '$' { // simple non-partition mapping + tp, err := strconv.Atoi(token[1:]) + if err != nil { + // other things rely on tokens starting with $ so not an error just leave it as is + return NoTransform, []int{-1}, -1, _EMPTY_, nil + } + return Wildcard, []int{tp}, -1, _EMPTY_, nil + } + + // New 'mustache' style mapping + if length > 4 && token[0] == '{' && token[1] == '{' && token[length-2] == '}' && token[length-1] == '}' { + // wildcard(wildcard token index) (equivalent to $) + args := getMappingFunctionArgs(wildcardMappingFunctionRegEx, token) + if args != nil { + if len(args) == 1 && args[0] == _EMPTY_ { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationNotEnoughArgs} + } + if len(args) == 1 { + tokenIndex, err := strconv.Atoi(strings.Trim(args[0], " ")) + if err != nil { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationInvalidArg} + } + return Wildcard, []int{tokenIndex}, -1, _EMPTY_, nil + } else { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationTooManyArgs} + } + } + + // partition(number of partitions, token1, token2, ...) + args = getMappingFunctionArgs(partitionMappingFunctionRegEx, token) + if args != nil { + if len(args) < 2 { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationNotEnoughArgs} + } + if len(args) >= 2 { + mappingFunctionIntArg, err := strconv.Atoi(strings.Trim(args[0], " ")) + if err != nil { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationInvalidArg} + } + var numPositions = len(args[1:]) + tokenIndexes := make([]int, numPositions) + for ti, t := range args[1:] { + i, err := strconv.Atoi(strings.Trim(t, " ")) + if err != nil { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationInvalidArg} + } + tokenIndexes[ti] = i + } + + return Partition, tokenIndexes, int32(mappingFunctionIntArg), _EMPTY_, nil + } + } + + // SplitFromLeft(token, position) + args = getMappingFunctionArgs(splitFromLeftMappingFunctionRegEx, token) + if args != nil { + return transformIndexIntArgsHelper(token, args, SplitFromLeft) + } + + // SplitFromRight(token, position) + args = getMappingFunctionArgs(splitFromRightMappingFunctionRegEx, token) + if args != nil { + return transformIndexIntArgsHelper(token, args, SplitFromRight) + } + + // SliceFromLeft(token, position) + args = getMappingFunctionArgs(sliceFromLeftMappingFunctionRegEx, token) + if args != nil { + return transformIndexIntArgsHelper(token, args, SliceFromLeft) + } + + // SliceFromRight(token, position) + args = getMappingFunctionArgs(sliceFromRightMappingFunctionRegEx, token) + if args != nil { + return transformIndexIntArgsHelper(token, args, SliceFromRight) + } + + // Right(token, length) + args = getMappingFunctionArgs(rightMappingFunctionRegEx, token) + if args != nil { + return transformIndexIntArgsHelper(token, args, Right) + } + + // Left(token, length) + args = getMappingFunctionArgs(leftMappingFunctionRegEx, token) + if args != nil { + return transformIndexIntArgsHelper(token, args, Left) + } + + // split(token, deliminator) + args = getMappingFunctionArgs(splitMappingFunctionRegEx, token) + if args != nil { + if len(args) < 2 { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationNotEnoughArgs} + } + if len(args) > 2 { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationTooManyArgs} + } + i, err := strconv.Atoi(strings.Trim(args[0], " ")) + if err != nil { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrMappingDestinationInvalidArg} + } + if strings.Contains(args[1], " ") || strings.Contains(args[1], tsep) { + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token: token, err: ErrMappingDestinationInvalidArg} + } + + return Split, []int{i}, -1, args[1], nil + } + + return BadTransform, []int{}, -1, _EMPTY_, &mappingDestinationErr{token, ErrUnknownMappingDestinationFunction} + } + } + return NoTransform, []int{-1}, -1, _EMPTY_, nil +} + +// Helper function to tokenize subjects with partial wildcards into formal transform destinations. +// e.g. "foo.*.*" -> "foo.$1.$2" +func transformTokenize(subject string) string { + // We need to make the appropriate markers for the wildcards etc. + i := 1 + var nda []string + for token := range strings.SplitSeq(subject, tsep) { + if token == pwcs { + nda = append(nda, fmt.Sprintf("$%d", i)) + i++ + } else { + nda = append(nda, token) + } + } + return strings.Join(nda, tsep) +} + +// Helper function to go from transform destination to a subject with partial wildcards and ordered list of placeholders +// E.g.: +// +// "bar" -> "bar", [] +// "foo.$2.$1" -> "foo.*.*", ["$2","$1"] +// "foo.{{wildcard(2)}}.{{wildcard(1)}}" -> "foo.*.*", ["{{wildcard(2)}}","{{wildcard(1)}}"] +func transformUntokenize(subject string) (string, []string) { + var phs []string + var nda []string + + for token := range strings.SplitSeq(subject, tsep) { + if args := getMappingFunctionArgs(wildcardMappingFunctionRegEx, token); (len(token) > 1 && token[0] == '$' && token[1] >= '1' && token[1] <= '9') || (len(args) == 1 && args[0] != _EMPTY_) { + phs = append(phs, token) + nda = append(nda, pwcs) + } else { + nda = append(nda, token) + } + } + return strings.Join(nda, tsep), phs +} + +func tokenizeSubject(subject string) []string { + // Tokenize the subject. + tsa := [32]string{} + tts := tsa[:0] + start := 0 + for i := 0; i < len(subject); i++ { + if subject[i] == btsep { + tts = append(tts, subject[start:i]) + start = i + 1 + } + } + tts = append(tts, subject[start:]) + return tts +} + +// Match will take a literal published subject that is associated with a client and will match and subjectTransform +// the subject if possible. +// +// This API is not part of the public API and not subject to SemVer protections +func (tr *subjectTransform) Match(subject string) (string, error) { + // Special case: matches any and no no-op subjectTransform. May not be legal config for some features + // but specific validations made at subjectTransform create time + if (tr.src == fwcs || tr.src == _EMPTY_) && (tr.dest == fwcs || tr.dest == _EMPTY_) { + return subject, nil + } + + tts := tokenizeSubject(subject) + + // TODO(jnm): optimization -> not sure this is actually needed but was there in initial code + if !isValidLiteralSubject(slices.Values(tts)) { + return _EMPTY_, ErrBadSubject + } + + if (tr.src == _EMPTY_ || tr.src == fwcs) || isSubsetMatch(tts, tr.src) { + return tr.TransformTokenizedSubject(tts), nil + } + return _EMPTY_, ErrNoTransforms +} + +// TransformSubject transforms a subject +// +// This API is not part of the public API and not subject to SemVer protection +func (tr *subjectTransform) TransformSubject(subject string) string { + return tr.TransformTokenizedSubject(tokenizeSubject(subject)) +} + +func (tr *subjectTransform) getHashPartition(key []byte, numBuckets int) string { + h := fnv.New32a() + _, _ = h.Write(key) + + return strconv.Itoa(int(h.Sum32() % uint32(numBuckets))) +} + +// Do a subjectTransform on the subject to the dest subject. +func (tr *subjectTransform) TransformTokenizedSubject(tokens []string) string { + if len(tr.dtokmftypes) == 0 { + return tr.dest + } + + var b strings.Builder + + // We need to walk destination tokens and create the mapped subject pulling tokens or mapping functions + li := len(tr.dtokmftypes) - 1 + for i, mfType := range tr.dtokmftypes { + if mfType == NoTransform { + // Break if fwc + if len(tr.dtoks[i]) == 1 && tr.dtoks[i][0] == fwc { + break + } + b.WriteString(tr.dtoks[i]) + } else { + switch mfType { + case Partition: + var ( + _buffer [64]byte + keyForHashing = _buffer[:0] + ) + for _, sourceToken := range tr.dtokmftokindexesargs[i] { + keyForHashing = append(keyForHashing, []byte(tokens[sourceToken])...) + } + b.WriteString(tr.getHashPartition(keyForHashing, int(tr.dtokmfintargs[i]))) + case Wildcard: // simple substitution + switch { + case len(tr.dtokmftokindexesargs) < i: + break + case len(tr.dtokmftokindexesargs[i]) < 1: + break + case len(tokens) <= tr.dtokmftokindexesargs[i][0]: + break + default: + b.WriteString(tokens[tr.dtokmftokindexesargs[i][0]]) + } + case SplitFromLeft: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + sourceTokenLen := len(sourceToken) + position := int(tr.dtokmfintargs[i]) + if position > 0 && position < sourceTokenLen { + b.WriteString(sourceToken[:position]) + b.WriteString(tsep) + b.WriteString(sourceToken[position:]) + } else { // too small to split at the requested position: don't split + b.WriteString(sourceToken) + } + case SplitFromRight: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + sourceTokenLen := len(sourceToken) + position := int(tr.dtokmfintargs[i]) + if position > 0 && position < sourceTokenLen { + b.WriteString(sourceToken[:sourceTokenLen-position]) + b.WriteString(tsep) + b.WriteString(sourceToken[sourceTokenLen-position:]) + } else { // too small to split at the requested position: don't split + b.WriteString(sourceToken) + } + case SliceFromLeft: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + sourceTokenLen := len(sourceToken) + sliceSize := int(tr.dtokmfintargs[i]) + if sliceSize > 0 && sliceSize < sourceTokenLen { + for i := 0; i+sliceSize <= sourceTokenLen; i += sliceSize { + if i != 0 { + b.WriteString(tsep) + } + b.WriteString(sourceToken[i : i+sliceSize]) + if i+sliceSize != sourceTokenLen && i+sliceSize+sliceSize > sourceTokenLen { + b.WriteString(tsep) + b.WriteString(sourceToken[i+sliceSize:]) + break + } + } + } else { // too small to slice at the requested size: don't slice + b.WriteString(sourceToken) + } + case SliceFromRight: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + sourceTokenLen := len(sourceToken) + sliceSize := int(tr.dtokmfintargs[i]) + if sliceSize > 0 && sliceSize < sourceTokenLen { + remainder := sourceTokenLen % sliceSize + if remainder > 0 { + b.WriteString(sourceToken[:remainder]) + b.WriteString(tsep) + } + for i := remainder; i+sliceSize <= sourceTokenLen; i += sliceSize { + b.WriteString(sourceToken[i : i+sliceSize]) + if i+sliceSize < sourceTokenLen { + b.WriteString(tsep) + } + } + } else { // too small to slice at the requested size: don't slice + b.WriteString(sourceToken) + } + case Split: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + splits := strings.Split(sourceToken, tr.dtokmfstringargs[i]) + for j, split := range splits { + if split != _EMPTY_ { + b.WriteString(split) + } + if j < len(splits)-1 && splits[j+1] != _EMPTY_ && !(j == 0 && split == _EMPTY_) { + b.WriteString(tsep) + } + } + case Left: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + sourceTokenLen := len(sourceToken) + sliceSize := int(tr.dtokmfintargs[i]) + if sliceSize > 0 && sliceSize < sourceTokenLen { + b.WriteString(sourceToken[0:sliceSize]) + } else { // too small to slice at the requested size: don't slice + b.WriteString(sourceToken) + } + case Right: + sourceToken := tokens[tr.dtokmftokindexesargs[i][0]] + sourceTokenLen := len(sourceToken) + sliceSize := int(tr.dtokmfintargs[i]) + if sliceSize > 0 && sliceSize < sourceTokenLen { + b.WriteString(sourceToken[sourceTokenLen-sliceSize : sourceTokenLen]) + } else { // too small to slice at the requested size: don't slice + b.WriteString(sourceToken) + } + } + } + + if i < li { + b.WriteByte(btsep) + } + } + + // We may have more source tokens available. This happens with ">". + if tr.dtoks[len(tr.dtoks)-1] == fwcs { + for sli, i := len(tokens)-1, len(tr.stoks)-1; i < len(tokens); i++ { + b.WriteString(tokens[i]) + if i < sli { + b.WriteByte(btsep) + } + } + } + return b.String() +} + +// Reverse a subjectTransform. +func (tr *subjectTransform) reverse() *subjectTransform { + if len(tr.dtokmftokindexesargs) == 0 { + rtr, _ := NewSubjectTransformStrict(tr.dest, tr.src) + return rtr + } + // If we are here we need to dynamically get the correct reverse + // of this subjectTransform. + nsrc, phs := transformUntokenize(tr.dest) + var nda []string + for _, token := range tr.stoks { + if token == pwcs { + if len(phs) == 0 { + // TODO(dlc) - Should not happen + return nil + } + nda = append(nda, phs[0]) + phs = phs[1:] + } else { + nda = append(nda, token) + } + } + ndest := strings.Join(nda, tsep) + rtr, _ := NewSubjectTransformStrict(nsrc, ndest) + return rtr +} + +// Will share relevant info regarding the subject. +// Returns valid, tokens, num pwcs, has fwc. +func subjectInfo(subject string) (bool, []string, int, bool) { + if subject == "" { + return false, nil, 0, false + } + npwcs := 0 + sfwc := false + tokens := strings.Split(subject, tsep) + for _, t := range tokens { + if len(t) == 0 || sfwc { + return false, nil, 0, false + } + if len(t) > 1 { + continue + } + switch t[0] { + case fwc: + sfwc = true + case pwc: + npwcs++ + } + } + return true, tokens, npwcs, sfwc +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sublist.go b/vendor/github.com/nats-io/nats-server/v2/server/sublist.go index c5785e6..8978698 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/sublist.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sublist.go @@ -1,4 +1,4 @@ -// Copyright 2016-2020 The NATS Authors +// Copyright 2016-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,9 +16,11 @@ package server import ( "bytes" "errors" + "iter" "strings" "sync" "sync/atomic" + "unicode/utf8" ) // Sublist is a routing mechanism to handle subject distribution and @@ -29,7 +31,9 @@ import ( // Common byte variables for wildcards and token separator. const ( pwc = '*' + pwcs = "*" fwc = '>' + fwcs = ">" tsep = "." btsep = '.' ) @@ -46,7 +50,7 @@ const ( // cacheMax is used to bound limit the frontend cache slCacheMax = 1024 // If we run a sweeper we will drain to this count. - slCacheSweep = 512 + slCacheSweep = 256 // plistMin is our lower bounds to create a fast plist for Match. plistMin = 256 ) @@ -82,8 +86,8 @@ type notifyMaps struct { // A node contains subscriptions and a pointer to the next level. type node struct { next *level - psubs map[*subscription]*subscription - qsubs map[string](map[*subscription]*subscription) + psubs map[*subscription]struct{} + qsubs map[string]map[*subscription]struct{} plist []*subscription } @@ -96,7 +100,7 @@ type level struct { // Create a new default node. func newNode() *node { - return &node{psubs: make(map[*subscription]*subscription)} + return &node{psubs: make(map[*subscription]struct{})} } // Create a new default level. @@ -136,13 +140,21 @@ func (s *Sublist) CacheEnabled() bool { } // RegisterNotification will register for notifications when interest for the given -// subject changes. The subject must be a literal publish type subject. The -// notification is true for when the first interest for a subject is inserted, +// subject changes. The subject must be a literal publish type subject. +// The notification is true for when the first interest for a subject is inserted, // and false when all interest in the subject is removed. Note that this interest // needs to be exact and that wildcards will not trigger the notifications. The sublist // will not block when trying to send the notification. Its up to the caller to make // sure the channel send will not block. func (s *Sublist) RegisterNotification(subject string, notify chan<- bool) error { + return s.registerNotification(subject, _EMPTY_, notify) +} + +func (s *Sublist) RegisterQueueNotification(subject, queue string, notify chan<- bool) error { + return s.registerNotification(subject, queue, notify) +} + +func (s *Sublist) registerNotification(subject, queue string, notify chan<- bool) error { if subjectHasWildcard(subject) { return ErrInvalidSubject } @@ -154,21 +166,27 @@ func (s *Sublist) RegisterNotification(subject string, notify chan<- bool) error r := s.Match(subject) if len(r.psubs)+len(r.qsubs) > 0 { - for _, sub := range r.psubs { - if string(sub.subject) == subject { - hasInterest = true - break + if queue == _EMPTY_ { + for _, sub := range r.psubs { + if string(sub.subject) == subject { + hasInterest = true + break + } } - } - for _, qsub := range r.qsubs { - qs := qsub[0] - if string(qs.subject) == subject { - hasInterest = true - break + } else { + for _, qsub := range r.qsubs { + qs := qsub[0] + if string(qs.subject) == subject && string(qs.queue) == queue { + hasInterest = true + break + } } } } + key := keyFromSubjectAndQueue(subject, queue) + var err error + s.Lock() if s.notify == nil { s.notify = ¬ifyMaps{ @@ -176,14 +194,14 @@ func (s *Sublist) RegisterNotification(subject string, notify chan<- bool) error remove: make(map[string][]chan<- bool), } } - - var err error + // Check which list to add us to. if hasInterest { - err = s.addRemoveNotify(subject, notify) + err = s.addRemoveNotify(key, notify) } else { - err = s.addInsertNotify(subject, notify) + err = s.addInsertNotify(key, notify) } s.Unlock() + if err == nil { sendNotification(notify, hasInterest) } @@ -191,14 +209,14 @@ func (s *Sublist) RegisterNotification(subject string, notify chan<- bool) error } // Lock should be held. -func chkAndRemove(subject string, notify chan<- bool, ms map[string][]chan<- bool) bool { - chs := ms[subject] +func chkAndRemove(key string, notify chan<- bool, ms map[string][]chan<- bool) bool { + chs := ms[key] for i, ch := range chs { if ch == notify { chs[i] = chs[len(chs)-1] chs = chs[:len(chs)-1] if len(chs) == 0 { - delete(ms, subject) + delete(ms, key) } return true } @@ -207,14 +225,23 @@ func chkAndRemove(subject string, notify chan<- bool, ms map[string][]chan<- boo } func (s *Sublist) ClearNotification(subject string, notify chan<- bool) bool { + return s.clearNotification(subject, _EMPTY_, notify) +} + +func (s *Sublist) ClearQueueNotification(subject, queue string, notify chan<- bool) bool { + return s.clearNotification(subject, queue, notify) +} + +func (s *Sublist) clearNotification(subject, queue string, notify chan<- bool) bool { s.Lock() if s.notify == nil { s.Unlock() return false } + key := keyFromSubjectAndQueue(subject, queue) // Check both, start with remove. - didRemove := chkAndRemove(subject, notify, s.notify.remove) - didRemove = didRemove || chkAndRemove(subject, notify, s.notify.insert) + didRemove := chkAndRemove(key, notify, s.notify.remove) + didRemove = didRemove || chkAndRemove(key, notify, s.notify.insert) // Check if everything is gone if len(s.notify.remove)+len(s.notify.insert) == 0 { s.notify = nil @@ -247,51 +274,70 @@ func (s *Sublist) addRemoveNotify(subject string, notify chan<- bool) error { func (s *Sublist) addNotify(m map[string][]chan<- bool, subject string, notify chan<- bool) error { chs := m[subject] if len(chs) > 0 { - // Check to see if this chan is alredy registered. + // Check to see if this chan is already registered. for _, ch := range chs { if ch == notify { return ErrAlreadyRegistered } } } + m[subject] = append(chs, notify) return nil } +// To generate a key from subject and queue. We just add spc. +func keyFromSubjectAndQueue(subject, queue string) string { + if len(queue) == 0 { + return subject + } + var sb strings.Builder + sb.WriteString(subject) + sb.WriteString(" ") + sb.WriteString(queue) + return sb.String() +} + // chkForInsertNotification will check to see if we need to notify on this subject. // Write lock should be held. -func (s *Sublist) chkForInsertNotification(subject string) { +func (s *Sublist) chkForInsertNotification(subject, queue string) { + key := keyFromSubjectAndQueue(subject, queue) + // All notify subjects are also literal so just do a hash lookup here. - if chs := s.notify.insert[subject]; len(chs) > 0 { + if chs := s.notify.insert[key]; len(chs) > 0 { for _, ch := range chs { sendNotification(ch, true) } // Move from the insert map to the remove map. - s.notify.remove[subject] = append(s.notify.remove[subject], chs...) - delete(s.notify.insert, subject) + s.notify.remove[key] = append(s.notify.remove[key], chs...) + delete(s.notify.insert, key) } } // chkForRemoveNotification will check to see if we need to notify on this subject. // Write lock should be held. -func (s *Sublist) chkForRemoveNotification(subject string) { - if chs := s.notify.remove[subject]; len(chs) > 0 { +func (s *Sublist) chkForRemoveNotification(subject, queue string) { + key := keyFromSubjectAndQueue(subject, queue) + if chs := s.notify.remove[key]; len(chs) > 0 { // We need to always check that we have no interest anymore. var hasInterest bool r := s.matchNoLock(subject) if len(r.psubs)+len(r.qsubs) > 0 { - for _, sub := range r.psubs { - if string(sub.subject) == subject { - hasInterest = true - break + if queue == _EMPTY_ { + for _, sub := range r.psubs { + if string(sub.subject) == subject { + hasInterest = true + break + } } - } - for _, qsub := range r.qsubs { - qs := qsub[0] - if string(qs.subject) == subject { - hasInterest = true - break + } else { + for _, qsub := range r.qsubs { + qs := qsub[0] + if string(qs.subject) == subject && string(qs.queue) == queue { + hasInterest = true + break + } } } } @@ -300,8 +346,8 @@ func (s *Sublist) chkForRemoveNotification(subject string) { sendNotification(ch, false) } // Move from the remove map to the insert map. - s.notify.insert[subject] = append(s.notify.insert[subject], chs...) - delete(s.notify.remove, subject) + s.notify.insert[key] = append(s.notify.insert[key], chs...) + delete(s.notify.remove, key) } } } @@ -310,16 +356,6 @@ func (s *Sublist) chkForRemoveNotification(subject string) { func (s *Sublist) Insert(sub *subscription) error { // copy the subject since we hold this and this might be part of a large byte slice. subject := string(sub.subject) - tsa := [32]string{} - tokens := tsa[:0] - start := 0 - for i := 0; i < len(subject); i++ { - if subject[i] == btsep { - tokens = append(tokens, subject[start:i]) - start = i + 1 - } - } - tokens = append(tokens, subject[start:]) s.Lock() @@ -327,7 +363,7 @@ func (s *Sublist) Insert(sub *subscription) error { var n *node l := s.root - for _, t := range tokens { + for t := range strings.SplitSeq(subject, tsep) { lt := len(t) if lt == 0 || sfwc { s.Unlock() @@ -349,7 +385,6 @@ func (s *Sublist) Insert(sub *subscription) error { } } if n == nil { - isnew = true n = newNode() if lt > 1 { l.nodes[t] = n @@ -370,28 +405,30 @@ func (s *Sublist) Insert(sub *subscription) error { l = n.next } if sub.queue == nil { - n.psubs[sub] = sub + n.psubs[sub] = struct{}{} + isnew = len(n.psubs) == 1 if n.plist != nil { n.plist = append(n.plist, sub) } else if len(n.psubs) > plistMin { n.plist = make([]*subscription, 0, len(n.psubs)) // Populate - for _, psub := range n.psubs { + for psub := range n.psubs { n.plist = append(n.plist, psub) } } } else { if n.qsubs == nil { - n.qsubs = make(map[string]map[*subscription]*subscription) + n.qsubs = make(map[string]map[*subscription]struct{}) } qname := string(sub.queue) // This is a queue subscription subs, ok := n.qsubs[qname] if !ok { - subs = make(map[*subscription]*subscription) + subs = make(map[*subscription]struct{}) n.qsubs[qname] = subs + isnew = true } - subs[sub] = sub + subs[sub] = struct{}{} } s.count++ @@ -401,7 +438,7 @@ func (s *Sublist) Insert(sub *subscription) error { atomic.AddUint64(&s.genid, 1) if s.notify != nil && isnew && !haswc && len(s.notify.insert) > 0 { - s.chkForInsertNotification(subject) + s.chkForInsertNotification(subject, string(sub.queue)) } s.Unlock() @@ -458,7 +495,7 @@ func (s *Sublist) addToCache(subject string, sub *subscription) { // removeFromCache will remove the sub from any active cache entries. // Assumes write lock is held. -func (s *Sublist) removeFromCache(subject string, sub *subscription) { +func (s *Sublist) removeFromCache(subject string) { if s.cache == nil { return } @@ -481,20 +518,40 @@ var emptyResult = &SublistResult{} // Match will match all entries to the literal subject. // It will return a set of results for both normal and queue subscribers. func (s *Sublist) Match(subject string) *SublistResult { - return s.match(subject, true) + return s.match(subject, true, false) +} + +// MatchBytes will match all entries to the literal subject. +// It will return a set of results for both normal and queue subscribers. +func (s *Sublist) MatchBytes(subject []byte) *SublistResult { + return s.match(bytesToString(subject), true, true) +} + +// HasInterest will return whether or not there is any interest in the subject. +// In cases where more detail is not required, this may be faster than Match. +func (s *Sublist) HasInterest(subject string) bool { + return s.hasInterest(subject, true, nil, nil) +} + +// NumInterest will return the number of subs/qsubs interested in the subject. +// In cases where more detail is not required, this may be faster than Match. +func (s *Sublist) NumInterest(subject string) (np, nq int) { + s.hasInterest(subject, true, &np, &nq) + return } func (s *Sublist) matchNoLock(subject string) *SublistResult { - return s.match(subject, false) + return s.match(subject, false, false) } -func (s *Sublist) match(subject string, doLock bool) *SublistResult { +func (s *Sublist) match(subject string, doLock bool, doCopyOnCache bool) *SublistResult { atomic.AddUint64(&s.matches, 1) // Check cache first. if doLock { s.RLock() } + cacheEnabled := s.cache != nil r, ok := s.cache[subject] if doLock { s.RUnlock() @@ -509,10 +566,16 @@ func (s *Sublist) match(subject string, doLock bool) *SublistResult { start := 0 for i := 0; i < len(subject); i++ { if subject[i] == btsep { + if i-start == 0 { + return emptyResult + } tokens = append(tokens, subject[start:i]) start = i + 1 } } + if start >= len(subject) { + return emptyResult + } tokens = append(tokens, subject[start:]) // FIXME(dlc) - Make shared pool between sublist and client readLoop? @@ -523,7 +586,11 @@ func (s *Sublist) match(subject string, doLock bool) *SublistResult { var n int if doLock { - s.Lock() + if cacheEnabled { + s.Lock() + } else { + s.RLock() + } } matchLevel(s.root, tokens, result) @@ -531,22 +598,78 @@ func (s *Sublist) match(subject string, doLock bool) *SublistResult { if len(result.psubs) == 0 && len(result.qsubs) == 0 { result = emptyResult } - if s.cache != nil { + if cacheEnabled { + if doCopyOnCache { + subject = copyString(subject) + } s.cache[subject] = result n = len(s.cache) } if doLock { - s.Unlock() + if cacheEnabled { + s.Unlock() + } else { + s.RUnlock() + } } // Reduce the cache count if we have exceeded our set maximum. - if n > slCacheMax && atomic.CompareAndSwapInt32(&s.ccSweep, 0, 1) { + if cacheEnabled && n > slCacheMax && atomic.CompareAndSwapInt32(&s.ccSweep, 0, 1) { go s.reduceCacheCount() } return result } +func (s *Sublist) hasInterest(subject string, doLock bool, np, nq *int) bool { + // Check cache first. + if doLock { + s.RLock() + } + var matched bool + if s.cache != nil { + if r, ok := s.cache[subject]; ok { + if np != nil && nq != nil { + *np += len(r.psubs) + for _, qsub := range r.qsubs { + *nq += len(qsub) + } + } + matched = len(r.psubs)+len(r.qsubs) > 0 + } + } + if doLock { + s.RUnlock() + } + if matched { + atomic.AddUint64(&s.cacheHits, 1) + return true + } + + tsa := [32]string{} + tokens := tsa[:0] + start := 0 + for i := 0; i < len(subject); i++ { + if subject[i] == btsep { + if i-start == 0 { + return false + } + tokens = append(tokens, subject[start:i]) + start = i + 1 + } + } + if start >= len(subject) { + return false + } + tokens = append(tokens, subject[start:]) + + if doLock { + s.RLock() + defer s.RUnlock() + } + return matchLevelForAny(s.root, tokens, np, nq) +} + // Remove entries in the cache until we are under the maximum. // TODO(dlc) this could be smarter now that its not inline. func (s *Sublist) reduceCacheCount() { @@ -564,7 +687,7 @@ func (s *Sublist) reduceCacheCount() { // Helper function for auto-expanding remote qsubs. func isRemoteQSub(sub *subscription) bool { - return sub != nil && sub.queue != nil && sub.client != nil && sub.client.kind == ROUTER + return sub != nil && sub.queue != nil && sub.client != nil && (sub.client.kind == ROUTER || sub.client.kind == LEAF) } // UpdateRemoteQSub should be called when we update the weight of an existing @@ -574,7 +697,7 @@ func (s *Sublist) UpdateRemoteQSub(sub *subscription) { // it unless we are thrashing the cache. Just remove from our L2 and update // the genid so L1 will be flushed. s.Lock() - s.removeFromCache(string(sub.subject), sub) + s.removeFromCache(string(sub.subject)) atomic.AddUint64(&s.genid, 1) s.Unlock() } @@ -585,7 +708,7 @@ func addNodeToResults(n *node, results *SublistResult) { if n.plist != nil { results.psubs = append(results.psubs, n.plist...) } else { - for _, psub := range n.psubs { + for psub := range n.psubs { results.psubs = append(results.psubs, psub) } } @@ -601,7 +724,7 @@ func addNodeToResults(n *node, results *SublistResult) { nqsub := make([]*subscription, 0, len(qr)) results.qsubs = append(results.qsubs, nqsub) } - for _, sub := range qr { + for sub := range qr { if isRemoteQSub(sub) { ns := atomic.LoadInt32(&sub.qw) // Shadow these subscriptions @@ -659,6 +782,56 @@ func matchLevel(l *level, toks []string, results *SublistResult) { } } +func matchLevelForAny(l *level, toks []string, np, nq *int) bool { + var pwc, n *node + for i, t := range toks { + if l == nil { + return false + } + if l.fwc != nil { + if np != nil && nq != nil { + *np += len(l.fwc.psubs) + for _, qsub := range l.fwc.qsubs { + *nq += len(qsub) + } + } + return true + } + if pwc = l.pwc; pwc != nil { + if match := matchLevelForAny(pwc.next, toks[i+1:], np, nq); match { + return true + } + } + n = l.nodes[t] + if n != nil { + l = n.next + } else { + l = nil + } + } + if n != nil { + if np != nil && nq != nil { + *np += len(n.psubs) + for _, qsub := range n.qsubs { + *nq += len(qsub) + } + } + if len(n.plist) > 0 || len(n.psubs) > 0 || len(n.qsubs) > 0 { + return true + } + } + if pwc != nil { + if np != nil && nq != nil { + *np += len(pwc.psubs) + for _, qsub := range pwc.qsubs { + *nq += len(qsub) + } + } + return len(pwc.plist) > 0 || len(pwc.psubs) > 0 || len(pwc.qsubs) > 0 + } + return false +} + // lnt is used to track descent into levels for a removal for pruning. type lnt struct { l *level @@ -669,23 +842,13 @@ type lnt struct { // Raw low level remove, can do batches with lock held outside. func (s *Sublist) remove(sub *subscription, shouldLock bool, doCacheUpdates bool) error { subject := string(sub.subject) - tsa := [32]string{} - tokens := tsa[:0] - start := 0 - for i := 0; i < len(subject); i++ { - if subject[i] == btsep { - tokens = append(tokens, subject[start:i]) - start = i + 1 - } - } - tokens = append(tokens, subject[start:]) if shouldLock { s.Lock() defer s.Unlock() } - var sfwc, haswc, last bool + var sfwc, haswc bool var n *node l := s.root @@ -693,7 +856,7 @@ func (s *Sublist) remove(sub *subscription, shouldLock bool, doCacheUpdates bool var lnts [32]lnt levels := lnts[:0] - for _, t := range tokens { + for t := range strings.SplitSeq(subject, tsep) { lt := len(t) if lt == 0 || sfwc { return ErrInvalidSubject @@ -722,7 +885,8 @@ func (s *Sublist) remove(sub *subscription, shouldLock bool, doCacheUpdates bool l = nil } } - if !s.removeFromNode(n, sub) { + removed, last := s.removeFromNode(n, sub) + if !removed { return ErrNotFound } @@ -732,17 +896,16 @@ func (s *Sublist) remove(sub *subscription, shouldLock bool, doCacheUpdates bool for i := len(levels) - 1; i >= 0; i-- { l, n, t := levels[i].l, levels[i].n, levels[i].t if n.isEmpty() { - last = true l.pruneNode(n, t) } } if doCacheUpdates { - s.removeFromCache(subject, sub) + s.removeFromCache(subject) atomic.AddUint64(&s.genid, 1) } if s.notify != nil && last && !haswc && len(s.notify.remove) > 0 { - s.chkForRemoveNotification(subject) + s.chkForRemoveNotification(subject, string(sub.queue)) } return nil @@ -769,9 +932,13 @@ func (s *Sublist) RemoveBatch(subs []*subscription) error { // Turn off our cache if enabled. wasEnabled := s.cache != nil s.cache = nil + // We will try to remove all subscriptions but will report the first that caused + // an error. In other words, we don't bail out at the first error which would + // possibly leave a bunch of subscriptions that could have been removed. + var err error for _, sub := range subs { - if err := s.remove(sub, false, false); err != nil { - return err + if lerr := s.remove(sub, false, false); lerr != nil && err == nil { + err = lerr } } // Turn caching back on here. @@ -779,7 +946,7 @@ func (s *Sublist) RemoveBatch(subs []*subscription) error { if wasEnabled { s.cache = make(map[string]*SublistResult) } - return nil + return err } // pruneNode is used to prune an empty node from the tree. @@ -809,6 +976,9 @@ func (n *node) isEmpty() bool { // Return the number of nodes for the given level. func (l *level) numNodes() int { + if l == nil { + return 0 + } num := len(l.nodes) if l.pwc != nil { num++ @@ -820,9 +990,9 @@ func (l *level) numNodes() int { } // Remove the sub for the given node. -func (s *Sublist) removeFromNode(n *node, sub *subscription) (found bool) { +func (s *Sublist) removeFromNode(n *node, sub *subscription) (found, last bool) { if n == nil { - return false + return false, true } if sub.queue == nil { _, found = n.psubs[sub] @@ -833,7 +1003,7 @@ func (s *Sublist) removeFromNode(n *node, sub *subscription) (found bool) { // to Match as needed. n.plist = nil } - return found + return found, len(n.psubs) == 0 } // We have a queue group subscription here @@ -841,9 +1011,12 @@ func (s *Sublist) removeFromNode(n *node, sub *subscription) (found bool) { _, found = qsub[sub] delete(qsub, sub) if len(qsub) == 0 { + // This is the last queue subscription interest when len(qsub) == 0, not + // when n.qsubs is empty. + last = true delete(n.qsubs, string(sub.queue)) } - return found + return found, last } // Count returns the number of subscriptions. @@ -873,6 +1046,7 @@ type SublistStats struct { AvgFanout float64 `json:"avg_fanout"` totFanout int cacheCnt int + cacheHits uint64 } func (s *SublistStats) add(stat *SublistStats) { @@ -881,7 +1055,7 @@ func (s *SublistStats) add(stat *SublistStats) { s.NumInserts += stat.NumInserts s.NumRemoves += stat.NumRemoves s.NumMatches += stat.NumMatches - s.CacheHitRate += stat.CacheHitRate + s.cacheHits += stat.cacheHits if s.MaxFanout < stat.MaxFanout { s.MaxFanout = stat.MaxFanout } @@ -893,6 +1067,9 @@ func (s *SublistStats) add(stat *SublistStats) { if s.totFanout > 0 { s.AvgFanout = float64(s.totFanout) / float64(s.cacheCnt) } + if s.NumMatches > 0 { + s.CacheHitRate = float64(s.cacheHits) / float64(s.NumMatches) + } } // Stats will return a stats structure for the current state. @@ -909,8 +1086,9 @@ func (s *Sublist) Stats() *SublistStats { st.NumCache = uint32(cc) st.NumMatches = atomic.LoadUint64(&s.matches) + st.cacheHits = atomic.LoadUint64(&s.cacheHits) if st.NumMatches > 0 { - st.CacheHitRate = float64(atomic.LoadUint64(&s.cacheHits)) / float64(st.NumMatches) + st.CacheHitRate = float64(st.cacheHits) / float64(st.NumMatches) } // whip through cache for fanout stats, this can be off if cache is full and doing evictions. @@ -979,7 +1157,16 @@ func visitLevel(l *level, depth int) int { // Determine if a subject has any wildcard tokens. func subjectHasWildcard(subject string) bool { - return !subjectIsLiteral(subject) + // This one exits earlier then !subjectIsLiteral(subject) + for i, c := range subject { + if c == pwc || c == fwc { + if (i == 0 || subject[i-1] == btsep) && + (i+1 == len(subject) || subject[i+1] == btsep) { + return true + } + } + } + return false } // Determine if the subject has any wildcards. Fast version, does not check for @@ -1003,60 +1190,56 @@ func IsValidPublishSubject(subject string) bool { // IsValidSubject returns true if a subject is valid, false otherwise func IsValidSubject(subject string) bool { - if subject == "" { + return isValidSubject(subject, false) +} + +func isValidSubject(subject string, checkRunes bool) bool { + if subject == _EMPTY_ { return false } - sfwc := false - tokens := strings.Split(subject, tsep) - for _, t := range tokens { - if len(t) == 0 || sfwc { + if checkRunes { + // Check if we have embedded nulls. + if bytes.IndexByte(stringToBytes(subject), 0) >= 0 { return false } - if len(t) > 1 { - continue - } - switch t[0] { - case fwc: - sfwc = true + // Since casting to a string will always produce valid UTF-8, we need to look for replacement runes. + // This signals something is off or corrupt. + for _, r := range subject { + if r == utf8.RuneError { + return false + } } } - return true -} - -// Will share relevant info regarding the subject. -// Returns valid, tokens, num pwcs, has fwc. -func subjectInfo(subject string) (bool, []string, int, bool) { - if subject == "" { - return false, nil, 0, false - } - npwcs := 0 sfwc := false - tokens := strings.Split(subject, tsep) - for _, t := range tokens { - if len(t) == 0 || sfwc { - return false, nil, 0, false + for t := range strings.SplitSeq(subject, tsep) { + length := len(t) + if length == 0 || sfwc { + return false } - if len(t) > 1 { + if length > 1 { + if strings.ContainsAny(t, "\t\n\f\r ") { + return false + } continue } switch t[0] { case fwc: sfwc = true - case pwc: - npwcs++ + case ' ', '\t', '\n', '\r', '\f': + return false } } - return true, tokens, npwcs, sfwc + return true } // IsValidLiteralSubject returns true if a subject is valid and literal (no wildcards), false otherwise func IsValidLiteralSubject(subject string) bool { - return isValidLiteralSubject(strings.Split(subject, tsep)) + return isValidLiteralSubject(strings.SplitSeq(subject, tsep)) } // isValidLiteralSubject returns true if the tokens are valid and literal (no wildcards), false otherwise -func isValidLiteralSubject(tokens []string) bool { - for _, t := range tokens { +func isValidLiteralSubject(tokens iter.Seq[string]) bool { + for t := range tokens { if len(t) == 0 { return false } @@ -1071,6 +1254,45 @@ func isValidLiteralSubject(tokens []string) bool { return true } +// ValidateMapping returns nil error if the subject is a valid subject mapping destination subject +func ValidateMapping(src string, dest string) error { + if dest == _EMPTY_ { + return nil + } + sfwc := false + for t := range strings.SplitSeq(dest, tsep) { + length := len(t) + if length == 0 || sfwc { + return &mappingDestinationErr{t, ErrInvalidMappingDestinationSubject} + } + + // if it looks like it contains a mapping function, it should be a valid mapping function + if length > 4 && t[0] == '{' && t[1] == '{' && t[length-2] == '}' && t[length-1] == '}' { + if !partitionMappingFunctionRegEx.MatchString(t) && + !wildcardMappingFunctionRegEx.MatchString(t) && + !splitFromLeftMappingFunctionRegEx.MatchString(t) && + !splitFromRightMappingFunctionRegEx.MatchString(t) && + !sliceFromLeftMappingFunctionRegEx.MatchString(t) && + !sliceFromRightMappingFunctionRegEx.MatchString(t) && + !splitMappingFunctionRegEx.MatchString(t) { + return &mappingDestinationErr{t, ErrUnknownMappingDestinationFunction} + } else { + continue + } + } + + if length == 1 && t[0] == fwc { + sfwc = true + } else if strings.ContainsAny(t, "\t\n\f\r ") { + return ErrInvalidMappingDestinationSubject + } + } + + // Finally, verify that the transform can actually be created from the source and destination + _, err := NewSubjectTransform(src, dest) + return err +} + // Will check tokens and report back if the have any partial or full wildcards. func analyzeTokens(tokens []string) (hasPWC, hasFWC bool) { for _, t := range tokens { @@ -1124,10 +1346,18 @@ func SubjectsCollide(subj1, subj2 string) bool { if !fwc1 && !fwc2 && len(toks1) != len(toks2) { return false } + if lt1, lt2 := len(toks1), len(toks2); lt1 != lt2 { + // If the shorter one only has partials then these will not collide. + if lt1 < lt2 && !fwc1 || lt2 < lt1 && !fwc2 { + return false + } + } + stop := len(toks1) if len(toks2) < stop { stop = len(toks2) } + // We look for reasons to say no. for i := 0; i < stop; i++ { t1, t2 := toks1[i], toks2[i] @@ -1135,6 +1365,7 @@ func SubjectsCollide(subj1, subj2 string) bool { return false } } + return true } @@ -1171,10 +1402,8 @@ func tokenAt(subject string, index uint8) string { return _EMPTY_ } -// Calls into the function isSubsetMatch() -func subjectIsSubsetMatch(subject, test string) bool { - tsa := [32]string{} - tts := tsa[:0] +// use similar to append. meaning, the updated slice will be returned +func tokenizeSubjectIntoSlice(tts []string, subject string) []string { start := 0 for i := 0; i < len(subject); i++ { if subject[i] == btsep { @@ -1183,27 +1412,37 @@ func subjectIsSubsetMatch(subject, test string) bool { } } tts = append(tts, subject[start:]) + return tts +} + +// SubjectMatchesFilter returns true if the subject matches the provided +// filter or false otherwise. +func SubjectMatchesFilter(subject, filter string) bool { + return subjectIsSubsetMatch(subject, filter) +} + +// Calls into the function isSubsetMatch() +func subjectIsSubsetMatch(subject, test string) bool { + tsa := [32]string{} + tts := tokenizeSubjectIntoSlice(tsa[:0], subject) return isSubsetMatch(tts, test) } // This will test a subject as an array of tokens against a test subject -// and determine if the tokens are matched. Both test subject and tokens -// may contain wildcards. So foo.* is a subset match of [">", "*.*", "foo.*"], -// but not of foo.bar, etc. +// Calls into the function isSubsetMatchTokenized func isSubsetMatch(tokens []string, test string) bool { tsa := [32]string{} - tts := tsa[:0] - start := 0 - for i := 0; i < len(test); i++ { - if test[i] == btsep { - tts = append(tts, test[start:i]) - start = i + 1 - } - } - tts = append(tts, test[start:]) + tts := tokenizeSubjectIntoSlice(tsa[:0], test) + return isSubsetMatchTokenized(tokens, tts) +} +// This will test a subject as an array of tokens against a test subject (also encoded as array of tokens) +// and determine if the tokens are matched. Both test subject and tokens +// may contain wildcards. So foo.* is a subset match of [">", "*.*", "foo.*"], +// but not of foo.bar, etc. +func isSubsetMatchTokenized(tokens, test []string) bool { // Walk the target tokens - for i, t2 := range tts { + for i, t2 := range test { if i >= len(tokens) { return false } @@ -1226,7 +1465,7 @@ func isSubsetMatch(tokens []string, test string) bool { if !m { return false } - if i >= len(tts) { + if i >= len(test) { return true } continue @@ -1235,7 +1474,7 @@ func isSubsetMatch(tokens []string, test string) bool { return false } } - return len(tokens) == len(tts) + return len(tokens) == len(test) } // matchLiteral is used to test literal subjects, those that do not have any @@ -1309,51 +1548,54 @@ func matchLiteral(literal, subject string) bool { return li >= ll } -func addLocalSub(sub *subscription, subs *[]*subscription) { - if sub != nil && sub.client != nil && - (sub.client.kind == CLIENT || sub.client.kind == SYSTEM || sub.client.kind == JETSTREAM || sub.client.kind == ACCOUNT) && sub.im == nil { - *subs = append(*subs, sub) +func addLocalSub(sub *subscription, subs *[]*subscription, includeLeafHubs bool) { + if sub != nil && sub.client != nil { + kind := sub.client.kind + if kind == CLIENT || kind == SYSTEM || kind == JETSTREAM || kind == ACCOUNT || + (includeLeafHubs && sub.client.isHubLeafNode() /* implied kind==LEAF */) { + *subs = append(*subs, sub) + } } } -func (s *Sublist) addNodeToSubs(n *node, subs *[]*subscription) { +func (s *Sublist) addNodeToSubs(n *node, subs *[]*subscription, includeLeafHubs bool) { // Normal subscriptions if n.plist != nil { for _, sub := range n.plist { - addLocalSub(sub, subs) + addLocalSub(sub, subs, includeLeafHubs) } } else { - for _, sub := range n.psubs { - addLocalSub(sub, subs) + for sub := range n.psubs { + addLocalSub(sub, subs, includeLeafHubs) } } // Queue subscriptions for _, qr := range n.qsubs { - for _, sub := range qr { - addLocalSub(sub, subs) + for sub := range qr { + addLocalSub(sub, subs, includeLeafHubs) } } } -func (s *Sublist) collectLocalSubs(l *level, subs *[]*subscription) { +func (s *Sublist) collectLocalSubs(l *level, subs *[]*subscription, includeLeafHubs bool) { for _, n := range l.nodes { - s.addNodeToSubs(n, subs) - s.collectLocalSubs(n.next, subs) + s.addNodeToSubs(n, subs, includeLeafHubs) + s.collectLocalSubs(n.next, subs, includeLeafHubs) } if l.pwc != nil { - s.addNodeToSubs(l.pwc, subs) - s.collectLocalSubs(l.pwc.next, subs) + s.addNodeToSubs(l.pwc, subs, includeLeafHubs) + s.collectLocalSubs(l.pwc.next, subs, includeLeafHubs) } if l.fwc != nil { - s.addNodeToSubs(l.fwc, subs) - s.collectLocalSubs(l.fwc.next, subs) + s.addNodeToSubs(l.fwc, subs, includeLeafHubs) + s.collectLocalSubs(l.fwc.next, subs, includeLeafHubs) } } // Return all local client subscriptions. Use the supplied slice. -func (s *Sublist) localSubs(subs *[]*subscription) { +func (s *Sublist) localSubs(subs *[]*subscription, includeLeafHubs bool) { s.RLock() - s.collectLocalSubs(s.root, subs) + s.collectLocalSubs(s.root, subs, includeLeafHubs) s.RUnlock() } @@ -1369,13 +1611,13 @@ func (s *Sublist) addAllNodeToSubs(n *node, subs *[]*subscription) { if n.plist != nil { *subs = append(*subs, n.plist...) } else { - for _, sub := range n.psubs { + for sub := range n.psubs { *subs = append(*subs, sub) } } // Queue subscriptions for _, qr := range n.qsubs { - for _, sub := range qr { + for sub := range qr { *subs = append(*subs, sub) } } @@ -1417,22 +1659,22 @@ func (s *Sublist) ReverseMatch(subject string) *SublistResult { result := &SublistResult{} - s.Lock() + s.RLock() reverseMatchLevel(s.root, tokens, nil, result) // Check for empty result. if len(result.psubs) == 0 && len(result.qsubs) == 0 { result = emptyResult } - s.Unlock() + s.RUnlock() return result } func reverseMatchLevel(l *level, toks []string, n *node, results *SublistResult) { + if l == nil { + return + } for i, t := range toks { - if l == nil { - return - } if len(t) == 1 { if t[0] == fwc { getAllNodes(l, results) @@ -1441,9 +1683,22 @@ func reverseMatchLevel(l *level, toks []string, n *node, results *SublistResult) for _, n := range l.nodes { reverseMatchLevel(n.next, toks[i+1:], n, results) } + if l.pwc != nil { + reverseMatchLevel(l.pwc.next, toks[i+1:], n, results) + } + if l.fwc != nil { + getAllNodes(l, results) + } return } } + // If the sub tree has a fwc at this position, match as well. + if l.fwc != nil { + getAllNodes(l, results) + return + } else if l.pwc != nil { + reverseMatchLevel(l.pwc.next, toks[i+1:], n, results) + } n = l.nodes[t] if n == nil { break @@ -1459,6 +1714,12 @@ func getAllNodes(l *level, results *SublistResult) { if l == nil { return } + if l.pwc != nil { + addNodeToResults(l.pwc, results) + } + if l.fwc != nil { + addNodeToResults(l.fwc, results) + } for _, n := range l.nodes { addNodeToResults(n, results) getAllNodes(n.next, results) diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_bsd.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_bsd.go index f62a7d2..46aaf99 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_bsd.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_bsd.go @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build freebsd openbsd dragonfly netbsd +//go:build freebsd || openbsd || dragonfly || netbsd package sysmem diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_darwin.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_darwin.go index e5cce83..e2dee28 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_darwin.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_darwin.go @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build darwin +//go:build darwin package sysmem diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_linux.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_linux.go index 6842a15..2d15e5b 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_linux.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_linux.go @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux +//go:build linux package sysmem diff --git a/vendor/github.com/nats-io/nats-server/v2/server/fuzz.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_solaris.go similarity index 51% rename from vendor/github.com/nats-io/nats-server/v2/server/fuzz.go rename to vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_solaris.go index 1f62698..afba036 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/fuzz.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_solaris.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,37 +11,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build gofuzz +//go:build illumos || solaris -package server +package sysmem -var defaultServerOptions = Options{ - Host: "127.0.0.1", - Trace: true, - Debug: true, - DisableShortFirstPing: true, - NoLog: true, - NoSigs: true, -} +import ( + "golang.org/x/sys/unix" +) -func dummyClient() *client { - return &client{srv: New(&defaultServerOptions), msubs: -1, mpay: -1, mcl: MAX_CONTROL_LINE_SIZE} -} +const ( + _SC_PHYS_PAGES = 500 + _SC_PAGESIZE = 11 +) -func FuzzClient(data []byte) int { - if len(data) < 100 { - return -1 - } - c := dummyClient() - - err := c.parse(data[:50]) +func Memory() int64 { + pages, err := unix.Sysconf(_SC_PHYS_PAGES) if err != nil { return 0 } - - err = c.parse(data[50:]) + pageSize, err := unix.Sysconf(_SC_PAGESIZE) if err != nil { return 0 } - return 1 + return int64(pages) * int64(pageSize) } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_wasm.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_wasm.go new file mode 100644 index 0000000..bde3586 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_wasm.go @@ -0,0 +1,21 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build wasm + +package sysmem + +func Memory() int64 { + // TODO: We don't know the system memory + return 0 +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_windows.go index 8bf8897..9fcb0ea 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_windows.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_windows.go @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,15 +11,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build windows +//go:build windows package sysmem import ( - "syscall" "unsafe" + + "golang.org/x/sys/windows" ) +var winKernel32 = windows.NewLazySystemDLL("kernel32.dll") +var winGlobalMemoryStatusEx = winKernel32.NewProc("GlobalMemoryStatusEx") + +func init() { + if err := winKernel32.Load(); err != nil { + panic(err) + } + if err := winGlobalMemoryStatusEx.Find(); err != nil { + panic(err) + } +} + // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-memorystatusex type _memoryStatusEx struct { dwLength uint32 @@ -29,16 +42,8 @@ type _memoryStatusEx struct { } func Memory() int64 { - kernel32, err := syscall.LoadDLL("kernel32.dll") - if err != nil { - return 0 - } - globalMemoryStatusEx, err := kernel32.FindProc("GlobalMemoryStatusEx") - if err != nil { - return 0 - } msx := &_memoryStatusEx{dwLength: 64} - res, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx))) + res, _, _ := winGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msx))) if res == 0 { return 0 } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_zos.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_zos.go new file mode 100644 index 0000000..f8db5c5 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/mem_zos.go @@ -0,0 +1,21 @@ +// Copyright 2022-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build zos + +package sysmem + +func Memory() int64 { + // TODO: We don't know the system memory + return 0 +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/sysctl.go b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/sysctl.go index e70e037..fd6a41d 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/sysmem/sysctl.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/sysmem/sysctl.go @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build darwin freebsd openbsd dragonfly netbsd +//go:build darwin || freebsd || openbsd || dragonfly || netbsd package sysmem @@ -25,7 +25,9 @@ func sysctlInt64(name string) int64 { if err != nil { return 0 } - // hack because the string conversion above drops a \0 - b := []byte(s) + // Make sure it's 8 bytes when we do the cast below. + // We were getting fatal error: checkptr: converted pointer straddles multiple allocations in go 1.22.1 on darwin. + var b [8]byte + copy(b[:], s) return *(*int64)(unsafe.Pointer(&b[0])) } diff --git a/vendor/github.com/nats-io/nats-server/v2/server/thw/thw.go b/vendor/github.com/nats-io/nats-server/v2/server/thw/thw.go new file mode 100644 index 0000000..77e909d --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/thw/thw.go @@ -0,0 +1,241 @@ +// Copyright 2024-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package thw + +import ( + "encoding/binary" + "errors" + "io" + "math" + "time" +) + +// Error for when we can not locate a task for removal or updates. +var ErrTaskNotFound = errors.New("thw: task not found") + +// Error for when we try to decode a binary-encoded THW with an unknown version number. +var ErrInvalidVersion = errors.New("thw: encoded version not known") + +const ( + tickDuration = int64(time.Second) // Tick duration in nanoseconds. + wheelBits = 12 // 2^12 = 4096 slots. + wheelSize = 1 << wheelBits // Number of slots in the wheel. + wheelMask = wheelSize - 1 // Mask for calculating position. + headerLen = 17 // 1 byte magic + 2x uint64s +) + +// slot represents a single slot in the wheel. +type slot struct { + entries map[uint64]int64 // Map of sequence to expires. + lowest int64 // Lowest expiration time in this slot. +} + +// HashWheel represents the timing wheel. +type HashWheel struct { + wheel []*slot // Array of slots. + lowest int64 // Track the lowest expiration time across all slots. + count uint64 // How many entries are present? +} + +// HashWheelEntry represents a single entry in the wheel. +type HashWheelEntry struct { + Seq uint64 + Expires int64 +} + +// NewHashWheel initializes a new HashWheel. +func NewHashWheel() *HashWheel { + return &HashWheel{ + wheel: make([]*slot, wheelSize), + lowest: math.MaxInt64, + } +} + +// getPosition calculates the slot position for a given expiration time. +func (hw *HashWheel) getPosition(expires int64) int64 { + return (expires / tickDuration) & wheelMask +} + +// newSlot creates a new slot. +func newSlot() *slot { + return &slot{ + entries: make(map[uint64]int64), + lowest: math.MaxInt64, + } +} + +// Add schedules a new timer task. +func (hw *HashWheel) Add(seq uint64, expires int64) error { + pos := hw.getPosition(expires) + // Initialize the slot lazily. + if hw.wheel[pos] == nil { + hw.wheel[pos] = newSlot() + } + if _, ok := hw.wheel[pos].entries[seq]; !ok { + hw.count++ + } + hw.wheel[pos].entries[seq] = expires + + // Update slot's lowest expiration if this is earlier. + if expires < hw.wheel[pos].lowest { + hw.wheel[pos].lowest = expires + // Update global lowest if this is now the earliest. + if expires < hw.lowest { + hw.lowest = expires + } + } + + return nil +} + +// Remove removes a timer task. +func (hw *HashWheel) Remove(seq uint64, expires int64) error { + pos := hw.getPosition(expires) + s := hw.wheel[pos] + if s == nil { + return ErrTaskNotFound + } + if _, exists := s.entries[seq]; !exists { + return ErrTaskNotFound + } + delete(s.entries, seq) + hw.count-- + + // If the slot is empty, we can set it to nil to free memory. + if len(s.entries) == 0 { + hw.wheel[pos] = nil + } + return nil +} + +// Update updates the expiration time of an existing timer task. +func (hw *HashWheel) Update(seq uint64, oldExpires int64, newExpires int64) error { + // Remove from old position. + if err := hw.Remove(seq, oldExpires); err != nil { + return err + } + // Add to new position. + return hw.Add(seq, newExpires) +} + +// ExpireTasks processes all expired tasks using a callback, but only expires a task if the callback returns true. +func (hw *HashWheel) ExpireTasks(callback func(seq uint64, expires int64) bool) { + now := time.Now().UnixNano() + hw.expireTasks(now, callback) +} + +func (hw *HashWheel) expireTasks(ts int64, callback func(seq uint64, expires int64) bool) { + // Quick return if nothing is expired. + if hw.lowest > ts { + return + } + + globalLowest := int64(math.MaxInt64) + for pos, s := range hw.wheel { + // Skip s if nothing to expire. + if s == nil || s.lowest > ts { + if s != nil && s.lowest < globalLowest { + globalLowest = s.lowest + } + continue + } + + // Track new lowest while processing expirations + slotLowest := int64(math.MaxInt64) + for seq, expires := range s.entries { + if expires <= ts && callback(seq, expires) { + delete(s.entries, seq) + hw.count-- + continue + } + if expires < slotLowest { + slotLowest = expires + } + } + + // Nil out if we are empty. + if len(s.entries) == 0 { + hw.wheel[pos] = nil + } else { + s.lowest = slotLowest + if slotLowest < globalLowest { + globalLowest = slotLowest + } + } + } + hw.lowest = globalLowest +} + +// GetNextExpiration returns the earliest expiration time before the given time. +// Returns math.MaxInt64 if no expirations exist before the specified time. +func (hw *HashWheel) GetNextExpiration(before int64) int64 { + if hw.lowest < before { + return hw.lowest + } + return math.MaxInt64 +} + +// Count returns the amount of tasks in the THW. +func (hw *HashWheel) Count() uint64 { + return hw.count +} + +// AppendEncode writes out the contents of the THW into a binary snapshot +// and returns it. The high seq number is included in the snapshot and will +// be returned on decode. +func (hw *HashWheel) Encode(highSeq uint64) []byte { + b := make([]byte, 0, headerLen+(hw.count*(2*binary.MaxVarintLen64))) + b = append(b, 1) // Magic version + b = binary.LittleEndian.AppendUint64(b, hw.count) // Entry count + b = binary.LittleEndian.AppendUint64(b, highSeq) // Stamp + for _, slot := range hw.wheel { + if slot == nil || slot.entries == nil { + continue + } + for v, ts := range slot.entries { + b = binary.AppendVarint(b, ts) + b = binary.AppendUvarint(b, v) + } + } + return b +} + +// Decode snapshots a binary-encoded THW and replaces the contents of this +// THW with them. Returns the high seq number from the snapshot. +func (hw *HashWheel) Decode(b []byte) (uint64, error) { + if len(b) < headerLen { + return 0, io.ErrShortBuffer + } + if b[0] != 1 { + return 0, ErrInvalidVersion + } + hw.wheel = make([]*slot, wheelSize) + hw.lowest = math.MaxInt64 + count := binary.LittleEndian.Uint64(b[1:]) + stamp := binary.LittleEndian.Uint64(b[9:]) + b = b[headerLen:] + for i := uint64(0); i < count; i++ { + ts, tn := binary.Varint(b) + if tn < 0 { + return 0, io.ErrUnexpectedEOF + } + v, vn := binary.Uvarint(b[tn:]) + if vn < 0 { + return 0, io.ErrUnexpectedEOF + } + hw.Add(v, ts) + b = b[tn+vn:] + } + return stamp, nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/tpm/js_ek_tpm_other.go b/vendor/github.com/nats-io/nats-server/v2/server/tpm/js_ek_tpm_other.go new file mode 100644 index 0000000..a1ed593 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/tpm/js_ek_tpm_other.go @@ -0,0 +1,23 @@ +// Copyright 2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !windows + +package tpm + +import "fmt" + +// LoadJetStreamEncryptionKeyFromTPM here is a stub for unsupported platforms. +func LoadJetStreamEncryptionKeyFromTPM(srkPassword, jsKeyFile, jsKeyPassword string, pcr int) (string, error) { + return "", fmt.Errorf("TPM functionality is not supported on this platform") +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/tpm/js_ek_tpm_windows.go b/vendor/github.com/nats-io/nats-server/v2/server/tpm/js_ek_tpm_windows.go new file mode 100644 index 0000000..5e40168 --- /dev/null +++ b/vendor/github.com/nats-io/nats-server/v2/server/tpm/js_ek_tpm_windows.go @@ -0,0 +1,281 @@ +// Copyright 2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows + +package tpm + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + + "github.com/google/go-tpm/legacy/tpm2" + "github.com/google/go-tpm/tpmutil" + "github.com/nats-io/nkeys" +) + +var ( + // Version of the NATS TPM JS implmentation + JsKeyTPMVersion = 1 +) + +// How this works: +// Create a Storage Root Key (SRK) in the TPM. +// If existing JS Encryption keys do not exist on disk. +// - Create a JetStream encryption key (js key) and seal it to the SRK +// using a provided js encryption key password. +// - Save the public and private blobs to a file on disk. +// - Return the new js encryption key (the private portion of the nkey) +// Otherwise (keys exist on disk) +// - Read the public and private blobs from disk +// - Load them into the TPM +// - Unseal the js key using the TPM, and the provided js encryption keys password. +// +// Note: a SRK password for the SRK is supported but not tested here. + +// Gets/Regenerates the Storage Root Key (SRK) from the TPM. Caller MUST flush this handle when done. +func regenerateSRK(rwc io.ReadWriteCloser, srkPassword string) (tpmutil.Handle, error) { + // Default EK template defined in: + // https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf + // Shared SRK template based off of EK template and specified in: + // https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf + srkTemplate := tpm2.Public{ + Type: tpm2.AlgRSA, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth | tpm2.FlagRestricted | tpm2.FlagDecrypt | tpm2.FlagNoDA, + AuthPolicy: nil, + // We must use RSA 2048 for the intel TSS2 stack + RSAParameters: &tpm2.RSAParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + KeyBits: 2048, + ModulusRaw: make([]byte, 256), + }, + } + // Create the parent key against which to seal the data + srkHandle, _, err := tpm2.CreatePrimary(rwc, tpm2.HandleOwner, tpm2.PCRSelection{}, "", srkPassword, srkTemplate) + return srkHandle, err +} + +type natsTPMPersistedKeys struct { + Version int `json:"version"` + PrivateKey []byte `json:"private_key"` + PublicKey []byte `json:"public_key"` +} + +// Writes the private and public blobs to disk in a single file. If the directory does +// not exist, it will be created. If the file already exists it will be overwritten. +func writeTPMKeysToFile(filename string, privateBlob []byte, publicBlob []byte) error { + keyDir := filepath.Dir(filename) + if err := os.MkdirAll(keyDir, 0750); err != nil { + return fmt.Errorf("unable to create/access directory %q: %v", keyDir, err) + } + + // Create a new set of persisted keys. Note that the private key doesn't necessarily + // need to be protected as the TPM password is required to use unseal, although it's + // a good idea to put this in a secure location accessible to the server. + tpmKeys := natsTPMPersistedKeys{ + Version: JsKeyTPMVersion, + PrivateKey: make([]byte, base64.StdEncoding.EncodedLen(len(privateBlob))), + PublicKey: make([]byte, base64.StdEncoding.EncodedLen(len(publicBlob))), + } + base64.StdEncoding.Encode(tpmKeys.PrivateKey, privateBlob) + base64.StdEncoding.Encode(tpmKeys.PublicKey, publicBlob) + // Convert to JSON + keysJSON, err := json.Marshal(tpmKeys) + if err != nil { + return fmt.Errorf("unable to marshal keys to JSON: %v", err) + } + // Write the JSON to a file + if err := os.WriteFile(filename, keysJSON, 0640); err != nil { + return fmt.Errorf("unable to write keys file to %q: %v", filename, err) + } + return nil +} + +// Reads the private and public blobs from a single file. If the file does not exist, +// or the file cannot be read and the keys decoded, an error is returned. +func readTPMKeysFromFile(filename string) ([]byte, []byte, error) { + keysJSON, err := os.ReadFile(filename) + if err != nil { + return nil, nil, err + } + + var tpmKeys natsTPMPersistedKeys + if err := json.Unmarshal(keysJSON, &tpmKeys); err != nil { + return nil, nil, fmt.Errorf("unable to unmarshal TPM file keys JSON from %s: %v", filename, err) + } + + // Placeholder for future-proofing. Here is where we would + // check the current version against tpmKeys.Version and + // handle any changes. + + // Base64 decode the private and public blobs. + privateBlob := make([]byte, base64.StdEncoding.DecodedLen(len(tpmKeys.PrivateKey))) + publicBlob := make([]byte, base64.StdEncoding.DecodedLen(len(tpmKeys.PublicKey))) + prn, err := base64.StdEncoding.Decode(privateBlob, tpmKeys.PrivateKey) + if err != nil { + return nil, nil, fmt.Errorf("unable to decode privateBlob from base64: %v", err) + } + pun, err := base64.StdEncoding.Decode(publicBlob, tpmKeys.PublicKey) + if err != nil { + return nil, nil, fmt.Errorf("unable to decode publicBlob from base64: %v", err) + } + return publicBlob[:pun], privateBlob[:prn], nil +} + +// Creates a new JetStream encryption key, seals it to the TPM, and saves the public and +// private blobs to disk in a JSON encoded file. The key is returned as a string. +func createAndSealJsEncryptionKey(rwc io.ReadWriteCloser, srkHandle tpmutil.Handle, srkPassword, jsKeyFile, jsKeyPassword string, pcr int) (string, error) { + // Get the authorization policy that will protect the data to be sealed + sessHandle, policy, err := policyPCRPasswordSession(rwc, pcr) + if err != nil { + return "", fmt.Errorf("unable to get policy: %v", err) + } + if err := tpm2.FlushContext(rwc, sessHandle); err != nil { + return "", fmt.Errorf("unable to flush session: %v", err) + } + // Seal the data to the parent key and the policy + user, err := nkeys.CreateUser() + if err != nil { + return "", fmt.Errorf("unable to create seed: %v", err) + } + // We'll use the seed to represent the encryption key. + jsStoreKey, err := user.Seed() + if err != nil { + return "", fmt.Errorf("unable to get seed: %v", err) + } + privateArea, publicArea, err := tpm2.Seal(rwc, srkHandle, srkPassword, jsKeyPassword, policy, jsStoreKey) + if err != nil { + return "", fmt.Errorf("unable to seal data: %v", err) + } + err = writeTPMKeysToFile(jsKeyFile, privateArea, publicArea) + if err != nil { + return "", fmt.Errorf("unable to write key file: %v", err) + } + return string(jsStoreKey), nil +} + +// Unseals the JetStream encryption key from the TPM with the provided keys. +// The key is returned as a string. +func unsealJsEncrpytionKey(rwc io.ReadWriteCloser, pcr int, srkHandle tpmutil.Handle, srkPassword, objectPassword string, publicBlob, privateBlob []byte) (string, error) { + // Load the public/private blobs into the TPM for decryption. + objectHandle, _, err := tpm2.Load(rwc, srkHandle, srkPassword, publicBlob, privateBlob) + if err != nil { + return "", fmt.Errorf("unable to load data: %v", err) + } + defer tpm2.FlushContext(rwc, objectHandle) + + // Create the authorization session with TPM. + sessHandle, _, err := policyPCRPasswordSession(rwc, pcr) + if err != nil { + return "", fmt.Errorf("unable to get auth session: %v", err) + } + defer func() { + tpm2.FlushContext(rwc, sessHandle) + }() + // Unseal the data we've loaded into the TPM with the object (js key) password. + unsealedData, err := tpm2.UnsealWithSession(rwc, sessHandle, objectHandle, objectPassword) + if err != nil { + return "", fmt.Errorf("unable to unseal data: %v", err) + } + return string(unsealedData), nil +} + +// Returns session handle and policy digest. +func policyPCRPasswordSession(rwc io.ReadWriteCloser, pcr int) (sessHandle tpmutil.Handle, policy []byte, retErr error) { + sessHandle, _, err := tpm2.StartAuthSession( + rwc, + tpm2.HandleNull, /*tpmKey*/ + tpm2.HandleNull, /*bindKey*/ + make([]byte, 16), /*nonceCaller*/ + nil, /*secret*/ + tpm2.SessionPolicy, + tpm2.AlgNull, + tpm2.AlgSHA256) + if err != nil { + return tpm2.HandleNull, nil, fmt.Errorf("unable to start session: %v", err) + } + defer func() { + if sessHandle != tpm2.HandleNull && err != nil { + if err := tpm2.FlushContext(rwc, sessHandle); err != nil { + retErr = fmt.Errorf("%v\nunable to flush session: %v", retErr, err) + } + } + }() + + pcrSelection := tpm2.PCRSelection{ + Hash: tpm2.AlgSHA256, + PCRs: []int{pcr}, + } + if err := tpm2.PolicyPCR(rwc, sessHandle, nil, pcrSelection); err != nil { + return sessHandle, nil, fmt.Errorf("unable to bind PCRs to auth policy: %v", err) + } + if err := tpm2.PolicyPassword(rwc, sessHandle); err != nil { + return sessHandle, nil, fmt.Errorf("unable to require password for auth policy: %v", err) + } + policy, err = tpm2.PolicyGetDigest(rwc, sessHandle) + if err != nil { + return sessHandle, nil, fmt.Errorf("unable to get policy digest: %v", err) + } + return sessHandle, policy, nil +} + +// LoadJetStreamEncryptionKeyFromTPM loads the JetStream encryption key from the TPM. +// If the keyfile does not exist, a key will be created and sealed. Public and private blobs +// used to decrypt the key in future sessions will be saved to disk in the file provided. +// The key will be unsealed and returned only with the correct password and PCR value. +func LoadJetStreamEncryptionKeyFromTPM(srkPassword, jsKeyFile, jsKeyPassword string, pcr int) (string, error) { + rwc, err := tpm2.OpenTPM() + if err != nil { + return "", fmt.Errorf("could not open the TPM: %v", err) + } + defer rwc.Close() + + // Load the key from the TPM + srkHandle, err := regenerateSRK(rwc, srkPassword) + defer func() { + tpm2.FlushContext(rwc, srkHandle) + }() + if err != nil { + return "", fmt.Errorf("unable to regenerate SRK from the TPM: %v", err) + } + // Read the keys from the key file. If the filed doesn't exist it means we need to create + // a new js encrytpion key. + publicBlob, privateBlob, err := readTPMKeysFromFile(jsKeyFile) + if err != nil { + if os.IsNotExist(err) { + jsek, err := createAndSealJsEncryptionKey(rwc, srkHandle, srkPassword, jsKeyFile, jsKeyPassword, pcr) + if err != nil { + return "", fmt.Errorf("unable to generate new key from the TPM: %v", err) + } + // we've created and sealed the JS Encryption key, now we just return it. + return jsek, nil + } + return "", fmt.Errorf("unable to load key from TPM: %v", err) + } + + // Unseal the JetStream encryption key using the TPM. + jsek, err := unsealJsEncrpytionKey(rwc, pcr, srkHandle, srkPassword, jsKeyPassword, publicBlob, privateBlob) + if err != nil { + return "", fmt.Errorf("unable to unseal key from the TPM: %v", err) + } + return jsek, nil +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/util.go b/vendor/github.com/nats-io/nats-server/v2/server/util.go index 88b3f63..98cc102 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/util.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/util.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,13 +14,16 @@ package server import ( + "bytes" "context" + "encoding/json" "errors" "fmt" "math" "net" "net/url" "reflect" + "runtime" "strconv" "strings" "time" @@ -36,6 +39,44 @@ const ( asciiNine = 57 ) +func versionComponents(version string) (major, minor, patch int, err error) { + m := semVerRe.FindStringSubmatch(version) + if len(m) == 0 { + return 0, 0, 0, errors.New("invalid semver") + } + major, err = strconv.Atoi(m[1]) + if err != nil { + return -1, -1, -1, err + } + minor, err = strconv.Atoi(m[2]) + if err != nil { + return -1, -1, -1, err + } + patch, err = strconv.Atoi(m[3]) + if err != nil { + return -1, -1, -1, err + } + return major, minor, patch, err +} + +func versionAtLeastCheckError(version string, emajor, eminor, epatch int) (bool, error) { + major, minor, patch, err := versionComponents(version) + if err != nil { + return false, err + } + if major > emajor || + (major == emajor && minor > eminor) || + (major == emajor && minor == eminor && patch >= epatch) { + return true, nil + } + return false, err +} + +func versionAtLeast(version string, emajor, eminor, epatch int) bool { + res, _ := versionAtLeastCheckError(version, emajor, eminor, epatch) + return res +} + // parseSize expects decimal positive numbers. We // return -1 to signal error. func parseSize(d []byte) (n int) { @@ -221,3 +262,104 @@ func natsDialTimeout(network, address string, timeout time.Duration) (net.Conn, } return d.Dial(network, address) } + +// redactURLList() returns a copy of a list of URL pointers where each item +// in the list will either be the same pointer if the URL does not contain a +// password, or to a new object if there is a password. +// The intended use-case is for logging lists of URLs safely. +func redactURLList(unredacted []*url.URL) []*url.URL { + r := make([]*url.URL, len(unredacted)) + // In the common case of no passwords, if we don't let the new object leave + // this function then GC should be easier. + needCopy := false + for i := range unredacted { + if unredacted[i] == nil { + r[i] = nil + continue + } + if _, has := unredacted[i].User.Password(); !has { + r[i] = unredacted[i] + continue + } + needCopy = true + ru := *unredacted[i] + ru.User = url.UserPassword(ru.User.Username(), "xxxxx") + r[i] = &ru + } + if needCopy { + return r + } + return unredacted +} + +// redactURLString() attempts to redact a URL string. +func redactURLString(raw string) string { + if !strings.ContainsRune(raw, '@') { + return raw + } + u, err := url.Parse(raw) + if err != nil { + return raw + } + return u.Redacted() +} + +// getURLsAsString returns a slice of u.Host from the given slice of url.URL's +func getURLsAsString(urls []*url.URL) []string { + a := make([]string, 0, len(urls)) + for _, u := range urls { + a = append(a, u.Host) + } + return a +} + +// copyBytes make a new slice of the same size than `src` and copy its content. +// If `src` is nil or its length is 0, then this returns `nil` +func copyBytes(src []byte) []byte { + if len(src) == 0 { + return nil + } + dst := make([]byte, len(src)) + copy(dst, src) + return dst +} + +// copyStrings make a new slice of the same size than `src` and copy its content. +// If `src` is nil, then this returns `nil` +func copyStrings(src []string) []string { + if src == nil { + return nil + } + dst := make([]string, len(src)) + copy(dst, src) + return dst +} + +// Returns a byte slice for the INFO protocol. +func generateInfoJSON(info *Info) []byte { + b, _ := json.Marshal(info) + pcs := [][]byte{[]byte("INFO"), b, []byte(CR_LF)} + return bytes.Join(pcs, []byte(" ")) +} + +// parallelTaskQueue starts a number of goroutines and returns a channel +// which functions can be sent to for queued parallel execution. The +// goroutines will stop running when the returned channel is closed and +// all queued tasks have completed. The passed in mp limits concurrency, +// or a value <= 0 will default to GOMAXPROCS. +func parallelTaskQueue(mp int) chan<- func() { + if rmp := runtime.GOMAXPROCS(-1); mp <= 0 { + mp = rmp + } else { + mp = max(rmp, mp) + } + tq := make(chan func(), mp) + for range mp { + go func() { + for fn := range tq { + fn() + } + }() + } + return tq +} diff --git a/vendor/github.com/nats-io/nats-server/v2/server/websocket.go b/vendor/github.com/nats-io/nats-server/v2/server/websocket.go index 901b401..572affa 100644 --- a/vendor/github.com/nats-io/nats-server/v2/server/websocket.go +++ b/vendor/github.com/nats-io/nats-server/v2/server/websocket.go @@ -1,4 +1,4 @@ -// Copyright 2020 The NATS Authors +// Copyright 2020-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,7 +15,7 @@ package server import ( "bytes" - "compress/flate" + crand "crypto/rand" "crypto/sha1" "crypto/tls" "encoding/base64" @@ -23,16 +23,19 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" + mrand "math/rand" "net" "net/http" "net/url" "strconv" "strings" "sync" + "sync/atomic" "time" "unicode/utf8" + + "github.com/klauspost/compress/flate" ) type wsOpCode int @@ -53,9 +56,11 @@ const ( wsMaskBit = 1 << 7 wsContinuationFrame = 0 - wsMaxFrameHeaderSize = 10 // For a server-to-client frame + wsMaxFrameHeaderSize = 14 // Since LeafNode may need to behave as a client wsMaxControlPayloadSize = 125 wsFrameSizeForBrowsers = 4096 // From experiment, webrowsers behave better with limited frame size + wsCompressThreshold = 64 // Don't compress for small buffer(s) + wsCloseSatusSize = 2 // From https://tools.ietf.org/html/rfc6455#section-11.7 wsCloseStatusNormalClosure = 1000 @@ -63,7 +68,6 @@ const ( wsCloseStatusProtocolError = 1002 wsCloseStatusUnsupportedData = 1003 wsCloseStatusNoStatusReceived = 1005 - wsCloseStatusAbnormalClosure = 1006 wsCloseStatusInvalidPayloadData = 1007 wsCloseStatusPolicyViolation = 1008 wsCloseStatusMessageTooBig = 1009 @@ -73,36 +77,69 @@ const ( wsFirstFrame = true wsContFrame = false wsFinalFrame = true - wsCompressedFrame = true wsUncompressedFrame = false + + wsSchemePrefix = "ws" + wsSchemePrefixTLS = "wss" + + wsNoMaskingHeader = "Nats-No-Masking" + wsNoMaskingValue = "true" + wsXForwardedForHeader = "X-Forwarded-For" + wsNoMaskingFullResponse = wsNoMaskingHeader + ": " + wsNoMaskingValue + CR_LF + wsPMCExtension = "permessage-deflate" // per-message compression + wsPMCSrvNoCtx = "server_no_context_takeover" + wsPMCCliNoCtx = "client_no_context_takeover" + wsPMCReqHeaderValue = wsPMCExtension + "; " + wsPMCSrvNoCtx + "; " + wsPMCCliNoCtx + wsPMCFullResponse = "Sec-WebSocket-Extensions: " + wsPMCExtension + "; " + wsPMCSrvNoCtx + "; " + wsPMCCliNoCtx + _CRLF_ + wsSecProto = "Sec-Websocket-Protocol" + wsMQTTSecProtoVal = "mqtt" + wsMQTTSecProto = wsSecProto + ": " + wsMQTTSecProtoVal + CR_LF ) var decompressorPool sync.Pool +var compressLastBlock = []byte{0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff} // From https://tools.ietf.org/html/rfc6455#section-1.3 var wsGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") +// Test can enable this so that server does not support "no-masking" requests. +var wsTestRejectNoMasking = false + type websocket struct { - frames net.Buffers - fs int64 - closeMsg []byte - compress bool - closeSent bool - browser bool - compressor *flate.Writer - cookieJwt string + frames net.Buffers + fs int64 + closeMsg []byte + compress bool + closeSent bool + browser bool + nocompfrag bool // No fragment for compressed frames + maskread bool + maskwrite bool + compressor *flate.Writer + cookieJwt string + cookieUsername string + cookiePassword string + cookieToken string + clientIP string } type srvWebsocket struct { mu sync.RWMutex server *http.Server listener net.Listener - tls bool + listenerErr error allowedOrigins map[string]*allowedOrigin // host will be the key sameOrigin bool connectURLs []string connectURLsMap refCountedUrlSet - authOverride bool // indicate if there is auth override in websocket config + authOverride bool // indicate if there is auth override in websocket config + rawHeaders string // raw headers to be used in the upgrade response. + + // These are immutable and can be accessed without lock. + // This is the case when generating the client INFO. + tls bool // True if TLS is required (TLSConfig is specified). + host string // Host/IP the webserver is listening on (shortcut to opts.Websocket.Host). + port int // Port the webserver is listening on. This is after an ephemeral port may have been selected (shortcut to opts.Websocket.Port). } type allowedOrigin struct { @@ -113,6 +150,7 @@ type allowedOrigin struct { type wsUpgradeResult struct { conn net.Conn ws *websocket + kind int } type wsReadInfo struct { @@ -120,9 +158,11 @@ type wsReadInfo struct { fs bool ff bool fc bool + mask bool // Incoming leafnode connections may not have masking. mkpos byte mkey [4]byte - buf []byte + cbufs [][]byte + coff int } func (r *wsReadInfo) init() { @@ -172,6 +212,7 @@ func (c *client) wsRead(r *wsReadInfo, ior io.Reader, buf []byte) ([][]byte, err err error pos int max = len(buf) + mpay = int(atomic.LoadInt32(&c.mpay)) ) for pos != max { if r.fs { @@ -188,7 +229,8 @@ func (c *client) wsRead(r *wsReadInfo, ior io.Reader, buf []byte) ([][]byte, err b1 := tmpBuf[0] // Clients MUST set the mask bit. If not set, reject. - if b1&wsMaskBit == 0 { + // However, LEAF by default will not have masking, unless they are forced to, by configuration. + if r.mask && b1&wsMaskBit == 0 { return bufs, c.wsHandleProtocolError("mask bit missing") } @@ -236,13 +278,15 @@ func (c *client) wsRead(r *wsReadInfo, ior io.Reader, buf []byte) ([][]byte, err r.rem = int(binary.BigEndian.Uint64(tmpBuf)) } - // Read masking key - tmpBuf, pos, err = wsGet(ior, buf, pos, 4) - if err != nil { - return bufs, err + if r.mask { + // Read masking key + tmpBuf, pos, err = wsGet(ior, buf, pos, 4) + if err != nil { + return bufs, err + } + copy(r.mkey[:], tmpBuf) + r.mkpos = 0 } - copy(r.mkey[:], tmpBuf) - r.mkpos = 0 // Handle control messages in place... if wsIsControlFrame(frameType) { @@ -267,40 +311,134 @@ func (c *client) wsRead(r *wsReadInfo, ior io.Reader, buf []byte) ([][]byte, err b = buf[pos : pos+n] pos += n r.rem -= n - if r.fc { - r.buf = append(r.buf, b...) - b = r.buf - } - if !r.fc || r.rem == 0 { + // If needed, unmask the buffer + if r.mask { r.unmask(b) - if r.fc { - // As per https://tools.ietf.org/html/rfc7692#section-7.2.2 - // add 0x00, 0x00, 0xff, 0xff and then a final block so that flate reader - // does not report unexpected EOF. - b = append(b, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff) - br := bytes.NewBuffer(b) - d, _ := decompressorPool.Get().(io.ReadCloser) - if d == nil { - d = flate.NewReader(br) - } else { - d.(flate.Resetter).Reset(br, nil) - } - b, err = ioutil.ReadAll(d) - decompressorPool.Put(d) + } + addToBufs := true + // Handle compressed message + if r.fc { + // Assume that we may have continuation frames or not the full payload. + addToBufs = false + // Make a copy of the buffer before adding it to the list + // of compressed fragments. + r.cbufs = append(r.cbufs, append([]byte(nil), b...)) + // When we have the final frame and we have read the full payload, + // we can decompress it. + if r.ff && r.rem == 0 { + b, err = r.decompress(mpay) if err != nil { return bufs, err } + r.fc = false + // Now we can add to `bufs` + addToBufs = true } + } + // For non compressed frames, or when we have decompressed the + // whole message. + if addToBufs { bufs = append(bufs, b) - if r.rem == 0 { - r.fs, r.fc, r.buf = true, false, nil - } + } + // If payload has been fully read, then indicate that next + // is the start of a frame. + if r.rem == 0 { + r.fs = true } } } return bufs, nil } +func (r *wsReadInfo) Read(dst []byte) (int, error) { + if len(dst) == 0 { + return 0, nil + } + if len(r.cbufs) == 0 { + return 0, io.EOF + } + copied := 0 + rem := len(dst) + for buf := r.cbufs[0]; buf != nil && rem > 0; { + n := len(buf[r.coff:]) + if n > rem { + n = rem + } + copy(dst[copied:], buf[r.coff:r.coff+n]) + copied += n + rem -= n + r.coff += n + buf = r.nextCBuf() + } + return copied, nil +} + +func (r *wsReadInfo) nextCBuf() []byte { + // We still have remaining data in the first buffer + if r.coff != len(r.cbufs[0]) { + return r.cbufs[0] + } + // We read the full first buffer. Reset offset. + r.coff = 0 + // We were at the last buffer, so we are done. + if len(r.cbufs) == 1 { + r.cbufs = nil + return nil + } + // Here we move to the next buffer. + r.cbufs = r.cbufs[1:] + return r.cbufs[0] +} + +func (r *wsReadInfo) ReadByte() (byte, error) { + if len(r.cbufs) == 0 { + return 0, io.EOF + } + b := r.cbufs[0][r.coff] + r.coff++ + r.nextCBuf() + return b, nil +} + +// decompress decompresses the collected buffers. +// The size of the decompressed buffer will be limited to the `mpay` value. +// If, while decompressing, the resulting uncompressed buffer exceeds this +// limit, the decompression stops and an empty buffer and the ErrMaxPayload +// error are returned. +func (r *wsReadInfo) decompress(mpay int) ([]byte, error) { + // If not limit is specified, use the default maximum payload size. + if mpay <= 0 { + mpay = MAX_PAYLOAD_SIZE + } + r.coff = 0 + // As per https://tools.ietf.org/html/rfc7692#section-7.2.2 + // add 0x00, 0x00, 0xff, 0xff and then a final block so that flate reader + // does not report unexpected EOF. + r.cbufs = append(r.cbufs, compressLastBlock) + // Get a decompressor from the pool and bind it to this object (wsReadInfo) + // that provides Read() and ReadByte() APIs that will consume the compressed + // buffers (r.cbufs). + d, _ := decompressorPool.Get().(io.ReadCloser) + if d == nil { + d = flate.NewReader(r) + } else { + d.(flate.Resetter).Reset(r, nil) + } + // Use a LimitedReader to limit the decompressed size. + // We use "limit+1" bytes for "N" so we can detect if the limit is exceeded. + lr := io.LimitedReader{R: d, N: int64(mpay + 1)} + b, err := io.ReadAll(&lr) + if err == nil && len(b) > mpay { + // Decompressed data exceeds the maximum payload size. + b, err = nil, ErrMaxPayload + } + lr.R = nil + decompressorPool.Put(d) + // Now reset the compressed buffers list. + r.cbufs = nil + return b, err +} + // Handles the PING, PONG and CLOSE websocket control frames. // // Client lock MUST NOT be held on entry. @@ -308,32 +446,54 @@ func (c *client) wsHandleControlFrame(r *wsReadInfo, frameType wsOpCode, nc io.R var payload []byte var err error - statusPos := pos if r.rem > 0 { payload, pos, err = wsGet(nc, buf, pos, r.rem) if err != nil { return pos, err } - r.unmask(payload) + if r.mask { + r.unmask(payload) + } r.rem = 0 } switch frameType { case wsCloseMessage: status := wsCloseStatusNoStatusReceived - body := "" - // If there is a payload, it should contain 2 unsigned bytes - // that represent the status code and then optional payload. - if len(payload) >= 2 { - status = int(binary.BigEndian.Uint16(buf[statusPos : statusPos+2])) - body = string(buf[statusPos+2 : statusPos+len(payload)]) - if body != "" && !utf8.ValidString(body) { - // https://tools.ietf.org/html/rfc6455#section-5.5.1 - // If body is present, it must be a valid utf8 - status = wsCloseStatusInvalidPayloadData - body = "invalid utf8 body in close frame" + var body string + lp := len(payload) + // If there is a payload, the status is represented as a 2-byte + // unsigned integer (in network byte order). Then, there may be an + // optional body. + hasStatus, hasBody := lp >= wsCloseSatusSize, lp > wsCloseSatusSize + if hasStatus { + // Decode the status + status = int(binary.BigEndian.Uint16(payload[:wsCloseSatusSize])) + // Now if there is a body, capture it and make sure this is a valid UTF-8. + if hasBody { + body = string(payload[wsCloseSatusSize:]) + if !utf8.ValidString(body) { + // https://tools.ietf.org/html/rfc6455#section-5.5.1 + // If body is present, it must be a valid utf8 + status = wsCloseStatusInvalidPayloadData + body = "invalid utf8 body in close frame" + } } } - c.wsEnqueueControlMessage(wsCloseMessage, wsCreateCloseMessage(status, body)) + // If the status indicates that nothing was received, then we don't + // send anything back. + // From https://datatracker.ietf.org/doc/html/rfc6455#section-7.4 + // it says that code 1005 is a reserved value and MUST NOT be set as a + // status code in a Close control frame by an endpoint. It is + // designated for use in applications expecting a status code to indicate + // that no status code was actually present. + var clm []byte + if status != wsCloseStatusNoStatusReceived { + clm = wsCreateCloseMessage(status, body) + } + c.wsEnqueueControlMessage(wsCloseMessage, clm) + if len(clm) > 0 { + nbPoolPut(clm) // wsEnqueueControlMessage has taken a copy. + } // Return io.EOF so that readLoop will close the connection as ClientClosed // after processing pending buffers. return pos, io.EOF @@ -382,13 +542,13 @@ func wsIsControlFrame(frameType wsOpCode) bool { // Create the frame header. // Encodes the frame type and optional compression flag, and the size of the payload. -func wsCreateFrameHeader(compressed bool, frameType wsOpCode, l int) []byte { - fh := make([]byte, wsMaxFrameHeaderSize) - n := wsFillFrameHeader(fh, wsFirstFrame, wsFinalFrame, compressed, frameType, l) - return fh[:n] +func wsCreateFrameHeader(useMasking, compressed bool, frameType wsOpCode, l int) ([]byte, []byte) { + fh := nbPoolGet(wsMaxFrameHeaderSize)[:wsMaxFrameHeaderSize] + n, key := wsFillFrameHeader(fh, useMasking, wsFirstFrame, wsFinalFrame, compressed, frameType, l) + return fh[:n], key } -func wsFillFrameHeader(fh []byte, first, final, compressed bool, frameType wsOpCode, l int) int { +func wsFillFrameHeader(fh []byte, useMasking, first, final, compressed bool, frameType wsOpCode, l int) (int, []byte) { var n int var b byte if first { @@ -400,23 +560,38 @@ func wsFillFrameHeader(fh []byte, first, final, compressed bool, frameType wsOpC if compressed { b |= wsRsv1Bit } + b1 := byte(0) + if useMasking { + b1 |= wsMaskBit + } switch { case l <= 125: n = 2 fh[0] = b - fh[1] = byte(l) + fh[1] = b1 | byte(l) case l < 65536: n = 4 fh[0] = b - fh[1] = 126 + fh[1] = b1 | 126 binary.BigEndian.PutUint16(fh[2:], uint16(l)) default: n = 10 fh[0] = b - fh[1] = 127 + fh[1] = b1 | 127 binary.BigEndian.PutUint64(fh[2:], uint64(l)) } - return n + var key []byte + if useMasking { + var keyBuf [4]byte + if _, err := io.ReadFull(crand.Reader, keyBuf[:4]); err != nil { + kv := mrand.Int31() + binary.LittleEndian.PutUint32(keyBuf[:4], uint32(kv)) + } + copy(fh[n:], keyBuf[:4]) + key = fh[n : n+4] + n += 4 + } + return n, key } // Invokes wsEnqueueControlMessageLocked under client lock. @@ -428,6 +603,25 @@ func (c *client) wsEnqueueControlMessage(controlMsg wsOpCode, payload []byte) { c.mu.Unlock() } +// Mask the buffer with the given key +func wsMaskBuf(key, buf []byte) { + for i := 0; i < len(buf); i++ { + buf[i] ^= key[i&3] + } +} + +// Mask the buffers, as if they were contiguous, with the given key +func wsMaskBufs(key []byte, bufs [][]byte) { + pos := 0 + for i := 0; i < len(bufs); i++ { + buf := bufs[i] + for j := 0; j < len(buf); j++ { + buf[j] ^= key[pos&3] + pos++ + } + } +} + // Enqueues a websocket control message. // If the control message is a wsCloseMessage, then marks this client // has having sent the close message (since only one should be sent). @@ -437,12 +631,22 @@ func (c *client) wsEnqueueControlMessage(controlMsg wsOpCode, payload []byte) { func (c *client) wsEnqueueControlMessageLocked(controlMsg wsOpCode, payload []byte) { // Control messages are never compressed and their size will be // less than wsMaxControlPayloadSize, which means the frame header - // will be only 2 bytes. - cm := make([]byte, 2+len(payload)) - wsFillFrameHeader(cm, wsFirstFrame, wsFinalFrame, wsUncompressedFrame, controlMsg, len(payload)) + // will be only 2 or 6 bytes. + useMasking := c.ws.maskwrite + sz := 2 + if useMasking { + sz += 4 + } + cm := nbPoolGet(sz + len(payload)) + cm = cm[:cap(cm)] + n, key := wsFillFrameHeader(cm, useMasking, wsFirstFrame, wsFinalFrame, wsUncompressedFrame, controlMsg, len(payload)) + cm = cm[:n] // Note that payload is optional. if len(payload) > 0 { - copy(cm[2:], payload) + cm = append(cm, payload...) + if useMasking { + wsMaskBuf(key, cm[n:]) + } } c.out.pb += int64(len(cm)) if controlMsg == wsCloseMessage { @@ -476,15 +680,17 @@ func (c *client) wsEnqueueCloseMessage(reason ClosedState) { status = wsCloseStatusProtocolError case MaxPayloadExceeded: status = wsCloseStatusMessageTooBig - case ServerShutdown: + case WriteError, ReadError, StaleConnection, ServerShutdown: + // We used to have WriteError, ReadError and StaleConnection result in + // code 1006, which the spec says that it must not be used to set the + // status in the close message. So using this one instead. status = wsCloseStatusGoingAway - case WriteError, ReadError, StaleConnection: - status = wsCloseStatusAbnormalClosure default: status = wsCloseStatusInternalSrvError } body := wsCreateCloseMessage(status, reason.String()) c.wsEnqueueControlMessageLocked(wsCloseMessage, body) + nbPoolPut(body) // wsEnqueueControlMessageLocked has taken a copy. } // Create and then enqueue a close message with a protocol error and the @@ -494,7 +700,8 @@ func (c *client) wsEnqueueCloseMessage(reason ClosedState) { func (c *client) wsHandleProtocolError(message string) error { buf := wsCreateCloseMessage(wsCloseStatusProtocolError, message) c.wsEnqueueControlMessage(wsCloseMessage, buf) - return fmt.Errorf(message) + nbPoolPut(buf) // wsEnqueueControlMessage has taken a copy. + return errors.New(message) } // Create a close message with the given `status` and `body`. @@ -510,7 +717,7 @@ func wsCreateCloseMessage(status int, body string) []byte { body = body[:wsMaxControlPayloadSize-5] body += "..." } - buf := make([]byte, 2+len(body)) + buf := nbPoolGet(2 + len(body))[:2+len(body)] // We need to have a 2 byte unsigned int that represents the error status code // https://tools.ietf.org/html/rfc6455#section-5.5.1 binary.BigEndian.PutUint16(buf[:2], uint16(status)) @@ -522,38 +729,48 @@ func wsCreateCloseMessage(status int, body string) []byte { // will be used to create a *client object. // Invoked from the HTTP server listening on websocket port. func (s *Server) wsUpgrade(w http.ResponseWriter, r *http.Request) (*wsUpgradeResult, error) { + kind := CLIENT + if r.URL != nil { + ep := r.URL.EscapedPath() + if strings.HasSuffix(ep, leafNodeWSPath) { + kind = LEAF + } else if strings.HasSuffix(ep, mqttWSPath) { + kind = MQTT + } + } + opts := s.getOpts() // From https://tools.ietf.org/html/rfc6455#section-4.2.1 // Point 1. if r.Method != "GET" { - return nil, wsReturnHTTPError(w, http.StatusMethodNotAllowed, "request method must be GET") + return nil, wsReturnHTTPError(w, r, http.StatusMethodNotAllowed, "request method must be GET") } // Point 2. - if r.Host == "" { - return nil, wsReturnHTTPError(w, http.StatusBadRequest, "'Host' missing in request") + if r.Host == _EMPTY_ { + return nil, wsReturnHTTPError(w, r, http.StatusBadRequest, "'Host' missing in request") } // Point 3. if !wsHeaderContains(r.Header, "Upgrade", "websocket") { - return nil, wsReturnHTTPError(w, http.StatusBadRequest, "invalid value for header 'Upgrade'") + return nil, wsReturnHTTPError(w, r, http.StatusBadRequest, "invalid value for header 'Upgrade'") } // Point 4. if !wsHeaderContains(r.Header, "Connection", "Upgrade") { - return nil, wsReturnHTTPError(w, http.StatusBadRequest, "invalid value for header 'Connection'") + return nil, wsReturnHTTPError(w, r, http.StatusBadRequest, "invalid value for header 'Connection'") } // Point 5. key := r.Header.Get("Sec-Websocket-Key") - if key == "" { - return nil, wsReturnHTTPError(w, http.StatusBadRequest, "key missing") + if key == _EMPTY_ { + return nil, wsReturnHTTPError(w, r, http.StatusBadRequest, "key missing") } // Point 6. if !wsHeaderContains(r.Header, "Sec-Websocket-Version", "13") { - return nil, wsReturnHTTPError(w, http.StatusBadRequest, "invalid version") + return nil, wsReturnHTTPError(w, r, http.StatusBadRequest, "invalid version") } // Others are optional // Point 7. if err := s.websocket.checkOrigin(r); err != nil { - return nil, wsReturnHTTPError(w, http.StatusForbidden, fmt.Sprintf("origin not allowed: %v", err)) + return nil, wsReturnHTTPError(w, r, http.StatusForbidden, fmt.Sprintf("origin not allowed: %v", err)) } // Point 8. // We don't have protocols, so ignore. @@ -561,8 +778,11 @@ func (s *Server) wsUpgrade(w http.ResponseWriter, r *http.Request) (*wsUpgradeRe // Extensions, only support for compression at the moment compress := opts.Websocket.Compression if compress { - compress = wsClientSupportsCompression(r.Header) + // Simply check if permessage-deflate extension is present. + compress, _ = wsPMCExtensionSupport(r.Header, true) } + // We will do masking if asked (unless we reject for tests) + noMasking := r.Header.Get(wsNoMaskingHeader) == wsNoMaskingValue && !wsTestRejectNoMasking h := w.(http.Hijacker) conn, brw, err := h.Hijack() @@ -570,11 +790,11 @@ func (s *Server) wsUpgrade(w http.ResponseWriter, r *http.Request) (*wsUpgradeRe if conn != nil { conn.Close() } - return nil, wsReturnHTTPError(w, http.StatusInternalServerError, err.Error()) + return nil, wsReturnHTTPError(w, r, http.StatusInternalServerError, err.Error()) } if brw.Reader.Buffered() > 0 { conn.Close() - return nil, wsReturnHTTPError(w, http.StatusBadRequest, "client sent data before handshake is complete") + return nil, wsReturnHTTPError(w, r, http.StatusBadRequest, "client sent data before handshake is complete") } var buf [1024]byte @@ -585,7 +805,16 @@ func (s *Server) wsUpgrade(w http.ResponseWriter, r *http.Request) (*wsUpgradeRe p = append(p, wsAcceptKey(key)...) p = append(p, _CRLF_...) if compress { - p = append(p, "Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r\n"...) + p = append(p, wsPMCFullResponse...) + } + if noMasking { + p = append(p, wsNoMaskingFullResponse...) + } + if kind == MQTT { + p = append(p, wsMQTTSecProto...) + } + if s.websocket.rawHeaders != _EMPTY_ { + p = append(p, s.websocket.rawHeaders...) } p = append(p, _CRLF_...) @@ -597,17 +826,46 @@ func (s *Server) wsUpgrade(w http.ResponseWriter, r *http.Request) (*wsUpgradeRe if opts.Websocket.HandshakeTimeout > 0 { conn.SetDeadline(time.Time{}) } - ws := &websocket{compress: compress} - // Indicate if this is likely coming from a browser. - if ua := r.Header.Get("User-Agent"); ua != "" && strings.HasPrefix(ua, "Mozilla/") { - ws.browser = true + // Server always expect "clients" to send masked payload, unless the option + // "no-masking" has been enabled. + ws := &websocket{compress: compress, maskread: !noMasking} + + // Check for X-Forwarded-For header + if cips, ok := r.Header[wsXForwardedForHeader]; ok { + cip := cips[0] + if net.ParseIP(cip) != nil { + ws.clientIP = cip + } } - if opts.Websocket.JWTCookie != "" { - if c, err := r.Cookie(opts.Websocket.JWTCookie); err == nil && c != nil { - ws.cookieJwt = c.Value + + if kind == CLIENT || kind == MQTT { + // Indicate if this is likely coming from a browser. + if ua := r.Header.Get("User-Agent"); ua != _EMPTY_ && strings.HasPrefix(ua, "Mozilla/") { + ws.browser = true + // Disable fragmentation of compressed frames for Safari browsers. + // Unfortunately, you could be running Chrome on macOS and this + // string will contain "Safari/" (along "Chrome/"). However, what + // I have found is that actual Safari browser also have "Version/". + // So make the combination of the two. + ws.nocompfrag = ws.compress && strings.Contains(ua, "Version/") && strings.Contains(ua, "Safari/") + } + + if cookies := r.Cookies(); len(cookies) > 0 { + ows := &opts.Websocket + for _, c := range cookies { + if ows.JWTCookie == c.Name { + ws.cookieJwt = c.Value + } else if ows.UsernameCookie == c.Name { + ws.cookieUsername = c.Value + } else if ows.PasswordCookie == c.Name { + ws.cookiePassword = c.Value + } else if ows.TokenCookie == c.Name { + ws.cookieToken = c.Value + } + } } } - return &wsUpgradeResult{conn: conn, ws: ws}, nil + return &wsUpgradeResult{conn: conn, ws: ws, kind: kind}, nil } // Returns true if the header named `name` contains a token with value `value`. @@ -624,36 +882,53 @@ func wsHeaderContains(header http.Header, name string, value string) bool { return false } -// Return true if the client has "permessage-deflate" in its extensions. -func wsClientSupportsCompression(header http.Header) bool { +func wsPMCExtensionSupport(header http.Header, checkPMCOnly bool) (bool, bool) { for _, extensionList := range header["Sec-Websocket-Extensions"] { extensions := strings.Split(extensionList, ",") for _, extension := range extensions { extension = strings.Trim(extension, " \t") params := strings.Split(extension, ";") - for _, p := range params { + for i, p := range params { p = strings.Trim(p, " \t") - if strings.EqualFold(p, "permessage-deflate") { - return true + if strings.EqualFold(p, wsPMCExtension) { + if checkPMCOnly { + return true, false + } + var snc bool + var cnc bool + for j := i + 1; j < len(params); j++ { + p = params[j] + p = strings.Trim(p, " \t") + if strings.EqualFold(p, wsPMCSrvNoCtx) { + snc = true + } else if strings.EqualFold(p, wsPMCCliNoCtx) { + cnc = true + } + if snc && cnc { + return true, true + } + } + return true, false } } } } - return false + return false, false } -// Send an HTTP error with the given `status`` to the given http response writer `w`. +// Send an HTTP error with the given `status` to the given http response writer `w`. // Return an error created based on the `reason` string. -func wsReturnHTTPError(w http.ResponseWriter, status int, reason string) error { - err := fmt.Errorf("websocket handshake error: %s", reason) +func wsReturnHTTPError(w http.ResponseWriter, r *http.Request, status int, reason string) error { + err := fmt.Errorf("%s - websocket handshake error: %s", r.RemoteAddr, reason) w.Header().Set("Sec-Websocket-Version", "13") http.Error(w, http.StatusText(status), status) return err } // If the server is configured to accept any origin, then this function returns -// `nil` without checking if the Origin is present and valid. -// Otherwise, this will check that the Origin matches the same origine or +// `nil` without checking if the Origin is present and valid. This is also +// the case if the request does not have the Origin header. +// Otherwise, this will check that the Origin matches the same origin or // any origin in the allowed list. func (w *srvWebsocket) checkOrigin(r *http.Request) error { w.mu.RLock() @@ -664,11 +939,16 @@ func (w *srvWebsocket) checkOrigin(r *http.Request) error { return nil } origin := r.Header.Get("Origin") - if origin == "" { + if origin == _EMPTY_ { origin = r.Header.Get("Sec-Websocket-Origin") } - if origin == "" { - return errors.New("origin not provided") + // If the header is not present, we will accept. + // From https://datatracker.ietf.org/doc/html/rfc6455#section-1.6 + // "Naturally, when the WebSocket Protocol is used by a dedicated client + // directly (i.e., not from a web page through a web browser), the origin + // model is not useful, as the client can provide any arbitrary origin string." + if origin == _EMPTY_ { + return nil } u, err := url.ParseRequestURI(origin) if err != nil { @@ -728,6 +1008,14 @@ func wsAcceptKey(key string) string { return base64.StdEncoding.EncodeToString(h.Sum(nil)) } +func wsMakeChallengeKey() (string, error) { + p := make([]byte, 16) + if _, err := io.ReadFull(crand.Reader, p); err != nil { + return _EMPTY_, err + } + return base64.StdEncoding.EncodeToString(p), nil +} + // Validate the websocket related options. func validateWebsocketOptions(o *Options) error { wo := &o.Websocket @@ -762,11 +1050,32 @@ func validateWebsocketOptions(o *Options) error { } } // Using JWT requires Trusted Keys - if wo.JWTCookie != "" { + if wo.JWTCookie != _EMPTY_ { if len(o.TrustedOperators) == 0 && len(o.TrustedKeys) == 0 { return fmt.Errorf("trusted operators or trusted keys configuration is required for JWT authentication via cookie %q", wo.JWTCookie) } } + if err := validatePinnedCerts(wo.TLSPinnedCerts); err != nil { + return fmt.Errorf("websocket: %v", err) + } + + // Check for invalid headers here. + for key := range wo.Headers { + k := strings.ToLower(key) + switch k { + case "host", + "content-length", + "connection", + "upgrade", + "nats-no-masking": + return fmt.Errorf("websocket: invalid header %q not allowed", key) + } + + if strings.HasPrefix(k, "sec-websocket-") { + return fmt.Errorf("websocket: invalid header %q, \"Sec-WebSocket-\" prefix not allowed", key) + } + } + return nil } @@ -798,6 +1107,21 @@ func (s *Server) wsSetOriginOptions(o *WebsocketOpts) { } } +// Calculate the raw headers for websocket upgrade response. +func (s *Server) wsSetHeadersOptions(o *WebsocketOpts) { + var sb strings.Builder + for k, v := range o.Headers { + sb.WriteString(k) + sb.WriteString(": ") + sb.WriteString(v) + sb.WriteString(_CRLF_) + } + ws := &s.websocket + ws.mu.Lock() + defer ws.mu.Unlock() + ws.rawHeaders = sb.String() +} + // Given the websocket options, we check if any auth configuration // has been provided. If so, possibly create users/nkey users and // store them in s.websocket.users/nkeys. @@ -811,10 +1135,15 @@ func (s *Server) wsConfigAuth(opts *WebsocketOpts) { } func (s *Server) startWebsocketServer() { + if s.isShuttingDown() { + return + } + sopts := s.getOpts() o := &sopts.Websocket s.wsSetOriginOptions(o) + s.wsSetHeadersOptions(o) var hl net.Listener var proto string @@ -832,37 +1161,39 @@ func (s *Server) startWebsocketServer() { // avoid the possibility of it being "intercepted". s.mu.Lock() - if s.shutdown { - s.mu.Unlock() - return - } // Do not check o.NoTLS here. If a TLS configuration is available, use it, // regardless of NoTLS. If we don't have a TLS config, it means that the // user has configured NoTLS because otherwise the server would have failed // to start due to options validation. if o.TLSConfig != nil { - proto = "wss" + proto = wsSchemePrefixTLS config := o.TLSConfig.Clone() + config.GetConfigForClient = s.wsGetTLSConfig hl, err = tls.Listen("tcp", hp, config) } else { - proto = "ws" + proto = wsSchemePrefix hl, err = net.Listen("tcp", hp) } + s.websocket.listenerErr = err if err != nil { s.mu.Unlock() s.Fatalf("Unable to listen for websocket connections: %v", err) return } - s.Noticef("Listening for websocket clients on %s://%s:%d", proto, o.Host, port) - if proto == "ws" { + if port == 0 { + o.Port = hl.Addr().(*net.TCPAddr).Port + } + s.Noticef("Listening for websocket clients on %s://%s:%d", proto, o.Host, o.Port) + if proto == wsSchemePrefix { s.Warnf("Websocket not configured with TLS. DO NOT USE IN PRODUCTION!") } - s.websocket.tls = proto == "wss" - if port == 0 { - s.opts.Websocket.Port = hl.Addr().(*net.TCPAddr).Port - } - s.Noticef("Listening for websocket clients on %s://%s:%d", proto, o.Host, port) + // These 3 are immutable and will be accessed without lock by the client + // when generating/sending the INFO protocols. + s.websocket.tls = proto == wsSchemePrefixTLS + s.websocket.host, s.websocket.port = o.Host, o.Port + + // This will be updated when/if the cluster changes. s.websocket.connectURLs, err = s.getConnectURLs(o.Advertise, o.Host, o.Port) if err != nil { s.Fatalf("Unable to get websocket connect URLs: %v", err) @@ -870,6 +1201,7 @@ func (s *Server) startWebsocketServer() { s.mu.Unlock() return } + hasLeaf := sopts.LeafNode.Port != 0 mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { res, err := s.wsUpgrade(w, r) @@ -877,16 +1209,33 @@ func (s *Server) startWebsocketServer() { s.Errorf(err.Error()) return } - s.createWSClient(res.conn, res.ws) + switch res.kind { + case CLIENT: + s.createWSClient(res.conn, res.ws) + case MQTT: + s.createMQTTClient(res.conn, res.ws) + case LEAF: + if !hasLeaf { + s.Errorf("Not configured to accept leaf node connections") + // Silently close for now. If we want to send an error back, we would + // need to create the leafnode client anyway, so that is handling websocket + // frames, then send the error to the remote. + res.conn.Close() + return + } + s.createLeafNode(res.conn, nil, nil, res.ws) + } }) hs := &http.Server{ Addr: hp, Handler: mux, ReadTimeout: o.HandshakeTimeout, - ErrorLog: log.New(&wsCaptureHTTPServerLog{s}, "", 0), + ErrorLog: log.New(&captureHTTPServerLog{s, "websocket: "}, _EMPTY_, 0), } + s.websocket.mu.Lock() s.websocket.server = hs s.websocket.listener = hl + s.websocket.mu.Unlock() go func() { if err := hs.Serve(hl); err != http.ErrServerClosed { s.Fatalf("websocket listener error: %v", err) @@ -903,6 +1252,17 @@ func (s *Server) startWebsocketServer() { s.mu.Unlock() } +// The TLS configuration is passed to the listener when the websocket +// "server" is setup. That prevents TLS configuration updates on reload +// from being used. By setting this function in tls.Config.GetConfigForClient +// we instruct the TLS handshake to ask for the tls configuration to be +// used for a specific client. We don't care which client, we always use +// the same TLS configuration. +func (s *Server) wsGetTLSConfig(_ *tls.ClientHelloInfo) (*tls.Config, error) { + opts := s.getOpts() + return opts.Websocket.TLSConfig, nil +} + // This is similar to createClient() but has some modifications // specific to handle websocket clients. // The comments have been kept to minimum to reduce code size. @@ -915,7 +1275,7 @@ func (s *Server) createWSClient(conn net.Conn, ws *websocket) *client { if maxSubs == 0 { maxSubs = -1 } - now := time.Now() + now := time.Now().UTC() c := &client{srv: s, nc: conn, opts: defaultOpts, mpay: maxPay, msubs: maxSubs, start: now, last: now, ws: ws} @@ -953,8 +1313,8 @@ func (s *Server) createWSClient(conn net.Conn, ws *websocket) *client { c.mu.Unlock() s.mu.Lock() - if !s.running || s.ldm { - if s.shutdown { + if !s.isRunning() || s.ldm { + if s.isShuttingDown() { conn.Close() } s.mu.Unlock() @@ -967,12 +1327,14 @@ func (s *Server) createWSClient(conn net.Conn, ws *websocket) *client { return nil } s.clients[c.cid] = c - - // Websocket clients do TLS in the websocket http server. - // So no TLS here... s.mu.Unlock() c.mu.Lock() + // Websocket clients do TLS in the websocket http server. + // So no TLS initiation here... + if _, ok := conn.(*tls.Conn); ok { + c.flags.set(handshakeComplete) + } if c.isClosed() { c.mu.Unlock() @@ -999,44 +1361,36 @@ func (s *Server) createWSClient(conn net.Conn, ws *websocket) *client { return c } -type wsCaptureHTTPServerLog struct { - s *Server -} - -func (cl *wsCaptureHTTPServerLog) Write(p []byte) (int, error) { - var buf [128]byte - var b = buf[:0] - - copy(b, []byte("websocket :")) - offset := 0 - if bytes.HasPrefix(p, []byte("http:")) { - offset = 6 - } - b = append(b, p[offset:]...) - cl.s.Errorf(string(b)) - return len(p), nil -} - func (c *client) wsCollapsePtoNB() (net.Buffers, int64) { - var nb net.Buffers - var total = 0 - var mfs = 0 + nb := c.out.nb + var mfs int + var usz int if c.ws.browser { mfs = wsFrameSizeForBrowsers } - if len(c.out.p) > 0 { - p := c.out.p - c.out.p = nil - nb = append(c.out.nb, p) - } else if len(c.out.nb) > 0 { - nb = c.out.nb - } + mask := c.ws.maskwrite // Start with possible already framed buffers (that we could have // got from partials or control messages such as ws pings or pongs). bufs := c.ws.frames - if c.ws.compress && len(nb) > 0 { - buf := &bytes.Buffer{} - + compress := c.ws.compress + if compress && len(nb) > 0 { + // First, make sure we don't compress for very small cumulative buffers. + for _, b := range nb { + usz += len(b) + } + if usz <= wsCompressThreshold { + compress = false + if cp := c.ws.compressor; cp != nil { + cp.Reset(nil) + } + } + } + if compress && len(nb) > 0 { + // Overwrite mfs if this connection does not support fragmented compressed frames. + if mfs > 0 && c.ws.nocompfrag { + mfs = 0 + } + buf := bytes.NewBuffer(nbPoolGet(usz)) cp := c.ws.compressor if cp == nil { c.ws.compressor, _ = flate.NewWriter(buf, flate.BestSpeed) @@ -1044,13 +1398,27 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) { } else { cp.Reset(buf) } - var usz int var csz int for _, b := range nb { - usz += len(b) - cp.Write(b) + for len(b) > 0 { + n, err := cp.Write(b) + if err != nil { + // Whatever this error is, it'll be handled by the cp.Flush() + // call below, as the same error will be returned there. + // Let the outer loop return all the buffers back to the pool + // and fall through naturally. + break + } + b = b[n:] + } + nbPoolPut(b) // No longer needed as contents written to compressor. + } + if err := cp.Flush(); err != nil { + c.Errorf("Error during compression: %v", err) + c.markConnAsClosed(WriteError) + cp.Reset(nil) + return nil, 0 } - cp.Close() b := buf.Bytes() p := b[:len(b)-4] if mfs > 0 && len(p) > mfs { @@ -1061,54 +1429,84 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) { } else { final = true } - fh := make([]byte, wsMaxFrameHeaderSize) - n := wsFillFrameHeader(fh, first, final, wsCompressedFrame, wsBinaryMessage, lp) + // Only the first frame should be marked as compressed, so pass + // `first` for the compressed boolean. + fh := nbPoolGet(wsMaxFrameHeaderSize)[:wsMaxFrameHeaderSize] + n, key := wsFillFrameHeader(fh, mask, first, final, first, wsBinaryMessage, lp) + if mask { + wsMaskBuf(key, p[:lp]) + } bufs = append(bufs, fh[:n], p[:lp]) csz += n + lp p = p[lp:] } } else { - h := wsCreateFrameHeader(true, wsBinaryMessage, len(p)) - bufs = append(bufs, h, p) - csz = len(h) + len(p) + ol := len(p) + h, key := wsCreateFrameHeader(mask, true, wsBinaryMessage, ol) + if mask { + wsMaskBuf(key, p) + } + if ol > 0 { + bufs = append(bufs, h, p) + } + csz = len(h) + ol } + // Make sure that the compressor no longer holds a reference to + // the bytes.Buffer, so that the underlying memory gets cleaned + // up after flushOutbound/flushAndClose. For this to be safe, we + // always cp.Reset(...) before reusing the compressor again. + cp.Reset(nil) // Add to pb the compressed data size (including headers), but // remove the original uncompressed data size that was added // during the queueing. c.out.pb += int64(csz) - int64(usz) c.ws.fs += int64(csz) } else if len(nb) > 0 { + var total int if mfs > 0 { // We are limiting the frame size. startFrame := func() int { - bufs = append(bufs, make([]byte, wsMaxFrameHeaderSize)) + bufs = append(bufs, nbPoolGet(wsMaxFrameHeaderSize)) return len(bufs) - 1 } endFrame := func(idx, size int) { - n := wsFillFrameHeader(bufs[idx], wsFirstFrame, wsFinalFrame, wsUncompressedFrame, wsBinaryMessage, size) + bufs[idx] = bufs[idx][:wsMaxFrameHeaderSize] + n, key := wsFillFrameHeader(bufs[idx], mask, wsFirstFrame, wsFinalFrame, wsUncompressedFrame, wsBinaryMessage, size) + bufs[idx] = bufs[idx][:n] c.out.pb += int64(n) c.ws.fs += int64(n + size) - bufs[idx] = bufs[idx][:n] + if mask { + wsMaskBufs(key, bufs[idx+1:]) + } } fhIdx := startFrame() for i := 0; i < len(nb); i++ { b := nb[i] if total+len(b) <= mfs { - bufs = append(bufs, b) + buf := nbPoolGet(len(b)) + bufs = append(bufs, append(buf, b...)) total += len(b) + nbPoolPut(nb[i]) continue } for len(b) > 0 { - endFrame(fhIdx, total) + endStart := total != 0 + if endStart { + endFrame(fhIdx, total) + } total = len(b) if total >= mfs { total = mfs } - fhIdx = startFrame() - bufs = append(bufs, b[:total]) + if endStart { + fhIdx = startFrame() + } + buf := nbPoolGet(total) + bufs = append(bufs, append(buf, b[:total]...)) b = b[total:] } + nbPoolPut(nb[i]) // No longer needed as copied into smaller frames. } if total > 0 { endFrame(fhIdx, total) @@ -1119,10 +1517,14 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) { for _, b := range nb { total += len(b) } - wsfh := wsCreateFrameHeader(false, wsBinaryMessage, total) + wsfh, key := wsCreateFrameHeader(mask, false, wsBinaryMessage, total) c.out.pb += int64(len(wsfh)) bufs = append(bufs, wsfh) + idx := len(bufs) bufs = append(bufs, nb...) + if mask { + wsMaskBufs(key, bufs[idx:]) + } c.ws.fs += int64(len(wsfh) + total) } } @@ -1130,7 +1532,16 @@ func (c *client) wsCollapsePtoNB() (net.Buffers, int64) { bufs = append(bufs, c.ws.closeMsg) c.ws.fs += int64(len(c.ws.closeMsg)) c.ws.closeMsg = nil + c.ws.compressor = nil } c.ws.frames = nil return bufs, c.ws.fs } + +func isWSURL(u *url.URL) bool { + return strings.HasPrefix(strings.ToLower(u.Scheme), wsSchemePrefix) +} + +func isWSSURL(u *url.URL) bool { + return strings.HasPrefix(strings.ToLower(u.Scheme), wsSchemePrefixTLS) +} diff --git a/vendor/github.com/nats-io/nats-server/v2/test/test.go b/vendor/github.com/nats-io/nats-server/v2/test/test.go index ca3c8b4..183e7ce 100644 --- a/vendor/github.com/nats-io/nats-server/v2/test/test.go +++ b/vendor/github.com/nats-io/nats-server/v2/test/test.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -20,6 +20,7 @@ import ( "fmt" "io" "net" + "os" "regexp" "runtime" "strconv" @@ -28,12 +29,14 @@ import ( "time" "github.com/nats-io/nats-server/v2/server" + + srvlog "github.com/nats-io/nats-server/v2/logger" ) // So we can pass tests and benchmarks.. type tLogger interface { - Fatalf(format string, args ...interface{}) - Errorf(format string, args ...interface{}) + Fatalf(format string, args ...any) + Errorf(format string, args ...any) } // DefaultTestOptions are default options for the unit tests. @@ -67,6 +70,10 @@ var ( // RunServer starts a new Go routine based server func RunServer(opts *server.Options) *server.Server { + return RunServerCallback(opts, nil) +} + +func RunServerCallback(opts *server.Options, callback func(*server.Server)) *server.Server { if opts == nil { opts = &DefaultTestOptions } @@ -74,6 +81,11 @@ func RunServer(opts *server.Options) *server.Server { opts.NoLog = !doLog opts.Trace = doTrace opts.Debug = doDebug + // For all tests in the "test" package, we will disable route pooling. + opts.Cluster.PoolSize = -1 + // Also disable compression for "test" package. + opts.Cluster.Compression.Mode = server.CompressionOff + opts.LeafNode.Compression.Mode = server.CompressionOff s, err := server.NewServer(opts) if err != nil || s == nil { @@ -84,6 +96,17 @@ func RunServer(opts *server.Options) *server.Server { s.ConfigureLogger() } + if ll := os.Getenv("NATS_LOGGING"); ll != "" { + log := srvlog.NewTestLogger(fmt.Sprintf("[%s] | ", s), true) + debug := ll == "debug" || ll == "trace" + trace := ll == "trace" + s.SetLoggerV2(log, debug, trace, false) + } + + if callback != nil { + callback(s) + } + // Run server in Go routine. go s.Start() @@ -110,7 +133,18 @@ func RunServerWithConfig(configFile string) (srv *server.Server, opts *server.Op return } -func stackFatalf(t tLogger, f string, args ...interface{}) { +// RunServerWithConfigOverrides starts a new Go routine based server with a configuration file, +// providing a callback to update the options configured. +func RunServerWithConfigOverrides(configFile string, optsCallback func(*server.Options), svrCallback func(*server.Server)) (srv *server.Server, opts *server.Options) { + opts = LoadConfig(configFile) + if optsCallback != nil { + optsCallback(opts) + } + srv = RunServerCallback(opts, svrCallback) + return +} + +func stackFatalf(t tLogger, f string, args ...any) { lines := make([]string, 0, 32) msg := fmt.Sprintf(f, args...) lines = append(lines, msg) @@ -254,11 +288,27 @@ func setupConnWithProto(t tLogger, c net.Conn, proto int) (sendFun, expectFun) { return sendCommand(t, c), expectCommand(t, c) } -func setupConnWithAccount(t tLogger, c net.Conn, account string) (sendFun, expectFun) { - checkInfoMsg(t, c) - cs := fmt.Sprintf("CONNECT {\"verbose\":%v,\"pedantic\":%v,\"tls_required\":%v,\"account\":%q}\r\n", false, false, false, account) +func setupConnWithAccount(t tLogger, s *server.Server, c net.Conn, account string) (sendFun, expectFun) { + info := checkInfoMsg(t, c) + s.RegisterAccount(account) + acc, err := s.LookupAccount(account) + if err != nil { + t.Fatalf("Unexpected Error: %v", err) + } + cs := fmt.Sprintf("CONNECT {\"verbose\":%v,\"pedantic\":%v,\"tls_required\":%v}\r\n", false, false, false) sendProto(t, c, cs) - return sendCommand(t, c), expectCommand(t, c) + + send, expect := sendCommand(t, c), expectCommand(t, c) + send("PING\r\n") + expect(pongRe) + + nc := s.GetClient(info.CID) + if nc == nil { + t.Fatalf("Could not get client for CID:%d", info.CID) + } + nc.RegisterUser(&server.User{Account: acc}) + + return send, expect } func setupConnWithUserPass(t tLogger, c net.Conn, username, password string) (sendFun, expectFun) { @@ -266,7 +316,7 @@ func setupConnWithUserPass(t tLogger, c net.Conn, username, password string) (se cs := fmt.Sprintf("CONNECT {\"verbose\":%v,\"pedantic\":%v,\"tls_required\":%v,\"protocol\":1,\"user\":%q,\"pass\":%q}\r\n", false, false, false, username, password) sendProto(t, c, cs) - return sendCommand(t, c), expectCommand(t, c) + return sendCommand(t, c), expectLefMostCommand(t, c) } type sendFun func(string) @@ -286,6 +336,14 @@ func expectCommand(t tLogger, c net.Conn) expectFun { } } +// Closure version for easier reading +func expectLefMostCommand(t tLogger, c net.Conn) expectFun { + var buf []byte + return func(re *regexp.Regexp) []byte { + return expectLeftMostResult(t, c, re, &buf) + } +} + // Send the protocol command to the server. func sendProto(t tLogger, c net.Conn, op string) { n, err := c.Write([]byte(op)) @@ -298,24 +356,27 @@ func sendProto(t tLogger, c net.Conn, op string) { } var ( - infoRe = regexp.MustCompile(`INFO\s+([^\r\n]+)\r\n`) - pingRe = regexp.MustCompile(`^PING\r\n`) - pongRe = regexp.MustCompile(`^PONG\r\n`) - hmsgRe = regexp.MustCompile(`(?:(?:HMSG\s+([^\s]+)\s+([^\s]+)\s+(([^\s]+)[^\S\r\n]+)?(\d+)\s+(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) - msgRe = regexp.MustCompile(`(?:(?:MSG\s+([^\s]+)\s+([^\s]+)\s+(([^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) - rawMsgRe = regexp.MustCompile(`(?:(?:MSG\s+([^\s]+)\s+([^\s]+)\s+(([^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n(.*?)))`) - okRe = regexp.MustCompile(`\A\+OK\r\n`) - errRe = regexp.MustCompile(`\A\-ERR\s+([^\r\n]+)\r\n`) - connectRe = regexp.MustCompile(`CONNECT\s+([^\r\n]+)\r\n`) - rsubRe = regexp.MustCompile(`RS\+\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\s*(\d+)?\r\n`) - runsubRe = regexp.MustCompile(`RS\-\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\r\n`) - rmsgRe = regexp.MustCompile(`(?:(?:RMSG\s+([^\s]+)\s+([^\s]+)\s+(?:([|+]\s+([\w\s]+)|[^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) - asubRe = regexp.MustCompile(`A\+\s+([^\r\n]+)\r\n`) - aunsubRe = regexp.MustCompile(`A\-\s+([^\r\n]+)\r\n`) - lsubRe = regexp.MustCompile(`LS\+\s+([^\s]+)\s*([^\s]+)?\s*(\d+)?\r\n`) - lunsubRe = regexp.MustCompile(`LS\-\s+([^\s]+)\s*([^\s]+)?\r\n`) - lmsgRe = regexp.MustCompile(`(?:(?:LMSG\s+([^\s]+)\s+(?:([|+]\s+([\w\s]+)|[^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) - rlsubRe = regexp.MustCompile(`LS\+\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\s*(\d+)?\r\n`) + anyRe = regexp.MustCompile(`.*`) + infoRe = regexp.MustCompile(`INFO\s+([^\r\n]+)\r\n`) + infoStartRe = regexp.MustCompile(`^INFO\s+([^\r\n]+)\r\n`) + pingRe = regexp.MustCompile(`^PING\r\n`) + pongRe = regexp.MustCompile(`^PONG\r\n`) + hmsgRe = regexp.MustCompile(`(?:(?:HMSG\s+([^\s]+)\s+([^\s]+)\s+(([^\s]+)[^\S\r\n]+)?(\d+)\s+(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) + msgRe = regexp.MustCompile(`(?:(?:MSG\s+([^\s]+)\s+([^\s]+)\s+(([^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) + rawMsgRe = regexp.MustCompile(`(?:(?:MSG\s+([^\s]+)\s+([^\s]+)\s+(([^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n(.*?)))`) + okRe = regexp.MustCompile(`\A\+OK\r\n`) + errRe = regexp.MustCompile(`\A\-ERR\s+([^\r\n]+)\r\n`) + connectRe = regexp.MustCompile(`CONNECT\s+([^\r\n]+)\r\n`) + rsubRe = regexp.MustCompile(`RS\+\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\s*(\d+)?\r\n`) + runsubRe = regexp.MustCompile(`RS\-\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\r\n`) + rmsgRe = regexp.MustCompile(`(?:(?:RMSG\s+([^\s]+)\s+([^\s]+)\s+(?:([|+]\s+([\w\s]+)|[^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) + asubRe = regexp.MustCompile(`A\+\s+([^\r\n]+)\r\n`) + aunsubRe = regexp.MustCompile(`A\-\s+([^\r\n]+)\r\n`) + lsubRe = regexp.MustCompile(`LS\+\s+([^\s]+)\s*([^\s]+)?\s*(\d+)?\r\n`) + lunsubRe = regexp.MustCompile(`LS\-\s+([^\s]+)\s*([^\s]+)\s*([^\s]+)?\r\n`) + lmsgRe = regexp.MustCompile(`(?:(?:LMSG\s+([^\s]+)\s+(?:([|+]\s+([\w\s]+)|[^\s]+)[^\S\r\n]+)?(\d+)\s*\r\n([^\\r\\n]*?)\r\n)+?)`) + rlsubRe = regexp.MustCompile(`LS\+\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\s*(\d+)?\r\n`) + rlunsubRe = regexp.MustCompile(`LS\-\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\r\n`) ) const ( @@ -336,6 +397,40 @@ const ( replyAndQueueIndex = 3 ) +// Test result from server against regexp and return left most match +func expectLeftMostResult(t tLogger, c net.Conn, re *regexp.Regexp, buf *[]byte) []byte { + recv := func() []byte { + expBuf := make([]byte, 32768) + // Wait for commands to be processed and results queued for read + c.SetReadDeadline(time.Now().Add(2 * time.Second)) + n, err := c.Read(expBuf) + c.SetReadDeadline(time.Time{}) + + if n <= 0 && err != nil { + stackFatalf(t, "Error reading from conn: %v\n", err) + } + return expBuf[:n] + } + if len(*buf) == 0 { + *buf = recv() + } + emptyCnt := 0 + for { + result := re.Find(*buf) + if result == nil { + emptyCnt++ + if emptyCnt > 5 { + stackFatalf(t, "Reading empty data too often\n") + } + *buf = append(*buf, recv()...) + } else { + cutIdx := strings.Index(string(*buf), string(result)) + len(result) + *buf = (*buf)[cutIdx:] + return result + } + } +} + // Test result from server against regexp func expectResult(t tLogger, c net.Conn, re *regexp.Regexp) []byte { expBuf := make([]byte, 32768) @@ -554,3 +649,12 @@ func nextServerOpts(opts *server.Options) *server.Options { nopts.HTTPPort++ return nopts } + +func createTempFile(t testing.TB, prefix string) *os.File { + t.Helper() + file, err := os.CreateTemp(t.TempDir(), prefix) + if err != nil { + t.Fatal(err) + } + return file +} diff --git a/vendor/github.com/nats-io/nats.go/.gitignore b/vendor/github.com/nats-io/nats.go/.gitignore index a9977fc..01716ae 100644 --- a/vendor/github.com/nats-io/nats.go/.gitignore +++ b/vendor/github.com/nats-io/nats.go/.gitignore @@ -21,6 +21,9 @@ _testmain.go *.exe +# Git backup files +*.orig + # Emacs *~ \#*\# @@ -39,4 +42,7 @@ _testmain.go # bin # Goland -.idea \ No newline at end of file +.idea + +# VS Code +.vscode diff --git a/vendor/github.com/nats-io/nats.go/.golangci.yaml b/vendor/github.com/nats-io/nats.go/.golangci.yaml new file mode 100644 index 0000000..fb548e5 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/.golangci.yaml @@ -0,0 +1,16 @@ +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + exclude-rules: + - linters: + - errcheck + text: "Unsubscribe" + - linters: + - errcheck + text: "Drain" + - linters: + - errcheck + text: "msg.Ack" + - linters: + - errcheck + text: "watcher.Stop" diff --git a/vendor/github.com/nats-io/nats.go/.travis.yml b/vendor/github.com/nats-io/nats.go/.travis.yml deleted file mode 100644 index dcbac5b..0000000 --- a/vendor/github.com/nats-io/nats.go/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: go -go: -- 1.15.x -- 1.14.x -env: -- GO111MODULE=off -go_import_path: github.com/nats-io/nats.go -install: -- go get -t ./... -- go get github.com/nats-io/nats-server -- go get github.com/mattn/goveralls -- go get github.com/wadey/gocovmerge -- go get -u honnef.co/go/tools/cmd/staticcheck -- go get -u github.com/client9/misspell/cmd/misspell -before_script: -- $(exit $(go fmt ./... | wc -l)) -- go vet ./... -- find . -type f -name "*.go" | xargs misspell -error -locale US -- staticcheck ./... -script: -- go test -i -race ./... -- go test -v -run=TestNoRace -p=1 ./... -- if [[ "$TRAVIS_GO_VERSION" =~ 1.15 ]]; then ./scripts/cov.sh TRAVIS; else go test -race -v -p=1 ./... --failfast; fi diff --git a/vendor/github.com/nats-io/nats.go/.words b/vendor/github.com/nats-io/nats.go/.words new file mode 100644 index 0000000..24be7f6 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/.words @@ -0,0 +1,106 @@ +1 + +derek +dlc +ivan + +acknowledgement/SM +arity +deduplication/S +demarshal/SDG +durables +iff +observable/S +redelivery/S +retransmitting +retry/SB + +SlowConsumer + +AppendInt +ReadMIMEHeader + +clientProtoZero +jetstream +v1 +v2 + +ack/SGD +auth +authToken +chans +creds +config/S +cseq +impl +msgh +msgId +mux/S +nack +ptr +puback +scanf +stderr +stdout +structs +tm +todo +unsub/S + +permessage +permessage-deflate +urlA +urlB +websocket +ws +wss + +NKey +pList + +backend/S +backoff/S +decompressor/CGS +inflight +inlined +lookups +reconnection/MS +redeliver/ADGS +responder/S +rewrap/S +rollup/S +unreceive/DRSZGB +variadic +wakeup/S +whitespace +wrap/AS + +omitempty + +apache +html +ietf +www + +sum256 +32bit/S +64bit/S +64k +128k +512k + +hacky +handroll/D + +rfc6455 +rfc7692 +0x00 +0xff +20x +40x +50x + +ErrXXX + +atlanta +eu diff --git a/vendor/github.com/nats-io/nats.go/.words.readme b/vendor/github.com/nats-io/nats.go/.words.readme new file mode 100644 index 0000000..9d9f5cb --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/.words.readme @@ -0,0 +1,25 @@ +The .words file is used by gospel (v1.2+), which wraps the Hunspell libraries +but populates the dictionary with identifiers from the Go source. + + + +Alas, no comments are allowed in the .words file and newer versions of gospel +error out on seeing them. This is really a hunspell restriction. + +We assume en_US hunspell dictionaries are installed and used. +The /AFFIXRULES are defined in en_US.aff (eg: /usr/share/hunspell/en_US.aff) +Invoke `hunspell -D` to see the actual locations. + +Words which are in the base dictionary can't have extra affix rules added to +them, so we have to start with the affixed variant we want to add. +Thus `creds` rather than `cred/S` and so on. + +So we can't use receive/DRSZGBU, adding 'U', to allow unreceive and variants, +we have to use unreceive as the stem. + +We can't define our own affix or compound rules, +to capture rfc\d{3,} or 0x[0-9A-Fa-f]{2} + +The spelling tokenizer doesn't take "permessage-deflate" as allowing for ... +"permessage-deflate", which is an RFC7692 registered extension for websockets. +We have to explicitly list "permessage". diff --git a/vendor/github.com/nats-io/nats.go/CONTRIBUTING.md b/vendor/github.com/nats-io/nats.go/CONTRIBUTING.md new file mode 100644 index 0000000..cfb7e4e --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/CONTRIBUTING.md @@ -0,0 +1,80 @@ +# Contributing + +Thanks for your interest in contributing! This document contains `nats-io/nats.go` specific contributing details. If you +are a first-time contributor, please refer to the general [NATS Contributor Guide](https://nats.io/contributing/) to get +a comprehensive overview of contributing to the NATS project. + +## Getting started + +There are three general ways you can contribute to this repo: + +- Proposing an enhancement or new feature +- Reporting a bug or regression +- Contributing changes to the source code + +For the first two, refer to the [GitHub Issues](https://github.com/nats-io/nats.go/issues/new/choose) which guides you +through the available options along with the needed information to collect. + +## Contributing changes + +_Prior to opening a pull request, it is recommended to open an issue first to ensure the maintainers can review intended +changes. Exceptions to this rule include fixing non-functional source such as code comments, documentation or other +supporting files._ + +Proposing source code changes is done through GitHub's standard pull request workflow. + +If your branch is a work-in-progress then please start by creating your pull requests as draft, by clicking the +down-arrow next to the `Create pull request` button and instead selecting `Create draft pull request`. + +This will defer the automatic process of requesting a review from the NATS team and significantly reduces noise until +you are ready. Once you are happy, you can click the `Ready for review` button. + +### Guidelines + +A good pull request includes: + +- A high-level description of the changes, including links to any issues that are related by adding comments + like `Resolves #NNN` to your description. + See [Linking a Pull Request to an Issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) + for more information. +- An up-to-date parent commit. Please make sure you are pulling in the latest `main` branch and rebasing your work on + top of it, i.e. `git rebase main`. +- Unit tests where appropriate. Bug fixes will benefit from the addition of regression tests. New features will not be + accepted without suitable test coverage! +- No more commits than necessary. Sometimes having multiple commits is useful for telling a story or isolating changes + from one another, but please squash down any unnecessary commits that may just be for clean-up, comments or small + changes. +- No additional external dependencies that aren't absolutely essential. Please do everything you can to avoid pulling in + additional libraries/dependencies into `go.mod` as we will be very critical of these. + +### Sign-off + +In order to accept a contribution, you will first need to certify that the contribution is your original work and that +you license the work to the project under +the [Apache-2.0 license](https://github.com/nats-io/nats.go/blob/main/LICENSE). + +This is done by using `Signed-off-by` statements, which should appear in **both** your commit messages and your PR +description. Please note that we can only accept sign-offs under a legal name. Nicknames and aliases are not permitted. + +To perform a sign-off with `git`, use `git commit -s` (or `--signoff`). + +## Get help + +If you have questions about the contribution process, please start +a [GitHub discussion](https://github.com/nats-io/nats.go/discussions), join the [NATS Slack](https://slack.nats.io/), or +send your question to the [NATS Google Group](https://groups.google.com/forum/#!forum/natsio). + +## Testing + +You should use `go_test.mod` to manage your testing dependencies. Please use the following command to update your +dependencies and avoid changing the main `go.mod` in a PR: + +```shell +go mod tidy -modfile=go_test.mod +``` + +To the tests you can pass `-modfile=go_test.mod` flag to `go test` or instead you can also set `GOFLAGS="-modfile=go_test.mod"` as an environment variable: + +```shell +go test ./... -modfile=go_test.mod +``` diff --git a/vendor/github.com/nats-io/nats.go/README.md b/vendor/github.com/nats-io/nats.go/README.md index 8b6e6f0..9340a88 100644 --- a/vendor/github.com/nats-io/nats.go/README.md +++ b/vendor/github.com/nats-io/nats.go/README.md @@ -1,39 +1,38 @@ # NATS - Go Client A [Go](http://golang.org) client for the [NATS messaging system](https://nats.io). -[![License Apache 2](https://img.shields.io/badge/License-Apache2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnats-io%2Fgo-nats.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fgo-nats?ref=badge_shield) -[![Go Report Card](https://goreportcard.com/badge/github.com/nats-io/nats.go)](https://goreportcard.com/report/github.com/nats-io/nats.go) [![Build Status](https://travis-ci.org/nats-io/nats.go.svg?branch=master)](http://travis-ci.org/nats-io/nats.go) [![GoDoc](https://img.shields.io/badge/GoDoc-reference-007d9c)](https://pkg.go.dev/github.com/nats-io/nats.go) - [![Coverage Status](https://coveralls.io/repos/nats-io/nats.go/badge.svg?branch=master)](https://coveralls.io/r/nats-io/nats.go?branch=master) +[![License Apache 2][License-Image]][License-Url] [![Go Report Card][ReportCard-Image]][ReportCard-Url] [![Build Status][Build-Status-Image]][Build-Status-Url] [![GoDoc][GoDoc-Image]][GoDoc-Url] [![Coverage Status][Coverage-image]][Coverage-Url] -## Installation - -```bash -# Go client -go get github.com/nats-io/nats.go/ +[License-Url]: https://www.apache.org/licenses/LICENSE-2.0 +[License-Image]: https://img.shields.io/badge/License-Apache2-blue.svg +[ReportCard-Url]: https://goreportcard.com/report/github.com/nats-io/nats.go +[ReportCard-Image]: https://goreportcard.com/badge/github.com/nats-io/nats.go +[Build-Status-Url]: https://github.com/nats-io/nats.go/actions +[Build-Status-Image]: https://github.com/nats-io/nats.go/actions/workflows/ci.yaml/badge.svg?branch=main +[GoDoc-Url]: https://pkg.go.dev/github.com/nats-io/nats.go +[GoDoc-Image]: https://img.shields.io/badge/GoDoc-reference-007d9c +[Coverage-Url]: https://coveralls.io/r/nats-io/nats.go?branch=main +[Coverage-image]: https://coveralls.io/repos/github/nats-io/nats.go/badge.svg?branch=main -# Server -go get github.com/nats-io/nats-server -``` +**Check out [NATS by example](https://natsbyexample.com) - An evolving collection of runnable, cross-client reference examples for NATS.** -When using or transitioning to Go modules support: +## Installation ```bash -# Go client latest or explicit version -go get github.com/nats-io/nats.go/@latest -go get github.com/nats-io/nats.go/@v1.10.0 +# To get the latest released Go client: +go get github.com/nats-io/nats.go@latest -# For latest NATS Server, add /v2 at the end -go get github.com/nats-io/nats-server/v2 +# To get a specific version: +go get github.com/nats-io/nats.go@v1.48.0 -# NATS Server v1 is installed otherwise -# go get github.com/nats-io/nats-server +# Note that the latest major version for NATS Server is v2: +go get github.com/nats-io/nats-server/v2@latest ``` ## Basic Usage ```go -import nats "github.com/nats-io/nats.go" +import "github.com/nats-io/nats.go" // Connect to a server nc, _ := nats.Connect(nats.DefaultURL) @@ -82,59 +81,49 @@ nc.Drain() nc.Close() ``` -## Encoded Connections +## JetStream +[![JetStream API Reference](https://pkg.go.dev/badge/github.com/nats-io/nats.go/jetstream.svg)](https://pkg.go.dev/github.com/nats-io/nats.go/jetstream) -```go +JetStream is the built-in NATS persistence system. `nats.go` provides a built-in +API enabling both managing JetStream assets as well as publishing/consuming +persistent messages. -nc, _ := nats.Connect(nats.DefaultURL) -c, _ := nats.NewEncodedConn(nc, nats.JSON_ENCODER) -defer c.Close() -// Simple Publisher -c.Publish("foo", "Hello World") +### Basic usage -// Simple Async Subscriber -c.Subscribe("foo", func(s string) { - fmt.Printf("Received a message: %s\n", s) -}) +```go +// connect to nats server +nc, _ := nats.Connect(nats.DefaultURL) -// EncodedConn can Publish any raw Go type using the registered Encoder -type person struct { - Name string - Address string - Age int -} +// create jetstream context from nats connection +js, _ := jetstream.New(nc) -// Go type Subscriber -c.Subscribe("hello", func(p *person) { - fmt.Printf("Received a person: %+v\n", p) -}) +ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +defer cancel() -me := &person{Name: "derek", Age: 22, Address: "140 New Montgomery Street, San Francisco, CA"} +// get existing stream handle +stream, _ := js.Stream(ctx, "foo") -// Go type Publisher -c.Publish("hello", me) +// retrieve consumer handle from a stream +cons, _ := stream.Consumer(ctx, "cons") -// Unsubscribe -sub, err := c.Subscribe("foo", nil) -// ... -sub.Unsubscribe() +// consume messages from the consumer in callback +cc, _ := cons.Consume(func(msg jetstream.Msg) { + fmt.Println("Received jetstream message: ", string(msg.Data())) + msg.Ack() +}) +defer cc.Stop() +``` -// Requests -var response string -err = c.Request("help", "help me", &response, 10*time.Millisecond) -if err != nil { - fmt.Printf("Request failed: %v\n", err) -} +To find more information on `nats.go` JetStream API, visit +[`jetstream/README.md`](jetstream/README.md) -// Replying -c.Subscribe("help", func(subj, reply string, msg string) { - c.Publish(reply, "I can help!") -}) +> The current JetStream API replaces the [legacy JetStream API](legacy_jetstream.md) -// Close connection -c.Close(); -``` +## Service API + +The service API (`micro`) allows you to [easily build NATS services](micro/README.md) The +services API is currently in beta release. ## New Authentication (Nkeys and User Credentials) This requires server with version >= 2.0.0 @@ -215,34 +204,6 @@ if err != nil { ``` -## Using Go Channels (netchan) - -```go -nc, _ := nats.Connect(nats.DefaultURL) -ec, _ := nats.NewEncodedConn(nc, nats.JSON_ENCODER) -defer ec.Close() - -type person struct { - Name string - Address string - Age int -} - -recvCh := make(chan *person) -ec.BindRecvChan("hello", recvCh) - -sendCh := make(chan *person) -ec.BindSendChan("hello", sendCh) - -me := &person{Name: "derek", Age: 22, Address: "140 New Montgomery Street"} - -// Send via Go channels -sendCh <- me - -// Receive via Go channels -who := <- recvCh -``` - ## Wildcard Subscriptions ```go @@ -278,7 +239,6 @@ nc.Publish("foo.bar.baz", []byte("Hello World")) nc.QueueSubscribe("foo", "job_workers", func(_ *Msg) { received += 1; }) - ``` ## Advanced Usage @@ -410,19 +370,21 @@ msg, err := nc.RequestWithContext(ctx, "foo", []byte("bar")) sub, err := nc.SubscribeSync("foo") msg, err := sub.NextMsgWithContext(ctx) -// Encoded Request with context -c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) -type request struct { - Message string `json:"message"` -} -type response struct { - Code int `json:"code"` -} -req := &request{Message: "Hello"} -resp := &response{} -err := c.RequestWithContext(ctx, "foo", req, resp) ``` +## Backwards compatibility + +In the development of nats.go, we are committed to maintaining backward compatibility and ensuring a stable and reliable experience for all users. In general, we follow the standard go compatibility guidelines. +However, it's important to clarify our stance on certain types of changes: + +- **Expanding structures:** +Adding new fields to structs is not considered a breaking change. + +- **Adding methods to exported interfaces:** +Extending public interfaces with new methods is also not viewed as a breaking change within the context of this project. It is important to note that no unexported methods will be added to interfaces allowing users to implement them. + +Additionally, this library always supports at least 2 latest minor Go versions. For example, if the latest Go version is 1.22, the library will support Go 1.21 and 1.22. + ## License Unless otherwise noted, the NATS source files are distributed diff --git a/vendor/github.com/nats-io/nats.go/TODO.md b/vendor/github.com/nats-io/nats.go/TODO.md deleted file mode 100644 index 213aaec..0000000 --- a/vendor/github.com/nats-io/nats.go/TODO.md +++ /dev/null @@ -1,26 +0,0 @@ - -- [ ] Better constructors, options handling -- [ ] Functions for callback settings after connection created. -- [ ] Better options for subscriptions. Slow Consumer state settable, Go routines vs Inline. -- [ ] Move off of channels for subscribers, use syncPool linkedLists, etc with highwater. -- [ ] Test for valid subjects on publish and subscribe? -- [ ] SyncSubscriber and Next for EncodedConn -- [ ] Fast Publisher? -- [ ] pooling for structs used? leaky bucket? -- [ ] Timeout 0 should work as no timeout -- [x] Ping timer -- [x] Name in Connect for gnatsd -- [x] Asynchronous error handling -- [x] Parser rewrite -- [x] Reconnect -- [x] Hide Lock -- [x] Easier encoder interface -- [x] QueueSubscribeSync -- [x] Make nats specific errors prefixed with 'nats:' -- [x] API test for closed connection -- [x] TLS/SSL -- [x] Stats collection -- [x] Disconnect detection -- [x] Optimized Publish (coalescing) -- [x] Do Examples via Go style -- [x] Standardized Errors diff --git a/vendor/github.com/nats-io/nats.go/context.go b/vendor/github.com/nats-io/nats.go/context.go index 4aa3bf0..b3dfa4f 100644 --- a/vendor/github.com/nats-io/nats.go/context.go +++ b/vendor/github.com/nats-io/nats.go/context.go @@ -1,4 +1,4 @@ -// Copyright 2016-2018 The NATS Authors +// Copyright 2016-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,7 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// A Go client for the NATS messaging system (https://nats.io). package nats import ( @@ -22,20 +21,13 @@ import ( // RequestMsgWithContext takes a context, a subject and payload // in bytes and request expecting a single response. func (nc *Conn) RequestMsgWithContext(ctx context.Context, msg *Msg) (*Msg, error) { - var hdr []byte - var err error - - if len(msg.Header) > 0 { - if !nc.info.Headers { - return nil, ErrHeadersNotSupported - } - - hdr, err = msg.headerBytes() - if err != nil { - return nil, err - } + if msg == nil { + return nil, ErrInvalidMsg + } + hdr, err := msg.headerBytes() + if err != nil { + return nil, err } - return nc.requestWithContext(ctx, msg.Subject, hdr, msg.Data) } @@ -93,17 +85,17 @@ func (nc *Conn) requestWithContext(ctx context.Context, subj string, hdr, data [ // oldRequestWithContext utilizes inbox and subscription per request. func (nc *Conn) oldRequestWithContext(ctx context.Context, subj string, hdr, data []byte) (*Msg, error) { - inbox := NewInbox() + inbox := nc.NewInbox() ch := make(chan *Msg, RequestChanLen) - s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, true) + s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, nil, true, nil) if err != nil { return nil, err } s.AutoUnsubscribe(1) defer s.Unsubscribe() - err = nc.publish(subj, inbox, hdr, data) + err = nc.publish(subj, inbox, false, hdr, data) if err != nil { return nil, err } @@ -111,10 +103,7 @@ func (nc *Conn) oldRequestWithContext(ctx context.Context, subj string, hdr, dat return s.NextMsgWithContext(ctx) } -// NextMsgWithContext takes a context and returns the next message -// available to a synchronous subscriber, blocking until it is delivered -// or context gets canceled. -func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) { +func (s *Subscription) nextMsgWithContext(ctx context.Context, pullSubInternal, waitIfNoMsg bool) (*Msg, error) { if ctx == nil { return nil, ErrInvalidContext } @@ -126,7 +115,7 @@ func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) { } s.mu.Lock() - err := s.validateNextMsgState() + err := s.validateNextMsgState(pullSubInternal) if err != nil { s.mu.Unlock() return nil, err @@ -147,10 +136,14 @@ func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) { } if err := s.processNextMsgDelivered(msg); err != nil { return nil, err - } else { - return msg, nil } + return msg, nil default: + // If internal and we don't want to wait, signal that there is no + // message in the internal queue. + if pullSubInternal && !waitIfNoMsg { + return nil, errNoMessages + } } select { @@ -168,6 +161,13 @@ func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) { return msg, nil } +// NextMsgWithContext takes a context and returns the next message +// available to a synchronous subscriber, blocking until it is delivered +// or context gets canceled. +func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) { + return s.nextMsgWithContext(ctx, false, true) +} + // FlushWithContext will allow a context to control the duration // of a Flush() call. This context should be non-nil and should // have a deadline set. We will return an error if none is present. @@ -216,8 +216,10 @@ func (nc *Conn) FlushWithContext(ctx context.Context) error { // RequestWithContext will create an Inbox and perform a Request // using the provided cancellation context with the Inbox reply -// for the data v. A response will be decoded into the vPtrResponse. -func (c *EncodedConn) RequestWithContext(ctx context.Context, subject string, v interface{}, vPtr interface{}) error { +// for the data v. A response will be decoded into the vPtr last parameter. +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) RequestWithContext(ctx context.Context, subject string, v any, vPtr any) error { if ctx == nil { return ErrInvalidContext } diff --git a/vendor/github.com/nats-io/nats.go/dependencies.md b/vendor/github.com/nats-io/nats.go/dependencies.md new file mode 100644 index 0000000..ec9ab3c --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/dependencies.md @@ -0,0 +1,15 @@ +# External Dependencies + +This file lists the dependencies used in this repository. + +| Dependency | License | +|-----------------------------------|--------------| +| Go | BSD 3-Clause | +| github.com/golang/protobuf/proto | BSD-3-Clause | +| github.com/klauspost/compress | BSD-3-Clause | +| github.com/nats-io/nats-server/v2 | Apache-2.0 | +| github.com/nats-io/nkeys | Apache-2.0 | +| github.com/nats-io/nuid | Apache-2.0 | +| go.uber.org/goleak | MIT | +| golang.org/x/text | BSD-3-Clause | +| google.golang.org/protobuf | BSD-3-Clause | diff --git a/vendor/github.com/nats-io/nats.go/dependencies.tpl b/vendor/github.com/nats-io/nats.go/dependencies.tpl new file mode 100644 index 0000000..41cd374 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/dependencies.tpl @@ -0,0 +1,9 @@ +# External Dependencies + +This file lists the dependencies used in this repository. + +{{/* compress has actually a BSD 3-Clause license, but the License file in the repo confuses go-license tooling, hence the manual exception */}} +| Dependency | License | +|--------------------------------------------------|-----------------------------------------| +{{ range . }}| {{ .Name }} | {{ if eq .Name "github.com/klauspost/compress/flate" }}BSD 3-Clause{{ else }}{{ .LicenseName }}{{ end }} | +{{ end }} diff --git a/vendor/github.com/nats-io/nats.go/enc.go b/vendor/github.com/nats-io/nats.go/enc.go index 38149c9..f2297b4 100644 --- a/vendor/github.com/nats-io/nats.go/enc.go +++ b/vendor/github.com/nats-io/nats.go/enc.go @@ -1,4 +1,4 @@ -// Copyright 2012-2019 The NATS Authors +// Copyright 2012-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -24,10 +24,14 @@ import ( "github.com/nats-io/nats.go/encoders/builtin" ) +//lint:file-ignore SA1019 Ignore deprecation warnings for EncodedConn + // Encoder interface is for all register encoders +// +// Deprecated: Encoded connections are no longer supported. type Encoder interface { - Encode(subject string, v interface{}) ([]byte, error) - Decode(subject string, data []byte, vPtr interface{}) error + Encode(subject string, v any) ([]byte, error) + Decode(subject string, data []byte, vPtr any) error } var encMap map[string]Encoder @@ -51,6 +55,8 @@ func init() { // EncodedConn are the preferred way to interface with NATS. They wrap a bare connection to // a nats server and have an extendable encoder system that will encode and decode messages // from raw Go types. +// +// Deprecated: Encoded connections are no longer supported. type EncodedConn struct { Conn *Conn Enc Encoder @@ -58,6 +64,8 @@ type EncodedConn struct { // NewEncodedConn will wrap an existing Connection and utilize the appropriate registered // encoder. +// +// Deprecated: Encoded connections are no longer supported. func NewEncodedConn(c *Conn, encType string) (*EncodedConn, error) { if c == nil { return nil, errors.New("nats: Nil Connection") @@ -73,6 +81,8 @@ func NewEncodedConn(c *Conn, encType string) (*EncodedConn, error) { } // RegisterEncoder will register the encType with the given Encoder. Useful for customization. +// +// Deprecated: Encoded connections are no longer supported. func RegisterEncoder(encType string, enc Encoder) { encLock.Lock() defer encLock.Unlock() @@ -80,6 +90,8 @@ func RegisterEncoder(encType string, enc Encoder) { } // EncoderForType will return the registered Encoder for the encType. +// +// Deprecated: Encoded connections are no longer supported. func EncoderForType(encType string) Encoder { encLock.Lock() defer encLock.Unlock() @@ -88,29 +100,35 @@ func EncoderForType(encType string) Encoder { // Publish publishes the data argument to the given subject. The data argument // will be encoded using the associated encoder. -func (c *EncodedConn) Publish(subject string, v interface{}) error { +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) Publish(subject string, v any) error { b, err := c.Enc.Encode(subject, v) if err != nil { return err } - return c.Conn.publish(subject, _EMPTY_, nil, b) + return c.Conn.publish(subject, _EMPTY_, false, nil, b) } // PublishRequest will perform a Publish() expecting a response on the // reply subject. Use Request() for automatically waiting for a response // inline. -func (c *EncodedConn) PublishRequest(subject, reply string, v interface{}) error { +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) PublishRequest(subject, reply string, v any) error { b, err := c.Enc.Encode(subject, v) if err != nil { return err } - return c.Conn.publish(subject, reply, nil, b) + return c.Conn.publish(subject, reply, true, nil, b) } // Request will create an Inbox and perform a Request() call // with the Inbox reply for the data v. A response will be // decoded into the vPtr Response. -func (c *EncodedConn) Request(subject string, v interface{}, vPtr interface{}, timeout time.Duration) error { +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) Request(subject string, v any, vPtr any, timeout time.Duration) error { b, err := c.Enc.Encode(subject, v) if err != nil { return err @@ -129,8 +147,8 @@ func (c *EncodedConn) Request(subject string, v interface{}, vPtr interface{}, t } // Handler is a specific callback used for Subscribe. It is generalized to -// an interface{}, but we will discover its format and arguments at runtime -// and perform the correct callback, including de-marshaling encoded data +// an any, but we will discover its format and arguments at runtime +// and perform the correct callback, including demarshaling encoded data // back into the appropriate struct based on the signature of the Handler. // // Handlers are expected to have one of four signatures. @@ -150,7 +168,9 @@ func (c *EncodedConn) Request(subject string, v interface{}, vPtr interface{}, t // and demarshal it into the given struct, e.g. person. // There are also variants where the callback wants either the subject, or the // subject and the reply subject. -type Handler interface{} +// +// Deprecated: Encoded connections are no longer supported. +type Handler any // Dissect the cb Handler's signature func argInfo(cb Handler) (reflect.Type, int) { @@ -170,6 +190,8 @@ var emptyMsgType = reflect.TypeOf(&Msg{}) // Subscribe will create a subscription on the given subject and process incoming // messages using the specified Handler. The Handler should be a func that matches // a signature from the description of Handler from above. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) Subscribe(subject string, cb Handler) (*Subscription, error) { return c.subscribe(subject, _EMPTY_, cb) } @@ -177,6 +199,8 @@ func (c *EncodedConn) Subscribe(subject string, cb Handler) (*Subscription, erro // QueueSubscribe will create a queue subscription on the given subject and process // incoming messages using the specified Handler. The Handler should be a func that // matches a signature from the description of Handler from above. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) QueueSubscribe(subject, queue string, cb Handler) (*Subscription, error) { return c.subscribe(subject, queue, cb) } @@ -234,22 +258,28 @@ func (c *EncodedConn) subscribe(subject, queue string, cb Handler) (*Subscriptio cbValue.Call(oV) } - return c.Conn.subscribe(subject, queue, natsCB, nil, false) + return c.Conn.subscribe(subject, queue, natsCB, nil, nil, false, nil) } // FlushTimeout allows a Flush operation to have an associated timeout. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) FlushTimeout(timeout time.Duration) (err error) { return c.Conn.FlushTimeout(timeout) } // Flush will perform a round trip to the server and return when it // receives the internal reply. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) Flush() error { return c.Conn.Flush() } // Close will close the connection to the server. This call will release // all blocking calls, such as Flush(), etc. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) Close() { c.Conn.Close() } @@ -259,11 +289,15 @@ func (c *EncodedConn) Close() { // will be drained and can not publish any additional messages. Upon draining // of the publishers, the connection will be closed. Use the ClosedCB() // option to know when the connection has moved from draining to closed. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) Drain() error { return c.Conn.Drain() } // LastError reports the last error encountered via the Connection. +// +// Deprecated: Encoded connections are no longer supported. func (c *EncodedConn) LastError() error { - return c.Conn.err + return c.Conn.LastError() } diff --git a/vendor/github.com/nats-io/nats.go/encoders/builtin/default_enc.go b/vendor/github.com/nats-io/nats.go/encoders/builtin/default_enc.go index 46d918e..e73113d 100644 --- a/vendor/github.com/nats-io/nats.go/encoders/builtin/default_enc.go +++ b/vendor/github.com/nats-io/nats.go/encoders/builtin/default_enc.go @@ -1,4 +1,4 @@ -// Copyright 2012-2018 The NATS Authors +// Copyright 2012-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -24,8 +24,10 @@ import ( // DefaultEncoder implementation for EncodedConn. // This encoder will leave []byte and string untouched, but will attempt to // turn numbers into appropriate strings that can be decoded. It will also -// propely encoded and decode bools. If will encode a struct, but if you want +// properly encoded and decode bools. If will encode a struct, but if you want // to properly handle structures you should use JsonEncoder. +// +// Deprecated: Encoded connections are no longer supported. type DefaultEncoder struct { // Empty } @@ -35,7 +37,9 @@ var falseB = []byte("false") var nilB = []byte("") // Encode -func (je *DefaultEncoder) Encode(subject string, v interface{}) ([]byte, error) { +// +// Deprecated: Encoded connections are no longer supported. +func (je *DefaultEncoder) Encode(subject string, v any) ([]byte, error) { switch arg := v.(type) { case string: bytes := *(*[]byte)(unsafe.Pointer(&arg)) @@ -58,7 +62,9 @@ func (je *DefaultEncoder) Encode(subject string, v interface{}) ([]byte, error) } // Decode -func (je *DefaultEncoder) Decode(subject string, data []byte, vPtr interface{}) error { +// +// Deprecated: Encoded connections are no longer supported. +func (je *DefaultEncoder) Decode(subject string, data []byte, vPtr any) error { // Figure out what it's pointing to... sData := *(*string)(unsafe.Pointer(&data)) switch arg := vPtr.(type) { diff --git a/vendor/github.com/nats-io/nats.go/encoders/builtin/gob_enc.go b/vendor/github.com/nats-io/nats.go/encoders/builtin/gob_enc.go index 632bcbd..e2e8c32 100644 --- a/vendor/github.com/nats-io/nats.go/encoders/builtin/gob_enc.go +++ b/vendor/github.com/nats-io/nats.go/encoders/builtin/gob_enc.go @@ -1,4 +1,4 @@ -// Copyright 2013-2018 The NATS Authors +// Copyright 2013-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -21,6 +21,8 @@ import ( // GobEncoder is a Go specific GOB Encoder implementation for EncodedConn. // This encoder will use the builtin encoding/gob to Marshal // and Unmarshal most types, including structs. +// +// Deprecated: Encoded connections are no longer supported. type GobEncoder struct { // Empty } @@ -28,7 +30,9 @@ type GobEncoder struct { // FIXME(dlc) - This could probably be more efficient. // Encode -func (ge *GobEncoder) Encode(subject string, v interface{}) ([]byte, error) { +// +// Deprecated: Encoded connections are no longer supported. +func (ge *GobEncoder) Encode(subject string, v any) ([]byte, error) { b := new(bytes.Buffer) enc := gob.NewEncoder(b) if err := enc.Encode(v); err != nil { @@ -38,7 +42,9 @@ func (ge *GobEncoder) Encode(subject string, v interface{}) ([]byte, error) { } // Decode -func (ge *GobEncoder) Decode(subject string, data []byte, vPtr interface{}) (err error) { +// +// Deprecated: Encoded connections are no longer supported. +func (ge *GobEncoder) Decode(subject string, data []byte, vPtr any) (err error) { dec := gob.NewDecoder(bytes.NewBuffer(data)) err = dec.Decode(vPtr) return diff --git a/vendor/github.com/nats-io/nats.go/encoders/builtin/json_enc.go b/vendor/github.com/nats-io/nats.go/encoders/builtin/json_enc.go index c9670f3..8e4c852 100644 --- a/vendor/github.com/nats-io/nats.go/encoders/builtin/json_enc.go +++ b/vendor/github.com/nats-io/nats.go/encoders/builtin/json_enc.go @@ -1,4 +1,4 @@ -// Copyright 2012-2018 The NATS Authors +// Copyright 2012-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -21,12 +21,16 @@ import ( // JsonEncoder is a JSON Encoder implementation for EncodedConn. // This encoder will use the builtin encoding/json to Marshal // and Unmarshal most types, including structs. +// +// Deprecated: Encoded connections are no longer supported. type JsonEncoder struct { // Empty } // Encode -func (je *JsonEncoder) Encode(subject string, v interface{}) ([]byte, error) { +// +// Deprecated: Encoded connections are no longer supported. +func (je *JsonEncoder) Encode(subject string, v any) ([]byte, error) { b, err := json.Marshal(v) if err != nil { return nil, err @@ -35,7 +39,9 @@ func (je *JsonEncoder) Encode(subject string, v interface{}) ([]byte, error) { } // Decode -func (je *JsonEncoder) Decode(subject string, data []byte, vPtr interface{}) (err error) { +// +// Deprecated: Encoded connections are no longer supported. +func (je *JsonEncoder) Decode(subject string, data []byte, vPtr any) (err error) { switch arg := vPtr.(type) { case *string: // If they want a string and it is a JSON string, strip quotes diff --git a/vendor/github.com/nats-io/nats.go/go.mod b/vendor/github.com/nats-io/nats.go/go.mod deleted file mode 100644 index 383f223..0000000 --- a/vendor/github.com/nats-io/nats.go/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module github.com/nats-io/nats.go - -go 1.14 - -require ( - github.com/golang/protobuf v1.4.2 - github.com/nats-io/nats-server/v2 v2.1.8-0.20200929001935-7f44d075f7ad - github.com/nats-io/nkeys v0.2.0 - github.com/nats-io/nuid v1.0.1 - google.golang.org/protobuf v1.23.0 -) diff --git a/vendor/github.com/nats-io/nats.go/go.sum b/vendor/github.com/nats-io/nats.go/go.sum deleted file mode 100644 index 1419245..0000000 --- a/vendor/github.com/nats-io/nats.go/go.sum +++ /dev/null @@ -1,54 +0,0 @@ -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA= -github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7 h1:RnGotxlghqR5D2KDAu4TyuLqyjuylOsJiAFhXvMvQIc= -github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= -github.com/nats-io/jwt/v2 v2.0.0-20200916203241-1f8ce17dff02 h1:WloZv3SCb55D/rOHYy1rWBXLrj3BYc9zw8VIq6X54lI= -github.com/nats-io/jwt/v2 v2.0.0-20200916203241-1f8ce17dff02/go.mod h1:vs+ZEjP+XKy8szkBmQwCB7RjYdIlMaPsFPs4VdS4bTQ= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200524125952-51ebd92a9093/go.mod h1:rQnBf2Rv4P9adtAs/Ti6LfFmVtFG6HLhl/H7cVshcJU= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200601203034-f8d6dd992b71 h1:nexMtKbOeM+w3vGQMNF0BEt+2xZDmVCtYXql2Ym+RWg= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200601203034-f8d6dd992b71/go.mod h1:Nan/1L5Sa1JRW+Thm4HNYcIDcVRFc5zK9OpSZeI2kk4= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200929001935-7f44d075f7ad h1:oRb9MIi1Y4N5cTZWciqH68aVNt1e+o4N2uRnjVzv/UE= -github.com/nats-io/nats-server/v2 v2.1.8-0.20200929001935-7f44d075f7ad/go.mod h1:TkHpUIDETmTI7mrHN40D1pzxfzHZuGmtMbtb83TGVQw= -github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= -github.com/nats-io/nats.go v1.10.1-0.20200531124210-96f2130e4d55/go.mod h1:ARiFsjW9DVxk48WJbO3OSZ2DG8fjkMi7ecLmXoY/n9I= -github.com/nats-io/nats.go v1.10.1-0.20200606002146-fc6fed82929a/go.mod h1:8eAIv96Mo9QW6Or40jUHejS7e4VwZ3VRYD6Sf0BTDp4= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= diff --git a/vendor/github.com/nats-io/nats.go/go_test.mod b/vendor/github.com/nats-io/nats.go/go_test.mod new file mode 100644 index 0000000..c3b7499 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/go_test.mod @@ -0,0 +1,22 @@ +module github.com/nats-io/nats.go + +go 1.24.0 + +require ( + github.com/golang/protobuf v1.4.2 + github.com/klauspost/compress v1.18.0 + github.com/nats-io/jwt/v2 v2.8.0 + github.com/nats-io/nats-server/v2 v2.12.0 + github.com/nats-io/nkeys v0.4.11 + github.com/nats-io/nuid v1.0.1 + google.golang.org/protobuf v1.23.0 +) + +require ( + github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op // indirect + github.com/google/go-tpm v0.9.5 // indirect + github.com/minio/highwayhash v1.0.3 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/time v0.13.0 // indirect +) diff --git a/vendor/github.com/nats-io/nats.go/go_test.sum b/vendor/github.com/nats-io/nats.go/go_test.sum new file mode 100644 index 0000000..9b1b8c3 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/go_test.sum @@ -0,0 +1,43 @@ +github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op h1:+OSa/t11TFhqfrX0EOSqQBDJ0YlpmK0rDSiB19dg9M0= +github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU= +github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= +github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g= +github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA= +github.com/nats-io/nats-server/v2 v2.12.0 h1:OIwe8jZUqJFrh+hhiyKu8snNib66qsx806OslqJuo74= +github.com/nats-io/nats-server/v2 v2.12.0/go.mod h1:nr8dhzqkP5E/lDwmn+A2CvQPMd1yDKXQI7iGg3lAvww= +github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0= +github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= diff --git a/vendor/github.com/nats-io/nats.go/internal/parser/parse.go b/vendor/github.com/nats-io/nats.go/internal/parser/parse.go new file mode 100644 index 0000000..7eab8ad --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/internal/parser/parse.go @@ -0,0 +1,104 @@ +// Copyright 2020-2022 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "errors" + "fmt" +) + +const ( + AckDomainTokenPos = iota + 2 + AckAccHashTokenPos + AckStreamTokenPos + AckConsumerTokenPos + AckNumDeliveredTokenPos + AckStreamSeqTokenPos + AckConsumerSeqTokenPos + AckTimestampSeqTokenPos + AckNumPendingTokenPos +) + +var ErrInvalidSubjectFormat = errors.New("invalid format of ACK subject") + +// Quick parser for positive numbers in ack reply encoding. +// NOTE: This parser does not detect uint64 overflow +func ParseNum(d string) (n uint64) { + if len(d) == 0 { + return 0 + } + + // ASCII numbers 0-9 + const ( + asciiZero = 48 + asciiNine = 57 + ) + + for _, dec := range d { + if dec < asciiZero || dec > asciiNine { + return 0 + } + n = n*10 + uint64(dec) - asciiZero + } + return +} + +func GetMetadataFields(subject string) ([]string, error) { + v1TokenCounts, v2TokenCounts := 9, 12 + + var start int + tokens := make([]string, 0, v2TokenCounts) + for i := 0; i < len(subject); i++ { + if subject[i] == '.' { + tokens = append(tokens, subject[start:i]) + start = i + 1 + } + } + tokens = append(tokens, subject[start:]) + // + // Newer server will include the domain name and account hash in the subject, + // and a token at the end. + // + // Old subject was: + // $JS.ACK....... + // + // New subject would be: + // $JS.ACK.......... + // + // v1 has 9 tokens, v2 has 12, but we must not be strict on the 12th since + // it may be removed in the future. Also, the library has no use for it. + // The point is that a v2 ACK subject is valid if it has at least 11 tokens. + // + tokensLen := len(tokens) + // If lower than 9 or more than 9 but less than 11, report an error + if tokensLen < v1TokenCounts || (tokensLen > v1TokenCounts && tokensLen < v2TokenCounts-1) { + return nil, ErrInvalidSubjectFormat + } + if tokens[0] != "$JS" || tokens[1] != "ACK" { + return nil, fmt.Errorf("%w: subject should start with $JS.ACK", ErrInvalidSubjectFormat) + } + // For v1 style, we insert 2 empty tokens (domain and hash) so that the + // rest of the library references known fields at a constant location. + if tokensLen == v1TokenCounts { + // Extend the array (we know the backend is big enough) + tokens = append(tokens[:AckDomainTokenPos+2], tokens[AckDomainTokenPos:]...) + // Clear the domain and hash tokens + tokens[AckDomainTokenPos], tokens[AckAccHashTokenPos] = "", "" + + } else if tokens[AckDomainTokenPos] == "_" { + // If domain is "_", replace with empty value. + tokens[AckDomainTokenPos] = "" + } + return tokens, nil +} diff --git a/vendor/github.com/nats-io/nats.go/jetstream.go b/vendor/github.com/nats-io/nats.go/jetstream.go deleted file mode 100644 index 4d2691c..0000000 --- a/vendor/github.com/nats-io/nats.go/jetstream.go +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2020 The NATS Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package nats - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "strconv" - "time" -) - -// JetStreamMsgMetaData is metadata related to a JetStream originated message -type JetStreamMsgMetaData struct { - Stream string - Consumer string - Parsed bool - Delivered int - StreamSeq int - ConsumerSeq int - TimeStamp time.Time -} - -func (m *Msg) JetStreamMetaData() (*JetStreamMsgMetaData, error) { - var err error - - if m.jsMeta != nil && m.jsMeta.Parsed { - return m.jsMeta, nil - } - - m.jsMeta, err = m.parseJSMsgMetadata() - - return m.jsMeta, err -} - -func (m *Msg) parseJSMsgMetadata() (*JetStreamMsgMetaData, error) { - if m.jsMeta != nil { - return m.jsMeta, nil - } - - if len(m.Reply) == 0 { - return nil, ErrNotJSMessage - } - - meta := &JetStreamMsgMetaData{} - - tsa := [32]string{} - parts := tsa[:0] - start := 0 - btsep := byte('.') - for i := 0; i < len(m.Reply); i++ { - if m.Reply[i] == btsep { - parts = append(parts, m.Reply[start:i]) - start = i + 1 - } - } - parts = append(parts, m.Reply[start:]) - - if len(parts) != 8 || parts[0] != "$JS" || parts[1] != "ACK" { - return nil, ErrNotJSMessage - } - - var err error - - meta.Stream = parts[2] - meta.Consumer = parts[3] - meta.Delivered, err = strconv.Atoi(parts[4]) - if err != nil { - return nil, ErrNotJSMessage - } - - meta.StreamSeq, err = strconv.Atoi(parts[5]) - if err != nil { - return nil, ErrNotJSMessage - } - - meta.ConsumerSeq, err = strconv.Atoi(parts[6]) - if err != nil { - return nil, ErrNotJSMessage - } - - tsi, err := strconv.Atoi(parts[7]) - if err != nil { - return nil, ErrNotJSMessage - } - meta.TimeStamp = time.Unix(0, int64(tsi)) - - meta.Parsed = true - - return meta, nil -} - -const jsStreamUnspecified = "not.set" - -type jsOpts struct { - timeout time.Duration - ctx context.Context - - ackstr string - consumer *ConsumerConfig - streamName string -} - -func newJsOpts() *jsOpts { - return &jsOpts{ackstr: jsStreamUnspecified, consumer: &ConsumerConfig{}} -} - -func (j *jsOpts) context(dftl time.Duration) (context.Context, context.CancelFunc) { - if j.ctx != nil { - return context.WithCancel(j.ctx) - } - - if j.timeout == 0 { - j.timeout = dftl - } - - return context.WithTimeout(context.Background(), j.timeout) -} - -// AckOption configures the various JetStream message acknowledgement helpers -type AckOption func(opts *jsOpts) error - -// PublishOption configures publishing messages -type PublishOption func(opts *jsOpts) error - -// SubscribeOption configures JetStream consumer behavior -type SubscribeOption func(opts *jsOpts) error - -// Consumer creates a JetStream Consumer on a Stream -func Consumer(stream string, cfg ConsumerConfig) SubscribeOption { - return func(jopts *jsOpts) error { - jopts.consumer = &cfg - jopts.streamName = stream - return nil - } -} - -// PublishExpectsStream waits for an ack after publishing and ensure it's from a specific stream, empty arguments waits for any valid acknowledgement -func PublishExpectsStream(stream ...string) PublishOption { - return func(opts *jsOpts) error { - switch len(stream) { - case 0: - opts.ackstr = "" - case 1: - opts.ackstr = stream[0] - if !isValidJSName(opts.ackstr) { - return ErrInvalidStreamName - } - default: - return ErrMultiStreamUnsupported - } - - return nil - } -} - -// PublishStreamTimeout sets the period of time to wait for JetStream to acknowledge receipt, defaults to JetStreamTimeout option -func PublishStreamTimeout(t time.Duration) PublishOption { - return func(opts *jsOpts) error { - opts.timeout = t - return nil - } -} - -// PublishCtx sets an interrupt context for waiting on a stream to reply -func PublishCtx(ctx context.Context) PublishOption { - return func(opts *jsOpts) error { - opts.ctx = ctx - return nil - } -} - -// AckWaitDuration waits for confirmation from the JetStream server -func AckWaitDuration(d time.Duration) AckOption { - return func(opts *jsOpts) error { - opts.timeout = d - return nil - } -} - -func (m *Msg) jsAck(body []byte, opts ...AckOption) error { - if m.Reply == "" { - return ErrMsgNoReply - } - - if m == nil || m.Sub == nil { - return ErrMsgNotBound - } - - m.Sub.mu.Lock() - nc := m.Sub.conn - m.Sub.mu.Unlock() - - var err error - var aopts *jsOpts - - if len(opts) > 0 { - aopts = newJsOpts() - for _, f := range opts { - if err = f(aopts); err != nil { - return err - } - } - } - - if aopts == nil || aopts.timeout == 0 { - return m.Respond(body) - } - - _, err = nc.Request(m.Reply, body, aopts.timeout) - - return err -} - -// Ack acknowledges a JetStream messages received from a Consumer, indicating the message -// should not be received again later -func (m *Msg) Ack(opts ...AckOption) error { - return m.jsAck(AckAck, opts...) -} - -// Nak acknowledges a JetStream message received from a Consumer, indicating that the message -// is not completely processed and should be sent again later -func (m *Msg) Nak(opts ...AckOption) error { - return m.jsAck(AckNak, opts...) -} - -// AckProgress acknowledges a Jetstream message received from a Consumer, indicating that work is -// ongoing and further processing time is required equal to the configured AckWait of the Consumer -func (m *Msg) AckProgress(opts ...AckOption) error { - return m.jsAck(AckProgress, opts...) -} - -// AckNext performs an Ack() and request that the next message be sent to subject ib -func (m *Msg) AckNext(ib string) error { - return m.RespondMsg(&Msg{Subject: m.Reply, Reply: ib, Data: AckNext}) -} - -// AckAndFetch performs an AckNext() and returns the next message from the stream -func (m *Msg) AckAndFetch(opts ...AckOption) (*Msg, error) { - if m.Reply == "" { - return nil, ErrMsgNoReply - } - - if m == nil || m.Sub == nil { - return nil, ErrMsgNotBound - } - - m.Sub.mu.Lock() - nc := m.Sub.conn - m.Sub.mu.Unlock() - - var err error - - aopts := newJsOpts() - for _, f := range opts { - if err = f(aopts); err != nil { - return nil, err - } - } - - ctx, cancel := aopts.context(nc.Opts.JetStreamTimeout) - defer cancel() - - sub, err := nc.SubscribeSync(NewInbox()) - if err != nil { - return nil, err - } - sub.AutoUnsubscribe(1) - defer sub.Unsubscribe() - - err = m.RespondMsg(&Msg{Reply: sub.Subject, Data: AckNext, Subject: m.Reply}) - if err != nil { - return nil, err - } - nc.Flush() - - return sub.NextMsgWithContext(ctx) -} - -// AckTerm acknowledges a message received from JetStream indicating the message will not be processed -// and should not be sent to another consumer -func (m *Msg) AckTerm(opts ...AckOption) error { - return m.jsAck(AckTerm, opts...) -} - -// JetStreamPublishAck metadata received from JetStream when publishing messages -type JetStreamPublishAck struct { - Stream string `json:"stream"` - Sequence int `json:"seq"` -} - -// ParsePublishAck parses the publish acknowledgement sent by JetStream -func ParsePublishAck(m []byte) (*JetStreamPublishAck, error) { - if bytes.HasPrefix([]byte("-ERR"), m) { - if len(m) > 7 { - return nil, fmt.Errorf(string(m[6 : len(m)-1])) - } - - return nil, fmt.Errorf(string(m)) - } - - if !bytes.HasPrefix(m, []byte("+OK {")) { - return nil, fmt.Errorf("invalid JetStream Ack: %v", string(m)) - } - - ack := &JetStreamPublishAck{} - err := json.Unmarshal(m[3:], ack) - return ack, err -} - -func (nc *Conn) jsPublish(subj string, data []byte, opts []PublishOption) error { - var err error - var aopts *jsOpts - - if len(opts) > 0 { - aopts = newJsOpts() - for _, f := range opts { - if err = f(aopts); err != nil { - return err - } - } - } - - if aopts == nil || aopts.timeout == 0 && aopts.ctx == nil && aopts.ackstr == jsStreamUnspecified { - return nc.publish(subj, _EMPTY_, nil, data) - } - - ctx, cancel := aopts.context(nc.Opts.JetStreamTimeout) - defer cancel() - - resp, err := nc.RequestWithContext(ctx, subj, data) - if err != nil { - return err - } - - ack, err := ParsePublishAck(resp.Data) - if err != nil { - return err - } - - if ack.Stream == "" || ack.Sequence == 0 { - return ErrInvalidJSAck - } - - if aopts.ackstr == jsStreamUnspecified || aopts.ackstr == "" { - return nil - } - - if ack.Stream == aopts.ackstr { - return nil - } - - return fmt.Errorf("received ack from stream %q", ack.Stream) -} diff --git a/vendor/github.com/nats-io/nats.go/jetstream_consumer.go b/vendor/github.com/nats-io/nats.go/jetstream_consumer.go deleted file mode 100644 index 9c59859..0000000 --- a/vendor/github.com/nats-io/nats.go/jetstream_consumer.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2020 The NATS Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package nats - -import ( - "encoding/json" - "fmt" - "strings" - "time" -) - -func (nc *Conn) createOrUpdateConsumer(opts *jsOpts, delivery string) (*ConsumerInfo, error) { - if opts.streamName == "" { - return nil, ErrStreamNameRequired - } - if opts.consumer == nil { - return nil, ErrConsumerConfigRequired - } - - crj, err := json.Marshal(&jSApiConsumerCreateRequest{ - Stream: opts.streamName, - Config: consumerConfig{DeliverSubject: delivery, ConsumerConfig: opts.consumer}, - }) - if err != nil { - return nil, err - } - - ctx, cancel := opts.context(nc.Opts.JetStreamTimeout) - defer cancel() - - var subj string - switch len(opts.consumer.Durable) { - case 0: - subj = fmt.Sprintf(jSApiConsumerCreateT, opts.streamName) - default: - subj = fmt.Sprintf(jSApiDurableCreateT, opts.streamName, opts.consumer.Durable) - } - - resp, err := nc.RequestWithContext(ctx, subj, crj) - if err != nil { - return nil, err - } - - cresp := &jSApiConsumerCreateResponse{} - err = json.Unmarshal(resp.Data, cresp) - if err != nil { - return nil, err - } - - if cresp.Error != nil { - return nil, cresp.Error - } - - return cresp.ConsumerInfo, nil -} - -const ( - jSApiConsumerCreateT = "$JS.API.CONSUMER.CREATE.%s" - jSApiDurableCreateT = "$JS.API.CONSUMER.DURABLE.CREATE.%s.%s" -) - -type apiError struct { - Code int `json:"code"` - Description string `json:"description,omitempty"` -} - -// Error implements error -func (e apiError) Error() string { - switch { - case e.Description == "" && e.Code == 0: - return "unknown JetStream Error" - case e.Description == "" && e.Code > 0: - return fmt.Sprintf("unknown JetStream %d Error", e.Code) - default: - return e.Description - } -} - -type jSApiResponse struct { - Type string `json:"type"` - Error *apiError `json:"error,omitempty"` -} - -// io.nats.jetstream.api.v1.consumer_create_request -type jSApiConsumerCreateRequest struct { - Stream string `json:"stream_name"` - Config consumerConfig `json:"config"` -} - -// io.nats.jetstream.api.v1.consumer_create_response -type jSApiConsumerCreateResponse struct { - jSApiResponse - *ConsumerInfo -} - -type AckPolicy int - -const ( - AckNone AckPolicy = iota - AckAll - AckExplicit -) - -func (p *AckPolicy) UnmarshalJSON(data []byte) error { - switch string(data) { - case jsonString("none"): - *p = AckNone - case jsonString("all"): - *p = AckAll - case jsonString("explicit"): - *p = AckExplicit - default: - return fmt.Errorf("can not unmarshal %q", data) - } - - return nil -} - -func (p AckPolicy) MarshalJSON() ([]byte, error) { - switch p { - case AckNone: - return json.Marshal("none") - case AckAll: - return json.Marshal("all") - case AckExplicit: - return json.Marshal("explicit") - default: - return nil, fmt.Errorf("unknown acknowlegement policy %v", p) - } -} - -type ReplayPolicy int - -const ( - ReplayInstant ReplayPolicy = iota - ReplayOriginal -) - -func (p *ReplayPolicy) UnmarshalJSON(data []byte) error { - switch string(data) { - case jsonString("instant"): - *p = ReplayInstant - case jsonString("original"): - *p = ReplayOriginal - default: - return fmt.Errorf("can not unmarshal %q", data) - } - - return nil -} - -func (p ReplayPolicy) MarshalJSON() ([]byte, error) { - switch p { - case ReplayOriginal: - return json.Marshal("original") - case ReplayInstant: - return json.Marshal("instant") - default: - return nil, fmt.Errorf("unknown replay policy %v", p) - } -} - -var ( - AckAck = []byte("+ACK") - AckNak = []byte("-NAK") - AckProgress = []byte("+WPI") - AckNext = []byte("+NXT") - AckTerm = []byte("+TERM") -) - -type DeliverPolicy int - -const ( - DeliverAll DeliverPolicy = iota - DeliverLast - DeliverNew - DeliverByStartSequence - DeliverByStartTime -) - -func (p *DeliverPolicy) UnmarshalJSON(data []byte) error { - switch string(data) { - case jsonString("all"), jsonString("undefined"): - *p = DeliverAll - case jsonString("last"): - *p = DeliverLast - case jsonString("new"): - *p = DeliverNew - case jsonString("by_start_sequence"): - *p = DeliverByStartSequence - case jsonString("by_start_time"): - *p = DeliverByStartTime - } - - return nil -} - -func (p DeliverPolicy) MarshalJSON() ([]byte, error) { - switch p { - case DeliverAll: - return json.Marshal("all") - case DeliverLast: - return json.Marshal("last") - case DeliverNew: - return json.Marshal("new") - case DeliverByStartSequence: - return json.Marshal("by_start_sequence") - case DeliverByStartTime: - return json.Marshal("by_start_time") - default: - return nil, fmt.Errorf("unknown deliver policy %v", p) - } -} - -// ConsumerConfig is the configuration for a JetStream consumes -type ConsumerConfig struct { - Durable string `json:"durable_name,omitempty"` - DeliverPolicy DeliverPolicy `json:"deliver_policy"` - OptStartSeq uint64 `json:"opt_start_seq,omitempty"` - OptStartTime *time.Time `json:"opt_start_time,omitempty"` - AckPolicy AckPolicy `json:"ack_policy"` - AckWait time.Duration `json:"ack_wait,omitempty"` - MaxDeliver int `json:"max_deliver,omitempty"` - FilterSubject string `json:"filter_subject,omitempty"` - ReplayPolicy ReplayPolicy `json:"replay_policy"` - SampleFrequency string `json:"sample_freq,omitempty"` - RateLimit uint64 `json:"rate_limit_bps,omitempty"` -} - -type consumerConfig struct { - DeliverSubject string `json:"deliver_subject,omitempty"` - *ConsumerConfig -} - -type SequencePair struct { - ConsumerSeq uint64 `json:"consumer_seq"` - StreamSeq uint64 `json:"stream_seq"` -} - -type ConsumerInfo struct { - Stream string `json:"stream_name"` - Name string `json:"name"` - Config ConsumerConfig `json:"config"` - Created time.Time `json:"created"` - Delivered SequencePair `json:"delivered"` - AckFloor SequencePair `json:"ack_floor"` - NumPending int `json:"num_pending"` - NumRedelivered int `json:"num_redelivered"` -} - -func jsonString(s string) string { - return "\"" + s + "\"" -} - -func isValidJSName(n string) bool { - return !(n == "" || strings.ContainsAny(n, ">*. ")) -} diff --git a/vendor/github.com/nats-io/nats.go/js.go b/vendor/github.com/nats-io/nats.go/js.go new file mode 100644 index 0000000..def5941 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/js.go @@ -0,0 +1,4132 @@ +// Copyright 2020-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nats + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/json" + "errors" + "fmt" + "math/rand" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/nats-io/nats.go/internal/parser" + "github.com/nats-io/nuid" +) + +// JetStream allows persistent messaging through JetStream. +// +// NOTE: JetStream is part of legacy API. +// Users are encouraged to switch to the new JetStream API for enhanced capabilities and +// simplified API. Please refer to the `jetstream` package. +// See: https://github.com/nats-io/nats.go/blob/main/jetstream/README.md +type JetStream interface { + // Publish publishes a message to JetStream. + Publish(subj string, data []byte, opts ...PubOpt) (*PubAck, error) + + // PublishMsg publishes a Msg to JetStream. + PublishMsg(m *Msg, opts ...PubOpt) (*PubAck, error) + + // PublishAsync publishes a message to JetStream and returns a PubAckFuture. + // The data should not be changed until the PubAckFuture has been processed. + PublishAsync(subj string, data []byte, opts ...PubOpt) (PubAckFuture, error) + + // PublishMsgAsync publishes a Msg to JetStream and returns a PubAckFuture. + // The message should not be changed until the PubAckFuture has been processed. + PublishMsgAsync(m *Msg, opts ...PubOpt) (PubAckFuture, error) + + // PublishAsyncPending returns the number of async publishes outstanding for this context. + PublishAsyncPending() int + + // PublishAsyncComplete returns a channel that will be closed when all outstanding messages are ack'd. + PublishAsyncComplete() <-chan struct{} + + // CleanupPublisher will cleanup the publishing side of JetStreamContext. + // + // This will unsubscribe from the internal reply subject if needed. + // All pending async publishes will fail with ErrJetStreamPublisherClosed. + // + // If an error handler was provided, it will be called for each pending async + // publish and PublishAsyncComplete will be closed. + // + // After completing JetStreamContext is still usable - internal subscription + // will be recreated on next publish, but the acks from previous publishes will + // be lost. + CleanupPublisher() + + // Subscribe creates an async Subscription for JetStream. + // The stream and consumer names can be provided with the nats.Bind() option. + // For creating an ephemeral (where the consumer name is picked by the server), + // you can provide the stream name with nats.BindStream(). + // If no stream name is specified, the library will attempt to figure out which + // stream the subscription is for. See important notes below for more details. + // + // IMPORTANT NOTES: + // * If none of the options Bind() nor Durable() are specified, the library will + // send a request to the server to create an ephemeral JetStream consumer, + // which will be deleted after an Unsubscribe() or Drain(), or automatically + // by the server after a short period of time after the NATS subscription is + // gone. + // * If Durable() option is specified, the library will attempt to lookup a JetStream + // consumer with this name, and if found, will bind to it and not attempt to + // delete it. However, if not found, the library will send a request to + // create such durable JetStream consumer. Note that the library will delete + // the JetStream consumer after an Unsubscribe() or Drain() only if it + // created the durable consumer while subscribing. If the durable consumer + // already existed prior to subscribing it won't be deleted. + // * If Bind() option is provided, the library will attempt to lookup the + // consumer with the given name, and if successful, bind to it. If the lookup fails, + // then the Subscribe() call will return an error. + Subscribe(subj string, cb MsgHandler, opts ...SubOpt) (*Subscription, error) + + // SubscribeSync creates a Subscription that can be used to process messages synchronously. + // See important note in Subscribe() + SubscribeSync(subj string, opts ...SubOpt) (*Subscription, error) + + // ChanSubscribe creates channel based Subscription. + // See important note in Subscribe() + ChanSubscribe(subj string, ch chan *Msg, opts ...SubOpt) (*Subscription, error) + + // ChanQueueSubscribe creates channel based Subscription with a queue group. + // See important note in QueueSubscribe() + ChanQueueSubscribe(subj, queue string, ch chan *Msg, opts ...SubOpt) (*Subscription, error) + + // QueueSubscribe creates a Subscription with a queue group. + // If no optional durable name nor binding options are specified, the queue name will be used as a durable name. + // See important note in Subscribe() + QueueSubscribe(subj, queue string, cb MsgHandler, opts ...SubOpt) (*Subscription, error) + + // QueueSubscribeSync creates a Subscription with a queue group that can be used to process messages synchronously. + // See important note in QueueSubscribe() + QueueSubscribeSync(subj, queue string, opts ...SubOpt) (*Subscription, error) + + // PullSubscribe creates a Subscription that can fetch messages. + // See important note in Subscribe(). Additionally, for an ephemeral pull consumer, the "durable" value must be + // set to an empty string. + // When using PullSubscribe, the messages are fetched using Fetch() and FetchBatch() methods. + PullSubscribe(subj, durable string, opts ...SubOpt) (*Subscription, error) +} + +// JetStreamContext allows JetStream messaging and stream management. +// +// NOTE: JetStreamContext is part of legacy API. +// Users are encouraged to switch to the new JetStream API for enhanced capabilities and +// simplified API. Please refer to the `jetstream` package. +// See: https://github.com/nats-io/nats.go/blob/main/jetstream/README.md +type JetStreamContext interface { + JetStream + JetStreamManager + KeyValueManager + ObjectStoreManager +} + +// Request API subjects for JetStream. +const ( + // defaultAPIPrefix is the default prefix for the JetStream API. + defaultAPIPrefix = "$JS.API." + + // jsDomainT is used to create JetStream API prefix by specifying only Domain + jsDomainT = "$JS.%s.API." + + // jsExtDomainT is used to create a StreamSource External APIPrefix + jsExtDomainT = "$JS.%s.API" + + // apiAccountInfo is for obtaining general information about JetStream. + apiAccountInfo = "INFO" + + // apiConsumerCreateT is used to create consumers. + // it accepts stream name and consumer name. + apiConsumerCreateT = "CONSUMER.CREATE.%s.%s" + + // apiConsumerCreateT is used to create consumers. + // it accepts stream name, consumer name and filter subject + apiConsumerCreateWithFilterSubjectT = "CONSUMER.CREATE.%s.%s.%s" + + // apiLegacyConsumerCreateT is used to create consumers. + // this is a legacy endpoint to support creating ephemerals before nats-server v2.9.0. + apiLegacyConsumerCreateT = "CONSUMER.CREATE.%s" + + // apiDurableCreateT is used to create durable consumers. + // this is a legacy endpoint to support creating durable consumers before nats-server v2.9.0. + apiDurableCreateT = "CONSUMER.DURABLE.CREATE.%s.%s" + + // apiConsumerInfoT is used to create consumers. + apiConsumerInfoT = "CONSUMER.INFO.%s.%s" + + // apiRequestNextT is the prefix for the request next message(s) for a consumer in worker/pull mode. + apiRequestNextT = "CONSUMER.MSG.NEXT.%s.%s" + + // apiConsumerDeleteT is used to delete consumers. + apiConsumerDeleteT = "CONSUMER.DELETE.%s.%s" + + // apiConsumerListT is used to return all detailed consumer information + apiConsumerListT = "CONSUMER.LIST.%s" + + // apiConsumerNamesT is used to return a list with all consumer names for the stream. + apiConsumerNamesT = "CONSUMER.NAMES.%s" + + // apiStreams can lookup a stream by subject. + apiStreams = "STREAM.NAMES" + + // apiStreamCreateT is the endpoint to create new streams. + apiStreamCreateT = "STREAM.CREATE.%s" + + // apiStreamInfoT is the endpoint to get information on a stream. + apiStreamInfoT = "STREAM.INFO.%s" + + // apiStreamUpdateT is the endpoint to update existing streams. + apiStreamUpdateT = "STREAM.UPDATE.%s" + + // apiStreamDeleteT is the endpoint to delete streams. + apiStreamDeleteT = "STREAM.DELETE.%s" + + // apiStreamPurgeT is the endpoint to purge streams. + apiStreamPurgeT = "STREAM.PURGE.%s" + + // apiStreamListT is the endpoint that will return all detailed stream information + apiStreamListT = "STREAM.LIST" + + // apiMsgGetT is the endpoint to get a message. + apiMsgGetT = "STREAM.MSG.GET.%s" + + // apiMsgGetT is the endpoint to perform a direct get of a message. + apiDirectMsgGetT = "DIRECT.GET.%s" + + // apiDirectMsgGetLastBySubjectT is the endpoint to perform a direct get of a message by subject. + apiDirectMsgGetLastBySubjectT = "DIRECT.GET.%s.%s" + + // apiMsgDeleteT is the endpoint to remove a message. + apiMsgDeleteT = "STREAM.MSG.DELETE.%s" + + // orderedHeartbeatsInterval is how fast we want HBs from the server during idle. + orderedHeartbeatsInterval = 5 * time.Second + + // Scale for threshold of missed HBs or lack of activity. + hbcThresh = 2 + + // For ChanSubscription, we can't update sub.delivered as we do for other + // type of subscriptions, since the channel is user provided. + // With flow control in play, we will check for flow control on incoming + // messages (as opposed to when they are delivered), but also from a go + // routine. Without this, the subscription would possibly stall until + // a new message or heartbeat/fc are received. + chanSubFCCheckInterval = 250 * time.Millisecond + + // Default time wait between retries on Publish iff err is NoResponders. + DefaultPubRetryWait = 250 * time.Millisecond + + // Default number of retries + DefaultPubRetryAttempts = 2 + + // defaultAsyncPubAckInflight is the number of async pub acks inflight. + defaultAsyncPubAckInflight = 4000 +) + +// Types of control messages, so far heartbeat and flow control +const ( + jsCtrlHB = 1 + jsCtrlFC = 2 +) + +// js is an internal struct from a JetStreamContext. +type js struct { + nc *Conn + opts *jsOpts + + // For async publish context. + mu sync.RWMutex + rpre string + rsub *Subscription + pafs map[string]*pubAckFuture + stc chan struct{} + dch chan struct{} + rr *rand.Rand + connStatusCh chan (Status) + replyPrefix string + replyPrefixLen int +} + +type jsOpts struct { + ctx context.Context + // For importing JetStream from other accounts. + pre string + // Amount of time to wait for API requests. + wait time.Duration + // For async publish error handling. + aecb MsgErrHandler + // Max async pub ack in flight + maxpa int + // ackTimeout is the max time to wait for an ack in async publish. + ackTimeout time.Duration + // the domain that produced the pre + domain string + // enables protocol tracing + ctrace ClientTrace + shouldTrace bool + // purgeOpts contains optional stream purge options + purgeOpts *StreamPurgeRequest + // streamInfoOpts contains optional stream info options + streamInfoOpts *StreamInfoRequest + // streamListSubject is used for subject filtering when listing streams / stream names + streamListSubject string + // For direct get message requests + directGet bool + // For direct get next message + directNextFor string + + // featureFlags are used to enable/disable specific JetStream features + featureFlags featureFlags +} + +const ( + defaultRequestWait = 5 * time.Second + defaultAccountCheck = 20 * time.Second +) + +// JetStream returns a JetStreamContext for messaging and stream management. +// Errors are only returned if inconsistent options are provided. +// +// NOTE: JetStreamContext is part of legacy API. +// Users are encouraged to switch to the new JetStream API for enhanced capabilities and +// simplified API. Please refer to the `jetstream` package. +// See: https://github.com/nats-io/nats.go/blob/main/jetstream/README.md +func (nc *Conn) JetStream(opts ...JSOpt) (JetStreamContext, error) { + js := &js{ + nc: nc, + opts: &jsOpts{ + pre: defaultAPIPrefix, + wait: defaultRequestWait, + maxpa: defaultAsyncPubAckInflight, + }, + } + inboxPrefix := InboxPrefix + if js.nc.Opts.InboxPrefix != _EMPTY_ { + inboxPrefix = js.nc.Opts.InboxPrefix + "." + } + js.replyPrefix = inboxPrefix + js.replyPrefixLen = len(js.replyPrefix) + aReplyTokensize + 1 + + for _, opt := range opts { + if err := opt.configureJSContext(js.opts); err != nil { + return nil, err + } + } + return js, nil +} + +// JSOpt configures a JetStreamContext. +type JSOpt interface { + configureJSContext(opts *jsOpts) error +} + +// jsOptFn configures an option for the JetStreamContext. +type jsOptFn func(opts *jsOpts) error + +func (opt jsOptFn) configureJSContext(opts *jsOpts) error { + return opt(opts) +} + +type featureFlags struct { + useDurableConsumerCreate bool +} + +// UseLegacyDurableConsumers makes JetStream use the legacy (pre nats-server v2.9.0) subjects for consumer creation. +// If this option is used when creating JetStreamContext, $JS.API.CONSUMER.DURABLE.CREATE.. will be used +// to create a consumer with Durable provided, rather than $JS.API.CONSUMER.CREATE... +func UseLegacyDurableConsumers() JSOpt { + return jsOptFn(func(opts *jsOpts) error { + opts.featureFlags.useDurableConsumerCreate = true + return nil + }) +} + +// ClientTrace can be used to trace API interactions for the JetStream Context. +type ClientTrace struct { + RequestSent func(subj string, payload []byte) + ResponseReceived func(subj string, payload []byte, hdr Header) +} + +func (ct ClientTrace) configureJSContext(js *jsOpts) error { + js.ctrace = ct + js.shouldTrace = true + return nil +} + +// Domain changes the domain part of JetStream API prefix. +func Domain(domain string) JSOpt { + if domain == _EMPTY_ { + return APIPrefix(_EMPTY_) + } + + return jsOptFn(func(js *jsOpts) error { + js.domain = domain + js.pre = fmt.Sprintf(jsDomainT, domain) + + return nil + }) + +} + +func (s *StreamPurgeRequest) configureJSContext(js *jsOpts) error { + js.purgeOpts = s + return nil +} + +func (s *StreamInfoRequest) configureJSContext(js *jsOpts) error { + js.streamInfoOpts = s + return nil +} + +// APIPrefix changes the default prefix used for the JetStream API. +func APIPrefix(pre string) JSOpt { + return jsOptFn(func(js *jsOpts) error { + if pre == _EMPTY_ { + return nil + } + + js.pre = pre + if !strings.HasSuffix(js.pre, ".") { + js.pre = js.pre + "." + } + + return nil + }) +} + +// DirectGet is an option that can be used to make GetMsg() or GetLastMsg() +// retrieve message directly from a group of servers (leader and replicas) +// if the stream was created with the AllowDirect option. +func DirectGet() JSOpt { + return jsOptFn(func(js *jsOpts) error { + js.directGet = true + return nil + }) +} + +// DirectGetNext is an option that can be used to make GetMsg() retrieve message +// directly from a group of servers (leader and replicas) if the stream was +// created with the AllowDirect option. +// The server will find the next message matching the filter `subject` starting +// at the start sequence (argument in GetMsg()). The filter `subject` can be a +// wildcard. +func DirectGetNext(subject string) JSOpt { + return jsOptFn(func(js *jsOpts) error { + js.directGet = true + js.directNextFor = subject + return nil + }) +} + +// StreamListFilter is an option that can be used to configure `StreamsInfo()` and `StreamNames()` requests. +// It allows filtering the returned streams by subject associated with each stream. +// Wildcards can be used. For example, `StreamListFilter(FOO.*.A) will return +// all streams which have at least one subject matching the provided pattern (e.g. FOO.TEST.A). +func StreamListFilter(subject string) JSOpt { + return jsOptFn(func(opts *jsOpts) error { + opts.streamListSubject = subject + return nil + }) +} + +func (js *js) apiSubj(subj string) string { + if js.opts.pre == _EMPTY_ { + return subj + } + var b strings.Builder + b.WriteString(js.opts.pre) + b.WriteString(subj) + return b.String() +} + +// PubOpt configures options for publishing JetStream messages. +type PubOpt interface { + configurePublish(opts *pubOpts) error +} + +// pubOptFn is a function option used to configure JetStream Publish. +type pubOptFn func(opts *pubOpts) error + +func (opt pubOptFn) configurePublish(opts *pubOpts) error { + return opt(opts) +} + +type pubOpts struct { + ctx context.Context + ttl time.Duration + id string + lid string // Expected last msgId + str string // Expected stream name + seq *uint64 // Expected last sequence + lss *uint64 // Expected last sequence per subject + msgTTL time.Duration // Message TTL + + // Publish retries for NoResponders err. + rwait time.Duration // Retry wait between attempts + rnum int // Retry attempts + + // stallWait is the max wait of a async pub ack. + stallWait time.Duration + + // internal option to re-use existing paf in case of retry. + pafRetry *pubAckFuture +} + +// pubAckResponse is the ack response from the JetStream API when publishing a message. +type pubAckResponse struct { + apiResponse + *PubAck +} + +// PubAck is an ack received after successfully publishing a message. +type PubAck struct { + Stream string `json:"stream"` + Sequence uint64 `json:"seq"` + Duplicate bool `json:"duplicate,omitempty"` + Domain string `json:"domain,omitempty"` +} + +// Headers for published messages. +const ( + MsgIdHdr = "Nats-Msg-Id" + ExpectedStreamHdr = "Nats-Expected-Stream" + ExpectedLastSeqHdr = "Nats-Expected-Last-Sequence" + ExpectedLastSubjSeqHdr = "Nats-Expected-Last-Subject-Sequence" + ExpectedLastMsgIdHdr = "Nats-Expected-Last-Msg-Id" + MsgRollup = "Nats-Rollup" + MsgTTLHdr = "Nats-TTL" +) + +// Headers for republished messages and direct gets. +const ( + JSStream = "Nats-Stream" + JSSequence = "Nats-Sequence" + JSTimeStamp = "Nats-Time-Stamp" + JSSubject = "Nats-Subject" + JSLastSequence = "Nats-Last-Sequence" +) + +// MsgSize is a header that will be part of a consumer's delivered message if HeadersOnly requested. +const MsgSize = "Nats-Msg-Size" + +// Rollups, can be subject only or all messages. +const ( + MsgRollupSubject = "sub" + MsgRollupAll = "all" +) + +// PublishMsg publishes a Msg to a stream from JetStream. +func (js *js) PublishMsg(m *Msg, opts ...PubOpt) (*PubAck, error) { + var o = pubOpts{rwait: DefaultPubRetryWait, rnum: DefaultPubRetryAttempts} + if len(opts) > 0 { + if m.Header == nil { + m.Header = Header{} + } + for _, opt := range opts { + if err := opt.configurePublish(&o); err != nil { + return nil, err + } + } + } + // Check for option collisions. Right now just timeout and context. + if o.ctx != nil && o.ttl != 0 { + return nil, ErrContextAndTimeout + } + if o.ttl == 0 && o.ctx == nil { + o.ttl = js.opts.wait + } + if o.stallWait > 0 { + return nil, errors.New("nats: stall wait cannot be set to sync publish") + } + + if o.id != _EMPTY_ { + m.Header.Set(MsgIdHdr, o.id) + } + if o.lid != _EMPTY_ { + m.Header.Set(ExpectedLastMsgIdHdr, o.lid) + } + if o.str != _EMPTY_ { + m.Header.Set(ExpectedStreamHdr, o.str) + } + if o.seq != nil { + m.Header.Set(ExpectedLastSeqHdr, strconv.FormatUint(*o.seq, 10)) + } + if o.lss != nil { + m.Header.Set(ExpectedLastSubjSeqHdr, strconv.FormatUint(*o.lss, 10)) + } + if o.msgTTL > 0 { + m.Header.Set(MsgTTLHdr, o.msgTTL.String()) + } + + var resp *Msg + var err error + + if o.ttl > 0 { + resp, err = js.nc.RequestMsg(m, time.Duration(o.ttl)) + } else { + resp, err = js.nc.RequestMsgWithContext(o.ctx, m) + } + + if err != nil { + for r, ttl := 0, o.ttl; errors.Is(err, ErrNoResponders) && (r < o.rnum || o.rnum < 0); r++ { + // To protect against small blips in leadership changes etc, if we get a no responders here retry. + if o.ctx != nil { + select { + case <-o.ctx.Done(): + case <-time.After(o.rwait): + } + } else { + time.Sleep(o.rwait) + } + if o.ttl > 0 { + ttl -= o.rwait + if ttl <= 0 { + err = ErrTimeout + break + } + resp, err = js.nc.RequestMsg(m, time.Duration(ttl)) + } else { + resp, err = js.nc.RequestMsgWithContext(o.ctx, m) + } + } + if err != nil { + if errors.Is(err, ErrNoResponders) { + err = ErrNoStreamResponse + } + return nil, err + } + } + + var pa pubAckResponse + if err := json.Unmarshal(resp.Data, &pa); err != nil { + return nil, ErrInvalidJSAck + } + if pa.Error != nil { + return nil, pa.Error + } + if pa.PubAck == nil || pa.PubAck.Stream == _EMPTY_ { + return nil, ErrInvalidJSAck + } + return pa.PubAck, nil +} + +// Publish publishes a message to a stream from JetStream. +func (js *js) Publish(subj string, data []byte, opts ...PubOpt) (*PubAck, error) { + return js.PublishMsg(&Msg{Subject: subj, Data: data}, opts...) +} + +// PubAckFuture is a future for a PubAck. +type PubAckFuture interface { + // Ok returns a receive only channel that can be used to get a PubAck. + Ok() <-chan *PubAck + + // Err returns a receive only channel that can be used to get the error from an async publish. + Err() <-chan error + + // Msg returns the message that was sent to the server. + Msg() *Msg +} + +type pubAckFuture struct { + js *js + msg *Msg + pa *PubAck + st time.Time + err error + errCh chan error + doneCh chan *PubAck + retries int + maxRetries int + retryWait time.Duration + reply string + timeout *time.Timer +} + +func (paf *pubAckFuture) Ok() <-chan *PubAck { + paf.js.mu.Lock() + defer paf.js.mu.Unlock() + + if paf.doneCh == nil { + paf.doneCh = make(chan *PubAck, 1) + if paf.pa != nil { + paf.doneCh <- paf.pa + } + } + + return paf.doneCh +} + +func (paf *pubAckFuture) Err() <-chan error { + paf.js.mu.Lock() + defer paf.js.mu.Unlock() + + if paf.errCh == nil { + paf.errCh = make(chan error, 1) + if paf.err != nil { + paf.errCh <- paf.err + } + } + + return paf.errCh +} + +func (paf *pubAckFuture) Msg() *Msg { + paf.js.mu.RLock() + defer paf.js.mu.RUnlock() + return paf.msg +} + +// For quick token lookup etc. +const aReplyTokensize = 6 + +func (js *js) newAsyncReply() string { + js.mu.Lock() + if js.rsub == nil { + // Create our wildcard reply subject. + sha := sha256.New() + sha.Write([]byte(nuid.Next())) + b := sha.Sum(nil) + for i := 0; i < aReplyTokensize; i++ { + b[i] = rdigits[int(b[i]%base)] + } + js.rpre = fmt.Sprintf("%s%s.", js.replyPrefix, b[:aReplyTokensize]) + sub, err := js.nc.Subscribe(fmt.Sprintf("%s*", js.rpre), js.handleAsyncReply) + if err != nil { + js.mu.Unlock() + return _EMPTY_ + } + js.rsub = sub + js.rr = rand.New(rand.NewSource(time.Now().UnixNano())) + } + if js.connStatusCh == nil { + js.connStatusCh = js.nc.StatusChanged(RECONNECTING, CLOSED) + go js.resetPendingAcksOnReconnect() + } + var sb strings.Builder + sb.WriteString(js.rpre) + for { + rn := js.rr.Int63() + var b [aReplyTokensize]byte + for i, l := 0, rn; i < len(b); i++ { + b[i] = rdigits[l%base] + l /= base + } + if _, ok := js.pafs[string(b[:])]; ok { + continue + } + sb.Write(b[:]) + break + } + js.mu.Unlock() + return sb.String() +} + +func (js *js) resetPendingAcksOnReconnect() { + js.mu.Lock() + connStatusCh := js.connStatusCh + js.mu.Unlock() + for { + newStatus, ok := <-connStatusCh + if !ok || newStatus == CLOSED { + return + } + js.mu.Lock() + errCb := js.opts.aecb + for id, paf := range js.pafs { + paf.err = ErrDisconnected + if paf.errCh != nil { + paf.errCh <- paf.err + } + if errCb != nil { + defer errCb(js, paf.msg, ErrDisconnected) + } + delete(js.pafs, id) + } + if js.dch != nil { + close(js.dch) + js.dch = nil + } + js.mu.Unlock() + } +} + +// CleanupPublisher will cleanup the publishing side of JetStreamContext. +// +// This will unsubscribe from the internal reply subject if needed. +// All pending async publishes will fail with ErrJetStreamContextClosed. +// +// If an error handler was provided, it will be called for each pending async +// publish and PublishAsyncComplete will be closed. +// +// After completing JetStreamContext is still usable - internal subscription +// will be recreated on next publish, but the acks from previous publishes will +// be lost. +func (js *js) CleanupPublisher() { + js.cleanupReplySub() + js.mu.Lock() + errCb := js.opts.aecb + for id, paf := range js.pafs { + paf.err = ErrJetStreamPublisherClosed + if paf.errCh != nil { + paf.errCh <- paf.err + } + if errCb != nil { + defer errCb(js, paf.msg, ErrJetStreamPublisherClosed) + } + delete(js.pafs, id) + } + if js.dch != nil { + close(js.dch) + js.dch = nil + } + js.mu.Unlock() +} + +func (js *js) cleanupReplySub() { + js.mu.Lock() + if js.rsub != nil { + js.rsub.Unsubscribe() + js.rsub = nil + } + if js.connStatusCh != nil { + close(js.connStatusCh) + js.connStatusCh = nil + } + js.mu.Unlock() +} + +// registerPAF will register for a PubAckFuture. +func (js *js) registerPAF(id string, paf *pubAckFuture) (int, int) { + js.mu.Lock() + if js.pafs == nil { + js.pafs = make(map[string]*pubAckFuture) + } + paf.js = js + js.pafs[id] = paf + np := len(js.pafs) + maxpa := js.opts.maxpa + js.mu.Unlock() + return np, maxpa +} + +// Lock should be held. +func (js *js) getPAF(id string) *pubAckFuture { + if js.pafs == nil { + return nil + } + return js.pafs[id] +} + +// clearPAF will remove a PubAckFuture that was registered. +func (js *js) clearPAF(id string) { + js.mu.Lock() + delete(js.pafs, id) + js.mu.Unlock() +} + +// PublishAsyncPending returns how many PubAckFutures are pending. +func (js *js) PublishAsyncPending() int { + js.mu.RLock() + defer js.mu.RUnlock() + return len(js.pafs) +} + +func (js *js) asyncStall() <-chan struct{} { + js.mu.Lock() + if js.stc == nil { + js.stc = make(chan struct{}) + } + stc := js.stc + js.mu.Unlock() + return stc +} + +// Handle an async reply from PublishAsync. +func (js *js) handleAsyncReply(m *Msg) { + if len(m.Subject) <= js.replyPrefixLen { + return + } + id := m.Subject[js.replyPrefixLen:] + + js.mu.Lock() + paf := js.getPAF(id) + if paf == nil { + js.mu.Unlock() + return + } + + closeStc := func() { + // Check on anyone stalled and waiting. + if js.stc != nil && len(js.pafs) < js.opts.maxpa { + close(js.stc) + js.stc = nil + } + } + + closeDchFn := func() func() { + var dch chan struct{} + // Check on anyone one waiting on done status. + if js.dch != nil && len(js.pafs) == 0 { + dch = js.dch + js.dch = nil + } + // Return function to close done channel which + // should be deferred so that error is processed and + // can be checked. + return func() { + if dch != nil { + close(dch) + } + } + } + + doErr := func(err error) { + paf.err = err + if paf.errCh != nil { + paf.errCh <- paf.err + } + cb := js.opts.aecb + js.mu.Unlock() + if cb != nil { + cb(paf.js, paf.msg, err) + } + } + + if paf.timeout != nil { + paf.timeout.Stop() + } + + // Process no responders etc. + if len(m.Data) == 0 && m.Header.Get(statusHdr) == noResponders { + if paf.retries < paf.maxRetries { + paf.retries++ + time.AfterFunc(paf.retryWait, func() { + js.mu.Lock() + paf := js.getPAF(id) + js.mu.Unlock() + if paf == nil { + return + } + _, err := js.PublishMsgAsync(paf.msg, pubOptFn(func(po *pubOpts) error { + po.pafRetry = paf + return nil + })) + if err != nil { + js.mu.Lock() + doErr(err) + } + }) + js.mu.Unlock() + return + } + delete(js.pafs, id) + closeStc() + defer closeDchFn()() + doErr(ErrNoResponders) + return + } + + //remove + delete(js.pafs, id) + closeStc() + defer closeDchFn()() + + var pa pubAckResponse + if err := json.Unmarshal(m.Data, &pa); err != nil { + doErr(ErrInvalidJSAck) + return + } + if pa.Error != nil { + doErr(pa.Error) + return + } + if pa.PubAck == nil || pa.PubAck.Stream == _EMPTY_ { + doErr(ErrInvalidJSAck) + return + } + + // So here we have received a proper puback. + paf.pa = pa.PubAck + if paf.doneCh != nil { + paf.doneCh <- paf.pa + } + js.mu.Unlock() +} + +// MsgErrHandler is used to process asynchronous errors from +// JetStream PublishAsync. It will return the original +// message sent to the server for possible retransmitting and the error encountered. +type MsgErrHandler func(JetStream, *Msg, error) + +// PublishAsyncErrHandler sets the error handler for async publishes in JetStream. +func PublishAsyncErrHandler(cb MsgErrHandler) JSOpt { + return jsOptFn(func(js *jsOpts) error { + js.aecb = cb + return nil + }) +} + +// PublishAsyncMaxPending sets the maximum outstanding async publishes that can be inflight at one time. +func PublishAsyncMaxPending(max int) JSOpt { + return jsOptFn(func(js *jsOpts) error { + if max < 1 { + return errors.New("nats: max ack pending should be >= 1") + } + js.maxpa = max + return nil + }) +} + +// PublishAsyncTimeout sets the timeout for async message publish. +// If not provided, timeout is disabled. +func PublishAsyncTimeout(dur time.Duration) JSOpt { + return jsOptFn(func(opts *jsOpts) error { + opts.ackTimeout = dur + return nil + }) +} + +// PublishAsync publishes a message to JetStream and returns a PubAckFuture +func (js *js) PublishAsync(subj string, data []byte, opts ...PubOpt) (PubAckFuture, error) { + return js.PublishMsgAsync(&Msg{Subject: subj, Data: data}, opts...) +} + +const defaultStallWait = 200 * time.Millisecond + +func (js *js) PublishMsgAsync(m *Msg, opts ...PubOpt) (PubAckFuture, error) { + var o pubOpts + if len(opts) > 0 { + if m.Header == nil { + m.Header = Header{} + } + for _, opt := range opts { + if err := opt.configurePublish(&o); err != nil { + return nil, err + } + } + } + + if o.rnum < 0 { + return nil, fmt.Errorf("%w: retry attempts cannot be negative", ErrInvalidArg) + } + + // Timeouts and contexts do not make sense for these. + if o.ttl != 0 || o.ctx != nil { + return nil, ErrContextAndTimeout + } + stallWait := defaultStallWait + if o.stallWait > 0 { + stallWait = o.stallWait + } + + // FIXME(dlc) - Make common. + if o.id != _EMPTY_ { + m.Header.Set(MsgIdHdr, o.id) + } + if o.lid != _EMPTY_ { + m.Header.Set(ExpectedLastMsgIdHdr, o.lid) + } + if o.str != _EMPTY_ { + m.Header.Set(ExpectedStreamHdr, o.str) + } + if o.seq != nil { + m.Header.Set(ExpectedLastSeqHdr, strconv.FormatUint(*o.seq, 10)) + } + if o.lss != nil { + m.Header.Set(ExpectedLastSubjSeqHdr, strconv.FormatUint(*o.lss, 10)) + } + if o.msgTTL > 0 { + m.Header.Set(MsgTTLHdr, o.msgTTL.String()) + } + + // Reply + paf := o.pafRetry + if paf == nil && m.Reply != _EMPTY_ { + return nil, errors.New("nats: reply subject should be empty") + } + var id string + var reply string + + // register new paf if not retrying + if paf == nil { + reply = js.newAsyncReply() + + if reply == _EMPTY_ { + return nil, errors.New("nats: error creating async reply handler") + } + + id = reply[js.replyPrefixLen:] + paf = &pubAckFuture{msg: m, st: time.Now(), maxRetries: o.rnum, retryWait: o.rwait, reply: reply} + numPending, maxPending := js.registerPAF(id, paf) + + if maxPending > 0 && numPending > maxPending { + select { + case <-js.asyncStall(): + case <-time.After(stallWait): + js.clearPAF(id) + return nil, ErrTooManyStalledMsgs + } + } + if js.opts.ackTimeout > 0 { + paf.timeout = time.AfterFunc(js.opts.ackTimeout, func() { + js.mu.Lock() + defer js.mu.Unlock() + + if _, ok := js.pafs[id]; !ok { + // paf has already been resolved + // while waiting for the lock + return + } + + // ack timed out, remove from pending acks + delete(js.pafs, id) + + // check on anyone stalled and waiting. + if js.stc != nil && len(js.pafs) < js.opts.maxpa { + close(js.stc) + js.stc = nil + } + + // send error to user + paf.err = ErrAsyncPublishTimeout + if paf.errCh != nil { + paf.errCh <- paf.err + } + + // call error callback if set + if js.opts.aecb != nil { + js.opts.aecb(js, paf.msg, ErrAsyncPublishTimeout) + } + + // check on anyone one waiting on done status. + if js.dch != nil && len(js.pafs) == 0 { + close(js.dch) + js.dch = nil + } + }) + } + } else { + reply = paf.reply + if paf.timeout != nil { + paf.timeout.Reset(js.opts.ackTimeout) + } + id = reply[js.replyPrefixLen:] + } + hdr, err := m.headerBytes() + if err != nil { + return nil, err + } + if err := js.nc.publish(m.Subject, reply, false, hdr, m.Data); err != nil { + js.clearPAF(id) + return nil, err + } + + return paf, nil +} + +// PublishAsyncComplete returns a channel that will be closed when all outstanding messages have been ack'd. +func (js *js) PublishAsyncComplete() <-chan struct{} { + js.mu.Lock() + defer js.mu.Unlock() + if js.dch == nil { + js.dch = make(chan struct{}) + } + dch := js.dch + if len(js.pafs) == 0 { + close(js.dch) + js.dch = nil + } + return dch +} + +// MsgId sets the message ID used for deduplication. +func MsgId(id string) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.id = id + return nil + }) +} + +// ExpectStream sets the expected stream to respond from the publish. +func ExpectStream(stream string) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.str = stream + return nil + }) +} + +// ExpectLastSequence sets the expected sequence in the response from the publish. +func ExpectLastSequence(seq uint64) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.seq = &seq + return nil + }) +} + +// ExpectLastSequencePerSubject sets the expected sequence per subject in the response from the publish. +func ExpectLastSequencePerSubject(seq uint64) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.lss = &seq + return nil + }) +} + +// ExpectLastMsgId sets the expected last msgId in the response from the publish. +func ExpectLastMsgId(id string) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.lid = id + return nil + }) +} + +// RetryWait sets the retry wait time when ErrNoResponders is encountered. +func RetryWait(dur time.Duration) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.rwait = dur + return nil + }) +} + +// RetryAttempts sets the retry number of attempts when ErrNoResponders is encountered. +func RetryAttempts(num int) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.rnum = num + return nil + }) +} + +// StallWait sets the max wait when the producer becomes stall producing messages. +func StallWait(ttl time.Duration) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + if ttl <= 0 { + return errors.New("nats: stall wait should be more than 0") + } + opts.stallWait = ttl + return nil + }) +} + +// MsgTTL sets per msg TTL. +// Requires [StreamConfig.AllowMsgTTL] to be enabled. +func MsgTTL(dur time.Duration) PubOpt { + return pubOptFn(func(opts *pubOpts) error { + opts.msgTTL = dur + return nil + }) +} + +type ackOpts struct { + ttl time.Duration + ctx context.Context + nakDelay time.Duration +} + +// AckOpt are the options that can be passed when acknowledge a message. +type AckOpt interface { + configureAck(opts *ackOpts) error +} + +// MaxWait sets the maximum amount of time we will wait for a response. +type MaxWait time.Duration + +func (ttl MaxWait) configureJSContext(js *jsOpts) error { + js.wait = time.Duration(ttl) + return nil +} + +func (ttl MaxWait) configurePull(opts *pullOpts) error { + opts.ttl = time.Duration(ttl) + return nil +} + +// AckWait sets the maximum amount of time we will wait for an ack. +type AckWait time.Duration + +func (ttl AckWait) configurePublish(opts *pubOpts) error { + opts.ttl = time.Duration(ttl) + return nil +} + +func (ttl AckWait) configureSubscribe(opts *subOpts) error { + opts.cfg.AckWait = time.Duration(ttl) + return nil +} + +func (ttl AckWait) configureAck(opts *ackOpts) error { + opts.ttl = time.Duration(ttl) + return nil +} + +// ContextOpt is an option used to set a context.Context. +type ContextOpt struct { + context.Context +} + +func (ctx ContextOpt) configureJSContext(opts *jsOpts) error { + opts.ctx = ctx + return nil +} + +func (ctx ContextOpt) configurePublish(opts *pubOpts) error { + opts.ctx = ctx + return nil +} + +func (ctx ContextOpt) configureSubscribe(opts *subOpts) error { + opts.ctx = ctx + return nil +} + +func (ctx ContextOpt) configurePull(opts *pullOpts) error { + opts.ctx = ctx + return nil +} + +func (ctx ContextOpt) configureAck(opts *ackOpts) error { + opts.ctx = ctx + return nil +} + +// Context returns an option that can be used to configure a context for APIs +// that are context aware such as those part of the JetStream interface. +func Context(ctx context.Context) ContextOpt { + return ContextOpt{ctx} +} + +type nakDelay time.Duration + +func (d nakDelay) configureAck(opts *ackOpts) error { + opts.nakDelay = time.Duration(d) + return nil +} + +// Subscribe + +// ConsumerConfig is the configuration of a JetStream consumer. +type ConsumerConfig struct { + Durable string `json:"durable_name,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + DeliverPolicy DeliverPolicy `json:"deliver_policy"` + OptStartSeq uint64 `json:"opt_start_seq,omitempty"` + OptStartTime *time.Time `json:"opt_start_time,omitempty"` + AckPolicy AckPolicy `json:"ack_policy"` + AckWait time.Duration `json:"ack_wait,omitempty"` + MaxDeliver int `json:"max_deliver,omitempty"` + BackOff []time.Duration `json:"backoff,omitempty"` + FilterSubject string `json:"filter_subject,omitempty"` + FilterSubjects []string `json:"filter_subjects,omitempty"` + ReplayPolicy ReplayPolicy `json:"replay_policy"` + RateLimit uint64 `json:"rate_limit_bps,omitempty"` // Bits per sec + SampleFrequency string `json:"sample_freq,omitempty"` + MaxWaiting int `json:"max_waiting,omitempty"` + MaxAckPending int `json:"max_ack_pending,omitempty"` + FlowControl bool `json:"flow_control,omitempty"` + Heartbeat time.Duration `json:"idle_heartbeat,omitempty"` + HeadersOnly bool `json:"headers_only,omitempty"` + + // Pull based options. + MaxRequestBatch int `json:"max_batch,omitempty"` + MaxRequestExpires time.Duration `json:"max_expires,omitempty"` + MaxRequestMaxBytes int `json:"max_bytes,omitempty"` + + // Push based consumers. + DeliverSubject string `json:"deliver_subject,omitempty"` + DeliverGroup string `json:"deliver_group,omitempty"` + + // Inactivity threshold. + InactiveThreshold time.Duration `json:"inactive_threshold,omitempty"` + + // Generally inherited by parent stream and other markers, now can be configured directly. + Replicas int `json:"num_replicas"` + // Force memory storage. + MemoryStorage bool `json:"mem_storage,omitempty"` + + // Metadata is additional metadata for the Consumer. + // Keys starting with `_nats` are reserved. + // NOTE: Metadata requires nats-server v2.10.0+ + Metadata map[string]string `json:"metadata,omitempty"` +} + +// ConsumerInfo is the info from a JetStream consumer. +type ConsumerInfo struct { + Stream string `json:"stream_name"` + Name string `json:"name"` + Created time.Time `json:"created"` + Config ConsumerConfig `json:"config"` + Delivered SequenceInfo `json:"delivered"` + AckFloor SequenceInfo `json:"ack_floor"` + NumAckPending int `json:"num_ack_pending"` + NumRedelivered int `json:"num_redelivered"` + NumWaiting int `json:"num_waiting"` + NumPending uint64 `json:"num_pending"` + Cluster *ClusterInfo `json:"cluster,omitempty"` + PushBound bool `json:"push_bound,omitempty"` +} + +// SequenceInfo has both the consumer and the stream sequence and last activity. +type SequenceInfo struct { + Consumer uint64 `json:"consumer_seq"` + Stream uint64 `json:"stream_seq"` + Last *time.Time `json:"last_active,omitempty"` +} + +// SequencePair includes the consumer and stream sequence info from a JetStream consumer. +type SequencePair struct { + Consumer uint64 `json:"consumer_seq"` + Stream uint64 `json:"stream_seq"` +} + +// nextRequest is for getting next messages for pull based consumers from JetStream. +type nextRequest struct { + Expires time.Duration `json:"expires,omitempty"` + Batch int `json:"batch,omitempty"` + NoWait bool `json:"no_wait,omitempty"` + MaxBytes int `json:"max_bytes,omitempty"` + Heartbeat time.Duration `json:"idle_heartbeat,omitempty"` +} + +// jsSub includes JetStream subscription info. +type jsSub struct { + js *js + + // For pull subscribers, this is the next message subject to send requests to. + nms string + + psubj string // the subject that was passed by user to the subscribe calls + consumer string + stream string + deliver string + pull bool + dc bool // Delete JS consumer + ackNone bool + + // This is ConsumerInfo's Pending+Consumer.Delivered that we get from the + // add consumer response. Note that some versions of the server gather the + // consumer info *after* the creation of the consumer, which means that + // some messages may have been already delivered. So the sum of the two + // is a more accurate representation of the number of messages pending or + // in the process of being delivered to the subscription when created. + pending uint64 + + // Ordered consumers + ordered bool + dseq uint64 + sseq uint64 + ccreq *createConsumerRequest + + // Heartbeats and Flow Control handling from push consumers. + hbc *time.Timer + hbi time.Duration + active bool + cmeta string + fcr string + fcd uint64 + fciseq uint64 + csfct *time.Timer + + // context set on js.Subscribe used e.g. to recreate ordered consumer + ctx context.Context + + // Cancellation function to cancel context on drain/unsubscribe. + cancel func() +} + +// Deletes the JS Consumer. +// No connection nor subscription lock must be held on entry. +func (sub *Subscription) deleteConsumer() error { + sub.mu.Lock() + jsi := sub.jsi + if jsi == nil { + sub.mu.Unlock() + return nil + } + if jsi.stream == _EMPTY_ || jsi.consumer == _EMPTY_ { + sub.mu.Unlock() + return nil + } + stream, consumer := jsi.stream, jsi.consumer + js := jsi.js + sub.mu.Unlock() + + return js.DeleteConsumer(stream, consumer) +} + +// SubOpt configures options for subscribing to JetStream consumers. +type SubOpt interface { + configureSubscribe(opts *subOpts) error +} + +// subOptFn is a function option used to configure a JetStream Subscribe. +type subOptFn func(opts *subOpts) error + +func (opt subOptFn) configureSubscribe(opts *subOpts) error { + return opt(opts) +} + +// Subscribe creates an async Subscription for JetStream. +// The stream and consumer names can be provided with the nats.Bind() option. +// For creating an ephemeral (where the consumer name is picked by the server), +// you can provide the stream name with nats.BindStream(). +// If no stream name is specified, the library will attempt to figure out which +// stream the subscription is for. See important notes below for more details. +// +// IMPORTANT NOTES: +// * If none of the options Bind() nor Durable() are specified, the library will +// send a request to the server to create an ephemeral JetStream consumer, +// which will be deleted after an Unsubscribe() or Drain(), or automatically +// by the server after a short period of time after the NATS subscription is +// gone. +// * If Durable() option is specified, the library will attempt to lookup a JetStream +// consumer with this name, and if found, will bind to it and not attempt to +// delete it. However, if not found, the library will send a request to create +// such durable JetStream consumer. The library will delete the JetStream consumer +// after an Unsubscribe() or Drain(). +// * If Bind() option is provided, the library will attempt to lookup the +// consumer with the given name, and if successful, bind to it. If the lookup fails, +// then the Subscribe() call will return an error. +func (js *js) Subscribe(subj string, cb MsgHandler, opts ...SubOpt) (*Subscription, error) { + if cb == nil { + return nil, ErrBadSubscription + } + return js.subscribe(subj, _EMPTY_, cb, nil, false, false, opts) +} + +// SubscribeSync creates a Subscription that can be used to process messages synchronously. +// See important note in Subscribe() +func (js *js) SubscribeSync(subj string, opts ...SubOpt) (*Subscription, error) { + mch := make(chan *Msg, js.nc.Opts.SubChanLen) + return js.subscribe(subj, _EMPTY_, nil, mch, true, false, opts) +} + +// QueueSubscribe creates a Subscription with a queue group. +// If no optional durable name nor binding options are specified, the queue name will be used as a durable name. +// See important note in Subscribe() +func (js *js) QueueSubscribe(subj, queue string, cb MsgHandler, opts ...SubOpt) (*Subscription, error) { + if cb == nil { + return nil, ErrBadSubscription + } + return js.subscribe(subj, queue, cb, nil, false, false, opts) +} + +// QueueSubscribeSync creates a Subscription with a queue group that can be used to process messages synchronously. +// See important note in QueueSubscribe() +func (js *js) QueueSubscribeSync(subj, queue string, opts ...SubOpt) (*Subscription, error) { + mch := make(chan *Msg, js.nc.Opts.SubChanLen) + return js.subscribe(subj, queue, nil, mch, true, false, opts) +} + +// ChanSubscribe creates channel based Subscription. +// Using ChanSubscribe without buffered capacity is not recommended since +// it will be prone to dropping messages with a slow consumer error. Make sure to give the channel enough +// capacity to handle bursts in traffic, for example other Subscribe APIs use a default of 512k capacity in comparison. +// See important note in Subscribe() +func (js *js) ChanSubscribe(subj string, ch chan *Msg, opts ...SubOpt) (*Subscription, error) { + return js.subscribe(subj, _EMPTY_, nil, ch, false, false, opts) +} + +// ChanQueueSubscribe creates channel based Subscription with a queue group. +// See important note in QueueSubscribe() +func (js *js) ChanQueueSubscribe(subj, queue string, ch chan *Msg, opts ...SubOpt) (*Subscription, error) { + return js.subscribe(subj, queue, nil, ch, false, false, opts) +} + +// PullSubscribe creates a Subscription that can fetch messages. +// See important note in Subscribe() +func (js *js) PullSubscribe(subj, durable string, opts ...SubOpt) (*Subscription, error) { + mch := make(chan *Msg, js.nc.Opts.SubChanLen) + if durable != "" { + opts = append(opts, Durable(durable)) + } + return js.subscribe(subj, _EMPTY_, nil, mch, true, true, opts) +} + +func processConsInfo(info *ConsumerInfo, userCfg *ConsumerConfig, isPullMode bool, subj, queue string) (string, error) { + ccfg := &info.Config + + // Make sure this new subject matches or is a subset. + if ccfg.FilterSubject != _EMPTY_ && subj != ccfg.FilterSubject { + return _EMPTY_, ErrSubjectMismatch + } + + // Prevent binding a subscription against incompatible consumer types. + if isPullMode && ccfg.DeliverSubject != _EMPTY_ { + return _EMPTY_, ErrPullSubscribeToPushConsumer + } else if !isPullMode && ccfg.DeliverSubject == _EMPTY_ { + return _EMPTY_, ErrPullSubscribeRequired + } + + // If pull mode, nothing else to check here. + if isPullMode { + return _EMPTY_, checkConfig(ccfg, userCfg) + } + + // At this point, we know the user wants push mode, and the JS consumer is + // really push mode. + + dg := info.Config.DeliverGroup + if dg == _EMPTY_ { + // Prevent an user from attempting to create a queue subscription on + // a JS consumer that was not created with a deliver group. + if queue != _EMPTY_ { + return _EMPTY_, errors.New("cannot create a queue subscription for a consumer without a deliver group") + } else if info.PushBound { + // Need to reject a non queue subscription to a non queue consumer + // if the consumer is already bound. + return _EMPTY_, errors.New("consumer is already bound to a subscription") + } + } else { + // If the JS consumer has a deliver group, we need to fail a non queue + // subscription attempt: + if queue == _EMPTY_ { + return _EMPTY_, fmt.Errorf("cannot create a subscription for a consumer with a deliver group %q", dg) + } else if queue != dg { + // Here the user's queue group name does not match the one associated + // with the JS consumer. + return _EMPTY_, fmt.Errorf("cannot create a queue subscription %q for a consumer with a deliver group %q", + queue, dg) + } + } + if err := checkConfig(ccfg, userCfg); err != nil { + return _EMPTY_, err + } + return ccfg.DeliverSubject, nil +} + +func checkConfig(s, u *ConsumerConfig) error { + makeErr := func(fieldName string, usrVal, srvVal any) error { + return fmt.Errorf("nats: configuration requests %s to be %v, but consumer's value is %v", fieldName, usrVal, srvVal) + } + + if u.Durable != _EMPTY_ && u.Durable != s.Durable { + return makeErr("durable", u.Durable, s.Durable) + } + if u.Description != _EMPTY_ && u.Description != s.Description { + return makeErr("description", u.Description, s.Description) + } + if u.DeliverPolicy != deliverPolicyNotSet && u.DeliverPolicy != s.DeliverPolicy { + return makeErr("deliver policy", u.DeliverPolicy, s.DeliverPolicy) + } + if u.OptStartSeq > 0 && u.OptStartSeq != s.OptStartSeq { + return makeErr("optional start sequence", u.OptStartSeq, s.OptStartSeq) + } + if u.OptStartTime != nil && !u.OptStartTime.IsZero() && !(*u.OptStartTime).Equal(*s.OptStartTime) { + return makeErr("optional start time", u.OptStartTime, s.OptStartTime) + } + if u.AckPolicy != ackPolicyNotSet && u.AckPolicy != s.AckPolicy { + return makeErr("ack policy", u.AckPolicy, s.AckPolicy) + } + if u.AckWait > 0 && u.AckWait != s.AckWait { + return makeErr("ack wait", u.AckWait, s.AckWait) + } + if u.MaxDeliver > 0 && u.MaxDeliver != s.MaxDeliver { + return makeErr("max deliver", u.MaxDeliver, s.MaxDeliver) + } + if u.ReplayPolicy != replayPolicyNotSet && u.ReplayPolicy != s.ReplayPolicy { + return makeErr("replay policy", u.ReplayPolicy, s.ReplayPolicy) + } + if u.RateLimit > 0 && u.RateLimit != s.RateLimit { + return makeErr("rate limit", u.RateLimit, s.RateLimit) + } + if u.SampleFrequency != _EMPTY_ && u.SampleFrequency != s.SampleFrequency { + return makeErr("sample frequency", u.SampleFrequency, s.SampleFrequency) + } + if u.MaxWaiting > 0 && u.MaxWaiting != s.MaxWaiting { + return makeErr("max waiting", u.MaxWaiting, s.MaxWaiting) + } + if u.MaxAckPending > 0 && u.MaxAckPending != s.MaxAckPending { + return makeErr("max ack pending", u.MaxAckPending, s.MaxAckPending) + } + // For flow control, we want to fail if the user explicit wanted it, but + // it is not set in the existing consumer. If it is not asked by the user, + // the library still handles it and so no reason to fail. + if u.FlowControl && !s.FlowControl { + return makeErr("flow control", u.FlowControl, s.FlowControl) + } + if u.Heartbeat > 0 && u.Heartbeat != s.Heartbeat { + return makeErr("heartbeat", u.Heartbeat, s.Heartbeat) + } + if u.Replicas > 0 && u.Replicas != s.Replicas { + return makeErr("replicas", u.Replicas, s.Replicas) + } + if u.MemoryStorage && !s.MemoryStorage { + return makeErr("memory storage", u.MemoryStorage, s.MemoryStorage) + } + return nil +} + +func (js *js) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync, isPullMode bool, opts []SubOpt) (*Subscription, error) { + cfg := ConsumerConfig{ + DeliverPolicy: deliverPolicyNotSet, + AckPolicy: ackPolicyNotSet, + ReplayPolicy: replayPolicyNotSet, + } + o := subOpts{cfg: &cfg} + if len(opts) > 0 { + for _, opt := range opts { + if opt == nil { + continue + } + if err := opt.configureSubscribe(&o); err != nil { + return nil, err + } + } + } + + // If no stream name is specified, the subject cannot be empty. + if subj == _EMPTY_ && o.stream == _EMPTY_ { + return nil, errors.New("nats: subject required") + } + + // Note that these may change based on the consumer info response we may get. + hasHeartbeats := o.cfg.Heartbeat > 0 + hasFC := o.cfg.FlowControl + + // Some checks for pull subscribers + if isPullMode { + // No deliver subject should be provided + if o.cfg.DeliverSubject != _EMPTY_ { + return nil, ErrPullSubscribeToPushConsumer + } + } + + // Some check/setting specific to queue subs + if queue != _EMPTY_ { + // Queue subscriber cannot have HB or FC (since messages will be randomly dispatched + // to members). We may in the future have a separate NATS subscription that all members + // would subscribe to and server would send on. + if o.cfg.Heartbeat > 0 || o.cfg.FlowControl { + // Not making this a public ErrXXX in case we allow in the future. + return nil, errors.New("nats: queue subscription doesn't support idle heartbeat nor flow control") + } + + // If this is a queue subscription and no consumer nor durable name was specified, + // then we will use the queue name as a durable name. + if o.consumer == _EMPTY_ && o.cfg.Durable == _EMPTY_ { + if err := checkConsumerName(queue); err != nil { + return nil, err + } + o.cfg.Durable = queue + } + } + + var ( + err error + shouldCreate bool + info *ConsumerInfo + deliver string + stream = o.stream + consumer = o.consumer + isDurable = o.cfg.Durable != _EMPTY_ + consumerBound = o.bound + ctx = o.ctx + skipCInfo = o.skipCInfo + notFoundErr bool + lookupErr bool + nc = js.nc + nms string + hbi time.Duration + ccreq *createConsumerRequest // In case we need to hold onto it for ordered consumers. + maxap int + ) + + // Do some quick checks here for ordered consumers. We do these here instead of spread out + // in the individual SubOpts. + if o.ordered { + // Make sure we are not durable. + if isDurable { + return nil, errors.New("nats: durable can not be set for an ordered consumer") + } + // Check ack policy. + if o.cfg.AckPolicy != ackPolicyNotSet { + return nil, errors.New("nats: ack policy can not be set for an ordered consumer") + } + // Check max deliver. + if o.cfg.MaxDeliver != 1 && o.cfg.MaxDeliver != 0 { + return nil, errors.New("nats: max deliver can not be set for an ordered consumer") + } + // No deliver subject, we pick our own. + if o.cfg.DeliverSubject != _EMPTY_ { + return nil, errors.New("nats: deliver subject can not be set for an ordered consumer") + } + // Queue groups not allowed. + if queue != _EMPTY_ { + return nil, errors.New("nats: queues not be set for an ordered consumer") + } + // Check for bound consumers. + if consumer != _EMPTY_ { + return nil, errors.New("nats: can not bind existing consumer for an ordered consumer") + } + // Check for pull mode. + if isPullMode { + return nil, errors.New("nats: can not use pull mode for an ordered consumer") + } + // Setup how we need it to be here. + o.cfg.FlowControl = true + o.cfg.AckPolicy = AckNonePolicy + o.cfg.MaxDeliver = 1 + o.cfg.AckWait = 22 * time.Hour // Just set to something known, not utilized. + // Force R1 and MemoryStorage for these. + o.cfg.Replicas = 1 + o.cfg.MemoryStorage = true + + if !hasHeartbeats { + o.cfg.Heartbeat = orderedHeartbeatsInterval + } + hasFC, hasHeartbeats = true, true + o.mack = true // To avoid auto-ack wrapping call below. + hbi = o.cfg.Heartbeat + } + + // In case a consumer has not been set explicitly, then the + // durable name will be used as the consumer name. + if consumer == _EMPTY_ { + consumer = o.cfg.Durable + } + + // Find the stream mapped to the subject if not bound to a stream already. + if stream == _EMPTY_ { + stream, err = js.StreamNameBySubject(subj) + if err != nil { + return nil, err + } + } + + // With an explicit durable name, we can lookup the consumer first + // to which it should be attaching to. + // If SkipConsumerLookup was used, do not call consumer info. + if consumer != _EMPTY_ && !o.skipCInfo { + info, err = js.ConsumerInfo(stream, consumer) + notFoundErr = errors.Is(err, ErrConsumerNotFound) + lookupErr = err == ErrJetStreamNotEnabled || errors.Is(err, ErrTimeout) || errors.Is(err, context.DeadlineExceeded) + } + + switch { + case info != nil: + deliver, err = processConsInfo(info, o.cfg, isPullMode, subj, queue) + if err != nil { + return nil, err + } + icfg := &info.Config + hasFC, hbi = icfg.FlowControl, icfg.Heartbeat + hasHeartbeats = hbi > 0 + maxap = icfg.MaxAckPending + case (err != nil && !notFoundErr) || (notFoundErr && consumerBound): + // If the consumer is being bound and we got an error on pull subscribe then allow the error. + if !(isPullMode && lookupErr && consumerBound) { + return nil, err + } + case skipCInfo: + // When skipping consumer info, need to rely on the manually passed sub options + // to match the expected behavior from the subscription. + hasFC, hbi = o.cfg.FlowControl, o.cfg.Heartbeat + hasHeartbeats = hbi > 0 + maxap = o.cfg.MaxAckPending + deliver = o.cfg.DeliverSubject + if consumerBound { + break + } + + // When not bound to a consumer already, proceed to create. + fallthrough + default: + // Attempt to create consumer if not found nor using Bind. + shouldCreate = true + if o.cfg.DeliverSubject != _EMPTY_ { + deliver = o.cfg.DeliverSubject + } else if !isPullMode { + deliver = nc.NewInbox() + cfg.DeliverSubject = deliver + } + // Do filtering always, server will clear as needed. + cfg.FilterSubject = subj + + // Pass the queue to the consumer config + if queue != _EMPTY_ { + cfg.DeliverGroup = queue + } + + // If not set, default to deliver all + if cfg.DeliverPolicy == deliverPolicyNotSet { + cfg.DeliverPolicy = DeliverAllPolicy + } + // If not set, default to ack explicit. + if cfg.AckPolicy == ackPolicyNotSet { + cfg.AckPolicy = AckExplicitPolicy + } + // If not set, default to instant + if cfg.ReplayPolicy == replayPolicyNotSet { + cfg.ReplayPolicy = ReplayInstantPolicy + } + + // If we have acks at all and the MaxAckPending is not set go ahead + // and set to the internal max for channel based consumers + if cfg.MaxAckPending == 0 && ch != nil && cfg.AckPolicy != AckNonePolicy { + cfg.MaxAckPending = cap(ch) + } + // Create request here. + ccreq = &createConsumerRequest{ + Stream: stream, + Config: &cfg, + } + hbi = cfg.Heartbeat + } + + if isPullMode { + nms = fmt.Sprintf(js.apiSubj(apiRequestNextT), stream, consumer) + deliver = nc.NewInbox() + // for pull consumers, create a wildcard subscription to differentiate pull requests + deliver += ".*" + } + + // In case this has a context, then create a child context that + // is possible to cancel via unsubscribe / drain. + var cancel func() + if ctx != nil { + ctx, cancel = context.WithCancel(ctx) + } + + jsi := &jsSub{ + js: js, + stream: stream, + consumer: consumer, + deliver: deliver, + hbi: hbi, + ordered: o.ordered, + ccreq: ccreq, + dseq: 1, + pull: isPullMode, + nms: nms, + psubj: subj, + cancel: cancel, + ackNone: o.cfg.AckPolicy == AckNonePolicy, + ctx: o.ctx, + } + + // Auto acknowledge unless manual ack is set or policy is set to AckNonePolicy + if cb != nil && !o.mack && o.cfg.AckPolicy != AckNonePolicy { + ocb := cb + cb = func(m *Msg) { ocb(m); m.Ack() } + } + sub, err := nc.subscribe(deliver, queue, cb, ch, nil, isSync, jsi) + if err != nil { + return nil, err + } + + // If we fail and we had the sub we need to cleanup, but can't just do a straight Unsubscribe or Drain. + // We need to clear the jsi so we do not remove any durables etc. + cleanUpSub := func() { + if sub != nil { + sub.mu.Lock() + sub.jsi = nil + sub.mu.Unlock() + sub.Unsubscribe() + } + } + + // If we are creating or updating let's process that request. + consName := o.cfg.Name + if shouldCreate { + if cfg.Durable != "" { + consName = cfg.Durable + } else if consName == "" { + consName = getHash(nuid.Next()) + } + var info *ConsumerInfo + if o.ctx != nil { + info, err = js.upsertConsumer(stream, consName, ccreq.Config, Context(o.ctx)) + } else { + info, err = js.upsertConsumer(stream, consName, ccreq.Config) + } + if err != nil { + var apiErr *APIError + if ok := errors.As(err, &apiErr); !ok { + cleanUpSub() + return nil, err + } + if consumer == _EMPTY_ || + (apiErr.ErrorCode != JSErrCodeConsumerAlreadyExists && apiErr.ErrorCode != JSErrCodeConsumerNameExists) { + cleanUpSub() + if errors.Is(apiErr, ErrStreamNotFound) { + return nil, ErrStreamNotFound + } + return nil, err + } + // We will not be using this sub here if we were push based. + if !isPullMode { + cleanUpSub() + } + + info, err = js.ConsumerInfo(stream, consumer) + if err != nil { + return nil, err + } + deliver, err = processConsInfo(info, o.cfg, isPullMode, subj, queue) + if err != nil { + return nil, err + } + + if !isPullMode { + // We can't reuse the channel, so if one was passed, we need to create a new one. + if isSync { + ch = make(chan *Msg, cap(ch)) + } else if ch != nil { + // User provided (ChanSubscription), simply try to drain it. + for done := false; !done; { + select { + case <-ch: + default: + done = true + } + } + } + jsi.deliver = deliver + jsi.hbi = info.Config.Heartbeat + + // Recreate the subscription here. + sub, err = nc.subscribe(jsi.deliver, queue, cb, ch, nil, isSync, jsi) + if err != nil { + return nil, err + } + hasFC = info.Config.FlowControl + hasHeartbeats = info.Config.Heartbeat > 0 + } + } else { + // Since the library created the JS consumer, it will delete it on Unsubscribe()/Drain() + sub.mu.Lock() + sub.jsi.dc = true + sub.jsi.pending = info.NumPending + info.Delivered.Consumer + // If this is an ephemeral, we did not have a consumer name, we get it from the info + // after the AddConsumer returns. + if consumer == _EMPTY_ { + sub.jsi.consumer = info.Name + if isPullMode { + sub.jsi.nms = fmt.Sprintf(js.apiSubj(apiRequestNextT), stream, info.Name) + } + } + sub.mu.Unlock() + } + // Capture max ack pending from the info response here which covers both + // success and failure followed by consumer lookup. + maxap = info.Config.MaxAckPending + } + + // If maxap is greater than the default sub's pending limit, use that. + if maxap > DefaultSubPendingMsgsLimit { + // For bytes limit, use the min of maxp*1MB or DefaultSubPendingBytesLimit + bl := maxap * 1024 * 1024 + if bl < DefaultSubPendingBytesLimit { + bl = DefaultSubPendingBytesLimit + } + if err := sub.SetPendingLimits(maxap, bl); err != nil { + return nil, err + } + } + + // Do heartbeats last if needed. + if hasHeartbeats { + sub.scheduleHeartbeatCheck() + } + // For ChanSubscriptions, if we know that there is flow control, we will + // start a go routine that evaluates the number of delivered messages + // and process flow control. + if sub.Type() == ChanSubscription && hasFC { + sub.chanSubcheckForFlowControlResponse() + } + + // Wait for context to get canceled if there is one. + if ctx != nil { + go func() { + <-ctx.Done() + sub.Unsubscribe() + }() + } + + return sub, nil +} + +// InitialConsumerPending returns the number of messages pending to be +// delivered to the consumer when the subscription was created. +func (sub *Subscription) InitialConsumerPending() (uint64, error) { + sub.mu.Lock() + defer sub.mu.Unlock() + if sub.jsi == nil || sub.jsi.consumer == _EMPTY_ { + return 0, fmt.Errorf("%w: not a JetStream subscription", ErrTypeSubscription) + } + return sub.jsi.pending, nil +} + +// This long-lived routine is used per ChanSubscription to check +// on the number of delivered messages and check for flow control response. +func (sub *Subscription) chanSubcheckForFlowControlResponse() { + sub.mu.Lock() + // We don't use defer since if we need to send an RC reply, we need + // to do it outside the sub's lock. So doing explicit unlock... + if sub.closed { + sub.mu.Unlock() + return + } + var fcReply string + var nc *Conn + + jsi := sub.jsi + if jsi.csfct == nil { + jsi.csfct = time.AfterFunc(chanSubFCCheckInterval, sub.chanSubcheckForFlowControlResponse) + } else { + fcReply = sub.checkForFlowControlResponse() + nc = sub.conn + // Do the reset here under the lock, it's ok... + jsi.csfct.Reset(chanSubFCCheckInterval) + } + sub.mu.Unlock() + // This call will return an error (which we don't care here) + // if nc is nil or fcReply is empty. + nc.Publish(fcReply, nil) +} + +// ErrConsumerSequenceMismatch represents an error from a consumer +// that received a Heartbeat including sequence different to the +// one expected from the view of the client. +type ErrConsumerSequenceMismatch struct { + // StreamResumeSequence is the stream sequence from where the consumer + // should resume consuming from the stream. + StreamResumeSequence uint64 + + // ConsumerSequence is the sequence of the consumer that is behind. + ConsumerSequence uint64 + + // LastConsumerSequence is the sequence of the consumer when the heartbeat + // was received. + LastConsumerSequence uint64 +} + +func (ecs *ErrConsumerSequenceMismatch) Error() string { + return fmt.Sprintf("nats: sequence mismatch for consumer at sequence %d (%d sequences behind), should restart consumer from stream sequence %d", + ecs.ConsumerSequence, + ecs.LastConsumerSequence-ecs.ConsumerSequence, + ecs.StreamResumeSequence, + ) +} + +// isJSControlMessage will return true if this is an empty control status message +// and indicate what type of control message it is, say jsCtrlHB or jsCtrlFC +func isJSControlMessage(msg *Msg) (bool, int) { + if len(msg.Data) > 0 || msg.Header.Get(statusHdr) != controlMsg { + return false, 0 + } + val := msg.Header.Get(descrHdr) + if strings.HasPrefix(val, "Idle") { + return true, jsCtrlHB + } + if strings.HasPrefix(val, "Flow") { + return true, jsCtrlFC + } + return true, 0 +} + +// Keeps track of the incoming message's reply subject so that the consumer's +// state (deliver sequence, etc..) can be checked against heartbeats. +// We will also bump the incoming data message sequence that is used in FC cases. +// Runs under the subscription lock +func (sub *Subscription) trackSequences(reply string) { + // For flow control, keep track of incoming message sequence. + sub.jsi.fciseq++ + sub.jsi.cmeta = reply +} + +// Check to make sure messages are arriving in order. +// Returns true if the sub had to be replaced. Will cause upper layers to return. +// The caller has verified that sub.jsi != nil and that this is not a control message. +// Lock should be held. +func (sub *Subscription) checkOrderedMsgs(m *Msg) bool { + // Ignore msgs with no reply like HBs and flow control, they are handled elsewhere. + if m.Reply == _EMPTY_ { + return false + } + + // Normal message here. + tokens, err := parser.GetMetadataFields(m.Reply) + if err != nil { + return false + } + sseq, dseq := parser.ParseNum(tokens[parser.AckStreamSeqTokenPos]), parser.ParseNum(tokens[parser.AckConsumerSeqTokenPos]) + + jsi := sub.jsi + if dseq != jsi.dseq { + sub.resetOrderedConsumer(jsi.sseq + 1) + return true + } + // Update our tracking here. + jsi.dseq, jsi.sseq = dseq+1, sseq + return false +} + +// Update and replace sid. +// Lock should be held on entry but will be unlocked to prevent lock inversion. +func (sub *Subscription) applyNewSID() (osid int64) { + nc := sub.conn + sub.mu.Unlock() + + nc.subsMu.Lock() + osid = sub.sid + delete(nc.subs, osid) + // Place new one. + nc.ssid++ + nsid := nc.ssid + nc.subs[nsid] = sub + nc.subsMu.Unlock() + + sub.mu.Lock() + sub.sid = nsid + return osid +} + +// We are here if we have detected a gap with an ordered consumer. +// We will create a new consumer and rewire the low level subscription. +// Lock should be held. +func (sub *Subscription) resetOrderedConsumer(sseq uint64) { + nc := sub.conn + if sub.jsi == nil || nc == nil || sub.closed { + return + } + + var maxStr string + // If there was an AUTO_UNSUB done, we need to adjust the new value + // to send after the SUB for the new sid. + if sub.max > 0 { + if sub.jsi.fciseq < sub.max { + adjustedMax := sub.max - sub.jsi.fciseq + maxStr = strconv.Itoa(int(adjustedMax)) + } else { + // We are already at the max, so we should just unsub the + // existing sub and be done + go func(sid int64) { + nc.mu.Lock() + nc.bw.appendString(fmt.Sprintf(unsubProto, sid, _EMPTY_)) + nc.kickFlusher() + nc.mu.Unlock() + }(sub.sid) + return + } + } + + // Quick unsubscribe. Since we know this is a simple push subscriber we do in place. + osid := sub.applyNewSID() + + // Grab new inbox. + newDeliver := nc.NewInbox() + sub.Subject = newDeliver + + // Snapshot the new sid under sub lock. + nsid := sub.sid + + // We are still in the low level readLoop for the connection so we need + // to spin a go routine to try to create the new consumer. + go func() { + // Unsubscribe and subscribe with new inbox and sid. + // Remap a new low level sub into this sub since its client accessible. + // This is done here in this go routine to prevent lock inversion. + nc.mu.Lock() + nc.bw.appendString(fmt.Sprintf(unsubProto, osid, _EMPTY_)) + nc.bw.appendString(fmt.Sprintf(subProto, newDeliver, _EMPTY_, nsid)) + if maxStr != _EMPTY_ { + nc.bw.appendString(fmt.Sprintf(unsubProto, nsid, maxStr)) + } + nc.kickFlusher() + nc.mu.Unlock() + + pushErr := func(err error) { + nc.handleConsumerSequenceMismatch(sub, fmt.Errorf("%w: recreating ordered consumer", err)) + nc.unsubscribe(sub, 0, true) + } + + sub.mu.Lock() + jsi := sub.jsi + // Reset some items in jsi. + jsi.dseq = 1 + jsi.cmeta = _EMPTY_ + jsi.fcr, jsi.fcd = _EMPTY_, 0 + jsi.deliver = newDeliver + // Reset consumer request for starting policy. + cfg := jsi.ccreq.Config + cfg.DeliverSubject = newDeliver + cfg.DeliverPolicy = DeliverByStartSequencePolicy + cfg.OptStartSeq = sseq + // In case the consumer was created with a start time, we need to clear it + // since we are now using a start sequence. + cfg.OptStartTime = nil + + js := jsi.js + sub.mu.Unlock() + + sub.mu.Lock() + // Attempt to delete the existing consumer. + // We don't wait for the response since even if it's unsuccessful, + // inactivity threshold will kick in and delete it. + if jsi.consumer != _EMPTY_ { + go js.DeleteConsumer(jsi.stream, jsi.consumer) + } + jsi.consumer = "" + sub.mu.Unlock() + consName := getHash(nuid.Next()) + var cinfo *ConsumerInfo + var err error + if js.opts.ctx != nil { + cinfo, err = js.upsertConsumer(jsi.stream, consName, cfg, Context(js.opts.ctx)) + } else { + cinfo, err = js.upsertConsumer(jsi.stream, consName, cfg) + } + if err != nil { + var apiErr *APIError + if errors.Is(err, ErrJetStreamNotEnabled) || errors.Is(err, ErrTimeout) || errors.Is(err, context.DeadlineExceeded) { + // if creating consumer failed, retry + return + } else if errors.As(err, &apiErr) && apiErr.ErrorCode == JSErrCodeInsufficientResourcesErr { + // retry for insufficient resources, as it may mean that client is connected to a running + // server in cluster while the server hosting R1 JetStream resources is restarting + return + } else if errors.As(err, &apiErr) && apiErr.ErrorCode == JSErrCodeJetStreamNotAvailable { + // retry if JetStream meta leader is temporarily unavailable + return + } + pushErr(err) + return + } + + sub.mu.Lock() + jsi.consumer = cinfo.Name + sub.mu.Unlock() + }() +} + +// For jetstream subscriptions, returns the number of delivered messages. +// For ChanSubscription, this value is computed based on the known number +// of messages added to the channel minus the current size of that channel. +// Lock held on entry +func (sub *Subscription) getJSDelivered() uint64 { + if sub.typ == ChanSubscription { + return sub.jsi.fciseq - uint64(len(sub.mch)) + } + return sub.delivered +} + +// checkForFlowControlResponse will check to see if we should send a flow control response +// based on the subscription current delivered index and the target. +// Runs under subscription lock +func (sub *Subscription) checkForFlowControlResponse() string { + // Caller has verified that there is a sub.jsi and fc + jsi := sub.jsi + jsi.active = true + if sub.getJSDelivered() >= jsi.fcd { + fcr := jsi.fcr + jsi.fcr, jsi.fcd = _EMPTY_, 0 + return fcr + } + return _EMPTY_ +} + +// Record an inbound flow control message. +// Runs under subscription lock +func (sub *Subscription) scheduleFlowControlResponse(reply string) { + sub.jsi.fcr, sub.jsi.fcd = reply, sub.jsi.fciseq +} + +// Checks for activity from our consumer. +// If we do not think we are active send an async error. +func (sub *Subscription) activityCheck() { + sub.mu.Lock() + jsi := sub.jsi + if jsi == nil || sub.closed { + sub.mu.Unlock() + return + } + + active := jsi.active + jsi.hbc.Reset(jsi.hbi * hbcThresh) + jsi.active = false + nc := sub.conn + sub.mu.Unlock() + + if !active { + if !jsi.ordered || nc.Status() != CONNECTED { + nc.mu.Lock() + if errCB := nc.Opts.AsyncErrorCB; errCB != nil { + nc.ach.push(func() { errCB(nc, sub, ErrConsumerNotActive) }) + } + nc.mu.Unlock() + return + } + sub.mu.Lock() + sub.resetOrderedConsumer(jsi.sseq + 1) + sub.mu.Unlock() + } +} + +// scheduleHeartbeatCheck sets up the timer check to make sure we are active +// or receiving idle heartbeats.. +func (sub *Subscription) scheduleHeartbeatCheck() { + sub.mu.Lock() + defer sub.mu.Unlock() + + jsi := sub.jsi + if jsi == nil { + return + } + + if jsi.hbc == nil { + jsi.hbc = time.AfterFunc(jsi.hbi*hbcThresh, sub.activityCheck) + } else { + jsi.hbc.Reset(jsi.hbi * hbcThresh) + } +} + +// handleConsumerSequenceMismatch will send an async error that can be used to restart a push based consumer. +func (nc *Conn) handleConsumerSequenceMismatch(sub *Subscription, err error) { + nc.mu.Lock() + errCB := nc.Opts.AsyncErrorCB + if errCB != nil { + nc.ach.push(func() { errCB(nc, sub, err) }) + } + nc.mu.Unlock() +} + +// checkForSequenceMismatch will make sure we have not missed any messages since last seen. +func (nc *Conn) checkForSequenceMismatch(msg *Msg, s *Subscription, jsi *jsSub) { + // Process heartbeat received, get latest control metadata if present. + s.mu.Lock() + ctrl, ordered := jsi.cmeta, jsi.ordered + jsi.active = true + s.mu.Unlock() + + if ctrl == _EMPTY_ { + return + } + + tokens, err := parser.GetMetadataFields(ctrl) + if err != nil { + return + } + + // Consumer sequence. + var ldseq string + dseq := tokens[parser.AckConsumerSeqTokenPos] + hdr := msg.Header[lastConsumerSeqHdr] + if len(hdr) == 1 { + ldseq = hdr[0] + } + + // Detect consumer sequence mismatch and whether + // should restart the consumer. + if ldseq != dseq { + // Dispatch async error including details such as + // from where the consumer could be restarted. + sseq := parser.ParseNum(tokens[parser.AckStreamSeqTokenPos]) + if ordered { + s.mu.Lock() + s.resetOrderedConsumer(jsi.sseq + 1) + s.mu.Unlock() + } else { + ecs := &ErrConsumerSequenceMismatch{ + StreamResumeSequence: uint64(sseq), + ConsumerSequence: parser.ParseNum(dseq), + LastConsumerSequence: parser.ParseNum(ldseq), + } + nc.handleConsumerSequenceMismatch(s, ecs) + } + } +} + +type streamRequest struct { + Subject string `json:"subject,omitempty"` +} + +type streamNamesResponse struct { + apiResponse + apiPaged + Streams []string `json:"streams"` +} + +type subOpts struct { + // For attaching. + stream, consumer string + // For creating or updating. + cfg *ConsumerConfig + // For binding a subscription to a consumer without creating it. + bound bool + // For manual ack + mack bool + // For an ordered consumer. + ordered bool + ctx context.Context + + // To disable calling ConsumerInfo + skipCInfo bool +} + +// SkipConsumerLookup will omit looking up consumer when [Bind], [Durable] +// or [ConsumerName] are provided. +// +// NOTE: This setting may cause an existing consumer to be overwritten. Also, +// because consumer lookup is skipped, all consumer options like AckPolicy, +// DeliverSubject etc. need to be provided even if consumer already exists. +func SkipConsumerLookup() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.skipCInfo = true + return nil + }) +} + +// OrderedConsumer will create a FIFO direct/ephemeral consumer for in order delivery of messages. +// There are no redeliveries and no acks, and flow control and heartbeats will be added but +// will be taken care of without additional client code. +func OrderedConsumer() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.ordered = true + return nil + }) +} + +// ManualAck disables auto ack functionality for async subscriptions. +func ManualAck() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.mack = true + return nil + }) +} + +// Description will set the description for the created consumer. +func Description(description string) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.Description = description + return nil + }) +} + +// Durable defines the consumer name for JetStream durable subscribers. +// This function will return ErrInvalidConsumerName if the name contains +// any dot ".". +func Durable(consumer string) SubOpt { + return subOptFn(func(opts *subOpts) error { + if opts.cfg.Durable != _EMPTY_ { + return errors.New("nats: option Durable set more than once") + } + if opts.consumer != _EMPTY_ && opts.consumer != consumer { + return fmt.Errorf("nats: duplicate consumer names (%s and %s)", opts.consumer, consumer) + } + if err := checkConsumerName(consumer); err != nil { + return err + } + + opts.cfg.Durable = consumer + return nil + }) +} + +// DeliverAll will configure a Consumer to receive all the +// messages from a Stream. +func DeliverAll() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverPolicy = DeliverAllPolicy + return nil + }) +} + +// DeliverLast configures a Consumer to receive messages +// starting with the latest one. +func DeliverLast() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverPolicy = DeliverLastPolicy + return nil + }) +} + +// DeliverLastPerSubject configures a Consumer to receive messages +// starting with the latest one for each filtered subject. +func DeliverLastPerSubject() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverPolicy = DeliverLastPerSubjectPolicy + return nil + }) +} + +// DeliverNew configures a Consumer to receive messages +// published after the subscription. +func DeliverNew() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverPolicy = DeliverNewPolicy + return nil + }) +} + +// StartSequence configures a Consumer to receive +// messages from a start sequence. +func StartSequence(seq uint64) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverPolicy = DeliverByStartSequencePolicy + opts.cfg.OptStartSeq = seq + return nil + }) +} + +// StartTime configures a Consumer to receive +// messages from a start time. +func StartTime(startTime time.Time) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverPolicy = DeliverByStartTimePolicy + opts.cfg.OptStartTime = &startTime + return nil + }) +} + +// AckNone requires no acks for delivered messages. +func AckNone() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.AckPolicy = AckNonePolicy + return nil + }) +} + +// AckAll when acking a sequence number, this implicitly acks all sequences +// below this one as well. +func AckAll() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.AckPolicy = AckAllPolicy + return nil + }) +} + +// AckExplicit requires ack or nack for all messages. +func AckExplicit() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.AckPolicy = AckExplicitPolicy + return nil + }) +} + +// MaxDeliver sets the number of redeliveries for a message. +func MaxDeliver(n int) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MaxDeliver = n + return nil + }) +} + +// MaxAckPending sets the number of outstanding acks that are allowed before +// message delivery is halted. +func MaxAckPending(n int) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MaxAckPending = n + return nil + }) +} + +// ReplayOriginal replays the messages at the original speed. +func ReplayOriginal() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.ReplayPolicy = ReplayOriginalPolicy + return nil + }) +} + +// ReplayInstant replays the messages as fast as possible. +func ReplayInstant() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.ReplayPolicy = ReplayInstantPolicy + return nil + }) +} + +// RateLimit is the Bits per sec rate limit applied to a push consumer. +func RateLimit(n uint64) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.RateLimit = n + return nil + }) +} + +// BackOff is an array of time durations that represent the time to delay based on delivery count. +func BackOff(backOff []time.Duration) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.BackOff = backOff + return nil + }) +} + +// BindStream binds a consumer to a stream explicitly based on a name. +// When a stream name is not specified, the library uses the subscribe +// subject as a way to find the stream name. It is done by making a request +// to the server to get list of stream names that have a filter for this +// subject. If the returned list contains a single stream, then this +// stream name will be used, otherwise the `ErrNoMatchingStream` is returned. +// To avoid the stream lookup, provide the stream name with this function. +// See also `Bind()`. +func BindStream(stream string) SubOpt { + return subOptFn(func(opts *subOpts) error { + if opts.stream != _EMPTY_ && opts.stream != stream { + return fmt.Errorf("nats: duplicate stream name (%s and %s)", opts.stream, stream) + } + + opts.stream = stream + return nil + }) +} + +// Bind binds a subscription to an existing consumer from a stream without attempting to create. +// The first argument is the stream name and the second argument will be the consumer name. +func Bind(stream, consumer string) SubOpt { + return subOptFn(func(opts *subOpts) error { + if stream == _EMPTY_ { + return ErrStreamNameRequired + } + if consumer == _EMPTY_ { + return ErrConsumerNameRequired + } + + // In case of pull subscribers, the durable name is a required parameter + // so check that they are not different. + if opts.cfg.Durable != _EMPTY_ && opts.cfg.Durable != consumer { + return fmt.Errorf("nats: duplicate consumer names (%s and %s)", opts.cfg.Durable, consumer) + } + if opts.stream != _EMPTY_ && opts.stream != stream { + return fmt.Errorf("nats: duplicate stream name (%s and %s)", opts.stream, stream) + } + opts.stream = stream + opts.consumer = consumer + opts.bound = true + return nil + }) +} + +// EnableFlowControl enables flow control for a push based consumer. +func EnableFlowControl() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.FlowControl = true + return nil + }) +} + +// IdleHeartbeat enables push based consumers to have idle heartbeats delivered. +// For pull consumers, idle heartbeat has to be set on each [Fetch] call. +func IdleHeartbeat(duration time.Duration) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.Heartbeat = duration + return nil + }) +} + +// DeliverSubject specifies the JetStream consumer deliver subject. +// +// This option is used only in situations where the consumer does not exist +// and a creation request is sent to the server. If not provided, an inbox +// will be selected. +// If a consumer exists, then the NATS subscription will be created on +// the JetStream consumer's DeliverSubject, not necessarily this subject. +func DeliverSubject(subject string) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.DeliverSubject = subject + return nil + }) +} + +// HeadersOnly() will instruct the consumer to only deliver headers and no payloads. +func HeadersOnly() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.HeadersOnly = true + return nil + }) +} + +// MaxRequestBatch sets the maximum pull consumer batch size that a Fetch() +// can request. +func MaxRequestBatch(max int) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MaxRequestBatch = max + return nil + }) +} + +// MaxRequestExpires sets the maximum pull consumer request expiration that a +// Fetch() can request (using the Fetch's timeout value). +func MaxRequestExpires(max time.Duration) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MaxRequestExpires = max + return nil + }) +} + +// MaxRequesMaxBytes sets the maximum pull consumer request bytes that a +// Fetch() can receive. +func MaxRequestMaxBytes(bytes int) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MaxRequestMaxBytes = bytes + return nil + }) +} + +// InactiveThreshold indicates how long the server should keep a consumer +// after detecting a lack of activity. In NATS Server 2.8.4 and earlier, this +// option only applies to ephemeral consumers. In NATS Server 2.9.0 and later, +// this option applies to both ephemeral and durable consumers, allowing durable +// consumers to also be deleted automatically after the inactivity threshold has +// passed. +func InactiveThreshold(threshold time.Duration) SubOpt { + return subOptFn(func(opts *subOpts) error { + if threshold < 0 { + return fmt.Errorf("invalid InactiveThreshold value (%v), needs to be greater or equal to 0", threshold) + } + opts.cfg.InactiveThreshold = threshold + return nil + }) +} + +// ConsumerReplicas sets the number of replica count for a consumer. +func ConsumerReplicas(replicas int) SubOpt { + return subOptFn(func(opts *subOpts) error { + if replicas < 1 { + return fmt.Errorf("invalid ConsumerReplicas value (%v), needs to be greater than 0", replicas) + } + opts.cfg.Replicas = replicas + return nil + }) +} + +// ConsumerMemoryStorage sets the memory storage to true for a consumer. +func ConsumerMemoryStorage() SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MemoryStorage = true + return nil + }) +} + +// ConsumerName sets the name for a consumer. +func ConsumerName(name string) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.Name = name + return nil + }) +} + +// ConsumerFilterSubjects can be used to set multiple subject filters on the consumer. +// It has to be used in conjunction with [nats.BindStream] and +// with empty 'subject' parameter. +func ConsumerFilterSubjects(subjects ...string) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.FilterSubjects = subjects + return nil + }) +} + +func (sub *Subscription) ConsumerInfo() (*ConsumerInfo, error) { + sub.mu.Lock() + // TODO(dlc) - Better way to mark especially if we attach. + if sub.jsi == nil || sub.jsi.consumer == _EMPTY_ { + if sub.jsi.ordered { + sub.mu.Unlock() + return nil, ErrConsumerInfoOnOrderedReset + } + sub.mu.Unlock() + return nil, ErrTypeSubscription + } + + // Consumer info lookup should fail if in direct mode. + js := sub.jsi.js + stream, consumer := sub.jsi.stream, sub.jsi.consumer + sub.mu.Unlock() + + return js.getConsumerInfo(stream, consumer) +} + +type pullOpts struct { + maxBytes int + ttl time.Duration + ctx context.Context + hb time.Duration +} + +// PullOpt are the options that can be passed when pulling a batch of messages. +type PullOpt interface { + configurePull(opts *pullOpts) error +} + +// PullMaxWaiting defines the max inflight pull requests. +func PullMaxWaiting(n int) SubOpt { + return subOptFn(func(opts *subOpts) error { + opts.cfg.MaxWaiting = n + return nil + }) +} + +type PullHeartbeat time.Duration + +func (h PullHeartbeat) configurePull(opts *pullOpts) error { + if h <= 0 { + return fmt.Errorf("%w: idle heartbeat has to be greater than 0", ErrInvalidArg) + } + opts.hb = time.Duration(h) + return nil +} + +// PullMaxBytes defines the max bytes allowed for a fetch request. +type PullMaxBytes int + +func (n PullMaxBytes) configurePull(opts *pullOpts) error { + opts.maxBytes = int(n) + return nil +} + +var ( + // errNoMessages is an error that a Fetch request using no_wait can receive to signal + // that there are no more messages available. + errNoMessages = errors.New("nats: no messages") + + // errRequestsPending is an error that represents a sub.Fetch requests that was using + // no_wait and expires time got discarded by the server. + errRequestsPending = errors.New("nats: requests pending") +) + +// Returns if the given message is a user message or not, and if +// `checkSts` is true, returns appropriate error based on the +// content of the status (404, etc..) +func checkMsg(msg *Msg, checkSts, isNoWait bool) (usrMsg bool, err error) { + // Assume user message + usrMsg = true + + // If payload or no header, consider this a user message + if len(msg.Data) > 0 || len(msg.Header) == 0 { + return + } + // Look for status header + val := msg.Header.Get(statusHdr) + // If not present, then this is considered a user message + if val == _EMPTY_ { + return + } + // At this point, this is not a user message since there is + // no payload and a "Status" header. + usrMsg = false + + // If we don't care about status, we are done. + if !checkSts { + return + } + + // if it's a heartbeat message, report as not user msg + if isHb, _ := isJSControlMessage(msg); isHb { + return + } + switch val { + case noResponders: + err = ErrNoResponders + case noMessagesSts: + // 404 indicates that there are no messages. + err = errNoMessages + case reqTimeoutSts: + // In case of a fetch request with no wait request and expires time, + // need to skip 408 errors and retry. + if isNoWait { + err = errRequestsPending + } else { + // Older servers may send a 408 when a request in the server was expired + // and interest is still found, which will be the case for our + // implementation. Regardless, ignore 408 errors until receiving at least + // one message when making requests without no_wait. + err = ErrTimeout + } + case jetStream409Sts: + if strings.Contains(strings.ToLower(msg.Header.Get(descrHdr)), "consumer deleted") { + err = ErrConsumerDeleted + break + } + + if strings.Contains(strings.ToLower(msg.Header.Get(descrHdr)), "leadership change") { + err = ErrConsumerLeadershipChanged + break + } + fallthrough + default: + err = fmt.Errorf("nats: %s", msg.Header.Get(descrHdr)) + } + return +} + +// Fetch pulls a batch of messages from a stream for a pull consumer. +func (sub *Subscription) Fetch(batch int, opts ...PullOpt) ([]*Msg, error) { + if sub == nil { + return nil, ErrBadSubscription + } + if batch < 1 { + return nil, ErrInvalidArg + } + + var o pullOpts + for _, opt := range opts { + if err := opt.configurePull(&o); err != nil { + return nil, err + } + } + if o.ctx != nil && o.ttl != 0 { + return nil, ErrContextAndTimeout + } + + sub.mu.Lock() + jsi := sub.jsi + // Reject if this is not a pull subscription. Note that sub.typ is SyncSubscription, + // so check for jsi.pull boolean instead. + if jsi == nil || !jsi.pull { + sub.mu.Unlock() + return nil, ErrTypeSubscription + } + + nc := sub.conn + nms := sub.jsi.nms + rply, _ := newFetchInbox(jsi.deliver) + js := sub.jsi.js + pmc := len(sub.mch) > 0 + + // All fetch requests have an expiration, in case of no explicit expiration + // then the default timeout of the JetStream context is used. + ttl := o.ttl + if ttl == 0 { + ttl = js.opts.wait + } + sub.mu.Unlock() + + // Use the given context or setup a default one for the span + // of the pull batch request. + var ( + ctx = o.ctx + err error + cancel context.CancelFunc + ) + if ctx == nil { + ctx, cancel = context.WithTimeout(context.Background(), ttl) + } else if _, hasDeadline := ctx.Deadline(); !hasDeadline { + // Prevent from passing the background context which will just block + // and cannot be canceled either. + if octx, ok := ctx.(ContextOpt); ok && octx.Context == context.Background() { + return nil, ErrNoDeadlineContext + } + + // If the context did not have a deadline, then create a new child context + // that will use the default timeout from the JS context. + ctx, cancel = context.WithTimeout(ctx, ttl) + } else { + ctx, cancel = context.WithCancel(ctx) + } + defer cancel() + + // if heartbeat is set, validate it against the context timeout + if o.hb > 0 { + deadline, _ := ctx.Deadline() + if 2*o.hb >= time.Until(deadline) { + return nil, fmt.Errorf("%w: idle heartbeat value too large", ErrInvalidArg) + } + } + + // Check if context not done already before making the request. + select { + case <-ctx.Done(): + if o.ctx != nil { // Timeout or Cancel triggered by context object option + err = ctx.Err() + } else { // Timeout triggered by timeout option + err = ErrTimeout + } + default: + } + if err != nil { + return nil, err + } + + var ( + msgs = make([]*Msg, 0, batch) + msg *Msg + ) + for pmc && len(msgs) < batch { + // Check next msg with booleans that say that this is an internal call + // for a pull subscribe (so don't reject it) and don't wait if there + // are no messages. + msg, err = sub.nextMsgWithContext(ctx, true, false) + if err != nil { + if errors.Is(err, errNoMessages) { + err = nil + } + break + } + // Check msg but just to determine if this is a user message + // or status message, however, we don't care about values of status + // messages at this point in the Fetch() call, so checkMsg can't + // return an error. + if usrMsg, _ := checkMsg(msg, false, false); usrMsg { + msgs = append(msgs, msg) + } + } + var hbTimer *time.Timer + defer func() { + if hbTimer != nil { + hbTimer.Stop() + } + }() + var hbErr error + sub.mu.Lock() + subClosed := sub.closed || sub.draining + sub.mu.Unlock() + if subClosed { + err = errors.Join(ErrBadSubscription, ErrSubscriptionClosed) + } + hbLock := sync.Mutex{} + var disconnected atomic.Bool + if err == nil && len(msgs) < batch && !subClosed { + // For batch real size of 1, it does not make sense to set no_wait in + // the request. + noWait := batch-len(msgs) > 1 + + var nr nextRequest + + sendReq := func() error { + // The current deadline for the context will be used + // to set the expires TTL for a fetch request. + deadline, _ := ctx.Deadline() + ttl = time.Until(deadline) + + // Check if context has already been canceled or expired. + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + // Make our request expiration a bit shorter than the current timeout. + expiresDiff := time.Duration(float64(ttl) * 0.1) + if expiresDiff > 5*time.Second { + expiresDiff = 5 * time.Second + } + expires := ttl - expiresDiff + + nr.Batch = batch - len(msgs) + nr.Expires = expires + nr.NoWait = noWait + nr.MaxBytes = o.maxBytes + if 2*o.hb < expires { + nr.Heartbeat = o.hb + } else { + nr.Heartbeat = 0 + } + req, _ := json.Marshal(nr) + if err := nc.PublishRequest(nms, rply, req); err != nil { + return err + } + if o.hb > 0 { + if hbTimer == nil { + hbTimer = time.AfterFunc(2*o.hb, func() { + hbLock.Lock() + hbErr = ErrNoHeartbeat + hbLock.Unlock() + cancel() + }) + } else { + hbTimer.Reset(2 * o.hb) + } + } + return nil + } + connStatusChanged := nc.StatusChanged() + go func() { + select { + case <-ctx.Done(): + case <-connStatusChanged: + disconnected.Store(true) + cancel() + } + nc.RemoveStatusListener(connStatusChanged) + }() + err = sendReq() + for err == nil && len(msgs) < batch { + // Ask for next message and wait if there are no messages + msg, err = sub.nextMsgWithContext(ctx, true, true) + if err == nil { + if hbTimer != nil { + hbTimer.Reset(2 * o.hb) + } + var usrMsg bool + + usrMsg, err = checkMsg(msg, true, noWait) + if err == nil && usrMsg { + msgs = append(msgs, msg) + } else if noWait && (errors.Is(err, errNoMessages) || errors.Is(err, errRequestsPending)) && len(msgs) == 0 { + // If we have a 404/408 for our "no_wait" request and have + // not collected any message, then resend request to + // wait this time. + noWait = false + err = sendReq() + } else if errors.Is(err, ErrTimeout) && len(msgs) == 0 { + // If we get a 408, we will bail if we already collected some + // messages, otherwise ignore and go back calling nextMsg. + err = nil + } + } + } + } + // If there is at least a message added to msgs, then need to return OK and no error + if err != nil && len(msgs) == 0 { + hbLock.Lock() + defer hbLock.Unlock() + if hbErr != nil { + return nil, hbErr + } + if disconnected.Load() { + return nil, ErrFetchDisconnected + } + return nil, o.checkCtxErr(err) + } + return msgs, nil +} + +// newFetchInbox returns subject used as reply subject when sending pull requests +// as well as request ID. For non-wildcard subject, request ID is empty and +// passed subject is not transformed +func newFetchInbox(subj string) (string, string) { + if !strings.HasSuffix(subj, ".*") { + return subj, "" + } + reqID := nuid.Next() + var sb strings.Builder + sb.WriteString(subj[:len(subj)-1]) + sb.WriteString(reqID) + return sb.String(), reqID +} + +func subjectMatchesReqID(subject, reqID string) bool { + subjectParts := strings.Split(subject, ".") + if len(subjectParts) < 2 { + return false + } + return subjectParts[len(subjectParts)-1] == reqID +} + +// MessageBatch provides methods to retrieve messages consumed using [Subscribe.FetchBatch]. +type MessageBatch interface { + // Messages returns a channel on which messages will be published. + Messages() <-chan *Msg + + // Error returns an error encountered when fetching messages. + Error() error + + // Done signals end of execution. + Done() <-chan struct{} +} + +type messageBatch struct { + sync.Mutex + msgs chan *Msg + err error + done chan struct{} +} + +func (mb *messageBatch) Messages() <-chan *Msg { + mb.Lock() + defer mb.Unlock() + return mb.msgs +} + +func (mb *messageBatch) Error() error { + mb.Lock() + defer mb.Unlock() + return mb.err +} + +func (mb *messageBatch) Done() <-chan struct{} { + mb.Lock() + defer mb.Unlock() + return mb.done +} + +// FetchBatch pulls a batch of messages from a stream for a pull consumer. +// Unlike [Subscription.Fetch], it is non blocking and returns [MessageBatch], +// allowing to retrieve incoming messages from a channel. +// The returned channel is always closed after all messages for a batch have been +// delivered by the server - it is safe to iterate over it using range. +// +// To avoid using default JetStream timeout as fetch expiry time, use [nats.MaxWait] +// or [nats.Context] (with deadline set). +// +// This method will not return error in case of pull request expiry (even if there are no messages). +// Any other error encountered when receiving messages will cause FetchBatch to stop receiving new messages. +func (sub *Subscription) FetchBatch(batch int, opts ...PullOpt) (MessageBatch, error) { + if sub == nil { + return nil, ErrBadSubscription + } + if batch < 1 { + return nil, ErrInvalidArg + } + + var o pullOpts + for _, opt := range opts { + if err := opt.configurePull(&o); err != nil { + return nil, err + } + } + if o.ctx != nil && o.ttl != 0 { + return nil, ErrContextAndTimeout + } + sub.mu.Lock() + jsi := sub.jsi + // Reject if this is not a pull subscription. Note that sub.typ is SyncSubscription, + // so check for jsi.pull boolean instead. + if jsi == nil || !jsi.pull { + sub.mu.Unlock() + return nil, ErrTypeSubscription + } + + nc := sub.conn + nms := sub.jsi.nms + rply, reqID := newFetchInbox(sub.jsi.deliver) + js := sub.jsi.js + pmc := len(sub.mch) > 0 + + // All fetch requests have an expiration, in case of no explicit expiration + // then the default timeout of the JetStream context is used. + ttl := o.ttl + if ttl == 0 { + ttl = js.opts.wait + } + sub.mu.Unlock() + + // Use the given context or setup a default one for the span + // of the pull batch request. + var ( + ctx = o.ctx + cancel context.CancelFunc + cancelContext = true + ) + if ctx == nil { + ctx, cancel = context.WithTimeout(context.Background(), ttl) + } else if _, hasDeadline := ctx.Deadline(); !hasDeadline { + // Prevent from passing the background context which will just block + // and cannot be canceled either. + if octx, ok := ctx.(ContextOpt); ok && octx.Context == context.Background() { + return nil, ErrNoDeadlineContext + } + + // If the context did not have a deadline, then create a new child context + // that will use the default timeout from the JS context. + ctx, cancel = context.WithTimeout(ctx, ttl) + } else { + ctx, cancel = context.WithCancel(ctx) + } + defer func() { + // only cancel the context here if we are sure the fetching goroutine has not been started yet + if cancelContext { + cancel() + } + }() + + // if heartbeat is set, validate it against the context timeout + if o.hb > 0 { + deadline, _ := ctx.Deadline() + if 2*o.hb >= time.Until(deadline) { + return nil, fmt.Errorf("%w: idle heartbeat value too large", ErrInvalidArg) + } + } + + // Check if context not done already before making the request. + select { + case <-ctx.Done(): + if o.ctx != nil { // Timeout or Cancel triggered by context object option + return nil, ctx.Err() + } else { // Timeout triggered by timeout option + return nil, ErrTimeout + } + default: + } + + result := &messageBatch{ + msgs: make(chan *Msg, batch), + done: make(chan struct{}, 1), + } + var msg *Msg + for pmc && len(result.msgs) < batch { + // Check next msg with booleans that say that this is an internal call + // for a pull subscribe (so don't reject it) and don't wait if there + // are no messages. + msg, err := sub.nextMsgWithContext(ctx, true, false) + if err != nil { + if errors.Is(err, errNoMessages) { + err = nil + } + result.err = err + break + } + // Check msg but just to determine if this is a user message + // or status message, however, we don't care about values of status + // messages at this point in the Fetch() call, so checkMsg can't + // return an error. + if usrMsg, _ := checkMsg(msg, false, false); usrMsg { + result.msgs <- msg + } + } + sub.mu.Lock() + subClosed := sub.closed || sub.draining + sub.mu.Unlock() + if len(result.msgs) == batch || result.err != nil || subClosed { + close(result.msgs) + if subClosed && len(result.msgs) == 0 { + return nil, errors.Join(ErrBadSubscription, ErrSubscriptionClosed) + } + result.done <- struct{}{} + return result, nil + } + + deadline, _ := ctx.Deadline() + ttl = time.Until(deadline) + + // Make our request expiration a bit shorter than the current timeout. + expiresDiff := time.Duration(float64(ttl) * 0.1) + if expiresDiff > 5*time.Second { + expiresDiff = 5 * time.Second + } + expires := ttl - expiresDiff + + connStatusChanged := nc.StatusChanged() + var disconnected atomic.Bool + go func() { + select { + case <-ctx.Done(): + case <-connStatusChanged: + disconnected.Store(true) + cancel() + } + nc.RemoveStatusListener(connStatusChanged) + }() + requestBatch := batch - len(result.msgs) + req := nextRequest{ + Expires: expires, + Batch: requestBatch, + MaxBytes: o.maxBytes, + Heartbeat: o.hb, + } + reqJSON, err := json.Marshal(req) + if err != nil { + close(result.msgs) + result.done <- struct{}{} + result.err = err + return result, nil + } + if err := nc.PublishRequest(nms, rply, reqJSON); err != nil { + if len(result.msgs) == 0 { + return nil, err + } + close(result.msgs) + result.done <- struct{}{} + result.err = err + return result, nil + } + var hbTimer *time.Timer + defer func() { + if hbTimer != nil { + hbTimer.Stop() + } + }() + var hbErr error + if o.hb > 0 { + hbTimer = time.AfterFunc(2*o.hb, func() { + result.Lock() + hbErr = ErrNoHeartbeat + result.Unlock() + cancel() + }) + } + cancelContext = false + go func() { + defer cancel() + var requestMsgs int + for requestMsgs < requestBatch { + // Ask for next message and wait if there are no messages + msg, err = sub.nextMsgWithContext(ctx, true, true) + if err != nil { + break + } + if hbTimer != nil { + hbTimer.Reset(2 * o.hb) + } + var usrMsg bool + + usrMsg, err = checkMsg(msg, true, false) + if err != nil { + if errors.Is(err, ErrTimeout) { + if reqID != "" && !subjectMatchesReqID(msg.Subject, reqID) { + // ignore timeout message from server if it comes from a different pull request + continue + } + err = nil + } + break + } + if usrMsg { + result.Lock() + result.msgs <- msg + result.Unlock() + requestMsgs++ + } + } + if err != nil { + result.Lock() + if hbErr != nil { + result.err = hbErr + } else if disconnected.Load() { + result.err = ErrFetchDisconnected + } else { + result.err = o.checkCtxErr(err) + } + result.Unlock() + } + close(result.msgs) + result.Lock() + result.done <- struct{}{} + result.Unlock() + }() + return result, nil +} + +// checkCtxErr is used to determine whether ErrTimeout should be returned in case of context timeout +func (o *pullOpts) checkCtxErr(err error) error { + if o.ctx == nil && errors.Is(err, context.DeadlineExceeded) { + return ErrTimeout + } + return err +} + +func (js *js) getConsumerInfo(stream, consumer string) (*ConsumerInfo, error) { + ctx, cancel := context.WithTimeout(context.Background(), js.opts.wait) + defer cancel() + return js.getConsumerInfoContext(ctx, stream, consumer) +} + +func (js *js) getConsumerInfoContext(ctx context.Context, stream, consumer string) (*ConsumerInfo, error) { + ccInfoSubj := fmt.Sprintf(apiConsumerInfoT, stream, consumer) + resp, err := js.apiRequestWithContext(ctx, js.apiSubj(ccInfoSubj), nil) + if err != nil { + if errors.Is(err, ErrNoResponders) { + err = ErrJetStreamNotEnabled + } + return nil, err + } + + var info consumerResponse + if err := json.Unmarshal(resp.Data, &info); err != nil { + return nil, err + } + if info.Error != nil { + if errors.Is(info.Error, ErrConsumerNotFound) { + return nil, ErrConsumerNotFound + } + if errors.Is(info.Error, ErrStreamNotFound) { + return nil, ErrStreamNotFound + } + return nil, info.Error + } + if info.Error == nil && info.ConsumerInfo == nil { + return nil, ErrConsumerNotFound + } + return info.ConsumerInfo, nil +} + +// a RequestWithContext with tracing via TraceCB +func (js *js) apiRequestWithContext(ctx context.Context, subj string, data []byte) (*Msg, error) { + if js.opts.shouldTrace { + ctrace := js.opts.ctrace + if ctrace.RequestSent != nil { + ctrace.RequestSent(subj, data) + } + } + resp, err := js.nc.RequestWithContext(ctx, subj, data) + if err != nil { + return nil, err + } + if js.opts.shouldTrace { + ctrace := js.opts.ctrace + if ctrace.ResponseReceived != nil { + ctrace.ResponseReceived(subj, resp.Data, resp.Header) + } + } + + return resp, nil +} + +func (m *Msg) checkReply() error { + if m == nil || m.Sub == nil { + return ErrMsgNotBound + } + if m.Reply == _EMPTY_ { + return ErrMsgNoReply + } + return nil +} + +// ackReply handles all acks. Will do the right thing for pull and sync mode. +// It ensures that an ack is only sent a single time, regardless of +// how many times it is being called to avoid duplicated acks. +func (m *Msg) ackReply(ackType []byte, sync bool, opts ...AckOpt) error { + var o ackOpts + for _, opt := range opts { + if err := opt.configureAck(&o); err != nil { + return err + } + } + + if err := m.checkReply(); err != nil { + return err + } + + var ackNone bool + var js *js + + sub := m.Sub + sub.mu.Lock() + nc := sub.conn + if jsi := sub.jsi; jsi != nil { + js = jsi.js + ackNone = jsi.ackNone + } + sub.mu.Unlock() + + // Skip if already acked. + if atomic.LoadUint32(&m.ackd) == 1 { + return ErrMsgAlreadyAckd + } + if ackNone { + return ErrCantAckIfConsumerAckNone + } + + usesCtx := o.ctx != nil + usesWait := o.ttl > 0 + + // Only allow either AckWait or Context option to set the timeout. + if usesWait && usesCtx { + return ErrContextAndTimeout + } + + sync = sync || usesCtx || usesWait + ctx := o.ctx + wait := defaultRequestWait + if usesWait { + wait = o.ttl + } else if js != nil { + wait = js.opts.wait + } + + var body []byte + var err error + // This will be > 0 only when called from NakWithDelay() + if o.nakDelay > 0 { + body = []byte(fmt.Sprintf("%s {\"delay\": %d}", ackType, o.nakDelay.Nanoseconds())) + } else { + body = ackType + } + + if sync { + if usesCtx { + _, err = nc.RequestWithContext(ctx, m.Reply, body) + } else { + _, err = nc.Request(m.Reply, body, wait) + } + } else { + err = nc.Publish(m.Reply, body) + } + + // Mark that the message has been acked unless it is ackProgress + // which can be sent many times. + if err == nil && !bytes.Equal(ackType, ackProgress) { + atomic.StoreUint32(&m.ackd, 1) + } + + return err +} + +// Ack acknowledges a message. This tells the server that the message was +// successfully processed and it can move on to the next message. +func (m *Msg) Ack(opts ...AckOpt) error { + return m.ackReply(ackAck, false, opts...) +} + +// AckSync is the synchronous version of Ack. This indicates successful message +// processing. +func (m *Msg) AckSync(opts ...AckOpt) error { + return m.ackReply(ackAck, true, opts...) +} + +// Nak negatively acknowledges a message. This tells the server to redeliver +// the message. You can configure the number of redeliveries by passing +// nats.MaxDeliver when you Subscribe. The default is infinite redeliveries. +func (m *Msg) Nak(opts ...AckOpt) error { + return m.ackReply(ackNak, false, opts...) +} + +// Nak negatively acknowledges a message. This tells the server to redeliver +// the message after the give `delay` duration. You can configure the number +// of redeliveries by passing nats.MaxDeliver when you Subscribe. +// The default is infinite redeliveries. +func (m *Msg) NakWithDelay(delay time.Duration, opts ...AckOpt) error { + if delay > 0 { + opts = append(opts, nakDelay(delay)) + } + return m.ackReply(ackNak, false, opts...) +} + +// Term tells the server to not redeliver this message, regardless of the value +// of nats.MaxDeliver. +func (m *Msg) Term(opts ...AckOpt) error { + return m.ackReply(ackTerm, false, opts...) +} + +// InProgress tells the server that this message is being worked on. It resets +// the redelivery timer on the server. +func (m *Msg) InProgress(opts ...AckOpt) error { + return m.ackReply(ackProgress, false, opts...) +} + +// MsgMetadata is the JetStream metadata associated with received messages. +type MsgMetadata struct { + Sequence SequencePair + NumDelivered uint64 + NumPending uint64 + Timestamp time.Time + Stream string + Consumer string + Domain string +} + +// Metadata retrieves the metadata from a JetStream message. This method will +// return an error for non-JetStream Msgs. +func (m *Msg) Metadata() (*MsgMetadata, error) { + if err := m.checkReply(); err != nil { + return nil, err + } + + tokens, err := parser.GetMetadataFields(m.Reply) + if err != nil { + return nil, err + } + + meta := &MsgMetadata{ + Domain: tokens[parser.AckDomainTokenPos], + NumDelivered: parser.ParseNum(tokens[parser.AckNumDeliveredTokenPos]), + NumPending: parser.ParseNum(tokens[parser.AckNumPendingTokenPos]), + Timestamp: time.Unix(0, int64(parser.ParseNum(tokens[parser.AckTimestampSeqTokenPos]))), + Stream: tokens[parser.AckStreamTokenPos], + Consumer: tokens[parser.AckConsumerTokenPos], + } + meta.Sequence.Stream = parser.ParseNum(tokens[parser.AckStreamSeqTokenPos]) + meta.Sequence.Consumer = parser.ParseNum(tokens[parser.AckConsumerSeqTokenPos]) + return meta, nil +} + +// AckPolicy determines how the consumer should acknowledge delivered messages. +type AckPolicy int + +const ( + // AckNonePolicy requires no acks for delivered messages. + AckNonePolicy AckPolicy = iota + + // AckAllPolicy when acking a sequence number, this implicitly acks all + // sequences below this one as well. + AckAllPolicy + + // AckExplicitPolicy requires ack or nack for all messages. + AckExplicitPolicy + + // For configuration mismatch check + ackPolicyNotSet = 99 +) + +func jsonString(s string) string { + return "\"" + s + "\"" +} + +func (p *AckPolicy) UnmarshalJSON(data []byte) error { + switch string(data) { + case jsonString("none"): + *p = AckNonePolicy + case jsonString("all"): + *p = AckAllPolicy + case jsonString("explicit"): + *p = AckExplicitPolicy + default: + return fmt.Errorf("nats: can not unmarshal %q", data) + } + + return nil +} + +func (p AckPolicy) MarshalJSON() ([]byte, error) { + switch p { + case AckNonePolicy: + return json.Marshal("none") + case AckAllPolicy: + return json.Marshal("all") + case AckExplicitPolicy: + return json.Marshal("explicit") + default: + return nil, fmt.Errorf("nats: unknown acknowledgement policy %v", p) + } +} + +func (p AckPolicy) String() string { + switch p { + case AckNonePolicy: + return "AckNone" + case AckAllPolicy: + return "AckAll" + case AckExplicitPolicy: + return "AckExplicit" + case ackPolicyNotSet: + return "Not Initialized" + default: + return "Unknown AckPolicy" + } +} + +// ReplayPolicy determines how the consumer should replay messages it already has queued in the stream. +type ReplayPolicy int + +const ( + // ReplayInstantPolicy will replay messages as fast as possible. + ReplayInstantPolicy ReplayPolicy = iota + + // ReplayOriginalPolicy will maintain the same timing as the messages were received. + ReplayOriginalPolicy + + // For configuration mismatch check + replayPolicyNotSet = 99 +) + +func (p *ReplayPolicy) UnmarshalJSON(data []byte) error { + switch string(data) { + case jsonString("instant"): + *p = ReplayInstantPolicy + case jsonString("original"): + *p = ReplayOriginalPolicy + default: + return fmt.Errorf("nats: can not unmarshal %q", data) + } + + return nil +} + +func (p ReplayPolicy) MarshalJSON() ([]byte, error) { + switch p { + case ReplayOriginalPolicy: + return json.Marshal("original") + case ReplayInstantPolicy: + return json.Marshal("instant") + default: + return nil, fmt.Errorf("nats: unknown replay policy %v", p) + } +} + +var ( + ackAck = []byte("+ACK") + ackNak = []byte("-NAK") + ackProgress = []byte("+WPI") + ackTerm = []byte("+TERM") +) + +// DeliverPolicy determines how the consumer should select the first message to deliver. +type DeliverPolicy int + +const ( + // DeliverAllPolicy starts delivering messages from the very beginning of a + // stream. This is the default. + DeliverAllPolicy DeliverPolicy = iota + + // DeliverLastPolicy will start the consumer with the last sequence + // received. + DeliverLastPolicy + + // DeliverNewPolicy will only deliver new messages that are sent after the + // consumer is created. + DeliverNewPolicy + + // DeliverByStartSequencePolicy will deliver messages starting from a given + // sequence. + DeliverByStartSequencePolicy + + // DeliverByStartTimePolicy will deliver messages starting from a given + // time. + DeliverByStartTimePolicy + + // DeliverLastPerSubjectPolicy will start the consumer with the last message + // for all subjects received. + DeliverLastPerSubjectPolicy + + // For configuration mismatch check + deliverPolicyNotSet = 99 +) + +func (p *DeliverPolicy) UnmarshalJSON(data []byte) error { + switch string(data) { + case jsonString("all"), jsonString("undefined"): + *p = DeliverAllPolicy + case jsonString("last"): + *p = DeliverLastPolicy + case jsonString("new"): + *p = DeliverNewPolicy + case jsonString("by_start_sequence"): + *p = DeliverByStartSequencePolicy + case jsonString("by_start_time"): + *p = DeliverByStartTimePolicy + case jsonString("last_per_subject"): + *p = DeliverLastPerSubjectPolicy + } + + return nil +} + +func (p DeliverPolicy) MarshalJSON() ([]byte, error) { + switch p { + case DeliverAllPolicy: + return json.Marshal("all") + case DeliverLastPolicy: + return json.Marshal("last") + case DeliverNewPolicy: + return json.Marshal("new") + case DeliverByStartSequencePolicy: + return json.Marshal("by_start_sequence") + case DeliverByStartTimePolicy: + return json.Marshal("by_start_time") + case DeliverLastPerSubjectPolicy: + return json.Marshal("last_per_subject") + default: + return nil, fmt.Errorf("nats: unknown deliver policy %v", p) + } +} + +// RetentionPolicy determines how messages in a set are retained. +type RetentionPolicy int + +const ( + // LimitsPolicy (default) means that messages are retained until any given limit is reached. + // This could be one of MaxMsgs, MaxBytes, or MaxAge. + LimitsPolicy RetentionPolicy = iota + // InterestPolicy specifies that when all known observables have acknowledged a message it can be removed. + InterestPolicy + // WorkQueuePolicy specifies that when the first worker or subscriber acknowledges the message it can be removed. + WorkQueuePolicy +) + +// DiscardPolicy determines how to proceed when limits of messages or bytes are +// reached. +type DiscardPolicy int + +const ( + // DiscardOld will remove older messages to return to the limits. This is + // the default. + DiscardOld DiscardPolicy = iota + //DiscardNew will fail to store new messages. + DiscardNew +) + +const ( + limitsPolicyString = "limits" + interestPolicyString = "interest" + workQueuePolicyString = "workqueue" +) + +func (rp RetentionPolicy) String() string { + switch rp { + case LimitsPolicy: + return "Limits" + case InterestPolicy: + return "Interest" + case WorkQueuePolicy: + return "WorkQueue" + default: + return "Unknown Retention Policy" + } +} + +func (rp RetentionPolicy) MarshalJSON() ([]byte, error) { + switch rp { + case LimitsPolicy: + return json.Marshal(limitsPolicyString) + case InterestPolicy: + return json.Marshal(interestPolicyString) + case WorkQueuePolicy: + return json.Marshal(workQueuePolicyString) + default: + return nil, fmt.Errorf("nats: can not marshal %v", rp) + } +} + +func (rp *RetentionPolicy) UnmarshalJSON(data []byte) error { + switch string(data) { + case jsonString(limitsPolicyString): + *rp = LimitsPolicy + case jsonString(interestPolicyString): + *rp = InterestPolicy + case jsonString(workQueuePolicyString): + *rp = WorkQueuePolicy + default: + return fmt.Errorf("nats: can not unmarshal %q", data) + } + return nil +} + +func (dp DiscardPolicy) String() string { + switch dp { + case DiscardOld: + return "DiscardOld" + case DiscardNew: + return "DiscardNew" + default: + return "Unknown Discard Policy" + } +} + +func (dp DiscardPolicy) MarshalJSON() ([]byte, error) { + switch dp { + case DiscardOld: + return json.Marshal("old") + case DiscardNew: + return json.Marshal("new") + default: + return nil, fmt.Errorf("nats: can not marshal %v", dp) + } +} + +func (dp *DiscardPolicy) UnmarshalJSON(data []byte) error { + switch strings.ToLower(string(data)) { + case jsonString("old"): + *dp = DiscardOld + case jsonString("new"): + *dp = DiscardNew + default: + return fmt.Errorf("nats: can not unmarshal %q", data) + } + return nil +} + +// StorageType determines how messages are stored for retention. +type StorageType int + +const ( + // FileStorage specifies on disk storage. It's the default. + FileStorage StorageType = iota + // MemoryStorage specifies in memory only. + MemoryStorage +) + +const ( + memoryStorageString = "memory" + fileStorageString = "file" +) + +func (st StorageType) String() string { + switch st { + case MemoryStorage: + return "Memory" + case FileStorage: + return "File" + default: + return "Unknown Storage Type" + } +} + +func (st StorageType) MarshalJSON() ([]byte, error) { + switch st { + case MemoryStorage: + return json.Marshal(memoryStorageString) + case FileStorage: + return json.Marshal(fileStorageString) + default: + return nil, fmt.Errorf("nats: can not marshal %v", st) + } +} + +func (st *StorageType) UnmarshalJSON(data []byte) error { + switch string(data) { + case jsonString(memoryStorageString): + *st = MemoryStorage + case jsonString(fileStorageString): + *st = FileStorage + default: + return fmt.Errorf("nats: can not unmarshal %q", data) + } + return nil +} + +type StoreCompression uint8 + +const ( + NoCompression StoreCompression = iota + S2Compression +) + +func (alg StoreCompression) String() string { + switch alg { + case NoCompression: + return "None" + case S2Compression: + return "S2" + default: + return "Unknown StoreCompression" + } +} + +func (alg StoreCompression) MarshalJSON() ([]byte, error) { + var str string + switch alg { + case S2Compression: + str = "s2" + case NoCompression: + str = "none" + default: + return nil, errors.New("unknown compression algorithm") + } + return json.Marshal(str) +} + +func (alg *StoreCompression) UnmarshalJSON(b []byte) error { + var str string + if err := json.Unmarshal(b, &str); err != nil { + return err + } + switch str { + case "s2": + *alg = S2Compression + case "none": + *alg = NoCompression + default: + return errors.New("unknown compression algorithm") + } + return nil +} + +// Length of our hash used for named consumers. +const nameHashLen = 8 + +// Computes a hash for the given `name`. +func getHash(name string) string { + sha := sha256.New() + sha.Write([]byte(name)) + b := sha.Sum(nil) + for i := 0; i < nameHashLen; i++ { + b[i] = rdigits[int(b[i]%base)] + } + return string(b[:nameHashLen]) +} diff --git a/vendor/github.com/nats-io/nats.go/jserrors.go b/vendor/github.com/nats-io/nats.go/jserrors.go new file mode 100644 index 0000000..af9e015 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/jserrors.go @@ -0,0 +1,268 @@ +// Copyright 2020-2025 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nats + +import ( + "errors" + "fmt" +) + +var ( + // API errors + + // ErrJetStreamNotEnabled is an error returned when JetStream is not enabled for an account. + // + // Note: This error will not be returned in clustered mode, even if each + // server in the cluster does not have JetStream enabled. In clustered mode, + // requests will time out instead. + ErrJetStreamNotEnabled JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeJetStreamNotEnabled, Description: "jetstream not enabled", Code: 503}} + + // ErrJetStreamNotEnabledForAccount is an error returned when JetStream is not enabled for an account. + ErrJetStreamNotEnabledForAccount JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeJetStreamNotEnabledForAccount, Description: "jetstream not enabled for account", Code: 503}} + + // ErrStreamNotFound is an error returned when stream with given name does not exist. + ErrStreamNotFound JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeStreamNotFound, Description: "stream not found", Code: 404}} + + // ErrStreamNameAlreadyInUse is returned when a stream with given name already exists and has a different configuration. + ErrStreamNameAlreadyInUse JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeStreamNameInUse, Description: "stream name already in use", Code: 400}} + + // ErrStreamSubjectTransformNotSupported is returned when the connected nats-server version does not support setting + // the stream subject transform. If this error is returned when executing AddStream(), the stream with invalid + // configuration was already created in the server. + ErrStreamSubjectTransformNotSupported JetStreamError = &jsError{message: "stream subject transformation not supported by nats-server"} + + // ErrStreamSourceSubjectTransformNotSupported is returned when the connected nats-server version does not support setting + // the stream source subject transform. If this error is returned when executing AddStream(), the stream with invalid + // configuration was already created in the server. + ErrStreamSourceSubjectTransformNotSupported JetStreamError = &jsError{message: "stream subject transformation not supported by nats-server"} + + // ErrStreamSourceNotSupported is returned when the connected nats-server version does not support setting + // the stream sources. If this error is returned when executing AddStream(), the stream with invalid + // configuration was already created in the server. + ErrStreamSourceNotSupported JetStreamError = &jsError{message: "stream sourcing is not supported by nats-server"} + + // ErrStreamSourceMultipleSubjectTransformsNotSupported is returned when the connected nats-server version does not support setting + // the stream sources. If this error is returned when executing AddStream(), the stream with invalid + // configuration was already created in the server. + ErrStreamSourceMultipleSubjectTransformsNotSupported JetStreamError = &jsError{message: "stream sourcing with multiple subject transforms not supported by nats-server"} + + // ErrConsumerNotFound is an error returned when consumer with given name does not exist. + ErrConsumerNotFound JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeConsumerNotFound, Description: "consumer not found", Code: 404}} + + // ErrConsumerCreationResponseEmpty is an error returned when the response from the server + // when creating a consumer is empty. This means that the state of the consumer is unknown and + // the consumer may not have been created successfully. + ErrConsumerCreationResponseEmpty JetStreamError = &jsError{message: "consumer creation response is empty"} + + // ErrMsgNotFound is returned when message with provided sequence number does npt exist. + ErrMsgNotFound JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeMessageNotFound, Description: "message not found", Code: 404}} + + // ErrBadRequest is returned when invalid request is sent to JetStream API. + ErrBadRequest JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeBadRequest, Description: "bad request", Code: 400}} + + // ErrDuplicateFilterSubjects is returned when both FilterSubject and FilterSubjects are specified when creating consumer. + ErrDuplicateFilterSubjects JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeDuplicateFilterSubjects, Description: "consumer cannot have both FilterSubject and FilterSubjects specified", Code: 500}} + + // ErrDuplicateFilterSubjects is returned when filter subjects overlap when creating consumer. + ErrOverlappingFilterSubjects JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeOverlappingFilterSubjects, Description: "consumer subject filters cannot overlap", Code: 500}} + + // ErrEmptyFilter is returned when a filter in FilterSubjects is empty. + ErrEmptyFilter JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeConsumerEmptyFilter, Description: "consumer filter in FilterSubjects cannot be empty", Code: 500}} + + // Client errors + + // ErrConsumerNameAlreadyInUse is an error returned when consumer with given name already exists. + ErrConsumerNameAlreadyInUse JetStreamError = &jsError{message: "consumer name already in use"} + + // ErrConsumerNotActive is an error returned when consumer is not active. + ErrConsumerNotActive JetStreamError = &jsError{message: "consumer not active"} + + // ErrInvalidJSAck is returned when JetStream ack from message publish is invalid. + ErrInvalidJSAck JetStreamError = &jsError{message: "invalid jetstream publish response"} + + // ErrStreamConfigRequired is returned when empty stream configuration is supplied to add/update stream. + ErrStreamConfigRequired JetStreamError = &jsError{message: "stream configuration is required"} + + // ErrStreamNameRequired is returned when the provided stream name is empty. + ErrStreamNameRequired JetStreamError = &jsError{message: "stream name is required"} + + // ErrConsumerNameRequired is returned when the provided consumer durable name is empty. + ErrConsumerNameRequired JetStreamError = &jsError{message: "consumer name is required"} + + // ErrConsumerMultipleFilterSubjectsNotSupported is returned when the connected nats-server version does not support setting + // multiple filter subjects with filter_subjects field. If this error is returned when executing AddConsumer(), the consumer with invalid + // configuration was already created in the server. + ErrConsumerMultipleFilterSubjectsNotSupported JetStreamError = &jsError{message: "multiple consumer filter subjects not supported by nats-server"} + + // ErrConsumerConfigRequired is returned when empty consumer consuguration is supplied to add/update consumer. + ErrConsumerConfigRequired JetStreamError = &jsError{message: "consumer configuration is required"} + + // ErrPullSubscribeToPushConsumer is returned when attempting to use PullSubscribe on push consumer. + ErrPullSubscribeToPushConsumer JetStreamError = &jsError{message: "cannot pull subscribe to push based consumer"} + + // ErrPullSubscribeRequired is returned when attempting to use subscribe methods not suitable for pull consumers for pull consumers. + ErrPullSubscribeRequired JetStreamError = &jsError{message: "must use pull subscribe to bind to pull based consumer"} + + // ErrMsgAlreadyAckd is returned when attempting to acknowledge message more than once. + ErrMsgAlreadyAckd JetStreamError = &jsError{message: "message was already acknowledged"} + + // ErrNoStreamResponse is returned when there is no response from stream (e.g. no responders error). + ErrNoStreamResponse JetStreamError = &jsError{message: "no response from stream"} + + // ErrNotJSMessage is returned when attempting to get metadata from non JetStream message . + ErrNotJSMessage JetStreamError = &jsError{message: "not a jetstream message"} + + // ErrInvalidStreamName is returned when the provided stream name is invalid (contains '.' or ' '). + ErrInvalidStreamName JetStreamError = &jsError{message: "invalid stream name"} + + // ErrInvalidConsumerName is returned when the provided consumer name is invalid (contains '.' or ' '). + ErrInvalidConsumerName JetStreamError = &jsError{message: "invalid consumer name"} + + // ErrInvalidFilterSubject is returned when the provided filter subject is invalid. + ErrInvalidFilterSubject JetStreamError = &jsError{message: "invalid filter subject"} + + // ErrNoMatchingStream is returned when stream lookup by subject is unsuccessful. + ErrNoMatchingStream JetStreamError = &jsError{message: "no stream matches subject"} + + // ErrSubjectMismatch is returned when the provided subject does not match consumer's filter subject. + ErrSubjectMismatch JetStreamError = &jsError{message: "subject does not match consumer"} + + // ErrContextAndTimeout is returned when attempting to use both context and timeout. + ErrContextAndTimeout JetStreamError = &jsError{message: "context and timeout can not both be set"} + + // ErrCantAckIfConsumerAckNone is returned when attempting to ack a message for consumer with AckNone policy set. + ErrCantAckIfConsumerAckNone JetStreamError = &jsError{message: "cannot acknowledge a message for a consumer with AckNone policy"} + + // ErrConsumerDeleted is returned when attempting to send pull request to a consumer which does not exist + ErrConsumerDeleted JetStreamError = &jsError{message: "consumer deleted"} + + // ErrConsumerLeadershipChanged is returned when pending requests are no longer valid after leadership has changed + ErrConsumerLeadershipChanged JetStreamError = &jsError{message: "Leadership Changed"} + + // ErrConsumerInfoOnOrderedReset is returned when attempting to fetch consumer info for an ordered consumer that is currently being recreated. + ErrConsumerInfoOnOrderedReset JetStreamError = &jsError{message: "cannot fetch consumer info; ordered consumer is being reset"} + + // ErrNoHeartbeat is returned when no heartbeat is received from server when sending requests with pull consumer. + ErrNoHeartbeat JetStreamError = &jsError{message: "no heartbeat received"} + + // ErrSubscriptionClosed is returned when attempting to send pull request to a closed subscription + ErrSubscriptionClosed JetStreamError = &jsError{message: "subscription closed"} + + // ErrJetStreamPublisherClosed is returned for each unfinished ack future when JetStream.Cleanup is called. + ErrJetStreamPublisherClosed JetStreamError = &jsError{message: "jetstream context closed"} + + // Deprecated: ErrInvalidDurableName is no longer returned and will be removed in future releases. + // Use ErrInvalidConsumerName instead. + ErrInvalidDurableName = errors.New("nats: invalid durable name") + + // ErrAsyncPublishTimeout is returned when waiting for ack on async publish + ErrAsyncPublishTimeout JetStreamError = &jsError{message: "timeout waiting for ack"} + + // ErrTooManyStalledMsgs is returned when too many outstanding async + // messages are waiting for ack. + ErrTooManyStalledMsgs JetStreamError = &jsError{message: "stalled with too many outstanding async published messages"} + + // ErrFetchDisconnected is returned when the connection to the server is lost + // while waiting for messages to be delivered on PullSubscribe. + ErrFetchDisconnected = &jsError{message: "disconnected during fetch"} +) + +// Error code represents JetStream error codes returned by the API +type ErrorCode uint16 + +const ( + JSErrCodeJetStreamNotEnabledForAccount ErrorCode = 10039 + JSErrCodeJetStreamNotEnabled ErrorCode = 10076 + JSErrCodeInsufficientResourcesErr ErrorCode = 10023 + JSErrCodeJetStreamNotAvailable ErrorCode = 10008 + + JSErrCodeStreamNotFound ErrorCode = 10059 + JSErrCodeStreamNameInUse ErrorCode = 10058 + + JSErrCodeConsumerNotFound ErrorCode = 10014 + JSErrCodeConsumerNameExists ErrorCode = 10013 + JSErrCodeConsumerAlreadyExists ErrorCode = 10105 + JSErrCodeDuplicateFilterSubjects ErrorCode = 10136 + JSErrCodeOverlappingFilterSubjects ErrorCode = 10138 + JSErrCodeConsumerEmptyFilter ErrorCode = 10139 + + JSErrCodeMessageNotFound ErrorCode = 10037 + + JSErrCodeBadRequest ErrorCode = 10003 + JSStreamInvalidConfig ErrorCode = 10052 + + JSErrCodeStreamWrongLastSequence ErrorCode = 10071 +) + +// APIError is included in all API responses if there was an error. +type APIError struct { + Code int `json:"code"` + ErrorCode ErrorCode `json:"err_code"` + Description string `json:"description,omitempty"` +} + +// Error prints the JetStream API error code and description +func (e *APIError) Error() string { + return fmt.Sprintf("nats: %s", e.Description) +} + +// APIError implements the JetStreamError interface. +func (e *APIError) APIError() *APIError { + return e +} + +// Is matches against an APIError. +func (e *APIError) Is(err error) bool { + if e == nil { + return false + } + // Extract internal APIError to match against. + var aerr *APIError + ok := errors.As(err, &aerr) + if !ok { + return ok + } + return e.ErrorCode == aerr.ErrorCode +} + +// JetStreamError is an error result that happens when using JetStream. +// In case of client-side error, `APIError()` returns nil +type JetStreamError interface { + APIError() *APIError + error +} + +type jsError struct { + apiErr *APIError + message string +} + +func (err *jsError) APIError() *APIError { + return err.apiErr +} + +func (err *jsError) Error() string { + if err.apiErr != nil && err.apiErr.Description != "" { + return err.apiErr.Error() + } + return fmt.Sprintf("nats: %s", err.message) +} + +func (err *jsError) Unwrap() error { + // Allow matching to embedded APIError in case there is one. + if err.apiErr == nil { + return nil + } + return err.apiErr +} diff --git a/vendor/github.com/nats-io/nats.go/jsm.go b/vendor/github.com/nats-io/nats.go/jsm.go new file mode 100644 index 0000000..eaa2f63 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/jsm.go @@ -0,0 +1,1796 @@ +// Copyright 2021-2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nats + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + "time" +) + +// JetStreamManager manages JetStream Streams and Consumers. +type JetStreamManager interface { + // AddStream creates a stream. + AddStream(cfg *StreamConfig, opts ...JSOpt) (*StreamInfo, error) + + // UpdateStream updates a stream. + UpdateStream(cfg *StreamConfig, opts ...JSOpt) (*StreamInfo, error) + + // DeleteStream deletes a stream. + DeleteStream(name string, opts ...JSOpt) error + + // StreamInfo retrieves information from a stream. + StreamInfo(stream string, opts ...JSOpt) (*StreamInfo, error) + + // PurgeStream purges a stream messages. + PurgeStream(name string, opts ...JSOpt) error + + // StreamsInfo can be used to retrieve a list of StreamInfo objects. + // Deprecated: Use Streams() instead. + StreamsInfo(opts ...JSOpt) <-chan *StreamInfo + + // Streams can be used to retrieve a list of StreamInfo objects. + Streams(opts ...JSOpt) <-chan *StreamInfo + + // StreamNames is used to retrieve a list of Stream names. + StreamNames(opts ...JSOpt) <-chan string + + // GetMsg retrieves a raw stream message stored in JetStream by sequence number. + // Use options nats.DirectGet() or nats.DirectGetNext() to trigger retrieval + // directly from a distributed group of servers (leader and replicas). + // The stream must have been created/updated with the AllowDirect boolean. + GetMsg(name string, seq uint64, opts ...JSOpt) (*RawStreamMsg, error) + + // GetLastMsg retrieves the last raw stream message stored in JetStream by subject. + // Use option nats.DirectGet() to trigger retrieval + // directly from a distributed group of servers (leader and replicas). + // The stream must have been created/updated with the AllowDirect boolean. + GetLastMsg(name, subject string, opts ...JSOpt) (*RawStreamMsg, error) + + // DeleteMsg deletes a message from a stream. The message is marked as erased, but its value is not overwritten. + DeleteMsg(name string, seq uint64, opts ...JSOpt) error + + // SecureDeleteMsg deletes a message from a stream. The deleted message is overwritten with random data + // As a result, this operation is slower than DeleteMsg() + SecureDeleteMsg(name string, seq uint64, opts ...JSOpt) error + + // AddConsumer adds a consumer to a stream. + // If the consumer already exists, and the configuration is the same, it + // will return the existing consumer. + // If the consumer already exists, and the configuration is different, it + // will return ErrConsumerNameAlreadyInUse. + AddConsumer(stream string, cfg *ConsumerConfig, opts ...JSOpt) (*ConsumerInfo, error) + + // UpdateConsumer updates an existing consumer. + UpdateConsumer(stream string, cfg *ConsumerConfig, opts ...JSOpt) (*ConsumerInfo, error) + + // DeleteConsumer deletes a consumer. + DeleteConsumer(stream, consumer string, opts ...JSOpt) error + + // ConsumerInfo retrieves information of a consumer from a stream. + ConsumerInfo(stream, name string, opts ...JSOpt) (*ConsumerInfo, error) + + // ConsumersInfo is used to retrieve a list of ConsumerInfo objects. + // Deprecated: Use Consumers() instead. + ConsumersInfo(stream string, opts ...JSOpt) <-chan *ConsumerInfo + + // Consumers is used to retrieve a list of ConsumerInfo objects. + Consumers(stream string, opts ...JSOpt) <-chan *ConsumerInfo + + // ConsumerNames is used to retrieve a list of Consumer names. + ConsumerNames(stream string, opts ...JSOpt) <-chan string + + // AccountInfo retrieves info about the JetStream usage from an account. + AccountInfo(opts ...JSOpt) (*AccountInfo, error) + + // StreamNameBySubject returns a stream matching given subject. + StreamNameBySubject(string, ...JSOpt) (string, error) +} + +// StreamConfig will determine the properties for a stream. +// There are sensible defaults for most. If no subjects are +// given the name will be used as the only subject. +type StreamConfig struct { + // Name is the name of the stream. It is required and must be unique + // across the JetStream account. + // + // Name Names cannot contain whitespace, ., *, >, path separators + // (forward or backwards slash), and non-printable characters. + Name string `json:"name"` + + // Description is an optional description of the stream. + Description string `json:"description,omitempty"` + + // Subjects is a list of subjects that the stream is listening on. + // Wildcards are supported. Subjects cannot be set if the stream is + // created as a mirror. + Subjects []string `json:"subjects,omitempty"` + + // Retention defines the message retention policy for the stream. + // Defaults to LimitsPolicy. + Retention RetentionPolicy `json:"retention"` + + // MaxConsumers specifies the maximum number of consumers allowed for + // the stream. + MaxConsumers int `json:"max_consumers"` + + // MaxMsgs is the maximum number of messages the stream will store. + // After reaching the limit, stream adheres to the discard policy. + // If not set, server default is -1 (unlimited). + MaxMsgs int64 `json:"max_msgs"` + + // MaxBytes is the maximum total size of messages the stream will store. + // After reaching the limit, stream adheres to the discard policy. + // If not set, server default is -1 (unlimited). + MaxBytes int64 `json:"max_bytes"` + + // Discard defines the policy for handling messages when the stream + // reaches its limits in terms of number of messages or total bytes. + Discard DiscardPolicy `json:"discard"` + + // DiscardNewPerSubject is a flag to enable discarding new messages per + // subject when limits are reached. Requires DiscardPolicy to be + // DiscardNew and the MaxMsgsPerSubject to be set. + DiscardNewPerSubject bool `json:"discard_new_per_subject,omitempty"` + + // MaxAge is the maximum age of messages that the stream will retain. + MaxAge time.Duration `json:"max_age"` + + // MaxMsgsPerSubject is the maximum number of messages per subject that + // the stream will retain. + MaxMsgsPerSubject int64 `json:"max_msgs_per_subject"` + + // MaxMsgSize is the maximum size of any single message in the stream. + MaxMsgSize int32 `json:"max_msg_size,omitempty"` + + // Storage specifies the type of storage backend used for the stream + // (file or memory). + Storage StorageType `json:"storage"` + + // Replicas is the number of stream replicas in clustered JetStream. + // Defaults to 1, maximum is 5. + Replicas int `json:"num_replicas"` + + // NoAck is a flag to disable acknowledging messages received by this + // stream. + // + // If set to true, publish methods from the JetStream client will not + // work as expected, since they rely on acknowledgements. Core NATS + // publish methods should be used instead. Note that this will make + // message delivery less reliable. + NoAck bool `json:"no_ack,omitempty"` + + // Duplicates is the window within which to track duplicate messages. + // If not set, server default is 2 minutes. + Duplicates time.Duration `json:"duplicate_window,omitempty"` + + // Placement is used to declare where the stream should be placed via + // tags and/or an explicit cluster name. + Placement *Placement `json:"placement,omitempty"` + + // Mirror defines the configuration for mirroring another stream. + Mirror *StreamSource `json:"mirror,omitempty"` + + // Sources is a list of other streams this stream sources messages from. + Sources []*StreamSource `json:"sources,omitempty"` + + // Sealed streams do not allow messages to be published or deleted via limits or API, + // sealed streams can not be unsealed via configuration update. Can only + // be set on already created streams via the Update API. + Sealed bool `json:"sealed,omitempty"` + + // DenyDelete restricts the ability to delete messages from a stream via + // the API. Defaults to false. + DenyDelete bool `json:"deny_delete,omitempty"` + + // DenyPurge restricts the ability to purge messages from a stream via + // the API. Defaults to false. + DenyPurge bool `json:"deny_purge,omitempty"` + + // AllowRollup allows the use of the Nats-Rollup header to replace all + // contents of a stream, or subject in a stream, with a single new + // message. + AllowRollup bool `json:"allow_rollup_hdrs,omitempty"` + + // Compression specifies the message storage compression algorithm. + // Defaults to NoCompression. + Compression StoreCompression `json:"compression"` + + // FirstSeq is the initial sequence number of the first message in the + // stream. + FirstSeq uint64 `json:"first_seq,omitempty"` + + // SubjectTransform allows applying a transformation to matching + // messages' subjects. + SubjectTransform *SubjectTransformConfig `json:"subject_transform,omitempty"` + + // RePublish allows immediate republishing a message to the configured + // subject after it's stored. + RePublish *RePublish `json:"republish,omitempty"` + + // AllowDirect enables direct access to individual messages using direct + // get API. Defaults to false. + AllowDirect bool `json:"allow_direct"` + + // MirrorDirect enables direct access to individual messages from the + // origin stream using direct get API. Defaults to false. + MirrorDirect bool `json:"mirror_direct"` + + // ConsumerLimits defines limits of certain values that consumers can + // set, defaults for those who don't set these settings + ConsumerLimits StreamConsumerLimits `json:"consumer_limits,omitempty"` + + // Metadata is a set of application-defined key-value pairs for + // associating metadata on the stream. This feature requires nats-server + // v2.10.0 or later. + Metadata map[string]string `json:"metadata,omitempty"` + + // Template identifies the template that manages the Stream. Deprecated: + // This feature is no longer supported. + Template string `json:"template_owner,omitempty"` + + // AllowMsgTTL allows header initiated per-message TTLs. + // This feature requires nats-server v2.11.0 or later. + AllowMsgTTL bool `json:"allow_msg_ttl"` + + // Enables and sets a duration for adding server markers for delete, purge and max age limits. + // This feature requires nats-server v2.11.0 or later. + SubjectDeleteMarkerTTL time.Duration `json:"subject_delete_marker_ttl,omitempty"` +} + +// SubjectTransformConfig is for applying a subject transform (to matching messages) before doing anything else when a new message is received. +type SubjectTransformConfig struct { + Source string `json:"src,omitempty"` + Destination string `json:"dest"` +} + +// RePublish is for republishing messages once committed to a stream. The original +// subject cis remapped from the subject pattern to the destination pattern. +type RePublish struct { + Source string `json:"src,omitempty"` + Destination string `json:"dest"` + HeadersOnly bool `json:"headers_only,omitempty"` +} + +// Placement is used to guide placement of streams in clustered JetStream. +type Placement struct { + Cluster string `json:"cluster"` + Tags []string `json:"tags,omitempty"` +} + +// StreamSource dictates how streams can source from other streams. +type StreamSource struct { + Name string `json:"name"` + OptStartSeq uint64 `json:"opt_start_seq,omitempty"` + OptStartTime *time.Time `json:"opt_start_time,omitempty"` + FilterSubject string `json:"filter_subject,omitempty"` + SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"` + External *ExternalStream `json:"external,omitempty"` + Domain string `json:"-"` +} + +// ExternalStream allows you to qualify access to a stream source in another +// account. +type ExternalStream struct { + APIPrefix string `json:"api"` + DeliverPrefix string `json:"deliver,omitempty"` +} + +// StreamConsumerLimits are the limits for a consumer on a stream. +// These can be overridden on a per consumer basis. +type StreamConsumerLimits struct { + InactiveThreshold time.Duration `json:"inactive_threshold,omitempty"` + MaxAckPending int `json:"max_ack_pending,omitempty"` +} + +// Helper for copying when we do not want to change user's version. +func (ss *StreamSource) copy() *StreamSource { + nss := *ss + // Check pointers + if ss.OptStartTime != nil { + t := *ss.OptStartTime + nss.OptStartTime = &t + } + if ss.External != nil { + ext := *ss.External + nss.External = &ext + } + return &nss +} + +// If we have a Domain, convert to the appropriate ext.APIPrefix. +// This will change the stream source, so should be a copy passed in. +func (ss *StreamSource) convertDomain() error { + if ss.Domain == _EMPTY_ { + return nil + } + if ss.External != nil { + // These should be mutually exclusive. + // TODO(dlc) - Make generic? + return errors.New("nats: domain and external are both set") + } + ss.External = &ExternalStream{APIPrefix: fmt.Sprintf(jsExtDomainT, ss.Domain)} + return nil +} + +// apiResponse is a standard response from the JetStream JSON API +type apiResponse struct { + Type string `json:"type"` + Error *APIError `json:"error,omitempty"` +} + +// apiPaged includes variables used to create paged responses from the JSON API +type apiPaged struct { + Total int `json:"total"` + Offset int `json:"offset"` + Limit int `json:"limit"` +} + +// apiPagedRequest includes parameters allowing specific pages to be requested +// from APIs responding with apiPaged. +type apiPagedRequest struct { + Offset int `json:"offset,omitempty"` +} + +// AccountInfo contains info about the JetStream usage from the current account. +type AccountInfo struct { + Tier + Domain string `json:"domain"` + API APIStats `json:"api"` + Tiers map[string]Tier `json:"tiers"` +} + +type Tier struct { + Memory uint64 `json:"memory"` + Store uint64 `json:"storage"` + ReservedMemory uint64 `json:"reserved_memory"` + ReservedStore uint64 `json:"reserved_storage"` + Streams int `json:"streams"` + Consumers int `json:"consumers"` + Limits AccountLimits `json:"limits"` +} + +// APIStats reports on API calls to JetStream for this account. +type APIStats struct { + Total uint64 `json:"total"` + Errors uint64 `json:"errors"` +} + +// AccountLimits includes the JetStream limits of the current account. +type AccountLimits struct { + MaxMemory int64 `json:"max_memory"` + MaxStore int64 `json:"max_storage"` + MaxStreams int `json:"max_streams"` + MaxConsumers int `json:"max_consumers"` + MaxAckPending int `json:"max_ack_pending"` + MemoryMaxStreamBytes int64 `json:"memory_max_stream_bytes"` + StoreMaxStreamBytes int64 `json:"storage_max_stream_bytes"` + MaxBytesRequired bool `json:"max_bytes_required"` +} + +type accountInfoResponse struct { + apiResponse + AccountInfo +} + +// AccountInfo fetches account information from the server, containing details +// about the account associated with this JetStream connection. If account is +// not enabled for JetStream, ErrJetStreamNotEnabledForAccount is returned. +// +// If the server does not have JetStream enabled, ErrJetStreamNotEnabled is +// returned (for a single server setup). For clustered topologies, AccountInfo +// will time out. +func (js *js) AccountInfo(opts ...JSOpt) (*AccountInfo, error) { + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + + resp, err := js.apiRequestWithContext(o.ctx, js.apiSubj(apiAccountInfo), nil) + if err != nil { + // todo maybe nats server should never have no responder on this subject and always respond if they know there is no js to be had + if errors.Is(err, ErrNoResponders) { + err = ErrJetStreamNotEnabled + } + return nil, err + } + var info accountInfoResponse + if err := json.Unmarshal(resp.Data, &info); err != nil { + return nil, err + } + if info.Error != nil { + // Internally checks based on error code instead of description match. + if errors.Is(info.Error, ErrJetStreamNotEnabledForAccount) { + return nil, ErrJetStreamNotEnabledForAccount + } + return nil, info.Error + } + + return &info.AccountInfo, nil +} + +type createConsumerRequest struct { + Stream string `json:"stream_name"` + Config *ConsumerConfig `json:"config"` +} + +type consumerResponse struct { + apiResponse + *ConsumerInfo +} + +// AddConsumer adds a consumer to a stream. +// If the consumer already exists, and the configuration is the same, it +// will return the existing consumer. +// If the consumer already exists, and the configuration is different, it +// will return ErrConsumerNameAlreadyInUse. +func (js *js) AddConsumer(stream string, cfg *ConsumerConfig, opts ...JSOpt) (*ConsumerInfo, error) { + if cfg == nil { + cfg = &ConsumerConfig{} + } + consumerName := cfg.Name + if consumerName == _EMPTY_ { + consumerName = cfg.Durable + } + if consumerName != _EMPTY_ { + consInfo, err := js.ConsumerInfo(stream, consumerName, opts...) + if err != nil && !errors.Is(err, ErrConsumerNotFound) && !errors.Is(err, ErrStreamNotFound) { + return nil, err + } + + if consInfo != nil { + sameConfig := checkConfig(&consInfo.Config, cfg) + if sameConfig != nil { + return nil, fmt.Errorf("%w: creating consumer %q on stream %q", ErrConsumerNameAlreadyInUse, consumerName, stream) + } else { + return consInfo, nil + } + } + } + + return js.upsertConsumer(stream, consumerName, cfg, opts...) +} + +func (js *js) UpdateConsumer(stream string, cfg *ConsumerConfig, opts ...JSOpt) (*ConsumerInfo, error) { + if cfg == nil { + return nil, ErrConsumerConfigRequired + } + consumerName := cfg.Name + if consumerName == _EMPTY_ { + consumerName = cfg.Durable + } + if consumerName == _EMPTY_ { + return nil, ErrConsumerNameRequired + } + return js.upsertConsumer(stream, consumerName, cfg, opts...) +} + +func (js *js) upsertConsumer(stream, consumerName string, cfg *ConsumerConfig, opts ...JSOpt) (*ConsumerInfo, error) { + if err := checkStreamName(stream); err != nil { + return nil, err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + + req, err := json.Marshal(&createConsumerRequest{Stream: stream, Config: cfg}) + if err != nil { + return nil, err + } + + var ccSubj string + if consumerName == _EMPTY_ { + // if consumer name is empty (neither Durable nor Name is set), use the legacy ephemeral endpoint + ccSubj = fmt.Sprintf(apiLegacyConsumerCreateT, stream) + } else if err := checkConsumerName(consumerName); err != nil { + return nil, err + } else if js.nc.serverMinVersion(2, 9, 0) { + if cfg.Durable != "" && js.opts.featureFlags.useDurableConsumerCreate { + // if user set the useDurableConsumerCreate flag, use the legacy DURABLE.CREATE endpoint + ccSubj = fmt.Sprintf(apiDurableCreateT, stream, consumerName) + } else if cfg.FilterSubject == _EMPTY_ || cfg.FilterSubject == ">" { + // if filter subject is empty or ">", use the endpoint without filter subject + ccSubj = fmt.Sprintf(apiConsumerCreateT, stream, consumerName) + } else { + // safeguard against passing invalid filter subject in request subject + if cfg.FilterSubject[0] == '.' || cfg.FilterSubject[len(cfg.FilterSubject)-1] == '.' { + return nil, fmt.Errorf("%w: %q", ErrInvalidFilterSubject, cfg.FilterSubject) + } + // if filter subject is not empty, use the endpoint with filter subject + ccSubj = fmt.Sprintf(apiConsumerCreateWithFilterSubjectT, stream, consumerName, cfg.FilterSubject) + } + } else { + if cfg.Durable != "" { + // if Durable is set, use the DURABLE.CREATE endpoint + ccSubj = fmt.Sprintf(apiDurableCreateT, stream, consumerName) + } else { + // if Durable is not set, use the legacy ephemeral endpoint + ccSubj = fmt.Sprintf(apiLegacyConsumerCreateT, stream) + } + } + + resp, err := js.apiRequestWithContext(o.ctx, js.apiSubj(ccSubj), req) + if err != nil { + if errors.Is(err, ErrNoResponders) { + err = ErrJetStreamNotEnabled + } + return nil, err + } + var info consumerResponse + err = json.Unmarshal(resp.Data, &info) + if err != nil { + return nil, err + } + if info.Error != nil { + if errors.Is(info.Error, ErrStreamNotFound) { + return nil, ErrStreamNotFound + } + if errors.Is(info.Error, ErrConsumerNotFound) { + return nil, ErrConsumerNotFound + } + return nil, info.Error + } + + if info.Error == nil && info.ConsumerInfo == nil { + return nil, ErrConsumerCreationResponseEmpty + } + + // check whether multiple filter subjects (if used) are reflected in the returned ConsumerInfo + if len(cfg.FilterSubjects) != 0 && len(info.Config.FilterSubjects) == 0 { + return nil, ErrConsumerMultipleFilterSubjectsNotSupported + } + return info.ConsumerInfo, nil +} + +// consumerDeleteResponse is the response for a Consumer delete request. +type consumerDeleteResponse struct { + apiResponse + Success bool `json:"success,omitempty"` +} + +func checkStreamName(stream string) error { + if stream == _EMPTY_ { + return ErrStreamNameRequired + } + if strings.ContainsAny(stream, ". ") { + return ErrInvalidStreamName + } + return nil +} + +// Check that the consumer name is not empty and is valid (does not contain "." and " "). +// Additional consumer name validation is done in nats-server. +// Returns ErrConsumerNameRequired if consumer name is empty, ErrInvalidConsumerName is invalid, otherwise nil +func checkConsumerName(consumer string) error { + if consumer == _EMPTY_ { + return ErrConsumerNameRequired + } + if strings.ContainsAny(consumer, ". ") { + return ErrInvalidConsumerName + } + return nil +} + +// DeleteConsumer deletes a Consumer. +func (js *js) DeleteConsumer(stream, consumer string, opts ...JSOpt) error { + if err := checkStreamName(stream); err != nil { + return err + } + if err := checkConsumerName(consumer); err != nil { + return err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return err + } + if cancel != nil { + defer cancel() + } + + dcSubj := js.apiSubj(fmt.Sprintf(apiConsumerDeleteT, stream, consumer)) + r, err := js.apiRequestWithContext(o.ctx, dcSubj, nil) + if err != nil { + return err + } + var resp consumerDeleteResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return err + } + + if resp.Error != nil { + if errors.Is(resp.Error, ErrConsumerNotFound) { + return ErrConsumerNotFound + } + return resp.Error + } + return nil +} + +// ConsumerInfo returns information about a Consumer. +func (js *js) ConsumerInfo(stream, consumer string, opts ...JSOpt) (*ConsumerInfo, error) { + if err := checkStreamName(stream); err != nil { + return nil, err + } + if err := checkConsumerName(consumer); err != nil { + return nil, err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + return js.getConsumerInfoContext(o.ctx, stream, consumer) +} + +// consumerLister fetches pages of ConsumerInfo objects. This object is not +// safe to use for multiple threads. +type consumerLister struct { + stream string + js *js + + err error + offset int + page []*ConsumerInfo + pageInfo *apiPaged +} + +// consumersRequest is the type used for Consumers requests. +type consumersRequest struct { + apiPagedRequest +} + +// consumerListResponse is the response for a Consumers List request. +type consumerListResponse struct { + apiResponse + apiPaged + Consumers []*ConsumerInfo `json:"consumers"` +} + +// Next fetches the next ConsumerInfo page. +func (c *consumerLister) Next() bool { + if c.err != nil { + return false + } + if err := checkStreamName(c.stream); err != nil { + c.err = err + return false + } + if c.pageInfo != nil && c.offset >= c.pageInfo.Total { + return false + } + + req, err := json.Marshal(consumersRequest{ + apiPagedRequest: apiPagedRequest{Offset: c.offset}, + }) + if err != nil { + c.err = err + return false + } + + var cancel context.CancelFunc + ctx := c.js.opts.ctx + if ctx == nil { + ctx, cancel = context.WithTimeout(context.Background(), c.js.opts.wait) + defer cancel() + } + + clSubj := c.js.apiSubj(fmt.Sprintf(apiConsumerListT, c.stream)) + r, err := c.js.apiRequestWithContext(ctx, clSubj, req) + if err != nil { + c.err = err + return false + } + var resp consumerListResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + c.err = err + return false + } + if resp.Error != nil { + c.err = resp.Error + return false + } + + c.pageInfo = &resp.apiPaged + c.page = resp.Consumers + c.offset += len(c.page) + return true +} + +// Page returns the current ConsumerInfo page. +func (c *consumerLister) Page() []*ConsumerInfo { + return c.page +} + +// Err returns any errors found while fetching pages. +func (c *consumerLister) Err() error { + return c.err +} + +// Consumers is used to retrieve a list of ConsumerInfo objects. +func (jsc *js) Consumers(stream string, opts ...JSOpt) <-chan *ConsumerInfo { + o, cancel, err := getJSContextOpts(jsc.opts, opts...) + if err != nil { + return nil + } + + ch := make(chan *ConsumerInfo) + l := &consumerLister{js: &js{nc: jsc.nc, opts: o}, stream: stream} + go func() { + if cancel != nil { + defer cancel() + } + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + select { + case ch <- info: + case <-o.ctx.Done(): + return + } + } + } + }() + + return ch +} + +// ConsumersInfo is used to retrieve a list of ConsumerInfo objects. +// Deprecated: Use Consumers() instead. +func (jsc *js) ConsumersInfo(stream string, opts ...JSOpt) <-chan *ConsumerInfo { + return jsc.Consumers(stream, opts...) +} + +type consumerNamesLister struct { + stream string + js *js + + err error + offset int + page []string + pageInfo *apiPaged +} + +// consumerNamesListResponse is the response for a Consumers Names List request. +type consumerNamesListResponse struct { + apiResponse + apiPaged + Consumers []string `json:"consumers"` +} + +// Next fetches the next consumer names page. +func (c *consumerNamesLister) Next() bool { + if c.err != nil { + return false + } + if err := checkStreamName(c.stream); err != nil { + c.err = err + return false + } + if c.pageInfo != nil && c.offset >= c.pageInfo.Total { + return false + } + + var cancel context.CancelFunc + ctx := c.js.opts.ctx + if ctx == nil { + ctx, cancel = context.WithTimeout(context.Background(), c.js.opts.wait) + defer cancel() + } + + req, err := json.Marshal(consumersRequest{ + apiPagedRequest: apiPagedRequest{Offset: c.offset}, + }) + if err != nil { + c.err = err + return false + } + clSubj := c.js.apiSubj(fmt.Sprintf(apiConsumerNamesT, c.stream)) + r, err := c.js.apiRequestWithContext(ctx, clSubj, req) + if err != nil { + c.err = err + return false + } + var resp consumerNamesListResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + c.err = err + return false + } + if resp.Error != nil { + c.err = resp.Error + return false + } + + c.pageInfo = &resp.apiPaged + c.page = resp.Consumers + c.offset += len(c.page) + return true +} + +// Page returns the current ConsumerInfo page. +func (c *consumerNamesLister) Page() []string { + return c.page +} + +// Err returns any errors found while fetching pages. +func (c *consumerNamesLister) Err() error { + return c.err +} + +// ConsumerNames is used to retrieve a list of Consumer names. +func (jsc *js) ConsumerNames(stream string, opts ...JSOpt) <-chan string { + o, cancel, err := getJSContextOpts(jsc.opts, opts...) + if err != nil { + return nil + } + + ch := make(chan string) + l := &consumerNamesLister{stream: stream, js: &js{nc: jsc.nc, opts: o}} + go func() { + if cancel != nil { + defer cancel() + } + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + select { + case ch <- info: + case <-o.ctx.Done(): + return + } + } + } + }() + + return ch +} + +// streamCreateResponse stream creation. +type streamCreateResponse struct { + apiResponse + *StreamInfo +} + +func (js *js) AddStream(cfg *StreamConfig, opts ...JSOpt) (*StreamInfo, error) { + if cfg == nil { + return nil, ErrStreamConfigRequired + } + if err := checkStreamName(cfg.Name); err != nil { + return nil, err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + + // In case we need to change anything, copy so we do not change the caller's version. + ncfg := *cfg + + // If we have a mirror and an external domain, convert to ext.APIPrefix. + if cfg.Mirror != nil && cfg.Mirror.Domain != _EMPTY_ { + // Copy so we do not change the caller's version. + ncfg.Mirror = ncfg.Mirror.copy() + if err := ncfg.Mirror.convertDomain(); err != nil { + return nil, err + } + } + // Check sources for the same. + if len(ncfg.Sources) > 0 { + ncfg.Sources = append([]*StreamSource(nil), ncfg.Sources...) + for i, ss := range ncfg.Sources { + if ss.Domain != _EMPTY_ { + ncfg.Sources[i] = ss.copy() + if err := ncfg.Sources[i].convertDomain(); err != nil { + return nil, err + } + } + } + } + + req, err := json.Marshal(&ncfg) + if err != nil { + return nil, err + } + + csSubj := js.apiSubj(fmt.Sprintf(apiStreamCreateT, cfg.Name)) + r, err := js.apiRequestWithContext(o.ctx, csSubj, req) + if err != nil { + return nil, err + } + var resp streamCreateResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return nil, err + } + if resp.Error != nil { + if errors.Is(resp.Error, ErrStreamNameAlreadyInUse) { + return nil, ErrStreamNameAlreadyInUse + } + return nil, resp.Error + } + + // check that input subject transform (if used) is reflected in the returned ConsumerInfo + if cfg.SubjectTransform != nil && resp.StreamInfo.Config.SubjectTransform == nil { + return nil, ErrStreamSubjectTransformNotSupported + } + if len(cfg.Sources) != 0 { + if len(cfg.Sources) != len(resp.Config.Sources) { + return nil, ErrStreamSourceNotSupported + } + for i := range cfg.Sources { + if len(cfg.Sources[i].SubjectTransforms) != 0 && len(resp.Sources[i].SubjectTransforms) == 0 { + return nil, ErrStreamSourceMultipleSubjectTransformsNotSupported + } + } + } + + return resp.StreamInfo, nil +} + +type ( + // StreamInfoRequest contains additional option to return + StreamInfoRequest struct { + apiPagedRequest + // DeletedDetails when true includes information about deleted messages + DeletedDetails bool `json:"deleted_details,omitempty"` + // SubjectsFilter when set, returns information on the matched subjects + SubjectsFilter string `json:"subjects_filter,omitempty"` + } + streamInfoResponse = struct { + apiResponse + apiPaged + *StreamInfo + } +) + +func (js *js) StreamInfo(stream string, opts ...JSOpt) (*StreamInfo, error) { + if err := checkStreamName(stream); err != nil { + return nil, err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + + var i int + var subjectMessagesMap map[string]uint64 + var req []byte + var requestPayload bool + + var siOpts StreamInfoRequest + if o.streamInfoOpts != nil { + requestPayload = true + siOpts = *o.streamInfoOpts + } + + for { + if requestPayload { + siOpts.Offset = i + if req, err = json.Marshal(&siOpts); err != nil { + return nil, err + } + } + + siSubj := js.apiSubj(fmt.Sprintf(apiStreamInfoT, stream)) + + r, err := js.apiRequestWithContext(o.ctx, siSubj, req) + if err != nil { + return nil, err + } + + var resp streamInfoResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return nil, err + } + + if resp.Error != nil { + if errors.Is(resp.Error, ErrStreamNotFound) { + return nil, ErrStreamNotFound + } + return nil, resp.Error + } + + var total int + // for backwards compatibility + if resp.Total != 0 { + total = resp.Total + } else { + total = len(resp.State.Subjects) + } + + if requestPayload && len(resp.StreamInfo.State.Subjects) > 0 { + if subjectMessagesMap == nil { + subjectMessagesMap = make(map[string]uint64, total) + } + + for k, j := range resp.State.Subjects { + subjectMessagesMap[k] = j + i++ + } + } + + if i >= total { + if requestPayload { + resp.StreamInfo.State.Subjects = subjectMessagesMap + } + return resp.StreamInfo, nil + } + } +} + +// StreamInfo shows config and current state for this stream. +type StreamInfo struct { + Config StreamConfig `json:"config"` + Created time.Time `json:"created"` + State StreamState `json:"state"` + Cluster *ClusterInfo `json:"cluster,omitempty"` + Mirror *StreamSourceInfo `json:"mirror,omitempty"` + Sources []*StreamSourceInfo `json:"sources,omitempty"` + Alternates []*StreamAlternate `json:"alternates,omitempty"` +} + +// StreamAlternate is an alternate stream represented by a mirror. +type StreamAlternate struct { + Name string `json:"name"` + Domain string `json:"domain,omitempty"` + Cluster string `json:"cluster"` +} + +// StreamSourceInfo shows information about an upstream stream source. +type StreamSourceInfo struct { + Name string `json:"name"` + Lag uint64 `json:"lag"` + Active time.Duration `json:"active"` + External *ExternalStream `json:"external"` + Error *APIError `json:"error"` + FilterSubject string `json:"filter_subject,omitempty"` + SubjectTransforms []SubjectTransformConfig `json:"subject_transforms,omitempty"` +} + +// StreamState is information about the given stream. +type StreamState struct { + Msgs uint64 `json:"messages"` + Bytes uint64 `json:"bytes"` + FirstSeq uint64 `json:"first_seq"` + FirstTime time.Time `json:"first_ts"` + LastSeq uint64 `json:"last_seq"` + LastTime time.Time `json:"last_ts"` + Consumers int `json:"consumer_count"` + Deleted []uint64 `json:"deleted"` + NumDeleted int `json:"num_deleted"` + NumSubjects uint64 `json:"num_subjects"` + Subjects map[string]uint64 `json:"subjects"` +} + +// ClusterInfo shows information about the underlying set of servers +// that make up the stream or consumer. +type ClusterInfo struct { + Name string `json:"name,omitempty"` + RaftGroup string `json:"raft_group,omitempty"` + Leader string `json:"leader,omitempty"` + LeaderSince *time.Time `json:"leader_since,omitempty"` + SystemAcc bool `json:"system_account,omitempty"` + TrafficAcc string `json:"traffic_account,omitempty"` + Replicas []*PeerInfo `json:"replicas,omitempty"` +} + +// PeerInfo shows information about all the peers in the cluster that +// are supporting the stream or consumer. +type PeerInfo struct { + Name string `json:"name"` + Current bool `json:"current"` + Offline bool `json:"offline,omitempty"` + Active time.Duration `json:"active"` + Lag uint64 `json:"lag,omitempty"` +} + +// UpdateStream updates a Stream. +func (js *js) UpdateStream(cfg *StreamConfig, opts ...JSOpt) (*StreamInfo, error) { + if cfg == nil { + return nil, ErrStreamConfigRequired + } + if err := checkStreamName(cfg.Name); err != nil { + return nil, err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + + req, err := json.Marshal(cfg) + if err != nil { + return nil, err + } + + usSubj := js.apiSubj(fmt.Sprintf(apiStreamUpdateT, cfg.Name)) + r, err := js.apiRequestWithContext(o.ctx, usSubj, req) + if err != nil { + return nil, err + } + var resp streamInfoResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return nil, err + } + if resp.Error != nil { + if errors.Is(resp.Error, ErrStreamNotFound) { + return nil, ErrStreamNotFound + } + return nil, resp.Error + } + + // check that input subject transform (if used) is reflected in the returned StreamInfo + if cfg.SubjectTransform != nil && resp.StreamInfo.Config.SubjectTransform == nil { + return nil, ErrStreamSubjectTransformNotSupported + } + + if len(cfg.Sources) != 0 { + if len(cfg.Sources) != len(resp.Config.Sources) { + return nil, ErrStreamSourceNotSupported + } + for i := range cfg.Sources { + if len(cfg.Sources[i].SubjectTransforms) != 0 && len(resp.Sources[i].SubjectTransforms) == 0 { + return nil, ErrStreamSourceMultipleSubjectTransformsNotSupported + } + } + } + + return resp.StreamInfo, nil +} + +// streamDeleteResponse is the response for a Stream delete request. +type streamDeleteResponse struct { + apiResponse + Success bool `json:"success,omitempty"` +} + +// DeleteStream deletes a Stream. +func (js *js) DeleteStream(name string, opts ...JSOpt) error { + if err := checkStreamName(name); err != nil { + return err + } + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return err + } + if cancel != nil { + defer cancel() + } + + dsSubj := js.apiSubj(fmt.Sprintf(apiStreamDeleteT, name)) + r, err := js.apiRequestWithContext(o.ctx, dsSubj, nil) + if err != nil { + return err + } + var resp streamDeleteResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return err + } + + if resp.Error != nil { + if errors.Is(resp.Error, ErrStreamNotFound) { + return ErrStreamNotFound + } + return resp.Error + } + return nil +} + +type apiMsgGetRequest struct { + Seq uint64 `json:"seq,omitempty"` + LastFor string `json:"last_by_subj,omitempty"` + NextFor string `json:"next_by_subj,omitempty"` +} + +// RawStreamMsg is a raw message stored in JetStream. +type RawStreamMsg struct { + Subject string + Sequence uint64 + Header Header + Data []byte + Time time.Time +} + +// storedMsg is a raw message stored in JetStream. +type storedMsg struct { + Subject string `json:"subject"` + Sequence uint64 `json:"seq"` + Header []byte `json:"hdrs,omitempty"` + Data []byte `json:"data,omitempty"` + Time time.Time `json:"time"` +} + +// apiMsgGetResponse is the response for a Stream get request. +type apiMsgGetResponse struct { + apiResponse + Message *storedMsg `json:"message,omitempty"` +} + +// GetLastMsg retrieves the last raw stream message stored in JetStream by subject. +func (js *js) GetLastMsg(name, subject string, opts ...JSOpt) (*RawStreamMsg, error) { + return js.getMsg(name, &apiMsgGetRequest{LastFor: subject}, opts...) +} + +// GetMsg retrieves a raw stream message stored in JetStream by sequence number. +func (js *js) GetMsg(name string, seq uint64, opts ...JSOpt) (*RawStreamMsg, error) { + return js.getMsg(name, &apiMsgGetRequest{Seq: seq}, opts...) +} + +// Low level getMsg +func (js *js) getMsg(name string, mreq *apiMsgGetRequest, opts ...JSOpt) (*RawStreamMsg, error) { + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return nil, err + } + if cancel != nil { + defer cancel() + } + + if err := checkStreamName(name); err != nil { + return nil, err + } + + var apiSubj string + if o.directGet && mreq.LastFor != _EMPTY_ { + apiSubj = apiDirectMsgGetLastBySubjectT + dsSubj := js.apiSubj(fmt.Sprintf(apiSubj, name, mreq.LastFor)) + r, err := js.apiRequestWithContext(o.ctx, dsSubj, nil) + if err != nil { + return nil, err + } + return convertDirectGetMsgResponseToMsg(name, r) + } + + if o.directGet { + apiSubj = apiDirectMsgGetT + mreq.NextFor = o.directNextFor + } else { + apiSubj = apiMsgGetT + } + + req, err := json.Marshal(mreq) + if err != nil { + return nil, err + } + + dsSubj := js.apiSubj(fmt.Sprintf(apiSubj, name)) + r, err := js.apiRequestWithContext(o.ctx, dsSubj, req) + if err != nil { + return nil, err + } + + if o.directGet { + return convertDirectGetMsgResponseToMsg(name, r) + } + + var resp apiMsgGetResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return nil, err + } + if resp.Error != nil { + if errors.Is(resp.Error, ErrMsgNotFound) { + return nil, ErrMsgNotFound + } + if errors.Is(resp.Error, ErrStreamNotFound) { + return nil, ErrStreamNotFound + } + return nil, resp.Error + } + + msg := resp.Message + + var hdr Header + if len(msg.Header) > 0 { + hdr, err = DecodeHeadersMsg(msg.Header) + if err != nil { + return nil, err + } + } + + return &RawStreamMsg{ + Subject: msg.Subject, + Sequence: msg.Sequence, + Header: hdr, + Data: msg.Data, + Time: msg.Time, + }, nil +} + +func convertDirectGetMsgResponseToMsg(name string, r *Msg) (*RawStreamMsg, error) { + // Check for 404/408. We would get a no-payload message and a "Status" header + if len(r.Data) == 0 { + val := r.Header.Get(statusHdr) + if val != _EMPTY_ { + switch val { + case noMessagesSts: + return nil, ErrMsgNotFound + default: + desc := r.Header.Get(descrHdr) + if desc == _EMPTY_ { + desc = "unable to get message" + } + return nil, fmt.Errorf("nats: %s", desc) + } + } + } + // Check for headers that give us the required information to + // reconstruct the message. + if len(r.Header) == 0 { + return nil, errors.New("nats: response should have headers") + } + stream := r.Header.Get(JSStream) + if stream == _EMPTY_ { + return nil, errors.New("nats: missing stream header") + } + + // Mirrors can now answer direct gets, so removing check for name equality. + // TODO(dlc) - We could have server also have a header with origin and check that? + + seqStr := r.Header.Get(JSSequence) + if seqStr == _EMPTY_ { + return nil, errors.New("nats: missing sequence header") + } + seq, err := strconv.ParseUint(seqStr, 10, 64) + if err != nil { + return nil, fmt.Errorf("nats: invalid sequence header '%s': %v", seqStr, err) + } + timeStr := r.Header.Get(JSTimeStamp) + if timeStr == _EMPTY_ { + return nil, errors.New("nats: missing timestamp header") + } + // Temporary code: the server in main branch is sending with format + // "2006-01-02 15:04:05.999999999 +0000 UTC", but will be changed + // to use format RFC3339Nano. Because of server test deps/cycle, + // support both until the server PR lands. + tm, err := time.Parse(time.RFC3339Nano, timeStr) + if err != nil { + tm, err = time.Parse("2006-01-02 15:04:05.999999999 +0000 UTC", timeStr) + if err != nil { + return nil, fmt.Errorf("nats: invalid timestamp header '%s': %v", timeStr, err) + } + } + subj := r.Header.Get(JSSubject) + if subj == _EMPTY_ { + return nil, errors.New("nats: missing subject header") + } + return &RawStreamMsg{ + Subject: subj, + Sequence: seq, + Header: r.Header, + Data: r.Data, + Time: tm, + }, nil +} + +type msgDeleteRequest struct { + Seq uint64 `json:"seq"` + NoErase bool `json:"no_erase,omitempty"` +} + +// msgDeleteResponse is the response for a Stream delete request. +type msgDeleteResponse struct { + apiResponse + Success bool `json:"success,omitempty"` +} + +// DeleteMsg deletes a message from a stream. +// The message is marked as erased, but not overwritten +func (js *js) DeleteMsg(name string, seq uint64, opts ...JSOpt) error { + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return err + } + if cancel != nil { + defer cancel() + } + + return js.deleteMsg(o.ctx, name, &msgDeleteRequest{Seq: seq, NoErase: true}) +} + +// SecureDeleteMsg deletes a message from a stream. The deleted message is overwritten with random data +// As a result, this operation is slower than DeleteMsg() +func (js *js) SecureDeleteMsg(name string, seq uint64, opts ...JSOpt) error { + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return err + } + if cancel != nil { + defer cancel() + } + + return js.deleteMsg(o.ctx, name, &msgDeleteRequest{Seq: seq}) +} + +func (js *js) deleteMsg(ctx context.Context, stream string, req *msgDeleteRequest) error { + if err := checkStreamName(stream); err != nil { + return err + } + reqJSON, err := json.Marshal(req) + if err != nil { + return err + } + + dsSubj := js.apiSubj(fmt.Sprintf(apiMsgDeleteT, stream)) + r, err := js.apiRequestWithContext(ctx, dsSubj, reqJSON) + if err != nil { + return err + } + var resp msgDeleteResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return err + } + if resp.Error != nil { + return resp.Error + } + return nil +} + +// StreamPurgeRequest is optional request information to the purge API. +type StreamPurgeRequest struct { + // Purge up to but not including sequence. + Sequence uint64 `json:"seq,omitempty"` + // Subject to match against messages for the purge command. + Subject string `json:"filter,omitempty"` + // Number of messages to keep. + Keep uint64 `json:"keep,omitempty"` +} + +type streamPurgeResponse struct { + apiResponse + Success bool `json:"success,omitempty"` + Purged uint64 `json:"purged"` +} + +// PurgeStream purges messages on a Stream. +func (js *js) PurgeStream(stream string, opts ...JSOpt) error { + if err := checkStreamName(stream); err != nil { + return err + } + var req *StreamPurgeRequest + var ok bool + for _, opt := range opts { + // For PurgeStream, only request body opt is relevant + if req, ok = opt.(*StreamPurgeRequest); ok { + break + } + } + return js.purgeStream(stream, req) +} + +func (js *js) purgeStream(stream string, req *StreamPurgeRequest, opts ...JSOpt) error { + o, cancel, err := getJSContextOpts(js.opts, opts...) + if err != nil { + return err + } + if cancel != nil { + defer cancel() + } + + var b []byte + if req != nil { + if b, err = json.Marshal(req); err != nil { + return err + } + } + + psSubj := js.apiSubj(fmt.Sprintf(apiStreamPurgeT, stream)) + r, err := js.apiRequestWithContext(o.ctx, psSubj, b) + if err != nil { + return err + } + var resp streamPurgeResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + return err + } + if resp.Error != nil { + if errors.Is(resp.Error, ErrBadRequest) { + return fmt.Errorf("%w: %s", ErrBadRequest, "invalid purge request body") + } + return resp.Error + } + return nil +} + +// streamLister fetches pages of StreamInfo objects. This object is not safe +// to use for multiple threads. +type streamLister struct { + js *js + page []*StreamInfo + err error + + offset int + pageInfo *apiPaged +} + +// streamListResponse list of detailed stream information. +// A nil request is valid and means all streams. +type streamListResponse struct { + apiResponse + apiPaged + Streams []*StreamInfo `json:"streams"` +} + +// streamNamesRequest is used for Stream Name requests. +type streamNamesRequest struct { + apiPagedRequest + // These are filters that can be applied to the list. + Subject string `json:"subject,omitempty"` +} + +// Next fetches the next StreamInfo page. +func (s *streamLister) Next() bool { + if s.err != nil { + return false + } + if s.pageInfo != nil && s.offset >= s.pageInfo.Total { + return false + } + + req, err := json.Marshal(streamNamesRequest{ + apiPagedRequest: apiPagedRequest{Offset: s.offset}, + Subject: s.js.opts.streamListSubject, + }) + if err != nil { + s.err = err + return false + } + + var cancel context.CancelFunc + ctx := s.js.opts.ctx + if ctx == nil { + ctx, cancel = context.WithTimeout(context.Background(), s.js.opts.wait) + defer cancel() + } + + slSubj := s.js.apiSubj(apiStreamListT) + r, err := s.js.apiRequestWithContext(ctx, slSubj, req) + if err != nil { + s.err = err + return false + } + var resp streamListResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + s.err = err + return false + } + if resp.Error != nil { + s.err = resp.Error + return false + } + + s.pageInfo = &resp.apiPaged + s.page = resp.Streams + s.offset += len(s.page) + return true +} + +// Page returns the current StreamInfo page. +func (s *streamLister) Page() []*StreamInfo { + return s.page +} + +// Err returns any errors found while fetching pages. +func (s *streamLister) Err() error { + return s.err +} + +// Streams can be used to retrieve a list of StreamInfo objects. +func (jsc *js) Streams(opts ...JSOpt) <-chan *StreamInfo { + o, cancel, err := getJSContextOpts(jsc.opts, opts...) + if err != nil { + return nil + } + + ch := make(chan *StreamInfo) + l := &streamLister{js: &js{nc: jsc.nc, opts: o}} + go func() { + if cancel != nil { + defer cancel() + } + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + select { + case ch <- info: + case <-o.ctx.Done(): + return + } + } + } + }() + + return ch +} + +// StreamsInfo can be used to retrieve a list of StreamInfo objects. +// Deprecated: Use Streams() instead. +func (jsc *js) StreamsInfo(opts ...JSOpt) <-chan *StreamInfo { + return jsc.Streams(opts...) +} + +type streamNamesLister struct { + js *js + + err error + offset int + page []string + pageInfo *apiPaged +} + +// Next fetches the next stream names page. +func (l *streamNamesLister) Next() bool { + if l.err != nil { + return false + } + if l.pageInfo != nil && l.offset >= l.pageInfo.Total { + return false + } + + var cancel context.CancelFunc + ctx := l.js.opts.ctx + if ctx == nil { + ctx, cancel = context.WithTimeout(context.Background(), l.js.opts.wait) + defer cancel() + } + + req, err := json.Marshal(streamNamesRequest{ + apiPagedRequest: apiPagedRequest{Offset: l.offset}, + Subject: l.js.opts.streamListSubject, + }) + if err != nil { + l.err = err + return false + } + r, err := l.js.apiRequestWithContext(ctx, l.js.apiSubj(apiStreams), req) + if err != nil { + l.err = err + return false + } + var resp streamNamesResponse + if err := json.Unmarshal(r.Data, &resp); err != nil { + l.err = err + return false + } + if resp.Error != nil { + l.err = resp.Error + return false + } + + l.pageInfo = &resp.apiPaged + l.page = resp.Streams + l.offset += len(l.page) + return true +} + +// Page returns the current ConsumerInfo page. +func (l *streamNamesLister) Page() []string { + return l.page +} + +// Err returns any errors found while fetching pages. +func (l *streamNamesLister) Err() error { + return l.err +} + +// StreamNames is used to retrieve a list of Stream names. +func (jsc *js) StreamNames(opts ...JSOpt) <-chan string { + o, cancel, err := getJSContextOpts(jsc.opts, opts...) + if err != nil { + return nil + } + + ch := make(chan string) + l := &streamNamesLister{js: &js{nc: jsc.nc, opts: o}} + go func() { + if cancel != nil { + defer cancel() + } + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + select { + case ch <- info: + case <-o.ctx.Done(): + return + } + } + } + }() + + return ch +} + +// StreamNameBySubject returns a stream name that matches the subject. +func (jsc *js) StreamNameBySubject(subj string, opts ...JSOpt) (string, error) { + o, cancel, err := getJSContextOpts(jsc.opts, opts...) + if err != nil { + return "", err + } + if cancel != nil { + defer cancel() + } + + var slr streamNamesResponse + req := &streamRequest{subj} + j, err := json.Marshal(req) + if err != nil { + return _EMPTY_, err + } + + resp, err := jsc.apiRequestWithContext(o.ctx, jsc.apiSubj(apiStreams), j) + if err != nil { + if errors.Is(err, ErrNoResponders) { + err = ErrJetStreamNotEnabled + } + return _EMPTY_, err + } + if err := json.Unmarshal(resp.Data, &slr); err != nil { + return _EMPTY_, err + } + + if slr.Error != nil || len(slr.Streams) != 1 { + return _EMPTY_, ErrNoMatchingStream + } + return slr.Streams[0], nil +} + +func getJSContextOpts(defs *jsOpts, opts ...JSOpt) (*jsOpts, context.CancelFunc, error) { + var o jsOpts + for _, opt := range opts { + if err := opt.configureJSContext(&o); err != nil { + return nil, nil, err + } + } + + // Check for option collisions. Right now just timeout and context. + if o.ctx != nil && o.wait != 0 { + return nil, nil, ErrContextAndTimeout + } + if o.wait == 0 && o.ctx == nil { + o.wait = defs.wait + } + var cancel context.CancelFunc + if o.ctx == nil && o.wait > 0 { + o.ctx, cancel = context.WithTimeout(context.Background(), o.wait) + } + if o.pre == _EMPTY_ { + o.pre = defs.pre + } + if o.ctx != nil { + // if context does not have a deadline, use timeout from js context + if _, hasDeadline := o.ctx.Deadline(); !hasDeadline { + o.ctx, cancel = context.WithTimeout(o.ctx, defs.wait) + } + } + return &o, cancel, nil +} diff --git a/vendor/github.com/nats-io/nats.go/kv.go b/vendor/github.com/nats-io/nats.go/kv.go new file mode 100644 index 0000000..dda644e --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/kv.go @@ -0,0 +1,1287 @@ +// Copyright 2021-2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nats + +import ( + "context" + "errors" + "fmt" + "reflect" + "regexp" + "strconv" + "strings" + "sync" + "time" + + "github.com/nats-io/nats.go/internal/parser" +) + +// KeyValueManager is used to manage KeyValue stores. +type KeyValueManager interface { + // KeyValue will lookup and bind to an existing KeyValue store. + KeyValue(bucket string) (KeyValue, error) + // CreateKeyValue will create a KeyValue store with the following configuration. + CreateKeyValue(cfg *KeyValueConfig) (KeyValue, error) + // DeleteKeyValue will delete this KeyValue store (JetStream stream). + DeleteKeyValue(bucket string) error + // KeyValueStoreNames is used to retrieve a list of key value store names + KeyValueStoreNames() <-chan string + // KeyValueStores is used to retrieve a list of key value store statuses + KeyValueStores() <-chan KeyValueStatus +} + +// KeyValue contains methods to operate on a KeyValue store. +type KeyValue interface { + // Get returns the latest value for the key. + Get(key string) (entry KeyValueEntry, err error) + // GetRevision returns a specific revision value for the key. + GetRevision(key string, revision uint64) (entry KeyValueEntry, err error) + // Put will place the new value for the key into the store. + Put(key string, value []byte) (revision uint64, err error) + // PutString will place the string for the key into the store. + PutString(key string, value string) (revision uint64, err error) + // Create will add the key/value pair iff it does not exist. + Create(key string, value []byte) (revision uint64, err error) + // Update will update the value iff the latest revision matches. + // Update also resets the TTL associated with the key (if any). + Update(key string, value []byte, last uint64) (revision uint64, err error) + // Delete will place a delete marker and leave all revisions. + Delete(key string, opts ...DeleteOpt) error + // Purge will place a delete marker and remove all previous revisions. + Purge(key string, opts ...DeleteOpt) error + // Watch for any updates to keys that match the keys argument which could include wildcards. + // Watch will send a nil entry when it has received all initial values. + Watch(keys string, opts ...WatchOpt) (KeyWatcher, error) + // WatchAll will invoke the callback for all updates. + WatchAll(opts ...WatchOpt) (KeyWatcher, error) + // WatchFiltered will watch for any updates to keys that match the keys + // argument. It can be configured with the same options as Watch. + WatchFiltered(keys []string, opts ...WatchOpt) (KeyWatcher, error) + // Keys will return all keys. + // Deprecated: Use ListKeys instead to avoid memory issues. + Keys(opts ...WatchOpt) ([]string, error) + // ListKeys will return all keys in a channel. + ListKeys(opts ...WatchOpt) (KeyLister, error) + // History will return all historical values for the key. + History(key string, opts ...WatchOpt) ([]KeyValueEntry, error) + // Bucket returns the current bucket name. + Bucket() string + // PurgeDeletes will remove all current delete markers. + PurgeDeletes(opts ...PurgeOpt) error + // Status retrieves the status and configuration of a bucket + Status() (KeyValueStatus, error) +} + +// KeyValueStatus is run-time status about a Key-Value bucket +type KeyValueStatus interface { + // Bucket the name of the bucket + Bucket() string + + // Values is how many messages are in the bucket, including historical values + Values() uint64 + + // History returns the configured history kept per key + History() int64 + + // TTL is how long the bucket keeps values for + TTL() time.Duration + + // BackingStore indicates what technology is used for storage of the bucket + BackingStore() string + + // Bytes returns the size in bytes of the bucket + Bytes() uint64 + + // IsCompressed indicates if the data is compressed on disk + IsCompressed() bool +} + +// KeyWatcher is what is returned when doing a watch. +type KeyWatcher interface { + // Context returns watcher context optionally provided by nats.Context option. + Context() context.Context + // Updates returns a channel to read any updates to entries. + Updates() <-chan KeyValueEntry + // Stop will stop this watcher. + Stop() error + // Error returns a channel that will receive any error that occurs during + // watching. In particular, this will receive an error if the watcher times + // out while expecting more initial keys. The channel is closed when the + // watch operation completes or when Stop() is called. + Error() <-chan error +} + +// KeyLister is used to retrieve a list of key value store keys +type KeyLister interface { + Keys() <-chan string + Stop() error + // Error returns a channel that will receive any error that occurs during + // key listing. In particular, this will receive an error if the underlying + // watcher times out while expecting more keys. The channel is closed when + // the listing operation completes or when Stop() is called. + Error() <-chan error +} + +type WatchOpt interface { + configureWatcher(opts *watchOpts) error +} + +// For nats.Context() support. +func (ctx ContextOpt) configureWatcher(opts *watchOpts) error { + opts.ctx = ctx + return nil +} + +type watchOpts struct { + ctx context.Context + // Do not send delete markers to the update channel. + ignoreDeletes bool + // Include all history per subject, not just last one. + includeHistory bool + // Include only updates for keys. + updatesOnly bool + // retrieve only the meta data of the entry + metaOnly bool +} + +type watchOptFn func(opts *watchOpts) error + +func (opt watchOptFn) configureWatcher(opts *watchOpts) error { + return opt(opts) +} + +// IncludeHistory instructs the key watcher to include historical values as well. +func IncludeHistory() WatchOpt { + return watchOptFn(func(opts *watchOpts) error { + if opts.updatesOnly { + return errors.New("nats: include history can not be used with updates only") + } + opts.includeHistory = true + return nil + }) +} + +// UpdatesOnly instructs the key watcher to only include updates on values (without latest values when started). +func UpdatesOnly() WatchOpt { + return watchOptFn(func(opts *watchOpts) error { + if opts.includeHistory { + return errors.New("nats: updates only can not be used with include history") + } + opts.updatesOnly = true + return nil + }) +} + +// IgnoreDeletes will have the key watcher not pass any deleted keys. +func IgnoreDeletes() WatchOpt { + return watchOptFn(func(opts *watchOpts) error { + opts.ignoreDeletes = true + return nil + }) +} + +// MetaOnly instructs the key watcher to retrieve only the entry meta data, not the entry value +func MetaOnly() WatchOpt { + return watchOptFn(func(opts *watchOpts) error { + opts.metaOnly = true + return nil + }) +} + +type PurgeOpt interface { + configurePurge(opts *purgeOpts) error +} + +type purgeOpts struct { + dmthr time.Duration // Delete markers threshold + ctx context.Context +} + +// DeleteMarkersOlderThan indicates that delete or purge markers older than that +// will be deleted as part of PurgeDeletes() operation, otherwise, only the data +// will be removed but markers that are recent will be kept. +// Note that if no option is specified, the default is 30 minutes. You can set +// this option to a negative value to instruct to always remove the markers, +// regardless of their age. +type DeleteMarkersOlderThan time.Duration + +func (ttl DeleteMarkersOlderThan) configurePurge(opts *purgeOpts) error { + opts.dmthr = time.Duration(ttl) + return nil +} + +// For nats.Context() support. +func (ctx ContextOpt) configurePurge(opts *purgeOpts) error { + opts.ctx = ctx + return nil +} + +type DeleteOpt interface { + configureDelete(opts *deleteOpts) error +} + +type deleteOpts struct { + // Remove all previous revisions. + purge bool + + // Delete only if the latest revision matches. + revision uint64 +} + +type deleteOptFn func(opts *deleteOpts) error + +func (opt deleteOptFn) configureDelete(opts *deleteOpts) error { + return opt(opts) +} + +// LastRevision deletes if the latest revision matches. +func LastRevision(revision uint64) DeleteOpt { + return deleteOptFn(func(opts *deleteOpts) error { + opts.revision = revision + return nil + }) +} + +// purge removes all previous revisions. +func purge() DeleteOpt { + return deleteOptFn(func(opts *deleteOpts) error { + opts.purge = true + return nil + }) +} + +// KeyValueConfig is for configuring a KeyValue store. +type KeyValueConfig struct { + Bucket string `json:"bucket"` + Description string `json:"description,omitempty"` + MaxValueSize int32 `json:"max_value_size,omitempty"` + History uint8 `json:"history,omitempty"` + TTL time.Duration `json:"ttl,omitempty"` + MaxBytes int64 `json:"max_bytes,omitempty"` + Storage StorageType `json:"storage,omitempty"` + Replicas int `json:"num_replicas,omitempty"` + Placement *Placement `json:"placement,omitempty"` + RePublish *RePublish `json:"republish,omitempty"` + Mirror *StreamSource `json:"mirror,omitempty"` + Sources []*StreamSource `json:"sources,omitempty"` + + // Enable underlying stream compression. + // NOTE: Compression is supported for nats-server 2.10.0+ + Compression bool `json:"compression,omitempty"` +} + +// Used to watch all keys. +const ( + KeyValueMaxHistory = 64 + AllKeys = ">" + kvLatestRevision = 0 + kvop = "KV-Operation" + kvdel = "DEL" + kvpurge = "PURGE" +) + +type KeyValueOp uint8 + +const ( + KeyValuePut KeyValueOp = iota + KeyValueDelete + KeyValuePurge +) + +func (op KeyValueOp) String() string { + switch op { + case KeyValuePut: + return "KeyValuePutOp" + case KeyValueDelete: + return "KeyValueDeleteOp" + case KeyValuePurge: + return "KeyValuePurgeOp" + default: + return "Unknown Operation" + } +} + +// KeyValueEntry is a retrieved entry for Get or List or Watch. +type KeyValueEntry interface { + // Bucket is the bucket the data was loaded from. + Bucket() string + // Key is the key that was retrieved. + Key() string + // Value is the retrieved value. + Value() []byte + // Revision is a unique sequence for this value. + Revision() uint64 + // Created is the time the data was put in the bucket. + Created() time.Time + // Delta is distance from the latest value. + Delta() uint64 + // Operation returns Put or Delete or Purge. + Operation() KeyValueOp +} + +// Errors +var ( + ErrKeyValueConfigRequired = errors.New("nats: config required") + ErrInvalidBucketName = errors.New("nats: invalid bucket name") + ErrInvalidKey = errors.New("nats: invalid key") + ErrBucketNotFound = errors.New("nats: bucket not found") + ErrBadBucket = errors.New("nats: bucket not valid key-value store") + ErrKeyNotFound = errors.New("nats: key not found") + ErrKeyDeleted = errors.New("nats: key was deleted") + ErrHistoryToLarge = errors.New("nats: history limited to a max of 64") + ErrNoKeysFound = errors.New("nats: no keys found") + ErrKeyWatcherTimeout = errors.New("nats: key watcher timed out waiting for initial keys") +) + +var ( + ErrKeyExists JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeStreamWrongLastSequence, Code: 400}, message: "key exists"} +) + +const ( + kvBucketNamePre = "KV_" + kvBucketNameTmpl = "KV_%s" + kvSubjectsTmpl = "$KV.%s.>" + kvSubjectsPreTmpl = "$KV.%s." + kvSubjectsPreDomainTmpl = "%s.$KV.%s." +) + +// Regex for valid keys and buckets. +var ( + validBucketRe = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`) + validKeyRe = regexp.MustCompile(`^[-/_=\.a-zA-Z0-9]+$`) + validSearchKeyRe = regexp.MustCompile(`^[-/_=\.a-zA-Z0-9*]*[>]?$`) +) + +// KeyValue will lookup and bind to an existing KeyValue store. +func (js *js) KeyValue(bucket string) (KeyValue, error) { + if !js.nc.serverMinVersion(2, 6, 2) { + return nil, errors.New("nats: key-value requires at least server version 2.6.2") + } + if !bucketValid(bucket) { + return nil, ErrInvalidBucketName + } + stream := fmt.Sprintf(kvBucketNameTmpl, bucket) + si, err := js.StreamInfo(stream) + if err != nil { + if errors.Is(err, ErrStreamNotFound) { + err = ErrBucketNotFound + } + return nil, err + } + // Do some quick sanity checks that this is a correctly formed stream for KV. + // Max msgs per subject should be > 0. + if si.Config.MaxMsgsPerSubject < 1 { + return nil, ErrBadBucket + } + + return mapStreamToKVS(js, si), nil +} + +// CreateKeyValue will create a KeyValue store with the following configuration. +func (js *js) CreateKeyValue(cfg *KeyValueConfig) (KeyValue, error) { + if !js.nc.serverMinVersion(2, 6, 2) { + return nil, errors.New("nats: key-value requires at least server version 2.6.2") + } + if cfg == nil { + return nil, ErrKeyValueConfigRequired + } + if !bucketValid(cfg.Bucket) { + return nil, ErrInvalidBucketName + } + if _, err := js.AccountInfo(); err != nil { + return nil, err + } + + // Default to 1 for history. Max is 64 for now. + history := int64(1) + if cfg.History > 0 { + if cfg.History > KeyValueMaxHistory { + return nil, ErrHistoryToLarge + } + history = int64(cfg.History) + } + + replicas := cfg.Replicas + if replicas == 0 { + replicas = 1 + } + + // We will set explicitly some values so that we can do comparison + // if we get an "already in use" error and need to check if it is same. + maxBytes := cfg.MaxBytes + if maxBytes == 0 { + maxBytes = -1 + } + maxMsgSize := cfg.MaxValueSize + if maxMsgSize == 0 { + maxMsgSize = -1 + } + // When stream's MaxAge is not set, server uses 2 minutes as the default + // for the duplicate window. If MaxAge is set, and lower than 2 minutes, + // then the duplicate window will be set to that. If MaxAge is greater, + // we will cap the duplicate window to 2 minutes (to be consistent with + // previous behavior). + duplicateWindow := 2 * time.Minute + if cfg.TTL > 0 && cfg.TTL < duplicateWindow { + duplicateWindow = cfg.TTL + } + var compression StoreCompression + if cfg.Compression { + compression = S2Compression + } + scfg := &StreamConfig{ + Name: fmt.Sprintf(kvBucketNameTmpl, cfg.Bucket), + Description: cfg.Description, + MaxMsgsPerSubject: history, + MaxBytes: maxBytes, + MaxAge: cfg.TTL, + MaxMsgSize: maxMsgSize, + Storage: cfg.Storage, + Replicas: replicas, + Placement: cfg.Placement, + AllowRollup: true, + DenyDelete: true, + Duplicates: duplicateWindow, + MaxMsgs: -1, + MaxConsumers: -1, + AllowDirect: true, + RePublish: cfg.RePublish, + Compression: compression, + } + if cfg.Mirror != nil { + // Copy in case we need to make changes so we do not change caller's version. + m := cfg.Mirror.copy() + if !strings.HasPrefix(m.Name, kvBucketNamePre) { + m.Name = fmt.Sprintf(kvBucketNameTmpl, m.Name) + } + scfg.Mirror = m + scfg.MirrorDirect = true + } else if len(cfg.Sources) > 0 { + for _, ss := range cfg.Sources { + var sourceBucketName string + if strings.HasPrefix(ss.Name, kvBucketNamePre) { + sourceBucketName = ss.Name[len(kvBucketNamePre):] + } else { + sourceBucketName = ss.Name + ss.Name = fmt.Sprintf(kvBucketNameTmpl, ss.Name) + } + + if ss.External == nil || sourceBucketName != cfg.Bucket { + ss.SubjectTransforms = []SubjectTransformConfig{{Source: fmt.Sprintf(kvSubjectsTmpl, sourceBucketName), Destination: fmt.Sprintf(kvSubjectsTmpl, cfg.Bucket)}} + } + scfg.Sources = append(scfg.Sources, ss) + } + scfg.Subjects = []string{fmt.Sprintf(kvSubjectsTmpl, cfg.Bucket)} + } else { + scfg.Subjects = []string{fmt.Sprintf(kvSubjectsTmpl, cfg.Bucket)} + } + + // If we are at server version 2.7.2 or above use DiscardNew. We can not use DiscardNew for 2.7.1 or below. + if js.nc.serverMinVersion(2, 7, 2) { + scfg.Discard = DiscardNew + } + + si, err := js.AddStream(scfg) + if err != nil { + // If we have a failure to add, it could be because we have + // a config change if the KV was created against a pre 2.7.2 + // and we are now moving to a v2.7.2+. If that is the case + // and the only difference is the discard policy, then update + // the stream. + // The same logic applies for KVs created pre 2.9.x and + // the AllowDirect setting. + if errors.Is(err, ErrStreamNameAlreadyInUse) { + if si, _ = js.StreamInfo(scfg.Name); si != nil { + // To compare, make the server's stream info discard + // policy same than ours. + si.Config.Discard = scfg.Discard + // Also need to set allow direct for v2.9.x+ + si.Config.AllowDirect = scfg.AllowDirect + if reflect.DeepEqual(&si.Config, scfg) { + si, err = js.UpdateStream(scfg) + } + } + } + if err != nil { + return nil, err + } + } + return mapStreamToKVS(js, si), nil +} + +// DeleteKeyValue will delete this KeyValue store (JetStream stream). +func (js *js) DeleteKeyValue(bucket string) error { + if !bucketValid(bucket) { + return ErrInvalidBucketName + } + stream := fmt.Sprintf(kvBucketNameTmpl, bucket) + return js.DeleteStream(stream) +} + +type kvs struct { + name string + stream string + pre string + putPre string + js *js + // If true, it means that APIPrefix/Domain was set in the context + // and we need to add something to some of our high level protocols + // (such as Put, etc..) + useJSPfx bool + // To know if we can use the stream direct get API + useDirect bool +} + +// Underlying entry. +type kve struct { + bucket string + key string + value []byte + revision uint64 + delta uint64 + created time.Time + op KeyValueOp +} + +func (e *kve) Bucket() string { return e.bucket } +func (e *kve) Key() string { return e.key } +func (e *kve) Value() []byte { return e.value } +func (e *kve) Revision() uint64 { return e.revision } +func (e *kve) Created() time.Time { return e.created } +func (e *kve) Delta() uint64 { return e.delta } +func (e *kve) Operation() KeyValueOp { return e.op } + +func bucketValid(bucket string) bool { + if len(bucket) == 0 { + return false + } + return validBucketRe.MatchString(bucket) +} + +func keyValid(key string) bool { + if len(key) == 0 || key[0] == '.' || key[len(key)-1] == '.' { + return false + } + return validKeyRe.MatchString(key) +} + +func searchKeyValid(key string) bool { + if len(key) == 0 || key[0] == '.' || key[len(key)-1] == '.' { + return false + } + return validSearchKeyRe.MatchString(key) +} + +// Get returns the latest value for the key. +func (kv *kvs) Get(key string) (KeyValueEntry, error) { + e, err := kv.get(key, kvLatestRevision) + if err != nil { + if errors.Is(err, ErrKeyDeleted) { + return nil, ErrKeyNotFound + } + return nil, err + } + + return e, nil +} + +// GetRevision returns a specific revision value for the key. +func (kv *kvs) GetRevision(key string, revision uint64) (KeyValueEntry, error) { + e, err := kv.get(key, revision) + if err != nil { + if errors.Is(err, ErrKeyDeleted) { + return nil, ErrKeyNotFound + } + return nil, err + } + + return e, nil +} + +func (kv *kvs) get(key string, revision uint64) (KeyValueEntry, error) { + if !keyValid(key) { + return nil, ErrInvalidKey + } + + var b strings.Builder + b.WriteString(kv.pre) + b.WriteString(key) + + var m *RawStreamMsg + var err error + var _opts [1]JSOpt + opts := _opts[:0] + if kv.useDirect { + opts = append(opts, DirectGet()) + } + + if revision == kvLatestRevision { + m, err = kv.js.GetLastMsg(kv.stream, b.String(), opts...) + } else { + m, err = kv.js.GetMsg(kv.stream, revision, opts...) + // If a sequence was provided, just make sure that the retrieved + // message subject matches the request. + if err == nil && m.Subject != b.String() { + return nil, ErrKeyNotFound + } + } + if err != nil { + if errors.Is(err, ErrMsgNotFound) { + err = ErrKeyNotFound + } + return nil, err + } + + entry := &kve{ + bucket: kv.name, + key: key, + value: m.Data, + revision: m.Sequence, + created: m.Time, + } + + // Double check here that this is not a DEL Operation marker. + if len(m.Header) > 0 { + switch m.Header.Get(kvop) { + case kvdel: + entry.op = KeyValueDelete + return entry, ErrKeyDeleted + case kvpurge: + entry.op = KeyValuePurge + return entry, ErrKeyDeleted + } + } + + return entry, nil +} + +// Put will place the new value for the key into the store. +func (kv *kvs) Put(key string, value []byte) (revision uint64, err error) { + if !keyValid(key) { + return 0, ErrInvalidKey + } + + var b strings.Builder + if kv.useJSPfx { + b.WriteString(kv.js.opts.pre) + } + if kv.putPre != _EMPTY_ { + b.WriteString(kv.putPre) + } else { + b.WriteString(kv.pre) + } + b.WriteString(key) + + pa, err := kv.js.Publish(b.String(), value) + if err != nil { + return 0, err + } + return pa.Sequence, err +} + +// PutString will place the string for the key into the store. +func (kv *kvs) PutString(key string, value string) (revision uint64, err error) { + return kv.Put(key, []byte(value)) +} + +// Create will add the key/value pair if it does not exist. +func (kv *kvs) Create(key string, value []byte) (revision uint64, err error) { + v, err := kv.Update(key, value, 0) + if err == nil { + return v, nil + } + + // TODO(dlc) - Since we have tombstones for DEL ops for watchers, this could be from that + // so we need to double check. + if e, err := kv.get(key, kvLatestRevision); errors.Is(err, ErrKeyDeleted) { + return kv.Update(key, value, e.Revision()) + } + + // Check if the expected last subject sequence is not zero which implies + // the key already exists. + if errors.Is(err, ErrKeyExists) { + jserr := ErrKeyExists.(*jsError) + return 0, fmt.Errorf("%w: %s", err, jserr.message) + } + + return 0, err +} + +// Update will update the value if the latest revision matches. +func (kv *kvs) Update(key string, value []byte, revision uint64) (uint64, error) { + if !keyValid(key) { + return 0, ErrInvalidKey + } + + var b strings.Builder + if kv.useJSPfx { + b.WriteString(kv.js.opts.pre) + } + b.WriteString(kv.pre) + b.WriteString(key) + + m := Msg{Subject: b.String(), Header: Header{}, Data: value} + m.Header.Set(ExpectedLastSubjSeqHdr, strconv.FormatUint(revision, 10)) + + pa, err := kv.js.PublishMsg(&m) + if err != nil { + return 0, err + } + return pa.Sequence, err +} + +// Delete will place a delete marker and leave all revisions. +func (kv *kvs) Delete(key string, opts ...DeleteOpt) error { + if !keyValid(key) { + return ErrInvalidKey + } + + var b strings.Builder + if kv.useJSPfx { + b.WriteString(kv.js.opts.pre) + } + if kv.putPre != _EMPTY_ { + b.WriteString(kv.putPre) + } else { + b.WriteString(kv.pre) + } + b.WriteString(key) + + // DEL op marker. For watch functionality. + m := NewMsg(b.String()) + + var o deleteOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureDelete(&o); err != nil { + return err + } + } + } + + if o.purge { + m.Header.Set(kvop, kvpurge) + m.Header.Set(MsgRollup, MsgRollupSubject) + } else { + m.Header.Set(kvop, kvdel) + } + + if o.revision != 0 { + m.Header.Set(ExpectedLastSubjSeqHdr, strconv.FormatUint(o.revision, 10)) + } + + _, err := kv.js.PublishMsg(m) + return err +} + +// Purge will remove the key and all revisions. +func (kv *kvs) Purge(key string, opts ...DeleteOpt) error { + return kv.Delete(key, append(opts, purge())...) +} + +const kvDefaultPurgeDeletesMarkerThreshold = 30 * time.Minute + +// PurgeDeletes will remove all current delete markers. +// This is a maintenance option if there is a larger buildup of delete markers. +// See DeleteMarkersOlderThan() option for more information. +func (kv *kvs) PurgeDeletes(opts ...PurgeOpt) error { + var o purgeOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configurePurge(&o); err != nil { + return err + } + } + } + // Transfer possible context purge option to the watcher. This is the + // only option that matters for the PurgeDeletes() feature. + var wopts []WatchOpt + if o.ctx != nil { + wopts = append(wopts, Context(o.ctx)) + } + watcher, err := kv.WatchAll(wopts...) + if err != nil { + return err + } + defer watcher.Stop() + + var limit time.Time + olderThan := o.dmthr + // Negative value is used to instruct to always remove markers, regardless + // of age. If set to 0 (or not set), use our default value. + if olderThan == 0 { + olderThan = kvDefaultPurgeDeletesMarkerThreshold + } + if olderThan > 0 { + limit = time.Now().Add(-olderThan) + } + + var deleteMarkers []KeyValueEntry + for entry := range watcher.Updates() { + if entry == nil { + break + } + if op := entry.Operation(); op == KeyValueDelete || op == KeyValuePurge { + deleteMarkers = append(deleteMarkers, entry) + } + } + // Stop watcher here so as we purge we do not have the system continually updating numPending. + watcher.Stop() + + var ( + pr StreamPurgeRequest + b strings.Builder + ) + // Do actual purges here. + purgeOpts := []JSOpt{} + if o.ctx != nil { + purgeOpts = append(purgeOpts, Context(o.ctx)) + } + for _, entry := range deleteMarkers { + b.WriteString(kv.pre) + b.WriteString(entry.Key()) + pr.Subject = b.String() + pr.Keep = 0 + if olderThan > 0 && entry.Created().After(limit) { + pr.Keep = 1 + } + if err := kv.js.purgeStream(kv.stream, &pr, purgeOpts...); err != nil { + return err + } + b.Reset() + } + return nil +} + +// Keys() will return all keys. +func (kv *kvs) Keys(opts ...WatchOpt) ([]string, error) { + opts = append(opts, IgnoreDeletes(), MetaOnly()) + watcher, err := kv.WatchAll(opts...) + if err != nil { + return nil, err + } + defer watcher.Stop() + + var keys []string + for entry := range watcher.Updates() { + if entry == nil { + break + } + keys = append(keys, entry.Key()) + } + if len(keys) == 0 { + return nil, ErrNoKeysFound + } + return keys, nil +} + +type keyLister struct { + watcher KeyWatcher + keys chan string +} + +// ListKeys will return all keys. +func (kv *kvs) ListKeys(opts ...WatchOpt) (KeyLister, error) { + opts = append(opts, IgnoreDeletes(), MetaOnly()) + watcher, err := kv.WatchAll(opts...) + if err != nil { + return nil, err + } + kl := &keyLister{watcher: watcher, keys: make(chan string, 256)} + + go func() { + defer close(kl.keys) + defer watcher.Stop() + for entry := range watcher.Updates() { + if entry == nil { + return + } + kl.keys <- entry.Key() + } + }() + return kl, nil +} + +func (kl *keyLister) Keys() <-chan string { + return kl.keys +} + +func (kl *keyLister) Stop() error { + return kl.watcher.Stop() +} + +func (kl *keyLister) Error() <-chan error { + return kl.watcher.Error() +} + +// History will return all values for the key. +func (kv *kvs) History(key string, opts ...WatchOpt) ([]KeyValueEntry, error) { + opts = append(opts, IncludeHistory()) + watcher, err := kv.Watch(key, opts...) + if err != nil { + return nil, err + } + defer watcher.Stop() + + var entries []KeyValueEntry + for entry := range watcher.Updates() { + if entry == nil { + break + } + entries = append(entries, entry) + } + if len(entries) == 0 { + return nil, ErrKeyNotFound + } + return entries, nil +} + +// Implementation for Watch +type watcher struct { + mu sync.Mutex + updates chan KeyValueEntry + sub *Subscription + initDone bool + initPending uint64 + received uint64 + ctx context.Context + initDoneTimer *time.Timer + errCh chan error +} + +// Context returns the context for the watcher if set. +func (w *watcher) Context() context.Context { + if w == nil { + return nil + } + return w.ctx +} + +// Updates returns the interior channel. +func (w *watcher) Updates() <-chan KeyValueEntry { + if w == nil { + return nil + } + return w.updates +} + +// Stop will unsubscribe from the watcher. +func (w *watcher) Stop() error { + if w == nil { + return nil + } + return w.sub.Unsubscribe() +} + +// Error returns a channel that will receive any error that occurs during watching. +func (w *watcher) Error() <-chan error { + if w == nil { + closedCh := make(chan error) + close(closedCh) + return closedCh + } + return w.errCh +} + +// WatchAll watches all keys. +func (kv *kvs) WatchAll(opts ...WatchOpt) (KeyWatcher, error) { + return kv.Watch(AllKeys, opts...) +} + +func (kv *kvs) WatchFiltered(keys []string, opts ...WatchOpt) (KeyWatcher, error) { + for _, key := range keys { + if !searchKeyValid(key) { + return nil, fmt.Errorf("%w: %s", ErrInvalidKey, "key cannot be empty and must be a valid NATS subject") + } + } + var o watchOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureWatcher(&o); err != nil { + return nil, err + } + } + } + + // Could be a pattern so don't check for validity as we normally do. + for i, key := range keys { + var b strings.Builder + b.WriteString(kv.pre) + b.WriteString(key) + keys[i] = b.String() + } + + // if no keys are provided, watch all keys + if len(keys) == 0 { + var b strings.Builder + b.WriteString(kv.pre) + b.WriteString(AllKeys) + keys = []string{b.String()} + } + + // We will block below on placing items on the chan. That is by design. + w := &watcher{ + updates: make(chan KeyValueEntry, 256), + ctx: o.ctx, + errCh: make(chan error, 1), + } + + update := func(m *Msg) { + tokens, err := parser.GetMetadataFields(m.Reply) + if err != nil { + return + } + if len(m.Subject) <= len(kv.pre) { + return + } + subj := m.Subject[len(kv.pre):] + + var op KeyValueOp + if len(m.Header) > 0 { + switch m.Header.Get(kvop) { + case kvdel: + op = KeyValueDelete + case kvpurge: + op = KeyValuePurge + } + } + delta := parser.ParseNum(tokens[parser.AckNumPendingTokenPos]) + w.mu.Lock() + defer w.mu.Unlock() + if !o.ignoreDeletes || (op != KeyValueDelete && op != KeyValuePurge) { + entry := &kve{ + bucket: kv.name, + key: subj, + value: m.Data, + revision: parser.ParseNum(tokens[parser.AckStreamSeqTokenPos]), + created: time.Unix(0, int64(parser.ParseNum(tokens[parser.AckTimestampSeqTokenPos]))), + delta: delta, + op: op, + } + w.updates <- entry + } + // Check if done and initial values. + // Skip if UpdatesOnly() is set, since there will never be updates initially. + if !w.initDone { + w.received++ + // Use the stable initPending value set at consumer creation. + // We're done if we've received all expected messages OR there are no more pending + if w.received >= w.initPending || delta == 0 { + // Avoid possible race setting up timer. + if w.initDoneTimer != nil { + w.initDoneTimer.Stop() + } + w.initDone = true + w.updates <- nil + } else if w.initDoneTimer != nil { + w.initDoneTimer.Reset(kv.js.opts.wait) + } + } + } + + // Used ordered consumer to deliver results. + subOpts := []SubOpt{BindStream(kv.stream), OrderedConsumer()} + if !o.includeHistory { + subOpts = append(subOpts, DeliverLastPerSubject()) + } + if o.updatesOnly { + subOpts = append(subOpts, DeliverNew()) + } + if o.metaOnly { + subOpts = append(subOpts, HeadersOnly()) + } + if o.ctx != nil { + subOpts = append(subOpts, Context(o.ctx)) + } + // Create the sub and rest of initialization under the lock. + // We want to prevent the race between this code and the + // update() callback. + w.mu.Lock() + defer w.mu.Unlock() + var sub *Subscription + var err error + if len(keys) == 1 { + sub, err = kv.js.Subscribe(keys[0], update, subOpts...) + } else { + subOpts = append(subOpts, ConsumerFilterSubjects(keys...)) + sub, err = kv.js.Subscribe("", update, subOpts...) + } + if err != nil { + return nil, err + } + sub.mu.Lock() + // If there were no pending messages at the time of the creation + // of the consumer, send the marker. + // Skip if UpdatesOnly() is set, since there will never be updates initially. + if !o.updatesOnly { + if sub.jsi != nil { + if sub.jsi.pending == 0 { + w.initDone = true + w.updates <- nil + } else { + w.initPending = sub.jsi.pending + // Set a timer to send the marker if we do not get any messages. + w.initDoneTimer = time.AfterFunc(kv.js.opts.wait, func() { + w.mu.Lock() + defer w.mu.Unlock() + if !w.initDone { + w.initDone = true + select { + case w.errCh <- ErrKeyWatcherTimeout: + default: + } + w.updates <- nil + } + }) + } + } + } else { + // if UpdatesOnly was used, mark initialization as complete + w.initDone = true + } + // Set us up to close when the waitForMessages func returns. + sub.pDone = func(_ string) { + w.mu.Lock() + defer w.mu.Unlock() + if w.initDoneTimer != nil { + w.initDoneTimer.Stop() + } + close(w.updates) + close(w.errCh) + } + + sub.mu.Unlock() + + w.sub = sub + return w, nil +} + +// Watch will fire the callback when a key that matches the keys pattern is updated. +// keys needs to be a valid NATS subject. +func (kv *kvs) Watch(keys string, opts ...WatchOpt) (KeyWatcher, error) { + return kv.WatchFiltered([]string{keys}, opts...) +} + +// Bucket returns the current bucket name (JetStream stream). +func (kv *kvs) Bucket() string { + return kv.name +} + +// KeyValueBucketStatus represents status of a Bucket, implements KeyValueStatus +type KeyValueBucketStatus struct { + nfo *StreamInfo + bucket string +} + +// Bucket the name of the bucket +func (s *KeyValueBucketStatus) Bucket() string { return s.bucket } + +// Values is how many messages are in the bucket, including historical values +func (s *KeyValueBucketStatus) Values() uint64 { return s.nfo.State.Msgs } + +// History returns the configured history kept per key +func (s *KeyValueBucketStatus) History() int64 { return s.nfo.Config.MaxMsgsPerSubject } + +// TTL is how long the bucket keeps values for +func (s *KeyValueBucketStatus) TTL() time.Duration { return s.nfo.Config.MaxAge } + +// BackingStore indicates what technology is used for storage of the bucket +func (s *KeyValueBucketStatus) BackingStore() string { return "JetStream" } + +// StreamInfo is the stream info retrieved to create the status +func (s *KeyValueBucketStatus) StreamInfo() *StreamInfo { return s.nfo } + +// Bytes is the size of the stream +func (s *KeyValueBucketStatus) Bytes() uint64 { return s.nfo.State.Bytes } + +// IsCompressed indicates if the data is compressed on disk +func (s *KeyValueBucketStatus) IsCompressed() bool { return s.nfo.Config.Compression != NoCompression } + +// Status retrieves the status and configuration of a bucket +func (kv *kvs) Status() (KeyValueStatus, error) { + nfo, err := kv.js.StreamInfo(kv.stream) + if err != nil { + return nil, err + } + + return &KeyValueBucketStatus{nfo: nfo, bucket: kv.name}, nil +} + +// KeyValueStoreNames is used to retrieve a list of key value store names +func (js *js) KeyValueStoreNames() <-chan string { + ch := make(chan string) + l := &streamNamesLister{js: js} + l.js.opts.streamListSubject = fmt.Sprintf(kvSubjectsTmpl, "*") + go func() { + defer close(ch) + for l.Next() { + for _, name := range l.Page() { + if !strings.HasPrefix(name, kvBucketNamePre) { + continue + } + ch <- strings.TrimPrefix(name, kvBucketNamePre) + } + } + }() + + return ch +} + +// KeyValueStores is used to retrieve a list of key value store statuses +func (js *js) KeyValueStores() <-chan KeyValueStatus { + ch := make(chan KeyValueStatus) + l := &streamLister{js: js} + l.js.opts.streamListSubject = fmt.Sprintf(kvSubjectsTmpl, "*") + go func() { + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + if !strings.HasPrefix(info.Config.Name, kvBucketNamePre) { + continue + } + ch <- &KeyValueBucketStatus{nfo: info, bucket: strings.TrimPrefix(info.Config.Name, kvBucketNamePre)} + } + } + }() + return ch +} + +func mapStreamToKVS(js *js, info *StreamInfo) *kvs { + bucket := strings.TrimPrefix(info.Config.Name, kvBucketNamePre) + + kv := &kvs{ + name: bucket, + stream: info.Config.Name, + pre: fmt.Sprintf(kvSubjectsPreTmpl, bucket), + js: js, + // Determine if we need to use the JS prefix in front of Put and Delete operations + useJSPfx: js.opts.pre != defaultAPIPrefix, + useDirect: info.Config.AllowDirect, + } + + // If we are mirroring, we will have mirror direct on, so just use the mirror name + // and override use + if m := info.Config.Mirror; m != nil { + bucket := strings.TrimPrefix(m.Name, kvBucketNamePre) + if m.External != nil && m.External.APIPrefix != _EMPTY_ { + kv.useJSPfx = false + kv.pre = fmt.Sprintf(kvSubjectsPreTmpl, bucket) + kv.putPre = fmt.Sprintf(kvSubjectsPreDomainTmpl, m.External.APIPrefix, bucket) + } else { + kv.putPre = fmt.Sprintf(kvSubjectsPreTmpl, bucket) + } + } + + return kv +} diff --git a/vendor/github.com/nats-io/nats.go/legacy_jetstream.md b/vendor/github.com/nats-io/nats.go/legacy_jetstream.md new file mode 100644 index 0000000..43e1c73 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/legacy_jetstream.md @@ -0,0 +1,83 @@ +# Legacy JetStream API + +This is a documentation for the legacy JetStream API. A README for the current +API can be found [here](jetstream/README.md) + +## JetStream Basic Usage + +```go +import "github.com/nats-io/nats.go" + +// Connect to NATS +nc, _ := nats.Connect(nats.DefaultURL) + +// Create JetStream Context +js, _ := nc.JetStream(nats.PublishAsyncMaxPending(256)) + +// Simple Stream Publisher +js.Publish("ORDERS.scratch", []byte("hello")) + +// Simple Async Stream Publisher +for i := 0; i < 500; i++ { + js.PublishAsync("ORDERS.scratch", []byte("hello")) +} +select { +case <-js.PublishAsyncComplete(): +case <-time.After(5 * time.Second): + fmt.Println("Did not resolve in time") +} + +// Simple Async Ephemeral Consumer +js.Subscribe("ORDERS.*", func(m *nats.Msg) { + fmt.Printf("Received a JetStream message: %s\n", string(m.Data)) +}) + +// Simple Sync Durable Consumer (optional SubOpts at the end) +sub, err := js.SubscribeSync("ORDERS.*", nats.Durable("MONITOR"), nats.MaxDeliver(3)) +m, err := sub.NextMsg(timeout) + +// Simple Pull Consumer +sub, err := js.PullSubscribe("ORDERS.*", "MONITOR") +msgs, err := sub.Fetch(10) + +// Unsubscribe +sub.Unsubscribe() + +// Drain +sub.Drain() +``` + +## JetStream Basic Management + +```go +import "github.com/nats-io/nats.go" + +// Connect to NATS +nc, _ := nats.Connect(nats.DefaultURL) + +// Create JetStream Context +js, _ := nc.JetStream() + +// Create a Stream +js.AddStream(&nats.StreamConfig{ + Name: "ORDERS", + Subjects: []string{"ORDERS.*"}, +}) + +// Update a Stream +js.UpdateStream(&nats.StreamConfig{ + Name: "ORDERS", + MaxBytes: 8, +}) + +// Create a Consumer +js.AddConsumer("ORDERS", &nats.ConsumerConfig{ + Durable: "MONITOR", +}) + +// Delete Consumer +js.DeleteConsumer("ORDERS", "MONITOR") + +// Delete Stream +js.DeleteStream("ORDERS") +``` diff --git a/vendor/github.com/nats-io/nats.go/nats.go b/vendor/github.com/nats-io/nats.go/nats.go index 6b0bb26..c569469 100644 --- a/vendor/github.com/nats-io/nats.go/nats.go +++ b/vendor/github.com/nats-io/nats.go/nats.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -24,7 +24,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math/rand" "net" "net/http" @@ -32,21 +31,24 @@ import ( "net/url" "os" "path/filepath" + "regexp" "runtime" + "slices" "strconv" "strings" "sync" "sync/atomic" "time" - "github.com/nats-io/nats.go/util" "github.com/nats-io/nkeys" "github.com/nats-io/nuid" + + "github.com/nats-io/nats.go/util" ) // Default Constants const ( - Version = "1.11.0" + Version = "1.48.0" DefaultURL = "nats://127.0.0.1:4222" DefaultPort = 4222 DefaultMaxReconnect = 60 @@ -54,13 +56,13 @@ const ( DefaultReconnectJitter = 100 * time.Millisecond DefaultReconnectJitterTLS = time.Second DefaultTimeout = 2 * time.Second - DefaultJetStreamTimeout = 2 * time.Second DefaultPingInterval = 2 * time.Minute DefaultMaxPingOut = 2 - DefaultMaxChanLen = 8192 // 8k + DefaultMaxChanLen = 64 * 1024 // 64k DefaultReconnectBufSize = 8 * 1024 * 1024 // 8MB RequestChanLen = 8 DefaultDrainTimeout = 30 * time.Second + DefaultFlusherTimeout = time.Minute LangString = "go" ) @@ -76,68 +78,82 @@ const ( // AUTHENTICATION_EXPIRED_ERR is for when nats server user authorization has expired. AUTHENTICATION_EXPIRED_ERR = "user authentication expired" + + // AUTHENTICATION_REVOKED_ERR is for when user authorization has been revoked. + AUTHENTICATION_REVOKED_ERR = "user authentication revoked" + + // ACCOUNT_AUTHENTICATION_EXPIRED_ERR is for when nats server account authorization has expired. + ACCOUNT_AUTHENTICATION_EXPIRED_ERR = "account authentication expired" + + // MAX_CONNECTIONS_ERR is for when nats server denies the connection due to server max_connections limit. + MAX_CONNECTIONS_ERR = "maximum connections exceeded" + + // MAX_ACCOUNT_CONNECTIONS_ERR is for when nats server denies the connection due to server max_connections limit on the account. + MAX_ACCOUNT_CONNECTIONS_ERR = `maximum account active connections exceeded` + + // MAX_SUBSCRIPTIONS_ERR is for when nats server denies the connection due to server subscriptions limit. + MAX_SUBSCRIPTIONS_ERR = "maximum subscriptions exceeded" ) // Errors var ( - ErrConnectionClosed = errors.New("nats: connection closed") - ErrConnectionDraining = errors.New("nats: connection draining") - ErrDrainTimeout = errors.New("nats: draining connection timed out") - ErrConnectionReconnecting = errors.New("nats: connection reconnecting") - ErrSecureConnRequired = errors.New("nats: secure connection required") - ErrSecureConnWanted = errors.New("nats: secure connection not available") - ErrBadSubscription = errors.New("nats: invalid subscription") - ErrTypeSubscription = errors.New("nats: invalid subscription type") - ErrBadSubject = errors.New("nats: invalid subject") - ErrBadQueueName = errors.New("nats: invalid queue name") - ErrSlowConsumer = errors.New("nats: slow consumer, messages dropped") - ErrTimeout = errors.New("nats: timeout") - ErrBadTimeout = errors.New("nats: timeout invalid") - ErrAuthorization = errors.New("nats: authorization violation") - ErrAuthExpired = errors.New("nats: authentication expired") - ErrNoServers = errors.New("nats: no servers available for connection") - ErrJsonParse = errors.New("nats: connect message, json parse error") - ErrChanArg = errors.New("nats: argument needs to be a channel type") - ErrMaxPayload = errors.New("nats: maximum payload exceeded") - ErrMaxMessages = errors.New("nats: maximum messages delivered") - ErrSyncSubRequired = errors.New("nats: illegal call on an async subscription") - ErrMultipleTLSConfigs = errors.New("nats: multiple tls.Configs not allowed") - ErrNoInfoReceived = errors.New("nats: protocol exception, INFO not received") - ErrReconnectBufExceeded = errors.New("nats: outbound buffer limit exceeded") - ErrInvalidConnection = errors.New("nats: invalid connection") - ErrInvalidMsg = errors.New("nats: invalid message or message nil") - ErrInvalidArg = errors.New("nats: invalid argument") - ErrInvalidContext = errors.New("nats: invalid context") - ErrNoDeadlineContext = errors.New("nats: context requires a deadline") - ErrNoEchoNotSupported = errors.New("nats: no echo option not supported by this server") - ErrClientIDNotSupported = errors.New("nats: client ID not supported by this server") - ErrUserButNoSigCB = errors.New("nats: user callback defined without a signature handler") - ErrNkeyButNoSigCB = errors.New("nats: nkey defined without a signature handler") - ErrNoUserCB = errors.New("nats: user callback not defined") - ErrNkeyAndUser = errors.New("nats: user callback and nkey defined") - ErrNkeysNotSupported = errors.New("nats: nkeys not supported by the server") - ErrStaleConnection = errors.New("nats: " + STALE_CONNECTION) - ErrTokenAlreadySet = errors.New("nats: token and token handler both set") - ErrMsgNotBound = errors.New("nats: message is not bound to subscription/connection") - ErrMsgNoReply = errors.New("nats: message does not have a reply") - ErrClientIPNotSupported = errors.New("nats: client IP not supported by this server") - ErrDisconnected = errors.New("nats: server is disconnected") - ErrHeadersNotSupported = errors.New("nats: headers not supported by this server") - ErrBadHeaderMsg = errors.New("nats: message could not decode headers") - ErrNoResponders = errors.New("nats: no responders available for request") - ErrNoContextOrTimeout = errors.New("nats: no context or timeout given") - ErrNotJSMessage = errors.New("nats: not a JetStream message") - ErrInvalidStreamName = errors.New("nats: invalid stream name") - ErrInvalidJSAck = errors.New("nats: invalid JetStream publish acknowledgement") - ErrMultiStreamUnsupported = errors.New("nats: multiple streams are not supported") - ErrStreamNameRequired = errors.New("nats: Stream name is required") - ErrConsumerConfigRequired = errors.New("nats: Consumer configuration is required") + ErrConnectionClosed = errors.New("nats: connection closed") + ErrConnectionDraining = errors.New("nats: connection draining") + ErrDrainTimeout = errors.New("nats: draining connection timed out") + ErrConnectionReconnecting = errors.New("nats: connection reconnecting") + ErrSecureConnRequired = errors.New("nats: secure connection required") + ErrSecureConnWanted = errors.New("nats: secure connection not available") + ErrBadSubscription = errors.New("nats: invalid subscription") + ErrTypeSubscription = errors.New("nats: invalid subscription type") + ErrBadSubject = errors.New("nats: invalid subject") + ErrBadQueueName = errors.New("nats: invalid queue name") + ErrSlowConsumer = errors.New("nats: slow consumer, messages dropped") + ErrTimeout = errors.New("nats: timeout") + ErrBadTimeout = errors.New("nats: timeout invalid") + ErrAuthorization = errors.New("nats: authorization violation") + ErrAuthExpired = errors.New("nats: authentication expired") + ErrAuthRevoked = errors.New("nats: authentication revoked") + ErrPermissionViolation = errors.New("nats: permissions violation") + ErrAccountAuthExpired = errors.New("nats: account authentication expired") + ErrNoServers = errors.New("nats: no servers available for connection") + ErrJsonParse = errors.New("nats: connect message, json parse error") + ErrChanArg = errors.New("nats: argument needs to be a channel type") + ErrMaxPayload = errors.New("nats: maximum payload exceeded") + ErrMaxMessages = errors.New("nats: maximum messages delivered") + ErrSyncSubRequired = errors.New("nats: illegal call on an async subscription") + ErrMultipleTLSConfigs = errors.New("nats: multiple tls.Configs not allowed") + ErrClientCertOrRootCAsRequired = errors.New("nats: at least one of certCB or rootCAsCB must be set") + ErrNoInfoReceived = errors.New("nats: protocol exception, INFO not received") + ErrReconnectBufExceeded = errors.New("nats: outbound buffer limit exceeded") + ErrInvalidConnection = errors.New("nats: invalid connection") + ErrInvalidMsg = errors.New("nats: invalid message or message nil") + ErrInvalidArg = errors.New("nats: invalid argument") + ErrInvalidContext = errors.New("nats: invalid context") + ErrNoDeadlineContext = errors.New("nats: context requires a deadline") + ErrNoEchoNotSupported = errors.New("nats: no echo option not supported by this server") + ErrClientIDNotSupported = errors.New("nats: client ID not supported by this server") + ErrUserButNoSigCB = errors.New("nats: user callback defined without a signature handler") + ErrNkeyButNoSigCB = errors.New("nats: nkey defined without a signature handler") + ErrNoUserCB = errors.New("nats: user callback not defined") + ErrNkeyAndUser = errors.New("nats: user callback and nkey defined") + ErrNkeysNotSupported = errors.New("nats: nkeys not supported by the server") + ErrStaleConnection = errors.New("nats: " + STALE_CONNECTION) + ErrTokenAlreadySet = errors.New("nats: token and token handler both set") + ErrUserInfoAlreadySet = errors.New("nats: cannot set user info callback and user/pass") + ErrMsgNotBound = errors.New("nats: message is not bound to subscription/connection") + ErrMsgNoReply = errors.New("nats: message does not have a reply") + ErrClientIPNotSupported = errors.New("nats: client IP not supported by this server") + ErrDisconnected = errors.New("nats: server is disconnected") + ErrHeadersNotSupported = errors.New("nats: headers not supported by this server") + ErrBadHeaderMsg = errors.New("nats: message could not decode headers") + ErrNoResponders = errors.New("nats: no responders available for request") + ErrMaxConnectionsExceeded = errors.New("nats: server maximum connections exceeded") + ErrMaxAccountConnectionsExceeded = errors.New("nats: maximum account active connections exceeded") + ErrConnectionNotTLS = errors.New("nats: connection is not tls") + ErrMaxSubscriptionsExceeded = errors.New("nats: server maximum subscriptions exceeded") + ErrWebSocketHeadersAlreadySet = errors.New("nats: websocket connection headers already set") ) -func init() { - rand.Seed(time.Now().UnixNano()) -} - // GetDefaultOptions returns default configuration options for the client. func GetDefaultOptions() Options { return Options{ @@ -147,16 +163,16 @@ func GetDefaultOptions() Options { ReconnectJitter: DefaultReconnectJitter, ReconnectJitterTLS: DefaultReconnectJitterTLS, Timeout: DefaultTimeout, - JetStreamTimeout: DefaultJetStreamTimeout, PingInterval: DefaultPingInterval, MaxPingsOut: DefaultMaxPingOut, SubChanLen: DefaultMaxChanLen, ReconnectBufSize: DefaultReconnectBufSize, DrainTimeout: DefaultDrainTimeout, + FlusherTimeout: DefaultFlusherTimeout, } } -// DEPRECATED: Use GetDefaultOptions() instead. +// Deprecated: Use GetDefaultOptions() instead. // DefaultOptions is not safe for use by multiple clients. // For details see #308. var DefaultOptions = GetDefaultOptions() @@ -174,6 +190,26 @@ const ( DRAINING_PUBS ) +func (s Status) String() string { + switch s { + case DISCONNECTED: + return "DISCONNECTED" + case CONNECTED: + return "CONNECTED" + case CLOSED: + return "CLOSED" + case RECONNECTING: + return "RECONNECTING" + case CONNECTING: + return "CONNECTING" + case DRAINING_SUBS: + return "DRAINING_SUBS" + case DRAINING_PUBS: + return "DRAINING_PUBS" + } + return "unknown status" +} + // ConnHandler is used for asynchronous events such as // disconnected and closed connections. type ConnHandler func(*Conn) @@ -190,6 +226,13 @@ type ErrHandler func(*Conn, *Subscription, error) // JWT for this user. type UserJWTHandler func() (string, error) +// TLSCertHandler is used to fetch and return tls certificate. +type TLSCertHandler func() (tls.Certificate, error) + +// RootCAsHandler is used to fetch and return a set of root certificate +// authorities that clients use when verifying server certificates. +type RootCAsHandler func() (*x509.CertPool, error) + // SignatureHandler is used to sign a nonce from the server while // authenticating with nkeys. The user should sign the nonce and // return the raw signature. The client will base64 encode this to @@ -199,12 +242,18 @@ type SignatureHandler func([]byte) ([]byte, error) // AuthTokenHandler is used to generate a new token. type AuthTokenHandler func() string +// UserInfoCB is used to pass the username and password when establishing connection. +type UserInfoCB func() (string, string) + // ReconnectDelayHandler is used to get from the user the desired // delay the library should pause before attempting to reconnect // again. Note that this is invoked after the library tried the // whole list of URLs and failed to reconnect. type ReconnectDelayHandler func(attempts int) time.Duration +// WebSocketHeadersHandler is an optional callback handler for generating token used for WebSocket connections. +type WebSocketHeadersHandler func() (http.Header, error) + // asyncCB is used to preserve order for async callbacks. type asyncCB struct { f func() @@ -221,20 +270,29 @@ type asyncCallbacksHandler struct { // Option is a function on the options for a connection. type Option func(*Options) error -// CustomDialer can be used to specify any dialer, not necessarily -// a *net.Dialer. +// CustomDialer can be used to specify any dialer, not necessarily a +// *net.Dialer. A CustomDialer may also implement `SkipTLSHandshake() bool` +// in order to skip the TLS handshake in case not required. type CustomDialer interface { Dial(network, address string) (net.Conn, error) } +type InProcessConnProvider interface { + InProcessConn() (net.Conn, error) +} + // Options can be used to create a customized connection. type Options struct { - // Url represents a single NATS server url to which the client // will be connecting. If the Servers option is also set, it // then becomes the first server in the Servers array. Url string + // InProcessServer represents a NATS server running within the + // same process. If this is set then we will attempt to connect + // to the server directly rather than using external TCP conns. + InProcessServer InProcessConnProvider + // Servers is a configured set of servers which this client // will use when attempting to connect. Servers []string @@ -268,6 +326,20 @@ type Options struct { // transports. TLSConfig *tls.Config + // TLSCertCB is used to fetch and return custom tls certificate. + TLSCertCB TLSCertHandler + + // TLSHandshakeFirst is used to instruct the library perform + // the TLS handshake right after the connect and before receiving + // the INFO protocol from the server. If this option is enabled + // but the server is not configured to perform the TLS handshake + // first, the connection will fail. + TLSHandshakeFirst bool + + // RootCAsCB is used to fetch and return a set of root certificate + // authorities that clients use when verifying server certificates. + RootCAsCB RootCAsHandler + // AllowReconnect enables reconnection logic to be used when we // encounter a disconnect from the current server. AllowReconnect bool @@ -275,10 +347,12 @@ type Options struct { // MaxReconnect sets the number of reconnect attempts that will be // tried before giving up. If negative, then it will never give up // trying to reconnect. + // Defaults to 60. MaxReconnect int // ReconnectWait sets the time to backoff after attempting a reconnect // to a server that we were already connected to previously. + // Defaults to 2s. ReconnectWait time.Duration // CustomReconnectDelayCB is invoked after the library tried every @@ -291,33 +365,35 @@ type Options struct { // ReconnectJitter sets the upper bound for a random delay added to // ReconnectWait during a reconnect when no TLS is used. - // Note that any jitter is capped with ReconnectJitterMax. + // Defaults to 100ms. ReconnectJitter time.Duration // ReconnectJitterTLS sets the upper bound for a random delay added to // ReconnectWait during a reconnect when TLS is used. - // Note that any jitter is capped with ReconnectJitterMax. + // Defaults to 1s. ReconnectJitterTLS time.Duration // Timeout sets the timeout for a Dial operation on a connection. + // Defaults to 2s. Timeout time.Duration - // JetStreamTimeout set the default timeout for the JetStream API - JetStreamTimeout time.Duration - // DrainTimeout sets the timeout for a Drain Operation to complete. + // Defaults to 30s. DrainTimeout time.Duration // FlusherTimeout is the maximum time to wait for write operations // to the underlying connection to complete (including the flusher loop). + // Defaults to 1m. FlusherTimeout time.Duration // PingInterval is the period at which the client will be sending ping // commands to the server, disabled if 0 or negative. + // Defaults to 2m. PingInterval time.Duration // MaxPingsOut is the maximum number of pending ping commands that can // be awaiting a response before raising an ErrStaleConnection error. + // Defaults to 2. MaxPingsOut int // ClosedCB sets the closed handler that is called when a client will @@ -327,7 +403,7 @@ type Options struct { // DisconnectedCB sets the disconnected handler that is called // whenever the connection is disconnected. // Will not be called if DisconnectedErrCB is set - // DEPRECATED. Use DisconnectedErrCB which passes error that caused + // Deprecated. Use DisconnectedErrCB which passes error that caused // the disconnect event. DisconnectedCB ConnHandler @@ -337,6 +413,12 @@ type Options struct { // DisconnectedCB will not be called if DisconnectedErrCB is set DisconnectedErrCB ConnErrHandler + // ConnectedCB sets the connected handler called when the initial connection + // is established. It is not invoked on successful reconnects - for reconnections, + // use ReconnectedCB. ConnectedCB can be used in conjunction with RetryOnFailedConnect + // to detect whether the initial connect was successful. + ConnectedCB ConnHandler + // ReconnectedCB sets the reconnected handler called whenever // the connection is successfully reconnected. ReconnectedCB ConnHandler @@ -348,14 +430,20 @@ type Options struct { // AsyncErrorCB sets the async error handler (e.g. slow consumer errors) AsyncErrorCB ErrHandler + // ReconnectErrCB sets the callback that is invoked whenever a + // reconnect attempt failed + ReconnectErrCB ConnErrHandler + // ReconnectBufSize is the size of the backing bufio during reconnect. // Once this has been exhausted publish operations will return an error. + // Defaults to 8388608 bytes (8MB). ReconnectBufSize int // SubChanLen is the size of the buffered channel used between the socket // Go routine and the message delivery for SyncSubscriptions. // NOTE: This does not affect AsyncSubscriptions which are // dictated by PendingLimits() + // Defaults to 65536. SubChanLen int // UserJWT sets the callback handler that will fetch a user's JWT. @@ -376,6 +464,9 @@ type Options struct { // Password sets the password to be used when connecting to a server. Password string + // UserInfo sets the callback handler that will fetch the username and password. + UserInfo UserInfoCB + // Token sets the token to be used when connecting to a server. Token string @@ -383,7 +474,7 @@ type Options struct { TokenHandler AuthTokenHandler // Dialer allows a custom net.Dialer when forming connections. - // DEPRECATED: should use CustomDialer instead. + // Deprecated: should use CustomDialer instead. Dialer *net.Dialer // CustomDialer allows to specify a custom dialer (not necessarily @@ -401,7 +492,7 @@ type Options struct { // LameDuckModeHandler sets the callback to invoke when the server notifies // the connection that it entered lame duck mode, that is, going to - // gradually disconnect all its connections before shuting down. This is + // gradually disconnect all its connections before shutting down. This is // often used in deployments when upgrading NATS Servers. LameDuckModeHandler ConnHandler @@ -409,10 +500,45 @@ type Options struct { // away if it can't connect to a server in the initial set. The // MaxReconnect and ReconnectWait options are used for this process, // similarly to when an established connection is disconnected. - // If a ReconnectHandler is set, it will be invoked when the connection - // is established, and if a ClosedHandler is set, it will be invoked if + // If a ReconnectHandler is set, it will be invoked on the first + // successful reconnect attempt (if the initial connect fails), + // and if a ClosedHandler is set, it will be invoked if // it fails to connect (after exhausting the MaxReconnect attempts). RetryOnFailedConnect bool + + // For websocket connections, indicates to the server that the connection + // supports compression. If the server does too, then data will be compressed. + Compression bool + + // For websocket connections, adds a path to connections url. + // This is useful when connecting to NATS behind a proxy. + ProxyPath string + + // InboxPrefix allows the default _INBOX prefix to be customized + InboxPrefix string + + // IgnoreAuthErrorAbort - if set to true, client opts out of the default connect behavior of aborting + // subsequent reconnect attempts if server returns the same auth error twice (regardless of reconnect policy). + IgnoreAuthErrorAbort bool + + // SkipHostLookup skips the DNS lookup for the server hostname. + SkipHostLookup bool + + // PermissionErrOnSubscribe - if set to true, the client will return ErrPermissionViolation + // from SubscribeSync if the server returns a permissions error for a subscription. + // Defaults to false. + PermissionErrOnSubscribe bool + + // WebSocketConnectionHeaders is an optional http request headers to be sent with the WebSocket request. + WebSocketConnectionHeaders http.Header + + // WebSocketConnectionHeadersHandler is an optional callback handler for generating token used for WebSocket connections. + WebSocketConnectionHeadersHandler WebSocketHeadersHandler + + // SkipSubjectValidation will disable publish subject validation. + // NOTE: This is not recommended in general, as the performance gain is minimal + // and may lead to breaking protocol. + SkipSubjectValidation bool } const ( @@ -431,8 +557,10 @@ const ( // NUID size nuidSize = 22 - // Default port used if none is specified in given URL(s) - defaultPortString = "4222" + // Default ports used if none is specified in given URL(s) + defaultWSPortString = "80" + defaultWSSPortString = "443" + defaultPortString = "4222" ) // A Conn represents a bare connection to a nats-server. @@ -447,40 +575,62 @@ type Conn struct { mu sync.RWMutex // Opts holds the configuration of the Conn. // Modifying the configuration of a running Conn is a race. - Opts Options - wg sync.WaitGroup - srvPool []*srv - current *srv - urls map[string]struct{} // Keep track of all known URLs (used by processInfo) - conn net.Conn - bw *bufio.Writer - pending *bytes.Buffer - fch chan struct{} - info serverInfo - ssid int64 - subsMu sync.RWMutex - subs map[int64]*Subscription - ach *asyncCallbacksHandler - pongs []chan struct{} - scratch [scratchSize]byte - status Status - initc bool // true if the connection is performing the initial connect - err error - ps *parseState - ptmr *time.Timer - pout int - ar bool // abort reconnect - rqch chan struct{} + Opts Options + wg sync.WaitGroup + srvPool []*srv + current *srv + urls map[string]struct{} // Keep track of all known URLs (used by processInfo) + conn net.Conn + bw *natsWriter + br *natsReader + fch chan struct{} + info serverInfo + ssid int64 + subsMu sync.RWMutex + subs map[int64]*Subscription + ach *asyncCallbacksHandler + pongs []chan struct{} + scratch [scratchSize]byte + status Status + statListeners map[Status]map[chan Status]struct{} + initc bool // true if the connection is performing the initial connect + err error + ps *parseState + ptmr *time.Timer + pout int + ar bool // abort reconnect + rqch chan struct{} + ws bool // true if a websocket connection // New style response handler - respSub string // The wildcard subject - respScanf string // The scanf template to extract mux token - respMux *Subscription // A single response subscription - respMap map[string]chan *Msg // Request map for the response msg channels - respRand *rand.Rand // Used for generating suffix + respSub string // The wildcard subject + respSubPrefix string // the wildcard prefix including trailing . + respSubLen int // the length of the wildcard prefix excluding trailing . + respMux *Subscription // A single response subscription + respMap map[string]chan *Msg // Request map for the response msg channels + respRand *rand.Rand // Used for generating suffix + + // Msg filters for testing. + // Protected by subsMu + filters map[string]msgFilter +} + +type natsReader struct { + r io.Reader + buf []byte + off int + n int } -// A Subscription represents interest in a given subject. +type natsWriter struct { + w io.Writer + bufs []byte + limit int + pending *bytes.Buffer + plimit int +} + +// Subscription represents interest in a given subject. type Subscription struct { mu sync.Mutex sid int64 @@ -494,18 +644,22 @@ type Subscription struct { // only be processed by one member of the group. Queue string - // ConsumerConfig is the configuration for the JetStream consumer if one was created - // or updated using the subscription options - ConsumerConfig *ConsumerConfig - - delivered uint64 - max uint64 - conn *Conn - mcb MsgHandler - mch chan *Msg - closed bool - sc bool - connClosed bool + // For holding information about a JetStream consumer. + jsi *jsSub + + delivered uint64 + max uint64 + conn *Conn + mcb MsgHandler + mch chan *Msg + errCh chan (error) + closed bool + sc bool + connClosed bool + draining bool + status SubStatus + statListeners map[chan SubStatus][]SubStatus + permissionsErr error // Type of Subscription typ SubscriptionType @@ -514,6 +668,7 @@ type Subscription struct { pHead *Msg pTail *Msg pCond *sync.Cond + pDone func(subject string) // Pending stats, async subscriptions, high-speed etc. pMsgs int @@ -525,16 +680,99 @@ type Subscription struct { dropped int } -// Msg is a structure used by Subscribers and PublishMsg(). +// Status represents the state of the connection. +type SubStatus int + +const ( + SubscriptionActive = SubStatus(iota) + SubscriptionDraining + SubscriptionClosed + SubscriptionSlowConsumer +) + +func (s SubStatus) String() string { + switch s { + case SubscriptionActive: + return "Active" + case SubscriptionDraining: + return "Draining" + case SubscriptionClosed: + return "Closed" + case SubscriptionSlowConsumer: + return "SlowConsumer" + } + return "unknown status" +} + +// Msg represents a message delivered by NATS. This structure is used +// by Subscribers and PublishMsg(). +// +// # Types of Acknowledgements +// +// In case using JetStream, there are multiple ways to ack a Msg: +// +// // Acknowledgement that a message has been processed. +// msg.Ack() +// +// // Negatively acknowledges a message. +// msg.Nak() +// +// // Terminate a message so that it is not redelivered further. +// msg.Term() +// +// // Signal the server that the message is being worked on and reset redelivery timer. +// msg.InProgress() type Msg struct { Subject string Reply string - Header http.Header + Header Header Data []byte Sub *Subscription + // Internal next *Msg + wsz int barrier *barrierInfo - jsMeta *JetStreamMsgMetaData + ackd uint32 +} + +// Compares two msgs, ignores sub but checks all other public fields. +func (m *Msg) Equal(msg *Msg) bool { + if m == msg { + return true + } + if m == nil || msg == nil { + return false + } + if m.Subject != msg.Subject || m.Reply != msg.Reply { + return false + } + if !bytes.Equal(m.Data, msg.Data) { + return false + } + if len(m.Header) != len(msg.Header) { + return false + } + for k, v := range m.Header { + val, ok := msg.Header[k] + if !ok || len(v) != len(val) { + return false + } + for i, hdr := range v { + if hdr != val[i] { + return false + } + } + } + return true +} + +// Size returns a message size in bytes. +func (m *Msg) Size() int { + if m.wsz != 0 { + return m.wsz + } + hdr, _ := m.headerBytes() + return len(m.Subject) + len(m.Reply) + len(hdr) + len(m.Data) } func (m *Msg) headerBytes() ([]byte, error) { @@ -549,7 +787,7 @@ func (m *Msg) headerBytes() ([]byte, error) { return nil, ErrBadHeaderMsg } - err = m.Header.Write(&b) + err = http.Header(m.Header).Write(&b) if err != nil { return nil, ErrBadHeaderMsg } @@ -590,19 +828,21 @@ type srv struct { // The INFO block received from the server. type serverInfo struct { ID string `json:"server_id"` - Host string `json:"host"` - Port uint `json:"port"` + Name string `json:"server_name"` + Proto int `json:"proto"` Version string `json:"version"` - AuthRequired bool `json:"auth_required"` - TLSRequired bool `json:"tls_required"` - TLSAvailable bool `json:"tls_available"` + Host string `json:"host"` + Port int `json:"port"` Headers bool `json:"headers"` + AuthRequired bool `json:"auth_required,omitempty"` + TLSRequired bool `json:"tls_required,omitempty"` + TLSAvailable bool `json:"tls_available,omitempty"` MaxPayload int64 `json:"max_payload"` - ConnectURLs []string `json:"connect_urls,omitempty"` - Proto int `json:"proto,omitempty"` CID uint64 `json:"client_id,omitempty"` ClientIP string `json:"client_ip,omitempty"` Nonce string `json:"nonce,omitempty"` + Cluster string `json:"cluster,omitempty"` + ConnectURLs []string `json:"connect_urls,omitempty"` LameDuckMode bool `json:"ldm,omitempty"` } @@ -642,6 +882,8 @@ type MsgHandler func(msg *Msg) // The url can contain username/password semantics. e.g. nats://derek:pass@localhost:4222 // Comma separated arrays are also supported, e.g. urlA, urlB. // Options start with the defaults but can be overridden. +// To connect to a NATS Server's websocket port, use the `ws` or `wss` scheme, such as +// `ws://localhost:8080`. Note that websocket schemes cannot be mixed with others (nats/tls). func Connect(url string, options ...Option) (*Conn, error) { opts := GetDefaultOptions() opts.Servers = processUrlString(url) @@ -665,9 +907,18 @@ func Name(name string) Option { } } +// InProcessServer is an Option that will try to establish a direction to a NATS server +// running within the process instead of dialing via TCP. +func InProcessServer(server InProcessConnProvider) Option { + return func(o *Options) error { + o.InProcessServer = server + return nil + } +} + // Secure is an Option to enable TLS secure connections that skip server verification by default. // Pass a TLS Configuration for proper TLS. -// NOTE: This should NOT be used in a production setting. +// A TLS Configuration using InsecureSkipVerify should NOT be used in a production setting. func Secure(tls ...*tls.Config) Option { return func(o *Options) error { o.Secure = true @@ -682,25 +933,65 @@ func Secure(tls ...*tls.Config) Option { } } +// ClientTLSConfig is an Option to set the TLS configuration for secure +// connections. It can be used to e.g. set TLS config with cert and root CAs +// from memory. For simple use case of loading cert and CAs from file, +// ClientCert and RootCAs options are more convenient. +// If Secure is not already set this will set it as well. +func ClientTLSConfig(certCB TLSCertHandler, rootCAsCB RootCAsHandler) Option { + return func(o *Options) error { + o.Secure = true + + if certCB == nil && rootCAsCB == nil { + return ErrClientCertOrRootCAsRequired + } + + // Smoke test the callbacks to fail early + // if they are not valid. + if certCB != nil { + if _, err := certCB(); err != nil { + return err + } + } + if rootCAsCB != nil { + if _, err := rootCAsCB(); err != nil { + return err + } + } + if o.TLSConfig == nil { + o.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12} + } + o.TLSCertCB = certCB + o.RootCAsCB = rootCAsCB + return nil + } +} + // RootCAs is a helper option to provide the RootCAs pool from a list of filenames. // If Secure is not already set this will set it as well. func RootCAs(file ...string) Option { return func(o *Options) error { - pool := x509.NewCertPool() - for _, f := range file { - rootPEM, err := ioutil.ReadFile(f) - if err != nil || rootPEM == nil { - return fmt.Errorf("nats: error loading or parsing rootCA file: %v", err) - } - ok := pool.AppendCertsFromPEM(rootPEM) - if !ok { - return fmt.Errorf("nats: failed to parse root certificate from %q", f) + rootCAsCB := func() (*x509.CertPool, error) { + pool := x509.NewCertPool() + for _, f := range file { + rootPEM, err := os.ReadFile(f) + if err != nil || rootPEM == nil { + return nil, fmt.Errorf("nats: error loading or parsing rootCA file: %w", err) + } + ok := pool.AppendCertsFromPEM(rootPEM) + if !ok { + return nil, fmt.Errorf("nats: failed to parse root certificate from %q", f) + } } + return pool, nil } if o.TLSConfig == nil { o.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12} } - o.TLSConfig.RootCAs = pool + if _, err := rootCAsCB(); err != nil { + return err + } + o.RootCAsCB = rootCAsCB o.Secure = true return nil } @@ -710,18 +1001,24 @@ func RootCAs(file ...string) Option { // If Secure is not already set this will set it as well. func ClientCert(certFile, keyFile string) Option { return func(o *Options) error { - cert, err := tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - return fmt.Errorf("nats: error loading client certificate: %v", err) - } - cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) - if err != nil { - return fmt.Errorf("nats: error parsing client certificate: %v", err) + tlsCertCB := func() (tls.Certificate, error) { + cert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return tls.Certificate{}, fmt.Errorf("nats: error loading client certificate: %w", err) + } + cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return tls.Certificate{}, fmt.Errorf("nats: error parsing client certificate: %w", err) + } + return cert, nil } if o.TLSConfig == nil { o.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12} } - o.TLSConfig.Certificates = []tls.Certificate{cert} + if _, err := tlsCertCB(); err != nil { + return err + } + o.TLSCertCB = tlsCertCB o.Secure = true return nil } @@ -753,6 +1050,7 @@ func NoEcho() Option { } // ReconnectWait is an Option to set the wait time between reconnect attempts. +// Defaults to 2s. func ReconnectWait(t time.Duration) Option { return func(o *Options) error { o.ReconnectWait = t @@ -761,6 +1059,8 @@ func ReconnectWait(t time.Duration) Option { } // MaxReconnects is an Option to set the maximum number of reconnect attempts. +// If negative, it will never stop trying to reconnect. +// Defaults to 60. func MaxReconnects(max int) Option { return func(o *Options) error { o.MaxReconnect = max @@ -769,6 +1069,7 @@ func MaxReconnects(max int) Option { } // ReconnectJitter is an Option to set the upper bound of a random delay added ReconnectWait. +// Defaults to 100ms and 1s, respectively. func ReconnectJitter(jitter, jitterForTLS time.Duration) Option { return func(o *Options) error { o.ReconnectJitter = jitter @@ -787,6 +1088,7 @@ func CustomReconnectDelay(cb ReconnectDelayHandler) Option { } // PingInterval is an Option to set the period for client ping commands. +// Defaults to 2m. func PingInterval(t time.Duration) Option { return func(o *Options) error { o.PingInterval = t @@ -795,7 +1097,8 @@ func PingInterval(t time.Duration) Option { } // MaxPingsOutstanding is an Option to set the maximum number of ping requests -// that can go un-answered by the server before closing the connection. +// that can go unanswered by the server before closing the connection. +// Defaults to 2. func MaxPingsOutstanding(max int) Option { return func(o *Options) error { o.MaxPingsOut = max @@ -804,6 +1107,7 @@ func MaxPingsOutstanding(max int) Option { } // ReconnectBufSize sets the buffer size of messages kept while busy reconnecting. +// Defaults to 8388608 bytes (8MB). It can be disabled by setting it to -1. func ReconnectBufSize(size int) Option { return func(o *Options) error { o.ReconnectBufSize = size @@ -812,6 +1116,7 @@ func ReconnectBufSize(size int) Option { } // Timeout is an Option to set the timeout for Dial on a connection. +// Defaults to 2s. func Timeout(t time.Duration) Option { return func(o *Options) error { o.Timeout = t @@ -819,14 +1124,6 @@ func Timeout(t time.Duration) Option { } } -// JetStreamTimeout is an Option to set the timeout for access to the JetStream API -func JetStreamTimeout(t time.Duration) Option { - return func(o *Options) error { - o.JetStreamTimeout = t - return nil - } -} - // FlusherTimeout is an Option to set the write (and flush) timeout on a connection. func FlusherTimeout(t time.Duration) Option { return func(o *Options) error { @@ -836,6 +1133,7 @@ func FlusherTimeout(t time.Duration) Option { } // DrainTimeout is an Option to set the timeout for draining a connection. +// Defaults to 30s. func DrainTimeout(t time.Duration) Option { return func(o *Options) error { o.DrainTimeout = t @@ -852,7 +1150,7 @@ func DisconnectErrHandler(cb ConnErrHandler) Option { } // DisconnectHandler is an Option to set the disconnected handler. -// DEPRECATED: Use DisconnectErrHandler. +// Deprecated: Use DisconnectErrHandler. func DisconnectHandler(cb ConnHandler) Option { return func(o *Options) error { o.DisconnectedCB = cb @@ -860,6 +1158,14 @@ func DisconnectHandler(cb ConnHandler) Option { } } +// ConnectHandler is an Option to set the connected handler. +func ConnectHandler(cb ConnHandler) Option { + return func(o *Options) error { + o.ConnectedCB = cb + return nil + } +} + // ReconnectHandler is an Option to set the reconnected handler. func ReconnectHandler(cb ConnHandler) Option { return func(o *Options) error { @@ -868,6 +1174,14 @@ func ReconnectHandler(cb ConnHandler) Option { } } +// ReconnectErrHandler is an Option to set the reconnect error handler. +func ReconnectErrHandler(cb ConnErrHandler) Option { + return func(o *Options) error { + o.ReconnectErrCB = cb + return nil + } +} + // ClosedHandler is an Option to set the closed handler. func ClosedHandler(cb ConnHandler) Option { return func(o *Options) error { @@ -902,6 +1216,13 @@ func UserInfo(user, password string) Option { } } +func UserInfoHandler(cb UserInfoCB) Option { + return func(o *Options) error { + o.UserInfo = cb + return nil + } +} + // Token is an Option to set the token to use // when a token is not included directly in the URLs // and when a token handler is not provided. @@ -946,6 +1267,57 @@ func UserCredentials(userOrChainedFile string, seedFiles ...string) Option { return UserJWT(userCB, sigCB) } +// UserCredentialBytes is a convenience function that takes the JWT and seed +// values as byte slices. This allows passing credentials directly from memory +// or environment variables without needing to write them to disk. +func UserCredentialBytes(userOrChainedFileBytes []byte, seedFiles ...[]byte) Option { + userCB := func() (string, error) { + return nkeys.ParseDecoratedJWT(userOrChainedFileBytes) + } + + var seedBytes []byte + if len(seedFiles) > 0 { + seedBytes = seedFiles[0] + } else { + seedBytes = userOrChainedFileBytes + } + + sigCB := func(nonce []byte) ([]byte, error) { + kp, err := nkeys.ParseDecoratedNKey(seedBytes) + if err != nil { + return nil, fmt.Errorf("unable to extract key pair from bytes: %w", err) + } + defer kp.Wipe() + + sig, _ := kp.Sign(nonce) + return sig, nil + } + + return UserJWT(userCB, sigCB) +} + +// UserJWTAndSeed is a convenience function that takes the JWT and seed +// values as strings. +func UserJWTAndSeed(jwt string, seed string) Option { + userCB := func() (string, error) { + return jwt, nil + } + + sigCB := func(nonce []byte) ([]byte, error) { + kp, err := nkeys.FromSeed([]byte(seed)) + if err != nil { + return nil, fmt.Errorf("unable to extract key pair from seed: %w", err) + } + // Wipe our key on exit. + defer kp.Wipe() + + sig, _ := kp.Sign(nonce) + return sig, nil + } + + return UserJWT(userCB, sigCB) +} + // UserJWT will set the callbacks to retrieve the user's JWT and // the signature callback to sign the server nonce. This an the Nkey // option are mutually exclusive. @@ -957,6 +1329,12 @@ func UserJWT(userCB UserJWTHandler, sigCB SignatureHandler) Option { if sigCB == nil { return ErrUserButNoSigCB } + // Smoke test the user callback to ensure it is setup properly + // when processing options. + if _, err := userCB(); err != nil { + return err + } + o.UserJWT = userCB o.SignatureCB = sigCB return nil @@ -978,6 +1356,7 @@ func Nkey(pubKey string, sigCB SignatureHandler) Option { // SyncQueueLen will set the maximum queue len for the internal // channel used for SubscribeSync(). +// Defaults to 65536. func SyncQueueLen(max int) Option { return func(o *Options) error { o.SubChanLen = max @@ -987,7 +1366,7 @@ func SyncQueueLen(max int) Option { // Dialer is an Option to set the dialer which will be used when // attempting to establish a connection. -// DEPRECATED: Should use CustomDialer instead. +// Deprecated: Should use CustomDialer instead. func Dialer(dialer *net.Dialer) Option { return func(o *Options) error { o.Dialer = dialer @@ -1025,7 +1404,7 @@ func NoCallbacksAfterClientClose() Option { // LameDuckModeHandler sets the callback to invoke when the server notifies // the connection that it entered lame duck mode, that is, going to -// gradually disconnect all its connections before shuting down. This is +// gradually disconnect all its connections before shutting down. This is // often used in deployments when upgrading NATS Servers. func LameDuckModeHandler(cb ConnHandler) Option { return func(o *Options) error { @@ -1044,10 +1423,118 @@ func RetryOnFailedConnect(retry bool) Option { } } +// Compression is an Option to indicate if this connection supports +// compression. Currently only supported for Websocket connections. +func Compression(enabled bool) Option { + return func(o *Options) error { + o.Compression = enabled + return nil + } +} + +// ProxyPath is an option for websocket connections that adds a path to connections url. +// This is useful when connecting to NATS behind a proxy. +func ProxyPath(path string) Option { + return func(o *Options) error { + o.ProxyPath = path + return nil + } +} + +// CustomInboxPrefix configures the request + reply inbox prefix +func CustomInboxPrefix(p string) Option { + return func(o *Options) error { + if p == "" || strings.Contains(p, ">") || strings.Contains(p, "*") || strings.HasSuffix(p, ".") { + return errors.New("nats: invalid custom prefix") + } + o.InboxPrefix = p + return nil + } +} + +// IgnoreAuthErrorAbort opts out of the default connect behavior of aborting +// subsequent reconnect attempts if server returns the same auth error twice. +func IgnoreAuthErrorAbort() Option { + return func(o *Options) error { + o.IgnoreAuthErrorAbort = true + return nil + } +} + +// SkipHostLookup is an Option to skip the host lookup when connecting to a server. +func SkipHostLookup() Option { + return func(o *Options) error { + o.SkipHostLookup = true + return nil + } +} + +func PermissionErrOnSubscribe(enabled bool) Option { + return func(o *Options) error { + o.PermissionErrOnSubscribe = enabled + return nil + } +} + +// TLSHandshakeFirst is an Option to perform the TLS handshake first, that is +// before receiving the INFO protocol. This requires the server to also be +// configured with such option, otherwise the connection will fail. +func TLSHandshakeFirst() Option { + return func(o *Options) error { + o.TLSHandshakeFirst = true + o.Secure = true + return nil + } +} + +// WebSocketConnectionHeaders sets a fixed set of HTTP headers that will be +// sent during the WebSocket connection handshake. +// This option is mutually exclusive with WebSocketConnectionHeadersHandler; +// if a headers handler has already been configured, it returns +// ErrWebSocketHeadersAlreadySet. +func WebSocketConnectionHeaders(headers http.Header) Option { + return func(o *Options) error { + if o.WebSocketConnectionHeadersHandler != nil { + return ErrWebSocketHeadersAlreadySet + } + o.WebSocketConnectionHeaders = headers + return nil + } +} + +// WebSocketConnectionHeadersHandler registers a callback used to supply HTTP +// headers for the WebSocket connection handshake. +// This option is mutually exclusive with WebSocketConnectionHeaders; if +// non-empty static headers have already been configured, it returns +// ErrWebSocketHeadersAlreadySet. +func WebSocketConnectionHeadersHandler(cb WebSocketHeadersHandler) Option { + return func(o *Options) error { + if len(o.WebSocketConnectionHeaders) != 0 { + return ErrWebSocketHeadersAlreadySet + } + o.WebSocketConnectionHeadersHandler = cb + return nil + } +} + +// SkipSubjectValidation is an Option to skip subject validation when +// publishing messages. +// By default, subject validation is performed to ensure that subjects +// are valid according to NATS subject syntax (no spaces newlines and tabs). +// NOTE: It is not recommended to use this option as the performance gain +// is minimal and disabling subject validation can lead breaking protocol +// rules. +func SkipSubjectValidation() Option { + return func(o *Options) error { + o.SkipSubjectValidation = true + return nil + } +} + // Handler processing // SetDisconnectHandler will set the disconnect event handler. -// DEPRECATED: Use SetDisconnectErrHandler +// Deprecated: Use SetDisconnectErrHandler func (nc *Conn) SetDisconnectHandler(dcb ConnHandler) { if nc == nil { return @@ -1067,6 +1554,16 @@ func (nc *Conn) SetDisconnectErrHandler(dcb ConnErrHandler) { nc.Opts.DisconnectedErrCB = dcb } +// DisconnectErrHandler will return the disconnect event handler. +func (nc *Conn) DisconnectErrHandler() ConnErrHandler { + if nc == nil { + return nil + } + nc.mu.Lock() + defer nc.mu.Unlock() + return nc.Opts.DisconnectedErrCB +} + // SetReconnectHandler will set the reconnect event handler. func (nc *Conn) SetReconnectHandler(rcb ConnHandler) { if nc == nil { @@ -1077,6 +1574,16 @@ func (nc *Conn) SetReconnectHandler(rcb ConnHandler) { nc.Opts.ReconnectedCB = rcb } +// ReconnectHandler will return the reconnect event handler. +func (nc *Conn) ReconnectHandler() ConnHandler { + if nc == nil { + return nil + } + nc.mu.Lock() + defer nc.mu.Unlock() + return nc.Opts.ReconnectedCB +} + // SetDiscoveredServersHandler will set the discovered servers handler. func (nc *Conn) SetDiscoveredServersHandler(dscb ConnHandler) { if nc == nil { @@ -1087,7 +1594,17 @@ func (nc *Conn) SetDiscoveredServersHandler(dscb ConnHandler) { nc.Opts.DiscoveredServersCB = dscb } -// SetClosedHandler will set the reconnect event handler. +// DiscoveredServersHandler will return the discovered servers handler. +func (nc *Conn) DiscoveredServersHandler() ConnHandler { + if nc == nil { + return nil + } + nc.mu.Lock() + defer nc.mu.Unlock() + return nc.Opts.DiscoveredServersCB +} + +// SetClosedHandler will set the closed event handler. func (nc *Conn) SetClosedHandler(cb ConnHandler) { if nc == nil { return @@ -1097,6 +1614,16 @@ func (nc *Conn) SetClosedHandler(cb ConnHandler) { nc.Opts.ClosedCB = cb } +// ClosedHandler will return the closed event handler. +func (nc *Conn) ClosedHandler() ConnHandler { + if nc == nil { + return nil + } + nc.mu.Lock() + defer nc.mu.Unlock() + return nc.Opts.ClosedCB +} + // SetErrorHandler will set the async error handler. func (nc *Conn) SetErrorHandler(cb ErrHandler) { if nc == nil { @@ -1107,14 +1634,29 @@ func (nc *Conn) SetErrorHandler(cb ErrHandler) { nc.Opts.AsyncErrorCB = cb } +// ErrorHandler will return the async error handler. +func (nc *Conn) ErrorHandler() ErrHandler { + if nc == nil { + return nil + } + nc.mu.Lock() + defer nc.mu.Unlock() + return nc.Opts.AsyncErrorCB +} + // Process the url string argument to Connect. // Return an array of urls, even if only one. func processUrlString(url string) []string { urls := strings.Split(url, ",") - for i, s := range urls { - urls[i] = strings.TrimSpace(s) + var j int + for _, s := range urls { + u := strings.TrimSuffix(strings.TrimSpace(s), "/") + if len(u) > 0 { + urls[j] = u + j++ + } } - return urls + return urls[:j] } // Connect will attempt to connect to a NATS server with multiple options. @@ -1148,13 +1690,19 @@ func (o Options) Connect() (*Conn, error) { return nil, ErrNkeyButNoSigCB } - // Allow custom Dialer for connecting using DialTimeout by default + // Allow custom Dialer for connecting using a timeout by default if nc.Opts.Dialer == nil { nc.Opts.Dialer = &net.Dialer{ Timeout: nc.Opts.Timeout, } } + // If the TLSHandshakeFirst option is specified, make sure that + // the Secure boolean is true. + if nc.Opts.TLSHandshakeFirst { + nc.Opts.Secure = true + } + if err := nc.setupServerPool(); err != nil { return nil, err } @@ -1163,16 +1711,58 @@ func (o Options) Connect() (*Conn, error) { nc.ach = &asyncCallbacksHandler{} nc.ach.cond = sync.NewCond(&nc.ach.mu) - if err := nc.connect(); err != nil { - return nil, err + // Set a default error handler that will print to stderr. + if nc.Opts.AsyncErrorCB == nil { + nc.Opts.AsyncErrorCB = defaultErrHandler } - // Spin up the async cb dispatcher on success + // Create reader/writer + nc.newReaderWriter() + + // Spin up the async cb dispatcher before connect so it's ready + // to handle callbacks, especially when RetryOnFailedConnect is used + // and initial connection fails. go nc.ach.asyncCBDispatcher() + connectionEstablished, err := nc.connect() + if err != nil { + nc.ach.close() + return nil, err + } + + if connectionEstablished { + if connectedCB := nc.Opts.ConnectedCB; connectedCB != nil { + nc.ach.push(func() { connectedCB(nc) }) + } + } + return nc, nil } +func defaultErrHandler(nc *Conn, sub *Subscription, err error) { + var cid uint64 + if nc != nil { + nc.mu.RLock() + cid = nc.info.CID + nc.mu.RUnlock() + } + var errStr string + if sub != nil { + var subject string + sub.mu.Lock() + if sub.jsi != nil { + subject = sub.jsi.psubj + } else { + subject = sub.Subject + } + sub.mu.Unlock() + errStr = fmt.Sprintf("%s on connection [%d] for subscription on %q\n", err.Error(), cid, subject) + } else { + errStr = fmt.Sprintf("%s on connection [%d]\n", err.Error(), cid) + } + os.Stderr.WriteString(errStr) +} + const ( _CRLF_ = "\r\n" _EMPTY_ = "" @@ -1181,6 +1771,8 @@ const ( _HPUB_P_ = "HPUB " ) +var _CRLF_BYTES_ = []byte(_CRLF_) + const ( _OK_OP_ = "+OK" _ERR_OP_ = "-ERR" @@ -1294,7 +1886,7 @@ func (nc *Conn) setupServerPool() error { // Check for Scheme hint to move to TLS mode. for _, srv := range nc.srvPool { - if srv.url.Scheme == tlsScheme { + if srv.url.Scheme == tlsScheme || srv.url.Scheme == wsSchemeTLS { // FIXME(dlc), this is for all in the pool, should be case by case. nc.Opts.Secure = true if nc.Opts.TLSConfig == nil { @@ -1308,6 +1900,12 @@ func (nc *Conn) setupServerPool() error { // Helper function to return scheme func (nc *Conn) connScheme() string { + if nc.ws { + if nc.Opts.Secure { + return wsSchemeTLS + } + return wsScheme + } if nc.Opts.Secure { return tlsScheme } @@ -1341,7 +1939,24 @@ func (nc *Conn) addURLToPool(sURL string, implicit, saveTLSName bool) error { if sURL[len(sURL)-1] != ':' { sURL += ":" } - sURL += defaultPortString + switch u.Scheme { + case wsScheme: + sURL += defaultWSPortString + case wsSchemeTLS: + sURL += defaultWSSPortString + default: + sURL += defaultPortString + } + } + + isWS := isWebsocketScheme(u) + // We don't support mix and match of websocket and non websocket URLs. + // If this is the first URL, then we accept and switch the global state + // to websocket. After that, we will know how to reject mixed URLs. + if len(nc.srvPool) == 0 { + nc.ws = isWS + } else if isWS && !nc.ws || !isWS && nc.ws { + return errors.New("mixing of websocket and non websocket URLs is not allowed") } var tlsName string @@ -1381,12 +1996,156 @@ func (nc *Conn) shufflePool(offset int) { } } -func (nc *Conn) newBuffer() *bufio.Writer { +func (nc *Conn) newReaderWriter() { + nc.br = &natsReader{ + buf: make([]byte, defaultBufSize), + off: -1, + } + nc.bw = &natsWriter{ + limit: defaultBufSize, + plimit: nc.Opts.ReconnectBufSize, + } +} + +func (nc *Conn) bindToNewConn() { + bw := nc.bw + bw.w, bw.bufs = nc.newWriter(), nil + br := nc.br + br.r, br.n, br.off = nc.conn, 0, -1 +} + +func (nc *Conn) newWriter() io.Writer { var w io.Writer = nc.conn if nc.Opts.FlusherTimeout > 0 { w = &timeoutWriter{conn: nc.conn, timeout: nc.Opts.FlusherTimeout} } - return bufio.NewWriterSize(w, defaultBufSize) + return w +} + +func (w *natsWriter) appendString(str string) error { + return w.appendBufs([]byte(str)) +} + +func (w *natsWriter) appendBufs(bufs ...[]byte) error { + for _, buf := range bufs { + if len(buf) == 0 { + continue + } + if w.pending != nil { + w.pending.Write(buf) + } else { + w.bufs = append(w.bufs, buf...) + } + } + if w.pending == nil && len(w.bufs) >= w.limit { + return w.flush() + } + return nil +} + +func (w *natsWriter) writeDirect(strs ...string) error { + for _, str := range strs { + if _, err := w.w.Write([]byte(str)); err != nil { + return err + } + } + return nil +} + +func (w *natsWriter) flush() error { + // If a pending buffer is set, we don't flush. Code that needs to + // write directly to the socket, by-passing buffers during (re)connect, + // will use the writeDirect() API. + if w.pending != nil { + return nil + } + // Do not skip calling w.w.Write() here if len(w.bufs) is 0 because + // the actual writer (if websocket for instance) may have things + // to do such as sending control frames, etc.. + _, err := w.w.Write(w.bufs) + w.bufs = w.bufs[:0] + return err +} + +func (w *natsWriter) buffered() int { + if w.pending != nil { + return w.pending.Len() + } + return len(w.bufs) +} + +func (w *natsWriter) switchToPending() { + w.pending = new(bytes.Buffer) +} + +func (w *natsWriter) flushPendingBuffer() error { + if w.pending == nil || w.pending.Len() == 0 { + return nil + } + _, err := w.w.Write(w.pending.Bytes()) + // Reset the pending buffer at this point because we don't want + // to take the risk of sending duplicates or partials. + w.pending.Reset() + return err +} + +func (w *natsWriter) atLimitIfUsingPending() bool { + if w.pending == nil { + return false + } + return w.pending.Len() >= w.plimit +} + +func (w *natsWriter) doneWithPending() { + w.pending = nil +} + +// Notify the reader that we are done with the connect, where "read" operations +// happen synchronously and under the connection lock. After this point, "read" +// will be happening from the read loop, without the connection lock. +// +// Note: this runs under the connection lock. +func (r *natsReader) doneWithConnect() { + if wsr, ok := r.r.(*websocketReader); ok { + wsr.doneWithConnect() + } +} + +func (r *natsReader) Read() ([]byte, error) { + if r.off >= 0 { + off := r.off + r.off = -1 + return r.buf[off:r.n], nil + } + var err error + r.n, err = r.r.Read(r.buf) + return r.buf[:r.n], err +} + +func (r *natsReader) ReadString(delim byte) (string, error) { + var s string +build_string: + // First look if we have something in the buffer + if r.off >= 0 { + i := bytes.IndexByte(r.buf[r.off:r.n], delim) + if i >= 0 { + end := r.off + i + 1 + s += string(r.buf[r.off:end]) + r.off = end + if r.off >= r.n { + r.off = -1 + } + return s, nil + } + // We did not find the delim, so will have to read more. + s += string(r.buf[r.off:r.n]) + r.off = -1 + } + if _, err := r.Read(); err != nil { + return s, err + } + r.off = 0 + goto build_string } // createConn will connect to the server and wrap the appropriate @@ -1400,11 +2159,23 @@ func (nc *Conn) createConn() (err error) { return ErrNoServers } + // If we have a reference to an in-process server then establish a + // connection using that. + if nc.Opts.InProcessServer != nil { + conn, err := nc.Opts.InProcessServer.InProcessConn() + if err != nil { + return fmt.Errorf("failed to get in-process connection: %w", err) + } + nc.conn = conn + nc.bindToNewConn() + return nil + } + // We will auto-expand host names if they resolve to multiple IPs hosts := []string{} u := nc.current.url - if net.ParseIP(u.Hostname()) == nil { + if !nc.Opts.SkipHostLookup && net.ParseIP(u.Hostname()) == nil { addrs, _ := net.LookupHost(u.Hostname()) for _, addr := range addrs { hosts = append(hosts, net.JoinHostPort(addr, u.Port())) @@ -1441,22 +2212,47 @@ func (nc *Conn) createConn() (err error) { return err } - if nc.pending != nil && nc.bw != nil { - // Move to pending buffer. - nc.bw.Flush() + // If scheme starts with "ws" then branch out to websocket code. + if isWebsocketScheme(u) { + return nc.wsInitHandshake(u) } - nc.bw = nc.newBuffer() + + // Reset reader/writer to this new TCP connection + nc.bindToNewConn() return nil } +type skipTLSDialer interface { + SkipTLSHandshake() bool +} + // makeTLSConn will wrap an existing Conn using TLS func (nc *Conn) makeTLSConn() error { + if nc.Opts.CustomDialer != nil { + // we do nothing when asked to skip the TLS wrapper + sd, ok := nc.Opts.CustomDialer.(skipTLSDialer) + if ok && sd.SkipTLSHandshake() { + return nil + } + } // Allow the user to configure their own tls.Config structure. - var tlsCopy *tls.Config + tlsCopy := &tls.Config{} if nc.Opts.TLSConfig != nil { tlsCopy = util.CloneTLSConfig(nc.Opts.TLSConfig) - } else { - tlsCopy = &tls.Config{} + } + if nc.Opts.TLSCertCB != nil { + cert, err := nc.Opts.TLSCertCB() + if err != nil { + return err + } + tlsCopy.Certificates = []tls.Certificate{cert} + } + if nc.Opts.RootCAsCB != nil { + rootCAs, err := nc.Opts.RootCAsCB() + if err != nil { + return err + } + tlsCopy.RootCAs = rootCAs } // If its blank we will override it with the current host if tlsCopy.ServerName == _EMPTY_ { @@ -1472,10 +2268,28 @@ func (nc *Conn) makeTLSConn() error { if err := conn.Handshake(); err != nil { return err } - nc.bw = nc.newBuffer() + nc.bindToNewConn() return nil } +// TLSConnectionState retrieves the state of the TLS connection to the server +func (nc *Conn) TLSConnectionState() (tls.ConnectionState, error) { + if !nc.isConnected() { + return tls.ConnectionState{}, ErrDisconnected + } + + nc.mu.RLock() + conn := nc.conn + nc.mu.RUnlock() + + tc, ok := conn.(*tls.Conn) + if !ok { + return tls.ConnectionState{}, ErrConnectionNotTLS + } + + return tc.ConnectionState(), nil +} + // waitForExits will wait for all socket watcher Go routines to // be shutdown before proceeding. func (nc *Conn) waitForExits() { @@ -1489,7 +2303,49 @@ func (nc *Conn) waitForExits() { nc.wg.Wait() } -// Report the connected server's Url +// ForceReconnect forces a reconnect attempt to the server. +// This is a non-blocking call and will start the reconnect +// process without waiting for it to complete. +// +// If the connection is already in the process of reconnecting, +// this call will force an immediate reconnect attempt (bypassing +// the current reconnect delay). +func (nc *Conn) ForceReconnect() error { + nc.mu.Lock() + defer nc.mu.Unlock() + + if nc.isClosed() { + return ErrConnectionClosed + } + if nc.isReconnecting() { + // if we're already reconnecting, force a reconnect attempt + // even if we're in the middle of a backoff + if nc.rqch != nil { + close(nc.rqch) + nc.rqch = nil + } + return nil + } + + // Clear any queued pongs + nc.clearPendingFlushCalls() + + // Clear any queued and blocking requests. + nc.clearPendingRequestCalls() + + // Stop ping timer if set. + nc.stopPingTimer() + + // Go ahead and make sure we have flushed the outbound + nc.bw.flush() + nc.conn.Close() + + nc.changeConnStatus(RECONNECTING) + go nc.doReconnect(nil, true) + return nil +} + +// ConnectedUrl reports the connected server's URL func (nc *Conn) ConnectedUrl() string { if nc == nil { return _EMPTY_ @@ -1504,6 +2360,21 @@ func (nc *Conn) ConnectedUrl() string { return nc.current.url.String() } +// ConnectedUrlRedacted reports the connected server's URL with passwords redacted +func (nc *Conn) ConnectedUrlRedacted() string { + if nc == nil { + return _EMPTY_ + } + + nc.mu.RLock() + defer nc.mu.RUnlock() + + if nc.status != CONNECTED { + return _EMPTY_ + } + return nc.current.url.Redacted() +} + // ConnectedAddr returns the connected server's IP func (nc *Conn) ConnectedAddr() string { if nc == nil { @@ -1516,11 +2387,102 @@ func (nc *Conn) ConnectedAddr() string { if nc.status != CONNECTED { return _EMPTY_ } - return nc.conn.RemoteAddr().String() + return nc.conn.RemoteAddr().String() +} + +// LocalAddr returns the local network address of the connection +func (nc *Conn) LocalAddr() string { + if nc == nil { + return _EMPTY_ + } + + nc.mu.RLock() + defer nc.mu.RUnlock() + + if nc.status != CONNECTED { + return _EMPTY_ + } + return nc.conn.LocalAddr().String() +} + +// ConnectedServerId reports the connected server's Id +func (nc *Conn) ConnectedServerId() string { + if nc == nil { + return _EMPTY_ + } + + nc.mu.RLock() + defer nc.mu.RUnlock() + + if nc.status != CONNECTED { + return _EMPTY_ + } + return nc.info.ID +} + +// ConnectedServerName reports the connected server's name +func (nc *Conn) ConnectedServerName() string { + if nc == nil { + return _EMPTY_ + } + + nc.mu.RLock() + defer nc.mu.RUnlock() + + if nc.status != CONNECTED { + return _EMPTY_ + } + return nc.info.Name +} + +var semVerRe = regexp.MustCompile(`\Av?([0-9]+)\.?([0-9]+)?\.?([0-9]+)?`) + +func versionComponents(version string) (major, minor, patch int, err error) { + m := semVerRe.FindStringSubmatch(version) + if m == nil { + return 0, 0, 0, errors.New("invalid semver") + } + major, err = strconv.Atoi(m[1]) + if err != nil { + return -1, -1, -1, err + } + minor, err = strconv.Atoi(m[2]) + if err != nil { + return -1, -1, -1, err + } + patch, err = strconv.Atoi(m[3]) + if err != nil { + return -1, -1, -1, err + } + return major, minor, patch, err +} + +// Check for minimum server requirement. +func (nc *Conn) serverMinVersion(major, minor, patch int) bool { + smajor, sminor, spatch, _ := versionComponents(nc.ConnectedServerVersion()) + if smajor < major || (smajor == major && sminor < minor) || (smajor == major && sminor == minor && spatch < patch) { + return false + } + return true +} + +// ConnectedServerVersion reports the connected server's version as a string +func (nc *Conn) ConnectedServerVersion() string { + if nc == nil { + return _EMPTY_ + } + + nc.mu.RLock() + defer nc.mu.RUnlock() + + if nc.status != CONNECTED { + return _EMPTY_ + } + return nc.info.Version } -// Report the connected server's Id -func (nc *Conn) ConnectedServerId() string { +// ConnectedClusterName reports the connected server's cluster name if any +func (nc *Conn) ConnectedClusterName() string { if nc == nil { return _EMPTY_ } @@ -1531,7 +2493,7 @@ func (nc *Conn) ConnectedServerId() string { if nc.status != CONNECTED { return _EMPTY_ } - return nc.info.ID + return nc.info.Cluster } // Low level setup for structs, etc @@ -1549,13 +2511,20 @@ func (nc *Conn) setup() { // Process a connected connection and initialize properly. func (nc *Conn) processConnectInit() error { - // Set our deadline for the whole connect process nc.conn.SetDeadline(time.Now().Add(nc.Opts.Timeout)) defer nc.conn.SetDeadline(time.Time{}) // Set our status to connecting. - nc.status = CONNECTING + nc.changeConnStatus(CONNECTING) + + // If we need to have a TLS connection and want the TLS handshake to occur + // first, do it now. + if nc.Opts.Secure && nc.Opts.TLSHandshakeFirst { + if err := nc.makeTLSConn(); err != nil { + return err + } + } // Process the INFO protocol received from the server err := nc.processExpectedInfo() @@ -1587,12 +2556,17 @@ func (nc *Conn) processConnectInit() error { go nc.readLoop() go nc.flusher() + // Notify the reader that we are done with the connect handshake, where + // reads were done synchronously and under the connection lock. + nc.br.doneWithConnect() + return nil } -// Main connect function. Will connect to the nats-server -func (nc *Conn) connect() error { - var returnedErr error +// Main connect function. Will connect to the nats-server. +func (nc *Conn) connect() (bool, error) { + var err error + var connectionEstablished bool // Create actual socket connection // For first connect we walk all servers in the pool and try @@ -1604,7 +2578,7 @@ func (nc *Conn) connect() error { for i := 0; i < len(nc.srvPool); i++ { nc.current = nc.srvPool[i] - if err := nc.createConn(); err == nil { + if err = nc.createConn(); err == nil { // This was moved out of processConnectInit() because // that function is now invoked from doReconnect() too. nc.setup() @@ -1615,10 +2589,8 @@ func (nc *Conn) connect() error { nc.current.didConnect = true nc.current.reconnects = 0 nc.current.lastErr = nil - returnedErr = nil break } else { - returnedErr = err nc.mu.Unlock() nc.close(DISCONNECTED, false, err) nc.mu.Lock() @@ -1630,32 +2602,29 @@ func (nc *Conn) connect() error { // Cancel out default connection refused, will trigger the // No servers error conditional if strings.Contains(err.Error(), "connection refused") { - returnedErr = nil + err = nil } } } - if returnedErr == nil && nc.status != CONNECTED { - returnedErr = ErrNoServers + if err == nil && nc.status != CONNECTED { + err = ErrNoServers } - if returnedErr == nil { + if err == nil { + connectionEstablished = true nc.initc = false } else if nc.Opts.RetryOnFailedConnect { nc.setup() - nc.status = RECONNECTING - nc.pending = new(bytes.Buffer) - if nc.bw == nil { - nc.bw = nc.newBuffer() - } - nc.bw.Reset(nc.pending) - go nc.doReconnect(ErrNoServers) - returnedErr = nil + nc.changeConnStatus(RECONNECTING) + nc.bw.switchToPending() + go nc.doReconnect(err, false) + err = nil } else { nc.current = nil } - return returnedErr + return connectionEstablished, err } // This will check to see if the connection should be @@ -1673,8 +2642,13 @@ func (nc *Conn) checkForSecure() error { o.Secure = true } - // Need to rewrap with bufio if o.Secure { + // If TLS handshake first is true, we have already done + // the handshake, so we are done here. + if o.TLSHandshakeFirst { + return nil + } + // Need to rewrap with bufio if err := nc.makeTLSConn(); err != nil { return err } @@ -1685,7 +2659,6 @@ func (nc *Conn) checkForSecure() error { // processExpectedInfo will look for the expected first INFO message // sent when a connection is established. The lock should be held entering. func (nc *Conn) processExpectedInfo() error { - c := &control{} // Read the protocol @@ -1708,6 +2681,12 @@ func (nc *Conn) processExpectedInfo() error { return ErrNkeysNotSupported } + // For websocket connections, we already switched to TLS if need be, + // so we are done here. + if nc.ws { + return nil + } + return nc.checkForSecure() } @@ -1715,7 +2694,7 @@ func (nc *Conn) processExpectedInfo() error { // and kicking the flush Go routine. These writes are protected. func (nc *Conn) sendProto(proto string) { nc.mu.Lock() - nc.bw.WriteString(proto) + nc.bw.appendString(proto) nc.kickFlusher() nc.mu.Unlock() } @@ -1740,6 +2719,13 @@ func (nc *Conn) connectProto() (string, error) { pass = o.Password token = o.Token nkey = o.Nkey + + if nc.Opts.UserInfo != nil { + if user != _EMPTY_ || pass != _EMPTY_ { + return _EMPTY_, ErrUserInfoAlreadySet + } + user, pass = nc.Opts.UserInfo() + } } // Look for user jwt. @@ -1763,7 +2749,7 @@ func (nc *Conn) connectProto() (string, error) { } sigraw, err := o.SignatureCB([]byte(nc.info.Nonce)) if err != nil { - return _EMPTY_, err + return _EMPTY_, fmt.Errorf("error signing nonce: %w", err) } sig = base64.RawURLEncoding.EncodeToString(sigraw) } @@ -1777,8 +2763,10 @@ func (nc *Conn) connectProto() (string, error) { // If our server does not support headers then we can't do them or no responders. hdrs := nc.info.Headers - cinfo := connectInfo{o.Verbose, o.Pedantic, ujwt, nkey, sig, user, pass, token, - o.Secure, o.Name, LangString, Version, clientProtoInfo, !o.NoEcho, hdrs, hdrs} + cinfo := connectInfo{ + o.Verbose, o.Pedantic, ujwt, nkey, sig, user, pass, token, + o.Secure, o.Name, LangString, Version, clientProtoInfo, !o.NoEcho, hdrs, hdrs, + } b, err := json.Marshal(cinfo) if err != nil { @@ -1800,6 +2788,19 @@ func normalizeErr(line string) string { return s } +// natsProtoErr represents an -ERR protocol message sent by the server. +type natsProtoErr struct { + description string +} + +func (nerr *natsProtoErr) Error() string { + return fmt.Sprintf("nats: %s", nerr.description) +} + +func (nerr *natsProtoErr) Is(err error) bool { + return strings.ToLower(nerr.Error()) == err.Error() +} + // Send a connect protocol message to the server, issue user/password if // applicable. Will wait for a flush to return from the server for error // processing. @@ -1807,24 +2808,16 @@ func (nc *Conn) sendConnect() error { // Construct the CONNECT protocol string cProto, err := nc.connectProto() if err != nil { + if !nc.initc { + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, nil, err) }) + } + } return err } - // Write the protocol into the buffer - _, err = nc.bw.WriteString(cProto) - if err != nil { - return err - } - - // Add to the buffer the PING protocol - _, err = nc.bw.WriteString(pingProto) - if err != nil { - return err - } - - // Flush the buffer - err = nc.bw.Flush() - if err != nil { + // Write the protocol and PING directly to the underlying writer. + if err := nc.bw.writeDirect(cProto, pingProto); err != nil { return err } @@ -1834,6 +2827,11 @@ func (nc *Conn) sendConnect() error { // reading byte-by-byte here is ok. proto, err := nc.readProto() if err != nil { + if !nc.initc { + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, nil, err) }) + } + } return err } @@ -1842,6 +2840,11 @@ func (nc *Conn) sendConnect() error { // Read the rest now... proto, err = nc.readProto() if err != nil { + if !nc.initc { + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, nil, err) }) + } + } return err } } @@ -1867,8 +2870,7 @@ func (nc *Conn) sendConnect() error { // in doReconnect()). nc.processAuthError(authErr) } - - return errors.New("nats: " + proto) + return &natsProtoErr{proto} } // Notify that we got an unexpected protocol. @@ -1876,32 +2878,14 @@ func (nc *Conn) sendConnect() error { } // This is where we are truly connected. - nc.status = CONNECTED + nc.changeConnStatus(CONNECTED) return nil } -// reads a protocol one byte at a time. +// reads a protocol line. func (nc *Conn) readProto() (string, error) { - var ( - _buf = [10]byte{} - buf = _buf[:0] - b = [1]byte{} - protoEnd = byte('\n') - ) - for { - if _, err := nc.conn.Read(b[:1]); err != nil { - // Do not report EOF error - if err == io.EOF { - return string(buf), nil - } - return "", err - } - buf = append(buf, b[0]) - if b[0] == protoEnd { - return string(buf), nil - } - } + return nc.br.ReadString('\n') } // A control protocol line. @@ -1911,8 +2895,7 @@ type control struct { // Read a control line and process the intended op. func (nc *Conn) readOp(c *control) error { - br := bufio.NewReaderSize(nc.conn, defaultBufSize) - line, err := br.ReadString('\n') + line, err := nc.readProto() if err != nil { return err } @@ -1933,15 +2916,10 @@ func parseControl(line string, c *control) { } } -// flushReconnectPending will push the pending items that were +// flushReconnectPendingItems will push the pending items that were // gathered while we were in a RECONNECTING state to the socket. -func (nc *Conn) flushReconnectPendingItems() { - if nc.pending == nil { - return - } - if nc.pending.Len() > 0 { - nc.bw.Write(nc.pending.Bytes()) - } +func (nc *Conn) flushReconnectPendingItems() error { + return nc.bw.flushPendingBuffer() } // Stops the ping timer if set. @@ -1954,7 +2932,7 @@ func (nc *Conn) stopPingTimer() { // Try to reconnect using the option parameters. // This function assumes we are allowed to reconnect. -func (nc *Conn) doReconnect(err error) { +func (nc *Conn) doReconnect(err error, forceReconnect bool) { // We want to make sure we have the other watchers shutdown properly // here before we proceed past this point. nc.waitForExits() @@ -1967,18 +2945,22 @@ func (nc *Conn) doReconnect(err error) { // can't do defer here. nc.mu.Lock() - // Clear any queued pongs, e.g. pending flush calls. - nc.clearPendingFlushCalls() - // Clear any errors. nc.err = nil + // Perform appropriate callback if needed for a disconnect. // DisconnectedErrCB has priority over deprecated DisconnectedCB if !nc.initc { - if nc.Opts.DisconnectedErrCB != nil { - nc.ach.push(func() { nc.Opts.DisconnectedErrCB(nc, err) }) - } else if nc.Opts.DisconnectedCB != nil { - nc.ach.push(func() { nc.Opts.DisconnectedCB(nc) }) + if disconnectedErrCB := nc.Opts.DisconnectedErrCB; disconnectedErrCB != nil { + nc.ach.push(func() { disconnectedErrCB(nc, err) }) + } else if disconnectedCB := nc.Opts.DisconnectedCB; disconnectedCB != nil { + nc.ach.push(func() { disconnectedCB(nc) }) + } + } else if nc.Opts.RetryOnFailedConnect && nc.initc && err != nil { + // For initial connection failure with RetryOnFailedConnect, + // report the error via ReconnectErrCB if available + if nc.Opts.ReconnectErrCB != nil { + nc.ach.push(func() { nc.Opts.ReconnectErrCB(nc, err) }) } } @@ -1988,6 +2970,16 @@ func (nc *Conn) doReconnect(err error) { var rt *time.Timer // Channel used to kick routine out of sleep when conn is closed. rqch := nc.rqch + + // if rqch is nil, we need to set it up to signal + // the reconnect loop to reconnect immediately + // this means that `ForceReconnect` was called + // before entering doReconnect + if rqch == nil { + rqch = make(chan struct{}) + close(rqch) + } + // Counter that is increased when the whole list of servers has been tried. var wlf int @@ -2013,7 +3005,8 @@ func (nc *Conn) doReconnect(err error) { break } - doSleep := i+1 >= len(nc.srvPool) + doSleep := i+1 >= len(nc.srvPool) && !forceReconnect + forceReconnect = false nc.mu.Unlock() if !doSleep { @@ -2040,6 +3033,12 @@ func (nc *Conn) doReconnect(err error) { select { case <-rqch: rt.Stop() + + // we need to reset the rqch channel to avoid + // closing a closed channel in the next iteration + nc.mu.Lock() + nc.rqch = make(chan struct{}) + nc.mu.Unlock() case <-rt.C: } } @@ -2060,10 +3059,13 @@ func (nc *Conn) doReconnect(err error) { // Try to create a new connection err = nc.createConn() - // Not yet connected, retry... // Continue to hold the lock if err != nil { + // Perform appropriate callback for a failed connection attempt. + if reconnectErrCB := nc.Opts.ReconnectErrCB; reconnectErrCB != nil { + nc.ach.push(func() { reconnectErrCB(nc, err) }) + } nc.err = nil continue } @@ -2078,10 +3080,7 @@ func (nc *Conn) doReconnect(err error) { if nc.ar { break } - nc.status = RECONNECTING - // Reset the buffered writer to the pending buffer - // (was set to a buffered writer on nc.conn in createConn) - nc.bw.Reset(nc.pending) + nc.changeConnStatus(RECONNECTING) continue } @@ -2097,14 +3096,9 @@ func (nc *Conn) doReconnect(err error) { nc.resendSubscriptions() // Now send off and clear pending buffer - nc.flushReconnectPendingItems() - - // Flush the buffer - nc.err = nc.bw.Flush() + nc.err = nc.flushReconnectPendingItems() if nc.err != nil { - nc.status = RECONNECTING - // Reset the buffered writer to the pending buffer (bytes.Buffer). - nc.bw.Reset(nc.pending) + nc.changeConnStatus(RECONNECTING) // Stop the ping timer (if set) nc.stopPingTimer() // Since processConnectInit() returned without error, the @@ -2115,20 +3109,21 @@ func (nc *Conn) doReconnect(err error) { } // Done with the pending buffer - nc.pending = nil + nc.bw.doneWithPending() - // This is where we are truly connected. - nc.status = CONNECTED + // Queue up the correct callback. If we are in initial connect state + // (using retry on failed connect), we will call the ConnectedCB, + // otherwise the ReconnectedCB. + if reconnectedCB := nc.Opts.ReconnectedCB; reconnectedCB != nil && !nc.initc { + nc.ach.push(func() { reconnectedCB(nc) }) + } else if connectedCB := nc.Opts.ConnectedCB; connectedCB != nil && nc.initc { + nc.ach.push(func() { connectedCB(nc) }) + } // If we are here with a retry on failed connect, indicate that the // initial connect is now complete. nc.initc = false - // Queue up the reconnect callback. - if nc.Opts.ReconnectedCB != nil { - nc.ach.push(func() { nc.Opts.ReconnectedCB(nc) }) - } - // Release lock here, we will return below. nc.mu.Unlock() @@ -2148,37 +3143,36 @@ func (nc *Conn) doReconnect(err error) { // processOpErr handles errors from reading or parsing the protocol. // The lock should not be held entering this function. -func (nc *Conn) processOpErr(err error) { +func (nc *Conn) processOpErr(err error) bool { nc.mu.Lock() + defer nc.mu.Unlock() if nc.isConnecting() || nc.isClosed() || nc.isReconnecting() { - nc.mu.Unlock() - return + return false } if nc.Opts.AllowReconnect && nc.status == CONNECTED { // Set our new status - nc.status = RECONNECTING + nc.changeConnStatus(RECONNECTING) // Stop ping timer if set nc.stopPingTimer() if nc.conn != nil { - nc.bw.Flush() nc.conn.Close() nc.conn = nil } // Create pending buffer before reconnecting. - nc.pending = new(bytes.Buffer) - nc.bw.Reset(nc.pending) + nc.bw.switchToPending() - go nc.doReconnect(err) - nc.mu.Unlock() - return + // Clear any queued pongs, e.g. pending flush calls. + nc.clearPendingFlushCalls() + + go nc.doReconnect(err, false) + return false } - nc.status = DISCONNECTED + nc.changeConnStatus(DISCONNECTED) nc.err = err - nc.mu.Unlock() - nc.close(CLOSED, true, nil) + return true } // dispatch is responsible for calling any async callbacks @@ -2255,21 +3249,29 @@ func (nc *Conn) readLoop() { nc.ps = &parseState{} } conn := nc.conn + br := nc.br nc.mu.Unlock() if conn == nil { return } - // Stack based buffer. - b := make([]byte, defaultBufSize) - for { - if n, err := conn.Read(b); err != nil { - nc.processOpErr(err) - break - } else if err = nc.parse(b[:n]); err != nil { - nc.processOpErr(err) + buf, err := br.Read() + if err == nil { + // With websocket, it is possible that there is no error but + // also no buffer returned (either WS control message or read of a + // partial compressed message). We could call parse(buf) which + // would ignore an empty buffer, but simply go back to top of the loop. + if len(buf) == 0 { + continue + } + err = nc.parse(buf) + } + if err != nil { + if shouldClose := nc.processOpErr(err); shouldClose { + nc.close(CLOSED, true, nil) + } break } } @@ -2320,12 +3322,21 @@ func (nc *Conn) waitForMsgs(s *Subscription) { mcb := s.mcb max = s.max closed = s.closed + var fcReply string if !s.closed { s.delivered++ delivered = s.delivered + if s.jsi != nil { + fcReply = s.checkForFlowControlResponse() + } } s.mu.Unlock() + // Respond to flow control if applicable + if fcReply != _EMPTY_ { + nc.Publish(fcReply, nil) + } + if closed { break } @@ -2354,26 +3365,40 @@ func (nc *Conn) waitForMsgs(s *Subscription) { } s.pHead = m.next } + // Now check for pDone + done := s.pDone s.mu.Unlock() + + if done != nil { + done(s.Subject) + } } +// Used for debugging and simulating loss for certain tests. +// Return what is to be used. If we return nil the message will be dropped. +type msgFilter func(m *Msg) *Msg + // processMsg is called by parse and will place the msg on the // appropriate channel/pending queue for processing. If the channel is full, // or the pending queue is over the pending limits, the connection is // considered a slow consumer. func (nc *Conn) processMsg(data []byte) { - // Don't lock the connection to avoid server cutting us off if the - // flusher is holding the connection lock, trying to send to the server - // that is itself trying to send data to us. - nc.subsMu.RLock() - // Stats atomic.AddUint64(&nc.InMsgs, 1) atomic.AddUint64(&nc.InBytes, uint64(len(data))) + // Don't lock the connection to avoid server cutting us off if the + // flusher is holding the connection lock, trying to send to the server + // that is itself trying to send data to us. + nc.subsMu.RLock() sub := nc.subs[nc.ps.ma.sid] + var mf msgFilter + if nc.filters != nil { + mf = nc.filters[string(nc.ps.ma.subject)] + } + nc.subsMu.RUnlock() + if sub == nil { - nc.subsMu.RUnlock() return } @@ -2385,76 +3410,186 @@ func (nc *Conn) processMsg(data []byte) { // It's possible that we end-up not using the message, but that's ok. // FIXME(dlc): Need to copy, should/can do COW? - msgPayload := make([]byte, len(data)) - copy(msgPayload, data) + msgPayload := data + if !nc.ps.msgCopied { + msgPayload = make([]byte, len(data)) + copy(msgPayload, data) + } // Check if we have headers encoded here. - var h http.Header + var h Header var err error + var ctrlMsg bool + var ctrlType int + var fcReply string if nc.ps.ma.hdr > 0 { hbuf := msgPayload[:nc.ps.ma.hdr] msgPayload = msgPayload[nc.ps.ma.hdr:] - h, err = decodeHeadersMsg(hbuf) + h, err = DecodeHeadersMsg(hbuf) if err != nil { // We will pass the message through but send async error. nc.mu.Lock() nc.err = ErrBadHeaderMsg - if nc.Opts.AsyncErrorCB != nil { - nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, sub, ErrBadHeaderMsg) }) + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, sub, ErrBadHeaderMsg) }) } nc.mu.Unlock() } } // FIXME(dlc): Should we recycle these containers? - m := &Msg{Header: h, Data: msgPayload, Subject: subj, Reply: reply, Sub: sub} + m := &Msg{ + Subject: subj, + Reply: reply, + Header: h, + Data: msgPayload, + Sub: sub, + wsz: len(data) + len(subj) + len(reply), + } + + // Check for message filters. + if mf != nil { + if m = mf(m); m == nil { + // Drop message. + return + } + } sub.mu.Lock() - // Subscription internal stats (applicable only for non ChanSubscription's) - if sub.typ != ChanSubscription { - sub.pMsgs++ - if sub.pMsgs > sub.pMsgsMax { - sub.pMsgsMax = sub.pMsgs + // Check if closed. + if sub.closed { + sub.mu.Unlock() + return + } + + // Skip flow control messages in case of using a JetStream context. + jsi := sub.jsi + if jsi != nil { + // There has to be a header for it to be a control message. + if h != nil { + ctrlMsg, ctrlType = isJSControlMessage(m) + if ctrlMsg && ctrlType == jsCtrlHB { + // Check if the heartbeat has a "Consumer Stalled" header, if + // so, the value is the FC reply to send a nil message to. + // We will send it at the end of this function. + fcReply = m.Header.Get(consumerStalledHdr) + } } - sub.pBytes += len(m.Data) - if sub.pBytes > sub.pBytesMax { - sub.pBytesMax = sub.pBytes + // Check for ordered consumer here. If checkOrderedMsgs returns true that means it detected a gap. + if !ctrlMsg && jsi.ordered && sub.checkOrderedMsgs(m) { + sub.mu.Unlock() + return } + } + + // Skip processing if this is a control message and + // if not a pull consumer heartbeat. For pull consumers, + // heartbeats have to be handled on per request basis. + if !ctrlMsg || (jsi != nil && jsi.pull) { + var chanSubCheckFC bool + // Subscription internal stats (applicable only for non ChanSubscription's) + if sub.typ != ChanSubscription { + sub.pMsgs++ + if sub.pMsgs > sub.pMsgsMax { + sub.pMsgsMax = sub.pMsgs + } + sub.pBytes += len(m.Data) + if sub.pBytes > sub.pBytesMax { + sub.pBytesMax = sub.pBytes + } - // Check for a Slow Consumer - if (sub.pMsgsLimit > 0 && sub.pMsgs > sub.pMsgsLimit) || - (sub.pBytesLimit > 0 && sub.pBytes > sub.pBytesLimit) { - goto slowConsumer + // Check for a Slow Consumer + if (sub.pMsgsLimit > 0 && sub.pMsgs > sub.pMsgsLimit) || + (sub.pBytesLimit > 0 && sub.pBytes > sub.pBytesLimit) { + goto slowConsumer + } + } else if jsi != nil { + chanSubCheckFC = true } - } - // We have two modes of delivery. One is the channel, used by channel - // subscribers and syncSubscribers, the other is a linked list for async. - if sub.mch != nil { - select { - case sub.mch <- m: - default: - goto slowConsumer + // We have two modes of delivery. One is the channel, used by channel + // subscribers and syncSubscribers, the other is a linked list for async. + if sub.mch != nil { + select { + case sub.mch <- m: + // For ChanSubscribe, track delivered count here + if sub.typ == ChanSubscription { + sub.delivered++ + } + default: + goto slowConsumer + } + } else { + // Push onto the async pList + if sub.pHead == nil { + sub.pHead = m + sub.pTail = m + if sub.pCond != nil { + sub.pCond.Signal() + } + } else { + sub.pTail.next = m + sub.pTail = m + } } - } else { - // Push onto the async pList - if sub.pHead == nil { - sub.pHead = m - sub.pTail = m - sub.pCond.Signal() + if jsi != nil { + // Store the ACK metadata from the message to + // compare later on with the received heartbeat. + sub.trackSequences(m.Reply) + if chanSubCheckFC { + // For ChanSubscription, since we can't call this when a message + // is "delivered" (since user is pull from their own channel), + // we have a go routine that does this check, however, we do it + // also here to make it much more responsive. The go routine is + // really to avoid stalling when there is no new messages coming. + fcReply = sub.checkForFlowControlResponse() + } + } + } else if ctrlType == jsCtrlFC && m.Reply != _EMPTY_ { + // This is a flow control message. + // We will schedule the send of the FC reply once we have delivered the + // DATA message that was received before this flow control message, which + // has sequence `jsi.fciseq`. However, it is possible that this message + // has already been delivered, in that case, we need to send the FC reply now. + if sub.getJSDelivered() >= jsi.fciseq { + fcReply = m.Reply } else { - sub.pTail.next = m - sub.pTail = m + // Schedule a reply after the previous message is delivered. + sub.scheduleFlowControlResponse(m.Reply) } } - // Clear SlowConsumer status. + // Clear any SlowConsumer status. + if sub.sc { + sub.changeSubStatus(SubscriptionActive) + } sub.sc = false - sub.mu.Unlock() - nc.subsMu.RUnlock() + + if fcReply != _EMPTY_ { + nc.Publish(fcReply, nil) + } + + // Handle control heartbeat messages. + if ctrlMsg && ctrlType == jsCtrlHB && m.Reply == _EMPTY_ { + nc.checkForSequenceMismatch(m, sub, jsi) + } + + // Check if we need to auto-unsubscribe for chan subscriptions + if sub.typ == ChanSubscription && sub.max > 0 && !ctrlMsg { + sub.mu.Lock() + if sub.delivered >= sub.max { + sub.mu.Unlock() + nc.mu.Lock() + nc.removeSub(sub) + nc.mu.Unlock() + } else { + sub.mu.Unlock() + } + } + return slowConsumer: @@ -2466,30 +3601,60 @@ slowConsumer: sub.pMsgs-- sub.pBytes -= len(m.Data) } - sub.mu.Unlock() - nc.subsMu.RUnlock() if sc { + sub.changeSubStatus(SubscriptionSlowConsumer) + sub.mu.Unlock() // Now we need connection's lock and we may end-up in the situation // that we were trying to avoid, except that in this case, the client // is already experiencing client-side slow consumer situation. nc.mu.Lock() nc.err = ErrSlowConsumer - if nc.Opts.AsyncErrorCB != nil { - nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, sub, ErrSlowConsumer) }) + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, sub, ErrSlowConsumer) }) } nc.mu.Unlock() + } else { + sub.mu.Unlock() } } -// processPermissionsViolation is called when the server signals a subject -// permissions violation on either publish or subscribe. -func (nc *Conn) processPermissionsViolation(err string) { +var ( + permissionsRe = regexp.MustCompile(`Subscription to "(\S+)"`) + permissionsQueueRe = regexp.MustCompile(`using queue "(\S+)"`) +) + +// processTransientError is called when the server signals a non terminal error +// which does not close the connection or trigger a reconnect. +// This will trigger the async error callback if set. +// These errors include the following: +// - permissions violation on publish or subscribe +// - maximum subscriptions exceeded +func (nc *Conn) processTransientError(err error) { nc.mu.Lock() - // create error here so we can pass it as a closure to the async cb dispatcher. - e := errors.New("nats: " + err) - nc.err = e - if nc.Opts.AsyncErrorCB != nil { - nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, e) }) + nc.err = err + if errors.Is(err, ErrPermissionViolation) { + matches := permissionsRe.FindStringSubmatch(err.Error()) + if len(matches) >= 2 { + queueMatches := permissionsQueueRe.FindStringSubmatch(err.Error()) + var q string + if len(queueMatches) >= 2 { + q = queueMatches[1] + } + subject := matches[1] + for _, sub := range nc.subs { + if sub.Subject == subject && sub.Queue == q && sub.permissionsErr == nil { + sub.mu.Lock() + if sub.errCh != nil { + sub.errCh <- err + } + sub.permissionsErr = err + sub.mu.Unlock() + } + } + } + } + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, nil, err) }) } nc.mu.Unlock() } @@ -2501,12 +3666,14 @@ func (nc *Conn) processPermissionsViolation(err string) { // Connection lock is held on entry func (nc *Conn) processAuthError(err error) bool { nc.err = err - if !nc.initc && nc.Opts.AsyncErrorCB != nil { - nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) }) + if !nc.initc { + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, nil, err) }) + } } // We should give up if we tried twice on this server and got the - // same error. - if nc.current.lastErr == err { + // same error. This behavior can be modified using IgnoreAuthErrorAbort. + if nc.current.lastErr == err && !nc.Opts.IgnoreAuthErrorAbort { nc.ar = true } else { nc.current.lastErr = err @@ -2538,15 +3705,18 @@ func (nc *Conn) flusher() { nc.mu.Lock() // Check to see if we should bail out. - if !nc.isConnected() || nc.isConnecting() || bw != nc.bw || conn != nc.conn { + if !nc.isConnected() || nc.isConnecting() || conn != nc.conn { nc.mu.Unlock() return } - if bw.Buffered() > 0 { - if err := bw.Flush(); err != nil { + if bw.buffered() > 0 { + if err := bw.flush(); err != nil { if nc.err == nil { nc.err = err } + if asyncErrorCB := nc.Opts.AsyncErrorCB; asyncErrorCB != nil { + nc.ach.push(func() { asyncErrorCB(nc, nil, err) }) + } } } nc.mu.Unlock() @@ -2567,7 +3737,7 @@ func (nc *Conn) processPong() { nc.mu.Lock() if len(nc.pongs) > 0 { ch = nc.pongs[0] - nc.pongs = nc.pongs[1:] + nc.pongs = append(nc.pongs[:0], nc.pongs[1:]...) } nc.pout = 0 nc.mu.Unlock() @@ -2588,7 +3758,7 @@ func (nc *Conn) processInfo(info string) error { if info == _EMPTY_ { return nil } - ncInfo := serverInfo{} + var ncInfo serverInfo if err := json.Unmarshal([]byte(info), &ncInfo); err != nil { return err } @@ -2599,7 +3769,7 @@ func (nc *Conn) processInfo(info string) error { // if advertise is disabled on that server, or servers that // did not include themselves in the async INFO protocol. // If empty, do not remove the implicit servers from the pool. - if len(ncInfo.ConnectURLs) == 0 { + if len(nc.info.ConnectURLs) == 0 { if !nc.initc && ncInfo.LameDuckMode && nc.Opts.LameDuckModeHandler != nil { nc.ach.push(func() { nc.Opts.LameDuckModeHandler(nc) }) } @@ -2659,12 +3829,16 @@ func (nc *Conn) processInfo(info string) error { if !nc.Opts.NoRandomize { nc.shufflePool(1) } - if !nc.initc && nc.Opts.DiscoveredServersCB != nil { - nc.ach.push(func() { nc.Opts.DiscoveredServersCB(nc) }) + if !nc.initc { + if discoveredServersCB := nc.Opts.DiscoveredServersCB; discoveredServersCB != nil { + nc.ach.push(func() { discoveredServersCB(nc) }) + } } } - if !nc.initc && ncInfo.LameDuckMode && nc.Opts.LameDuckModeHandler != nil { - nc.ach.push(func() { nc.Opts.LameDuckModeHandler(nc) }) + if !nc.initc && ncInfo.LameDuckMode { + if lameDuckModeHandler := nc.Opts.LameDuckModeHandler; lameDuckModeHandler != nil { + nc.ach.push(func() { lameDuckModeHandler(nc) }) + } } return nil } @@ -2701,24 +3875,36 @@ func checkAuthError(e string) error { if strings.HasPrefix(e, AUTHENTICATION_EXPIRED_ERR) { return ErrAuthExpired } + if strings.HasPrefix(e, AUTHENTICATION_REVOKED_ERR) { + return ErrAuthRevoked + } + if strings.HasPrefix(e, ACCOUNT_AUTHENTICATION_EXPIRED_ERR) { + return ErrAccountAuthExpired + } return nil } // processErr processes any error messages from the server and -// sets the connection's lastError. +// sets the connection's LastError. func (nc *Conn) processErr(ie string) { // Trim, remove quotes ne := normalizeErr(ie) // convert to lower case. e := strings.ToLower(ne) - close := false + var close bool // FIXME(dlc) - process Slow Consumer signals special. if e == STALE_CONNECTION { - nc.processOpErr(ErrStaleConnection) + close = nc.processOpErr(ErrStaleConnection) + } else if e == MAX_CONNECTIONS_ERR { + close = nc.processOpErr(ErrMaxConnectionsExceeded) + } else if e == MAX_ACCOUNT_CONNECTIONS_ERR { + close = nc.processOpErr(ErrMaxAccountConnectionsExceeded) } else if strings.HasPrefix(e, PERMISSIONS_ERR) { - nc.processPermissionsViolation(ne) + nc.processTransientError(fmt.Errorf("%w: %s", ErrPermissionViolation, ne)) + } else if strings.HasPrefix(e, MAX_SUBSCRIPTIONS_ERR) { + nc.processTransientError(ErrMaxSubscriptionsExceeded) } else if authErr := checkAuthError(e); authErr != nil { nc.mu.Lock() close = nc.processAuthError(authErr) @@ -2748,43 +3934,90 @@ func (nc *Conn) kickFlusher() { // Publish publishes the data argument to the given subject. The data // argument is left untouched and needs to be correctly interpreted on // the receiver. -func (nc *Conn) Publish(subj string, data []byte, opts ...PublishOption) error { - if len(opts) > 0 { - return nc.jsPublish(subj, data, opts) +func (nc *Conn) Publish(subj string, data []byte) error { + return nc.publish(subj, _EMPTY_, false, nil, data) +} + +// Header represents the optional Header for a NATS message, +// based on the implementation of http.Header. +type Header map[string][]string + +// Add adds the key, value pair to the header. It is case-sensitive +// and appends to any existing values associated with key. +func (h Header) Add(key, value string) { + h[key] = append(h[key], value) +} + +// Set sets the header entries associated with key to the single +// element value. It is case-sensitive and replaces any existing +// values associated with key. +func (h Header) Set(key, value string) { + h[key] = []string{value} +} + +// Get gets the first value associated with the given key. +// It is case-sensitive. +func (h Header) Get(key string) string { + if h == nil { + return _EMPTY_ } + if v := h[key]; v != nil { + return v[0] + } + return _EMPTY_ +} + +// Values returns all values associated with the given key. +// It is case-sensitive. +func (h Header) Values(key string) []string { + return h[key] +} - return nc.publish(subj, _EMPTY_, nil, data) +// Del deletes the values associated with a key. +// It is case-sensitive. +func (h Header) Del(key string) { + delete(h, key) } -// Used to create a new message for publishing that will use headers. +// NewMsg creates a message for publishing that will use headers. func NewMsg(subject string) *Msg { return &Msg{ Subject: subject, - Header: make(http.Header), + Header: make(Header), } } const ( - hdrLine = "NATS/1.0\r\n" - crlf = "\r\n" - hdrPreEnd = len(hdrLine) - len(crlf) - statusHdr = "Status" - descrHdr = "Description" - noResponders = "503" - statusLen = 3 // e.g. 20x, 40x, 50x + hdrLine = "NATS/1.0\r\n" + crlf = "\r\n" + hdrPreEnd = len(hdrLine) - len(crlf) + statusHdr = "Status" + descrHdr = "Description" + lastConsumerSeqHdr = "Nats-Last-Consumer" + lastStreamSeqHdr = "Nats-Last-Stream" + consumerStalledHdr = "Nats-Consumer-Stalled" + noResponders = "503" + noMessagesSts = "404" + reqTimeoutSts = "408" + jetStream409Sts = "409" + controlMsg = "100" + statusLen = 3 // e.g. 20x, 40x, 50x ) -// decodeHeadersMsg will decode and headers. -func decodeHeadersMsg(data []byte) (http.Header, error) { - tp := textproto.NewReader(bufio.NewReader(bytes.NewReader(data))) +// DecodeHeadersMsg will decode and headers. +func DecodeHeadersMsg(data []byte) (Header, error) { + br := bufio.NewReaderSize(bytes.NewReader(data), 128) + tp := textproto.NewReader(br) l, err := tp.ReadLine() if err != nil || len(l) < hdrPreEnd || l[:hdrPreEnd] != hdrLine[:hdrPreEnd] { return nil, ErrBadHeaderMsg } - mh, err := tp.ReadMIMEHeader() + + mh, err := readMIMEHeader(tp) if err != nil { - return nil, ErrBadHeaderMsg + return nil, err } + // Check if we have an inlined status. if len(l) > hdrPreEnd { var description string @@ -2798,7 +4031,41 @@ func decodeHeadersMsg(data []byte) (http.Header, error) { mh.Add(descrHdr, description) } } - return http.Header(mh), nil + return Header(mh), nil +} + +// readMIMEHeader returns a MIMEHeader that preserves the +// original case of the MIME header, based on the implementation +// of textproto.ReadMIMEHeader. +// +// https://golang.org/pkg/net/textproto/#Reader.ReadMIMEHeader +func readMIMEHeader(tp *textproto.Reader) (textproto.MIMEHeader, error) { + m := make(textproto.MIMEHeader) + for { + kv, err := tp.ReadLine() + if len(kv) == 0 { + return m, err + } + + // Process key fetching original case. + i := strings.IndexByte(kv, ':') + if i < 0 { + return nil, ErrBadHeaderMsg + } + key := kv[:i] + if key == "" { + // Skip empty keys. + continue + } + i++ + for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') { + i++ + } + m[key] = append(m[key], kv[i:]) + if err != nil { + return m, err + } + } } // PublishMsg publishes the Msg structure, which includes the @@ -2807,46 +4074,85 @@ func (nc *Conn) PublishMsg(m *Msg) error { if m == nil { return ErrInvalidMsg } - - var hdr []byte - var err error - - if len(m.Header) > 0 { - if !nc.info.Headers { - return ErrHeadersNotSupported - } - - hdr, err = m.headerBytes() - if err != nil { - return err - } + hdr, err := m.headerBytes() + if err != nil { + return err } - - return nc.publish(m.Subject, m.Reply, hdr, m.Data) + validateReply := m.Reply != _EMPTY_ + return nc.publish(m.Subject, m.Reply, validateReply, hdr, m.Data) } // PublishRequest will perform a Publish() expecting a response on the // reply subject. Use Request() for automatically waiting for a response // inline. func (nc *Conn) PublishRequest(subj, reply string, data []byte) error { - return nc.publish(subj, reply, nil, data) + return nc.publish(subj, reply, true, nil, data) } -// Used for handrolled itoa +// Used for handrolled Itoa const digits = "0123456789" +// validateSubject checks if the subject contains characters that break the NATS protocol. +// Uses an adaptive algorithm: manual loop for short subjects (< 16 chars) and +// SIMD-optimized strings.IndexByte for longer subjects. +func validateSubject(subj string) error { + if subj == "" { + return ErrBadSubject + } + + // Adaptive threshold based on benchmark data showing crossover at ~15-20 characters. + const lengthThreshold = 16 + + if len(subj) < lengthThreshold { + // Fast path for short subjects (< 16 chars) + // Short-circuit on non-control characters. + for i := range len(subj) { + c := subj[i] + if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') { + return ErrBadSubject + } + } + return nil + } + + // Optimized path for long subjects (>= 16 chars) + // Uses SIMD-optimized strings.IndexByte (processes 16+ bytes per instruction) + if strings.IndexByte(subj, ' ') >= 0 || + strings.IndexByte(subj, '\t') >= 0 || + strings.IndexByte(subj, '\r') >= 0 || + strings.IndexByte(subj, '\n') >= 0 { + return ErrBadSubject + } + return nil +} + // publish is the internal function to publish messages to a nats-server. // Sends a protocol data message by queuing into the bufio writer // and kicking the flush go routine. These writes should be protected. -func (nc *Conn) publish(subj, reply string, hdr, data []byte) error { +func (nc *Conn) publish(subj, reply string, validateReply bool, hdr, data []byte) error { if nc == nil { return ErrInvalidConnection } - if subj == "" { + if !nc.Opts.SkipSubjectValidation { + if err := validateSubject(subj); err != nil { + return err + } + if validateReply { + if err := validateSubject(reply); err != nil { + return ErrBadSubject + } + } + } else if subj == _EMPTY_ { return ErrBadSubject } nc.mu.Lock() + // Check if headers attempted to be sent to server that does not support them. + if len(hdr) > 0 && !nc.info.Headers { + nc.mu.Unlock() + return ErrHeadersNotSupported + } + if nc.isClosed() { nc.mu.Unlock() return ErrConnectionClosed @@ -2867,14 +4173,9 @@ func (nc *Conn) publish(subj, reply string, hdr, data []byte) error { // Check if we are reconnecting, and if so check if // we have exceeded our reconnect outbound buffer limits. - if nc.isReconnecting() { - // Flush to underlying buffer. - nc.bw.Flush() - // Check if we are over - if nc.pending.Len() >= nc.Opts.ReconnectBufSize { - nc.mu.Unlock() - return ErrReconnectBufExceeded - } + if nc.bw.atLimitIfUsingPending() { + nc.mu.Unlock() + return ErrReconnectBufExceeded } var mh []byte @@ -2897,7 +4198,7 @@ func (nc *Conn) publish(subj, reply string, hdr, data []byte) error { // go 1.14 some values strconv faster, may be able to switch over. var b [12]byte - var i = len(b) + i := len(b) if hdr != nil { if len(hdr) > 0 { @@ -2928,19 +4229,7 @@ func (nc *Conn) publish(subj, reply string, hdr, data []byte) error { mh = append(mh, b[i:]...) mh = append(mh, _CRLF_...) - _, err := nc.bw.Write(mh) - if err == nil { - if hdr != nil { - _, err = nc.bw.Write(hdr) - } - if err == nil { - _, err = nc.bw.Write(data) - } - } - if err == nil { - _, err = nc.bw.WriteString(_CRLF_) - } - if err != nil { + if err := nc.bw.appendBufs(mh, hdr, data, _CRLF_BYTES_); err != nil { nc.mu.Unlock() return err } @@ -3000,30 +4289,26 @@ func (nc *Conn) respHandler(m *Msg) { // Helper to setup and send new request style requests. Return the chan to receive the response. func (nc *Conn) createNewRequestAndSend(subj string, hdr, data []byte) (chan *Msg, string, error) { nc.mu.Lock() - // Do setup for the new style if needed. - if nc.respMap == nil { - nc.initNewResp() - } // Create new literal Inbox and map to a chan msg. mch := make(chan *Msg, RequestChanLen) respInbox := nc.newRespInbox() - token := respInbox[respInboxPrefixLen:] + token := respInbox[nc.respSubLen:] + nc.respMap[token] = mch if nc.respMux == nil { // Create the response subscription we will use for all new style responses. // This will be on an _INBOX with an additional terminal token. The subscription // will be on a wildcard. - s, err := nc.subscribeLocked(nc.respSub, _EMPTY_, nc.respHandler, nil, false) + s, err := nc.subscribeLocked(nc.respSub, _EMPTY_, nc.respHandler, nil, nil, false, nil) if err != nil { nc.mu.Unlock() return nil, token, err } - nc.respScanf = strings.Replace(nc.respSub, "*", "%s", -1) nc.respMux = s } nc.mu.Unlock() - if err := nc.publish(subj, respInbox, hdr, data); err != nil { + if err := nc.publish(subj, respInbox, false, hdr, data); err != nil { return nil, token, err } @@ -3033,17 +4318,12 @@ func (nc *Conn) createNewRequestAndSend(subj string, hdr, data []byte) (chan *Ms // RequestMsg will send a request payload including optional headers and deliver // the response message, or an error, including a timeout if no message was received properly. func (nc *Conn) RequestMsg(msg *Msg, timeout time.Duration) (*Msg, error) { - var hdr []byte - var err error - - if len(msg.Header) > 0 { - if !nc.info.Headers { - return nil, ErrHeadersNotSupported - } - hdr, err = msg.headerBytes() - if err != nil { - return nil, err - } + if msg == nil { + return nil, ErrInvalidMsg + } + hdr, err := msg.headerBytes() + if err != nil { + return nil, err } return nc.request(msg.Subject, hdr, msg.Data, timeout) @@ -3114,17 +4394,17 @@ func (nc *Conn) newRequest(subj string, hdr, data []byte, timeout time.Duration) // with the Inbox reply and return the first reply received. // This is optimized for the case of multiple responses. func (nc *Conn) oldRequest(subj string, hdr, data []byte, timeout time.Duration) (*Msg, error) { - inbox := NewInbox() + inbox := nc.NewInbox() ch := make(chan *Msg, RequestChanLen) - s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, true) + s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, nil, true, nil) if err != nil { return nil, err } s.AutoUnsubscribe(1) defer s.Unsubscribe() - err = nc.publish(subj, inbox, hdr, data) + err = nc.publish(subj, inbox, false, hdr, data) if err != nil { return nil, err } @@ -3134,12 +4414,11 @@ func (nc *Conn) oldRequest(subj string, hdr, data []byte, timeout time.Duration) // InboxPrefix is the prefix for all inbox subjects. const ( - InboxPrefix = "_INBOX." - inboxPrefixLen = len(InboxPrefix) - respInboxPrefixLen = inboxPrefixLen + nuidSize + 1 - replySuffixLen = 8 // Gives us 62^8 - rdigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - base = 62 + InboxPrefix = "_INBOX." + inboxPrefixLen = len(InboxPrefix) + replySuffixLen = 8 // Gives us 62^8 + rdigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + base = 62 ) // NewInbox will return an inbox string which can be used for directed replies from @@ -3154,10 +4433,24 @@ func NewInbox() string { return string(b[:]) } +// Create a new inbox that is prefix aware. +func (nc *Conn) NewInbox() string { + if nc.Opts.InboxPrefix == _EMPTY_ { + return NewInbox() + } + + var sb strings.Builder + sb.WriteString(nc.Opts.InboxPrefix) + sb.WriteByte('.') + sb.WriteString(nuid.Next()) + return sb.String() +} + // Function to init new response structures. func (nc *Conn) initNewResp() { - // _INBOX wildcard - nc.respSub = fmt.Sprintf("%s.*", NewInbox()) + nc.respSubPrefix = fmt.Sprintf("%s.", nc.NewInbox()) + nc.respSubLen = len(nc.respSubPrefix) + nc.respSub = fmt.Sprintf("%s*", nc.respSubPrefix) nc.respMap = make(map[string]chan *Msg) nc.respRand = rand.New(rand.NewSource(time.Now().UnixNano())) } @@ -3169,15 +4462,17 @@ func (nc *Conn) newRespInbox() string { if nc.respMap == nil { nc.initNewResp() } - var b [respInboxPrefixLen + replySuffixLen]byte - pres := b[:respInboxPrefixLen] - copy(pres, nc.respSub) + + var sb strings.Builder + sb.WriteString(nc.respSubPrefix) + rn := nc.respRand.Int63() - for i, l := respInboxPrefixLen, rn; i < len(b); i++ { - b[i] = rdigits[l%base] - l /= base + for i := 0; i < replySuffixLen; i++ { + sb.WriteByte(rdigits[rn%base]) + rn /= base } - return string(b[:]) + + return sb.String() } // NewRespInbox is the new format used for _INBOX. @@ -3189,30 +4484,33 @@ func (nc *Conn) NewRespInbox() string { } // respToken will return the last token of a literal response inbox -// which we use for the message channel lookup. This needs to do a -// scan to protect itself against the server changing the subject. +// which we use for the message channel lookup. This needs to verify the subject +// prefix matches to protect itself against the server changing the subject. // Lock should be held. func (nc *Conn) respToken(respInbox string) string { - var token string - n, err := fmt.Sscanf(respInbox, nc.respScanf, &token) - if err != nil || n != 1 { - return "" + if token, found := strings.CutPrefix(respInbox, nc.respSubPrefix); found { + return token } - return token + return "" } // Subscribe will express interest in the given subject. The subject -// can have wildcards (partial:*, full:>). Messages will be delivered -// to the associated MsgHandler. -func (nc *Conn) Subscribe(subj string, cb MsgHandler, opts ...SubscribeOption) (*Subscription, error) { - return nc.subscribe(subj, _EMPTY_, cb, nil, false, opts...) +// can have wildcards. +// There are two type of wildcards: * for partial, and > for full. +// A subscription on subject time.*.east would receive messages sent to time.us.east and time.eu.east. +// A subscription on subject time.us.> would receive messages sent to +// time.us.east and time.us.east.atlanta, while time.us.* would only match time.us.east +// since it can't match more than one token. +// Messages will be delivered to the associated MsgHandler. +func (nc *Conn) Subscribe(subj string, cb MsgHandler) (*Subscription, error) { + return nc.subscribe(subj, _EMPTY_, cb, nil, nil, false, nil) } // ChanSubscribe will express interest in the given subject and place // all messages received on the channel. // You should not close the channel until sub.Unsubscribe() has been called. -func (nc *Conn) ChanSubscribe(subj string, ch chan *Msg, opts ...SubscribeOption) (*Subscription, error) { - return nc.subscribe(subj, _EMPTY_, nil, ch, false, opts...) +func (nc *Conn) ChanSubscribe(subj string, ch chan *Msg) (*Subscription, error) { + return nc.subscribe(subj, _EMPTY_, nil, ch, nil, false, nil) } // ChanQueueSubscribe will express interest in the given subject. @@ -3221,37 +4519,43 @@ func (nc *Conn) ChanSubscribe(subj string, ch chan *Msg, opts ...SubscribeOption // which will be placed on the channel. // You should not close the channel until sub.Unsubscribe() has been called. // Note: This is the same than QueueSubscribeSyncWithChan. -func (nc *Conn) ChanQueueSubscribe(subj, group string, ch chan *Msg, opts ...SubscribeOption) (*Subscription, error) { - return nc.subscribe(subj, group, nil, ch, false, opts...) +func (nc *Conn) ChanQueueSubscribe(subj, group string, ch chan *Msg) (*Subscription, error) { + return nc.subscribe(subj, group, nil, ch, nil, false, nil) } // SubscribeSync will express interest on the given subject. Messages will // be received synchronously using Subscription.NextMsg(). -func (nc *Conn) SubscribeSync(subj string, opts ...SubscribeOption) (*Subscription, error) { +func (nc *Conn) SubscribeSync(subj string) (*Subscription, error) { if nc == nil { return nil, ErrInvalidConnection } mch := make(chan *Msg, nc.Opts.SubChanLen) - s, e := nc.subscribe(subj, _EMPTY_, nil, mch, true, opts...) - return s, e + var errCh chan error + if nc.Opts.PermissionErrOnSubscribe { + errCh = make(chan error, 100) + } + return nc.subscribe(subj, _EMPTY_, nil, mch, errCh, true, nil) } // QueueSubscribe creates an asynchronous queue subscriber on the given subject. // All subscribers with the same queue name will form the queue group and // only one member of the group will be selected to receive any given // message asynchronously. -func (nc *Conn) QueueSubscribe(subj, queue string, cb MsgHandler, opts ...SubscribeOption) (*Subscription, error) { - return nc.subscribe(subj, queue, cb, nil, false, opts...) +func (nc *Conn) QueueSubscribe(subj, queue string, cb MsgHandler) (*Subscription, error) { + return nc.subscribe(subj, queue, cb, nil, nil, false, nil) } // QueueSubscribeSync creates a synchronous queue subscriber on the given // subject. All subscribers with the same queue name will form the queue // group and only one member of the group will be selected to receive any // given message synchronously using Subscription.NextMsg(). -func (nc *Conn) QueueSubscribeSync(subj, queue string, opts ...SubscribeOption) (*Subscription, error) { +func (nc *Conn) QueueSubscribeSync(subj, queue string) (*Subscription, error) { mch := make(chan *Msg, nc.Opts.SubChanLen) - s, e := nc.subscribe(subj, queue, nil, mch, true, opts...) - return s, e + var errCh chan error + if nc.Opts.PermissionErrOnSubscribe { + errCh = make(chan error, 100) + } + return nc.subscribe(subj, queue, nil, mch, errCh, true, nil) } // QueueSubscribeSyncWithChan will express interest in the given subject. @@ -3260,8 +4564,8 @@ func (nc *Conn) QueueSubscribeSync(subj, queue string, opts ...SubscribeOption) // which will be placed on the channel. // You should not close the channel until sub.Unsubscribe() has been called. // Note: This is the same than ChanQueueSubscribe. -func (nc *Conn) QueueSubscribeSyncWithChan(subj, queue string, ch chan *Msg, opts ...SubscribeOption) (*Subscription, error) { - return nc.subscribe(subj, queue, nil, ch, false, opts...) +func (nc *Conn) QueueSubscribeSyncWithChan(subj, queue string, ch chan *Msg) (*Subscription, error) { + return nc.subscribe(subj, queue, nil, ch, nil, false, nil) } // badSubject will do quick test on whether a subject is acceptable. @@ -3285,54 +4589,23 @@ func badQueue(qname string) bool { } // subscribe is the internal subscribe function that indicates interest in a subject. -func (nc *Conn) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, isSync bool, opts ...SubscribeOption) (*Subscription, error) { +func (nc *Conn) subscribe(subj, queue string, cb MsgHandler, ch chan *Msg, errCh chan (error), isSync bool, js *jsSub) (*Subscription, error) { if nc == nil { return nil, ErrInvalidConnection } - - var aopts *jsOpts - if len(opts) > 0 { - aopts = newJsOpts() - for _, f := range opts { - if err := f(aopts); err != nil { - return nil, err - } - } - - if subj == "" { - subj = NewInbox() - } - } - nc.mu.Lock() - s, err := nc.subscribeLocked(subj, queue, cb, ch, isSync, opts...) - nc.mu.Unlock() - if err != nil { - return nil, err - } - - // here so that interest exist already when doing ephemerals - if aopts != nil { - nfo, err := nc.createOrUpdateConsumer(aopts, subj) - if err != nil { - s.Unsubscribe() - return nil, fmt.Errorf("nats: JetStream consumer creation failed: %s", err) - } - - s.ConsumerConfig = &nfo.Config - } - - return s, nil + defer nc.mu.Unlock() + return nc.subscribeLocked(subj, queue, cb, ch, errCh, isSync, js) } -func (nc *Conn) subscribeLocked(subj, queue string, cb MsgHandler, ch chan *Msg, isSync bool, opts ...SubscribeOption) (*Subscription, error) { +func (nc *Conn) subscribeLocked(subj, queue string, cb MsgHandler, ch chan *Msg, errCh chan (error), isSync bool, js *jsSub) (*Subscription, error) { if nc == nil { return nil, ErrInvalidConnection } if badSubject(subj) { return nil, ErrBadSubject } - if queue != "" && badQueue(queue) { + if queue != _EMPTY_ && badQueue(queue) { return nil, ErrBadQueueName } @@ -3348,23 +4621,35 @@ func (nc *Conn) subscribeLocked(subj, queue string, cb MsgHandler, ch chan *Msg, return nil, ErrBadSubscription } - sub := &Subscription{Subject: subj, Queue: queue, mcb: cb, conn: nc} + sub := &Subscription{ + Subject: subj, + Queue: queue, + mcb: cb, + conn: nc, + jsi: js, + } // Set pending limits. - sub.pMsgsLimit = DefaultSubPendingMsgsLimit + if ch != nil { + sub.pMsgsLimit = cap(ch) + } else { + sub.pMsgsLimit = DefaultSubPendingMsgsLimit + } sub.pBytesLimit = DefaultSubPendingBytesLimit // If we have an async callback, start up a sub specific // Go routine to deliver the messages. + var sr bool if cb != nil { sub.typ = AsyncSubscription sub.pCond = sync.NewCond(&sub.mu) - go nc.waitForMsgs(sub) + sr = true } else if !isSync { sub.typ = ChanSubscription sub.mch = ch } else { // Sync Subscription sub.typ = SyncSubscription sub.mch = ch + sub.errCh = errCh } nc.subsMu.Lock() @@ -3373,16 +4658,19 @@ func (nc *Conn) subscribeLocked(subj, queue string, cb MsgHandler, ch chan *Msg, nc.subs[sub.sid] = sub nc.subsMu.Unlock() + // Let's start the go routine now that it is fully setup and registered. + if sr { + go nc.waitForMsgs(sub) + } + // We will send these for all subs when we reconnect // so that we can suppress here if reconnecting. if !nc.isReconnecting() { - fmt.Fprintf(nc.bw, subProto, subj, queue, sub.sid) - // Kick flusher if needed. - if len(nc.fch) == 0 { - nc.kickFlusher() - } + nc.bw.appendString(fmt.Sprintf(subProto, subj, queue, sub.sid)) + nc.kickFlusher() } + sub.changeSubStatus(SubscriptionActive) return sub, nil } @@ -3406,8 +4694,27 @@ func (nc *Conn) removeSub(s *Subscription) { } s.mch = nil + // If JS subscription then stop HB timer. + if jsi := s.jsi; jsi != nil { + if jsi.hbc != nil { + jsi.hbc.Stop() + jsi.hbc = nil + } + if jsi.csfct != nil { + jsi.csfct.Stop() + jsi.csfct = nil + } + } + + if s.typ != AsyncSubscription { + done := s.pDone + if done != nil { + done(s.Subject) + } + } // Mark as invalid s.closed = true + s.changeSubStatus(SubscriptionClosed) if s.pCond != nil { s.pCond.Broadcast() } @@ -3422,6 +4729,7 @@ const ( SyncSubscription ChanSubscription NilSubscription + PullSubscription ) // Type returns the type of Subscription. @@ -3431,6 +4739,12 @@ func (s *Subscription) Type() SubscriptionType { } s.mu.Lock() defer s.mu.Unlock() + // Pull subscriptions are really a SyncSubscription and we want this + // type to be set internally for all delivered messages management, etc.. + // So check when to return PullSubscription to the user. + if s.jsi != nil && s.jsi.pull { + return PullSubscription + } return s.typ } @@ -3448,6 +4762,15 @@ func (s *Subscription) IsValid() bool { // Drain will remove interest but continue callbacks until all messages // have been processed. +// +// For a JetStream subscription, if the library has created the JetStream +// consumer, the library will send a DeleteConsumer request to the server +// when the Drain operation completes. If a failure occurs when deleting +// the JetStream consumer, an error will be reported to the asynchronous +// error callback. +// If you do not wish the JetStream consumer to be automatically deleted, +// ensure that the consumer is not created by the library, which means +// create the consumer with AddConsumer and bind to this consumer. func (s *Subscription) Drain() error { if s == nil { return ErrBadSubscription @@ -3461,7 +4784,99 @@ func (s *Subscription) Drain() error { return conn.unsubscribe(s, 0, true) } +// IsDraining returns a boolean indicating whether the subscription +// is being drained. +// This will return false if the subscription has already been closed. +func (s *Subscription) IsDraining() bool { + if s == nil { + return false + } + s.mu.Lock() + defer s.mu.Unlock() + return s.draining +} + +// StatusChanged returns a channel on which given list of subscription status +// changes will be sent. If no status is provided, all status changes will be sent. +// Available statuses are SubscriptionActive, SubscriptionDraining, SubscriptionClosed, +// and SubscriptionSlowConsumer. +// The returned channel will be closed when the subscription is closed. +func (s *Subscription) StatusChanged(statuses ...SubStatus) <-chan SubStatus { + if len(statuses) == 0 { + statuses = []SubStatus{SubscriptionActive, SubscriptionDraining, SubscriptionClosed, SubscriptionSlowConsumer} + } + ch := make(chan SubStatus, 10) + s.mu.Lock() + defer s.mu.Unlock() + for _, status := range statuses { + s.registerStatusChangeListener(status, ch) + // initial status + if status == s.status { + ch <- status + } + } + return ch +} + +// registerStatusChangeListener registers a channel waiting for a specific status change event. +// Status change events are non-blocking - if no receiver is waiting for the status change, +// it will not be sent on the channel. Closed channels are ignored. +// Lock should be held entering. +func (s *Subscription) registerStatusChangeListener(status SubStatus, ch chan SubStatus) { + if s.statListeners == nil { + s.statListeners = make(map[chan SubStatus][]SubStatus) + } + if _, ok := s.statListeners[ch]; !ok { + s.statListeners[ch] = make([]SubStatus, 0) + } + s.statListeners[ch] = append(s.statListeners[ch], status) +} + +// sendStatusEvent sends subscription status event to all channels. +// If there is no listener, sendStatusEvent +// will not block. Lock should be held entering. +func (s *Subscription) sendStatusEvent(status SubStatus) { + for ch, statuses := range s.statListeners { + if !slices.Contains(statuses, status) { + continue + } + // only send event if someone's listening + select { + case ch <- status: + default: + } + } + // After sending SubscriptionClosed status to all listeners, + // close all channels and clear the map to prevent future + // sends to closed channels that could cause panics + if status == SubscriptionClosed { + for ch := range s.statListeners { + close(ch) + } + s.statListeners = nil + } +} + +// changeSubStatus changes subscription status and sends events +// to all listeners. Lock should be held entering. +func (s *Subscription) changeSubStatus(status SubStatus) { + if s == nil { + return + } + s.sendStatusEvent(status) + s.status = status +} + // Unsubscribe will remove interest in the given subject. +// +// For a JetStream subscription, if the library has created the JetStream +// consumer, it will send a DeleteConsumer request to the server (if the +// unsubscribe itself was successful). If the delete operation fails, the +// error will be returned. +// If you do not wish the JetStream consumer to be automatically deleted, +// ensure that the consumer is not created by the library, which means +// create the consumer with AddConsumer and bind to this consumer (using +// the nats.Bind() option). func (s *Subscription) Unsubscribe() error { if s == nil { return ErrBadSubscription @@ -3469,6 +4884,7 @@ func (s *Subscription) Unsubscribe() error { s.mu.Lock() conn := s.conn closed := s.closed + dc := s.jsi != nil && s.jsi.dc s.mu.Unlock() if conn == nil || conn.IsClosed() { return ErrConnectionClosed @@ -3479,7 +4895,11 @@ func (s *Subscription) Unsubscribe() error { if conn.IsDraining() { return ErrConnectionDraining } - return conn.unsubscribe(s, 0, false) + err := conn.unsubscribe(s, 0, false) + if err == nil && dc { + err = s.deleteConsumer() + } + return err } // checkDrained will watch for a subscription to be fully drained @@ -3488,11 +4908,22 @@ func (nc *Conn) checkDrained(sub *Subscription) { if nc == nil || sub == nil { return } + defer func() { + sub.mu.Lock() + defer sub.mu.Unlock() + sub.draining = false + }() // This allows us to know that whatever we have in the client pending // is correct and the server will not send additional information. nc.Flush() + sub.mu.Lock() + // For JS subscriptions, check if we are going to delete the + // JS consumer when drain completes. + dc := sub.jsi != nil && sub.jsi.dc + sub.mu.Unlock() + // Once we are here we just wait for Pending to reach 0 or // any other state to exit this go routine. for { @@ -3512,6 +4943,15 @@ func (nc *Conn) checkDrained(sub *Subscription) { nc.mu.Lock() nc.removeSub(sub) nc.mu.Unlock() + if dc { + if err := sub.deleteConsumer(); err != nil { + nc.mu.Lock() + if errCB := nc.Opts.AsyncErrorCB; errCB != nil { + nc.ach.push(func() { errCB(nc, sub, err) }) + } + nc.mu.Unlock() + } + } return } @@ -3537,13 +4977,30 @@ func (s *Subscription) AutoUnsubscribe(max int) error { return conn.unsubscribe(s, max, false) } +// SetClosedHandler will set the closed handler for when a subscription +// is closed (either unsubscribed or drained). +func (s *Subscription) SetClosedHandler(handler func(subject string)) { + s.mu.Lock() + s.pDone = handler + s.mu.Unlock() +} + // unsubscribe performs the low level unsubscribe to the server. // Use Subscription.Unsubscribe() func (nc *Conn) unsubscribe(sub *Subscription, max int, drainMode bool) error { + var maxStr string + if max > 0 { + sub.mu.Lock() + sub.max = uint64(max) + if sub.delivered < sub.max { + maxStr = strconv.Itoa(max) + } + sub.mu.Unlock() + } + nc.mu.Lock() // ok here, but defer is expensive defer nc.mu.Unlock() - defer nc.kickFlusher() if nc.isClosed() { return ErrConnectionClosed @@ -3557,36 +5014,52 @@ func (nc *Conn) unsubscribe(sub *Subscription, max int, drainMode bool) error { return nil } - maxStr := _EMPTY_ - if max > 0 { - s.max = uint64(max) - maxStr = strconv.Itoa(max) - } else if !drainMode { + if maxStr == _EMPTY_ && !drainMode { nc.removeSub(s) } if drainMode { + s.mu.Lock() + s.draining = true + sub.changeSubStatus(SubscriptionDraining) + s.mu.Unlock() go nc.checkDrained(sub) } // We will send these for all subs when we reconnect // so that we can suppress here. if !nc.isReconnecting() { - fmt.Fprintf(nc.bw, unsubProto, s.sid, maxStr) + nc.bw.appendString(fmt.Sprintf(unsubProto, s.sid, maxStr)) + nc.kickFlusher() + } + + // For JetStream subscriptions cancel the attached context if there is any. + var cancel func() + sub.mu.Lock() + jsi := sub.jsi + if jsi != nil { + cancel = jsi.cancel + jsi.cancel = nil + } + sub.mu.Unlock() + if cancel != nil { + cancel() } + return nil } // NextMsg will return the next message available to a synchronous subscriber // or block until one is available. An error is returned if the subscription is invalid (ErrBadSubscription), -// the connection is closed (ErrConnectionClosed), or the timeout is reached (ErrTimeout). +// the connection is closed (ErrConnectionClosed), the timeout is reached (ErrTimeout), +// or if there were no responders (ErrNoResponders) when used in the context of a request/reply. func (s *Subscription) NextMsg(timeout time.Duration) (*Msg, error) { if s == nil { return nil, ErrBadSubscription } s.mu.Lock() - err := s.validateNextMsgState() + err := s.validateNextMsgState(false) if err != nil { s.mu.Unlock() return nil, err @@ -3619,16 +5092,92 @@ func (s *Subscription) NextMsg(timeout time.Duration) (*Msg, error) { t := globalTimerPool.Get(timeout) defer globalTimerPool.Put(t) + if s.errCh != nil { + select { + case msg, ok = <-mch: + if !ok { + return nil, s.getNextMsgErr() + } + if err := s.processNextMsgDelivered(msg); err != nil { + return nil, err + } + case err := <-s.errCh: + return nil, err + case <-t.C: + return nil, ErrTimeout + } + } else { + select { + case msg, ok = <-mch: + if !ok { + return nil, s.getNextMsgErr() + } + if err := s.processNextMsgDelivered(msg); err != nil { + return nil, err + } + case <-t.C: + return nil, ErrTimeout + } + } + + return msg, nil +} + +// nextMsgNoTimeout works similarly to Subscription.NextMsg() but will not +// time out. It is only used internally for non-timeout subscription iterator. +func (s *Subscription) nextMsgNoTimeout() (*Msg, error) { + if s == nil { + return nil, ErrBadSubscription + } + + s.mu.Lock() + err := s.validateNextMsgState(false) + if err != nil { + s.mu.Unlock() + return nil, err + } + + // snapshot + mch := s.mch + s.mu.Unlock() + + var ok bool + var msg *Msg + + // If something is available right away, let's optimize that case. select { case msg, ok = <-mch: + if !ok { + return nil, s.getNextMsgErr() + } + if err := s.processNextMsgDelivered(msg); err != nil { + return nil, err + } else { + return msg, nil + } + default: + } + + if s.errCh != nil { + select { + case msg, ok = <-mch: + if !ok { + return nil, s.getNextMsgErr() + } + if err := s.processNextMsgDelivered(msg); err != nil { + return nil, err + } + case err := <-s.errCh: + return nil, err + } + } else { + msg, ok = <-mch if !ok { return nil, s.getNextMsgErr() } if err := s.processNextMsgDelivered(msg); err != nil { return nil, err } - case <-t.C: - return nil, ErrTimeout } return msg, nil @@ -3637,7 +5186,7 @@ func (s *Subscription) NextMsg(timeout time.Duration) (*Msg, error) { // validateNextMsgState checks whether the subscription is in a valid // state to call NextMsg and be delivered another message synchronously. // This should be called while holding the lock. -func (s *Subscription) validateNextMsgState() error { +func (s *Subscription) validateNextMsgState(pullSubInternal bool) error { if s.connClosed { return ErrConnectionClosed } @@ -3651,11 +5200,22 @@ func (s *Subscription) validateNextMsgState() error { if s.mcb != nil { return ErrSyncSubRequired } + // if this subscription previously had a permissions error + // and no reconnect has been attempted, return the permissions error + // since the subscription does not exist on the server + if s.conn.Opts.PermissionErrOnSubscribe && s.permissionsErr != nil { + return s.permissionsErr + } if s.sc { + s.changeSubStatus(SubscriptionActive) s.sc = false return ErrSlowConsumer } - + // Unless this is from an internal call, reject use of this API. + // Users should use Fetch() instead. + if !pullSubInternal && s.jsi != nil && s.jsi.pull { + return ErrTypeSubscription + } return nil } @@ -3680,15 +5240,24 @@ func (s *Subscription) processNextMsgDelivered(msg *Msg) error { nc := s.conn max := s.max + var fcReply string // Update some stats. s.delivered++ delivered := s.delivered + if s.jsi != nil { + fcReply = s.checkForFlowControlResponse() + } + if s.typ == SyncSubscription { s.pMsgs-- s.pBytes -= len(msg.Data) } s.mu.Unlock() + if fcReply != _EMPTY_ { + nc.Publish(fcReply, nil) + } + if max > 0 { if delivered > max { return ErrMaxMessages @@ -3700,12 +5269,16 @@ func (s *Subscription) processNextMsgDelivered(msg *Msg) error { nc.mu.Unlock() } } + if len(msg.Data) == 0 && msg.Header.Get(statusHdr) == noResponders { + return ErrNoResponders + } return nil } // Queued returns the number of queued messages in the client for this subscription. -// DEPRECATED: Use Pending() +// +// Deprecated: Use Pending() func (s *Subscription) QueuedMsgs() (int, error) { m, _, err := s.Pending() return int(m), err @@ -3762,8 +5335,10 @@ func (s *Subscription) ClearMaxPending() error { // Pending Limits const ( - DefaultSubPendingMsgsLimit = 65536 - DefaultSubPendingBytesLimit = 65536 * 1024 + // DefaultSubPendingMsgsLimit will be 500k msgs. + DefaultSubPendingMsgsLimit = 500_000 + // DefaultSubPendingBytesLimit is 64MB + DefaultSubPendingBytesLimit = 64 * 1024 * 1024 ) // PendingLimits returns the current limits for this subscription. @@ -3857,6 +5432,7 @@ func (m *Msg) RespondMsg(msg *Msg) error { if m.Reply == "" { return ErrMsgNoReply } + msg.Subject = m.Reply m.Sub.mu.Lock() nc := m.Sub.conn m.Sub.mu.Unlock() @@ -3886,9 +5462,9 @@ func (nc *Conn) removeFlushEntry(ch chan struct{}) bool { // The lock must be held entering this function. func (nc *Conn) sendPing(ch chan struct{}) { nc.pongs = append(nc.pongs, ch) - nc.bw.WriteString(pingProto) + nc.bw.appendString(pingProto) // Flush in place. - nc.bw.Flush() + nc.bw.flush() } // This will fire periodically and send a client origin @@ -3906,7 +5482,9 @@ func (nc *Conn) processPingTimer() { nc.pout++ if nc.pout > nc.Opts.MaxPingsOut { nc.mu.Unlock() - nc.processOpErr(ErrStaleConnection) + if shouldClose := nc.processOpErr(ErrStaleConnection); shouldClose { + nc.close(CLOSED, true, nil) + } return } @@ -3985,7 +5563,7 @@ func (nc *Conn) Buffered() (int, error) { if nc.isClosed() || nc.bw == nil { return -1, ErrConnectionClosed } - return nc.bw.Buffered(), nil + return nc.bw.buffered(), nil } // resendSubscriptions will send our subscription state back to the @@ -4003,6 +5581,9 @@ func (nc *Conn) resendSubscriptions() { for _, s := range subs { adjustedMax := uint64(0) s.mu.Lock() + // when resending subscriptions, the permissions error should be cleared + // since the user may have fixed the permissions issue + s.permissionsErr = nil if s.max > 0 { if s.delivered < s.max { adjustedMax = s.max - s.delivered @@ -4011,16 +5592,17 @@ func (nc *Conn) resendSubscriptions() { // reached the max, if so unsubscribe. if adjustedMax == 0 { s.mu.Unlock() - fmt.Fprintf(nc.bw, unsubProto, s.sid, _EMPTY_) + nc.bw.writeDirect(fmt.Sprintf(unsubProto, s.sid, _EMPTY_)) continue } } + subj, queue, sid := s.Subject, s.Queue, s.sid s.mu.Unlock() - fmt.Fprintf(nc.bw, subProto, s.Subject, s.Queue, s.sid) + nc.bw.writeDirect(fmt.Sprintf(subProto, subj, queue, sid)) if adjustedMax > 0 { maxStr := strconv.Itoa(int(adjustedMax)) - fmt.Fprintf(nc.bw, unsubProto, s.sid, maxStr) + nc.bw.writeDirect(fmt.Sprintf(unsubProto, sid, maxStr)) } } } @@ -4040,9 +5622,6 @@ func (nc *Conn) clearPendingFlushCalls() { // This will clear any pending Request calls. // Lock is assumed to be held by the caller. func (nc *Conn) clearPendingRequestCalls() { - if nc.respMap == nil { - return - } for key, ch := range nc.respMap { if ch != nil { close(ch) @@ -4084,7 +5663,7 @@ func (nc *Conn) close(status Status, doCBs bool, err error) { nc.stopPingTimer() nc.ptmr = nil - // Need to close and set tcp conn to nil if reconnect loop has stopped, + // Need to close and set TCP conn to nil if reconnect loop has stopped, // otherwise we would incorrectly invoke Disconnect handler (if set) // down below. if nc.ar && nc.conn != nil { @@ -4092,7 +5671,7 @@ func (nc *Conn) close(status Status, doCBs bool, err error) { nc.conn = nil } else if nc.conn != nil { // Go ahead and make sure we have flushed the outbound - nc.bw.Flush() + nc.bw.flush() defer nc.conn.Close() } @@ -4107,7 +5686,15 @@ func (nc *Conn) close(status Status, doCBs bool, err error) { close(s.mch) } s.mch = nil - // Mark as invalid, for signaling to deliverMsgs + + // Call closed handler for non-AsyncSubscription types (AsyncSubscription handlers + // are called by waitForMsgs when it exits) + var done func(string) + if s.typ != AsyncSubscription && s.pDone != nil { + done = s.pDone + } + + // Mark as invalid, for signaling to waitForMsgs s.closed = true // Mark connection closed in subscription s.connClosed = true @@ -4117,27 +5704,32 @@ func (nc *Conn) close(status Status, doCBs bool, err error) { } s.mu.Unlock() + + // Call the closed handler outside the lock to avoid potential deadlocks + if done != nil { + done(s.Subject) + } } nc.subs = nil nc.subsMu.Unlock() - nc.status = status + nc.changeConnStatus(status) // Perform appropriate callback if needed for a disconnect. if doCBs { if nc.conn != nil { - if nc.Opts.DisconnectedErrCB != nil { - nc.ach.push(func() { nc.Opts.DisconnectedErrCB(nc, err) }) - } else if nc.Opts.DisconnectedCB != nil { - nc.ach.push(func() { nc.Opts.DisconnectedCB(nc) }) + if disconnectedErrCB := nc.Opts.DisconnectedErrCB; disconnectedErrCB != nil { + nc.ach.push(func() { disconnectedErrCB(nc, err) }) + } else if disconnectedCB := nc.Opts.DisconnectedCB; disconnectedCB != nil { + nc.ach.push(func() { disconnectedCB(nc) }) } } - if nc.Opts.ClosedCB != nil { - nc.ach.push(func() { nc.Opts.ClosedCB(nc) }) + if closedCB := nc.Opts.ClosedCB; closedCB != nil { + nc.ach.push(func() { closedCB(nc) }) } } // If this is terminal, then we have to notify the asyncCB handler that - // it can exit once all async cbs have been dispatched. + // it can exit once all async callbacks have been dispatched. if status == CLOSED { nc.ach.close() } @@ -4148,6 +5740,12 @@ func (nc *Conn) close(status Status, doCBs bool, err error) { // all blocking calls, such as Flush() and NextMsg() func (nc *Conn) Close() { if nc != nil { + // This will be a no-op if the connection was not websocket. + // We do this here as opposed to inside close() because we want + // to do this only for the final user-driven close of the client. + // Otherwise, we would need to change close() to pass a boolean + // indicating that this is the case. + nc.wsClose() nc.close(CLOSED, !nc.Opts.NoCallbacksAfterClientClose, nil) } } @@ -4187,16 +5785,22 @@ func (nc *Conn) drainConnection() { if nc.isConnecting() || nc.isReconnecting() { nc.mu.Unlock() // Move to closed state. - nc.close(CLOSED, true, nil) + nc.Close() return } subs := make([]*Subscription, 0, len(nc.subs)) for _, s := range nc.subs { + if s == nc.respMux { + // Skip since might be in use while messages + // are being processed (can miss responses). + continue + } subs = append(subs, s) } errCB := nc.Opts.AsyncErrorCB drainWait := nc.Opts.DrainTimeout + respMux := nc.respMux nc.mu.Unlock() // for pushing errors with context. @@ -4209,7 +5813,7 @@ func (nc *Conn) drainConnection() { nc.mu.Unlock() } - // Do subs first + // Do subs first, skip request handler if present. for _, s := range subs { if err := s.Drain(); err != nil { // We will notify about these but continue. @@ -4219,13 +5823,34 @@ func (nc *Conn) drainConnection() { // Wait for the subscriptions to drop to zero. timeout := time.Now().Add(drainWait) + var min int + if respMux != nil { + min = 1 + } else { + min = 0 + } for time.Now().Before(timeout) { - if nc.NumSubscriptions() == 0 { + if nc.NumSubscriptions() == min { break } time.Sleep(10 * time.Millisecond) } + // In case there was a request/response handler + // then need to call drain at the end. + if respMux != nil { + if err := respMux.Drain(); err != nil { + // We will notify about these but continue. + pushErr(err) + } + for time.Now().Before(timeout) { + if nc.NumSubscriptions() == 0 { + break + } + time.Sleep(10 * time.Millisecond) + } + } + // Check if we timed out. if nc.NumSubscriptions() != 0 { pushErr(ErrDrainTimeout) @@ -4233,26 +5858,26 @@ func (nc *Conn) drainConnection() { // Flip State nc.mu.Lock() - nc.status = DRAINING_PUBS + nc.changeConnStatus(DRAINING_PUBS) nc.mu.Unlock() // Do publish drain via Flush() call. err := nc.FlushTimeout(5 * time.Second) if err != nil { pushErr(err) - nc.close(CLOSED, true, nil) - return } // Move to closed state. - nc.close(CLOSED, true, nil) + nc.Close() } // Drain will put a connection into a drain state. All subscriptions will // immediately be put into a drain state. Upon completion, the publishers // will be drained and can not publish any additional messages. Upon draining -// of the publishers, the connection will be closed. Use the ClosedCB() +// of the publishers, the connection will be closed. Use the ClosedCB // option to know when the connection has moved from draining to closed. +// +// See note in Subscription.Drain for JetStream subscriptions. func (nc *Conn) Drain() error { nc.mu.Lock() if nc.isClosed() { @@ -4261,14 +5886,14 @@ func (nc *Conn) Drain() error { } if nc.isConnecting() || nc.isReconnecting() { nc.mu.Unlock() - nc.close(CLOSED, true, nil) + nc.Close() return ErrConnectionReconnecting } if nc.isDraining() { nc.mu.Unlock() return nil } - nc.status = DRAINING_SUBS + nc.changeConnStatus(DRAINING_SUBS) go nc.drainConnection() nc.mu.Unlock() @@ -4285,7 +5910,7 @@ func (nc *Conn) IsDraining() bool { // caller must lock func (nc *Conn) getServers(implicitOnly bool) []string { poolSize := len(nc.srvPool) - var servers = make([]string, 0) + servers := make([]string, 0) for i := 0; i < poolSize; i++ { if implicitOnly && !nc.srvPool[i].isImplicit { continue @@ -4478,6 +6103,88 @@ func (nc *Conn) GetClientID() (uint64, error) { return nc.info.CID, nil } +// StatusChanged returns a channel on which given list of connection status changes will be reported. +// If no statuses are provided, defaults will be used: CONNECTED, RECONNECTING, DISCONNECTED, CLOSED. +func (nc *Conn) StatusChanged(statuses ...Status) chan Status { + if len(statuses) == 0 { + statuses = []Status{CONNECTED, RECONNECTING, DISCONNECTED, CLOSED} + } + ch := make(chan Status, 10) + nc.mu.Lock() + defer nc.mu.Unlock() + for _, s := range statuses { + nc.registerStatusChangeListener(s, ch) + } + return ch +} + +// RemoveStatusListener removes a status change listener. +// If the channel is not closed, it will be closed. +// Listeners will be removed automatically on status change +// as well, but this is a way to remove them manually. +func (nc *Conn) RemoveStatusListener(ch chan (Status)) { + nc.mu.Lock() + defer nc.mu.Unlock() + + select { + case <-ch: + default: + close(ch) + } + + for _, listeners := range nc.statListeners { + for l := range listeners { + delete(listeners, l) + } + } +} + +// registerStatusChangeListener registers a channel waiting for a specific status change event. +// Status change events are non-blocking - if no receiver is waiting for the status change, +// it will not be sent on the channel. Closed channels are ignored. +// The lock should be held entering. +func (nc *Conn) registerStatusChangeListener(status Status, ch chan Status) { + if nc.statListeners == nil { + nc.statListeners = make(map[Status]map[chan Status]struct{}) + } + if _, ok := nc.statListeners[status]; !ok { + nc.statListeners[status] = make(map[chan Status]struct{}) + } + nc.statListeners[status][ch] = struct{}{} +} + +// sendStatusEvent sends connection status event to all channels. +// If channel is closed, or there is no listener, sendStatusEvent +// will not block. Lock should be held entering. +func (nc *Conn) sendStatusEvent(s Status) { +Loop: + for ch := range nc.statListeners[s] { + // make sure channel is not closed + select { + case <-ch: + // if chan is closed, remove it + delete(nc.statListeners[s], ch) + continue Loop + default: + } + // only send event if someone's listening + select { + case ch <- s: + default: + } + } +} + +// changeConnStatus changes connections status and sends events +// to all listeners. Lock should be held entering. +func (nc *Conn) changeConnStatus(status Status) { + if nc == nil { + return + } + nc.sendStatusEvent(status) + nc.status = status +} + // NkeyOptionFromSeed will load an nkey pair from a seed file. // It will return the NKey Option and will handle // signing of nonce challenges from the server. It will take @@ -4495,7 +6202,7 @@ func NkeyOptionFromSeed(seedFile string) (Option, error) { return nil, err } if !nkeys.IsValidPublicUserKey(pub) { - return nil, fmt.Errorf("nats: Not a valid nkey user seed") + return nil, errors.New("nats: Not a valid nkey user seed") } sigCB := func(nonce []byte) ([]byte, error) { return sigHandler(nonce, seedFile) @@ -4513,12 +6220,12 @@ func wipeSlice(buf []byte) { func userFromFile(userFile string) (string, error) { path, err := expandPath(userFile) if err != nil { - return _EMPTY_, fmt.Errorf("nats: %v", err) + return _EMPTY_, fmt.Errorf("nats: %w", err) } - contents, err := ioutil.ReadFile(path) + contents, err := os.ReadFile(path) if err != nil { - return _EMPTY_, fmt.Errorf("nats: %v", err) + return _EMPTY_, fmt.Errorf("nats: %w", err) } defer wipeSlice(contents) return nkeys.ParseDecoratedJWT(contents) @@ -4565,9 +6272,9 @@ func expandPath(p string) (string, error) { } func nkeyPairFromSeedFile(seedFile string) (nkeys.KeyPair, error) { - contents, err := ioutil.ReadFile(seedFile) + contents, err := os.ReadFile(seedFile) if err != nil { - return nil, fmt.Errorf("nats: %v", err) + return nil, fmt.Errorf("nats: %w", err) } defer wipeSlice(contents) return nkeys.ParseDecoratedNKey(contents) @@ -4578,7 +6285,7 @@ func nkeyPairFromSeedFile(seedFile string) (nkeys.KeyPair, error) { func sigHandler(nonce []byte, seedFile string) ([]byte, error) { kp, err := nkeyPairFromSeedFile(seedFile) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to extract key pair from file %q: %w", seedFile, err) } // Wipe our key on exit. defer kp.Wipe() @@ -4590,18 +6297,12 @@ func sigHandler(nonce []byte, seedFile string) ([]byte, error) { type timeoutWriter struct { timeout time.Duration conn net.Conn - err error } // Write implements the io.Writer interface. func (tw *timeoutWriter) Write(p []byte) (int, error) { - if tw.err != nil { - return 0, tw.err - } - - var n int tw.conn.SetWriteDeadline(time.Now().Add(tw.timeout)) - n, tw.err = tw.conn.Write(p) + n, err := tw.conn.Write(p) tw.conn.SetWriteDeadline(time.Time{}) - return n, tw.err + return n, err } diff --git a/vendor/github.com/nats-io/nats.go/nats_iter.go b/vendor/github.com/nats-io/nats.go/nats_iter.go new file mode 100644 index 0000000..05234d5 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/nats_iter.go @@ -0,0 +1,72 @@ +// Copyright 2012-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build go1.23 + +package nats + +import ( + "errors" + "iter" + "time" +) + +// Msgs returns an iter.Seq2[*Msg, error] that can be used to iterate over +// messages. It can only be used with a subscription that has been created with +// SubscribeSync or QueueSubscribeSync, otherwise it will return an error on the +// first iteration. +// +// The iterator will block until a message is available. The +// subscription will not be closed when the iterator is done. +func (sub *Subscription) Msgs() iter.Seq2[*Msg, error] { + return func(yield func(*Msg, error) bool) { + for { + msg, err := sub.nextMsgNoTimeout() + if err != nil { + yield(nil, err) + return + } + if !yield(msg, nil) { + return + } + + } + } +} + +// MsgsTimeout returns an iter.Seq2[*Msg, error] that can be used to iterate +// over messages. It can only be used with a subscription that has been created +// with SubscribeSync or QueueSubscribeSync, otherwise it will return an error +// on the first iteration. +// +// The iterator will block until a message is available or the timeout is +// reached. If the timeout is reached, the iterator will return nats.ErrTimeout +// but it will not be closed. +func (sub *Subscription) MsgsTimeout(timeout time.Duration) iter.Seq2[*Msg, error] { + return func(yield func(*Msg, error) bool) { + for { + msg, err := sub.NextMsg(timeout) + if err != nil { + if !yield(nil, err) { + return + } + if !errors.Is(err, ErrTimeout) { + return + } + } + if !yield(msg, nil) { + return + } + } + } +} diff --git a/vendor/github.com/nats-io/nats.go/netchan.go b/vendor/github.com/nats-io/nats.go/netchan.go index fd86d06..35d9214 100644 --- a/vendor/github.com/nats-io/nats.go/netchan.go +++ b/vendor/github.com/nats-io/nats.go/netchan.go @@ -1,4 +1,4 @@ -// Copyright 2013-2018 The NATS Authors +// Copyright 2013-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -23,7 +23,9 @@ import ( // Data will be encoded and decoded via the EncodedConn and its associated encoders. // BindSendChan binds a channel for send operations to NATS. -func (c *EncodedConn) BindSendChan(subject string, channel interface{}) error { +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) BindSendChan(subject string, channel any) error { chVal := reflect.ValueOf(channel) if chVal.Kind() != reflect.Chan { return ErrChanArg @@ -61,17 +63,21 @@ func chPublish(c *EncodedConn, chVal reflect.Value, subject string) { } // BindRecvChan binds a channel for receive operations from NATS. -func (c *EncodedConn) BindRecvChan(subject string, channel interface{}) (*Subscription, error) { +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) BindRecvChan(subject string, channel any) (*Subscription, error) { return c.bindRecvChan(subject, _EMPTY_, channel) } // BindRecvQueueChan binds a channel for queue-based receive operations from NATS. -func (c *EncodedConn) BindRecvQueueChan(subject, queue string, channel interface{}) (*Subscription, error) { +// +// Deprecated: Encoded connections are no longer supported. +func (c *EncodedConn) BindRecvQueueChan(subject, queue string, channel any) (*Subscription, error) { return c.bindRecvChan(subject, queue, channel) } // Internal function to bind receive operations for a channel. -func (c *EncodedConn) bindRecvChan(subject, queue string, channel interface{}) (*Subscription, error) { +func (c *EncodedConn) bindRecvChan(subject, queue string, channel any) (*Subscription, error) { chVal := reflect.ValueOf(channel) if chVal.Kind() != reflect.Chan { return nil, ErrChanArg @@ -107,5 +113,5 @@ func (c *EncodedConn) bindRecvChan(subject, queue string, channel interface{}) ( chVal.Send(oPtr) } - return c.Conn.subscribe(subject, queue, cb, nil, false) + return c.Conn.subscribe(subject, queue, cb, nil, nil, false, nil) } diff --git a/vendor/github.com/nats-io/nats.go/object.go b/vendor/github.com/nats-io/nats.go/object.go new file mode 100644 index 0000000..a5c1515 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/object.go @@ -0,0 +1,1432 @@ +// Copyright 2021-2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nats + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "hash" + "io" + "net" + "os" + "strings" + "sync" + "time" + + "github.com/nats-io/nats.go/internal/parser" + "github.com/nats-io/nuid" +) + +// ObjectStoreManager creates, loads and deletes Object Stores +type ObjectStoreManager interface { + // ObjectStore will look up and bind to an existing object store instance. + ObjectStore(bucket string) (ObjectStore, error) + // CreateObjectStore will create an object store. + CreateObjectStore(cfg *ObjectStoreConfig) (ObjectStore, error) + // DeleteObjectStore will delete the underlying stream for the named object. + DeleteObjectStore(bucket string) error + // ObjectStoreNames is used to retrieve a list of bucket names + ObjectStoreNames(opts ...ObjectOpt) <-chan string + // ObjectStores is used to retrieve a list of bucket statuses + ObjectStores(opts ...ObjectOpt) <-chan ObjectStoreStatus +} + +// ObjectStore is a blob store capable of storing large objects efficiently in +// JetStream streams +type ObjectStore interface { + // Put will place the contents from the reader into a new object. + Put(obj *ObjectMeta, reader io.Reader, opts ...ObjectOpt) (*ObjectInfo, error) + // Get will pull the named object from the object store. + Get(name string, opts ...GetObjectOpt) (ObjectResult, error) + + // PutBytes is convenience function to put a byte slice into this object store. + PutBytes(name string, data []byte, opts ...ObjectOpt) (*ObjectInfo, error) + // GetBytes is a convenience function to pull an object from this object store and return it as a byte slice. + GetBytes(name string, opts ...GetObjectOpt) ([]byte, error) + + // PutString is convenience function to put a string into this object store. + PutString(name string, data string, opts ...ObjectOpt) (*ObjectInfo, error) + // GetString is a convenience function to pull an object from this object store and return it as a string. + GetString(name string, opts ...GetObjectOpt) (string, error) + + // PutFile is convenience function to put a file into this object store. + PutFile(file string, opts ...ObjectOpt) (*ObjectInfo, error) + // GetFile is a convenience function to pull an object from this object store and place it in a file. + GetFile(name, file string, opts ...GetObjectOpt) error + + // GetInfo will retrieve the current information for the object. + GetInfo(name string, opts ...GetObjectInfoOpt) (*ObjectInfo, error) + // UpdateMeta will update the metadata for the object. + UpdateMeta(name string, meta *ObjectMeta) error + + // Delete will delete the named object. + Delete(name string) error + + // AddLink will add a link to another object. + AddLink(name string, obj *ObjectInfo) (*ObjectInfo, error) + + // AddBucketLink will add a link to another object store. + AddBucketLink(name string, bucket ObjectStore) (*ObjectInfo, error) + + // Seal will seal the object store, no further modifications will be allowed. + Seal() error + + // Watch for changes in the underlying store and receive meta information updates. + Watch(opts ...WatchOpt) (ObjectWatcher, error) + + // List will list all the objects in this store. + List(opts ...ListObjectsOpt) ([]*ObjectInfo, error) + + // Status retrieves run-time status about the backing store of the bucket. + Status() (ObjectStoreStatus, error) +} + +type ObjectOpt interface { + configureObject(opts *objOpts) error +} + +type objOpts struct { + ctx context.Context +} + +// For nats.Context() support. +func (ctx ContextOpt) configureObject(opts *objOpts) error { + opts.ctx = ctx + return nil +} + +// ObjectWatcher is what is returned when doing a watch. +type ObjectWatcher interface { + // Updates returns a channel to read any updates to entries. + Updates() <-chan *ObjectInfo + // Stop will stop this watcher. + Stop() error +} + +var ( + ErrObjectConfigRequired = errors.New("nats: object-store config required") + ErrBadObjectMeta = errors.New("nats: object-store meta information invalid") + ErrObjectNotFound = errors.New("nats: object not found") + ErrInvalidStoreName = errors.New("nats: invalid object-store name") + ErrDigestMismatch = errors.New("nats: received a corrupt object, digests do not match") + ErrInvalidDigestFormat = errors.New("nats: object digest hash has invalid format") + ErrNoObjectsFound = errors.New("nats: no objects found") + ErrObjectAlreadyExists = errors.New("nats: an object already exists with that name") + ErrNameRequired = errors.New("nats: name is required") + ErrNeeds262 = errors.New("nats: object-store requires at least server version 2.6.2") + ErrLinkNotAllowed = errors.New("nats: link cannot be set when putting the object in bucket") + ErrObjectRequired = errors.New("nats: object required") + ErrNoLinkToDeleted = errors.New("nats: not allowed to link to a deleted object") + ErrNoLinkToLink = errors.New("nats: not allowed to link to another link") + ErrCantGetBucket = errors.New("nats: invalid Get, object is a link to a bucket") + ErrBucketRequired = errors.New("nats: bucket required") + ErrBucketMalformed = errors.New("nats: bucket malformed") + ErrUpdateMetaDeleted = errors.New("nats: cannot update meta for a deleted object") +) + +// ObjectStoreConfig is the config for the object store. +type ObjectStoreConfig struct { + Bucket string `json:"bucket"` + Description string `json:"description,omitempty"` + TTL time.Duration `json:"max_age,omitempty"` + MaxBytes int64 `json:"max_bytes,omitempty"` + Storage StorageType `json:"storage,omitempty"` + Replicas int `json:"num_replicas,omitempty"` + Placement *Placement `json:"placement,omitempty"` + + // Bucket-specific metadata + // NOTE: Metadata requires nats-server v2.10.0+ + Metadata map[string]string `json:"metadata,omitempty"` + // Enable underlying stream compression. + // NOTE: Compression is supported for nats-server 2.10.0+ + Compression bool `json:"compression,omitempty"` +} + +type ObjectStoreStatus interface { + // Bucket is the name of the bucket + Bucket() string + // Description is the description supplied when creating the bucket + Description() string + // TTL indicates how long objects are kept in the bucket + TTL() time.Duration + // Storage indicates the underlying JetStream storage technology used to store data + Storage() StorageType + // Replicas indicates how many storage replicas are kept for the data in the bucket + Replicas() int + // Sealed indicates the stream is sealed and cannot be modified in any way + Sealed() bool + // Size is the combined size of all data in the bucket including metadata, in bytes + Size() uint64 + // BackingStore provides details about the underlying storage + BackingStore() string + // Metadata is the user supplied metadata for the bucket + Metadata() map[string]string + // IsCompressed indicates if the data is compressed on disk + IsCompressed() bool +} + +// ObjectMetaOptions +type ObjectMetaOptions struct { + Link *ObjectLink `json:"link,omitempty"` + ChunkSize uint32 `json:"max_chunk_size,omitempty"` +} + +// ObjectMeta is high level information about an object. +type ObjectMeta struct { + Name string `json:"name"` + Description string `json:"description,omitempty"` + Headers Header `json:"headers,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + + // Optional options. + Opts *ObjectMetaOptions `json:"options,omitempty"` +} + +// ObjectInfo is meta plus instance information. +type ObjectInfo struct { + ObjectMeta + Bucket string `json:"bucket"` + NUID string `json:"nuid"` + Size uint64 `json:"size"` + ModTime time.Time `json:"mtime"` + Chunks uint32 `json:"chunks"` + Digest string `json:"digest,omitempty"` + Deleted bool `json:"deleted,omitempty"` +} + +// ObjectLink is used to embed links to other buckets and objects. +type ObjectLink struct { + // Bucket is the name of the other object store. + Bucket string `json:"bucket"` + // Name can be used to link to a single object. + // If empty means this is a link to the whole store, like a directory. + Name string `json:"name,omitempty"` +} + +// ObjectResult will return the underlying stream info and also be an io.ReadCloser. +type ObjectResult interface { + io.ReadCloser + Info() (*ObjectInfo, error) + Error() error +} + +const ( + objNameTmpl = "OBJ_%s" // OBJ_ // stream name + objAllChunksPreTmpl = "$O.%s.C.>" // $O..C.> // chunk stream subject + objAllMetaPreTmpl = "$O.%s.M.>" // $O..M.> // meta stream subject + objChunksPreTmpl = "$O.%s.C.%s" // $O..C. // chunk message subject + objMetaPreTmpl = "$O.%s.M.%s" // $O..M. // meta message subject + objNoPending = "0" + objDefaultChunkSize = uint32(128 * 1024) // 128k + objDigestType = "SHA-256=" + objDigestTmpl = objDigestType + "%s" +) + +type obs struct { + name string + stream string + js *js +} + +// CreateObjectStore will create an object store. +func (js *js) CreateObjectStore(cfg *ObjectStoreConfig) (ObjectStore, error) { + if !js.nc.serverMinVersion(2, 6, 2) { + return nil, ErrNeeds262 + } + if cfg == nil { + return nil, ErrObjectConfigRequired + } + if !validBucketRe.MatchString(cfg.Bucket) { + return nil, ErrInvalidStoreName + } + + name := cfg.Bucket + chunks := fmt.Sprintf(objAllChunksPreTmpl, name) + meta := fmt.Sprintf(objAllMetaPreTmpl, name) + + // We will set explicitly some values so that we can do comparison + // if we get an "already in use" error and need to check if it is same. + // See kv + replicas := cfg.Replicas + if replicas == 0 { + replicas = 1 + } + maxBytes := cfg.MaxBytes + if maxBytes == 0 { + maxBytes = -1 + } + var compression StoreCompression + if cfg.Compression { + compression = S2Compression + } + scfg := &StreamConfig{ + Name: fmt.Sprintf(objNameTmpl, name), + Description: cfg.Description, + Subjects: []string{chunks, meta}, + MaxAge: cfg.TTL, + MaxBytes: maxBytes, + Storage: cfg.Storage, + Replicas: replicas, + Placement: cfg.Placement, + Discard: DiscardNew, + AllowRollup: true, + AllowDirect: true, + Metadata: cfg.Metadata, + Compression: compression, + } + + // Create our stream. + _, err := js.AddStream(scfg) + if err != nil { + return nil, err + } + + return &obs{name: name, stream: scfg.Name, js: js}, nil +} + +// ObjectStore will look up and bind to an existing object store instance. +func (js *js) ObjectStore(bucket string) (ObjectStore, error) { + if !validBucketRe.MatchString(bucket) { + return nil, ErrInvalidStoreName + } + if !js.nc.serverMinVersion(2, 6, 2) { + return nil, ErrNeeds262 + } + + stream := fmt.Sprintf(objNameTmpl, bucket) + si, err := js.StreamInfo(stream) + if err != nil { + return nil, err + } + return &obs{name: bucket, stream: si.Config.Name, js: js}, nil +} + +// DeleteObjectStore will delete the underlying stream for the named object. +func (js *js) DeleteObjectStore(bucket string) error { + stream := fmt.Sprintf(objNameTmpl, bucket) + return js.DeleteStream(stream) +} + +func encodeName(name string) string { + return base64.URLEncoding.EncodeToString([]byte(name)) +} + +// Put will place the contents from the reader into this object-store. +func (obs *obs) Put(meta *ObjectMeta, r io.Reader, opts ...ObjectOpt) (*ObjectInfo, error) { + if meta == nil || meta.Name == "" { + return nil, ErrBadObjectMeta + } + + if meta.Opts == nil { + meta.Opts = &ObjectMetaOptions{ChunkSize: objDefaultChunkSize} + } else if meta.Opts.Link != nil { + return nil, ErrLinkNotAllowed + } else if meta.Opts.ChunkSize == 0 { + meta.Opts.ChunkSize = objDefaultChunkSize + } + + var o objOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureObject(&o); err != nil { + return nil, err + } + } + } + ctx := o.ctx + + // Create the new nuid so chunks go on a new subject if the name is re-used + newnuid := nuid.Next() + + // These will be used in more than one place + chunkSubj := fmt.Sprintf(objChunksPreTmpl, obs.name, newnuid) + + // Grab existing meta info (einfo). Ok to be found or not found, any other error is a problem + // Chunks on the old nuid can be cleaned up at the end + einfo, err := obs.GetInfo(meta.Name, GetObjectInfoShowDeleted()) // GetInfo will encode the name + if err != nil && err != ErrObjectNotFound { + return nil, err + } + + // For async error handling + var perr error + var mu sync.Mutex + setErr := func(err error) { + mu.Lock() + defer mu.Unlock() + perr = err + } + getErr := func() error { + mu.Lock() + defer mu.Unlock() + return perr + } + + // Create our own JS context to handle errors etc. + jetStream, err := obs.js.nc.JetStream(PublishAsyncErrHandler(func(js JetStream, _ *Msg, err error) { setErr(err) })) + if err != nil { + return nil, err + } + + defer jetStream.(*js).cleanupReplySub() + + purgePartial := func() error { + // wait until all pubs are complete or up to default timeout before attempting purge + select { + case <-jetStream.PublishAsyncComplete(): + case <-time.After(obs.js.opts.wait): + } + if err := obs.js.purgeStream(obs.stream, &StreamPurgeRequest{Subject: chunkSubj}); err != nil { + return fmt.Errorf("could not cleanup bucket after erroneous put operation: %w", err) + } + return nil + } + + m, h := NewMsg(chunkSubj), sha256.New() + chunk, sent, total := make([]byte, meta.Opts.ChunkSize), 0, uint64(0) + + // set up the info object. The chunk upload sets the size and digest + info := &ObjectInfo{Bucket: obs.name, NUID: newnuid, ObjectMeta: *meta} + + for r != nil { + if ctx != nil { + select { + case <-ctx.Done(): + if ctx.Err() == context.Canceled { + err = ctx.Err() + } else { + err = ErrTimeout + } + default: + } + if err != nil { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(err, purgeErr) + } + return nil, err + } + } + + // Actual read. + // TODO(dlc) - Deadline? + n, readErr := r.Read(chunk) + + // Handle all non EOF errors + if readErr != nil && readErr != io.EOF { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(readErr, purgeErr) + } + return nil, readErr + } + + // Add chunk only if we received data + if n > 0 { + // Chunk processing. + m.Data = chunk[:n] + h.Write(m.Data) + + // Send msg itself. + if _, err := jetStream.PublishMsgAsync(m); err != nil { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(err, purgeErr) + } + return nil, err + } + if err := getErr(); err != nil { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(err, purgeErr) + } + return nil, err + } + // Update totals. + sent++ + total += uint64(n) + } + + // EOF Processing. + if readErr == io.EOF { + // Place meta info. + info.Size, info.Chunks = uint64(total), uint32(sent) + info.Digest = GetObjectDigestValue(h) + break + } + } + + // Prepare the meta message + metaSubj := fmt.Sprintf(objMetaPreTmpl, obs.name, encodeName(meta.Name)) + mm := NewMsg(metaSubj) + mm.Header.Set(MsgRollup, MsgRollupSubject) + mm.Data, err = json.Marshal(info) + if err != nil { + if r != nil { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(err, purgeErr) + } + } + return nil, err + } + + // Publish the meta message. + _, err = jetStream.PublishMsgAsync(mm) + if err != nil { + if r != nil { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(err, purgeErr) + } + } + return nil, err + } + + // Wait for all to be processed. + select { + case <-jetStream.PublishAsyncComplete(): + if err := getErr(); err != nil { + if r != nil { + if purgeErr := purgePartial(); purgeErr != nil { + return nil, errors.Join(err, purgeErr) + } + } + return nil, err + } + case <-time.After(obs.js.opts.wait): + return nil, ErrTimeout + } + + info.ModTime = time.Now().UTC() // This time is not actually the correct time + + // Delete any original chunks. + if einfo != nil && !einfo.Deleted { + echunkSubj := fmt.Sprintf(objChunksPreTmpl, obs.name, einfo.NUID) + if err := obs.js.purgeStream(obs.stream, &StreamPurgeRequest{Subject: echunkSubj}); err != nil { + return info, err + } + } + + // TODO would it be okay to do this to return the info with the correct time? + // With the understanding that it is an extra call to the server. + // Otherwise the time the user gets back is the client time, not the server time. + // return obs.GetInfo(info.Name) + + return info, nil +} + +// GetObjectDigestValue calculates the base64 value of hashed data +func GetObjectDigestValue(data hash.Hash) string { + sha := data.Sum(nil) + return fmt.Sprintf(objDigestTmpl, base64.URLEncoding.EncodeToString(sha[:])) +} + +// DecodeObjectDigest decodes base64 hash +func DecodeObjectDigest(data string) ([]byte, error) { + digest := strings.SplitN(data, "=", 2) + if len(digest) != 2 { + return nil, ErrInvalidDigestFormat + } + return base64.URLEncoding.DecodeString(digest[1]) +} + +// ObjectResult impl. +type objResult struct { + sync.Mutex + info *ObjectInfo + r io.ReadCloser + err error + ctx context.Context + digest hash.Hash + readTimeout time.Duration +} + +func (info *ObjectInfo) isLink() bool { + return info.ObjectMeta.Opts != nil && info.ObjectMeta.Opts.Link != nil +} + +type GetObjectOpt interface { + configureGetObject(opts *getObjectOpts) error +} +type getObjectOpts struct { + ctx context.Context + // Include deleted object in the result. + showDeleted bool +} + +type getObjectFn func(opts *getObjectOpts) error + +func (opt getObjectFn) configureGetObject(opts *getObjectOpts) error { + return opt(opts) +} + +// GetObjectShowDeleted makes Get() return object if it was marked as deleted. +func GetObjectShowDeleted() GetObjectOpt { + return getObjectFn(func(opts *getObjectOpts) error { + opts.showDeleted = true + return nil + }) +} + +// For nats.Context() support. +func (ctx ContextOpt) configureGetObject(opts *getObjectOpts) error { + opts.ctx = ctx + return nil +} + +// Get will pull the object from the underlying stream. +func (obs *obs) Get(name string, opts ...GetObjectOpt) (ObjectResult, error) { + var o getObjectOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureGetObject(&o); err != nil { + return nil, err + } + } + } + ctx := o.ctx + infoOpts := make([]GetObjectInfoOpt, 0) + if ctx != nil { + infoOpts = append(infoOpts, Context(ctx)) + } + if o.showDeleted { + infoOpts = append(infoOpts, GetObjectInfoShowDeleted()) + } + + // Grab meta info. + info, err := obs.GetInfo(name, infoOpts...) + if err != nil { + return nil, err + } + if info.NUID == _EMPTY_ { + return nil, ErrBadObjectMeta + } + + // Check for object links. If single objects we do a pass through. + if info.isLink() { + if info.ObjectMeta.Opts.Link.Name == _EMPTY_ { + return nil, ErrCantGetBucket + } + + // is the link in the same bucket? + lbuck := info.ObjectMeta.Opts.Link.Bucket + if lbuck == obs.name { + return obs.Get(info.ObjectMeta.Opts.Link.Name) + } + + // different bucket + lobs, err := obs.js.ObjectStore(lbuck) + if err != nil { + return nil, err + } + return lobs.Get(info.ObjectMeta.Opts.Link.Name) + } + + result := &objResult{info: info, ctx: ctx, readTimeout: obs.js.opts.wait} + if info.Size == 0 { + return result, nil + } + + pr, pw := net.Pipe() + result.r = pr + + gotErr := func(m *Msg, err error) { + pw.Close() + m.Sub.Unsubscribe() + result.setErr(err) + } + + // For calculating sum256 + result.digest = sha256.New() + + processChunk := func(m *Msg) { + var err error + if ctx != nil { + select { + case <-ctx.Done(): + if errors.Is(ctx.Err(), context.Canceled) { + err = ctx.Err() + } else { + err = ErrTimeout + } + default: + } + if err != nil { + gotErr(m, err) + return + } + } + + tokens, err := parser.GetMetadataFields(m.Reply) + if err != nil { + gotErr(m, err) + return + } + + // Write to our pipe. + for b := m.Data; len(b) > 0; { + n, err := pw.Write(b) + if err != nil { + gotErr(m, err) + return + } + b = b[n:] + } + // Update sha256 + result.digest.Write(m.Data) + + // Check if we are done. + if tokens[parser.AckNumPendingTokenPos] == objNoPending { + pw.Close() + m.Sub.Unsubscribe() + } + } + + chunkSubj := fmt.Sprintf(objChunksPreTmpl, obs.name, info.NUID) + streamName := fmt.Sprintf(objNameTmpl, obs.name) + subscribeOpts := []SubOpt{ + OrderedConsumer(), + BindStream(streamName), + } + _, err = obs.js.Subscribe(chunkSubj, processChunk, subscribeOpts...) + if err != nil { + return nil, err + } + + return result, nil +} + +// Delete will delete the object. +func (obs *obs) Delete(name string) error { + // Grab meta info. + info, err := obs.GetInfo(name, GetObjectInfoShowDeleted()) + if err != nil { + return err + } + if info.NUID == _EMPTY_ { + return ErrBadObjectMeta + } + + // Place a rollup delete marker and publish the info + info.Deleted = true + info.Size, info.Chunks, info.Digest = 0, 0, _EMPTY_ + + if err = publishMeta(info, obs.js); err != nil { + return err + } + + // Purge chunks for the object. + chunkSubj := fmt.Sprintf(objChunksPreTmpl, obs.name, info.NUID) + return obs.js.purgeStream(obs.stream, &StreamPurgeRequest{Subject: chunkSubj}) +} + +func publishMeta(info *ObjectInfo, js JetStreamContext) error { + // marshal the object into json, don't store an actual time + info.ModTime = time.Time{} + data, err := json.Marshal(info) + if err != nil { + return err + } + + // Prepare and publish the message. + mm := NewMsg(fmt.Sprintf(objMetaPreTmpl, info.Bucket, encodeName(info.ObjectMeta.Name))) + mm.Header.Set(MsgRollup, MsgRollupSubject) + mm.Data = data + if _, err := js.PublishMsg(mm); err != nil { + return err + } + + // set the ModTime in case it's returned to the user, even though it's not the correct time. + info.ModTime = time.Now().UTC() + return nil +} + +// AddLink will add a link to another object if it's not deleted and not another link +// name is the name of this link object +// obj is what is being linked too +func (obs *obs) AddLink(name string, obj *ObjectInfo) (*ObjectInfo, error) { + if name == "" { + return nil, ErrNameRequired + } + + // TODO Handle stale info + + if obj == nil || obj.Name == "" { + return nil, ErrObjectRequired + } + if obj.Deleted { + return nil, ErrNoLinkToDeleted + } + if obj.isLink() { + return nil, ErrNoLinkToLink + } + + // If object with link's name is found, error. + // If link with link's name is found, that's okay to overwrite. + // If there was an error that was not ErrObjectNotFound, error. + einfo, err := obs.GetInfo(name, GetObjectInfoShowDeleted()) + if einfo != nil { + if !einfo.isLink() { + return nil, ErrObjectAlreadyExists + } + } else if err != ErrObjectNotFound { + return nil, err + } + + // create the meta for the link + meta := &ObjectMeta{ + Name: name, + Opts: &ObjectMetaOptions{Link: &ObjectLink{Bucket: obj.Bucket, Name: obj.Name}}, + } + info := &ObjectInfo{Bucket: obs.name, NUID: nuid.Next(), ModTime: time.Now().UTC(), ObjectMeta: *meta} + + // put the link object + if err = publishMeta(info, obs.js); err != nil { + return nil, err + } + + return info, nil +} + +// AddBucketLink will add a link to another object store. +func (ob *obs) AddBucketLink(name string, bucket ObjectStore) (*ObjectInfo, error) { + if name == "" { + return nil, ErrNameRequired + } + if bucket == nil { + return nil, ErrBucketRequired + } + bos, ok := bucket.(*obs) + if !ok { + return nil, ErrBucketMalformed + } + + // If object with link's name is found, error. + // If link with link's name is found, that's okay to overwrite. + // If there was an error that was not ErrObjectNotFound, error. + einfo, err := ob.GetInfo(name, GetObjectInfoShowDeleted()) + if einfo != nil { + if !einfo.isLink() { + return nil, ErrObjectAlreadyExists + } + } else if err != ErrObjectNotFound { + return nil, err + } + + // create the meta for the link + meta := &ObjectMeta{ + Name: name, + Opts: &ObjectMetaOptions{Link: &ObjectLink{Bucket: bos.name}}, + } + info := &ObjectInfo{Bucket: ob.name, NUID: nuid.Next(), ObjectMeta: *meta} + + // put the link object + err = publishMeta(info, ob.js) + if err != nil { + return nil, err + } + + return info, nil +} + +// PutBytes is convenience function to put a byte slice into this object store. +func (obs *obs) PutBytes(name string, data []byte, opts ...ObjectOpt) (*ObjectInfo, error) { + return obs.Put(&ObjectMeta{Name: name}, bytes.NewReader(data), opts...) +} + +// GetBytes is a convenience function to pull an object from this object store and return it as a byte slice. +func (obs *obs) GetBytes(name string, opts ...GetObjectOpt) ([]byte, error) { + result, err := obs.Get(name, opts...) + if err != nil { + return nil, err + } + defer result.Close() + + var b bytes.Buffer + if _, err := b.ReadFrom(result); err != nil { + return nil, err + } + return b.Bytes(), nil +} + +// PutString is convenience function to put a string into this object store. +func (obs *obs) PutString(name string, data string, opts ...ObjectOpt) (*ObjectInfo, error) { + return obs.Put(&ObjectMeta{Name: name}, strings.NewReader(data), opts...) +} + +// GetString is a convenience function to pull an object from this object store and return it as a string. +func (obs *obs) GetString(name string, opts ...GetObjectOpt) (string, error) { + result, err := obs.Get(name, opts...) + if err != nil { + return _EMPTY_, err + } + defer result.Close() + + var b bytes.Buffer + if _, err := b.ReadFrom(result); err != nil { + return _EMPTY_, err + } + return b.String(), nil +} + +// PutFile is convenience function to put a file into an object store. +func (obs *obs) PutFile(file string, opts ...ObjectOpt) (*ObjectInfo, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + return obs.Put(&ObjectMeta{Name: file}, f, opts...) +} + +// GetFile is a convenience function to pull and object and place in a file. +func (obs *obs) GetFile(name, file string, opts ...GetObjectOpt) error { + // Expect file to be new. + f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return err + } + defer f.Close() + + result, err := obs.Get(name, opts...) + if err != nil { + os.Remove(f.Name()) + return err + } + defer result.Close() + + // Stream copy to the file. + _, err = io.Copy(f, result) + return err +} + +type GetObjectInfoOpt interface { + configureGetInfo(opts *getObjectInfoOpts) error +} +type getObjectInfoOpts struct { + ctx context.Context + // Include deleted object in the result. + showDeleted bool +} + +type getObjectInfoFn func(opts *getObjectInfoOpts) error + +func (opt getObjectInfoFn) configureGetInfo(opts *getObjectInfoOpts) error { + return opt(opts) +} + +// GetObjectInfoShowDeleted makes GetInfo() return object if it was marked as deleted. +func GetObjectInfoShowDeleted() GetObjectInfoOpt { + return getObjectInfoFn(func(opts *getObjectInfoOpts) error { + opts.showDeleted = true + return nil + }) +} + +// For nats.Context() support. +func (ctx ContextOpt) configureGetInfo(opts *getObjectInfoOpts) error { + opts.ctx = ctx + return nil +} + +// GetInfo will retrieve the current information for the object. +func (obs *obs) GetInfo(name string, opts ...GetObjectInfoOpt) (*ObjectInfo, error) { + // Grab last meta value we have. + if name == "" { + return nil, ErrNameRequired + } + var o getObjectInfoOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureGetInfo(&o); err != nil { + return nil, err + } + } + } + + metaSubj := fmt.Sprintf(objMetaPreTmpl, obs.name, encodeName(name)) // used as data in a JS API call + stream := fmt.Sprintf(objNameTmpl, obs.name) + + m, err := obs.js.GetLastMsg(stream, metaSubj) + if err != nil { + if errors.Is(err, ErrMsgNotFound) { + err = ErrObjectNotFound + } + return nil, err + } + var info ObjectInfo + if err := json.Unmarshal(m.Data, &info); err != nil { + return nil, ErrBadObjectMeta + } + if !o.showDeleted && info.Deleted { + return nil, ErrObjectNotFound + } + info.ModTime = m.Time + return &info, nil +} + +// UpdateMeta will update the meta for the object. +func (obs *obs) UpdateMeta(name string, meta *ObjectMeta) error { + if meta == nil { + return ErrBadObjectMeta + } + + // Grab the current meta. + info, err := obs.GetInfo(name) + if err != nil { + if errors.Is(err, ErrObjectNotFound) { + return ErrUpdateMetaDeleted + } + return err + } + + // If the new name is different from the old, and it exists, error + // If there was an error that was not ErrObjectNotFound, error. + if name != meta.Name { + existingInfo, err := obs.GetInfo(meta.Name, GetObjectInfoShowDeleted()) + if err != nil && !errors.Is(err, ErrObjectNotFound) { + return err + } + if err == nil && !existingInfo.Deleted { + return ErrObjectAlreadyExists + } + } + + // Update Meta prevents update of ObjectMetaOptions (Link, ChunkSize) + // These should only be updated internally when appropriate. + info.Name = meta.Name + info.Description = meta.Description + info.Headers = meta.Headers + info.Metadata = meta.Metadata + + // Prepare the meta message + if err = publishMeta(info, obs.js); err != nil { + return err + } + + // did the name of this object change? We just stored the meta under the new name + // so delete the meta from the old name via purge stream for subject + if name != meta.Name { + metaSubj := fmt.Sprintf(objMetaPreTmpl, obs.name, encodeName(name)) + return obs.js.purgeStream(obs.stream, &StreamPurgeRequest{Subject: metaSubj}) + } + + return nil +} + +// Seal will seal the object store, no further modifications will be allowed. +func (obs *obs) Seal() error { + stream := fmt.Sprintf(objNameTmpl, obs.name) + si, err := obs.js.StreamInfo(stream) + if err != nil { + return err + } + // Seal the stream from being able to take on more messages. + cfg := si.Config + cfg.Sealed = true + _, err = obs.js.UpdateStream(&cfg) + return err +} + +// Implementation for Watch +type objWatcher struct { + updates chan *ObjectInfo + sub *Subscription +} + +// Updates returns the interior channel. +func (w *objWatcher) Updates() <-chan *ObjectInfo { + if w == nil { + return nil + } + return w.updates +} + +// Stop will unsubscribe from the watcher. +func (w *objWatcher) Stop() error { + if w == nil { + return nil + } + return w.sub.Unsubscribe() +} + +// Watch for changes in the underlying store and receive meta information updates. +func (obs *obs) Watch(opts ...WatchOpt) (ObjectWatcher, error) { + var o watchOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureWatcher(&o); err != nil { + return nil, err + } + } + } + + var initDoneMarker bool + + w := &objWatcher{updates: make(chan *ObjectInfo, 32)} + + update := func(m *Msg) { + var info ObjectInfo + if err := json.Unmarshal(m.Data, &info); err != nil { + return // TODO(dlc) - Communicate this upwards? + } + meta, err := m.Metadata() + if err != nil { + return + } + + if !o.ignoreDeletes || !info.Deleted { + info.ModTime = meta.Timestamp + w.updates <- &info + } + + // if UpdatesOnly is set, no not send nil to the channel + // as it would always be triggered after initializing the watcher + if !initDoneMarker && meta.NumPending == 0 { + initDoneMarker = true + w.updates <- nil + } + } + + allMeta := fmt.Sprintf(objAllMetaPreTmpl, obs.name) + _, err := obs.js.GetLastMsg(obs.stream, allMeta) + // if there are no messages on the stream and we are not watching + // updates only, send nil to the channel to indicate that the initial + // watch is done + if !o.updatesOnly { + if errors.Is(err, ErrMsgNotFound) { + initDoneMarker = true + w.updates <- nil + } + } else { + // if UpdatesOnly was used, mark initialization as complete + initDoneMarker = true + } + + // Used ordered consumer to deliver results. + streamName := fmt.Sprintf(objNameTmpl, obs.name) + subOpts := []SubOpt{OrderedConsumer(), BindStream(streamName)} + if !o.includeHistory { + subOpts = append(subOpts, DeliverLastPerSubject()) + } + if o.updatesOnly { + subOpts = append(subOpts, DeliverNew()) + } + sub, err := obs.js.Subscribe(allMeta, update, subOpts...) + if err != nil { + return nil, err + } + // Set us up to close when the waitForMessages func returns. + sub.pDone = func(_ string) { + close(w.updates) + } + w.sub = sub + return w, nil +} + +type ListObjectsOpt interface { + configureListObjects(opts *listObjectOpts) error +} +type listObjectOpts struct { + ctx context.Context + // Include deleted objects in the result channel. + showDeleted bool +} + +type listObjectsFn func(opts *listObjectOpts) error + +func (opt listObjectsFn) configureListObjects(opts *listObjectOpts) error { + return opt(opts) +} + +// ListObjectsShowDeleted makes ListObjects() return deleted objects. +func ListObjectsShowDeleted() ListObjectsOpt { + return listObjectsFn(func(opts *listObjectOpts) error { + opts.showDeleted = true + return nil + }) +} + +// For nats.Context() support. +func (ctx ContextOpt) configureListObjects(opts *listObjectOpts) error { + opts.ctx = ctx + return nil +} + +// List will list all the objects in this store. +func (obs *obs) List(opts ...ListObjectsOpt) ([]*ObjectInfo, error) { + var o listObjectOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureListObjects(&o); err != nil { + return nil, err + } + } + } + watchOpts := make([]WatchOpt, 0) + if !o.showDeleted { + watchOpts = append(watchOpts, IgnoreDeletes()) + } + watcher, err := obs.Watch(watchOpts...) + if err != nil { + return nil, err + } + defer watcher.Stop() + if o.ctx == nil { + o.ctx = context.Background() + } + + var objs []*ObjectInfo + updates := watcher.Updates() +Updates: + for { + select { + case entry := <-updates: + if entry == nil { + break Updates + } + objs = append(objs, entry) + case <-o.ctx.Done(): + return nil, o.ctx.Err() + } + } + if len(objs) == 0 { + return nil, ErrNoObjectsFound + } + return objs, nil +} + +// ObjectBucketStatus represents status of a Bucket, implements ObjectStoreStatus +type ObjectBucketStatus struct { + nfo *StreamInfo + bucket string +} + +// Bucket is the name of the bucket +func (s *ObjectBucketStatus) Bucket() string { return s.bucket } + +// Description is the description supplied when creating the bucket +func (s *ObjectBucketStatus) Description() string { return s.nfo.Config.Description } + +// TTL indicates how long objects are kept in the bucket +func (s *ObjectBucketStatus) TTL() time.Duration { return s.nfo.Config.MaxAge } + +// Storage indicates the underlying JetStream storage technology used to store data +func (s *ObjectBucketStatus) Storage() StorageType { return s.nfo.Config.Storage } + +// Replicas indicates how many storage replicas are kept for the data in the bucket +func (s *ObjectBucketStatus) Replicas() int { return s.nfo.Config.Replicas } + +// Sealed indicates the stream is sealed and cannot be modified in any way +func (s *ObjectBucketStatus) Sealed() bool { return s.nfo.Config.Sealed } + +// Size is the combined size of all data in the bucket including metadata, in bytes +func (s *ObjectBucketStatus) Size() uint64 { return s.nfo.State.Bytes } + +// BackingStore indicates what technology is used for storage of the bucket +func (s *ObjectBucketStatus) BackingStore() string { return "JetStream" } + +// Metadata is the metadata supplied when creating the bucket +func (s *ObjectBucketStatus) Metadata() map[string]string { return s.nfo.Config.Metadata } + +// StreamInfo is the stream info retrieved to create the status +func (s *ObjectBucketStatus) StreamInfo() *StreamInfo { return s.nfo } + +// IsCompressed indicates if the data is compressed on disk +func (s *ObjectBucketStatus) IsCompressed() bool { return s.nfo.Config.Compression != NoCompression } + +// Status retrieves run-time status about a bucket +func (obs *obs) Status() (ObjectStoreStatus, error) { + nfo, err := obs.js.StreamInfo(obs.stream) + if err != nil { + return nil, err + } + + status := &ObjectBucketStatus{ + nfo: nfo, + bucket: obs.name, + } + + return status, nil +} + +// Read impl. +func (o *objResult) Read(p []byte) (n int, err error) { + o.Lock() + defer o.Unlock() + readDeadline := time.Now().Add(o.readTimeout) + if ctx := o.ctx; ctx != nil { + if deadline, ok := ctx.Deadline(); ok { + readDeadline = deadline + } + select { + case <-ctx.Done(): + if ctx.Err() == context.Canceled { + o.err = ctx.Err() + } else { + o.err = ErrTimeout + } + default: + } + } + if o.err != nil { + return 0, o.err + } + if o.r == nil { + return 0, io.EOF + } + + r := o.r.(net.Conn) + r.SetReadDeadline(readDeadline) + n, err = r.Read(p) + if err, ok := err.(net.Error); ok && err.Timeout() { + if ctx := o.ctx; ctx != nil { + select { + case <-ctx.Done(): + if ctx.Err() == context.Canceled { + return 0, ctx.Err() + } else { + return 0, ErrTimeout + } + default: + err = nil + } + } + } + if err == io.EOF { + // Make sure the digest matches. + sha := o.digest.Sum(nil) + rsha, decodeErr := DecodeObjectDigest(o.info.Digest) + if decodeErr != nil { + o.err = decodeErr + return 0, o.err + } + if !bytes.Equal(sha[:], rsha) { + o.err = ErrDigestMismatch + return 0, o.err + } + } + return n, err +} + +// Close impl. +func (o *objResult) Close() error { + o.Lock() + defer o.Unlock() + if o.r == nil { + return nil + } + return o.r.Close() +} + +func (o *objResult) setErr(err error) { + o.Lock() + defer o.Unlock() + o.err = err +} + +func (o *objResult) Info() (*ObjectInfo, error) { + o.Lock() + defer o.Unlock() + return o.info, o.err +} + +func (o *objResult) Error() error { + o.Lock() + defer o.Unlock() + return o.err +} + +// ObjectStoreNames is used to retrieve a list of bucket names +func (js *js) ObjectStoreNames(opts ...ObjectOpt) <-chan string { + var o objOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureObject(&o); err != nil { + return nil + } + } + } + ch := make(chan string) + var cancel context.CancelFunc + if o.ctx == nil { + o.ctx, cancel = context.WithTimeout(context.Background(), defaultRequestWait) + } + l := &streamLister{js: js} + l.js.opts.streamListSubject = fmt.Sprintf(objAllChunksPreTmpl, "*") + l.js.opts.ctx = o.ctx + go func() { + if cancel != nil { + defer cancel() + } + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + if !strings.HasPrefix(info.Config.Name, "OBJ_") { + continue + } + select { + case ch <- info.Config.Name: + case <-o.ctx.Done(): + return + } + } + } + }() + + return ch +} + +// ObjectStores is used to retrieve a list of bucket statuses +func (js *js) ObjectStores(opts ...ObjectOpt) <-chan ObjectStoreStatus { + var o objOpts + for _, opt := range opts { + if opt != nil { + if err := opt.configureObject(&o); err != nil { + return nil + } + } + } + ch := make(chan ObjectStoreStatus) + var cancel context.CancelFunc + if o.ctx == nil { + o.ctx, cancel = context.WithTimeout(context.Background(), defaultRequestWait) + } + l := &streamLister{js: js} + l.js.opts.streamListSubject = fmt.Sprintf(objAllChunksPreTmpl, "*") + l.js.opts.ctx = o.ctx + go func() { + if cancel != nil { + defer cancel() + } + defer close(ch) + for l.Next() { + for _, info := range l.Page() { + if !strings.HasPrefix(info.Config.Name, "OBJ_") { + continue + } + select { + case ch <- &ObjectBucketStatus{ + nfo: info, + bucket: strings.TrimPrefix(info.Config.Name, "OBJ_"), + }: + case <-o.ctx.Done(): + return + } + } + } + }() + + return ch +} diff --git a/vendor/github.com/nats-io/nats.go/parser.go b/vendor/github.com/nats-io/nats.go/parser.go index c9cbfeb..70204e6 100644 --- a/vendor/github.com/nats-io/nats.go/parser.go +++ b/vendor/github.com/nats-io/nats.go/parser.go @@ -1,4 +1,4 @@ -// Copyright 2012-2020 The NATS Authors +// Copyright 2012-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -28,14 +28,15 @@ type msgArg struct { const MAX_CONTROL_LINE_SIZE = 4096 type parseState struct { - state int - as int - drop int - hdr int - ma msgArg - argBuf []byte - msgBuf []byte - scratch [MAX_CONTROL_LINE_SIZE]byte + state int + as int + drop int + hdr int + ma msgArg + argBuf []byte + msgBuf []byte + msgCopied bool + scratch [MAX_CONTROL_LINE_SIZE]byte } const ( @@ -167,7 +168,7 @@ func (nc *Conn) parse(buf []byte) error { if nc.ps.msgBuf != nil { if len(nc.ps.msgBuf) >= nc.ps.ma.size { nc.processMsg(nc.ps.msgBuf) - nc.ps.argBuf, nc.ps.msgBuf, nc.ps.state = nil, nil, MSG_END + nc.ps.argBuf, nc.ps.msgBuf, nc.ps.msgCopied, nc.ps.state = nil, nil, false, MSG_END } else { // copy as much as we can to the buffer and skip ahead. toCopy := nc.ps.ma.size - len(nc.ps.msgBuf) @@ -190,7 +191,7 @@ func (nc *Conn) parse(buf []byte) error { } } else if i-nc.ps.as >= nc.ps.ma.size { nc.processMsg(buf[nc.ps.as:i]) - nc.ps.argBuf, nc.ps.msgBuf, nc.ps.state = nil, nil, MSG_END + nc.ps.argBuf, nc.ps.msgBuf, nc.ps.msgCopied, nc.ps.state = nil, nil, false, MSG_END } case MSG_END: switch b { @@ -403,6 +404,7 @@ func (nc *Conn) parse(buf []byte) error { nc.ps.msgBuf = make([]byte, lrem, nc.ps.ma.size) copy(nc.ps.msgBuf, buf[nc.ps.as:]) + nc.ps.msgCopied = true } else { nc.ps.msgBuf = nc.ps.scratch[len(nc.ps.argBuf):len(nc.ps.argBuf)] nc.ps.msgBuf = append(nc.ps.msgBuf, (buf[nc.ps.as:])...) @@ -530,7 +532,7 @@ func (nc *Conn) processHeaderMsgArgs(arg []byte) error { return nil } -// Ascii numbers 0-9 +// ASCII numbers 0-9 const ( ascii_0 = 48 ascii_9 = 57 diff --git a/vendor/github.com/nats-io/nats.go/testing_internal.go b/vendor/github.com/nats-io/nats.go/testing_internal.go new file mode 100644 index 0000000..78ca3b1 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/testing_internal.go @@ -0,0 +1,58 @@ +// Copyright 2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build internal_testing + +// Functions in this file are only available when building nats.go with the +// internal_testing build tag. They are used by the nats.go test suite. +package nats + +// AddMsgFilter adds a message filter for the given subject +// to the connection. The filter will be called for each +// message received on the subject. If the filter returns +// nil, the message will be dropped. +func (nc *Conn) AddMsgFilter(subject string, filter msgFilter) { + nc.subsMu.Lock() + defer nc.subsMu.Unlock() + + if nc.filters == nil { + nc.filters = make(map[string]msgFilter) + } + nc.filters[subject] = filter +} + +// RemoveMsgFilter removes a message filter for the given subject. +func (nc *Conn) RemoveMsgFilter(subject string) { + nc.subsMu.Lock() + defer nc.subsMu.Unlock() + + if nc.filters != nil { + delete(nc.filters, subject) + if len(nc.filters) == 0 { + nc.filters = nil + } + } +} + +// IsJSControlMessage returns true if the message is a JetStream control message. +func IsJSControlMessage(msg *Msg) (bool, int) { + return isJSControlMessage(msg) +} + +// CloseTCPConn closes the underlying TCP connection. +// It can be used to simulate a disconnect. +func (nc *Conn) CloseTCPConn() { + nc.mu.Lock() + defer nc.mu.Unlock() + nc.conn.Close() +} diff --git a/vendor/github.com/nats-io/nats.go/timer.go b/vendor/github.com/nats-io/nats.go/timer.go index 1216762..6edeb4c 100644 --- a/vendor/github.com/nats-io/nats.go/timer.go +++ b/vendor/github.com/nats-io/nats.go/timer.go @@ -1,4 +1,4 @@ -// Copyright 2017-2018 The NATS Authors +// Copyright 2017-2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -29,7 +29,7 @@ type timerPool struct { // Get returns a timer that completes after the given duration. func (tp *timerPool) Get(d time.Duration) *time.Timer { - if t, _ := tp.p.Get().(*time.Timer); t != nil { + if t, ok := tp.p.Get().(*time.Timer); ok && t != nil { t.Reset(d) return t } diff --git a/vendor/github.com/nats-io/nats.go/util/tls.go b/vendor/github.com/nats-io/nats.go/util/tls.go index 53ff9aa..ae16c3d 100644 --- a/vendor/github.com/nats-io/nats.go/util/tls.go +++ b/vendor/github.com/nats-io/nats.go/util/tls.go @@ -1,4 +1,4 @@ -// Copyright 2017-2018 The NATS Authors +// Copyright 2017-2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build go1.8 - package util import "crypto/tls" diff --git a/vendor/github.com/nats-io/nats.go/util/tls_go17.go b/vendor/github.com/nats-io/nats.go/util/tls_go17.go deleted file mode 100644 index fd646d3..0000000 --- a/vendor/github.com/nats-io/nats.go/util/tls_go17.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016-2018 The NATS Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build go1.7,!go1.8 - -package util - -import ( - "crypto/tls" -) - -// CloneTLSConfig returns a copy of c. Only the exported fields are copied. -// This is temporary, until this is provided by the language. -// https://go-review.googlesource.com/#/c/28075/ -func CloneTLSConfig(c *tls.Config) *tls.Config { - return &tls.Config{ - Rand: c.Rand, - Time: c.Time, - Certificates: c.Certificates, - NameToCertificate: c.NameToCertificate, - GetCertificate: c.GetCertificate, - RootCAs: c.RootCAs, - NextProtos: c.NextProtos, - ServerName: c.ServerName, - ClientAuth: c.ClientAuth, - ClientCAs: c.ClientCAs, - InsecureSkipVerify: c.InsecureSkipVerify, - CipherSuites: c.CipherSuites, - PreferServerCipherSuites: c.PreferServerCipherSuites, - SessionTicketsDisabled: c.SessionTicketsDisabled, - SessionTicketKey: c.SessionTicketKey, - ClientSessionCache: c.ClientSessionCache, - MinVersion: c.MinVersion, - MaxVersion: c.MaxVersion, - CurvePreferences: c.CurvePreferences, - DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, - Renegotiation: c.Renegotiation, - } -} diff --git a/vendor/github.com/nats-io/nats.go/ws.go b/vendor/github.com/nats-io/nats.go/ws.go new file mode 100644 index 0000000..3642917 --- /dev/null +++ b/vendor/github.com/nats-io/nats.go/ws.go @@ -0,0 +1,806 @@ +// Copyright 2021-2023 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nats + +import ( + "bufio" + "bytes" + "crypto/rand" + "crypto/sha1" + "encoding/base64" + "encoding/binary" + "errors" + "fmt" + "io" + mrand "math/rand" + "net/http" + "net/url" + "strings" + "time" + "unicode/utf8" + + "github.com/klauspost/compress/flate" +) + +type wsOpCode int + +const ( + // From https://tools.ietf.org/html/rfc6455#section-5.2 + wsTextMessage = wsOpCode(1) + wsBinaryMessage = wsOpCode(2) + wsCloseMessage = wsOpCode(8) + wsPingMessage = wsOpCode(9) + wsPongMessage = wsOpCode(10) + + wsFinalBit = 1 << 7 + wsRsv1Bit = 1 << 6 // Used for compression, from https://tools.ietf.org/html/rfc7692#section-6 + wsRsv2Bit = 1 << 5 + wsRsv3Bit = 1 << 4 + + wsMaskBit = 1 << 7 + + wsContinuationFrame = 0 + wsMaxFrameHeaderSize = 14 + wsMaxControlPayloadSize = 125 + wsCloseSatusSize = 2 + + // From https://tools.ietf.org/html/rfc6455#section-11.7 + wsCloseStatusNormalClosure = 1000 + wsCloseStatusNoStatusReceived = 1005 + wsCloseStatusAbnormalClosure = 1006 + wsCloseStatusInvalidPayloadData = 1007 + + wsScheme = "ws" + wsSchemeTLS = "wss" + + wsPMCExtension = "permessage-deflate" // per-message compression + wsPMCSrvNoCtx = "server_no_context_takeover" + wsPMCCliNoCtx = "client_no_context_takeover" + wsPMCReqHeaderValue = wsPMCExtension + "; " + wsPMCSrvNoCtx + "; " + wsPMCCliNoCtx +) + +// From https://tools.ietf.org/html/rfc6455#section-1.3 +var wsGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") + +var compressFinalBlock = []byte{0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff} + +type websocketReader struct { + r io.Reader + pending [][]byte + compress bool + ib []byte + ff bool + fc bool + nl bool + dc *wsDecompressor + nc *Conn +} + +type wsDecompressor struct { + flate io.ReadCloser + bufs [][]byte + off int +} + +type websocketWriter struct { + w io.Writer + compress bool + compressor *flate.Writer + ctrlFrames [][]byte // pending frames that should be sent at the next Write() + cm []byte // close message that needs to be sent when everything else has been sent + cmDone bool // a close message has been added or sent (never going back to false) + noMoreSend bool // if true, even if there is a Write() call, we should not send anything +} + +func (d *wsDecompressor) Read(dst []byte) (int, error) { + if len(dst) == 0 { + return 0, nil + } + if len(d.bufs) == 0 { + return 0, io.EOF + } + copied := 0 + rem := len(dst) + for buf := d.bufs[0]; buf != nil && rem > 0; { + n := len(buf[d.off:]) + if n > rem { + n = rem + } + copy(dst[copied:], buf[d.off:d.off+n]) + copied += n + rem -= n + d.off += n + buf = d.nextBuf() + } + return copied, nil +} + +func (d *wsDecompressor) nextBuf() []byte { + // We still have remaining data in the first buffer + if d.off != len(d.bufs[0]) { + return d.bufs[0] + } + // We read the full first buffer. Reset offset. + d.off = 0 + // We were at the last buffer, so we are done. + if len(d.bufs) == 1 { + d.bufs = nil + return nil + } + // Here we move to the next buffer. + d.bufs = d.bufs[1:] + return d.bufs[0] +} + +func (d *wsDecompressor) ReadByte() (byte, error) { + if len(d.bufs) == 0 { + return 0, io.EOF + } + b := d.bufs[0][d.off] + d.off++ + d.nextBuf() + return b, nil +} + +func (d *wsDecompressor) addBuf(b []byte) { + d.bufs = append(d.bufs, b) +} + +func (d *wsDecompressor) decompress() ([]byte, error) { + d.off = 0 + // As per https://tools.ietf.org/html/rfc7692#section-7.2.2 + // add 0x00, 0x00, 0xff, 0xff and then a final block so that flate reader + // does not report unexpected EOF. + d.bufs = append(d.bufs, compressFinalBlock) + // Create or reset the decompressor with his object (wsDecompressor) + // that provides Read() and ReadByte() APIs that will consume from + // the compressed buffers (d.bufs). + if d.flate == nil { + d.flate = flate.NewReader(d) + } else { + d.flate.(flate.Resetter).Reset(d, nil) + } + b, err := io.ReadAll(d.flate) + // Now reset the compressed buffers list + d.bufs = nil + return b, err +} + +func wsNewReader(r io.Reader) *websocketReader { + return &websocketReader{r: r, ff: true} +} + +// From now on, reads will be from the readLoop and we will need to +// acquire the connection lock should we have to send/write a control +// message from handleControlFrame. +// +// Note: this runs under the connection lock. +func (r *websocketReader) doneWithConnect() { + r.nl = true +} + +func (r *websocketReader) Read(p []byte) (int, error) { + var err error + var buf []byte + + if l := len(r.ib); l > 0 { + buf = r.ib + r.ib = nil + } else { + if len(r.pending) > 0 { + return r.drainPending(p), nil + } + + // Get some data from the underlying reader. + n, err := r.r.Read(p) + if err != nil { + return 0, err + } + buf = p[:n] + } + + // Now parse this and decode frames. We will possibly read more to + // ensure that we get a full frame. + var ( + tmpBuf []byte + pos int + max = len(buf) + rem = 0 + ) + for pos < max { + b0 := buf[pos] + frameType := wsOpCode(b0 & 0xF) + final := b0&wsFinalBit != 0 + compressed := b0&wsRsv1Bit != 0 + pos++ + + tmpBuf, pos, err = wsGet(r.r, buf, pos, 1) + if err != nil { + return 0, err + } + b1 := tmpBuf[0] + + // Store size in case it is < 125 + rem = int(b1 & 0x7F) + + switch frameType { + case wsPingMessage, wsPongMessage, wsCloseMessage: + if rem > wsMaxControlPayloadSize { + return 0, fmt.Errorf( + "control frame length bigger than maximum allowed of %v bytes", + wsMaxControlPayloadSize) + } + if compressed { + return 0, errors.New("control frame should not be compressed") + } + if !final { + return 0, errors.New("control frame does not have final bit set") + } + case wsTextMessage, wsBinaryMessage: + if !r.ff { + return 0, errors.New("new message started before final frame for previous message was received") + } + r.ff = final + r.fc = compressed + case wsContinuationFrame: + // Compressed bit must be only set in the first frame + if r.ff || compressed { + return 0, errors.New("invalid continuation frame") + } + r.ff = final + default: + return 0, fmt.Errorf("unknown opcode %v", frameType) + } + + // If the encoded size is <= 125, then `rem` is simply the remainder size of the + // frame. If it is 126, then the actual size is encoded as a uint16. For larger + // frames, `rem` will initially be 127 and the actual size is encoded as a uint64. + switch rem { + case 126: + tmpBuf, pos, err = wsGet(r.r, buf, pos, 2) + if err != nil { + return 0, err + } + rem = int(binary.BigEndian.Uint16(tmpBuf)) + case 127: + tmpBuf, pos, err = wsGet(r.r, buf, pos, 8) + if err != nil { + return 0, err + } + rem = int(binary.BigEndian.Uint64(tmpBuf)) + } + + // Handle control messages in place... + if wsIsControlFrame(frameType) { + pos, err = r.handleControlFrame(frameType, buf, pos, rem) + if err != nil { + return 0, err + } + rem = 0 + continue + } + + var b []byte + // This ensures that we get the full payload for this frame. + b, pos, err = wsGet(r.r, buf, pos, rem) + if err != nil { + return 0, err + } + // We read the full frame. + rem = 0 + addToPending := true + if r.fc { + // Don't add to pending if we are not dealing with the final frame. + addToPending = r.ff + // Add the compressed payload buffer to the list. + r.addCBuf(b) + // Decompress only when this is the final frame. + if r.ff { + b, err = r.dc.decompress() + if err != nil { + return 0, err + } + r.fc = false + } + } else if r.compress { + b = bytes.Clone(b) + } + // Add to the pending list if dealing with uncompressed frames or + // after we have received the full compressed message and decompressed it. + if addToPending { + r.pending = append(r.pending, b) + } + } + // In case of compression, there may be nothing to drain + if len(r.pending) > 0 { + return r.drainPending(p), nil + } + return 0, nil +} + +func (r *websocketReader) addCBuf(b []byte) { + if r.dc == nil { + r.dc = &wsDecompressor{} + } + // Add a copy of the incoming buffer to the list of compressed buffers. + r.dc.addBuf(append([]byte(nil), b...)) +} + +func (r *websocketReader) drainPending(p []byte) int { + var n int + var max = len(p) + + for i, buf := range r.pending { + if n+len(buf) <= max { + copy(p[n:], buf) + n += len(buf) + } else { + // Is there room left? + if n < max { + // Write the partial and update this slice. + rem := max - n + copy(p[n:], buf[:rem]) + n += rem + r.pending[i] = buf[rem:] + } + // These are the remaining slices that will need to be used at + // the next Read() call. + r.pending = r.pending[i:] + return n + } + } + r.pending = r.pending[:0] + return n +} + +func wsGet(r io.Reader, buf []byte, pos, needed int) ([]byte, int, error) { + avail := len(buf) - pos + if avail >= needed { + return buf[pos : pos+needed], pos + needed, nil + } + b := make([]byte, needed) + start := copy(b, buf[pos:]) + for start != needed { + n, err := r.Read(b[start:cap(b)]) + start += n + if err != nil { + return b, start, err + } + } + return b, pos + avail, nil +} + +func (r *websocketReader) handleControlFrame(frameType wsOpCode, buf []byte, pos, rem int) (int, error) { + var payload []byte + var err error + + if rem > 0 { + payload, pos, err = wsGet(r.r, buf, pos, rem) + if err != nil { + return pos, err + } + } + switch frameType { + case wsCloseMessage: + status := wsCloseStatusNoStatusReceived + var body string + lp := len(payload) + // If there is a payload, the status is represented as a 2-byte + // unsigned integer (in network byte order). Then, there may be an + // optional body. + hasStatus, hasBody := lp >= wsCloseSatusSize, lp > wsCloseSatusSize + if hasStatus { + // Decode the status + status = int(binary.BigEndian.Uint16(payload[:wsCloseSatusSize])) + // Now if there is a body, capture it and make sure this is a valid UTF-8. + if hasBody { + body = string(payload[wsCloseSatusSize:]) + if !utf8.ValidString(body) { + // https://tools.ietf.org/html/rfc6455#section-5.5.1 + // If body is present, it must be a valid utf8 + status = wsCloseStatusInvalidPayloadData + body = "invalid utf8 body in close frame" + } + } + } + r.nc.wsEnqueueCloseMsg(r.nl, status, body) + // Return io.EOF so that readLoop will close the connection as client closed + // after processing pending buffers. + return pos, io.EOF + case wsPingMessage: + r.nc.wsEnqueueControlMsg(r.nl, wsPongMessage, payload) + case wsPongMessage: + // Nothing to do.. + } + return pos, nil +} + +func (w *websocketWriter) Write(p []byte) (int, error) { + if w.noMoreSend { + return 0, nil + } + var total int + var n int + var err error + // If there are control frames, they can be sent now. Actually spec says + // that they should be sent ASAP, so we will send before any application data. + if len(w.ctrlFrames) > 0 { + n, err = w.writeCtrlFrames() + if err != nil { + return n, err + } + total += n + } + // Do the following only if there is something to send. + // We will end with checking for need to send close message. + if len(p) > 0 { + if w.compress { + buf := &bytes.Buffer{} + if w.compressor == nil { + w.compressor, _ = flate.NewWriter(buf, flate.BestSpeed) + } else { + w.compressor.Reset(buf) + } + if n, err = w.compressor.Write(p); err != nil { + return n, err + } + if err = w.compressor.Flush(); err != nil { + return n, err + } + b := buf.Bytes() + p = b[:len(b)-4] + } + fh, key := wsCreateFrameHeader(w.compress, wsBinaryMessage, len(p)) + wsMaskBuf(key, p) + n, err = w.w.Write(fh) + total += n + if err == nil { + n, err = w.w.Write(p) + total += n + } + } + if err == nil && w.cm != nil { + n, err = w.writeCloseMsg() + total += n + } + return total, err +} + +func (w *websocketWriter) writeCtrlFrames() (int, error) { + var ( + n int + total int + i int + err error + ) + for ; i < len(w.ctrlFrames); i++ { + buf := w.ctrlFrames[i] + n, err = w.w.Write(buf) + total += n + if err != nil { + break + } + } + if i != len(w.ctrlFrames) { + w.ctrlFrames = w.ctrlFrames[i+1:] + } else { + w.ctrlFrames = w.ctrlFrames[:0] + } + return total, err +} + +func (w *websocketWriter) writeCloseMsg() (int, error) { + n, err := w.w.Write(w.cm) + w.cm, w.noMoreSend = nil, true + return n, err +} + +func wsMaskBuf(key, buf []byte) { + for i := 0; i < len(buf); i++ { + buf[i] ^= key[i&3] + } +} + +// Create the frame header. +// Encodes the frame type and optional compression flag, and the size of the payload. +func wsCreateFrameHeader(compressed bool, frameType wsOpCode, l int) ([]byte, []byte) { + fh := make([]byte, wsMaxFrameHeaderSize) + n, key := wsFillFrameHeader(fh, compressed, frameType, l) + return fh[:n], key +} + +func wsFillFrameHeader(fh []byte, compressed bool, frameType wsOpCode, l int) (int, []byte) { + var n int + b := byte(frameType) + b |= wsFinalBit + if compressed { + b |= wsRsv1Bit + } + b1 := byte(wsMaskBit) + switch { + case l <= 125: + n = 2 + fh[0] = b + fh[1] = b1 | byte(l) + case l < 65536: + n = 4 + fh[0] = b + fh[1] = b1 | 126 + binary.BigEndian.PutUint16(fh[2:], uint16(l)) + default: + n = 10 + fh[0] = b + fh[1] = b1 | 127 + binary.BigEndian.PutUint64(fh[2:], uint64(l)) + } + var key []byte + var keyBuf [4]byte + if _, err := io.ReadFull(rand.Reader, keyBuf[:4]); err != nil { + kv := mrand.Int31() + binary.LittleEndian.PutUint32(keyBuf[:4], uint32(kv)) + } + copy(fh[n:], keyBuf[:4]) + key = fh[n : n+4] + n += 4 + return n, key +} + +func (nc *Conn) wsInitHandshake(u *url.URL) error { + compress := nc.Opts.Compression + tlsRequired := u.Scheme == wsSchemeTLS || nc.Opts.Secure || nc.Opts.TLSConfig != nil || nc.Opts.TLSCertCB != nil || nc.Opts.RootCAsCB != nil + // Do TLS here as needed. + if tlsRequired { + if err := nc.makeTLSConn(); err != nil { + return err + } + } else { + nc.bindToNewConn() + } + + var err error + + // For http request, we need the passed URL to contain either http or https scheme. + scheme := "http" + if tlsRequired { + scheme = "https" + } + ustr := fmt.Sprintf("%s://%s", scheme, u.Host) + + if nc.Opts.ProxyPath != "" { + proxyPath := nc.Opts.ProxyPath + if !strings.HasPrefix(proxyPath, "/") { + proxyPath = "/" + proxyPath + } + ustr += proxyPath + } + + u, err = url.Parse(ustr) + if err != nil { + return err + } + req := &http.Request{ + Method: "GET", + URL: u, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: make(http.Header), + Host: u.Host, + } + wsKey, err := wsMakeChallengeKey() + if err != nil { + return err + } + + req.Header["Upgrade"] = []string{"websocket"} + req.Header["Connection"] = []string{"Upgrade"} + req.Header["Sec-WebSocket-Key"] = []string{wsKey} + req.Header["Sec-WebSocket-Version"] = []string{"13"} + if compress { + req.Header.Add("Sec-WebSocket-Extensions", wsPMCReqHeaderValue) + } + if err := nc.wsUpdateConnectionHeaders(req); err != nil { + return err + } + if err := req.Write(nc.conn); err != nil { + return err + } + + var resp *http.Response + + br := bufio.NewReaderSize(nc.conn, 4096) + nc.conn.SetReadDeadline(time.Now().Add(nc.Opts.Timeout)) + resp, err = http.ReadResponse(br, req) + if err == nil && + (resp.StatusCode != 101 || + !strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") || + !strings.EqualFold(resp.Header.Get("Connection"), "upgrade") || + resp.Header.Get("Sec-Websocket-Accept") != wsAcceptKey(wsKey)) { + + err = errors.New("invalid websocket connection") + } + // Check compression extension... + if err == nil && compress { + // Check that not only permessage-deflate extension is present, but that + // we also have server and client no context take over. + srvCompress, noCtxTakeover := wsPMCExtensionSupport(resp.Header) + + // If server does not support compression, then simply disable it in our side. + if !srvCompress { + compress = false + } else if !noCtxTakeover { + err = errors.New("compression negotiation error") + } + } + if resp != nil { + resp.Body.Close() + } + nc.conn.SetReadDeadline(time.Time{}) + if err != nil { + return err + } + + wsr := wsNewReader(nc.br.r) + wsr.nc = nc + wsr.compress = compress + // We have to slurp whatever is in the bufio reader and copy to br.r + if n := br.Buffered(); n != 0 { + wsr.ib, _ = br.Peek(n) + } + nc.br.r = wsr + nc.bw.w = &websocketWriter{w: nc.bw.w, compress: compress} + nc.ws = true + return nil +} + +func (nc *Conn) wsClose() { + nc.mu.Lock() + defer nc.mu.Unlock() + if !nc.ws { + return + } + nc.wsEnqueueCloseMsgLocked(wsCloseStatusNormalClosure, _EMPTY_) +} + +func (nc *Conn) wsEnqueueCloseMsg(needsLock bool, status int, payload string) { + // In some low-level unit tests it will happen... + if nc == nil { + return + } + if needsLock { + nc.mu.Lock() + defer nc.mu.Unlock() + } + nc.wsEnqueueCloseMsgLocked(status, payload) +} + +func (nc *Conn) wsEnqueueCloseMsgLocked(status int, payload string) { + wr, ok := nc.bw.w.(*websocketWriter) + if !ok || wr.cmDone { + return + } + statusAndPayloadLen := 2 + len(payload) + frame := make([]byte, 2+4+statusAndPayloadLen) + n, key := wsFillFrameHeader(frame, false, wsCloseMessage, statusAndPayloadLen) + // Set the status + binary.BigEndian.PutUint16(frame[n:], uint16(status)) + // If there is a payload, copy + if len(payload) > 0 { + copy(frame[n+2:], payload) + } + // Mask status + payload + wsMaskBuf(key, frame[n:n+statusAndPayloadLen]) + wr.cm = frame + wr.cmDone = true + nc.bw.flush() + if c := wr.compressor; c != nil { + c.Close() + } +} + +func (nc *Conn) wsEnqueueControlMsg(needsLock bool, frameType wsOpCode, payload []byte) { + // In some low-level unit tests it will happen... + if nc == nil { + return + } + if needsLock { + nc.mu.Lock() + defer nc.mu.Unlock() + } + wr, ok := nc.bw.w.(*websocketWriter) + if !ok { + return + } + fh, key := wsCreateFrameHeader(false, frameType, len(payload)) + wr.ctrlFrames = append(wr.ctrlFrames, fh) + if len(payload) > 0 { + wsMaskBuf(key, payload) + wr.ctrlFrames = append(wr.ctrlFrames, payload) + } + nc.bw.flush() +} + +func (nc *Conn) wsUpdateConnectionHeaders(req *http.Request) error { + var headers http.Header + var err error + if nc.Opts.WebSocketConnectionHeadersHandler != nil { + headers, err = nc.Opts.WebSocketConnectionHeadersHandler() + if err != nil { + return err + } + } else { + headers = nc.Opts.WebSocketConnectionHeaders + } + for key, values := range headers { + for _, val := range values { + req.Header.Add(key, val) + } + } + return nil +} + +func wsPMCExtensionSupport(header http.Header) (bool, bool) { + for _, extensionList := range header["Sec-Websocket-Extensions"] { + extensions := strings.Split(extensionList, ",") + for _, extension := range extensions { + extension = strings.Trim(extension, " \t") + params := strings.Split(extension, ";") + for i, p := range params { + p = strings.Trim(p, " \t") + if strings.EqualFold(p, wsPMCExtension) { + var snc bool + var cnc bool + for j := i + 1; j < len(params); j++ { + p = params[j] + p = strings.Trim(p, " \t") + if strings.EqualFold(p, wsPMCSrvNoCtx) { + snc = true + } else if strings.EqualFold(p, wsPMCCliNoCtx) { + cnc = true + } + if snc && cnc { + return true, true + } + } + return true, false + } + } + } + } + return false, false +} + +func wsMakeChallengeKey() (string, error) { + p := make([]byte, 16) + if _, err := io.ReadFull(rand.Reader, p); err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(p), nil +} + +func wsAcceptKey(key string) string { + h := sha1.New() + h.Write([]byte(key)) + h.Write(wsGUID) + return base64.StdEncoding.EncodeToString(h.Sum(nil)) +} + +// Returns true if the op code corresponds to a control frame. +func wsIsControlFrame(frameType wsOpCode) bool { + return frameType >= wsCloseMessage +} + +func isWebsocketScheme(u *url.URL) bool { + return u.Scheme == wsScheme || u.Scheme == wsSchemeTLS +} diff --git a/vendor/github.com/nats-io/nkeys/.gitignore b/vendor/github.com/nats-io/nkeys/.gitignore index 9dca5eb..d23676d 100644 --- a/vendor/github.com/nats-io/nkeys/.gitignore +++ b/vendor/github.com/nats-io/nkeys/.gitignore @@ -13,3 +13,4 @@ build/ # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 .glide/ +.idea/ diff --git a/vendor/github.com/nats-io/nkeys/.goreleaser.yml b/vendor/github.com/nats-io/nkeys/.goreleaser.yml index 6df08be..e5c4f15 100644 --- a/vendor/github.com/nats-io/nkeys/.goreleaser.yml +++ b/vendor/github.com/nats-io/nkeys/.goreleaser.yml @@ -6,23 +6,45 @@ release: name_template: '{{.Tag}}' draft: true builds: - - main: ./nk/main.go + - id: nk + main: ./nk/main.go ldflags: "-X main.Version={{.Tag}}_{{.Commit}}" binary: nk goos: - - linux - darwin + - linux + - windows + - freebsd goarch: - amd64 - + - arm + - arm64 + - 386 + - mips64le + - s390x + goarm: + - 6 + - 7 + ignore: + - goos: darwin + goarch: 386 + - goos: freebsd + goarch: arm + - goos: freebsd + goarch: arm64 + - goos: freebsd + goarch: 386 dist: build -archive: - wrap_in_directory: true - name_template: '{{ .ProjectName }}-v{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm +archives: + - name_template: '{{ .ProjectName }}-v{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}' - format: zip + wrap_in_directory: true + format: zip + files: + - README.md + - LICENSE checksum: name_template: '{{ .ProjectName }}-v{{ .Version }}-checksums.txt' @@ -30,9 +52,12 @@ checksum: snapshot: name_template: 'dev' -nfpm: - formats: - - deb - bindir: /usr/local/bin - description: NKeys utility cli program - vendor: nats-io +nfpms: + - file_name_template: '{{ .ProjectName }}-v{{ .Version }}-{{ .Arch }}{{ if .Arm + }}v{{ .Arm }}{{ end }}' + maintainer: nats.io + description: NKeys utility cli program + vendor: nats-io + bindir: /usr/local/bin + formats: + - deb \ No newline at end of file diff --git a/vendor/github.com/nats-io/nkeys/.travis.yml b/vendor/github.com/nats-io/nkeys/.travis.yml deleted file mode 100644 index e1076cd..0000000 --- a/vendor/github.com/nats-io/nkeys/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: go -sudo: false -go: -- 1.14.x -- 1.13.x - -install: -- go get -t ./... -- go get github.com/mattn/goveralls -- go get -u honnef.co/go/tools/cmd/staticcheck -- go get -u github.com/client9/misspell/cmd/misspell - -before_script: -- $(exit $(go fmt ./... | wc -l)) -- go vet ./... -- misspell -error -locale US . -- staticcheck ./... - -script: -- go test -v -- go test -v --race -- go test -v -covermode=count -coverprofile=coverage.out -- $HOME/gopath/bin/goveralls -coverprofile coverage.out -service travis-ci - -#deploy: -#- provider: script -# skip_cleanup: true -# script: curl -sL http://git.io/goreleaser | bash -# on: -# tags: true -# condition: $TRAVIS_OS_NAME = linux diff --git a/vendor/github.com/nats-io/nkeys/MAINTAINERS.md b/vendor/github.com/nats-io/nkeys/MAINTAINERS.md index 6d0ed3e..2321465 100644 --- a/vendor/github.com/nats-io/nkeys/MAINTAINERS.md +++ b/vendor/github.com/nats-io/nkeys/MAINTAINERS.md @@ -2,5 +2,7 @@ Maintainership is on a per project basis. -### Core-maintainers - - Derek Collison [@derekcollison](https://github.com/derekcollison) \ No newline at end of file +### Maintainers + - Derek Collison [@derekcollison](https://github.com/derekcollison) + - Ivan Kozlovic [@kozlovic](https://github.com/kozlovic) + - Waldemar Quevedo [@wallyqs](https://github.com/wallyqs) diff --git a/vendor/github.com/nats-io/nkeys/README.md b/vendor/github.com/nats-io/nkeys/README.md index 8b787cc..17e3a8e 100644 --- a/vendor/github.com/nats-io/nkeys/README.md +++ b/vendor/github.com/nats-io/nkeys/README.md @@ -1,11 +1,10 @@ # NKEYS [![License Apache 2](https://img.shields.io/badge/License-Apache2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) -[![ReportCard](http://goreportcard.com/badge/nats-io/nkeys)](http://goreportcard.com/report/nats-io/nkeys) -[![Build Status](https://travis-ci.org/nats-io/nkeys.svg?branch=master)](http://travis-ci.org/nats-io/nkeys) -[![GoDoc](http://godoc.org/github.com/nats-io/nkeys?status.svg)](http://godoc.org/github.com/nats-io/nkeys) -[![Coverage Status](https://coveralls.io/repos/github/nats-io/nkeys/badge.svg?branch=master&service=github)](https://coveralls.io/github/nats-io/nkeys?branch=master) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys?ref=badge_shield) +[![Go Report Card](https://goreportcard.com/badge/github.com/nats-io/nkeys)](https://goreportcard.com/report/github.com/nats-io/nkeys) +[![Build Status](https://github.com/nats-io/nkeys/actions/workflows/release.yaml/badge.svg)](https://github.com/nats-io/nkeys/actions/workflows/release.yaml/badge.svg) +[![GoDoc](https://godoc.org/github.com/nats-io/nkeys?status.svg)](https://godoc.org/github.com/nats-io/nkeys) +[![Coverage Status](https://coveralls.io/repos/github/nats-io/nkeys/badge.svg?branch=main&service=github)](https://coveralls.io/github/nats-io/nkeys?branch=main) A public-key signature system based on [Ed25519](https://ed25519.cr.yp.to/) for the NATS ecosystem. @@ -67,6 +66,3 @@ user2, _ := nkeys.FromRawSeed(PrefixByteUser, rawSeed) Unless otherwise noted, the NATS source files are distributed under the Apache Version 2.0 license found in the LICENSE file. - - -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fnkeys?ref=badge_large) diff --git a/vendor/github.com/nats-io/nkeys/crc16.go b/vendor/github.com/nats-io/nkeys/crc16.go index c3356cf..fbe38fb 100644 --- a/vendor/github.com/nats-io/nkeys/crc16.go +++ b/vendor/github.com/nats-io/nkeys/crc16.go @@ -13,15 +13,8 @@ package nkeys -import ( - "errors" -) - // An implementation of crc16 according to CCITT standards for XMODEM. -// ErrInvalidChecksum indicates a failed verification. -var ErrInvalidChecksum = errors.New("nkeys: invalid checksum") - var crc16tab = [256]uint16{ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, diff --git a/vendor/github.com/nats-io/nkeys/creds_utils.go b/vendor/github.com/nats-io/nkeys/creds_utils.go index e1c3d94..ecd9463 100644 --- a/vendor/github.com/nats-io/nkeys/creds_utils.go +++ b/vendor/github.com/nats-io/nkeys/creds_utils.go @@ -2,8 +2,8 @@ package nkeys import ( "bytes" - "errors" "regexp" + "strings" ) var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}.*[-]{3,}\r?\n)([\w\-.=]+)(?:\r?\n[-]{3,}.*[-]{3,}\r?\n))`) @@ -19,7 +19,7 @@ func ParseDecoratedJWT(contents []byte) (string, error) { raw := items[0][1] tmp := make([]byte, len(raw)) copy(tmp, raw) - return string(tmp), nil + return strings.TrimSpace(string(tmp)), nil } // ParseDecoratedNKey takes a creds file, finds the NKey portion and creates a @@ -42,12 +42,12 @@ func ParseDecoratedNKey(contents []byte) (KeyPair, error) { } } if seed == nil { - return nil, errors.New("no nkey seed found") + return nil, ErrNoSeedFound } if !bytes.HasPrefix(seed, []byte("SO")) && !bytes.HasPrefix(seed, []byte("SA")) && !bytes.HasPrefix(seed, []byte("SU")) { - return nil, errors.New("doesn't contain a seed nkey") + return nil, ErrInvalidNkeySeed } kp, err := FromSeed(seed) if err != nil { @@ -68,7 +68,7 @@ func ParseDecoratedUserNKey(contents []byte) (KeyPair, error) { return nil, err } if !bytes.HasPrefix(seed, []byte("SU")) { - return nil, errors.New("doesn't contain an user seed nkey") + return nil, ErrInvalidUserSeed } kp, err := FromSeed(seed) if err != nil { diff --git a/vendor/github.com/nats-io/nkeys/dependencies.md b/vendor/github.com/nats-io/nkeys/dependencies.md new file mode 100644 index 0000000..370184a --- /dev/null +++ b/vendor/github.com/nats-io/nkeys/dependencies.md @@ -0,0 +1,12 @@ +# External Dependencies + +This file lists the dependencies used in this repository. + +| Dependency | License | +|-|-| +| Go | BSD 3-Clause "New" or "Revised" License | +| golang.org/x/crypto v0.3.0 | BSD 3-Clause "New" or "Revised" License | +| golang.org/x/net v0.2.0 | BSD 3-Clause "New" or "Revised" License | +| golang.org/x/sys v0.2.0 | BSD 3-Clause "New" or "Revised" License | +| golang.org/x/term v0.2.0 | BSD 3-Clause "New" or "Revised" License | +| golang.org/x/text v0.4.0 | BSD 3-Clause "New" or "Revised" License | diff --git a/vendor/github.com/nats-io/nkeys/errors.go b/vendor/github.com/nats-io/nkeys/errors.go new file mode 100644 index 0000000..a30bb96 --- /dev/null +++ b/vendor/github.com/nats-io/nkeys/errors.go @@ -0,0 +1,50 @@ +// Copyright 2022 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nkeys + +// Errors +const ( + ErrInvalidPrefixByte = nkeysError("nkeys: invalid prefix byte") + ErrInvalidKey = nkeysError("nkeys: invalid key") + ErrInvalidPublicKey = nkeysError("nkeys: invalid public key") + ErrInvalidPrivateKey = nkeysError("nkeys: invalid private key") + ErrInvalidSeedLen = nkeysError("nkeys: invalid seed length") + ErrInvalidSeed = nkeysError("nkeys: invalid seed") + ErrInvalidEncoding = nkeysError("nkeys: invalid encoded key") + ErrInvalidSignature = nkeysError("nkeys: signature verification failed") + ErrCannotSign = nkeysError("nkeys: can not sign, no private key available") + ErrPublicKeyOnly = nkeysError("nkeys: no seed or private key available") + ErrIncompatibleKey = nkeysError("nkeys: incompatible key") + ErrInvalidChecksum = nkeysError("nkeys: invalid checksum") + ErrNoSeedFound = nkeysError("nkeys: no nkey seed found") + ErrInvalidNkeySeed = nkeysError("nkeys: doesn't contain a seed nkey") + ErrInvalidUserSeed = nkeysError("nkeys: doesn't contain an user seed nkey") + ErrInvalidRecipient = nkeysError("nkeys: not a valid recipient public curve key") + ErrInvalidSender = nkeysError("nkeys: not a valid sender public curve key") + ErrInvalidCurveKey = nkeysError("nkeys: not a valid curve key") + ErrInvalidCurveSeed = nkeysError("nkeys: not a valid curve seed") + ErrInvalidEncrypted = nkeysError("nkeys: encrypted input is not valid") + ErrInvalidEncVersion = nkeysError("nkeys: encrypted input wrong version") + ErrCouldNotDecrypt = nkeysError("nkeys: could not decrypt input") + ErrInvalidCurveKeyOperation = nkeysError("nkeys: curve key is not valid for sign/verify") + ErrInvalidNKeyOperation = nkeysError("nkeys: only curve key can seal/open") + ErrCannotOpen = nkeysError("nkeys: cannot open no private curve key available") + ErrCannotSeal = nkeysError("nkeys: cannot seal no private curve key available") +) + +type nkeysError string + +func (e nkeysError) Error() string { + return string(e) +} diff --git a/vendor/github.com/nats-io/nkeys/go.mod b/vendor/github.com/nats-io/nkeys/go.mod deleted file mode 100644 index 6cdaeb3..0000000 --- a/vendor/github.com/nats-io/nkeys/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/nats-io/nkeys - -require golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 diff --git a/vendor/github.com/nats-io/nkeys/go.sum b/vendor/github.com/nats-io/nkeys/go.sum deleted file mode 100644 index 8fdcca7..0000000 --- a/vendor/github.com/nats-io/nkeys/go.sum +++ /dev/null @@ -1,7 +0,0 @@ -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/nats-io/nkeys/keypair.go b/vendor/github.com/nats-io/nkeys/keypair.go index acd8674..69ebe21 100644 --- a/vendor/github.com/nats-io/nkeys/keypair.go +++ b/vendor/github.com/nats-io/nkeys/keypair.go @@ -1,4 +1,4 @@ -// Copyright 2018 The NATS Authors +// Copyright 2018-2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,10 +15,9 @@ package nkeys import ( "bytes" + "crypto/ed25519" "crypto/rand" "io" - - "golang.org/x/crypto/ed25519" ) // kp is the internal struct for a kepypair using seed. @@ -26,16 +25,25 @@ type kp struct { seed []byte } -// CreatePair will create a KeyPair based on the rand entropy and a type/prefix byte. rand can be nil. +// All seeds are 32 bytes long. +const seedLen = 32 + +// CreatePair will create a KeyPair based on the rand entropy and a type/prefix byte. func CreatePair(prefix PrefixByte) (KeyPair, error) { - var rawSeed [32]byte + return CreatePairWithRand(prefix, nil) +} - _, err := io.ReadFull(rand.Reader, rawSeed[:]) +// CreatePair will create a KeyPair based on the rand reader and a type/prefix byte. rand can be nil. +func CreatePairWithRand(prefix PrefixByte, rr io.Reader) (KeyPair, error) { + if prefix == PrefixByteCurve { + return CreateCurveKeysWithRand(rr) + } + _, priv, err := ed25519.GenerateKey(rr) if err != nil { return nil, err } - seed, err := EncodeSeed(prefix, rawSeed[:]) + seed, err := EncodeSeed(prefix, priv.Seed()) if err != nil { return nil, err } @@ -115,3 +123,18 @@ func (pair *kp) Verify(input []byte, sig []byte) error { } return nil } + +// Seal is only supported on CurveKeyPair +func (pair *kp) Seal(input []byte, recipient string) ([]byte, error) { + return nil, ErrInvalidNKeyOperation +} + +// SealWithRand is only supported on CurveKeyPair +func (pair *kp) SealWithRand(input []byte, recipient string, rr io.Reader) ([]byte, error) { + return nil, ErrInvalidNKeyOperation +} + +// Open is only supported on CurveKey +func (pair *kp) Open(input []byte, sender string) ([]byte, error) { + return nil, ErrInvalidNKeyOperation +} diff --git a/vendor/github.com/nats-io/nkeys/main.go b/vendor/github.com/nats-io/nkeys/nkeys.go similarity index 76% rename from vendor/github.com/nats-io/nkeys/main.go rename to vendor/github.com/nats-io/nkeys/nkeys.go index 1c5d21b..6f1ba20 100644 --- a/vendor/github.com/nats-io/nkeys/main.go +++ b/vendor/github.com/nats-io/nkeys/nkeys.go @@ -13,37 +13,30 @@ // Package nkeys is an Ed25519 based public-key signature system that simplifies keys and seeds // and performs signing and verification. +// It also supports encryption via x25519 keys and is compatible with https://pkg.go.dev/golang.org/x/crypto/nacl/box. package nkeys -import ( - "errors" -) +import "io" // Version is our current version -const Version = "0.2.0" - -// Errors -var ( - ErrInvalidPrefixByte = errors.New("nkeys: invalid prefix byte") - ErrInvalidKey = errors.New("nkeys: invalid key") - ErrInvalidPublicKey = errors.New("nkeys: invalid public key") - ErrInvalidSeedLen = errors.New("nkeys: invalid seed length") - ErrInvalidSeed = errors.New("nkeys: invalid seed") - ErrInvalidEncoding = errors.New("nkeys: invalid encoded key") - ErrInvalidSignature = errors.New("nkeys: signature verification failed") - ErrCannotSign = errors.New("nkeys: can not sign, no private key available") - ErrPublicKeyOnly = errors.New("nkeys: no seed or private key available") - ErrIncompatibleKey = errors.New("nkeys: incompatible key") -) +const Version = "0.4.7" // KeyPair provides the central interface to nkeys. type KeyPair interface { Seed() ([]byte, error) PublicKey() (string, error) PrivateKey() ([]byte, error) + // Sign is only supported on Non CurveKeyPairs Sign(input []byte) ([]byte, error) + // Verify is only supported on Non CurveKeyPairs Verify(input []byte, sig []byte) error Wipe() + // Seal is only supported on CurveKeyPair + Seal(input []byte, recipient string) ([]byte, error) + // SealWithRand is only supported on CurveKeyPair + SealWithRand(input []byte, recipient string, rr io.Reader) ([]byte, error) + // Open is only supported on CurveKey + Open(input []byte, sender string) ([]byte, error) } // CreateUser will create a User typed KeyPair. @@ -86,10 +79,13 @@ func FromPublicKey(public string) (KeyPair, error) { // FromSeed will create a KeyPair capable of signing and verifying signatures. func FromSeed(seed []byte) (KeyPair, error) { - _, _, err := DecodeSeed(seed) + prefix, _, err := DecodeSeed(seed) if err != nil { return nil, err } + if prefix == PrefixByteCurve { + return FromCurveSeed(seed) + } copy := append([]byte{}, seed...) return &kp{copy}, nil } diff --git a/vendor/github.com/nats-io/nkeys/public.go b/vendor/github.com/nats-io/nkeys/public.go index cb7927a..a6e88c9 100644 --- a/vendor/github.com/nats-io/nkeys/public.go +++ b/vendor/github.com/nats-io/nkeys/public.go @@ -1,4 +1,4 @@ -// Copyright 2018 The NATS Authors +// Copyright 2018-2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -14,10 +14,9 @@ package nkeys import ( + "crypto/ed25519" "crypto/rand" "io" - - "golang.org/x/crypto/ed25519" ) // A KeyPair from a public key capable of verifying only. @@ -64,3 +63,23 @@ func (p *pub) Wipe() { p.pre = '0' io.ReadFull(rand.Reader, p.pub) } + +func (p *pub) Seal(input []byte, recipient string) ([]byte, error) { + if p.pre == PrefixByteCurve { + return nil, ErrCannotSeal + } + return nil, ErrInvalidNKeyOperation +} +func (p *pub) SealWithRand(input []byte, _recipient string, rr io.Reader) ([]byte, error) { + if p.pre == PrefixByteCurve { + return nil, ErrCannotSeal + } + return nil, ErrInvalidNKeyOperation +} + +func (p *pub) Open(input []byte, sender string) ([]byte, error) { + if p.pre == PrefixByteCurve { + return nil, ErrCannotOpen + } + return nil, ErrInvalidNKeyOperation +} diff --git a/vendor/github.com/nats-io/nkeys/strkey.go b/vendor/github.com/nats-io/nkeys/strkey.go index 324ea63..8ae3311 100644 --- a/vendor/github.com/nats-io/nkeys/strkey.go +++ b/vendor/github.com/nats-io/nkeys/strkey.go @@ -1,4 +1,4 @@ -// Copyright 2018 The NATS Authors +// Copyright 2018-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,7 +17,6 @@ import ( "bytes" "encoding/base32" "encoding/binary" - "golang.org/x/crypto/ed25519" ) // PrefixByte is a lead byte representing the type. @@ -45,8 +44,11 @@ const ( // PrefixByteUser is the version byte used for encoded NATS Users PrefixByteUser PrefixByte = 20 << 3 // Base32-encodes to 'U...' + // PrefixByteCurve is the version byte used for encoded CurveKeys (X25519) + PrefixByteCurve PrefixByte = 23 << 3 // Base32-encodes to 'X...' + // PrefixByteUnknown is for unknown prefixes. - PrefixByteUnknown PrefixByte = 23 << 3 // Base32-encodes to 'X...' + PrefixByteUnknown PrefixByte = 25 << 3 // Base32-encodes to 'Z...' ) // Set our encoding to not include padding '==' @@ -83,12 +85,13 @@ func Encode(prefix PrefixByte, src []byte) ([]byte, error) { } // EncodeSeed will encode a raw key with the prefix and then seed prefix and crc16 and then base32 encoded. +// `src` must be 32 bytes long (ed25519.SeedSize). func EncodeSeed(public PrefixByte, src []byte) ([]byte, error) { if err := checkValidPublicPrefixByte(public); err != nil { return nil, err } - if len(src) != ed25519.SeedSize { + if len(src) != seedLen { return nil, ErrInvalidSeedLen } @@ -134,22 +137,18 @@ func decode(src []byte) ([]byte, error) { } raw = raw[:n] - if len(raw) < 4 { + if n < 4 { return nil, ErrInvalidEncoding } - var crc uint16 - checksum := bytes.NewReader(raw[len(raw)-2:]) - if err := binary.Read(checksum, binary.LittleEndian, &crc); err != nil { - return nil, err - } + crc := binary.LittleEndian.Uint16(raw[n-2:]) // ensure checksum is valid - if err := validate(raw[0:len(raw)-2], crc); err != nil { + if err := validate(raw[0:n-2], crc); err != nil { return nil, err } - return raw[:len(raw)-2], nil + return raw[:n-2], nil } // Decode will decode the base32 string and check crc16 and enforce the prefix is what is expected. @@ -161,7 +160,8 @@ func Decode(expectedPrefix PrefixByte, src []byte) ([]byte, error) { if err != nil { return nil, err } - if prefix := PrefixByte(raw[0]); prefix != expectedPrefix { + b1 := raw[0] & 248 // 248 = 11111000 + if prefix := PrefixByte(b1); prefix != expectedPrefix { return nil, ErrInvalidPrefixByte } return raw[1:], nil @@ -248,12 +248,18 @@ func IsValidPublicOperatorKey(src string) bool { return err == nil } +// IsValidPublicCurveKey will decode and verify the string is a valid encoded Public Curve Key. +func IsValidPublicCurveKey(src string) bool { + _, err := Decode(PrefixByteCurve, []byte(src)) + return err == nil +} + // checkValidPrefixByte returns an error if the provided value // is not one of the defined valid prefix byte constants. func checkValidPrefixByte(prefix PrefixByte) error { switch prefix { case PrefixByteOperator, PrefixByteServer, PrefixByteCluster, - PrefixByteAccount, PrefixByteUser, PrefixByteSeed, PrefixBytePrivate: + PrefixByteAccount, PrefixByteUser, PrefixByteSeed, PrefixBytePrivate, PrefixByteCurve: return nil } return ErrInvalidPrefixByte @@ -263,7 +269,7 @@ func checkValidPrefixByte(prefix PrefixByte) error { // is not one of the public defined valid prefix byte constants. func checkValidPublicPrefixByte(prefix PrefixByte) error { switch prefix { - case PrefixByteServer, PrefixByteCluster, PrefixByteOperator, PrefixByteAccount, PrefixByteUser: + case PrefixByteOperator, PrefixByteServer, PrefixByteCluster, PrefixByteAccount, PrefixByteUser, PrefixByteCurve: return nil } return ErrInvalidPrefixByte @@ -285,6 +291,8 @@ func (p PrefixByte) String() string { return "seed" case PrefixBytePrivate: return "private" + case PrefixByteCurve: + return "x25519" } return "unknown" } diff --git a/vendor/github.com/nats-io/nkeys/xkeys.go b/vendor/github.com/nats-io/nkeys/xkeys.go new file mode 100644 index 0000000..7951fb7 --- /dev/null +++ b/vendor/github.com/nats-io/nkeys/xkeys.go @@ -0,0 +1,187 @@ +// Copyright 2022-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nkeys + +import ( + "bytes" + "crypto/ed25519" + "crypto/rand" + "encoding/binary" + "io" + + "golang.org/x/crypto/curve25519" + "golang.org/x/crypto/nacl/box" +) + +// This package will support safe use of X25519 keys for asymmetric encryption. +// We will be compatible with nacl.Box, but generate random nonces automatically. +// We may add more advanced options in the future for group recipients and better +// end to end algorithms. + +const ( + curveKeyLen = 32 + curveDecodeLen = 35 + curveNonceLen = 24 +) + +type ckp struct { + seed [curveKeyLen]byte // Private raw key. +} + +// CreateCurveKeys will create a Curve typed KeyPair. +func CreateCurveKeys() (KeyPair, error) { + return CreateCurveKeysWithRand(nil) +} + +// CreateCurveKeysWithRand will create a Curve typed KeyPair +// with specified rand source. +func CreateCurveKeysWithRand(rr io.Reader) (KeyPair, error) { + var kp ckp + _, priv, err := ed25519.GenerateKey(rr) + if err != nil { + return nil, err + } + kp.seed = [curveKeyLen]byte(priv.Seed()) + return &kp, nil +} + +// Will create a curve key pair from seed. +func FromCurveSeed(seed []byte) (KeyPair, error) { + pb, raw, err := DecodeSeed(seed) + if err != nil { + return nil, err + } + if pb != PrefixByteCurve || len(raw) != curveKeyLen { + return nil, ErrInvalidCurveSeed + } + var kp ckp + copy(kp.seed[:], raw) + return &kp, nil +} + +// Seed will return the encoded seed. +func (pair *ckp) Seed() ([]byte, error) { + return EncodeSeed(PrefixByteCurve, pair.seed[:]) +} + +// PublicKey will return the encoded public key. +func (pair *ckp) PublicKey() (string, error) { + var pub [curveKeyLen]byte + curve25519.ScalarBaseMult(&pub, &pair.seed) + key, err := Encode(PrefixByteCurve, pub[:]) + return string(key), err +} + +// PrivateKey will return the encoded private key. +func (pair *ckp) PrivateKey() ([]byte, error) { + return Encode(PrefixBytePrivate, pair.seed[:]) +} + +func decodePubCurveKey(src string, dest []byte) error { + var raw [curveDecodeLen]byte // should always be 35 + n, err := b32Enc.Decode(raw[:], []byte(src)) + if err != nil { + return err + } + if n != curveDecodeLen { + return ErrInvalidCurveKey + } + // Make sure it is what we expected. + if prefix := PrefixByte(raw[0]); prefix != PrefixByteCurve { + return ErrInvalidPublicKey + } + var crc uint16 + end := n - 2 + sum := raw[end:n] + checksum := bytes.NewReader(sum) + if err := binary.Read(checksum, binary.LittleEndian, &crc); err != nil { + return err + } + + // ensure checksum is valid + if err := validate(raw[:end], crc); err != nil { + return err + } + + // Copy over, ignore prefix byte. + copy(dest, raw[1:end]) + return nil +} + +// Only version for now, but could add in X3DH in the future, etc. +const XKeyVersionV1 = "xkv1" +const vlen = len(XKeyVersionV1) + +// Seal is compatible with nacl.Box.Seal() and can be used in similar situations for small messages. +// We generate the nonce from crypto rand by default. +func (pair *ckp) Seal(input []byte, recipient string) ([]byte, error) { + return pair.SealWithRand(input, recipient, rand.Reader) +} + +func (pair *ckp) SealWithRand(input []byte, recipient string, rr io.Reader) ([]byte, error) { + var ( + rpub [curveKeyLen]byte + nonce [curveNonceLen]byte + out [vlen + curveNonceLen]byte + err error + ) + + if err = decodePubCurveKey(recipient, rpub[:]); err != nil { + return nil, ErrInvalidRecipient + } + if _, err := io.ReadFull(rr, nonce[:]); err != nil { + return nil, err + } + copy(out[:vlen], []byte(XKeyVersionV1)) + copy(out[vlen:], nonce[:]) + return box.Seal(out[:], input, &nonce, &rpub, &pair.seed), nil +} + +func (pair *ckp) Open(input []byte, sender string) ([]byte, error) { + if len(input) <= vlen+curveNonceLen { + return nil, ErrInvalidEncrypted + } + var ( + spub [curveKeyLen]byte + nonce [curveNonceLen]byte + err error + ) + if !bytes.Equal(input[:vlen], []byte(XKeyVersionV1)) { + return nil, ErrInvalidEncVersion + } + copy(nonce[:], input[vlen:vlen+curveNonceLen]) + + if err = decodePubCurveKey(sender, spub[:]); err != nil { + return nil, ErrInvalidSender + } + + decrypted, ok := box.Open(nil, input[vlen+curveNonceLen:], &nonce, &spub, &pair.seed) + if !ok { + return nil, ErrCouldNotDecrypt + } + return decrypted, nil +} + +// Wipe will randomize the contents of the secret key +func (pair *ckp) Wipe() { + io.ReadFull(rand.Reader, pair.seed[:]) +} + +func (pair *ckp) Sign(_ []byte) ([]byte, error) { + return nil, ErrInvalidCurveKeyOperation +} + +func (pair *ckp) Verify(_ []byte, _ []byte) error { + return ErrInvalidCurveKeyOperation +} diff --git a/vendor/github.com/rs/cors/.travis.yml b/vendor/github.com/rs/cors/.travis.yml index 17e5e50..f59a345 100644 --- a/vendor/github.com/rs/cors/.travis.yml +++ b/vendor/github.com/rs/cors/.travis.yml @@ -1,7 +1,6 @@ language: go go: -- 1.9 -- "1.10" +- "1.13" - tip matrix: allow_failures: diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go index d301ca7..41d5f7c 100644 --- a/vendor/github.com/rs/cors/cors.go +++ b/vendor/github.com/rs/cors/cors.go @@ -5,8 +5,8 @@ as defined by http://www.w3.org/TR/cors/ You can configure it by passing an option struct to cors.New: c := cors.New(cors.Options{ - AllowedOrigins: []string{"foo.com"}, - AllowedMethods: []string{"GET", "POST", "DELETE"}, + AllowedOrigins: []string{"foo.com"}, + AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete}, AllowCredentials: true, }) @@ -41,7 +41,7 @@ type Options struct { // as argument and returns true if allowed or false otherwise. If this option is // set, the content of AllowedOrigins is ignored. AllowOriginFunc func(origin string) bool - // AllowOriginFunc is a custom function to validate the origin. It takes the HTTP Request object and the origin as + // AllowOriginRequestFunc is a custom function to validate the origin. It takes the HTTP Request object and the origin as // argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` // and `AllowOriginFunc` is ignored. AllowOriginRequestFunc func(r *http.Request, origin string) bool @@ -69,10 +69,15 @@ type Options struct { Debug bool } +// Logger generic interface for logger +type Logger interface { + Printf(string, ...interface{}) +} + // Cors http handler type Cors struct { // Debug logger - Log *log.Logger + Log Logger // Normalized list of plain allowed origins allowedOrigins []string // List of allowed origins containing wildcards @@ -106,7 +111,7 @@ func New(options Options) *Cors { maxAge: options.MaxAge, optionPassthrough: options.OptionsPassthrough, } - if options.Debug { + if options.Debug && c.Log == nil { c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags) } @@ -161,7 +166,7 @@ func New(options Options) *Cors { // Allowed Methods if len(options.AllowedMethods) == 0 { // Default is spec's "simple" methods - c.allowedMethods = []string{"GET", "POST", "HEAD"} + c.allowedMethods = []string{http.MethodGet, http.MethodPost, http.MethodHead} } else { c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper) } @@ -178,8 +183,15 @@ func Default() *Cors { // origins with all standard methods with any header and credentials. func AllowAll() *Cors { return New(Options{ - AllowedOrigins: []string{"*"}, - AllowedMethods: []string{"HEAD", "GET", "POST", "PUT", "PATCH", "DELETE"}, + AllowedOrigins: []string{"*"}, + AllowedMethods: []string{ + http.MethodHead, + http.MethodGet, + http.MethodPost, + http.MethodPut, + http.MethodPatch, + http.MethodDelete, + }, AllowedHeaders: []string{"*"}, AllowCredentials: false, }) @@ -199,7 +211,7 @@ func (c *Cors) Handler(h http.Handler) http.Handler { if c.optionPassthrough { h.ServeHTTP(w, r) } else { - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusNoContent) } } else { c.logf("Handler: Actual request") @@ -232,7 +244,7 @@ func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.Handl if c.optionPassthrough { next(w, r) } else { - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusNoContent) } } else { c.logf("ServeHTTP: Actual request") @@ -304,10 +316,6 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { headers := w.Header() origin := r.Header.Get("Origin") - if r.Method == http.MethodOptions { - c.logf(" Actual request no headers added: method == %s", r.Method) - return - } // Always set Vary, see https://github.com/rs/cors/issues/10 headers.Add("Vary", "Origin") if origin == "" { @@ -342,13 +350,19 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { c.logf(" Actual response added headers: %v", headers) } -// convenience method. checks if debugging is turned on before printing +// convenience method. checks if a logger is set. func (c *Cors) logf(format string, a ...interface{}) { if c.Log != nil { c.Log.Printf(format, a...) } } +// check the Origin of a request. No origin at all is also allowed. +func (c *Cors) OriginAllowed(r *http.Request) bool { + origin := r.Header.Get("Origin") + return c.isOriginAllowed(r, origin) +} + // isOriginAllowed checks if a given origin is allowed to perform cross-domain requests // on the endpoint func (c *Cors) isOriginAllowed(r *http.Request, origin string) bool { @@ -376,7 +390,7 @@ func (c *Cors) isOriginAllowed(r *http.Request, origin string) bool { } // isMethodAllowed checks if a given method can be used as part of a cross-domain request -// on the endpoing +// on the endpoint func (c *Cors) isMethodAllowed(method string) bool { if len(c.allowedMethods) == 0 { // If no method allowed, always return false, even for preflight request @@ -407,6 +421,7 @@ func (c *Cors) areHeadersAllowed(requestedHeaders []string) bool { for _, h := range c.allowedHeaders { if h == header { found = true + break } } if !found { diff --git a/vendor/github.com/rs/cors/go.mod b/vendor/github.com/rs/cors/go.mod deleted file mode 100644 index 0a4c652..0000000 --- a/vendor/github.com/rs/cors/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/rs/cors diff --git a/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go index 53ad9e9..6bb120c 100644 --- a/vendor/github.com/rs/cors/utils.go +++ b/vendor/github.com/rs/cors/utils.go @@ -12,7 +12,7 @@ type wildcard struct { } func (w wildcard) match(s string) bool { - return len(s) >= len(w.prefix+w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) + return len(s) >= len(w.prefix)+len(w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) } // convert converts a list of string using the passed converter function @@ -52,7 +52,7 @@ func parseHeaderList(headerList string) []string { } else { h = append(h, b) } - case b == '-' || b == '_' || (b >= '0' && b <= '9'): + case b == '-' || b == '_' || b == '.' || (b >= '0' && b <= '9'): h = append(h, b) } diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index dc20039..3bb22a9 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -3,6 +3,7 @@ package assert import ( "fmt" "reflect" + "time" ) type CompareType int @@ -13,12 +14,44 @@ const ( compareGreater ) +var ( + intType = reflect.TypeOf(int(1)) + int8Type = reflect.TypeOf(int8(1)) + int16Type = reflect.TypeOf(int16(1)) + int32Type = reflect.TypeOf(int32(1)) + int64Type = reflect.TypeOf(int64(1)) + + uintType = reflect.TypeOf(uint(1)) + uint8Type = reflect.TypeOf(uint8(1)) + uint16Type = reflect.TypeOf(uint16(1)) + uint32Type = reflect.TypeOf(uint32(1)) + uint64Type = reflect.TypeOf(uint64(1)) + + float32Type = reflect.TypeOf(float32(1)) + float64Type = reflect.TypeOf(float64(1)) + + stringType = reflect.TypeOf("") + + timeType = reflect.TypeOf(time.Time{}) +) + func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { + obj1Value := reflect.ValueOf(obj1) + obj2Value := reflect.ValueOf(obj2) + + // throughout this switch we try and avoid calling .Convert() if possible, + // as this has a pretty big performance impact switch kind { case reflect.Int: { - intobj1 := obj1.(int) - intobj2 := obj2.(int) + intobj1, ok := obj1.(int) + if !ok { + intobj1 = obj1Value.Convert(intType).Interface().(int) + } + intobj2, ok := obj2.(int) + if !ok { + intobj2 = obj2Value.Convert(intType).Interface().(int) + } if intobj1 > intobj2 { return compareGreater, true } @@ -31,8 +64,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int8: { - int8obj1 := obj1.(int8) - int8obj2 := obj2.(int8) + int8obj1, ok := obj1.(int8) + if !ok { + int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) + } + int8obj2, ok := obj2.(int8) + if !ok { + int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) + } if int8obj1 > int8obj2 { return compareGreater, true } @@ -45,8 +84,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int16: { - int16obj1 := obj1.(int16) - int16obj2 := obj2.(int16) + int16obj1, ok := obj1.(int16) + if !ok { + int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) + } + int16obj2, ok := obj2.(int16) + if !ok { + int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) + } if int16obj1 > int16obj2 { return compareGreater, true } @@ -59,8 +104,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int32: { - int32obj1 := obj1.(int32) - int32obj2 := obj2.(int32) + int32obj1, ok := obj1.(int32) + if !ok { + int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) + } + int32obj2, ok := obj2.(int32) + if !ok { + int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) + } if int32obj1 > int32obj2 { return compareGreater, true } @@ -73,8 +124,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int64: { - int64obj1 := obj1.(int64) - int64obj2 := obj2.(int64) + int64obj1, ok := obj1.(int64) + if !ok { + int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) + } + int64obj2, ok := obj2.(int64) + if !ok { + int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) + } if int64obj1 > int64obj2 { return compareGreater, true } @@ -87,8 +144,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint: { - uintobj1 := obj1.(uint) - uintobj2 := obj2.(uint) + uintobj1, ok := obj1.(uint) + if !ok { + uintobj1 = obj1Value.Convert(uintType).Interface().(uint) + } + uintobj2, ok := obj2.(uint) + if !ok { + uintobj2 = obj2Value.Convert(uintType).Interface().(uint) + } if uintobj1 > uintobj2 { return compareGreater, true } @@ -101,8 +164,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint8: { - uint8obj1 := obj1.(uint8) - uint8obj2 := obj2.(uint8) + uint8obj1, ok := obj1.(uint8) + if !ok { + uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) + } + uint8obj2, ok := obj2.(uint8) + if !ok { + uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) + } if uint8obj1 > uint8obj2 { return compareGreater, true } @@ -115,8 +184,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint16: { - uint16obj1 := obj1.(uint16) - uint16obj2 := obj2.(uint16) + uint16obj1, ok := obj1.(uint16) + if !ok { + uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) + } + uint16obj2, ok := obj2.(uint16) + if !ok { + uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) + } if uint16obj1 > uint16obj2 { return compareGreater, true } @@ -129,8 +204,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint32: { - uint32obj1 := obj1.(uint32) - uint32obj2 := obj2.(uint32) + uint32obj1, ok := obj1.(uint32) + if !ok { + uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) + } + uint32obj2, ok := obj2.(uint32) + if !ok { + uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) + } if uint32obj1 > uint32obj2 { return compareGreater, true } @@ -143,8 +224,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint64: { - uint64obj1 := obj1.(uint64) - uint64obj2 := obj2.(uint64) + uint64obj1, ok := obj1.(uint64) + if !ok { + uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) + } + uint64obj2, ok := obj2.(uint64) + if !ok { + uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) + } if uint64obj1 > uint64obj2 { return compareGreater, true } @@ -157,8 +244,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Float32: { - float32obj1 := obj1.(float32) - float32obj2 := obj2.(float32) + float32obj1, ok := obj1.(float32) + if !ok { + float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) + } + float32obj2, ok := obj2.(float32) + if !ok { + float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) + } if float32obj1 > float32obj2 { return compareGreater, true } @@ -171,8 +264,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Float64: { - float64obj1 := obj1.(float64) - float64obj2 := obj2.(float64) + float64obj1, ok := obj1.(float64) + if !ok { + float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) + } + float64obj2, ok := obj2.(float64) + if !ok { + float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) + } if float64obj1 > float64obj2 { return compareGreater, true } @@ -185,8 +284,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.String: { - stringobj1 := obj1.(string) - stringobj2 := obj2.(string) + stringobj1, ok := obj1.(string) + if !ok { + stringobj1 = obj1Value.Convert(stringType).Interface().(string) + } + stringobj2, ok := obj2.(string) + if !ok { + stringobj2 = obj2Value.Convert(stringType).Interface().(string) + } if stringobj1 > stringobj2 { return compareGreater, true } @@ -197,6 +302,27 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return compareLess, true } } + // Check for known struct types we can check for compare results. + case reflect.Struct: + { + // All structs enter here. We're not interested in most types. + if !canConvert(obj1Value, timeType) { + break + } + + // time.Time can compared! + timeObj1, ok := obj1.(time.Time) + if !ok { + timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) + } + + timeObj2, ok := obj2.(time.Time) + if !ok { + timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) + } + + return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64) + } } return compareEqual, false @@ -208,7 +334,10 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { // assert.Greater(t, float64(2), float64(1)) // assert.Greater(t, "b", "a") func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) } // GreaterOrEqual asserts that the first element is greater than or equal to the second @@ -218,7 +347,10 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface // assert.GreaterOrEqual(t, "b", "a") // assert.GreaterOrEqual(t, "b", "b") func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) } // Less asserts that the first element is less than the second @@ -227,7 +359,10 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in // assert.Less(t, float64(1), float64(2)) // assert.Less(t, "a", "b") func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) } // LessOrEqual asserts that the first element is less than or equal to the second @@ -237,7 +372,34 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) // assert.LessOrEqual(t, "a", "b") // assert.LessOrEqual(t, "b", "b") func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) +} + +// Positive asserts that the specified element is positive +// +// assert.Positive(t, 1) +// assert.Positive(t, 1.23) +func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + zero := reflect.Zero(reflect.TypeOf(e)) + return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...) +} + +// Negative asserts that the specified element is negative +// +// assert.Negative(t, -1) +// assert.Negative(t, -1.23) +func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + zero := reflect.Zero(reflect.TypeOf(e)) + return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...) } func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go new file mode 100644 index 0000000..df22c47 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go @@ -0,0 +1,16 @@ +//go:build go1.17 +// +build go1.17 + +// TODO: once support for Go 1.16 is dropped, this file can be +// merged/removed with assertion_compare_go1.17_test.go and +// assertion_compare_legacy.go + +package assert + +import "reflect" + +// Wrapper around reflect.Value.CanConvert, for compatability +// reasons. +func canConvert(value reflect.Value, to reflect.Type) bool { + return value.CanConvert(to) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go new file mode 100644 index 0000000..1701af2 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go @@ -0,0 +1,16 @@ +//go:build !go1.17 +// +build !go1.17 + +// TODO: once support for Go 1.16 is dropped, this file can be +// merged/removed with assertion_compare_go1.17_test.go and +// assertion_compare_can_convert.go + +package assert + +import "reflect" + +// Older versions of Go does not have the reflect.Value.CanConvert +// method. +func canConvert(value reflect.Value, to reflect.Type) bool { + return false +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 49370eb..27e2420 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -114,6 +114,36 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { return Error(t, err, append([]interface{}{msg}, args...)...) } +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") +func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...) +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...) +} + // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // @@ -321,6 +351,54 @@ func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsil return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } +// IsDecreasingf asserts that the collection is decreasing +// +// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsDecreasing(t, object, append([]interface{}{msg}, args...)...) +} + +// IsIncreasingf asserts that the collection is increasing +// +// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsIncreasing(t, object, append([]interface{}{msg}, args...)...) +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...) +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) +} + // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -375,6 +453,17 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args . return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) } +// Negativef asserts that the specified element is negative +// +// assert.Negativef(t, -1, "error message %s", "formatted") +// assert.Negativef(t, -1.23, "error message %s", "formatted") +func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Negative(t, e, append([]interface{}{msg}, args...)...) +} + // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -476,6 +565,15 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") @@ -572,6 +670,17 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) } +// Positivef asserts that the specified element is positive +// +// assert.Positivef(t, 1, "error message %s", "formatted") +// assert.Positivef(t, 1.23, "error message %s", "formatted") +func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Positive(t, e, append([]interface{}{msg}, args...)...) +} + // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index 9db8894..d9ea368 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -204,6 +204,66 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { return Error(a.t, err, msgAndArgs...) } +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorAs(a.t, err, target, msgAndArgs...) +} + +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorAsf(a.t, err, target, msg, args...) +} + +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContains(err, expectedErrorSubString) +func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorContains(a.t, theError, contains, msgAndArgs...) +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") +func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorContainsf(a.t, theError, contains, msg, args...) +} + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorIs(a.t, err, target, msgAndArgs...) +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorIsf(a.t, err, target, msg, args...) +} + // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() @@ -631,6 +691,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } +// IsDecreasing asserts that the collection is decreasing +// +// a.IsDecreasing([]int{2, 1, 0}) +// a.IsDecreasing([]float{2, 1}) +// a.IsDecreasing([]string{"b", "a"}) +func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsDecreasing(a.t, object, msgAndArgs...) +} + +// IsDecreasingf asserts that the collection is decreasing +// +// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") +// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsDecreasingf(a.t, object, msg, args...) +} + +// IsIncreasing asserts that the collection is increasing +// +// a.IsIncreasing([]int{1, 2, 3}) +// a.IsIncreasing([]float{1, 2}) +// a.IsIncreasing([]string{"a", "b"}) +func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsIncreasing(a.t, object, msgAndArgs...) +} + +// IsIncreasingf asserts that the collection is increasing +// +// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") +// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsIncreasingf(a.t, object, msg, args...) +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// a.IsNonDecreasing([]int{1, 1, 2}) +// a.IsNonDecreasing([]float{1, 2}) +// a.IsNonDecreasing([]string{"a", "b"}) +func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonDecreasing(a.t, object, msgAndArgs...) +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonDecreasingf(a.t, object, msg, args...) +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// a.IsNonIncreasing([]int{2, 1, 1}) +// a.IsNonIncreasing([]float{2, 1}) +// a.IsNonIncreasing([]string{"b", "a"}) +func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonIncreasing(a.t, object, msgAndArgs...) +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonIncreasingf(a.t, object, msg, args...) +} + // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { @@ -739,6 +895,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i return Lessf(a.t, e1, e2, msg, args...) } +// Negative asserts that the specified element is negative +// +// a.Negative(-1) +// a.Negative(-1.23) +func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Negative(a.t, e, msgAndArgs...) +} + +// Negativef asserts that the specified element is negative +// +// a.Negativef(-1, "error message %s", "formatted") +// a.Negativef(-1.23, "error message %s", "formatted") +func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Negativef(a.t, e, msg, args...) +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -941,6 +1119,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str return NotEqualf(a.t, expected, actual, msg, args...) } +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotErrorIs(a.t, err, target, msgAndArgs...) +} + +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotErrorIsf(a.t, err, target, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1133,6 +1329,28 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b return Panicsf(a.t, f, msg, args...) } +// Positive asserts that the specified element is positive +// +// a.Positive(1) +// a.Positive(1.23) +func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Positive(a.t, e, msgAndArgs...) +} + +// Positivef asserts that the specified element is positive +// +// a.Positivef(1, "error message %s", "formatted") +// a.Positivef(1.23, "error message %s", "formatted") +func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Positivef(a.t, e, msg, args...) +} + // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go new file mode 100644 index 0000000..7594487 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -0,0 +1,81 @@ +package assert + +import ( + "fmt" + "reflect" +) + +// isOrdered checks that collection contains orderable elements. +func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { + objKind := reflect.TypeOf(object).Kind() + if objKind != reflect.Slice && objKind != reflect.Array { + return false + } + + objValue := reflect.ValueOf(object) + objLen := objValue.Len() + + if objLen <= 1 { + return true + } + + value := objValue.Index(0) + valueInterface := value.Interface() + firstValueKind := value.Kind() + + for i := 1; i < objLen; i++ { + prevValue := value + prevValueInterface := valueInterface + + value = objValue.Index(i) + valueInterface = value.Interface() + + compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) + + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) + } + + if !containsValue(allowedComparesResults, compareResult) { + return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) + } + } + + return true +} + +// IsIncreasing asserts that the collection is increasing +// +// assert.IsIncreasing(t, []int{1, 2, 3}) +// assert.IsIncreasing(t, []float{1, 2}) +// assert.IsIncreasing(t, []string{"a", "b"}) +func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// assert.IsNonIncreasing(t, []int{2, 1, 1}) +// assert.IsNonIncreasing(t, []float{2, 1}) +// assert.IsNonIncreasing(t, []string{"b", "a"}) +func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) +} + +// IsDecreasing asserts that the collection is decreasing +// +// assert.IsDecreasing(t, []int{2, 1, 0}) +// assert.IsDecreasing(t, []float{2, 1}) +// assert.IsDecreasing(t, []string{"b", "a"}) +func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// assert.IsNonDecreasing(t, []int{1, 1, 2}) +// assert.IsNonDecreasing(t, []float{1, 2}) +// assert.IsNonDecreasing(t, []string{"a", "b"}) +func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 914a10d..0357b22 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -172,8 +172,8 @@ func isTest(name, prefix string) bool { if len(name) == len(prefix) { // "Test" is ok return true } - rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(rune) + r, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(r) } func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { @@ -718,10 +718,14 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte // return (false, false) if impossible. // return (true, false) if element was not found. // return (true, true) if element was found. -func includeElement(list interface{}, element interface{}) (ok, found bool) { +func containsElement(list interface{}, element interface{}) (ok, found bool) { listValue := reflect.ValueOf(list) - listKind := reflect.TypeOf(list).Kind() + listType := reflect.TypeOf(list) + if listType == nil { + return false, false + } + listKind := listType.Kind() defer func() { if e := recover(); e != nil { ok = false @@ -764,7 +768,7 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo h.Helper() } - ok, found := includeElement(s, contains) + ok, found := containsElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) } @@ -787,7 +791,7 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) h.Helper() } - ok, found := includeElement(s, contains) + ok, found := containsElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) } @@ -831,7 +835,7 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok for i := 0; i < subsetValue.Len(); i++ { element := subsetValue.Index(i).Interface() - ok, found := includeElement(list, element) + ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } @@ -852,7 +856,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) h.Helper() } if subset == nil { - return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) + return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) } subsetValue := reflect.ValueOf(subset) @@ -875,7 +879,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) for i := 0; i < subsetValue.Len(); i++ { element := subsetValue.Index(i).Interface() - ok, found := includeElement(list, element) + ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } @@ -1000,27 +1004,21 @@ func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { type PanicTestFunc func() // didPanic returns true if the function passed to it panics. Otherwise, it returns false. -func didPanic(f PanicTestFunc) (bool, interface{}, string) { - - didPanic := false - var message interface{} - var stack string - func() { - - defer func() { - if message = recover(); message != nil { - didPanic = true - stack = string(debug.Stack()) - } - }() - - // call the target function - f() +func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { + didPanic = true + defer func() { + message = recover() + if didPanic { + stack = string(debug.Stack()) + } }() - return didPanic, message, stack + // call the target function + f() + didPanic = false + return } // Panics asserts that the code inside the specified PanicTestFunc panics. @@ -1161,11 +1159,15 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs bf, bok := toFloat(actual) if !aok || !bok { - return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + return Fail(t, "Parameters must be numerical", msgAndArgs...) + } + + if math.IsNaN(af) && math.IsNaN(bf) { + return true } if math.IsNaN(af) { - return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) + return Fail(t, "Expected must not be NaN", msgAndArgs...) } if math.IsNaN(bf) { @@ -1188,7 +1190,7 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + return Fail(t, "Parameters must be slice", msgAndArgs...) } actualSlice := reflect.ValueOf(actual) @@ -1250,8 +1252,12 @@ func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, m func calcRelativeError(expected, actual interface{}) (float64, error) { af, aok := toFloat(expected) - if !aok { - return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + bf, bok := toFloat(actual) + if !aok || !bok { + return 0, fmt.Errorf("Parameters must be numerical") + } + if math.IsNaN(af) && math.IsNaN(bf) { + return 0, nil } if math.IsNaN(af) { return 0, errors.New("expected value must not be NaN") @@ -1259,10 +1265,6 @@ func calcRelativeError(expected, actual interface{}) (float64, error) { if af == 0 { return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") } - bf, bok := toFloat(actual) - if !bok { - return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) - } if math.IsNaN(bf) { return 0, errors.New("actual value must not be NaN") } @@ -1298,7 +1300,7 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + return Fail(t, "Parameters must be slice", msgAndArgs...) } actualSlice := reflect.ValueOf(actual) @@ -1375,6 +1377,27 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte return true } +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContains(t, err, expectedErrorSubString) +func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !Error(t, theError, msgAndArgs...) { + return false + } + + actual := theError.Error() + if !strings.Contains(actual, contains) { + return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) + } + + return true +} + // matchRegexp return true if a specified regexp matches a string. func matchRegexp(rx interface{}, str interface{}) bool { @@ -1588,12 +1611,17 @@ func diff(expected interface{}, actual interface{}) string { } var e, a string - if et != reflect.TypeOf("") { - e = spewConfig.Sdump(expected) - a = spewConfig.Sdump(actual) - } else { + + switch et { + case reflect.TypeOf(""): e = reflect.ValueOf(expected).String() a = reflect.ValueOf(actual).String() + case reflect.TypeOf(time.Time{}): + e = spewConfigStringerEnabled.Sdump(expected) + a = spewConfigStringerEnabled.Sdump(actual) + default: + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) } diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ @@ -1622,6 +1650,15 @@ var spewConfig = spew.ConfigState{ DisableCapacities: true, SortKeys: true, DisableMethods: true, + MaxDepth: 10, +} + +var spewConfigStringerEnabled = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, + MaxDepth: 10, } type tHelper interface { @@ -1693,3 +1730,81 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D } } } + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if errors.Is(err, target) { + return true + } + + var expectedText string + if target != nil { + expectedText = target.Error() + } + + chain := buildErrorChainString(err) + + return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ + "expected: %q\n"+ + "in chain: %s", expectedText, chain, + ), msgAndArgs...) +} + +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !errors.Is(err, target) { + return true + } + + var expectedText string + if target != nil { + expectedText = target.Error() + } + + chain := buildErrorChainString(err) + + return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ + "found: %q\n"+ + "in chain: %s", expectedText, chain, + ), msgAndArgs...) +} + +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if errors.As(err, target) { + return true + } + + chain := buildErrorChainString(err) + + return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ + "expected: %q\n"+ + "in chain: %s", target, chain, + ), msgAndArgs...) +} + +func buildErrorChainString(err error) string { + if err == nil { + return "" + } + + e := errors.Unwrap(err) + chain := fmt.Sprintf("%q", err.Error()) + for e != nil { + chain += fmt.Sprintf("\n\t%q", e.Error()) + e = errors.Unwrap(e) + } + return chain +} diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index ec4624b..59c4827 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -256,6 +256,84 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) { t.FailNow() } +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorAs(t, err, target, msgAndArgs...) { + return + } + t.FailNow() +} + +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorAsf(t, err, target, msg, args...) { + return + } + t.FailNow() +} + +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContains(t, err, expectedErrorSubString) +func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorContains(t, theError, contains, msgAndArgs...) { + return + } + t.FailNow() +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") +func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorContainsf(t, theError, contains, msg, args...) { + return + } + t.FailNow() +} + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorIs(t, err, target, msgAndArgs...) { + return + } + t.FailNow() +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorIsf(t, err, target, msg, args...) { + return + } + t.FailNow() +} + // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() @@ -806,6 +884,126 @@ func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon fl t.FailNow() } +// IsDecreasing asserts that the collection is decreasing +// +// assert.IsDecreasing(t, []int{2, 1, 0}) +// assert.IsDecreasing(t, []float{2, 1}) +// assert.IsDecreasing(t, []string{"b", "a"}) +func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsDecreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsDecreasingf asserts that the collection is decreasing +// +// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsDecreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// IsIncreasing asserts that the collection is increasing +// +// assert.IsIncreasing(t, []int{1, 2, 3}) +// assert.IsIncreasing(t, []float{1, 2}) +// assert.IsIncreasing(t, []string{"a", "b"}) +func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsIncreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsIncreasingf asserts that the collection is increasing +// +// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsIncreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// assert.IsNonDecreasing(t, []int{1, 1, 2}) +// assert.IsNonDecreasing(t, []float{1, 2}) +// assert.IsNonDecreasing(t, []string{"a", "b"}) +func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonDecreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonDecreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// assert.IsNonIncreasing(t, []int{2, 1, 1}) +// assert.IsNonIncreasing(t, []float{2, 1}) +// assert.IsNonIncreasing(t, []string{"b", "a"}) +func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonIncreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonIncreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { @@ -944,6 +1142,34 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter t.FailNow() } +// Negative asserts that the specified element is negative +// +// assert.Negative(t, -1) +// assert.Negative(t, -1.23) +func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Negative(t, e, msgAndArgs...) { + return + } + t.FailNow() +} + +// Negativef asserts that the specified element is negative +// +// assert.Negativef(t, -1, "error message %s", "formatted") +// assert.Negativef(t, -1.23, "error message %s", "formatted") +func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Negativef(t, e, msg, args...) { + return + } + t.FailNow() +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -1200,6 +1426,30 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotErrorIs(t, err, target, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotErrorIsf(t, err, target, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) @@ -1446,6 +1696,34 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{} t.FailNow() } +// Positive asserts that the specified element is positive +// +// assert.Positive(t, 1) +// assert.Positive(t, 1.23) +func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Positive(t, e, msgAndArgs...) { + return + } + t.FailNow() +} + +// Positivef asserts that the specified element is positive +// +// assert.Positivef(t, 1, "error message %s", "formatted") +// assert.Positivef(t, 1.23, "error message %s", "formatted") +func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Positivef(t, e, msg, args...) { + return + } + t.FailNow() +} + // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 103d7dc..5bb07c8 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -205,6 +205,66 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { Error(a.t, err, msgAndArgs...) } +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorAs(a.t, err, target, msgAndArgs...) +} + +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorAsf(a.t, err, target, msg, args...) +} + +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContains(err, expectedErrorSubString) +func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorContains(a.t, theError, contains, msgAndArgs...) +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") +func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorContainsf(a.t, theError, contains, msg, args...) +} + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorIs(a.t, err, target, msgAndArgs...) +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorIsf(a.t, err, target, msg, args...) +} + // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() @@ -632,6 +692,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } +// IsDecreasing asserts that the collection is decreasing +// +// a.IsDecreasing([]int{2, 1, 0}) +// a.IsDecreasing([]float{2, 1}) +// a.IsDecreasing([]string{"b", "a"}) +func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsDecreasing(a.t, object, msgAndArgs...) +} + +// IsDecreasingf asserts that the collection is decreasing +// +// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") +// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsDecreasingf(a.t, object, msg, args...) +} + +// IsIncreasing asserts that the collection is increasing +// +// a.IsIncreasing([]int{1, 2, 3}) +// a.IsIncreasing([]float{1, 2}) +// a.IsIncreasing([]string{"a", "b"}) +func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsIncreasing(a.t, object, msgAndArgs...) +} + +// IsIncreasingf asserts that the collection is increasing +// +// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") +// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsIncreasingf(a.t, object, msg, args...) +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// a.IsNonDecreasing([]int{1, 1, 2}) +// a.IsNonDecreasing([]float{1, 2}) +// a.IsNonDecreasing([]string{"a", "b"}) +func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonDecreasing(a.t, object, msgAndArgs...) +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonDecreasingf(a.t, object, msg, args...) +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// a.IsNonIncreasing([]int{2, 1, 1}) +// a.IsNonIncreasing([]float{2, 1}) +// a.IsNonIncreasing([]string{"b", "a"}) +func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonIncreasing(a.t, object, msgAndArgs...) +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonIncreasingf(a.t, object, msg, args...) +} + // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { @@ -740,6 +896,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i Lessf(a.t, e1, e2, msg, args...) } +// Negative asserts that the specified element is negative +// +// a.Negative(-1) +// a.Negative(-1.23) +func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Negative(a.t, e, msgAndArgs...) +} + +// Negativef asserts that the specified element is negative +// +// a.Negativef(-1, "error message %s", "formatted") +// a.Negativef(-1.23, "error message %s", "formatted") +func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Negativef(a.t, e, msg, args...) +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -942,6 +1120,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str NotEqualf(a.t, expected, actual, msg, args...) } +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotErrorIs(a.t, err, target, msgAndArgs...) +} + +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotErrorIsf(a.t, err, target, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1134,6 +1330,28 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa Panicsf(a.t, f, msg, args...) } +// Positive asserts that the specified element is positive +// +// a.Positive(1) +// a.Positive(1.23) +func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Positive(a.t, e, msgAndArgs...) +} + +// Positivef asserts that the specified element is positive +// +// a.Positivef(1, "error message %s", "formatted") +// a.Positivef(1.23, "error message %s", "formatted") +func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Positivef(a.t, e, msg, args...) +} + // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS deleted file mode 100644 index 2b00ddb..0000000 --- a/vendor/golang.org/x/crypto/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS deleted file mode 100644 index 1fbd3e9..0000000 --- a/vendor/golang.org/x/crypto/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE index 6a66aea..2a7cf70 100644 --- a/vendor/golang.org/x/crypto/LICENSE +++ b/vendor/golang.org/x/crypto/LICENSE @@ -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. diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go index aeb73f8..3e7f8df 100644 --- a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go +++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go @@ -4,7 +4,7 @@ // Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing // algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf -package bcrypt // import "golang.org/x/crypto/bcrypt" +package bcrypt // The code is a port of Provos and Mazières's C implementation. import ( @@ -50,7 +50,7 @@ func (ih InvalidHashPrefixError) Error() string { type InvalidCostError int func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed inclusive range %d..%d", int(ic), MinCost, MaxCost) } const ( @@ -82,11 +82,20 @@ type hashed struct { minor byte } +// ErrPasswordTooLong is returned when the password passed to +// GenerateFromPassword is too long (i.e. > 72 bytes). +var ErrPasswordTooLong = errors.New("bcrypt: password length exceeds 72 bytes") + // GenerateFromPassword returns the bcrypt hash of the password at the given // cost. If the cost given is less than MinCost, the cost will be set to // DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, // to compare the returned hashed password with its cleartext version. +// GenerateFromPassword does not accept passwords longer than 72 bytes, which +// is the longest password bcrypt will operate on. func GenerateFromPassword(password []byte, cost int) ([]byte, error) { + if len(password) > 72 { + return nil, ErrPasswordTooLong + } p, err := newFromPassword(password, cost) if err != nil { return nil, err diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go new file mode 100644 index 0000000..d2e98d4 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -0,0 +1,291 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xb. +// +// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and +// produces digests of any size between 1 and 64 bytes. +// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf +// and for BLAKE2Xb see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). +// If you need a secret-key MAC (message authentication code), use the New512 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 64 bytes. It +// can produce hash values between 0 and 4 GiB. +package blake2b + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2b in bytes. + BlockSize = 128 + // The hash size of BLAKE2b-512 in bytes. + Size = 64 + // The hash size of BLAKE2b-384 in bytes. + Size384 = 48 + // The hash size of BLAKE2b-256 in bytes. + Size256 = 32 +) + +var ( + useAVX2 bool + useAVX bool + useSSE4 bool +) + +var ( + errKeySize = errors.New("blake2b: invalid key size") + errHashSize = errors.New("blake2b: invalid hash size") +) + +var iv = [8]uint64{ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +} + +// Sum512 returns the BLAKE2b-512 checksum of the data. +func Sum512(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// Sum384 returns the BLAKE2b-384 checksum of the data. +func Sum384(data []byte) [Size384]byte { + var sum [Size]byte + var sum384 [Size384]byte + checkSum(&sum, Size384, data) + copy(sum384[:], sum[:Size384]) + return sum384 +} + +// Sum256 returns the BLAKE2b-256 checksum of the data. +func Sum256(data []byte) [Size256]byte { + var sum [Size]byte + var sum256 [Size256]byte + checkSum(&sum, Size256, data) + copy(sum256[:], sum[:Size256]) + return sum256 +} + +// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } + +// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } + +// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. +// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. +// The hash size can be a value between 1 and 64 but it is highly recommended to use +// values equal or greater than: +// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). +// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. +func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } + +func newDigest(hashSize int, key []byte) (*digest, error) { + if hashSize < 1 || hashSize > Size { + return nil, errHashSize + } + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + h := iv + h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) + var c [2]uint64 + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint64(BlockSize - offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h[:(hashSize+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } +} + +type digest struct { + h [8]uint64 + c [2]uint64 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +const ( + magic = "b2b" + marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2b: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint64(b, d.h[i]) + } + b = appendUint64(b, d.c[0]) + b = appendUint64(b, d.c[1]) + // Maximum value for size is 64 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2b: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2b: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint64(b) + } + b, d.c[0] = consumeUint64(b) + b, d.c[1] = consumeUint64(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + if len(p) > 0 { + d.offset += copy(d.block[:], p) + } + + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + copy(block[:], d.block[:d.offset]) + remaining := uint64(BlockSize - d.offset) + + c := d.c + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + h := d.h + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint64(hash[8*i:], v) + } +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := binary.BigEndian.Uint64(b) + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go new file mode 100644 index 0000000..199c21d --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go @@ -0,0 +1,37 @@ +// 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 amd64 && gc && !purego + +package blake2b + +import "golang.org/x/sys/cpu" + +func init() { + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 +} + +//go:noescape +func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + switch { + case useAVX2: + hashBlocksAVX2(h, c, flag, blocks) + case useAVX: + hashBlocksAVX(h, c, flag, blocks) + case useSSE4: + hashBlocksSSE4(h, c, flag, blocks) + default: + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s new file mode 100644 index 0000000..f75162e --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s @@ -0,0 +1,4559 @@ +// Code generated by command: go run blake2bAVX2_amd64_asm.go -out ../../blake2bAVX2_amd64.s -pkg blake2b. DO NOT EDIT. + +//go:build amd64 && gc && !purego + +#include "textflag.h" + +// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +// Requires: AVX, AVX2 +TEXT ·hashBlocksAVX2(SB), NOSPLIT, $320-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + MOVQ SP, DX + ADDQ $+31, DX + ANDQ $-32, DX + MOVQ CX, 16(DX) + XORQ CX, CX + MOVQ CX, 24(DX) + VMOVDQU ·AVX2_c40<>+0(SB), Y4 + VMOVDQU ·AVX2_c48<>+0(SB), Y5 + VMOVDQU (AX), Y8 + VMOVDQU 32(AX), Y9 + VMOVDQU ·AVX2_iv0<>+0(SB), Y6 + VMOVDQU ·AVX2_iv1<>+0(SB), Y7 + MOVQ (BX), R8 + MOVQ 8(BX), R9 + MOVQ R9, 8(DX) + +loop: + ADDQ $0x80, R8 + MOVQ R8, (DX) + CMPQ R8, $0x80 + JGE noinc + INCQ R9 + MOVQ R9, 8(DX) + +noinc: + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR (DX), Y7, Y3 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x26 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x30 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x28 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x38 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x70 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VMOVDQA Y12, 32(DX) + VMOVDQA Y13, 64(DX) + VMOVDQA Y14, 96(DX) + VMOVDQA Y15, 128(DX) + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x48 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x78 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x30 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x58 + VPSHUFD $0x4e, (SI), X14 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x28 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VMOVDQA Y12, 160(DX) + VMOVDQA Y13, 192(DX) + VMOVDQA Y14, 224(DX) + VMOVDQA Y15, 256(DX) + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x28 + VMOVDQU 88(SI), X12 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x2e + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x48 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x20 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x58 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x70 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x1e + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x40 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x2e + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x30 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x40 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x60 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x1e + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x40 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x58 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x78 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x08 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x70 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x48 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x70 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x20 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x36 + VPSHUFD $0x4e, 64(SI), X11 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x30 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x58 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x48 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x40 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x10 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x3e + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x30 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x58 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x1e + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x78 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x18 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x40 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x08 + VMOVDQU 96(SI), X14 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x10 + VMOVDQU 32(SI), X11 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x38 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x08 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x10 + VPSHUFD $0x4e, 40(SI), X11 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x20 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x78 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x18 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x1e + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + VPADDQ 32(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 64(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ 96(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 128(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + VPADDQ 160(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 192(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ 224(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 256(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + LEAQ 128(SI), SI + SUBQ $0x80, DI + JNE loop + MOVQ R8, (BX) + MOVQ R9, 8(BX) + VMOVDQU Y8, (AX) + VMOVDQU Y9, 32(AX) + VZEROUPPER + RET + +DATA ·AVX2_c40<>+0(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+16(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+24(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), RODATA|NOPTR, $32 + +DATA ·AVX2_c48<>+0(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+16(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+24(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), RODATA|NOPTR, $32 + +DATA ·AVX2_iv0<>+0(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+8(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+16(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+24(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), RODATA|NOPTR, $32 + +DATA ·AVX2_iv1<>+0(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+8(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+16(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+24(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), RODATA|NOPTR, $32 + +// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +// Requires: AVX, SSE2 +TEXT ·hashBlocksAVX(SB), NOSPLIT, $288-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + MOVQ SP, R10 + ADDQ $0x0f, R10 + ANDQ $-16, R10 + VMOVDQU ·AVX_c40<>+0(SB), X0 + VMOVDQU ·AVX_c48<>+0(SB), X1 + VMOVDQA X0, X8 + VMOVDQA X1, X9 + VMOVDQU ·AVX_iv3<>+0(SB), X0 + VMOVDQA X0, (R10) + XORQ CX, (R10) + VMOVDQU (AX), X10 + VMOVDQU 16(AX), X11 + VMOVDQU 32(AX), X2 + VMOVDQU 48(AX), X3 + MOVQ (BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $0x80, R8 + CMPQ R8, $0x80 + JGE noinc + INCQ R9 + +noinc: + BYTE $0xc4 + BYTE $0x41 + BYTE $0xf9 + BYTE $0x6e + BYTE $0xf8 + BYTE $0xc4 + BYTE $0x43 + BYTE $0x81 + BYTE $0x22 + BYTE $0xf9 + BYTE $0x01 + VMOVDQA X10, X0 + VMOVDQA X11, X1 + VMOVDQU ·AVX_iv0<>+0(SB), X4 + VMOVDQU ·AVX_iv1<>+0(SB), X5 + VMOVDQU ·AVX_iv2<>+0(SB), X6 + VPXOR X15, X6, X6 + VMOVDQA (R10), X7 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x26 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x28 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x38 + BYTE $0x01 + VMOVDQA X12, 16(R10) + VMOVDQA X13, 32(R10) + VMOVDQA X14, 48(R10) + VMOVDQA X15, 64(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x78 + BYTE $0x01 + VMOVDQA X12, 80(R10) + VMOVDQA X13, 96(R10) + VMOVDQA X14, 112(R10) + VMOVDQA X15, 128(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x78 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x68 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x30 + BYTE $0x01 + VMOVDQA X12, 144(R10) + VMOVDQA X13, 160(R10) + VMOVDQA X14, 176(R10) + VMOVDQA X15, 192(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VPSHUFD $0x4e, (SI), X12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x18 + BYTE $0x01 + VMOVDQA X12, 208(R10) + VMOVDQA X13, 224(R10) + VMOVDQA X14, 240(R10) + VMOVDQA X15, 256(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VMOVDQU 88(SI), X12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x36 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x68 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x20 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x70 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x3e + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x40 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x36 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x78 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x40 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x60 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x68 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x2e + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x58 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x18 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x78 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x70 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x48 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x50 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + MOVQ (SI), X12 + VPSHUFD $0x4e, 64(SI), X13 + MOVQ 56(SI), X14 + MOVQ 16(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x58 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x48 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + MOVQ 40(SI), X12 + MOVQ 64(SI), X13 + MOVQ (SI), X14 + MOVQ 48(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x50 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + MOVQ 48(SI), X12 + MOVQ 88(SI), X13 + MOVQ 120(SI), X14 + MOVQ 24(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x2e + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x40 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VMOVDQU 96(SI), X12 + MOVQ 8(SI), X13 + MOVQ 16(SI), X14 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x38 + BYTE $0x01 + VMOVDQU 32(SI), X15 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x30 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x28 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + MOVQ 120(SI), X12 + MOVQ 24(SI), X13 + MOVQ 88(SI), X14 + MOVQ 96(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x68 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x3e + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VPADDQ 16(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 32(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 48(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 64(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VPADDQ 80(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 96(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 112(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 128(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VPADDQ 144(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 160(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 176(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 192(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VPADDQ 208(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 224(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 240(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 256(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VMOVDQU 32(AX), X14 + VMOVDQU 48(AX), X15 + VPXOR X0, X10, X10 + VPXOR X1, X11, X11 + VPXOR X2, X14, X14 + VPXOR X3, X15, X15 + VPXOR X4, X10, X10 + VPXOR X5, X11, X11 + VPXOR X6, X14, X2 + VPXOR X7, X15, X3 + VMOVDQU X2, 32(AX) + VMOVDQU X3, 48(AX) + LEAQ 128(SI), SI + SUBQ $0x80, DI + JNE loop + VMOVDQU X10, (AX) + VMOVDQU X11, 16(AX) + MOVQ R8, (BX) + MOVQ R9, 8(BX) + VZEROUPPER + RET + +DATA ·AVX_c40<>+0(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_c48<>+0(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_iv3<>+0(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+8(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_iv0<>+0(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+8(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_iv1<>+0(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+8(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_iv2<>+0(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+8(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), RODATA|NOPTR, $16 diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s new file mode 100644 index 0000000..9a0ce21 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s @@ -0,0 +1,1441 @@ +// Code generated by command: go run blake2b_amd64_asm.go -out ../../blake2b_amd64.s -pkg blake2b. DO NOT EDIT. + +//go:build amd64 && gc && !purego + +#include "textflag.h" + +// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +// Requires: SSE2, SSE4.1, SSSE3 +TEXT ·hashBlocksSSE4(SB), NOSPLIT, $288-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + MOVQ SP, R10 + ADDQ $0x0f, R10 + ANDQ $-16, R10 + MOVOU ·iv3<>+0(SB), X0 + MOVO X0, (R10) + XORQ CX, (R10) + MOVOU ·c40<>+0(SB), X13 + MOVOU ·c48<>+0(SB), X14 + MOVOU (AX), X12 + MOVOU 16(AX), X15 + MOVQ (BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $0x80, R8 + CMPQ R8, $0x80 + JGE noinc + INCQ R9 + +noinc: + MOVQ R8, X8 + PINSRQ $0x01, R9, X8 + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>+0(SB), X4 + MOVOU ·iv1<>+0(SB), X5 + MOVOU ·iv2<>+0(SB), X6 + PXOR X8, X6 + MOVO (R10), X7 + MOVQ (SI), X8 + PINSRQ $0x01, 16(SI), X8 + MOVQ 32(SI), X9 + PINSRQ $0x01, 48(SI), X9 + MOVQ 8(SI), X10 + PINSRQ $0x01, 24(SI), X10 + MOVQ 40(SI), X11 + PINSRQ $0x01, 56(SI), X11 + MOVO X8, 16(R10) + MOVO X9, 32(R10) + MOVO X10, 48(R10) + MOVO X11, 64(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 64(SI), X8 + PINSRQ $0x01, 80(SI), X8 + MOVQ 96(SI), X9 + PINSRQ $0x01, 112(SI), X9 + MOVQ 72(SI), X10 + PINSRQ $0x01, 88(SI), X10 + MOVQ 104(SI), X11 + PINSRQ $0x01, 120(SI), X11 + MOVO X8, 80(R10) + MOVO X9, 96(R10) + MOVO X10, 112(R10) + MOVO X11, 128(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 112(SI), X8 + PINSRQ $0x01, 32(SI), X8 + MOVQ 72(SI), X9 + PINSRQ $0x01, 104(SI), X9 + MOVQ 80(SI), X10 + PINSRQ $0x01, 64(SI), X10 + MOVQ 120(SI), X11 + PINSRQ $0x01, 48(SI), X11 + MOVO X8, 144(R10) + MOVO X9, 160(R10) + MOVO X10, 176(R10) + MOVO X11, 192(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 8(SI), X8 + PINSRQ $0x01, (SI), X8 + MOVQ 88(SI), X9 + PINSRQ $0x01, 40(SI), X9 + MOVQ 96(SI), X10 + PINSRQ $0x01, 16(SI), X10 + MOVQ 56(SI), X11 + PINSRQ $0x01, 24(SI), X11 + MOVO X8, 208(R10) + MOVO X9, 224(R10) + MOVO X10, 240(R10) + MOVO X11, 256(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 88(SI), X8 + PINSRQ $0x01, 96(SI), X8 + MOVQ 40(SI), X9 + PINSRQ $0x01, 120(SI), X9 + MOVQ 64(SI), X10 + PINSRQ $0x01, (SI), X10 + MOVQ 16(SI), X11 + PINSRQ $0x01, 104(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 80(SI), X8 + PINSRQ $0x01, 24(SI), X8 + MOVQ 56(SI), X9 + PINSRQ $0x01, 72(SI), X9 + MOVQ 112(SI), X10 + PINSRQ $0x01, 48(SI), X10 + MOVQ 8(SI), X11 + PINSRQ $0x01, 32(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 56(SI), X8 + PINSRQ $0x01, 24(SI), X8 + MOVQ 104(SI), X9 + PINSRQ $0x01, 88(SI), X9 + MOVQ 72(SI), X10 + PINSRQ $0x01, 8(SI), X10 + MOVQ 96(SI), X11 + PINSRQ $0x01, 112(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 16(SI), X8 + PINSRQ $0x01, 40(SI), X8 + MOVQ 32(SI), X9 + PINSRQ $0x01, 120(SI), X9 + MOVQ 48(SI), X10 + PINSRQ $0x01, 80(SI), X10 + MOVQ (SI), X11 + PINSRQ $0x01, 64(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 72(SI), X8 + PINSRQ $0x01, 40(SI), X8 + MOVQ 16(SI), X9 + PINSRQ $0x01, 80(SI), X9 + MOVQ (SI), X10 + PINSRQ $0x01, 56(SI), X10 + MOVQ 32(SI), X11 + PINSRQ $0x01, 120(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 112(SI), X8 + PINSRQ $0x01, 88(SI), X8 + MOVQ 48(SI), X9 + PINSRQ $0x01, 24(SI), X9 + MOVQ 8(SI), X10 + PINSRQ $0x01, 96(SI), X10 + MOVQ 64(SI), X11 + PINSRQ $0x01, 104(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 16(SI), X8 + PINSRQ $0x01, 48(SI), X8 + MOVQ (SI), X9 + PINSRQ $0x01, 64(SI), X9 + MOVQ 96(SI), X10 + PINSRQ $0x01, 80(SI), X10 + MOVQ 88(SI), X11 + PINSRQ $0x01, 24(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 32(SI), X8 + PINSRQ $0x01, 56(SI), X8 + MOVQ 120(SI), X9 + PINSRQ $0x01, 8(SI), X9 + MOVQ 104(SI), X10 + PINSRQ $0x01, 40(SI), X10 + MOVQ 112(SI), X11 + PINSRQ $0x01, 72(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 96(SI), X8 + PINSRQ $0x01, 8(SI), X8 + MOVQ 112(SI), X9 + PINSRQ $0x01, 32(SI), X9 + MOVQ 40(SI), X10 + PINSRQ $0x01, 120(SI), X10 + MOVQ 104(SI), X11 + PINSRQ $0x01, 80(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ (SI), X8 + PINSRQ $0x01, 48(SI), X8 + MOVQ 72(SI), X9 + PINSRQ $0x01, 64(SI), X9 + MOVQ 56(SI), X10 + PINSRQ $0x01, 24(SI), X10 + MOVQ 16(SI), X11 + PINSRQ $0x01, 88(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 104(SI), X8 + PINSRQ $0x01, 56(SI), X8 + MOVQ 96(SI), X9 + PINSRQ $0x01, 24(SI), X9 + MOVQ 88(SI), X10 + PINSRQ $0x01, 112(SI), X10 + MOVQ 8(SI), X11 + PINSRQ $0x01, 72(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 40(SI), X8 + PINSRQ $0x01, 120(SI), X8 + MOVQ 64(SI), X9 + PINSRQ $0x01, 16(SI), X9 + MOVQ (SI), X10 + PINSRQ $0x01, 32(SI), X10 + MOVQ 48(SI), X11 + PINSRQ $0x01, 80(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 48(SI), X8 + PINSRQ $0x01, 112(SI), X8 + MOVQ 88(SI), X9 + PINSRQ $0x01, (SI), X9 + MOVQ 120(SI), X10 + PINSRQ $0x01, 72(SI), X10 + MOVQ 24(SI), X11 + PINSRQ $0x01, 64(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 96(SI), X8 + PINSRQ $0x01, 104(SI), X8 + MOVQ 8(SI), X9 + PINSRQ $0x01, 80(SI), X9 + MOVQ 16(SI), X10 + PINSRQ $0x01, 56(SI), X10 + MOVQ 32(SI), X11 + PINSRQ $0x01, 40(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 80(SI), X8 + PINSRQ $0x01, 64(SI), X8 + MOVQ 56(SI), X9 + PINSRQ $0x01, 8(SI), X9 + MOVQ 16(SI), X10 + PINSRQ $0x01, 32(SI), X10 + MOVQ 48(SI), X11 + PINSRQ $0x01, 40(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 120(SI), X8 + PINSRQ $0x01, 72(SI), X8 + MOVQ 24(SI), X9 + PINSRQ $0x01, 104(SI), X9 + MOVQ 88(SI), X10 + PINSRQ $0x01, 112(SI), X10 + MOVQ 96(SI), X11 + PINSRQ $0x01, (SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + PADDQ 16(R10), X0 + PADDQ 32(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 48(R10), X0 + PADDQ 64(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + PADDQ 80(R10), X0 + PADDQ 96(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 112(R10), X0 + PADDQ 128(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + PADDQ 144(R10), X0 + PADDQ 160(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 176(R10), X0 + PADDQ 192(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + PADDQ 208(R10), X0 + PADDQ 224(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 240(R10), X0 + PADDQ 256(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + LEAQ 128(SI), SI + SUBQ $0x80, DI + JNE loop + MOVOU X12, (AX) + MOVOU X15, 16(AX) + MOVQ R8, (BX) + MOVQ R9, 8(BX) + RET + +DATA ·iv3<>+0(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+8(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), RODATA|NOPTR, $16 + +DATA ·c40<>+0(SB)/8, $0x0201000706050403 +DATA ·c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), RODATA|NOPTR, $16 + +DATA ·c48<>+0(SB)/8, $0x0100070605040302 +DATA ·c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), RODATA|NOPTR, $16 + +DATA ·iv0<>+0(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+8(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), RODATA|NOPTR, $16 + +DATA ·iv1<>+0(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+8(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), RODATA|NOPTR, $16 + +DATA ·iv2<>+0(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+8(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), RODATA|NOPTR, $16 diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go new file mode 100644 index 0000000..3168a8a --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go @@ -0,0 +1,182 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "math/bits" +) + +// the precomputed values for BLAKE2b +// there are 12 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [12][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second +} + +func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + + for j := range precomputed { + s := &(precomputed[j]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -32) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -24) + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -32) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -24) + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -32) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -24) + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -32) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -24) + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -16) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -63) + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -16) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -63) + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -16) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -63) + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -16) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -63) + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -32) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -24) + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -32) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -24) + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -32) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -24) + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -32) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -24) + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -16) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -63) + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -16) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -63) + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -16) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -63) + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -16) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -63) + + } + + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 + } + c[0], c[1] = c0, c1 +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go new file mode 100644 index 0000000..6e28668 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go @@ -0,0 +1,11 @@ +// 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 !amd64 || purego || !gc + +package blake2b + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + hashBlocksGeneric(h, c, flag, blocks) +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2x.go b/vendor/golang.org/x/crypto/blake2b/blake2x.go new file mode 100644 index 0000000..7692bb3 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2x.go @@ -0,0 +1,185 @@ +// 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. + +package blake2b + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +// +// New callers should prefer the standard library [hash.XOF]. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = (1 << 32) - 1 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 64 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 256GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +// +// The result can be safely interface-upgraded to [hash.XOF]. +func NewXOF(size uint32, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^32-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2b: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint32 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2b: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) BlockSize() int { + return x.d.BlockSize() +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length + x.cfg[17] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[1] ^= uint64(x.length) << 32 + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/go125.go b/vendor/golang.org/x/crypto/blake2b/go125.go new file mode 100644 index 0000000..67e990b --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/go125.go @@ -0,0 +1,11 @@ +// 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.25 + +package blake2b + +import "hash" + +var _ hash.XOF = (*xof)(nil) diff --git a/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/golang.org/x/crypto/blake2b/register.go new file mode 100644 index 0000000..54e446e --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/register.go @@ -0,0 +1,30 @@ +// 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. + +package blake2b + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + newHash384 := func() hash.Hash { + h, _ := New384(nil) + return h + } + + newHash512 := func() hash.Hash { + h, _ := New512(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) + crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) + crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) +} diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go index 213bf20..0898956 100644 --- a/vendor/golang.org/x/crypto/blowfish/cipher.go +++ b/vendor/golang.org/x/crypto/blowfish/cipher.go @@ -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 blowfish // import "golang.org/x/crypto/blowfish" +package blowfish // The code is a port of Bruce Schneier's C implementation. // See https://www.schneier.com/blowfish.html. diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go new file mode 100644 index 0000000..661ea13 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go @@ -0,0 +1,16 @@ +// 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 gc && !purego + +package chacha20 + +const bufSize = 256 + +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s new file mode 100644 index 0000000..769af38 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s @@ -0,0 +1,307 @@ +// 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 gc && !purego + +#include "textflag.h" + +#define NUM_ROUNDS 10 + +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) +TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 + MOVD dst+0(FP), R1 + MOVD src+24(FP), R2 + MOVD src_len+32(FP), R3 + MOVD key+48(FP), R4 + MOVD nonce+56(FP), R6 + MOVD counter+64(FP), R7 + + MOVD $·constants(SB), R10 + MOVD $·incRotMatrix(SB), R11 + + MOVW (R7), R20 + + AND $~255, R3, R13 + ADD R2, R13, R12 // R12 for block end + AND $255, R3, R13 +loop: + MOVD $NUM_ROUNDS, R21 + VLD1 (R11), [V30.S4, V31.S4] + + // load constants + // VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] + WORD $0x4D60E940 + + // load keys + // VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4] + WORD $0x4DFFE884 + // VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4] + WORD $0x4DFFE888 + SUB $32, R4 + + // load counter + nonce + // VLD1R (R7), [V12.S4] + WORD $0x4D40C8EC + + // VLD3R (R6), [V13.S4, V14.S4, V15.S4] + WORD $0x4D40E8CD + + // update counter + VADD V30.S4, V12.S4, V12.S4 + +chacha: + // V0..V3 += V4..V7 + // V12..V15 <<<= ((V12..V15 XOR V0..V3), 16) + VADD V0.S4, V4.S4, V0.S4 + VADD V1.S4, V5.S4, V1.S4 + VADD V2.S4, V6.S4, V2.S4 + VADD V3.S4, V7.S4, V3.S4 + VEOR V12.B16, V0.B16, V12.B16 + VEOR V13.B16, V1.B16, V13.B16 + VEOR V14.B16, V2.B16, V14.B16 + VEOR V15.B16, V3.B16, V15.B16 + VREV32 V12.H8, V12.H8 + VREV32 V13.H8, V13.H8 + VREV32 V14.H8, V14.H8 + VREV32 V15.H8, V15.H8 + // V8..V11 += V12..V15 + // V4..V7 <<<= ((V4..V7 XOR V8..V11), 12) + VADD V8.S4, V12.S4, V8.S4 + VADD V9.S4, V13.S4, V9.S4 + VADD V10.S4, V14.S4, V10.S4 + VADD V11.S4, V15.S4, V11.S4 + VEOR V8.B16, V4.B16, V16.B16 + VEOR V9.B16, V5.B16, V17.B16 + VEOR V10.B16, V6.B16, V18.B16 + VEOR V11.B16, V7.B16, V19.B16 + VSHL $12, V16.S4, V4.S4 + VSHL $12, V17.S4, V5.S4 + VSHL $12, V18.S4, V6.S4 + VSHL $12, V19.S4, V7.S4 + VSRI $20, V16.S4, V4.S4 + VSRI $20, V17.S4, V5.S4 + VSRI $20, V18.S4, V6.S4 + VSRI $20, V19.S4, V7.S4 + + // V0..V3 += V4..V7 + // V12..V15 <<<= ((V12..V15 XOR V0..V3), 8) + VADD V0.S4, V4.S4, V0.S4 + VADD V1.S4, V5.S4, V1.S4 + VADD V2.S4, V6.S4, V2.S4 + VADD V3.S4, V7.S4, V3.S4 + VEOR V12.B16, V0.B16, V12.B16 + VEOR V13.B16, V1.B16, V13.B16 + VEOR V14.B16, V2.B16, V14.B16 + VEOR V15.B16, V3.B16, V15.B16 + VTBL V31.B16, [V12.B16], V12.B16 + VTBL V31.B16, [V13.B16], V13.B16 + VTBL V31.B16, [V14.B16], V14.B16 + VTBL V31.B16, [V15.B16], V15.B16 + + // V8..V11 += V12..V15 + // V4..V7 <<<= ((V4..V7 XOR V8..V11), 7) + VADD V12.S4, V8.S4, V8.S4 + VADD V13.S4, V9.S4, V9.S4 + VADD V14.S4, V10.S4, V10.S4 + VADD V15.S4, V11.S4, V11.S4 + VEOR V8.B16, V4.B16, V16.B16 + VEOR V9.B16, V5.B16, V17.B16 + VEOR V10.B16, V6.B16, V18.B16 + VEOR V11.B16, V7.B16, V19.B16 + VSHL $7, V16.S4, V4.S4 + VSHL $7, V17.S4, V5.S4 + VSHL $7, V18.S4, V6.S4 + VSHL $7, V19.S4, V7.S4 + VSRI $25, V16.S4, V4.S4 + VSRI $25, V17.S4, V5.S4 + VSRI $25, V18.S4, V6.S4 + VSRI $25, V19.S4, V7.S4 + + // V0..V3 += V5..V7, V4 + // V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16) + VADD V0.S4, V5.S4, V0.S4 + VADD V1.S4, V6.S4, V1.S4 + VADD V2.S4, V7.S4, V2.S4 + VADD V3.S4, V4.S4, V3.S4 + VEOR V15.B16, V0.B16, V15.B16 + VEOR V12.B16, V1.B16, V12.B16 + VEOR V13.B16, V2.B16, V13.B16 + VEOR V14.B16, V3.B16, V14.B16 + VREV32 V12.H8, V12.H8 + VREV32 V13.H8, V13.H8 + VREV32 V14.H8, V14.H8 + VREV32 V15.H8, V15.H8 + + // V10 += V15; V5 <<<= ((V10 XOR V5), 12) + // ... + VADD V15.S4, V10.S4, V10.S4 + VADD V12.S4, V11.S4, V11.S4 + VADD V13.S4, V8.S4, V8.S4 + VADD V14.S4, V9.S4, V9.S4 + VEOR V10.B16, V5.B16, V16.B16 + VEOR V11.B16, V6.B16, V17.B16 + VEOR V8.B16, V7.B16, V18.B16 + VEOR V9.B16, V4.B16, V19.B16 + VSHL $12, V16.S4, V5.S4 + VSHL $12, V17.S4, V6.S4 + VSHL $12, V18.S4, V7.S4 + VSHL $12, V19.S4, V4.S4 + VSRI $20, V16.S4, V5.S4 + VSRI $20, V17.S4, V6.S4 + VSRI $20, V18.S4, V7.S4 + VSRI $20, V19.S4, V4.S4 + + // V0 += V5; V15 <<<= ((V0 XOR V15), 8) + // ... + VADD V5.S4, V0.S4, V0.S4 + VADD V6.S4, V1.S4, V1.S4 + VADD V7.S4, V2.S4, V2.S4 + VADD V4.S4, V3.S4, V3.S4 + VEOR V0.B16, V15.B16, V15.B16 + VEOR V1.B16, V12.B16, V12.B16 + VEOR V2.B16, V13.B16, V13.B16 + VEOR V3.B16, V14.B16, V14.B16 + VTBL V31.B16, [V12.B16], V12.B16 + VTBL V31.B16, [V13.B16], V13.B16 + VTBL V31.B16, [V14.B16], V14.B16 + VTBL V31.B16, [V15.B16], V15.B16 + + // V10 += V15; V5 <<<= ((V10 XOR V5), 7) + // ... + VADD V15.S4, V10.S4, V10.S4 + VADD V12.S4, V11.S4, V11.S4 + VADD V13.S4, V8.S4, V8.S4 + VADD V14.S4, V9.S4, V9.S4 + VEOR V10.B16, V5.B16, V16.B16 + VEOR V11.B16, V6.B16, V17.B16 + VEOR V8.B16, V7.B16, V18.B16 + VEOR V9.B16, V4.B16, V19.B16 + VSHL $7, V16.S4, V5.S4 + VSHL $7, V17.S4, V6.S4 + VSHL $7, V18.S4, V7.S4 + VSHL $7, V19.S4, V4.S4 + VSRI $25, V16.S4, V5.S4 + VSRI $25, V17.S4, V6.S4 + VSRI $25, V18.S4, V7.S4 + VSRI $25, V19.S4, V4.S4 + + SUB $1, R21 + CBNZ R21, chacha + + // VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4] + WORD $0x4D60E950 + + // VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4] + WORD $0x4DFFE894 + VADD V30.S4, V12.S4, V12.S4 + VADD V16.S4, V0.S4, V0.S4 + VADD V17.S4, V1.S4, V1.S4 + VADD V18.S4, V2.S4, V2.S4 + VADD V19.S4, V3.S4, V3.S4 + // VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4] + WORD $0x4DFFE898 + // restore R4 + SUB $32, R4 + + // load counter + nonce + // VLD1R (R7), [V28.S4] + WORD $0x4D40C8FC + // VLD3R (R6), [V29.S4, V30.S4, V31.S4] + WORD $0x4D40E8DD + + VADD V20.S4, V4.S4, V4.S4 + VADD V21.S4, V5.S4, V5.S4 + VADD V22.S4, V6.S4, V6.S4 + VADD V23.S4, V7.S4, V7.S4 + VADD V24.S4, V8.S4, V8.S4 + VADD V25.S4, V9.S4, V9.S4 + VADD V26.S4, V10.S4, V10.S4 + VADD V27.S4, V11.S4, V11.S4 + VADD V28.S4, V12.S4, V12.S4 + VADD V29.S4, V13.S4, V13.S4 + VADD V30.S4, V14.S4, V14.S4 + VADD V31.S4, V15.S4, V15.S4 + + VZIP1 V1.S4, V0.S4, V16.S4 + VZIP2 V1.S4, V0.S4, V17.S4 + VZIP1 V3.S4, V2.S4, V18.S4 + VZIP2 V3.S4, V2.S4, V19.S4 + VZIP1 V5.S4, V4.S4, V20.S4 + VZIP2 V5.S4, V4.S4, V21.S4 + VZIP1 V7.S4, V6.S4, V22.S4 + VZIP2 V7.S4, V6.S4, V23.S4 + VZIP1 V9.S4, V8.S4, V24.S4 + VZIP2 V9.S4, V8.S4, V25.S4 + VZIP1 V11.S4, V10.S4, V26.S4 + VZIP2 V11.S4, V10.S4, V27.S4 + VZIP1 V13.S4, V12.S4, V28.S4 + VZIP2 V13.S4, V12.S4, V29.S4 + VZIP1 V15.S4, V14.S4, V30.S4 + VZIP2 V15.S4, V14.S4, V31.S4 + VZIP1 V18.D2, V16.D2, V0.D2 + VZIP2 V18.D2, V16.D2, V4.D2 + VZIP1 V19.D2, V17.D2, V8.D2 + VZIP2 V19.D2, V17.D2, V12.D2 + VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16] + + VZIP1 V22.D2, V20.D2, V1.D2 + VZIP2 V22.D2, V20.D2, V5.D2 + VZIP1 V23.D2, V21.D2, V9.D2 + VZIP2 V23.D2, V21.D2, V13.D2 + VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16] + VZIP1 V26.D2, V24.D2, V2.D2 + VZIP2 V26.D2, V24.D2, V6.D2 + VZIP1 V27.D2, V25.D2, V10.D2 + VZIP2 V27.D2, V25.D2, V14.D2 + VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16] + VZIP1 V30.D2, V28.D2, V3.D2 + VZIP2 V30.D2, V28.D2, V7.D2 + VZIP1 V31.D2, V29.D2, V11.D2 + VZIP2 V31.D2, V29.D2, V15.D2 + VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16] + VEOR V0.B16, V16.B16, V16.B16 + VEOR V1.B16, V17.B16, V17.B16 + VEOR V2.B16, V18.B16, V18.B16 + VEOR V3.B16, V19.B16, V19.B16 + VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1) + VEOR V4.B16, V20.B16, V20.B16 + VEOR V5.B16, V21.B16, V21.B16 + VEOR V6.B16, V22.B16, V22.B16 + VEOR V7.B16, V23.B16, V23.B16 + VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1) + VEOR V8.B16, V24.B16, V24.B16 + VEOR V9.B16, V25.B16, V25.B16 + VEOR V10.B16, V26.B16, V26.B16 + VEOR V11.B16, V27.B16, V27.B16 + VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1) + VEOR V12.B16, V28.B16, V28.B16 + VEOR V13.B16, V29.B16, V29.B16 + VEOR V14.B16, V30.B16, V30.B16 + VEOR V15.B16, V31.B16, V31.B16 + VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1) + + ADD $4, R20 + MOVW R20, (R7) // update counter + + CMP R2, R12 + BGT loop + + RET + + +DATA ·constants+0x00(SB)/4, $0x61707865 +DATA ·constants+0x04(SB)/4, $0x3320646e +DATA ·constants+0x08(SB)/4, $0x79622d32 +DATA ·constants+0x0c(SB)/4, $0x6b206574 +GLOBL ·constants(SB), NOPTR|RODATA, $32 + +DATA ·incRotMatrix+0x00(SB)/4, $0x00000000 +DATA ·incRotMatrix+0x04(SB)/4, $0x00000001 +DATA ·incRotMatrix+0x08(SB)/4, $0x00000002 +DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003 +DATA ·incRotMatrix+0x10(SB)/4, $0x02010003 +DATA ·incRotMatrix+0x14(SB)/4, $0x06050407 +DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B +DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F +GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go new file mode 100644 index 0000000..93eb5ae --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go @@ -0,0 +1,398 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms +// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01. +package chacha20 + +import ( + "crypto/cipher" + "encoding/binary" + "errors" + "math/bits" + + "golang.org/x/crypto/internal/alias" +) + +const ( + // KeySize is the size of the key used by this cipher, in bytes. + KeySize = 32 + + // NonceSize is the size of the nonce used with the standard variant of this + // cipher, in bytes. + // + // Note that this is too short to be safely generated at random if the same + // key is reused more than 2³² times. + NonceSize = 12 + + // NonceSizeX is the size of the nonce used with the XChaCha20 variant of + // this cipher, in bytes. + NonceSizeX = 24 +) + +// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key +// and nonce. A *Cipher implements the cipher.Stream interface. +type Cipher struct { + // The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter + // (incremented after each block), and 3 of nonce. + key [8]uint32 + counter uint32 + nonce [3]uint32 + + // The last len bytes of buf are leftover key stream bytes from the previous + // XORKeyStream invocation. The size of buf depends on how many blocks are + // computed at a time by xorKeyStreamBlocks. + buf [bufSize]byte + len int + + // overflow is set when the counter overflowed, no more blocks can be + // generated, and the next XORKeyStream call should panic. + overflow bool + + // The counter-independent results of the first round are cached after they + // are computed the first time. + precompDone bool + p1, p5, p9, p13 uint32 + p2, p6, p10, p14 uint32 + p3, p7, p11, p15 uint32 +} + +var _ cipher.Stream = (*Cipher)(nil) + +// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given +// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided, +// the XChaCha20 construction will be used. It returns an error if key or nonce +// have any other length. +// +// Note that ChaCha20, like all stream ciphers, is not authenticated and allows +// attackers to silently tamper with the plaintext. For this reason, it is more +// appropriate as a building block than as a standalone encryption mechanism. +// Instead, consider using package golang.org/x/crypto/chacha20poly1305. +func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) { + // This function is split into a wrapper so that the Cipher allocation will + // be inlined, and depending on how the caller uses the return value, won't + // escape to the heap. + c := &Cipher{} + return newUnauthenticatedCipher(c, key, nonce) +} + +func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20: wrong key size") + } + if len(nonce) == NonceSizeX { + // XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a + // derived key, allowing it to operate on a nonce of 24 bytes. See + // draft-irtf-cfrg-xchacha-01, Section 2.3. + key, _ = HChaCha20(key, nonce[0:16]) + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + nonce = cNonce + } else if len(nonce) != NonceSize { + return nil, errors.New("chacha20: wrong nonce size") + } + + key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint + c.key = [8]uint32{ + binary.LittleEndian.Uint32(key[0:4]), + binary.LittleEndian.Uint32(key[4:8]), + binary.LittleEndian.Uint32(key[8:12]), + binary.LittleEndian.Uint32(key[12:16]), + binary.LittleEndian.Uint32(key[16:20]), + binary.LittleEndian.Uint32(key[20:24]), + binary.LittleEndian.Uint32(key[24:28]), + binary.LittleEndian.Uint32(key[28:32]), + } + c.nonce = [3]uint32{ + binary.LittleEndian.Uint32(nonce[0:4]), + binary.LittleEndian.Uint32(nonce[4:8]), + binary.LittleEndian.Uint32(nonce[8:12]), + } + return c, nil +} + +// The constant first 4 words of the ChaCha20 state. +const ( + j0 uint32 = 0x61707865 // expa + j1 uint32 = 0x3320646e // nd 3 + j2 uint32 = 0x79622d32 // 2-by + j3 uint32 = 0x6b206574 // te k +) + +const blockSize = 64 + +// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words. +// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16 +// words each round, in columnar or diagonal groups of 4 at a time. +func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { + a += b + d ^= a + d = bits.RotateLeft32(d, 16) + c += d + b ^= c + b = bits.RotateLeft32(b, 12) + a += b + d ^= a + d = bits.RotateLeft32(d, 8) + c += d + b ^= c + b = bits.RotateLeft32(b, 7) + return a, b, c, d +} + +// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will +// behave as if (64 * counter) bytes had been encrypted so far. +// +// To prevent accidental counter reuse, SetCounter panics if counter is less +// than the current value. +// +// Note that the execution time of XORKeyStream is not independent of the +// counter value. +func (s *Cipher) SetCounter(counter uint32) { + // Internally, s may buffer multiple blocks, which complicates this + // implementation slightly. When checking whether the counter has rolled + // back, we must use both s.counter and s.len to determine how many blocks + // we have already output. + outputCounter := s.counter - uint32(s.len)/blockSize + if s.overflow || counter < outputCounter { + panic("chacha20: SetCounter attempted to rollback counter") + } + + // In the general case, we set the new counter value and reset s.len to 0, + // causing the next call to XORKeyStream to refill the buffer. However, if + // we're advancing within the existing buffer, we can save work by simply + // setting s.len. + if counter < s.counter { + s.len = int(s.counter-counter) * blockSize + } else { + s.counter = counter + s.len = 0 + } +} + +// XORKeyStream XORs each byte in the given slice with a byte from the +// cipher's key stream. Dst and src must overlap entirely or not at all. +// +// If len(dst) < len(src), XORKeyStream will panic. It is acceptable +// to pass a dst bigger than src, and in that case, XORKeyStream will +// only update dst[:len(src)] and will not touch the rest of dst. +// +// Multiple calls to XORKeyStream behave as if the concatenation of +// the src buffers was passed in a single run. That is, Cipher +// maintains state and does not reset at each XORKeyStream call. +func (s *Cipher) XORKeyStream(dst, src []byte) { + if len(src) == 0 { + return + } + if len(dst) < len(src) { + panic("chacha20: output smaller than input") + } + dst = dst[:len(src)] + if alias.InexactOverlap(dst, src) { + panic("chacha20: invalid buffer overlap") + } + + // First, drain any remaining key stream from a previous XORKeyStream. + if s.len != 0 { + keyStream := s.buf[bufSize-s.len:] + if len(src) < len(keyStream) { + keyStream = keyStream[:len(src)] + } + _ = src[len(keyStream)-1] // bounds check elimination hint + for i, b := range keyStream { + dst[i] = src[i] ^ b + } + s.len -= len(keyStream) + dst, src = dst[len(keyStream):], src[len(keyStream):] + } + if len(src) == 0 { + return + } + + // If we'd need to let the counter overflow and keep generating output, + // panic immediately. If instead we'd only reach the last block, remember + // not to generate any more output after the buffer is drained. + numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize + if s.overflow || uint64(s.counter)+numBlocks > 1<<32 { + panic("chacha20: counter overflow") + } else if uint64(s.counter)+numBlocks == 1<<32 { + s.overflow = true + } + + // xorKeyStreamBlocks implementations expect input lengths that are a + // multiple of bufSize. Platform-specific ones process multiple blocks at a + // time, so have bufSizes that are a multiple of blockSize. + + full := len(src) - len(src)%bufSize + if full > 0 { + s.xorKeyStreamBlocks(dst[:full], src[:full]) + } + dst, src = dst[full:], src[full:] + + // If using a multi-block xorKeyStreamBlocks would overflow, use the generic + // one that does one block at a time. + const blocksPerBuf = bufSize / blockSize + if uint64(s.counter)+blocksPerBuf > 1<<32 { + s.buf = [bufSize]byte{} + numBlocks := (len(src) + blockSize - 1) / blockSize + buf := s.buf[bufSize-numBlocks*blockSize:] + copy(buf, src) + s.xorKeyStreamBlocksGeneric(buf, buf) + s.len = len(buf) - copy(dst, buf) + return + } + + // If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and + // keep the leftover keystream for the next XORKeyStream invocation. + if len(src) > 0 { + s.buf = [bufSize]byte{} + copy(s.buf[:], src) + s.xorKeyStreamBlocks(s.buf[:], s.buf[:]) + s.len = bufSize - copy(dst, s.buf[:]) + } +} + +func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { + if len(dst) != len(src) || len(dst)%blockSize != 0 { + panic("chacha20: internal error: wrong dst and/or src length") + } + + // To generate each block of key stream, the initial cipher state + // (represented below) is passed through 20 rounds of shuffling, + // alternatively applying quarterRounds by columns (like 1, 5, 9, 13) + // or by diagonals (like 1, 6, 11, 12). + // + // 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc + // 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk + // 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk + // 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn + // + // c=constant k=key b=blockcount n=nonce + var ( + c0, c1, c2, c3 = j0, j1, j2, j3 + c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3] + c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7] + _, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2] + ) + + // Three quarters of the first round don't depend on the counter, so we can + // calculate them here, and reuse them for multiple blocks in the loop, and + // for future XORKeyStream invocations. + if !s.precompDone { + s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13) + s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14) + s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15) + s.precompDone = true + } + + // A condition of len(src) > 0 would be sufficient, but this also + // acts as a bounds check elimination hint. + for len(src) >= 64 && len(dst) >= 64 { + // The remainder of the first column round. + fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter) + + // The second diagonal round. + x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15) + x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12) + x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13) + x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14) + + // The remaining 18 rounds. + for i := 0; i < 9; i++ { + // Column round. + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + // Diagonal round. + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + // Add back the initial state to generate the key stream, then + // XOR the key stream with the source and write out the result. + addXor(dst[0:4], src[0:4], x0, c0) + addXor(dst[4:8], src[4:8], x1, c1) + addXor(dst[8:12], src[8:12], x2, c2) + addXor(dst[12:16], src[12:16], x3, c3) + addXor(dst[16:20], src[16:20], x4, c4) + addXor(dst[20:24], src[20:24], x5, c5) + addXor(dst[24:28], src[24:28], x6, c6) + addXor(dst[28:32], src[28:32], x7, c7) + addXor(dst[32:36], src[32:36], x8, c8) + addXor(dst[36:40], src[36:40], x9, c9) + addXor(dst[40:44], src[40:44], x10, c10) + addXor(dst[44:48], src[44:48], x11, c11) + addXor(dst[48:52], src[48:52], x12, s.counter) + addXor(dst[52:56], src[52:56], x13, c13) + addXor(dst[56:60], src[56:60], x14, c14) + addXor(dst[60:64], src[60:64], x15, c15) + + s.counter += 1 + + src, dst = src[blockSize:], dst[blockSize:] + } +} + +// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes +// key and a 16 bytes nonce. It returns an error if key or nonce have any other +// length. It is used as part of the XChaCha20 construction. +func HChaCha20(key, nonce []byte) ([]byte, error) { + // This function is split into a wrapper so that the slice allocation will + // be inlined, and depending on how the caller uses the return value, won't + // escape to the heap. + out := make([]byte, 32) + return hChaCha20(out, key, nonce) +} + +func hChaCha20(out, key, nonce []byte) ([]byte, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20: wrong HChaCha20 key size") + } + if len(nonce) != 16 { + return nil, errors.New("chacha20: wrong HChaCha20 nonce size") + } + + x0, x1, x2, x3 := j0, j1, j2, j3 + x4 := binary.LittleEndian.Uint32(key[0:4]) + x5 := binary.LittleEndian.Uint32(key[4:8]) + x6 := binary.LittleEndian.Uint32(key[8:12]) + x7 := binary.LittleEndian.Uint32(key[12:16]) + x8 := binary.LittleEndian.Uint32(key[16:20]) + x9 := binary.LittleEndian.Uint32(key[20:24]) + x10 := binary.LittleEndian.Uint32(key[24:28]) + x11 := binary.LittleEndian.Uint32(key[28:32]) + x12 := binary.LittleEndian.Uint32(nonce[0:4]) + x13 := binary.LittleEndian.Uint32(nonce[4:8]) + x14 := binary.LittleEndian.Uint32(nonce[8:12]) + x15 := binary.LittleEndian.Uint32(nonce[12:16]) + + for i := 0; i < 10; i++ { + // Diagonal round. + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + // Column round. + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + _ = out[31] // bounds check elimination hint + binary.LittleEndian.PutUint32(out[0:4], x0) + binary.LittleEndian.PutUint32(out[4:8], x1) + binary.LittleEndian.PutUint32(out[8:12], x2) + binary.LittleEndian.PutUint32(out[12:16], x3) + binary.LittleEndian.PutUint32(out[16:20], x12) + binary.LittleEndian.PutUint32(out[20:24], x13) + binary.LittleEndian.PutUint32(out[24:28], x14) + binary.LittleEndian.PutUint32(out[28:32], x15) + return out, nil +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go new file mode 100644 index 0000000..c709b72 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go @@ -0,0 +1,13 @@ +// 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 (!arm64 && !s390x && !ppc64 && !ppc64le) || !gc || purego + +package chacha20 + +const bufSize = blockSize + +func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) { + s.xorKeyStreamBlocksGeneric(dst, src) +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go new file mode 100644 index 0000000..bd183d9 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go @@ -0,0 +1,16 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego && (ppc64 || ppc64le) + +package chacha20 + +const bufSize = 256 + +//go:noescape +func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter) +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s new file mode 100644 index 0000000..a660b41 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s @@ -0,0 +1,501 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +// Code for the perl script that generates the ppc64 assembler +// can be found in the cryptogams repository at the link below. It is based on +// the original from openssl. + +// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91 + +// The differences in this and the original implementation are +// due to the calling conventions and initialization of constants. + +//go:build gc && !purego && (ppc64 || ppc64le) + +#include "textflag.h" + +#define OUT R3 +#define INP R4 +#define LEN R5 +#define KEY R6 +#define CNT R7 +#define TMP R15 + +#define CONSTBASE R16 +#define BLOCKS R17 + +// for VPERMXOR +#define MASK R18 + +DATA consts<>+0x00(SB)/4, $0x61707865 +DATA consts<>+0x04(SB)/4, $0x3320646e +DATA consts<>+0x08(SB)/4, $0x79622d32 +DATA consts<>+0x0c(SB)/4, $0x6b206574 +DATA consts<>+0x10(SB)/4, $0x00000001 +DATA consts<>+0x14(SB)/4, $0x00000000 +DATA consts<>+0x18(SB)/4, $0x00000000 +DATA consts<>+0x1c(SB)/4, $0x00000000 +DATA consts<>+0x20(SB)/4, $0x00000004 +DATA consts<>+0x24(SB)/4, $0x00000000 +DATA consts<>+0x28(SB)/4, $0x00000000 +DATA consts<>+0x2c(SB)/4, $0x00000000 +DATA consts<>+0x30(SB)/4, $0x0e0f0c0d +DATA consts<>+0x34(SB)/4, $0x0a0b0809 +DATA consts<>+0x38(SB)/4, $0x06070405 +DATA consts<>+0x3c(SB)/4, $0x02030001 +DATA consts<>+0x40(SB)/4, $0x0d0e0f0c +DATA consts<>+0x44(SB)/4, $0x090a0b08 +DATA consts<>+0x48(SB)/4, $0x05060704 +DATA consts<>+0x4c(SB)/4, $0x01020300 +DATA consts<>+0x50(SB)/4, $0x61707865 +DATA consts<>+0x54(SB)/4, $0x61707865 +DATA consts<>+0x58(SB)/4, $0x61707865 +DATA consts<>+0x5c(SB)/4, $0x61707865 +DATA consts<>+0x60(SB)/4, $0x3320646e +DATA consts<>+0x64(SB)/4, $0x3320646e +DATA consts<>+0x68(SB)/4, $0x3320646e +DATA consts<>+0x6c(SB)/4, $0x3320646e +DATA consts<>+0x70(SB)/4, $0x79622d32 +DATA consts<>+0x74(SB)/4, $0x79622d32 +DATA consts<>+0x78(SB)/4, $0x79622d32 +DATA consts<>+0x7c(SB)/4, $0x79622d32 +DATA consts<>+0x80(SB)/4, $0x6b206574 +DATA consts<>+0x84(SB)/4, $0x6b206574 +DATA consts<>+0x88(SB)/4, $0x6b206574 +DATA consts<>+0x8c(SB)/4, $0x6b206574 +DATA consts<>+0x90(SB)/4, $0x00000000 +DATA consts<>+0x94(SB)/4, $0x00000001 +DATA consts<>+0x98(SB)/4, $0x00000002 +DATA consts<>+0x9c(SB)/4, $0x00000003 +DATA consts<>+0xa0(SB)/4, $0x11223300 +DATA consts<>+0xa4(SB)/4, $0x55667744 +DATA consts<>+0xa8(SB)/4, $0x99aabb88 +DATA consts<>+0xac(SB)/4, $0xddeeffcc +DATA consts<>+0xb0(SB)/4, $0x22330011 +DATA consts<>+0xb4(SB)/4, $0x66774455 +DATA consts<>+0xb8(SB)/4, $0xaabb8899 +DATA consts<>+0xbc(SB)/4, $0xeeffccdd +GLOBL consts<>(SB), RODATA, $0xc0 + +#ifdef GOARCH_ppc64 +#define BE_XXBRW_INIT() \ + LVSL (R0)(R0), V24 \ + VSPLTISB $3, V25 \ + VXOR V24, V25, V24 \ + +#define BE_XXBRW(vr) VPERM vr, vr, V24, vr +#else +#define BE_XXBRW_INIT() +#define BE_XXBRW(vr) +#endif + +//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) +TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 + MOVD out+0(FP), OUT + MOVD inp+8(FP), INP + MOVD len+16(FP), LEN + MOVD key+24(FP), KEY + MOVD counter+32(FP), CNT + + // Addressing for constants + MOVD $consts<>+0x00(SB), CONSTBASE + MOVD $16, R8 + MOVD $32, R9 + MOVD $48, R10 + MOVD $64, R11 + SRD $6, LEN, BLOCKS + // for VPERMXOR + MOVD $consts<>+0xa0(SB), MASK + MOVD $16, R20 + // V16 + LXVW4X (CONSTBASE)(R0), VS48 + ADD $80,CONSTBASE + + // Load key into V17,V18 + LXVW4X (KEY)(R0), VS49 + LXVW4X (KEY)(R8), VS50 + + // Load CNT, NONCE into V19 + LXVW4X (CNT)(R0), VS51 + + // Clear V27 + VXOR V27, V27, V27 + + BE_XXBRW_INIT() + + // V28 + LXVW4X (CONSTBASE)(R11), VS60 + + // Load mask constants for VPERMXOR + LXVW4X (MASK)(R0), V20 + LXVW4X (MASK)(R20), V21 + + // splat slot from V19 -> V26 + VSPLTW $0, V19, V26 + + VSLDOI $4, V19, V27, V19 + VSLDOI $12, V27, V19, V19 + + VADDUWM V26, V28, V26 + + MOVD $10, R14 + MOVD R14, CTR + PCALIGN $16 +loop_outer_vsx: + // V0, V1, V2, V3 + LXVW4X (R0)(CONSTBASE), VS32 + LXVW4X (R8)(CONSTBASE), VS33 + LXVW4X (R9)(CONSTBASE), VS34 + LXVW4X (R10)(CONSTBASE), VS35 + + // splat values from V17, V18 into V4-V11 + VSPLTW $0, V17, V4 + VSPLTW $1, V17, V5 + VSPLTW $2, V17, V6 + VSPLTW $3, V17, V7 + VSPLTW $0, V18, V8 + VSPLTW $1, V18, V9 + VSPLTW $2, V18, V10 + VSPLTW $3, V18, V11 + + // VOR + VOR V26, V26, V12 + + // splat values from V19 -> V13, V14, V15 + VSPLTW $1, V19, V13 + VSPLTW $2, V19, V14 + VSPLTW $3, V19, V15 + + // splat const values + VSPLTISW $-16, V27 + VSPLTISW $12, V28 + VSPLTISW $8, V29 + VSPLTISW $7, V30 + PCALIGN $16 +loop_vsx: + VADDUWM V0, V4, V0 + VADDUWM V1, V5, V1 + VADDUWM V2, V6, V2 + VADDUWM V3, V7, V3 + + VPERMXOR V12, V0, V21, V12 + VPERMXOR V13, V1, V21, V13 + VPERMXOR V14, V2, V21, V14 + VPERMXOR V15, V3, V21, V15 + + VADDUWM V8, V12, V8 + VADDUWM V9, V13, V9 + VADDUWM V10, V14, V10 + VADDUWM V11, V15, V11 + + VXOR V4, V8, V4 + VXOR V5, V9, V5 + VXOR V6, V10, V6 + VXOR V7, V11, V7 + + VRLW V4, V28, V4 + VRLW V5, V28, V5 + VRLW V6, V28, V6 + VRLW V7, V28, V7 + + VADDUWM V0, V4, V0 + VADDUWM V1, V5, V1 + VADDUWM V2, V6, V2 + VADDUWM V3, V7, V3 + + VPERMXOR V12, V0, V20, V12 + VPERMXOR V13, V1, V20, V13 + VPERMXOR V14, V2, V20, V14 + VPERMXOR V15, V3, V20, V15 + + VADDUWM V8, V12, V8 + VADDUWM V9, V13, V9 + VADDUWM V10, V14, V10 + VADDUWM V11, V15, V11 + + VXOR V4, V8, V4 + VXOR V5, V9, V5 + VXOR V6, V10, V6 + VXOR V7, V11, V7 + + VRLW V4, V30, V4 + VRLW V5, V30, V5 + VRLW V6, V30, V6 + VRLW V7, V30, V7 + + VADDUWM V0, V5, V0 + VADDUWM V1, V6, V1 + VADDUWM V2, V7, V2 + VADDUWM V3, V4, V3 + + VPERMXOR V15, V0, V21, V15 + VPERMXOR V12, V1, V21, V12 + VPERMXOR V13, V2, V21, V13 + VPERMXOR V14, V3, V21, V14 + + VADDUWM V10, V15, V10 + VADDUWM V11, V12, V11 + VADDUWM V8, V13, V8 + VADDUWM V9, V14, V9 + + VXOR V5, V10, V5 + VXOR V6, V11, V6 + VXOR V7, V8, V7 + VXOR V4, V9, V4 + + VRLW V5, V28, V5 + VRLW V6, V28, V6 + VRLW V7, V28, V7 + VRLW V4, V28, V4 + + VADDUWM V0, V5, V0 + VADDUWM V1, V6, V1 + VADDUWM V2, V7, V2 + VADDUWM V3, V4, V3 + + VPERMXOR V15, V0, V20, V15 + VPERMXOR V12, V1, V20, V12 + VPERMXOR V13, V2, V20, V13 + VPERMXOR V14, V3, V20, V14 + + VADDUWM V10, V15, V10 + VADDUWM V11, V12, V11 + VADDUWM V8, V13, V8 + VADDUWM V9, V14, V9 + + VXOR V5, V10, V5 + VXOR V6, V11, V6 + VXOR V7, V8, V7 + VXOR V4, V9, V4 + + VRLW V5, V30, V5 + VRLW V6, V30, V6 + VRLW V7, V30, V7 + VRLW V4, V30, V4 + BDNZ loop_vsx + + VADDUWM V12, V26, V12 + + VMRGEW V0, V1, V27 + VMRGEW V2, V3, V28 + + VMRGOW V0, V1, V0 + VMRGOW V2, V3, V2 + + VMRGEW V4, V5, V29 + VMRGEW V6, V7, V30 + + XXPERMDI VS32, VS34, $0, VS33 + XXPERMDI VS32, VS34, $3, VS35 + XXPERMDI VS59, VS60, $0, VS32 + XXPERMDI VS59, VS60, $3, VS34 + + VMRGOW V4, V5, V4 + VMRGOW V6, V7, V6 + + VMRGEW V8, V9, V27 + VMRGEW V10, V11, V28 + + XXPERMDI VS36, VS38, $0, VS37 + XXPERMDI VS36, VS38, $3, VS39 + XXPERMDI VS61, VS62, $0, VS36 + XXPERMDI VS61, VS62, $3, VS38 + + VMRGOW V8, V9, V8 + VMRGOW V10, V11, V10 + + VMRGEW V12, V13, V29 + VMRGEW V14, V15, V30 + + XXPERMDI VS40, VS42, $0, VS41 + XXPERMDI VS40, VS42, $3, VS43 + XXPERMDI VS59, VS60, $0, VS40 + XXPERMDI VS59, VS60, $3, VS42 + + VMRGOW V12, V13, V12 + VMRGOW V14, V15, V14 + + VSPLTISW $4, V27 + VADDUWM V26, V27, V26 + + XXPERMDI VS44, VS46, $0, VS45 + XXPERMDI VS44, VS46, $3, VS47 + XXPERMDI VS61, VS62, $0, VS44 + XXPERMDI VS61, VS62, $3, VS46 + + VADDUWM V0, V16, V0 + VADDUWM V4, V17, V4 + VADDUWM V8, V18, V8 + VADDUWM V12, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + // Bottom of loop + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V1, V16, V0 + VADDUWM V5, V17, V4 + VADDUWM V9, V18, V8 + VADDUWM V13, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(V10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V2, V16, V0 + VADDUWM V6, V17, V4 + VADDUWM V10, V18, V8 + VADDUWM V14, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V3, V16, V0 + VADDUWM V7, V17, V4 + VADDUWM V11, V18, V8 + VADDUWM V15, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + + MOVD $10, R14 + MOVD R14, CTR + BNE loop_outer_vsx + +done_vsx: + // Increment counter by number of 64 byte blocks + MOVWZ (CNT), R14 + ADD BLOCKS, R14 + MOVWZ R14, (CNT) + RET + +tail_vsx: + ADD $32, R1, R11 + MOVD LEN, CTR + + // Save values on stack to copy from + STXVW4X VS32, (R11)(R0) + STXVW4X VS36, (R11)(R8) + STXVW4X VS40, (R11)(R9) + STXVW4X VS44, (R11)(R10) + ADD $-1, R11, R12 + ADD $-1, INP + ADD $-1, OUT + PCALIGN $16 +looptail_vsx: + // Copying the result to OUT + // in bytes. + MOVBZU 1(R12), KEY + MOVBZU 1(INP), TMP + XOR KEY, TMP, KEY + MOVBU KEY, 1(OUT) + BDNZ looptail_vsx + + // Clear the stack values + STXVW4X VS48, (R11)(R0) + STXVW4X VS48, (R11)(R8) + STXVW4X VS48, (R11)(R9) + STXVW4X VS48, (R11)(R10) + BR done_vsx diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go new file mode 100644 index 0000000..683ccfd --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go @@ -0,0 +1,27 @@ +// 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 gc && !purego + +package chacha20 + +import "golang.org/x/sys/cpu" + +var haveAsm = cpu.S390X.HasVX + +const bufSize = 256 + +// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only +// be called when the vector facility is available. Implementation in asm_s390x.s. +// +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + if cpu.S390X.HasVX { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) + } else { + c.xorKeyStreamBlocksGeneric(dst, src) + } +} diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s new file mode 100644 index 0000000..1eda91a --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s @@ -0,0 +1,224 @@ +// 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 gc && !purego + +#include "go_asm.h" +#include "textflag.h" + +// This is an implementation of the ChaCha20 encryption algorithm as +// specified in RFC 7539. It uses vector instructions to compute +// 4 keystream blocks in parallel (256 bytes) which are then XORed +// with the bytes in the input slice. + +GLOBL ·constants<>(SB), RODATA|NOPTR, $32 +// BSWAP: swap bytes in each 4-byte element +DATA ·constants<>+0x00(SB)/4, $0x03020100 +DATA ·constants<>+0x04(SB)/4, $0x07060504 +DATA ·constants<>+0x08(SB)/4, $0x0b0a0908 +DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c +// J0: [j0, j1, j2, j3] +DATA ·constants<>+0x10(SB)/4, $0x61707865 +DATA ·constants<>+0x14(SB)/4, $0x3320646e +DATA ·constants<>+0x18(SB)/4, $0x79622d32 +DATA ·constants<>+0x1c(SB)/4, $0x6b206574 + +#define BSWAP V5 +#define J0 V6 +#define KEY0 V7 +#define KEY1 V8 +#define NONCE V9 +#define CTR V10 +#define M0 V11 +#define M1 V12 +#define M2 V13 +#define M3 V14 +#define INC V15 +#define X0 V16 +#define X1 V17 +#define X2 V18 +#define X3 V19 +#define X4 V20 +#define X5 V21 +#define X6 V22 +#define X7 V23 +#define X8 V24 +#define X9 V25 +#define X10 V26 +#define X11 V27 +#define X12 V28 +#define X13 V29 +#define X14 V30 +#define X15 V31 + +#define NUM_ROUNDS 20 + +#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $16, a2, a2 \ + VERLLF $16, b2, b2 \ + VERLLF $16, c2, c2 \ + VERLLF $16, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $12, a1, a1 \ + VERLLF $12, b1, b1 \ + VERLLF $12, c1, c1 \ + VERLLF $12, d1, d1 \ + VAF a1, a0, a0 \ + VAF b1, b0, b0 \ + VAF c1, c0, c0 \ + VAF d1, d0, d0 \ + VX a0, a2, a2 \ + VX b0, b2, b2 \ + VX c0, c2, c2 \ + VX d0, d2, d2 \ + VERLLF $8, a2, a2 \ + VERLLF $8, b2, b2 \ + VERLLF $8, c2, c2 \ + VERLLF $8, d2, d2 \ + VAF a2, a3, a3 \ + VAF b2, b3, b3 \ + VAF c2, c3, c3 \ + VAF d2, d3, d3 \ + VX a3, a1, a1 \ + VX b3, b1, b1 \ + VX c3, c1, c1 \ + VX d3, d1, d1 \ + VERLLF $7, a1, a1 \ + VERLLF $7, b1, b1 \ + VERLLF $7, c1, c1 \ + VERLLF $7, d1, d1 + +#define PERMUTE(mask, v0, v1, v2, v3) \ + VPERM v0, v0, mask, v0 \ + VPERM v1, v1, mask, v1 \ + VPERM v2, v2, mask, v2 \ + VPERM v3, v3, mask, v3 + +#define ADDV(x, v0, v1, v2, v3) \ + VAF x, v0, v0 \ + VAF x, v1, v1 \ + VAF x, v2, v2 \ + VAF x, v3, v3 + +#define XORV(off, dst, src, v0, v1, v2, v3) \ + VLM off(src), M0, M3 \ + PERMUTE(BSWAP, v0, v1, v2, v3) \ + VX v0, M0, M0 \ + VX v1, M1, M1 \ + VX v2, M2, M2 \ + VX v3, M3, M3 \ + VSTM M0, M3, off(dst) + +#define SHUFFLE(a, b, c, d, t, u, v, w) \ + VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]} + VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]} + VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]} + VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]} + VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]} + VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]} + VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} + VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} + +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) +TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 + MOVD $·constants<>(SB), R1 + MOVD dst+0(FP), R2 // R2=&dst[0] + LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src) + MOVD key+48(FP), R5 // R5=key + MOVD nonce+56(FP), R6 // R6=nonce + MOVD counter+64(FP), R7 // R7=counter + + // load BSWAP and J0 + VLM (R1), BSWAP, J0 + + // setup + MOVD $95, R0 + VLM (R5), KEY0, KEY1 + VLL R0, (R6), NONCE + VZERO M0 + VLEIB $7, $32, M0 + VSRLB M0, NONCE, NONCE + + // initialize counter values + VLREPF (R7), CTR + VZERO INC + VLEIF $1, $1, INC + VLEIF $2, $2, INC + VLEIF $3, $3, INC + VAF INC, CTR, CTR + VREPIF $4, INC + +chacha: + VREPF $0, J0, X0 + VREPF $1, J0, X1 + VREPF $2, J0, X2 + VREPF $3, J0, X3 + VREPF $0, KEY0, X4 + VREPF $1, KEY0, X5 + VREPF $2, KEY0, X6 + VREPF $3, KEY0, X7 + VREPF $0, KEY1, X8 + VREPF $1, KEY1, X9 + VREPF $2, KEY1, X10 + VREPF $3, KEY1, X11 + VLR CTR, X12 + VREPF $1, NONCE, X13 + VREPF $2, NONCE, X14 + VREPF $3, NONCE, X15 + + MOVD $(NUM_ROUNDS/2), R1 + +loop: + ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11) + ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9) + + ADD $-1, R1 + BNE loop + + // decrement length + ADD $-256, R4 + + // rearrange vectors + SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) + ADDV(J0, X0, X1, X2, X3) + SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3) + ADDV(KEY0, X4, X5, X6, X7) + SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3) + ADDV(KEY1, X8, X9, X10, X11) + VAF CTR, X12, X12 + SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3) + ADDV(NONCE, X12, X13, X14, X15) + + // increment counters + VAF INC, CTR, CTR + + // xor keystream with plaintext + XORV(0*64, R2, R3, X0, X4, X8, X12) + XORV(1*64, R2, R3, X1, X5, X9, X13) + XORV(2*64, R2, R3, X2, X6, X10, X14) + XORV(3*64, R2, R3, X3, X7, X11, X15) + + // increment pointers + MOVD $256(R2), R2 + MOVD $256(R3), R3 + + CMPBNE R4, $0, chacha + + VSTEF $0, CTR, (R7) + RET diff --git a/vendor/golang.org/x/crypto/chacha20/xor.go b/vendor/golang.org/x/crypto/chacha20/xor.go new file mode 100644 index 0000000..c2d0485 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20/xor.go @@ -0,0 +1,42 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found src the LICENSE file. + +package chacha20 + +import "runtime" + +// Platforms that have fast unaligned 32-bit little endian accesses. +const unaligned = runtime.GOARCH == "386" || + runtime.GOARCH == "amd64" || + runtime.GOARCH == "arm64" || + runtime.GOARCH == "ppc64le" || + runtime.GOARCH == "s390x" + +// addXor reads a little endian uint32 from src, XORs it with (a + b) and +// places the result in little endian byte order in dst. +func addXor(dst, src []byte, a, b uint32) { + _, _ = src[3], dst[3] // bounds check elimination hint + if unaligned { + // The compiler should optimize this code into + // 32-bit unaligned little endian loads and stores. + // TODO: delete once the compiler does a reliably + // good job with the generic code below. + // See issue #25111 for more details. + v := uint32(src[0]) + v |= uint32(src[1]) << 8 + v |= uint32(src[2]) << 16 + v |= uint32(src[3]) << 24 + v ^= a + b + dst[0] = byte(v) + dst[1] = byte(v >> 8) + dst[2] = byte(v >> 16) + dst[3] = byte(v >> 24) + } else { + a += b + dst[0] = src[0] ^ byte(a) + dst[1] = src[1] ^ byte(a>>8) + dst[2] = src[2] ^ byte(a>>16) + dst[3] = src[3] ^ byte(a>>24) + } +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go new file mode 100644 index 0000000..9567955 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -0,0 +1,101 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its +// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and +// draft-irtf-cfrg-xchacha-01. +package chacha20poly1305 + +import ( + "crypto/cipher" + "errors" +) + +const ( + // KeySize is the size of the key used by this AEAD, in bytes. + KeySize = 32 + + // NonceSize is the size of the nonce used with the standard variant of this + // AEAD, in bytes. + // + // Note that this is too short to be safely generated at random if the same + // key is reused more than 2³² times. + NonceSize = 12 + + // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 + // variant of this AEAD, in bytes. + NonceSizeX = 24 + + // Overhead is the size of the Poly1305 authentication tag, and the + // difference between a ciphertext length and its plaintext. + Overhead = 16 +) + +type chacha20poly1305 struct { + key [KeySize]byte +} + +// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. +func New(key []byte) (cipher.AEAD, error) { + if fips140Enforced() { + return nil, errors.New("chacha20poly1305: use of ChaCha20Poly1305 is not allowed in FIPS 140-only mode") + } + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(chacha20poly1305) + copy(ret.key[:], key) + return ret, nil +} + +func (c *chacha20poly1305) NonceSize() int { + return NonceSize +} + +func (c *chacha20poly1305) Overhead() int { + return Overhead +} + +func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSize { + panic("chacha20poly1305: bad nonce length passed to Seal") + } + + if uint64(len(plaintext)) > (1<<38)-64 { + panic("chacha20poly1305: plaintext too large") + } + + return c.seal(dst, nonce, plaintext, additionalData) +} + +var errOpen = errors.New("chacha20poly1305: message authentication failed") + +func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSize { + panic("chacha20poly1305: bad nonce length passed to Open") + } + if len(ciphertext) < 16 { + return nil, errOpen + } + if uint64(len(ciphertext)) > (1<<38)-48 { + panic("chacha20poly1305: ciphertext too large") + } + + return c.open(dst, nonce, ciphertext, additionalData) +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go new file mode 100644 index 0000000..b850e77 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go @@ -0,0 +1,92 @@ +// 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 gc && !purego + +package chacha20poly1305 + +import ( + "encoding/binary" + + "golang.org/x/crypto/internal/alias" + "golang.org/x/sys/cpu" +) + +//go:noescape +func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool + +//go:noescape +func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) + +var ( + useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 +) + +// setupState writes a ChaCha20 input matrix to state. See +// https://tools.ietf.org/html/rfc7539#section-2.3. +func setupState(state *[16]uint32, key *[32]byte, nonce []byte) { + state[0] = 0x61707865 + state[1] = 0x3320646e + state[2] = 0x79622d32 + state[3] = 0x6b206574 + + state[4] = binary.LittleEndian.Uint32(key[0:4]) + state[5] = binary.LittleEndian.Uint32(key[4:8]) + state[6] = binary.LittleEndian.Uint32(key[8:12]) + state[7] = binary.LittleEndian.Uint32(key[12:16]) + state[8] = binary.LittleEndian.Uint32(key[16:20]) + state[9] = binary.LittleEndian.Uint32(key[20:24]) + state[10] = binary.LittleEndian.Uint32(key[24:28]) + state[11] = binary.LittleEndian.Uint32(key[28:32]) + + state[12] = 0 + state[13] = binary.LittleEndian.Uint32(nonce[0:4]) + state[14] = binary.LittleEndian.Uint32(nonce[4:8]) + state[15] = binary.LittleEndian.Uint32(nonce[8:12]) +} + +func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { + if !cpu.X86.HasSSSE3 { + return c.sealGeneric(dst, nonce, plaintext, additionalData) + } + + var state [16]uint32 + setupState(&state, &c.key, nonce) + + ret, out := sliceForAppend(dst, len(plaintext)+16) + if alias.InexactOverlap(out, plaintext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") + } + chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData) + return ret +} + +func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if !cpu.X86.HasSSSE3 { + return c.openGeneric(dst, nonce, ciphertext, additionalData) + } + + var state [16]uint32 + setupState(&state, &c.key, nonce) + + ciphertext = ciphertext[:len(ciphertext)-16] + ret, out := sliceForAppend(dst, len(ciphertext)) + if alias.InexactOverlap(out, ciphertext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") + } + if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) { + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + return ret, nil +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s new file mode 100644 index 0000000..fd5ee84 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s @@ -0,0 +1,9762 @@ +// Code generated by command: go run chacha20poly1305_amd64_asm.go -out ../chacha20poly1305_amd64.s -pkg chacha20poly1305. DO NOT EDIT. + +//go:build gc && !purego + +#include "textflag.h" + +// func polyHashADInternal<>() +TEXT polyHashADInternal<>(SB), NOSPLIT, $0 + // Hack: Must declare #define macros inside of a function due to Avo constraints + // ROL rotates the uint32s in register R left by N bits, using temporary T. + #define ROL(N, R, T) \ + MOVO R, T; \ + PSLLL $(N), T; \ + PSRLL $(32-(N)), R; \ + PXOR T, R + + // ROL8 rotates the uint32s in register R left by 8, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL8(R, T) PSHUFB ·rol8<>(SB), R + #else + #define ROL8(R, T) ROL(8, R, T) + #endif + + // ROL16 rotates the uint32s in register R left by 16, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL16(R, T) PSHUFB ·rol16<>(SB), R + #else + #define ROL16(R, T) ROL(16, R, T) + #endif + XORQ R10, R10 + XORQ R11, R11 + XORQ R12, R12 + CMPQ R9, $0x0d + JNE hashADLoop + MOVQ (CX), R10 + MOVQ 5(CX), R11 + SHRQ $0x18, R11 + MOVQ $0x00000001, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + RET + +hashADLoop: + // Hash in 16 byte chunks + CMPQ R9, $0x10 + JB hashADTail + ADDQ (CX), R10 + ADCQ 8(CX), R11 + ADCQ $0x01, R12 + LEAQ 16(CX), CX + SUBQ $0x10, R9 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + JMP hashADLoop + +hashADTail: + CMPQ R9, $0x00 + JE hashADDone + + // Hash last < 16 byte tail + XORQ R13, R13 + XORQ R14, R14 + XORQ R15, R15 + ADDQ R9, CX + +hashADTailLoop: + SHLQ $0x08, R13, R14 + SHLQ $0x08, R13 + MOVB -1(CX), R15 + XORQ R15, R13 + DECQ CX + DECQ R9 + JNE hashADTailLoop + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +hashADDone: + RET + +// func chacha20Poly1305Open(dst []byte, key []uint32, src []byte, ad []byte) bool +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Open(SB), $288-97 + // For aligned stack access + MOVQ SP, BP + ADDQ $0x20, BP + ANDQ $-32, BP + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX + + // Check for AVX2 support + CMPB ·useAVX2+0(SB), $0x01 + JE chacha20Poly1305Open_AVX2 + + // Special optimization, for very short buffers + CMPQ BX, $0x80 + JBE openSSE128 + + // For long buffers, prepare the poly key first + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X9, X13 + + // Store state on stack for future use + MOVO X3, 32(BP) + MOVO X6, 48(BP) + MOVO X9, 128(BP) + MOVQ $0x0000000a, R9 + +openSSEPreparePolyKey: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + DECQ R9 + JNE openSSEPreparePolyKey + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 + + // Clamp and store the key + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) + + // Hash AAD + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + +openSSEMainLoop: + CMPQ BX, $0x00000100 + JB openSSEMainLoopDone + + // Load state, increment counter blocks + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + + // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash + // 2 blocks, and for the remaining 4 only 1 block - for a total of 16 + MOVQ $0x00000004, CX + MOVQ SI, R9 + +openSSEInternalLoop: + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(R9), R9 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ CX + JGE openSSEInternalLoop + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + CMPQ CX, $-6 + JG openSSEInternalLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + + // Load - xor - store + MOVO X15, 64(BP) + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU X0, (DI) + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU X3, 16(DI) + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU X6, 32(DI) + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X9, 48(DI) + MOVOU 64(SI), X9 + PXOR X9, X1 + MOVOU X1, 64(DI) + MOVOU 80(SI), X9 + PXOR X9, X4 + MOVOU X4, 80(DI) + MOVOU 96(SI), X9 + PXOR X9, X7 + MOVOU X7, 96(DI) + MOVOU 112(SI), X9 + PXOR X9, X10 + MOVOU X10, 112(DI) + MOVOU 128(SI), X9 + PXOR X9, X2 + MOVOU X2, 128(DI) + MOVOU 144(SI), X9 + PXOR X9, X5 + MOVOU X5, 144(DI) + MOVOU 160(SI), X9 + PXOR X9, X8 + MOVOU X8, 160(DI) + MOVOU 176(SI), X9 + PXOR X9, X11 + MOVOU X11, 176(DI) + MOVOU 192(SI), X9 + PXOR X9, X12 + MOVOU X12, 192(DI) + MOVOU 208(SI), X9 + PXOR X9, X13 + MOVOU X13, 208(DI) + MOVOU 224(SI), X9 + PXOR X9, X14 + MOVOU X14, 224(DI) + MOVOU 240(SI), X9 + PXOR 64(BP), X9 + MOVOU X9, 240(DI) + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX + JMP openSSEMainLoop + +openSSEMainLoopDone: + // Handle the various tail sizes efficiently + TESTQ BX, BX + JE openSSEFinalize + CMPQ BX, $0x40 + JBE openSSETail64 + CMPQ BX, $0x80 + JBE openSSETail128 + CMPQ BX, $0xc0 + JBE openSSETail192 + JMP openSSETail256 + +openSSEFinalize: + // Hash in the PT, AAD lengths + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Final reduce + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 + + // Add in the "s" part of the key + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 + + // Finally, constant time compare to the tag at the end of the message + XORQ AX, AX + MOVQ $0x00000001, DX + XORQ (SI), R10 + XORQ 8(SI), R11 + ORQ R11, R10 + CMOVQEQ DX, AX + + // Return true iff tags are equal + MOVB AX, ret+96(FP) + RET + +openSSE128: + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 + +openSSE128InnerCipherLoop: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE openSSE128InnerCipherLoop + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 + + // Clamp and store the key + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) + + // Hash + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + +openSSE128Open: + CMPQ BX, $0x10 + JB openSSETail16 + SUBQ $0x10, BX + + // Load for hashing + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + + // Load for decryption + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Shift the stream "left" + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 + JMP openSSE128Open + +openSSETail16: + TESTQ BX, BX + JE openSSEFinalize + + // We can safely load the CT from the end, because it is padded with the MAC + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVOU (SI), X12 + ADDQ BX, SI + PAND -16(R13)(R9*1), X12 + MOVO X12, 64(BP) + MOVQ X12, R13 + MOVQ 72(BP), R14 + PXOR X1, X12 + + // We can only store one byte at a time, since plaintext can be shorter than 16 bytes +openSSETail16Store: + MOVQ X12, R8 + MOVB R8, (DI) + PSRLDQ $0x01, X12 + INCQ DI + DECQ BX + JNE openSSETail16Store + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + JMP openSSEFinalize + +openSSETail64: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + XORQ R9, R9 + MOVQ BX, CX + CMPQ CX, $0x10 + JB openSSETail64LoopB + +openSSETail64LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + +openSSETail64LoopB: + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + CMPQ CX, $0x10 + JAE openSSETail64LoopA + CMPQ R9, $0xa0 + JNE openSSETail64LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 + PADDL 48(BP), X6 + PADDL 80(BP), X9 + +openSSETail64DecLoop: + CMPQ BX, $0x10 + JB openSSETail64DecLoopDone + SUBQ $0x10, BX + MOVOU (SI), X12 + PXOR X12, X0 + MOVOU X0, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVO X3, X0 + MOVO X6, X3 + MOVO X9, X6 + JMP openSSETail64DecLoop + +openSSETail64DecLoopDone: + MOVO X0, X1 + JMP openSSETail16 + +openSSETail128: + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 96(BP) + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX + +openSSETail128LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openSSETail128LoopB: + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + CMPQ R9, CX + JB openSSETail128LoopA + CMPQ R9, $0xa0 + JNE openSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 96(BP), X9 + PADDL 80(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + SUBQ $0x40, BX + LEAQ 64(SI), SI + LEAQ 64(DI), DI + JMP openSSETail64DecLoop + +openSSETail192: + MOVO ·chacha20Constants<>+0(SB), X2 + MOVO 32(BP), X5 + MOVO 48(BP), X8 + MOVO 128(BP), X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 80(BP) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 112(BP) + MOVQ BX, CX + MOVQ $0x000000a0, R9 + CMPQ CX, $0xa0 + CMOVQGT R9, CX + ANDQ $-16, CX + XORQ R9, R9 + +openSSLTail192LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openSSLTail192LoopB: + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + CMPQ R9, CX + JB openSSLTail192LoopA + CMPQ R9, $0xa0 + JNE openSSLTail192LoopB + CMPQ BX, $0xb0 + JB openSSLTail192Store + ADDQ 160(SI), R10 + ADCQ 168(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + CMPQ BX, $0xc0 + JB openSSLTail192Store + ADDQ 176(SI), R10 + ADCQ 184(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openSSLTail192Store: + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 112(BP), X9 + PADDL 96(BP), X10 + PADDL 80(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X2 + PXOR X13, X5 + PXOR X14, X8 + PXOR X15, X11 + MOVOU X2, (DI) + MOVOU X5, 16(DI) + MOVOU X8, 32(DI) + MOVOU X11, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + LEAQ 128(DI), DI + JMP openSSETail64DecLoop + +openSSETail256: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + XORQ R9, R9 + +openSSETail256Loop: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + ADDQ $0x10, R9 + CMPQ R9, $0xa0 + JB openSSETail256Loop + MOVQ BX, CX + ANDQ $-16, CX + +openSSETail256HashLoop: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, R9 + CMPQ R9, CX + JB openSSETail256HashLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) + + // Load - xor - store + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + LEAQ 192(SI), SI + LEAQ 192(DI), DI + SUBQ $0xc0, BX + MOVO X12, X0 + MOVO X13, X3 + MOVO X14, X6 + MOVO 64(BP), X9 + JMP openSSETail64DecLoop + +chacha20Poly1305Open_AVX2: + VZEROUPPER + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 + + // Special optimization, for very short buffers + CMPQ BX, $0xc0 + JBE openAVX2192 + CMPQ BX, $0x00000140 + JBE openAVX2320 + + // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, 64(BP) + VMOVDQA Y4, 192(BP) + MOVQ $0x0000000a, R9 + +openAVX2PreparePolyKey: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ R9 + JNE openAVX2PreparePolyKey + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD 32(BP), Y14, Y14 + VPADDD 64(BP), Y12, Y12 + VPADDD 192(BP), Y4, Y4 + VPERM2I128 $0x02, Y0, Y14, Y3 + + // Clamp and store poly key + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for the first 64 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + + // Hash AD + first 64 bytes + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + XORQ CX, CX + +openAVX2InitialHash64: + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, CX + CMPQ CX, $0x40 + JNE openAVX2InitialHash64 + + // Decrypt the first 64 bytes + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VMOVDQU Y0, (DI) + VMOVDQU Y14, 32(DI) + LEAQ 64(SI), SI + LEAQ 64(DI), DI + SUBQ $0x40, BX + +openAVX2MainLoop: + CMPQ BX, $0x00000200 + JB openAVX2MainLoopDone + + // Load state, increment counter blocks, store the incremented counters + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX + +openAVX2InternalLoop: + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(SI)(CX*1), R10 + ADCQ 24(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(SI)(CX*1), R10 + ADCQ 40(SI)(CX*1), R11 + ADCQ $0x01, R12 + LEAQ 48(CX), CX + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + CMPQ CX, $0x000001e0 + JNE openAVX2InternalLoop + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + + // We only hashed 480 of the 512 bytes available - hash the remaining 32 here + ADDQ 480(SI), R10 + ADCQ 488(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + + // and here + ADDQ 496(SI), R10 + ADCQ 504(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + LEAQ 512(DI), DI + SUBQ $0x00000200, BX + JMP openAVX2MainLoop + +openAVX2MainLoopDone: + // Handle the various tail sizes efficiently + TESTQ BX, BX + JE openSSEFinalize + CMPQ BX, $0x80 + JBE openAVX2Tail128 + CMPQ BX, $0x00000100 + JBE openAVX2Tail256 + CMPQ BX, $0x00000180 + JBE openAVX2Tail384 + JMP openAVX2Tail512 + +openAVX2192: + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 + +openAVX2192InnerCipherLoop: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 + JNE openAVX2192InnerCipherLoop + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 + + // Clamp and store poly key + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for up to 192 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + +openAVX2ShortOpen: + // Hash + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + +openAVX2ShortOpenLoop: + CMPQ BX, $0x20 + JB openAVX2ShortTail32 + SUBQ $0x20, BX + + // Load for hashing + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Load for decryption + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI + + // Shift stream left + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 + JMP openAVX2ShortOpenLoop + +openAVX2ShortTail32: + CMPQ BX, $0x10 + VMOVDQA X0, X1 + JB openAVX2ShortDone + SUBQ $0x10, BX + + // Load for hashing + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Load for decryption + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 + +openAVX2ShortDone: + VZEROUPPER + JMP openSSETail16 + +openAVX2320: + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 + +openAVX2320InnerCipherLoop: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ R9 + JNE openAVX2320InnerCipherLoop + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 + + // Clamp and store poly key + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for up to 320 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 + JMP openAVX2ShortOpen + +openAVX2Tail128: + // Need to decrypt up to 128 bytes - prepare two blocks + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y1 + VMOVDQA Y1, Y4 + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX + TESTQ CX, CX + JE openAVX2Tail128LoopB + +openAVX2Tail128LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openAVX2Tail128LoopB: + ADDQ $0x10, R9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX + JB openAVX2Tail128LoopA + CMPQ R9, $0xa0 + JNE openAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y13, Y13 + VPADDD Y4, Y1, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + +openAVX2TailLoop: + CMPQ BX, $0x20 + JB openAVX2Tail + SUBQ $0x20, BX + + // Load for decryption + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + JMP openAVX2TailLoop + +openAVX2Tail: + CMPQ BX, $0x10 + VMOVDQA X0, X1 + JB openAVX2TailDone + SUBQ $0x10, BX + + // Load for decryption + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 + +openAVX2TailDone: + VZEROUPPER + JMP openSSETail16 + +openAVX2Tail256: + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 + + // Compute the number of iterations that will hash data + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x80, CX + SHRQ $0x04, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 + +openAVX2Tail256LoopA: + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX + +openAVX2Tail256LoopB: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX + JB openAVX2Tail256LoopA + CMPQ R9, $0x0a + JNE openAVX2Tail256LoopB + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX + +openAVX2Tail256Hash: + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail256HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail256Hash + +openAVX2Tail256HashEnd: + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y6 + VPERM2I128 $0x02, Y12, Y4, Y10 + VPERM2I128 $0x13, Y0, Y14, Y8 + VPERM2I128 $0x13, Y12, Y4, Y2 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR (SI), Y6, Y6 + VPXOR 32(SI), Y10, Y10 + VPXOR 64(SI), Y8, Y8 + VPXOR 96(SI), Y2, Y2 + VMOVDQU Y6, (DI) + VMOVDQU Y10, 32(DI) + VMOVDQU Y8, 64(DI) + VMOVDQU Y2, 96(DI) + LEAQ 128(SI), SI + LEAQ 128(DI), DI + SUBQ $0x80, BX + JMP openAVX2TailLoop + +openAVX2Tail384: + // Need to decrypt up to 384 bytes - prepare six blocks + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + + // Compute the number of iterations that will hash two blocks of data + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x00000100, CX + SHRQ $0x04, CX + ADDQ $0x06, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 + +openAVX2Tail384LoopB: + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX + +openAVX2Tail384LoopA: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + CMPQ R9, CX + JB openAVX2Tail384LoopB + CMPQ R9, $0x0a + JNE openAVX2Tail384LoopA + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX + +openAVX2Tail384Hash: + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail384HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail384Hash + +openAVX2Tail384HashEnd: + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX + JMP openAVX2TailLoop + +openAVX2Tail512: + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX + MOVQ SI, R9 + +openAVX2Tail512LoopB: + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + +openAVX2Tail512LoopA: + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(R9), R10 + ADCQ 24(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(R9), R9 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + INCQ CX + CMPQ CX, $0x04 + JLT openAVX2Tail512LoopB + CMPQ CX, $0x0a + JNE openAVX2Tail512LoopA + MOVQ BX, CX + SUBQ $0x00000180, CX + ANDQ $-16, CX + +openAVX2Tail512HashLoop: + TESTQ CX, CX + JE openAVX2Tail512HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + SUBQ $0x10, CX + JMP openAVX2Tail512HashLoop + +openAVX2Tail512HashEnd: + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + LEAQ 384(SI), SI + LEAQ 384(DI), DI + SUBQ $0x00000180, BX + JMP openAVX2TailLoop + +DATA ·chacha20Constants<>+0(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+4(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+8(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+12(SB)/4, $0x6b206574 +DATA ·chacha20Constants<>+16(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+20(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+24(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+28(SB)/4, $0x6b206574 +GLOBL ·chacha20Constants<>(SB), RODATA|NOPTR, $32 + +DATA ·polyClampMask<>+0(SB)/8, $0x0ffffffc0fffffff +DATA ·polyClampMask<>+8(SB)/8, $0x0ffffffc0ffffffc +DATA ·polyClampMask<>+16(SB)/8, $0xffffffffffffffff +DATA ·polyClampMask<>+24(SB)/8, $0xffffffffffffffff +GLOBL ·polyClampMask<>(SB), RODATA|NOPTR, $32 + +DATA ·sseIncMask<>+0(SB)/8, $0x0000000000000001 +DATA ·sseIncMask<>+8(SB)/8, $0x0000000000000000 +GLOBL ·sseIncMask<>(SB), RODATA|NOPTR, $16 + +DATA ·andMask<>+0(SB)/8, $0x00000000000000ff +DATA ·andMask<>+8(SB)/8, $0x0000000000000000 +DATA ·andMask<>+16(SB)/8, $0x000000000000ffff +DATA ·andMask<>+24(SB)/8, $0x0000000000000000 +DATA ·andMask<>+32(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+40(SB)/8, $0x0000000000000000 +DATA ·andMask<>+48(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+56(SB)/8, $0x0000000000000000 +DATA ·andMask<>+64(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+72(SB)/8, $0x0000000000000000 +DATA ·andMask<>+80(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+88(SB)/8, $0x0000000000000000 +DATA ·andMask<>+96(SB)/8, $0x00ffffffffffffff +DATA ·andMask<>+104(SB)/8, $0x0000000000000000 +DATA ·andMask<>+112(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+120(SB)/8, $0x0000000000000000 +DATA ·andMask<>+128(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+136(SB)/8, $0x00000000000000ff +DATA ·andMask<>+144(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+152(SB)/8, $0x000000000000ffff +DATA ·andMask<>+160(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+168(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+176(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+184(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+192(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+200(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+208(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+216(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+224(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+232(SB)/8, $0x00ffffffffffffff +GLOBL ·andMask<>(SB), RODATA|NOPTR, $240 + +DATA ·avx2InitMask<>+0(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+16(SB)/8, $0x0000000000000001 +DATA ·avx2InitMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2InitMask<>(SB), RODATA|NOPTR, $32 + +DATA ·rol16<>+0(SB)/8, $0x0504070601000302 +DATA ·rol16<>+8(SB)/8, $0x0d0c0f0e09080b0a +DATA ·rol16<>+16(SB)/8, $0x0504070601000302 +DATA ·rol16<>+24(SB)/8, $0x0d0c0f0e09080b0a +GLOBL ·rol16<>(SB), RODATA|NOPTR, $32 + +DATA ·rol8<>+0(SB)/8, $0x0605040702010003 +DATA ·rol8<>+8(SB)/8, $0x0e0d0c0f0a09080b +DATA ·rol8<>+16(SB)/8, $0x0605040702010003 +DATA ·rol8<>+24(SB)/8, $0x0e0d0c0f0a09080b +GLOBL ·rol8<>(SB), RODATA|NOPTR, $32 + +DATA ·avx2IncMask<>+0(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2IncMask<>+16(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2IncMask<>(SB), RODATA|NOPTR, $32 + +// func chacha20Poly1305Seal(dst []byte, key []uint32, src []byte, ad []byte) +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Seal(SB), $288-96 + MOVQ SP, BP + ADDQ $0x20, BP + ANDQ $-32, BP + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX + CMPB ·useAVX2+0(SB), $0x01 + JE chacha20Poly1305Seal_AVX2 + + // Special optimization, for very short buffers + CMPQ BX, $0x80 + JBE sealSSE128 + + // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + + // Store state on stack for future use + MOVO X3, 32(BP) + MOVO X6, 48(BP) + + // Load state, increment counter blocks + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + MOVQ $0x0000000a, R9 + +sealSSEIntroLoop: + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JNE sealSSEIntroLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + + // Clamp and store the key + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) + + // Hash AAD + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 64(DI) + MOVOU X5, 80(DI) + MOVOU X8, 96(DI) + MOVOU X11, 112(DI) + MOVQ $0x00000080, CX + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 + JBE sealSSE128SealHash + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 128(DI) + MOVOU X13, 144(DI) + MOVOU X14, 160(DI) + MOVOU X15, 176(DI) + ADDQ $0x40, CX + SUBQ $0x40, BX + LEAQ 64(SI), SI + MOVQ $0x00000002, CX + MOVQ $0x00000008, R9 + CMPQ BX, $0x40 + JBE sealSSETail64 + CMPQ BX, $0x80 + JBE sealSSETail128 + CMPQ BX, $0xc0 + JBE sealSSETail192 + +sealSSEMainLoop: + // Load state, increment counter blocks + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + +sealSSEInnerLoop: + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(DI), DI + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JGE sealSSEInnerLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSEInnerLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) + + // Load - xor - store + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVO 64(BP), X15 + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + ADDQ $0xc0, SI + MOVQ $0x000000c0, CX + SUBQ $0xc0, BX + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 + JBE sealSSE128SealHash + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 192(DI) + MOVOU X13, 208(DI) + MOVOU X14, 224(DI) + MOVOU X15, 240(DI) + LEAQ 64(SI), SI + SUBQ $0x40, BX + MOVQ $0x00000006, CX + MOVQ $0x00000004, R9 + CMPQ BX, $0xc0 + JG sealSSEMainLoop + MOVQ BX, CX + TESTQ BX, BX + JE sealSSE128SealHash + MOVQ $0x00000006, CX + CMPQ BX, $0x40 + JBE sealSSETail64 + CMPQ BX, $0x80 + JBE sealSSETail128 + JMP sealSSETail192 + +sealSSETail64: + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) + +sealSSETail64LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealSSETail64LoopB: + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSETail64LoopA + DECQ R9 + JGE sealSSETail64LoopB + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X4 + PADDL 48(BP), X7 + PADDL 80(BP), X10 + JMP sealSSE128Seal + +sealSSETail128: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + +sealSSETail128LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealSSETail128LoopB: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + DECQ CX + JG sealSSETail128LoopA + DECQ R9 + JGE sealSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVQ $0x00000040, CX + LEAQ 64(SI), SI + SUBQ $0x40, BX + JMP sealSSE128SealHash + +sealSSETail192: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 112(BP) + +sealSSETail192LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealSSETail192LoopB: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ CX + JG sealSSETail192LoopA + DECQ R9 + JGE sealSSETail192LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + PADDL 112(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + JMP sealSSE128SealHash + +sealSSE128: + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 + +sealSSE128InnerCipherLoop: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE sealSSE128InnerCipherLoop + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) + + // Hash + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + XORQ CX, CX + +sealSSE128SealHash: + CMPQ CX, $0x10 + JB sealSSE128Seal + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + ADDQ $0x10, DI + JMP sealSSE128SealHash + +sealSSE128Seal: + CMPQ BX, $0x10 + JB sealSSETail + SUBQ $0x10, BX + + // Load for decryption + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + + // Extract for hashing + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Shift the stream "left" + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 + JMP sealSSE128Seal + +sealSSETail: + TESTQ BX, BX + JE sealSSEFinalize + + // We can only load the PT one byte at a time to avoid read after end of buffer + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVQ BX, CX + LEAQ -1(SI)(BX*1), SI + XORQ R15, R15 + XORQ R8, R8 + XORQ AX, AX + +sealSSETailLoadLoop: + SHLQ $0x08, R15, R8 + SHLQ $0x08, R15 + MOVB (SI), AX + XORQ AX, R15 + LEAQ -1(SI), SI + DECQ CX + JNE sealSSETailLoadLoop + MOVQ R15, 64(BP) + MOVQ R8, 72(BP) + PXOR 64(BP), X1 + MOVOU X1, (DI) + MOVOU -16(R13)(R9*1), X12 + PAND X12, X1 + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ BX, DI + +sealSSEFinalize: + // Hash in the buffer lengths + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Final reduce + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 + + // Add in the "s" part of the key + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 + + // Finally store the tag at the end of the message + MOVQ R10, (DI) + MOVQ R11, 8(DI) + RET + +chacha20Poly1305Seal_AVX2: + VZEROUPPER + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 + + // Special optimizations, for very short buffers + CMPQ BX, $0x000000c0 + JBE seal192AVX2 + CMPQ BX, $0x00000140 + JBE seal320AVX2 + + // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA Y12, 64(BP) + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, 96(BP) + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y1, 128(BP) + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + MOVQ $0x0000000a, R9 + +sealAVX2IntroLoop: + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y3, Y3, Y3 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ R9 + JNE sealAVX2IntroLoop + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPERM2I128 $0x02, Y0, Y14, Y4 + VPERM2I128 $0x13, Y0, Y14, Y0 + + // Clamp and store poly key + VPAND ·polyClampMask<>+0(SB), Y4, Y4 + VMOVDQA Y4, (BP) + + // Hash AD + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + + // Can store at least 320 bytes + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y12, Y12 + VMOVDQU Y0, (DI) + VMOVDQU Y12, 32(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 64(SI), Y0, Y0 + VPXOR 96(SI), Y14, Y14 + VPXOR 128(SI), Y12, Y12 + VPXOR 160(SI), Y4, Y4 + VMOVDQU Y0, 64(DI) + VMOVDQU Y14, 96(DI) + VMOVDQU Y12, 128(DI) + VMOVDQU Y4, 160(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 192(SI), Y0, Y0 + VPXOR 224(SI), Y14, Y14 + VPXOR 256(SI), Y12, Y12 + VPXOR 288(SI), Y4, Y4 + VMOVDQU Y0, 192(DI) + VMOVDQU Y14, 224(DI) + VMOVDQU Y12, 256(DI) + VMOVDQU Y4, 288(DI) + MOVQ $0x00000140, CX + SUBQ $0x00000140, BX + LEAQ 320(SI), SI + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, Y15, Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, Y15, Y3, Y4 + CMPQ BX, $0x80 + JBE sealAVX2SealHash + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VPXOR 64(SI), Y12, Y12 + VPXOR 96(SI), Y4, Y4 + VMOVDQU Y0, 320(DI) + VMOVDQU Y14, 352(DI) + VMOVDQU Y12, 384(DI) + VMOVDQU Y4, 416(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVQ $0x00000008, CX + MOVQ $0x00000002, R9 + CMPQ BX, $0x80 + JBE sealAVX2Tail128 + CMPQ BX, $0x00000100 + JBE sealAVX2Tail256 + CMPQ BX, $0x00000180 + JBE sealAVX2Tail384 + CMPQ BX, $0x00000200 + JBE sealAVX2Tail512 + + // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y3, Y3, Y3 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + SUBQ $0x10, DI + MOVQ $0x00000009, CX + JMP sealAVX2InternalLoopStart + +sealAVX2MainLoop: + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + MOVQ $0x0000000a, CX + +sealAVX2InternalLoop: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +sealAVX2InternalLoopStart: + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(DI), R10 + ADCQ 40(DI), R11 + ADCQ $0x01, R12 + LEAQ 48(DI), DI + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ CX + JNE sealAVX2InternalLoop + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + + // We only hashed 480 of the 512 bytes available - hash the remaining 32 here + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + + // and here + ADDQ -16(DI), R10 + ADCQ -8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + SUBQ $0x00000200, BX + CMPQ BX, $0x00000200 + JG sealAVX2MainLoop + + // Tail can only hash 480 bytes + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + MOVQ $0x0000000a, CX + MOVQ $0x00000000, R9 + CMPQ BX, $0x80 + JBE sealAVX2Tail128 + CMPQ BX, $0x00000100 + JBE sealAVX2Tail256 + CMPQ BX, $0x00000180 + JBE sealAVX2Tail384 + JMP sealAVX2Tail512 + +seal192AVX2: + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 + +sealAVX2192InnerCipherLoop: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 + JNE sealAVX2192InnerCipherLoop + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 + + // Clamp and store poly key + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for up to 192 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + +sealAVX2ShortSeal: + // Hash aad + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + XORQ CX, CX + +sealAVX2SealHash: + // itr1 holds the number of bytes encrypted but not yet hashed + CMPQ CX, $0x10 + JB sealAVX2ShortSealLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + ADDQ $0x10, DI + JMP sealAVX2SealHash + +sealAVX2ShortSealLoop: + CMPQ BX, $0x20 + JB sealAVX2ShortTail32 + SUBQ $0x20, BX + + // Load for encryption + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + + // Now can hash + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + + // Shift stream left + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 + JMP sealAVX2ShortSealLoop + +sealAVX2ShortTail32: + CMPQ BX, $0x10 + VMOVDQA X0, X1 + JB sealAVX2ShortDone + SUBQ $0x10, BX + + // Load for encryption + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + + // Hash + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 + +sealAVX2ShortDone: + VZEROUPPER + JMP sealSSETail + +seal320AVX2: + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 + +sealAVX2320InnerCipherLoop: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ R9 + JNE sealAVX2320InnerCipherLoop + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 + + // Clamp and store poly key + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for up to 320 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 + JMP sealAVX2ShortSeal + +sealAVX2Tail128: + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA 32(BP), Y14 + VMOVDQA 64(BP), Y12 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VMOVDQA Y4, Y1 + +sealAVX2Tail128LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealAVX2Tail128LoopB: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ CX + JG sealAVX2Tail128LoopA + DECQ R9 + JGE sealAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y5 + VPADDD 32(BP), Y14, Y9 + VPADDD 64(BP), Y12, Y13 + VPADDD Y1, Y4, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + JMP sealAVX2ShortSealLoop + +sealAVX2Tail256: + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 + +sealAVX2Tail256LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealAVX2Tail256LoopB: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ CX + JG sealAVX2Tail256LoopA + DECQ R9 + JGE sealAVX2Tail256LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + JMP sealAVX2SealHash + +sealAVX2Tail384: + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 + VMOVDQA Y2, Y15 + +sealAVX2Tail384LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealAVX2Tail384LoopB: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ CX + JG sealAVX2Tail384LoopA + DECQ R9 + JGE sealAVX2Tail384LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPADDD Y15, Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + MOVQ $0x00000100, CX + LEAQ 256(SI), SI + SUBQ $0x00000100, BX + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + JMP sealAVX2SealHash + +sealAVX2Tail512: + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + +sealAVX2Tail512LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + +sealAVX2Tail512LoopB: + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ CX + JG sealAVX2Tail512LoopA + DECQ R9 + JGE sealAVX2Tail512LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPXOR (SI), Y15, Y15 + VMOVDQU Y15, (DI) + VPERM2I128 $0x02, Y12, Y4, Y15 + VPXOR 32(SI), Y15, Y15 + VMOVDQU Y15, 32(DI) + VPERM2I128 $0x13, Y0, Y14, Y15 + VPXOR 64(SI), Y15, Y15 + VMOVDQU Y15, 64(DI) + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + MOVQ $0x00000180, CX + LEAQ 384(SI), SI + SUBQ $0x00000180, BX + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + JMP sealAVX2SealHash diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go new file mode 100644 index 0000000..2ecc840 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go @@ -0,0 +1,87 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package chacha20poly1305 + +import ( + "encoding/binary" + + "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/alias" + "golang.org/x/crypto/internal/poly1305" +) + +func writeWithPadding(p *poly1305.MAC, b []byte) { + p.Write(b) + if rem := len(b) % 16; rem != 0 { + var buf [16]byte + padLen := 16 - rem + p.Write(buf[:padLen]) + } +} + +func writeUint64(p *poly1305.MAC, n int) { + var buf [8]byte + binary.LittleEndian.PutUint64(buf[:], uint64(n)) + p.Write(buf[:]) +} + +func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { + ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) + ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] + if alias.InexactOverlap(out, plaintext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") + } + + var polyKey [32]byte + s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) + s.XORKeyStream(polyKey[:], polyKey[:]) + s.SetCounter(1) // set the counter to 1, skipping 32 bytes + s.XORKeyStream(ciphertext, plaintext) + + p := poly1305.New(&polyKey) + writeWithPadding(p, additionalData) + writeWithPadding(p, ciphertext) + writeUint64(p, len(additionalData)) + writeUint64(p, len(plaintext)) + p.Sum(tag[:0]) + + return ret +} + +func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + tag := ciphertext[len(ciphertext)-16:] + ciphertext = ciphertext[:len(ciphertext)-16] + + var polyKey [32]byte + s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) + s.XORKeyStream(polyKey[:], polyKey[:]) + s.SetCounter(1) // set the counter to 1, skipping 32 bytes + + p := poly1305.New(&polyKey) + writeWithPadding(p, additionalData) + writeWithPadding(p, ciphertext) + writeUint64(p, len(additionalData)) + writeUint64(p, len(ciphertext)) + + ret, out := sliceForAppend(dst, len(ciphertext)) + if alias.InexactOverlap(out, ciphertext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") + } + if !p.Verify(tag) { + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + s.XORKeyStream(out, ciphertext) + return ret, nil +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go new file mode 100644 index 0000000..34e6ab1 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go @@ -0,0 +1,15 @@ +// 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 !amd64 || !gc || purego + +package chacha20poly1305 + +func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { + return c.sealGeneric(dst, nonce, plaintext, additionalData) +} + +func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + return c.openGeneric(dst, nonce, ciphertext, additionalData) +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go b/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go new file mode 100644 index 0000000..9b9d564 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go @@ -0,0 +1,9 @@ +// 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.26 + +package chacha20poly1305 + +func fips140Enforced() bool { return false } diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go b/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go new file mode 100644 index 0000000..f71089c --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go @@ -0,0 +1,11 @@ +// 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.26 + +package chacha20poly1305 + +import "crypto/fips140" + +func fips140Enforced() bool { return fips140.Enforced() } diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go new file mode 100644 index 0000000..b4299b7 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go @@ -0,0 +1,89 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package chacha20poly1305 + +import ( + "crypto/cipher" + "errors" + + "golang.org/x/crypto/chacha20" +) + +type xchacha20poly1305 struct { + key [KeySize]byte +} + +// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. +// +// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce, +// suitable to be generated randomly without risk of collisions. It should be +// preferred when nonce uniqueness cannot be trivially ensured, or whenever +// nonces are randomly generated. +func NewX(key []byte) (cipher.AEAD, error) { + if fips140Enforced() { + return nil, errors.New("chacha20poly1305: use of ChaCha20Poly1305 is not allowed in FIPS 140-only mode") + } + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(xchacha20poly1305) + copy(ret.key[:], key) + return ret, nil +} + +func (*xchacha20poly1305) NonceSize() int { + return NonceSizeX +} + +func (*xchacha20poly1305) Overhead() int { + return Overhead +} + +func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSizeX { + panic("chacha20poly1305: bad nonce length passed to Seal") + } + + // XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no + // size limit. However, since we reuse the ChaCha20-Poly1305 implementation, + // the second half of the counter is not available. This is unlikely to be + // an issue because the cipher.AEAD API requires the entire message to be in + // memory, and the counter overflows at 256 GB. + if uint64(len(plaintext)) > (1<<38)-64 { + panic("chacha20poly1305: plaintext too large") + } + + c := new(chacha20poly1305) + hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) + copy(c.key[:], hKey) + + // The first 4 bytes of the final nonce are unused counter space. + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + + return c.seal(dst, cNonce[:], plaintext, additionalData) +} + +func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSizeX { + panic("chacha20poly1305: bad nonce length passed to Open") + } + if len(ciphertext) < 16 { + return nil, errOpen + } + if uint64(len(ciphertext)) > (1<<38)-48 { + panic("chacha20poly1305: ciphertext too large") + } + + c := new(chacha20poly1305) + hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) + copy(c.key[:], hKey) + + // The first 4 bytes of the final nonce are unused counter space. + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + + return c.open(dst, cNonce[:], ciphertext, additionalData) +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go new file mode 100644 index 0000000..d25979d --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go @@ -0,0 +1,825 @@ +// 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. + +package cryptobyte + +import ( + encoding_asn1 "encoding/asn1" + "fmt" + "math/big" + "reflect" + "time" + + "golang.org/x/crypto/cryptobyte/asn1" +) + +// This file contains ASN.1-related methods for String and Builder. + +// Builder + +// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1Int64(v int64) { + b.addASN1Signed(asn1.INTEGER, v) +} + +// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the +// given tag. +func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { + b.addASN1Signed(tag, v) +} + +// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. +func (b *Builder) AddASN1Enum(v int64) { + b.addASN1Signed(asn1.ENUM, v) +} + +func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) { + b.AddASN1(tag, func(c *Builder) { + length := 1 + for i := v; i >= 0x80 || i < -0x80; i >>= 8 { + length++ + } + + for ; length > 0; length-- { + i := v >> uint((length-1)*8) & 0xff + c.AddUint8(uint8(i)) + } + }) +} + +// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1Uint64(v uint64) { + b.AddASN1(asn1.INTEGER, func(c *Builder) { + length := 1 + for i := v; i >= 0x80; i >>= 8 { + length++ + } + + for ; length > 0; length-- { + i := v >> uint((length-1)*8) & 0xff + c.AddUint8(uint8(i)) + } + }) +} + +// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1BigInt(n *big.Int) { + if b.err != nil { + return + } + + b.AddASN1(asn1.INTEGER, func(c *Builder) { + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement form. So we + // invert and subtract 1. If the most-significant-bit isn't set then + // we'll need to pad the beginning with 0xff in order to keep the number + // negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + c.add(0xff) + } + c.add(bytes...) + } else if n.Sign() == 0 { + c.add(0) + } else { + bytes := n.Bytes() + if bytes[0]&0x80 != 0 { + c.add(0) + } + c.add(bytes...) + } + }) +} + +// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING. +func (b *Builder) AddASN1OctetString(bytes []byte) { + b.AddASN1(asn1.OCTET_STRING, func(c *Builder) { + c.AddBytes(bytes) + }) +} + +const generalizedTimeFormatStr = "20060102150405Z0700" + +// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME. +func (b *Builder) AddASN1GeneralizedTime(t time.Time) { + if t.Year() < 0 || t.Year() > 9999 { + b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t) + return + } + b.AddASN1(asn1.GeneralizedTime, func(c *Builder) { + c.AddBytes([]byte(t.Format(generalizedTimeFormatStr))) + }) +} + +// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. +func (b *Builder) AddASN1UTCTime(t time.Time) { + b.AddASN1(asn1.UTCTime, func(c *Builder) { + // As utilized by the X.509 profile, UTCTime can only + // represent the years 1950 through 2049. + if t.Year() < 1950 || t.Year() >= 2050 { + b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) + return + } + c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) + }) +} + +// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not +// support BIT STRINGs that are not a whole number of bytes. +func (b *Builder) AddASN1BitString(data []byte) { + b.AddASN1(asn1.BIT_STRING, func(b *Builder) { + b.AddUint8(0) + b.AddBytes(data) + }) +} + +func (b *Builder) addBase128Int(n int64) { + var length int + if n == 0 { + length = 1 + } else { + for i := n; i > 0; i >>= 7 { + length++ + } + } + + for i := length - 1; i >= 0; i-- { + o := byte(n >> uint(i*7)) + o &= 0x7f + if i != 0 { + o |= 0x80 + } + + b.add(o) + } +} + +func isValidOID(oid encoding_asn1.ObjectIdentifier) bool { + if len(oid) < 2 { + return false + } + + if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) { + return false + } + + for _, v := range oid { + if v < 0 { + return false + } + } + + return true +} + +func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) { + b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) { + if !isValidOID(oid) { + b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid) + return + } + + b.addBase128Int(int64(oid[0])*40 + int64(oid[1])) + for _, v := range oid[2:] { + b.addBase128Int(int64(v)) + } + }) +} + +func (b *Builder) AddASN1Boolean(v bool) { + b.AddASN1(asn1.BOOLEAN, func(b *Builder) { + if v { + b.AddUint8(0xff) + } else { + b.AddUint8(0) + } + }) +} + +func (b *Builder) AddASN1NULL() { + b.add(uint8(asn1.NULL), 0) +} + +// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if +// successful or records an error if one occurred. +func (b *Builder) MarshalASN1(v interface{}) { + // NOTE(martinkr): This is somewhat of a hack to allow propagation of + // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a + // value embedded into a struct, its tag information is lost. + if b.err != nil { + return + } + bytes, err := encoding_asn1.Marshal(v) + if err != nil { + b.err = err + return + } + b.AddBytes(bytes) +} + +// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. +// Tags greater than 30 are not supported and result in an error (i.e. +// low-tag-number form only). The child builder passed to the +// BuilderContinuation can be used to build the content of the ASN.1 object. +func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { + if b.err != nil { + return + } + // Identifiers with the low five bits set indicate high-tag-number format + // (two or more octets), which we don't support. + if tag&0x1f == 0x1f { + b.err = fmt.Errorf("cryptobyte: high-tag number identifier octets not supported: 0x%x", tag) + return + } + b.AddUint8(uint8(tag)) + b.addLengthPrefixed(1, true, f) +} + +// String + +// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean +// representation into out and advances. It reports whether the read +// was successful. +func (s *String) ReadASN1Boolean(out *bool) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { + return false + } + + switch bytes[0] { + case 0: + *out = false + case 0xff: + *out = true + default: + return false + } + + return true +} + +// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does +// not point to an integer, to a big.Int, or to a []byte it panics. Only +// positive and zero values can be decoded into []byte, and they are returned as +// big-endian binary values that share memory with s. Positive values will have +// no leading zeroes, and zero will be returned as a single zero byte. +// ReadASN1Integer reports whether the read was successful. +func (s *String) ReadASN1Integer(out interface{}) bool { + switch out := out.(type) { + case *int, *int8, *int16, *int32, *int64: + var i int64 + if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { + return false + } + reflect.ValueOf(out).Elem().SetInt(i) + return true + case *uint, *uint8, *uint16, *uint32, *uint64: + var u uint64 + if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { + return false + } + reflect.ValueOf(out).Elem().SetUint(u) + return true + case *big.Int: + return s.readASN1BigInt(out) + case *[]byte: + return s.readASN1Bytes(out) + default: + panic("out does not point to an integer type") + } +} + +func checkASN1Integer(bytes []byte) bool { + if len(bytes) == 0 { + // An INTEGER is encoded with at least one octet. + return false + } + if len(bytes) == 1 { + return true + } + if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 { + // Value is not minimally encoded. + return false + } + return true +} + +var bigOne = big.NewInt(1) + +func (s *String) readASN1BigInt(out *big.Int) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { + return false + } + if bytes[0]&0x80 == 0x80 { + // Negative number. + neg := make([]byte, len(bytes)) + for i, b := range bytes { + neg[i] = ^b + } + out.SetBytes(neg) + out.Add(out, bigOne) + out.Neg(out) + } else { + out.SetBytes(bytes) + } + return true +} + +func (s *String) readASN1Bytes(out *[]byte) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { + return false + } + if bytes[0]&0x80 == 0x80 { + return false + } + for len(bytes) > 1 && bytes[0] == 0 { + bytes = bytes[1:] + } + *out = bytes + return true +} + +func (s *String) readASN1Int64(out *int64) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { + return false + } + return true +} + +func asn1Signed(out *int64, n []byte) bool { + length := len(n) + if length > 8 { + return false + } + for i := 0; i < length; i++ { + *out <<= 8 + *out |= int64(n[i]) + } + // Shift up and down in order to sign extend the result. + *out <<= 64 - uint8(length)*8 + *out >>= 64 - uint8(length)*8 + return true +} + +func (s *String) readASN1Uint64(out *uint64) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) { + return false + } + return true +} + +func asn1Unsigned(out *uint64, n []byte) bool { + length := len(n) + if length > 9 || length == 9 && n[0] != 0 { + // Too large for uint64. + return false + } + if n[0]&0x80 != 0 { + // Negative number. + return false + } + for i := 0; i < length; i++ { + *out <<= 8 + *out |= uint64(n[i]) + } + return true +} + +// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out +// and advances. It reports whether the read was successful and resulted in a +// value that can be represented in an int64. +func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { + var bytes String + return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) +} + +// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports +// whether the read was successful. +func (s *String) ReadASN1Enum(out *int) bool { + var bytes String + var i int64 + if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) { + return false + } + if int64(int(i)) != i { + return false + } + *out = int(i) + return true +} + +func (s *String) readBase128Int(out *int) bool { + ret := 0 + for i := 0; len(*s) > 0; i++ { + if i == 5 { + return false + } + // Avoid overflowing int on a 32-bit platform. + // We don't want different behavior based on the architecture. + if ret >= 1<<(31-7) { + return false + } + ret <<= 7 + b := s.read(1)[0] + + // ITU-T X.690, section 8.19.2: + // The subidentifier shall be encoded in the fewest possible octets, + // that is, the leading octet of the subidentifier shall not have the value 0x80. + if i == 0 && b == 0x80 { + return false + } + + ret |= int(b & 0x7f) + if b&0x80 == 0 { + *out = ret + return true + } + } + return false // truncated +} + +// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and +// advances. It reports whether the read was successful. +func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { + return false + } + + // In the worst case, we get two elements from the first byte (which is + // encoded differently) and then every varint is a single byte long. + components := make([]int, len(bytes)+1) + + // The first varint is 40*value1 + value2: + // According to this packing, value1 can take the values 0, 1 and 2 only. + // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, + // then there are no restrictions on value2. + var v int + if !bytes.readBase128Int(&v) { + return false + } + if v < 80 { + components[0] = v / 40 + components[1] = v % 40 + } else { + components[0] = 2 + components[1] = v - 80 + } + + i := 2 + for ; len(bytes) > 0; i++ { + if !bytes.readBase128Int(&v) { + return false + } + components[i] = v + } + *out = components[:i] + return true +} + +// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and +// advances. It reports whether the read was successful. +func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { + return false + } + t := string(bytes) + res, err := time.Parse(generalizedTimeFormatStr, t) + if err != nil { + return false + } + if serialized := res.Format(generalizedTimeFormatStr); serialized != t { + return false + } + *out = res + return true +} + +const defaultUTCTimeFormatStr = "060102150405Z0700" + +// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. +// It reports whether the read was successful. +func (s *String) ReadASN1UTCTime(out *time.Time) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.UTCTime) { + return false + } + t := string(bytes) + + formatStr := defaultUTCTimeFormatStr + var err error + res, err := time.Parse(formatStr, t) + if err != nil { + // Fallback to minute precision if we can't parse second + // precision. If we are following X.509 or X.690 we shouldn't + // support this, but we do. + formatStr = "0601021504Z0700" + res, err = time.Parse(formatStr, t) + } + if err != nil { + return false + } + + if serialized := res.Format(formatStr); serialized != t { + return false + } + + if res.Year() >= 2050 { + // UTCTime interprets the low order digits 50-99 as 1950-99. + // This only applies to its use in the X.509 profile. + // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + res = res.AddDate(-100, 0, 0) + } + *out = res + return true +} + +// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. +// It reports whether the read was successful. +func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || + len(bytes)*8/8 != len(bytes) { + return false + } + + paddingBits := bytes[0] + bytes = bytes[1:] + if paddingBits > 7 || + len(bytes) == 0 && paddingBits != 0 || + len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) { + return false + } + + lenBytes := String((*s)[2 : 2+lenLen]) + if !lenBytes.readUnsigned(&len32, int(lenLen)) { + return false + } + + // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length + // with the minimum number of octets. + if len32 < 128 { + // Length should have used short-form encoding. + return false + } + if len32>>((lenLen-1)*8) == 0 { + // Leading octet is 0. Length should have been at least one byte shorter. + return false + } + + headerLen = 2 + uint32(lenLen) + if headerLen+len32 < len32 { + // Overflow. + return false + } + length = headerLen + len32 + } + + if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { + return false + } + if skipHeader && !out.Skip(int(headerLen)) { + panic("cryptobyte: internal error") + } + + return true +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go new file mode 100644 index 0000000..90ef6a2 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go @@ -0,0 +1,46 @@ +// 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. + +// Package asn1 contains supporting types for parsing and building ASN.1 +// messages with the cryptobyte package. +package asn1 + +// Tag represents an ASN.1 identifier octet, consisting of a tag number +// (indicating a type) and class (such as context-specific or constructed). +// +// Methods in the cryptobyte package only support the low-tag-number form, i.e. +// a single identifier octet with bits 7-8 encoding the class and bits 1-6 +// encoding the tag number. +type Tag uint8 + +const ( + classConstructed = 0x20 + classContextSpecific = 0x80 +) + +// Constructed returns t with the constructed class bit set. +func (t Tag) Constructed() Tag { return t | classConstructed } + +// ContextSpecific returns t with the context-specific class bit set. +func (t Tag) ContextSpecific() Tag { return t | classContextSpecific } + +// The following is a list of standard tag and class combinations. +const ( + BOOLEAN = Tag(1) + INTEGER = Tag(2) + BIT_STRING = Tag(3) + OCTET_STRING = Tag(4) + NULL = Tag(5) + OBJECT_IDENTIFIER = Tag(6) + ENUM = Tag(10) + UTF8String = Tag(12) + SEQUENCE = Tag(16 | classConstructed) + SET = Tag(17 | classConstructed) + PrintableString = Tag(19) + T61String = Tag(20) + IA5String = Tag(22) + UTCTime = Tag(23) + GeneralizedTime = Tag(24) + GeneralString = Tag(27) +) diff --git a/vendor/golang.org/x/crypto/cryptobyte/builder.go b/vendor/golang.org/x/crypto/cryptobyte/builder.go new file mode 100644 index 0000000..cf254f5 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/builder.go @@ -0,0 +1,350 @@ +// 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. + +package cryptobyte + +import ( + "errors" + "fmt" +) + +// A Builder builds byte strings from fixed-length and length-prefixed values. +// Builders either allocate space as needed, or are ‘fixed’, which means that +// they write into a given buffer and produce an error if it's exhausted. +// +// The zero value is a usable Builder that allocates space as needed. +// +// Simple values are marshaled and appended to a Builder using methods on the +// Builder. Length-prefixed values are marshaled by providing a +// BuilderContinuation, which is a function that writes the inner contents of +// the value to a given Builder. See the documentation for BuilderContinuation +// for details. +type Builder struct { + err error + result []byte + fixedSize bool + child *Builder + offset int + pendingLenLen int + pendingIsASN1 bool + inContinuation *bool +} + +// NewBuilder creates a Builder that appends its output to the given buffer. +// Like append(), the slice will be reallocated if its capacity is exceeded. +// Use Bytes to get the final buffer. +func NewBuilder(buffer []byte) *Builder { + return &Builder{ + result: buffer, + } +} + +// NewFixedBuilder creates a Builder that appends its output into the given +// buffer. This builder does not reallocate the output buffer. Writes that +// would exceed the buffer's capacity are treated as an error. +func NewFixedBuilder(buffer []byte) *Builder { + return &Builder{ + result: buffer, + fixedSize: true, + } +} + +// SetError sets the value to be returned as the error from Bytes. Writes +// performed after calling SetError are ignored. +func (b *Builder) SetError(err error) { + b.err = err +} + +// Bytes returns the bytes written by the builder or an error if one has +// occurred during building. +func (b *Builder) Bytes() ([]byte, error) { + if b.err != nil { + return nil, b.err + } + return b.result[b.offset:], nil +} + +// BytesOrPanic returns the bytes written by the builder or panics if an error +// has occurred during building. +func (b *Builder) BytesOrPanic() []byte { + if b.err != nil { + panic(b.err) + } + return b.result[b.offset:] +} + +// AddUint8 appends an 8-bit value to the byte string. +func (b *Builder) AddUint8(v uint8) { + b.add(byte(v)) +} + +// AddUint16 appends a big-endian, 16-bit value to the byte string. +func (b *Builder) AddUint16(v uint16) { + b.add(byte(v>>8), byte(v)) +} + +// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest +// byte of the 32-bit input value is silently truncated. +func (b *Builder) AddUint24(v uint32) { + b.add(byte(v>>16), byte(v>>8), byte(v)) +} + +// AddUint32 appends a big-endian, 32-bit value to the byte string. +func (b *Builder) AddUint32(v uint32) { + b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +// AddUint48 appends a big-endian, 48-bit value to the byte string. +func (b *Builder) AddUint48(v uint64) { + b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +// AddUint64 appends a big-endian, 64-bit value to the byte string. +func (b *Builder) AddUint64(v uint64) { + b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +// AddBytes appends a sequence of bytes to the byte string. +func (b *Builder) AddBytes(v []byte) { + b.add(v...) +} + +// BuilderContinuation is a continuation-passing interface for building +// length-prefixed byte sequences. Builder methods for length-prefixed +// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation +// supplied to them. The child builder passed to the continuation can be used +// to build the content of the length-prefixed sequence. For example: +// +// parent := cryptobyte.NewBuilder() +// parent.AddUint8LengthPrefixed(func (child *Builder) { +// child.AddUint8(42) +// child.AddUint8LengthPrefixed(func (grandchild *Builder) { +// grandchild.AddUint8(5) +// }) +// }) +// +// It is an error to write more bytes to the child than allowed by the reserved +// length prefix. After the continuation returns, the child must be considered +// invalid, i.e. users must not store any copies or references of the child +// that outlive the continuation. +// +// If the continuation panics with a value of type BuildError then the inner +// error will be returned as the error from Bytes. If the child panics +// otherwise then Bytes will repanic with the same value. +type BuilderContinuation func(child *Builder) + +// BuildError wraps an error. If a BuilderContinuation panics with this value, +// the panic will be recovered and the inner error will be returned from +// Builder.Bytes. +type BuildError struct { + Err error +} + +// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence. +func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(1, false, f) +} + +// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence. +func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(2, false, f) +} + +// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence. +func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(3, false, f) +} + +// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence. +func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(4, false, f) +} + +func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) { + if !*b.inContinuation { + *b.inContinuation = true + + defer func() { + *b.inContinuation = false + + r := recover() + if r == nil { + return + } + + if buildError, ok := r.(BuildError); ok { + b.err = buildError.Err + } else { + panic(r) + } + }() + } + + f(arg) +} + +func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) { + // Subsequent writes can be ignored if the builder has encountered an error. + if b.err != nil { + return + } + + offset := len(b.result) + b.add(make([]byte, lenLen)...) + + if b.inContinuation == nil { + b.inContinuation = new(bool) + } + + b.child = &Builder{ + result: b.result, + fixedSize: b.fixedSize, + offset: offset, + pendingLenLen: lenLen, + pendingIsASN1: isASN1, + inContinuation: b.inContinuation, + } + + b.callContinuation(f, b.child) + b.flushChild() + if b.child != nil { + panic("cryptobyte: internal error") + } +} + +func (b *Builder) flushChild() { + if b.child == nil { + return + } + b.child.flushChild() + child := b.child + b.child = nil + + if child.err != nil { + b.err = child.err + return + } + + length := len(child.result) - child.pendingLenLen - child.offset + + if length < 0 { + panic("cryptobyte: internal error") // result unexpectedly shrunk + } + + if child.pendingIsASN1 { + // For ASN.1, we reserved a single byte for the length. If that turned out + // to be incorrect, we have to move the contents along in order to make + // space. + if child.pendingLenLen != 1 { + panic("cryptobyte: internal error") + } + var lenLen, lenByte uint8 + if int64(length) > 0xfffffffe { + b.err = errors.New("pending ASN.1 child too long") + return + } else if length > 0xffffff { + lenLen = 5 + lenByte = 0x80 | 4 + } else if length > 0xffff { + lenLen = 4 + lenByte = 0x80 | 3 + } else if length > 0xff { + lenLen = 3 + lenByte = 0x80 | 2 + } else if length > 0x7f { + lenLen = 2 + lenByte = 0x80 | 1 + } else { + lenLen = 1 + lenByte = uint8(length) + length = 0 + } + + // Insert the initial length byte, make space for successive length bytes, + // and adjust the offset. + child.result[child.offset] = lenByte + extraBytes := int(lenLen - 1) + if extraBytes != 0 { + child.add(make([]byte, extraBytes)...) + childStart := child.offset + child.pendingLenLen + copy(child.result[childStart+extraBytes:], child.result[childStart:]) + } + child.offset++ + child.pendingLenLen = extraBytes + } + + l := length + for i := child.pendingLenLen - 1; i >= 0; i-- { + child.result[child.offset+i] = uint8(l) + l >>= 8 + } + if l != 0 { + b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen) + return + } + + if b.fixedSize && &b.result[0] != &child.result[0] { + panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer") + } + + b.result = child.result +} + +func (b *Builder) add(bytes ...byte) { + if b.err != nil { + return + } + if b.child != nil { + panic("cryptobyte: attempted write while child is pending") + } + if len(b.result)+len(bytes) < len(bytes) { + b.err = errors.New("cryptobyte: length overflow") + } + if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) { + b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer") + return + } + b.result = append(b.result, bytes...) +} + +// Unwrite rolls back non-negative n bytes written directly to the Builder. +// An attempt by a child builder passed to a continuation to unwrite bytes +// from its parent will panic. +func (b *Builder) Unwrite(n int) { + if b.err != nil { + return + } + if b.child != nil { + panic("cryptobyte: attempted unwrite while child is pending") + } + length := len(b.result) - b.pendingLenLen - b.offset + if length < 0 { + panic("cryptobyte: internal error") + } + if n < 0 { + panic("cryptobyte: attempted to unwrite negative number of bytes") + } + if n > length { + panic("cryptobyte: attempted to unwrite more than was written") + } + b.result = b.result[:len(b.result)-n] +} + +// A MarshalingValue marshals itself into a Builder. +type MarshalingValue interface { + // Marshal is called by Builder.AddValue. It receives a pointer to a builder + // to marshal itself into. It may return an error that occurred during + // marshaling, such as unset or invalid values. + Marshal(b *Builder) error +} + +// AddValue calls Marshal on v, passing a pointer to the builder to append to. +// If Marshal returns an error, it is set on the Builder so that subsequent +// appends don't have an effect. +func (b *Builder) AddValue(v MarshalingValue) { + err := v.Marshal(b) + if err != nil { + b.err = err + } +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go new file mode 100644 index 0000000..4b0f809 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/string.go @@ -0,0 +1,183 @@ +// 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. + +// Package cryptobyte contains types that help with parsing and constructing +// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage +// contains useful ASN.1 constants.) +// +// The String type is for parsing. It wraps a []byte slice and provides helper +// functions for consuming structures, value by value. +// +// The Builder type is for constructing messages. It providers helper functions +// for appending values and also for appending length-prefixed submessages – +// without having to worry about calculating the length prefix ahead of time. +// +// See the documentation and examples for the Builder and String types to get +// started. +package cryptobyte + +// String represents a string of bytes. It provides methods for parsing +// fixed-length and length-prefixed values from it. +type String []byte + +// read advances a String by n bytes and returns them. If less than n bytes +// remain, it returns nil. +func (s *String) read(n int) []byte { + if len(*s) < n || n < 0 { + return nil + } + v := (*s)[:n] + *s = (*s)[n:] + return v +} + +// Skip advances the String by n byte and reports whether it was successful. +func (s *String) Skip(n int) bool { + return s.read(n) != nil +} + +// ReadUint8 decodes an 8-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint8(out *uint8) bool { + v := s.read(1) + if v == nil { + return false + } + *out = uint8(v[0]) + return true +} + +// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint16(out *uint16) bool { + v := s.read(2) + if v == nil { + return false + } + *out = uint16(v[0])<<8 | uint16(v[1]) + return true +} + +// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint24(out *uint32) bool { + v := s.read(3) + if v == nil { + return false + } + *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2]) + return true +} + +// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint32(out *uint32) bool { + v := s.read(4) + if v == nil { + return false + } + *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) + return true +} + +// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint48(out *uint64) bool { + v := s.read(6) + if v == nil { + return false + } + *out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5]) + return true +} + +// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint64(out *uint64) bool { + v := s.read(8) + if v == nil { + return false + } + *out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7]) + return true +} + +func (s *String) readUnsigned(out *uint32, length int) bool { + v := s.read(length) + if v == nil { + return false + } + var result uint32 + for i := 0; i < length; i++ { + result <<= 8 + result |= uint32(v[i]) + } + *out = result + return true +} + +func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { + lenBytes := s.read(lenLen) + if lenBytes == nil { + return false + } + var length uint32 + for _, b := range lenBytes { + length = length << 8 + length = length | uint32(b) + } + v := s.read(int(length)) + if v == nil { + return false + } + *outChild = v + return true +} + +// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value +// into out and advances over it. It reports whether the read was successful. +func (s *String) ReadUint8LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(1, out) +} + +// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit +// length-prefixed value into out and advances over it. It reports whether the +// read was successful. +func (s *String) ReadUint16LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(2, out) +} + +// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit +// length-prefixed value into out and advances over it. It reports whether +// the read was successful. +func (s *String) ReadUint24LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(3, out) +} + +// ReadBytes reads n bytes into out and advances over them. It reports +// whether the read was successful. +func (s *String) ReadBytes(out *[]byte, n int) bool { + v := s.read(n) + if v == nil { + return false + } + *out = v + return true +} + +// CopyBytes copies len(out) bytes into out and advances over them. It reports +// whether the copy operation was successful +func (s *String) CopyBytes(out []byte) bool { + n := len(out) + v := s.read(n) + if v == nil { + return false + } + return copy(out, v) == n +} + +// Empty reports whether the string does not contain any bytes. +func (s String) Empty() bool { + return len(s) == 0 +} diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go new file mode 100644 index 0000000..048faef --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -0,0 +1,93 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package curve25519 provides an implementation of the X25519 function, which +// performs scalar multiplication on the elliptic curve known as Curve25519 +// according to [RFC 7748]. +// +// The curve25519 package is a wrapper for the X25519 implementation in the +// crypto/ecdh package. It is [frozen] and is not accepting new features. +// +// [RFC 7748]: https://datatracker.ietf.org/doc/html/rfc7748 +// [frozen]: https://go.dev/wiki/Frozen +package curve25519 + +import "crypto/ecdh" + +// ScalarMult sets dst to the product scalar * point. +// +// Deprecated: when provided a low-order point, ScalarMult will set dst to all +// zeroes, irrespective of the scalar. Instead, use the X25519 function, which +// will return an error. +func ScalarMult(dst, scalar, point *[32]byte) { + if _, err := x25519(dst, scalar[:], point[:]); err != nil { + // The only error condition for x25519 when the inputs are 32 bytes long + // is if the output would have been the all-zero value. + for i := range dst { + dst[i] = 0 + } + } +} + +// ScalarBaseMult sets dst to the product scalar * base where base is the +// standard generator. +// +// It is recommended to use the X25519 function with Basepoint instead, as +// copying into fixed size arrays can lead to unexpected bugs. +func ScalarBaseMult(dst, scalar *[32]byte) { + curve := ecdh.X25519() + priv, err := curve.NewPrivateKey(scalar[:]) + if err != nil { + panic("curve25519: " + err.Error()) + } + copy(dst[:], priv.PublicKey().Bytes()) +} + +const ( + // ScalarSize is the size of the scalar input to X25519. + ScalarSize = 32 + // PointSize is the size of the point input to X25519. + PointSize = 32 +) + +// Basepoint is the canonical Curve25519 generator. +var Basepoint []byte + +var basePoint = [32]byte{9} + +func init() { Basepoint = basePoint[:] } + +// X25519 returns the result of the scalar multiplication (scalar * point), +// according to RFC 7748, Section 5. scalar, point and the return value are +// slices of 32 bytes. +// +// scalar can be generated at random, for example with crypto/rand. point should +// be either Basepoint or the output of another X25519 call. +// +// If point is Basepoint (but not if it's a different slice with the same +// contents) a precomputed implementation might be used for performance. +func X25519(scalar, point []byte) ([]byte, error) { + // Outline the body of function, to let the allocation be inlined in the + // caller, and possibly avoid escaping to the heap. + var dst [32]byte + return x25519(&dst, scalar, point) +} + +func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { + curve := ecdh.X25519() + pub, err := curve.NewPublicKey(point) + if err != nil { + return nil, err + } + priv, err := curve.NewPrivateKey(scalar) + if err != nil { + return nil, err + } + out, err := priv.ECDH(pub) + if err != nil { + return nil, err + } + copy(dst[:], out) + return dst[:], nil +} diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go deleted file mode 100644 index c7f8c7e..0000000 --- a/vendor/golang.org/x/crypto/ed25519/ed25519.go +++ /dev/null @@ -1,222 +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. - -// In Go 1.13, the ed25519 package was promoted to the standard library as -// crypto/ed25519, and this package became a wrapper for the standard library one. -// -// +build !go1.13 - -// Package ed25519 implements the Ed25519 signature algorithm. See -// https://ed25519.cr.yp.to/. -// -// These functions are also compatible with the “Ed25519” function defined in -// RFC 8032. However, unlike RFC 8032's formulation, this package's private key -// representation includes a public key suffix to make multiple signing -// operations with the same key more efficient. This package refers to the RFC -// 8032 private key as the “seed”. -package ed25519 - -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -import ( - "bytes" - "crypto" - cryptorand "crypto/rand" - "crypto/sha512" - "errors" - "io" - "strconv" - - "golang.org/x/crypto/ed25519/internal/edwards25519" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys as used in this package. - PublicKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = 64 - // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. - SeedSize = 32 -) - -// PublicKey is the type of Ed25519 public keys. -type PublicKey []byte - -// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -type PrivateKey []byte - -// Public returns the PublicKey corresponding to priv. -func (priv PrivateKey) Public() crypto.PublicKey { - publicKey := make([]byte, PublicKeySize) - copy(publicKey, priv[32:]) - return PublicKey(publicKey) -} - -// Seed returns the private key seed corresponding to priv. It is provided for -// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds -// in this package. -func (priv PrivateKey) Seed() []byte { - seed := make([]byte, SeedSize) - copy(seed, priv[:32]) - return seed -} - -// Sign signs the given message with priv. -// Ed25519 performs two passes over messages to be signed and therefore cannot -// handle pre-hashed messages. Thus opts.HashFunc() must return zero to -// indicate the message hasn't been hashed. This can be achieved by passing -// crypto.Hash(0) as the value for opts. -func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { - if opts.HashFunc() != crypto.Hash(0) { - return nil, errors.New("ed25519: cannot sign hashed message") - } - - return Sign(priv, message), nil -} - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - if rand == nil { - rand = cryptorand.Reader - } - - seed := make([]byte, SeedSize) - if _, err := io.ReadFull(rand, seed); err != nil { - return nil, nil, err - } - - privateKey := NewKeyFromSeed(seed) - publicKey := make([]byte, PublicKeySize) - copy(publicKey, privateKey[32:]) - - return publicKey, privateKey, nil -} - -// NewKeyFromSeed calculates a private key from a seed. It will panic if -// len(seed) is not SeedSize. This function is provided for interoperability -// with RFC 8032. RFC 8032's private keys correspond to seeds in this -// package. -func NewKeyFromSeed(seed []byte) PrivateKey { - if l := len(seed); l != SeedSize { - panic("ed25519: bad seed length: " + strconv.Itoa(l)) - } - - digest := sha512.Sum512(seed) - digest[0] &= 248 - digest[31] &= 127 - digest[31] |= 64 - - var A edwards25519.ExtendedGroupElement - var hBytes [32]byte - copy(hBytes[:], digest[:]) - edwards25519.GeScalarMultBase(&A, &hBytes) - var publicKeyBytes [32]byte - A.ToBytes(&publicKeyBytes) - - privateKey := make([]byte, PrivateKeySize) - copy(privateKey, seed) - copy(privateKey[32:], publicKeyBytes[:]) - - return privateKey -} - -// Sign signs the message with privateKey and returns a signature. It will -// panic if len(privateKey) is not PrivateKeySize. -func Sign(privateKey PrivateKey, message []byte) []byte { - if l := len(privateKey); l != PrivateKeySize { - panic("ed25519: bad private key length: " + strconv.Itoa(l)) - } - - h := sha512.New() - h.Write(privateKey[:32]) - - var digest1, messageDigest, hramDigest [64]byte - var expandedSecretKey [32]byte - h.Sum(digest1[:0]) - copy(expandedSecretKey[:], digest1[:]) - expandedSecretKey[0] &= 248 - expandedSecretKey[31] &= 63 - expandedSecretKey[31] |= 64 - - h.Reset() - h.Write(digest1[32:]) - h.Write(message) - h.Sum(messageDigest[:0]) - - var messageDigestReduced [32]byte - edwards25519.ScReduce(&messageDigestReduced, &messageDigest) - var R edwards25519.ExtendedGroupElement - edwards25519.GeScalarMultBase(&R, &messageDigestReduced) - - var encodedR [32]byte - R.ToBytes(&encodedR) - - h.Reset() - h.Write(encodedR[:]) - h.Write(privateKey[32:]) - h.Write(message) - h.Sum(hramDigest[:0]) - var hramDigestReduced [32]byte - edwards25519.ScReduce(&hramDigestReduced, &hramDigest) - - var s [32]byte - edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) - - signature := make([]byte, SignatureSize) - copy(signature[:], encodedR[:]) - copy(signature[32:], s[:]) - - return signature -} - -// Verify reports whether sig is a valid signature of message by publicKey. It -// will panic if len(publicKey) is not PublicKeySize. -func Verify(publicKey PublicKey, message, sig []byte) bool { - if l := len(publicKey); l != PublicKeySize { - panic("ed25519: bad public key length: " + strconv.Itoa(l)) - } - - if len(sig) != SignatureSize || sig[63]&224 != 0 { - return false - } - - var A edwards25519.ExtendedGroupElement - var publicKeyBytes [32]byte - copy(publicKeyBytes[:], publicKey) - if !A.FromBytes(&publicKeyBytes) { - return false - } - edwards25519.FeNeg(&A.X, &A.X) - edwards25519.FeNeg(&A.T, &A.T) - - h := sha512.New() - h.Write(sig[:32]) - h.Write(publicKey[:]) - h.Write(message) - var digest [64]byte - h.Sum(digest[:0]) - - var hReduced [32]byte - edwards25519.ScReduce(&hReduced, &digest) - - var R edwards25519.ProjectiveGroupElement - var s [32]byte - copy(s[:], sig[32:]) - - // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in - // the range [0, order) in order to prevent signature malleability. - if !edwards25519.ScMinimal(&s) { - return false - } - - edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) - - var checkR [32]byte - R.ToBytes(&checkR) - return bytes.Equal(sig[:32], checkR[:]) -} diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go b/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go deleted file mode 100644 index d1448d8..0000000 --- a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.13 - -// Package ed25519 implements the Ed25519 signature algorithm. See -// https://ed25519.cr.yp.to/. -// -// These functions are also compatible with the “Ed25519” function defined in -// RFC 8032. However, unlike RFC 8032's formulation, this package's private key -// representation includes a public key suffix to make multiple signing -// operations with the same key more efficient. This package refers to the RFC -// 8032 private key as the “seed”. -// -// Beginning with Go 1.13, the functionality of this package was moved to the -// standard library as crypto/ed25519. This package only acts as a compatibility -// wrapper. -package ed25519 - -import ( - "crypto/ed25519" - "io" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys as used in this package. - PublicKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = 64 - // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. - SeedSize = 32 -) - -// PublicKey is the type of Ed25519 public keys. -// -// This type is an alias for crypto/ed25519's PublicKey type. -// See the crypto/ed25519 package for the methods on this type. -type PublicKey = ed25519.PublicKey - -// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -// -// This type is an alias for crypto/ed25519's PrivateKey type. -// See the crypto/ed25519 package for the methods on this type. -type PrivateKey = ed25519.PrivateKey - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - return ed25519.GenerateKey(rand) -} - -// NewKeyFromSeed calculates a private key from a seed. It will panic if -// len(seed) is not SeedSize. This function is provided for interoperability -// with RFC 8032. RFC 8032's private keys correspond to seeds in this -// package. -func NewKeyFromSeed(seed []byte) PrivateKey { - return ed25519.NewKeyFromSeed(seed) -} - -// Sign signs the message with privateKey and returns a signature. It will -// panic if len(privateKey) is not PrivateKeySize. -func Sign(privateKey PrivateKey, message []byte) []byte { - return ed25519.Sign(privateKey, message) -} - -// Verify reports whether sig is a valid signature of message by publicKey. It -// will panic if len(publicKey) is not PublicKeySize. -func Verify(publicKey PublicKey, message, sig []byte) bool { - return ed25519.Verify(publicKey, message, sig) -} diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go deleted file mode 100644 index e39f086..0000000 --- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go +++ /dev/null @@ -1,1422 +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. - -package edwards25519 - -// These values are from the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -// d is a constant in the Edwards curve equation. -var d = FieldElement{ - -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, -} - -// d2 is 2*d. -var d2 = FieldElement{ - -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, -} - -// SqrtM1 is the square-root of -1 in the field. -var SqrtM1 = FieldElement{ - -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, -} - -// A is a constant in the Montgomery-form of curve25519. -var A = FieldElement{ - 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -// bi contains precomputed multiples of the base-point. See the Ed25519 paper -// for a discussion about how these values are used. -var bi = [8]PreComputedGroupElement{ - { - FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, - }, - { - FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, - }, - { - FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, - }, - { - FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, - }, - { - FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, - FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, - FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}, - }, - { - FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, - FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, - FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}, - }, - { - FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, - FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, - FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}, - }, - { - FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, - FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, - FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}, - }, -} - -// base contains precomputed multiples of the base-point. See the Ed25519 paper -// for a discussion about how these values are used. -var base = [32][8]PreComputedGroupElement{ - { - { - FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, - }, - { - FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, - FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, - FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}, - }, - { - FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, - }, - { - FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, - FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, - FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}, - }, - { - FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, - }, - { - FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, - FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, - FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}, - }, - { - FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, - }, - { - FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, - FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, - FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}, - }, - }, - { - { - FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, - FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, - FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}, - }, - { - FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, - FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, - FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}, - }, - { - FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, - FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, - FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}, - }, - { - FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, - FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, - FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}, - }, - { - FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, - FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, - FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}, - }, - { - FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, - FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, - FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}, - }, - { - FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, - FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, - FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}, - }, - { - FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, - FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, - FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}, - }, - }, - { - { - FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, - FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, - FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}, - }, - { - FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, - FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, - FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}, - }, - { - FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, - FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, - FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}, - }, - { - FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, - FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, - FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}, - }, - { - FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, - FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, - FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}, - }, - { - FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, - FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, - FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}, - }, - { - FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, - FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, - FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}, - }, - { - FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, - FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, - FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}, - }, - }, - { - { - FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, - FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, - FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}, - }, - { - FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, - FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, - FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}, - }, - { - FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, - FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, - FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}, - }, - { - FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, - FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, - FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}, - }, - { - FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, - FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, - FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}, - }, - { - FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, - FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, - FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}, - }, - { - FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, - FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, - FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}, - }, - { - FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, - FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, - FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}, - }, - }, - { - { - FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, - FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, - FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}, - }, - { - FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, - FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, - FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}, - }, - { - FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, - FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, - FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}, - }, - { - FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, - FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, - FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}, - }, - { - FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, - FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, - FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}, - }, - { - FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, - FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, - FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}, - }, - { - FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, - FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, - FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}, - }, - { - FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, - FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, - FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}, - }, - }, - { - { - FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, - FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, - FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}, - }, - { - FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, - FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, - FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}, - }, - { - FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, - FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, - FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}, - }, - { - FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, - FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, - FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}, - }, - { - FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, - FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, - FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}, - }, - { - FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, - FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, - FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}, - }, - { - FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, - FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, - FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}, - }, - { - FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, - FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, - FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}, - }, - }, - { - { - FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, - FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, - FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}, - }, - { - FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, - FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, - FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}, - }, - { - FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, - FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, - FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}, - }, - { - FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, - FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, - FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}, - }, - { - FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, - FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, - FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}, - }, - { - FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, - FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, - FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}, - }, - { - FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, - FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, - FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}, - }, - { - FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, - FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, - FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}, - }, - }, - { - { - FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, - FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, - FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}, - }, - { - FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, - FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, - FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}, - }, - { - FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, - FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, - FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}, - }, - { - FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, - FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, - FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}, - }, - { - FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, - FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, - FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}, - }, - { - FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, - FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, - FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}, - }, - { - FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, - FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, - FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}, - }, - { - FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, - FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, - FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}, - }, - }, - { - { - FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, - FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, - FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}, - }, - { - FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, - FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, - FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}, - }, - { - FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, - FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, - FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}, - }, - { - FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, - FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, - FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}, - }, - { - FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, - FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, - FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}, - }, - { - FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, - FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, - FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}, - }, - { - FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, - FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, - FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}, - }, - { - FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, - FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, - FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}, - }, - }, - { - { - FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, - FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, - FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}, - }, - { - FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, - FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, - FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}, - }, - { - FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, - FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, - FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}, - }, - { - FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, - FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, - FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}, - }, - { - FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, - FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, - FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}, - }, - { - FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, - FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, - FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}, - }, - { - FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, - FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, - FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}, - }, - { - FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, - FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, - FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}, - }, - }, - { - { - FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, - FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, - FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}, - }, - { - FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, - FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, - FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}, - }, - { - FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, - FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, - FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}, - }, - { - FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, - FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, - FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}, - }, - { - FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, - FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, - FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}, - }, - { - FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, - FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, - FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}, - }, - { - FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, - FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, - FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}, - }, - { - FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, - FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, - FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}, - }, - }, - { - { - FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, - FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, - FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}, - }, - { - FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, - FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, - FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}, - }, - { - FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, - FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, - FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}, - }, - { - FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, - FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, - FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}, - }, - { - FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, - FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, - FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}, - }, - { - FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, - FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, - FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}, - }, - { - FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, - FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, - FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}, - }, - { - FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, - FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, - FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}, - }, - }, - { - { - FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, - FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, - FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}, - }, - { - FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, - FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, - FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}, - }, - { - FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, - FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, - FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}, - }, - { - FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, - FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, - FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}, - }, - { - FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, - FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, - FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}, - }, - { - FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, - FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, - FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}, - }, - { - FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, - FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, - FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}, - }, - { - FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, - FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, - FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}, - }, - }, - { - { - FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, - FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, - FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}, - }, - { - FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, - FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, - FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}, - }, - { - FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, - FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, - FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}, - }, - { - FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, - FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, - FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}, - }, - { - FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, - FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, - FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}, - }, - { - FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, - FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, - FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}, - }, - { - FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, - FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, - FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}, - }, - { - FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, - FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, - FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}, - }, - }, - { - { - FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, - FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, - FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}, - }, - { - FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, - FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, - FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}, - }, - { - FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, - FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, - FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}, - }, - { - FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, - FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, - FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}, - }, - { - FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, - FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, - FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}, - }, - { - FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, - FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, - FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}, - }, - { - FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, - FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, - FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}, - }, - { - FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, - FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, - FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}, - }, - }, - { - { - FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, - FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, - FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}, - }, - { - FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, - FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, - FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}, - }, - { - FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, - FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, - FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}, - }, - { - FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, - FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, - FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}, - }, - { - FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, - FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, - FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}, - }, - { - FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, - FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, - FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}, - }, - { - FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, - FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, - FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}, - }, - { - FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, - FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, - FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}, - }, - }, - { - { - FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, - FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, - FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}, - }, - { - FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, - FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, - FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}, - }, - { - FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, - FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, - FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}, - }, - { - FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, - FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, - FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}, - }, - { - FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, - FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, - FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}, - }, - { - FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, - FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, - FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}, - }, - { - FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, - FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, - FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}, - }, - { - FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, - FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, - FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}, - }, - }, - { - { - FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, - FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, - FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}, - }, - { - FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, - FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, - FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}, - }, - { - FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, - FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, - FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}, - }, - { - FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, - FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, - FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}, - }, - { - FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, - FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, - FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}, - }, - { - FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, - FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, - FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}, - }, - { - FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, - FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, - FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}, - }, - { - FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, - FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, - FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}, - }, - }, - { - { - FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, - FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, - FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}, - }, - { - FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, - FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, - FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}, - }, - { - FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, - FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, - FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}, - }, - { - FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, - FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, - FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}, - }, - { - FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, - FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, - FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}, - }, - { - FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, - FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, - FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}, - }, - { - FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, - FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, - FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}, - }, - { - FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, - FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, - FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}, - }, - }, - { - { - FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, - FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, - FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}, - }, - { - FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, - FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, - FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}, - }, - { - FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, - FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, - FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}, - }, - { - FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, - FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, - FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}, - }, - { - FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, - FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, - FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}, - }, - { - FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, - FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, - FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}, - }, - { - FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, - FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, - FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}, - }, - { - FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, - FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, - FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}, - }, - }, - { - { - FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, - FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, - FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}, - }, - { - FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, - FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, - FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}, - }, - { - FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, - FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, - FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}, - }, - { - FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, - FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, - FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}, - }, - { - FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, - FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, - FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}, - }, - { - FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, - FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, - FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}, - }, - { - FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, - FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, - FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}, - }, - { - FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, - FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, - FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}, - }, - }, - { - { - FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, - FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, - FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}, - }, - { - FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, - FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, - FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}, - }, - { - FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, - FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, - FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}, - }, - { - FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, - FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, - FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}, - }, - { - FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, - FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, - FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}, - }, - { - FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, - FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, - FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}, - }, - { - FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, - FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, - FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}, - }, - { - FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, - FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, - FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}, - }, - }, - { - { - FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, - FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, - FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}, - }, - { - FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, - FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, - FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}, - }, - { - FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, - FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, - FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}, - }, - { - FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, - FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, - FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}, - }, - { - FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, - FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, - FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}, - }, - { - FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, - FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, - FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}, - }, - { - FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, - FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, - FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}, - }, - { - FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, - FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, - FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}, - }, - }, - { - { - FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, - FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, - FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}, - }, - { - FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, - FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, - FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}, - }, - { - FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, - FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, - FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}, - }, - { - FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, - FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, - FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}, - }, - { - FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, - FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, - FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}, - }, - { - FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, - FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, - FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}, - }, - { - FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, - FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, - FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}, - }, - { - FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, - FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, - FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}, - }, - }, - { - { - FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, - FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, - FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}, - }, - { - FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, - FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, - FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}, - }, - { - FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, - FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, - FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}, - }, - { - FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, - FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, - FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}, - }, - { - FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, - FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, - FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}, - }, - { - FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, - FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, - FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}, - }, - { - FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, - FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, - FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}, - }, - { - FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, - FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, - FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}, - }, - }, - { - { - FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, - FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, - FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}, - }, - { - FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, - FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, - FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}, - }, - { - FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, - FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, - FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}, - }, - { - FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, - FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, - FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}, - }, - { - FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, - FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, - FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}, - }, - { - FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, - FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, - FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}, - }, - { - FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, - FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, - FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}, - }, - { - FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, - FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, - FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}, - }, - }, - { - { - FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, - FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, - FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}, - }, - { - FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, - FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, - FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}, - }, - { - FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, - FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, - FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}, - }, - { - FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, - FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, - FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}, - }, - { - FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, - FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, - FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}, - }, - { - FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, - FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, - FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}, - }, - { - FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, - FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, - FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}, - }, - { - FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, - FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, - FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}, - }, - }, - { - { - FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, - FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, - FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}, - }, - { - FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, - FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, - FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}, - }, - { - FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, - FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, - FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}, - }, - { - FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, - FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, - FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}, - }, - { - FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, - FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, - FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}, - }, - { - FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, - FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, - FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}, - }, - { - FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, - FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, - FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}, - }, - { - FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, - FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, - FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}, - }, - }, - { - { - FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, - FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, - FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}, - }, - { - FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, - FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, - FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}, - }, - { - FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, - FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, - FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}, - }, - { - FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, - FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, - FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}, - }, - { - FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, - FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, - FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}, - }, - { - FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, - FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, - FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}, - }, - { - FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, - FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, - FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}, - }, - { - FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, - FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, - FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}, - }, - }, - { - { - FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, - FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, - FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}, - }, - { - FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, - FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, - FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}, - }, - { - FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, - FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, - FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}, - }, - { - FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, - FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, - FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}, - }, - { - FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, - FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, - FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}, - }, - { - FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, - FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, - FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}, - }, - { - FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, - FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, - FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}, - }, - { - FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, - FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, - FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}, - }, - }, - { - { - FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, - FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, - FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}, - }, - { - FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, - FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, - FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}, - }, - { - FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, - FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, - FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}, - }, - { - FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, - FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, - FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}, - }, - { - FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, - FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, - FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}, - }, - { - FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, - FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, - FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}, - }, - { - FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, - FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, - FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}, - }, - { - FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, - FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, - FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}, - }, - }, - { - { - FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, - FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, - FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}, - }, - { - FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, - FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, - FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}, - }, - { - FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, - FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, - FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}, - }, - { - FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, - FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, - FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}, - }, - { - FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, - FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, - FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}, - }, - { - FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, - FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, - FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}, - }, - { - FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, - FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, - FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}, - }, - { - FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, - FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, - FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}, - }, - }, -} diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go deleted file mode 100644 index fd03c25..0000000 --- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go +++ /dev/null @@ -1,1793 +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. - -package edwards25519 - -import "encoding/binary" - -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -// FieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type FieldElement [10]int32 - -var zero FieldElement - -func FeZero(fe *FieldElement) { - copy(fe[:], zero[:]) -} - -func FeOne(fe *FieldElement) { - FeZero(fe) - fe[0] = 1 -} - -func FeAdd(dst, a, b *FieldElement) { - dst[0] = a[0] + b[0] - dst[1] = a[1] + b[1] - dst[2] = a[2] + b[2] - dst[3] = a[3] + b[3] - dst[4] = a[4] + b[4] - dst[5] = a[5] + b[5] - dst[6] = a[6] + b[6] - dst[7] = a[7] + b[7] - dst[8] = a[8] + b[8] - dst[9] = a[9] + b[9] -} - -func FeSub(dst, a, b *FieldElement) { - dst[0] = a[0] - b[0] - dst[1] = a[1] - b[1] - dst[2] = a[2] - b[2] - dst[3] = a[3] - b[3] - dst[4] = a[4] - b[4] - dst[5] = a[5] - b[5] - dst[6] = a[6] - b[6] - dst[7] = a[7] - b[7] - dst[8] = a[8] - b[8] - dst[9] = a[9] - b[9] -} - -func FeCopy(dst, src *FieldElement) { - copy(dst[:], src[:]) -} - -// Replace (f,g) with (g,g) if b == 1; -// replace (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -func FeCMove(f, g *FieldElement, b int32) { - b = -b - f[0] ^= b & (f[0] ^ g[0]) - f[1] ^= b & (f[1] ^ g[1]) - f[2] ^= b & (f[2] ^ g[2]) - f[3] ^= b & (f[3] ^ g[3]) - f[4] ^= b & (f[4] ^ g[4]) - f[5] ^= b & (f[5] ^ g[5]) - f[6] ^= b & (f[6] ^ g[6]) - f[7] ^= b & (f[7] ^ g[7]) - f[8] ^= b & (f[8] ^ g[8]) - f[9] ^= b & (f[9] ^ g[9]) -} - -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -func load4(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - r |= int64(in[3]) << 24 - return r -} - -func FeFromBytes(dst *FieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 8388607) << 2 - - FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -// FeToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) -} - -func FeIsNegative(f *FieldElement) byte { - var s [32]byte - FeToBytes(&s, f) - return s[0] & 1 -} - -func FeIsNonZero(f *FieldElement) int32 { - var s [32]byte - FeToBytes(&s, f) - var x uint8 - for _, b := range s { - x |= b - } - x |= x >> 4 - x |= x >> 2 - x |= x >> 1 - return int32(x & 1) -} - -// FeNeg sets h = -f -// -// Preconditions: -// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func FeNeg(h, f *FieldElement) { - h[0] = -f[0] - h[1] = -f[1] - h[2] = -f[2] - h[3] = -f[3] - h[4] = -f[4] - h[5] = -f[5] - h[6] = -f[6] - h[7] = -f[7] - h[8] = -f[8] - h[9] = -f[9] -} - -func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { - var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64 - - /* - |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - */ - - c0 = (h0 + (1 << 25)) >> 26 - h1 += c0 - h0 -= c0 << 26 - c4 = (h4 + (1 << 25)) >> 26 - h5 += c4 - h4 -= c4 << 26 - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.51*2^58 */ - /* |h5| <= 1.51*2^58 */ - - c1 = (h1 + (1 << 24)) >> 25 - h2 += c1 - h1 -= c1 << 25 - c5 = (h5 + (1 << 24)) >> 25 - h6 += c5 - h5 -= c5 << 25 - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.21*2^59 */ - /* |h6| <= 1.21*2^59 */ - - c2 = (h2 + (1 << 25)) >> 26 - h3 += c2 - h2 -= c2 << 26 - c6 = (h6 + (1 << 25)) >> 26 - h7 += c6 - h6 -= c6 << 26 - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.51*2^58 */ - /* |h7| <= 1.51*2^58 */ - - c3 = (h3 + (1 << 24)) >> 25 - h4 += c3 - h3 -= c3 << 25 - c7 = (h7 + (1 << 24)) >> 25 - h8 += c7 - h7 -= c7 << 25 - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.52*2^33 */ - /* |h8| <= 1.52*2^33 */ - - c4 = (h4 + (1 << 25)) >> 26 - h5 += c4 - h4 -= c4 << 26 - c8 = (h8 + (1 << 25)) >> 26 - h9 += c8 - h8 -= c8 << 26 - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.51*2^58 */ - - c9 = (h9 + (1 << 24)) >> 25 - h0 += c9 * 19 - h9 -= c9 << 25 - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.8*2^37 */ - - c0 = (h0 + (1 << 25)) >> 26 - h1 += c0 - h0 -= c0 << 26 - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// FeMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: -// -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. -// -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs, can squeeze carries into int32. -func FeMul(h, f, g *FieldElement) { - f0 := int64(f[0]) - f1 := int64(f[1]) - f2 := int64(f[2]) - f3 := int64(f[3]) - f4 := int64(f[4]) - f5 := int64(f[5]) - f6 := int64(f[6]) - f7 := int64(f[7]) - f8 := int64(f[8]) - f9 := int64(f[9]) - - f1_2 := int64(2 * f[1]) - f3_2 := int64(2 * f[3]) - f5_2 := int64(2 * f[5]) - f7_2 := int64(2 * f[7]) - f9_2 := int64(2 * f[9]) - - g0 := int64(g[0]) - g1 := int64(g[1]) - g2 := int64(g[2]) - g3 := int64(g[3]) - g4 := int64(g[4]) - g5 := int64(g[5]) - g6 := int64(g[6]) - g7 := int64(g[7]) - g8 := int64(g[8]) - g9 := int64(g[9]) - - g1_19 := int64(19 * g[1]) /* 1.4*2^29 */ - g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */ - g3_19 := int64(19 * g[3]) - g4_19 := int64(19 * g[4]) - g5_19 := int64(19 * g[5]) - g6_19 := int64(19 * g[6]) - g7_19 := int64(19 * g[7]) - g8_19 := int64(19 * g[8]) - g9_19 := int64(19 * g[9]) - - h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19 - h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19 - h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19 - h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19 - h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19 - h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19 - h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19 - h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19 - h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19 - h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0 - - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { - f0 := int64(f[0]) - f1 := int64(f[1]) - f2 := int64(f[2]) - f3 := int64(f[3]) - f4 := int64(f[4]) - f5 := int64(f[5]) - f6 := int64(f[6]) - f7 := int64(f[7]) - f8 := int64(f[8]) - f9 := int64(f[9]) - f0_2 := int64(2 * f[0]) - f1_2 := int64(2 * f[1]) - f2_2 := int64(2 * f[2]) - f3_2 := int64(2 * f[3]) - f4_2 := int64(2 * f[4]) - f5_2 := int64(2 * f[5]) - f6_2 := int64(2 * f[6]) - f7_2 := int64(2 * f[7]) - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - - h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 - h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 - h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 - h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 - h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 - h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 - h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 - h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 - h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 - h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 - - return -} - -// FeSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func FeSquare(h, f *FieldElement) { - h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -// FeSquare2 sets h = 2 * f * f -// -// Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -// See fe_mul.c for discussion of implementation strategy. -func FeSquare2(h, f *FieldElement) { - h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) - - h0 += h0 - h1 += h1 - h2 += h2 - h3 += h3 - h4 += h4 - h5 += h5 - h6 += h6 - h7 += h7 - h8 += h8 - h9 += h9 - - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -func FeInvert(out, z *FieldElement) { - var t0, t1, t2, t3 FieldElement - var i int - - FeSquare(&t0, z) // 2^1 - FeSquare(&t1, &t0) // 2^2 - for i = 1; i < 2; i++ { // 2^3 - FeSquare(&t1, &t1) - } - FeMul(&t1, z, &t1) // 2^3 + 2^0 - FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0 - FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1 - FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0 - FeSquare(&t2, &t1) // 5,4,3,2,1 - for i = 1; i < 5; i++ { // 9,8,7,6,5 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0 - FeSquare(&t2, &t1) // 10..1 - for i = 1; i < 10; i++ { // 19..10 - FeSquare(&t2, &t2) - } - FeMul(&t2, &t2, &t1) // 19..0 - FeSquare(&t3, &t2) // 20..1 - for i = 1; i < 20; i++ { // 39..20 - FeSquare(&t3, &t3) - } - FeMul(&t2, &t3, &t2) // 39..0 - FeSquare(&t2, &t2) // 40..1 - for i = 1; i < 10; i++ { // 49..10 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 49..0 - FeSquare(&t2, &t1) // 50..1 - for i = 1; i < 50; i++ { // 99..50 - FeSquare(&t2, &t2) - } - FeMul(&t2, &t2, &t1) // 99..0 - FeSquare(&t3, &t2) // 100..1 - for i = 1; i < 100; i++ { // 199..100 - FeSquare(&t3, &t3) - } - FeMul(&t2, &t3, &t2) // 199..0 - FeSquare(&t2, &t2) // 200..1 - for i = 1; i < 50; i++ { // 249..50 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 249..0 - FeSquare(&t1, &t1) // 250..1 - for i = 1; i < 5; i++ { // 254..5 - FeSquare(&t1, &t1) - } - FeMul(out, &t1, &t0) // 254..5,3,1,0 -} - -func fePow22523(out, z *FieldElement) { - var t0, t1, t2 FieldElement - var i int - - FeSquare(&t0, z) - for i = 1; i < 1; i++ { - FeSquare(&t0, &t0) - } - FeSquare(&t1, &t0) - for i = 1; i < 2; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, z, &t1) - FeMul(&t0, &t0, &t1) - FeSquare(&t0, &t0) - for i = 1; i < 1; i++ { - FeSquare(&t0, &t0) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 5; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 10; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, &t1, &t0) - FeSquare(&t2, &t1) - for i = 1; i < 20; i++ { - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) - FeSquare(&t1, &t1) - for i = 1; i < 10; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 50; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, &t1, &t0) - FeSquare(&t2, &t1) - for i = 1; i < 100; i++ { - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) - FeSquare(&t1, &t1) - for i = 1; i < 50; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t0, &t0) - for i = 1; i < 2; i++ { - FeSquare(&t0, &t0) - } - FeMul(out, &t0, z) -} - -// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 * -// y^2 where d = -121665/121666. -// -// Several representations are used: -// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z -// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT -// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T -// PreComputedGroupElement: (y+x,y-x,2dxy) - -type ProjectiveGroupElement struct { - X, Y, Z FieldElement -} - -type ExtendedGroupElement struct { - X, Y, Z, T FieldElement -} - -type CompletedGroupElement struct { - X, Y, Z, T FieldElement -} - -type PreComputedGroupElement struct { - yPlusX, yMinusX, xy2d FieldElement -} - -type CachedGroupElement struct { - yPlusX, yMinusX, Z, T2d FieldElement -} - -func (p *ProjectiveGroupElement) Zero() { - FeZero(&p.X) - FeOne(&p.Y) - FeOne(&p.Z) -} - -func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) { - var t0 FieldElement - - FeSquare(&r.X, &p.X) - FeSquare(&r.Z, &p.Y) - FeSquare2(&r.T, &p.Z) - FeAdd(&r.Y, &p.X, &p.Y) - FeSquare(&t0, &r.Y) - FeAdd(&r.Y, &r.Z, &r.X) - FeSub(&r.Z, &r.Z, &r.X) - FeSub(&r.X, &t0, &r.Y) - FeSub(&r.T, &r.T, &r.Z) -} - -func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) { - var recip, x, y FieldElement - - FeInvert(&recip, &p.Z) - FeMul(&x, &p.X, &recip) - FeMul(&y, &p.Y, &recip) - FeToBytes(s, &y) - s[31] ^= FeIsNegative(&x) << 7 -} - -func (p *ExtendedGroupElement) Zero() { - FeZero(&p.X) - FeOne(&p.Y) - FeOne(&p.Z) - FeZero(&p.T) -} - -func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) { - var q ProjectiveGroupElement - p.ToProjective(&q) - q.Double(r) -} - -func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) { - FeAdd(&r.yPlusX, &p.Y, &p.X) - FeSub(&r.yMinusX, &p.Y, &p.X) - FeCopy(&r.Z, &p.Z) - FeMul(&r.T2d, &p.T, &d2) -} - -func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) { - FeCopy(&r.X, &p.X) - FeCopy(&r.Y, &p.Y) - FeCopy(&r.Z, &p.Z) -} - -func (p *ExtendedGroupElement) ToBytes(s *[32]byte) { - var recip, x, y FieldElement - - FeInvert(&recip, &p.Z) - FeMul(&x, &p.X, &recip) - FeMul(&y, &p.Y, &recip) - FeToBytes(s, &y) - s[31] ^= FeIsNegative(&x) << 7 -} - -func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool { - var u, v, v3, vxx, check FieldElement - - FeFromBytes(&p.Y, s) - FeOne(&p.Z) - FeSquare(&u, &p.Y) - FeMul(&v, &u, &d) - FeSub(&u, &u, &p.Z) // y = y^2-1 - FeAdd(&v, &v, &p.Z) // v = dy^2+1 - - FeSquare(&v3, &v) - FeMul(&v3, &v3, &v) // v3 = v^3 - FeSquare(&p.X, &v3) - FeMul(&p.X, &p.X, &v) - FeMul(&p.X, &p.X, &u) // x = uv^7 - - fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8) - FeMul(&p.X, &p.X, &v3) - FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8) - - var tmpX, tmp2 [32]byte - - FeSquare(&vxx, &p.X) - FeMul(&vxx, &vxx, &v) - FeSub(&check, &vxx, &u) // vx^2-u - if FeIsNonZero(&check) == 1 { - FeAdd(&check, &vxx, &u) // vx^2+u - if FeIsNonZero(&check) == 1 { - return false - } - FeMul(&p.X, &p.X, &SqrtM1) - - FeToBytes(&tmpX, &p.X) - for i, v := range tmpX { - tmp2[31-i] = v - } - } - - if FeIsNegative(&p.X) != (s[31] >> 7) { - FeNeg(&p.X, &p.X) - } - - FeMul(&p.T, &p.X, &p.Y) - return true -} - -func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) { - FeMul(&r.X, &p.X, &p.T) - FeMul(&r.Y, &p.Y, &p.Z) - FeMul(&r.Z, &p.Z, &p.T) -} - -func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) { - FeMul(&r.X, &p.X, &p.T) - FeMul(&r.Y, &p.Y, &p.Z) - FeMul(&r.Z, &p.Z, &p.T) - FeMul(&r.T, &p.X, &p.Y) -} - -func (p *PreComputedGroupElement) Zero() { - FeOne(&p.yPlusX) - FeOne(&p.yMinusX) - FeZero(&p.xy2d) -} - -func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yPlusX) - FeMul(&r.Y, &r.Y, &q.yMinusX) - FeMul(&r.T, &q.T2d, &p.T) - FeMul(&r.X, &p.Z, &q.Z) - FeAdd(&t0, &r.X, &r.X) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeAdd(&r.Z, &t0, &r.T) - FeSub(&r.T, &t0, &r.T) -} - -func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yMinusX) - FeMul(&r.Y, &r.Y, &q.yPlusX) - FeMul(&r.T, &q.T2d, &p.T) - FeMul(&r.X, &p.Z, &q.Z) - FeAdd(&t0, &r.X, &r.X) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeSub(&r.Z, &t0, &r.T) - FeAdd(&r.T, &t0, &r.T) -} - -func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yPlusX) - FeMul(&r.Y, &r.Y, &q.yMinusX) - FeMul(&r.T, &q.xy2d, &p.T) - FeAdd(&t0, &p.Z, &p.Z) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeAdd(&r.Z, &t0, &r.T) - FeSub(&r.T, &t0, &r.T) -} - -func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yMinusX) - FeMul(&r.Y, &r.Y, &q.yPlusX) - FeMul(&r.T, &q.xy2d, &p.T) - FeAdd(&t0, &p.Z, &p.Z) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeSub(&r.Z, &t0, &r.T) - FeAdd(&r.T, &t0, &r.T) -} - -func slide(r *[256]int8, a *[32]byte) { - for i := range r { - r[i] = int8(1 & (a[i>>3] >> uint(i&7))) - } - - for i := range r { - if r[i] != 0 { - for b := 1; b <= 6 && i+b < 256; b++ { - if r[i+b] != 0 { - if r[i]+(r[i+b]<= -15 { - r[i] -= r[i+b] << uint(b) - for k := i + b; k < 256; k++ { - if r[k] == 0 { - r[k] = 1 - break - } - r[k] = 0 - } - } else { - break - } - } - } - } - } -} - -// GeDoubleScalarMultVartime sets r = a*A + b*B -// where a = a[0]+256*a[1]+...+256^31 a[31]. -// and b = b[0]+256*b[1]+...+256^31 b[31]. -// B is the Ed25519 base point (x,4/5) with x positive. -func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) { - var aSlide, bSlide [256]int8 - var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A - var t CompletedGroupElement - var u, A2 ExtendedGroupElement - var i int - - slide(&aSlide, a) - slide(&bSlide, b) - - A.ToCached(&Ai[0]) - A.Double(&t) - t.ToExtended(&A2) - - for i := 0; i < 7; i++ { - geAdd(&t, &A2, &Ai[i]) - t.ToExtended(&u) - u.ToCached(&Ai[i+1]) - } - - r.Zero() - - for i = 255; i >= 0; i-- { - if aSlide[i] != 0 || bSlide[i] != 0 { - break - } - } - - for ; i >= 0; i-- { - r.Double(&t) - - if aSlide[i] > 0 { - t.ToExtended(&u) - geAdd(&t, &u, &Ai[aSlide[i]/2]) - } else if aSlide[i] < 0 { - t.ToExtended(&u) - geSub(&t, &u, &Ai[(-aSlide[i])/2]) - } - - if bSlide[i] > 0 { - t.ToExtended(&u) - geMixedAdd(&t, &u, &bi[bSlide[i]/2]) - } else if bSlide[i] < 0 { - t.ToExtended(&u) - geMixedSub(&t, &u, &bi[(-bSlide[i])/2]) - } - - t.ToProjective(r) - } -} - -// equal returns 1 if b == c and 0 otherwise, assuming that b and c are -// non-negative. -func equal(b, c int32) int32 { - x := uint32(b ^ c) - x-- - return int32(x >> 31) -} - -// negative returns 1 if b < 0 and 0 otherwise. -func negative(b int32) int32 { - return (b >> 31) & 1 -} - -func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) { - FeCMove(&t.yPlusX, &u.yPlusX, b) - FeCMove(&t.yMinusX, &u.yMinusX, b) - FeCMove(&t.xy2d, &u.xy2d, b) -} - -func selectPoint(t *PreComputedGroupElement, pos int32, b int32) { - var minusT PreComputedGroupElement - bNegative := negative(b) - bAbs := b - (((-bNegative) & b) << 1) - - t.Zero() - for i := int32(0); i < 8; i++ { - PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1)) - } - FeCopy(&minusT.yPlusX, &t.yMinusX) - FeCopy(&minusT.yMinusX, &t.yPlusX) - FeNeg(&minusT.xy2d, &t.xy2d) - PreComputedGroupElementCMove(t, &minusT, bNegative) -} - -// GeScalarMultBase computes h = a*B, where -// a = a[0]+256*a[1]+...+256^31 a[31] -// B is the Ed25519 base point (x,4/5) with x positive. -// -// Preconditions: -// a[31] <= 127 -func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) { - var e [64]int8 - - for i, v := range a { - e[2*i] = int8(v & 15) - e[2*i+1] = int8((v >> 4) & 15) - } - - // each e[i] is between 0 and 15 and e[63] is between 0 and 7. - - carry := int8(0) - for i := 0; i < 63; i++ { - e[i] += carry - carry = (e[i] + 8) >> 4 - e[i] -= carry << 4 - } - e[63] += carry - // each e[i] is between -8 and 8. - - h.Zero() - var t PreComputedGroupElement - var r CompletedGroupElement - for i := int32(1); i < 64; i += 2 { - selectPoint(&t, i/2, int32(e[i])) - geMixedAdd(&r, h, &t) - r.ToExtended(h) - } - - var s ProjectiveGroupElement - - h.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToExtended(h) - - for i := int32(0); i < 64; i += 2 { - selectPoint(&t, i/2, int32(e[i])) - geMixedAdd(&r, h, &t) - r.ToExtended(h) - } -} - -// The scalars are GF(2^252 + 27742317777372353535851937790883648493). - -// Input: -// a[0]+256*a[1]+...+256^31*a[31] = a -// b[0]+256*b[1]+...+256^31*b[31] = b -// c[0]+256*c[1]+...+256^31*c[31] = c -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func ScMulAdd(s, a, b, c *[32]byte) { - a0 := 2097151 & load3(a[:]) - a1 := 2097151 & (load4(a[2:]) >> 5) - a2 := 2097151 & (load3(a[5:]) >> 2) - a3 := 2097151 & (load4(a[7:]) >> 7) - a4 := 2097151 & (load4(a[10:]) >> 4) - a5 := 2097151 & (load3(a[13:]) >> 1) - a6 := 2097151 & (load4(a[15:]) >> 6) - a7 := 2097151 & (load3(a[18:]) >> 3) - a8 := 2097151 & load3(a[21:]) - a9 := 2097151 & (load4(a[23:]) >> 5) - a10 := 2097151 & (load3(a[26:]) >> 2) - a11 := (load4(a[28:]) >> 7) - b0 := 2097151 & load3(b[:]) - b1 := 2097151 & (load4(b[2:]) >> 5) - b2 := 2097151 & (load3(b[5:]) >> 2) - b3 := 2097151 & (load4(b[7:]) >> 7) - b4 := 2097151 & (load4(b[10:]) >> 4) - b5 := 2097151 & (load3(b[13:]) >> 1) - b6 := 2097151 & (load4(b[15:]) >> 6) - b7 := 2097151 & (load3(b[18:]) >> 3) - b8 := 2097151 & load3(b[21:]) - b9 := 2097151 & (load4(b[23:]) >> 5) - b10 := 2097151 & (load3(b[26:]) >> 2) - b11 := (load4(b[28:]) >> 7) - c0 := 2097151 & load3(c[:]) - c1 := 2097151 & (load4(c[2:]) >> 5) - c2 := 2097151 & (load3(c[5:]) >> 2) - c3 := 2097151 & (load4(c[7:]) >> 7) - c4 := 2097151 & (load4(c[10:]) >> 4) - c5 := 2097151 & (load3(c[13:]) >> 1) - c6 := 2097151 & (load4(c[15:]) >> 6) - c7 := 2097151 & (load3(c[18:]) >> 3) - c8 := 2097151 & load3(c[21:]) - c9 := 2097151 & (load4(c[23:]) >> 5) - c10 := 2097151 & (load3(c[26:]) >> 2) - c11 := (load4(c[28:]) >> 7) - var carry [23]int64 - - s0 := c0 + a0*b0 - s1 := c1 + a0*b1 + a1*b0 - s2 := c2 + a0*b2 + a1*b1 + a2*b0 - s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 - s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 - s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 - s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 - s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 - s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 - s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 - s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 - s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 - s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 - s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 - s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 - s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 - s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 - s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 - s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 - s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 - s20 := a9*b11 + a10*b10 + a11*b9 - s21 := a10*b11 + a11*b10 - s22 := a11 * b11 - s23 := int64(0) - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - carry[18] = (s18 + (1 << 20)) >> 21 - s19 += carry[18] - s18 -= carry[18] << 21 - carry[20] = (s20 + (1 << 20)) >> 21 - s21 += carry[20] - s20 -= carry[20] << 21 - carry[22] = (s22 + (1 << 20)) >> 21 - s23 += carry[22] - s22 -= carry[22] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - carry[17] = (s17 + (1 << 20)) >> 21 - s18 += carry[17] - s17 -= carry[17] << 21 - carry[19] = (s19 + (1 << 20)) >> 21 - s20 += carry[19] - s19 -= carry[19] << 21 - carry[21] = (s21 + (1 << 20)) >> 21 - s22 += carry[21] - s21 -= carry[21] << 21 - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - s[0] = byte(s0 >> 0) - s[1] = byte(s0 >> 8) - s[2] = byte((s0 >> 16) | (s1 << 5)) - s[3] = byte(s1 >> 3) - s[4] = byte(s1 >> 11) - s[5] = byte((s1 >> 19) | (s2 << 2)) - s[6] = byte(s2 >> 6) - s[7] = byte((s2 >> 14) | (s3 << 7)) - s[8] = byte(s3 >> 1) - s[9] = byte(s3 >> 9) - s[10] = byte((s3 >> 17) | (s4 << 4)) - s[11] = byte(s4 >> 4) - s[12] = byte(s4 >> 12) - s[13] = byte((s4 >> 20) | (s5 << 1)) - s[14] = byte(s5 >> 7) - s[15] = byte((s5 >> 15) | (s6 << 6)) - s[16] = byte(s6 >> 2) - s[17] = byte(s6 >> 10) - s[18] = byte((s6 >> 18) | (s7 << 3)) - s[19] = byte(s7 >> 5) - s[20] = byte(s7 >> 13) - s[21] = byte(s8 >> 0) - s[22] = byte(s8 >> 8) - s[23] = byte((s8 >> 16) | (s9 << 5)) - s[24] = byte(s9 >> 3) - s[25] = byte(s9 >> 11) - s[26] = byte((s9 >> 19) | (s10 << 2)) - s[27] = byte(s10 >> 6) - s[28] = byte((s10 >> 14) | (s11 << 7)) - s[29] = byte(s11 >> 1) - s[30] = byte(s11 >> 9) - s[31] = byte(s11 >> 17) -} - -// Input: -// s[0]+256*s[1]+...+256^63*s[63] = s -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = s mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func ScReduce(out *[32]byte, s *[64]byte) { - s0 := 2097151 & load3(s[:]) - s1 := 2097151 & (load4(s[2:]) >> 5) - s2 := 2097151 & (load3(s[5:]) >> 2) - s3 := 2097151 & (load4(s[7:]) >> 7) - s4 := 2097151 & (load4(s[10:]) >> 4) - s5 := 2097151 & (load3(s[13:]) >> 1) - s6 := 2097151 & (load4(s[15:]) >> 6) - s7 := 2097151 & (load3(s[18:]) >> 3) - s8 := 2097151 & load3(s[21:]) - s9 := 2097151 & (load4(s[23:]) >> 5) - s10 := 2097151 & (load3(s[26:]) >> 2) - s11 := 2097151 & (load4(s[28:]) >> 7) - s12 := 2097151 & (load4(s[31:]) >> 4) - s13 := 2097151 & (load3(s[34:]) >> 1) - s14 := 2097151 & (load4(s[36:]) >> 6) - s15 := 2097151 & (load3(s[39:]) >> 3) - s16 := 2097151 & load3(s[42:]) - s17 := 2097151 & (load4(s[44:]) >> 5) - s18 := 2097151 & (load3(s[47:]) >> 2) - s19 := 2097151 & (load4(s[49:]) >> 7) - s20 := 2097151 & (load4(s[52:]) >> 4) - s21 := 2097151 & (load3(s[55:]) >> 1) - s22 := 2097151 & (load4(s[57:]) >> 6) - s23 := (load4(s[60:]) >> 3) - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - var carry [17]int64 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - out[0] = byte(s0 >> 0) - out[1] = byte(s0 >> 8) - out[2] = byte((s0 >> 16) | (s1 << 5)) - out[3] = byte(s1 >> 3) - out[4] = byte(s1 >> 11) - out[5] = byte((s1 >> 19) | (s2 << 2)) - out[6] = byte(s2 >> 6) - out[7] = byte((s2 >> 14) | (s3 << 7)) - out[8] = byte(s3 >> 1) - out[9] = byte(s3 >> 9) - out[10] = byte((s3 >> 17) | (s4 << 4)) - out[11] = byte(s4 >> 4) - out[12] = byte(s4 >> 12) - out[13] = byte((s4 >> 20) | (s5 << 1)) - out[14] = byte(s5 >> 7) - out[15] = byte((s5 >> 15) | (s6 << 6)) - out[16] = byte(s6 >> 2) - out[17] = byte(s6 >> 10) - out[18] = byte((s6 >> 18) | (s7 << 3)) - out[19] = byte(s7 >> 5) - out[20] = byte(s7 >> 13) - out[21] = byte(s8 >> 0) - out[22] = byte(s8 >> 8) - out[23] = byte((s8 >> 16) | (s9 << 5)) - out[24] = byte(s9 >> 3) - out[25] = byte(s9 >> 11) - out[26] = byte((s9 >> 19) | (s10 << 2)) - out[27] = byte(s10 >> 6) - out[28] = byte((s10 >> 14) | (s11 << 7)) - out[29] = byte(s11 >> 1) - out[30] = byte(s11 >> 9) - out[31] = byte(s11 >> 17) -} - -// order is the order of Curve25519 in little-endian form. -var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} - -// ScMinimal returns true if the given scalar is less than the order of the -// curve. -func ScMinimal(scalar *[32]byte) bool { - for i := 3; ; i-- { - v := binary.LittleEndian.Uint64(scalar[i*8:]) - if v > order[i] { - return false - } else if v < order[i] { - break - } else if i == 0 { - return false - } - } - - return true -} diff --git a/vendor/golang.org/x/crypto/internal/alias/alias.go b/vendor/golang.org/x/crypto/internal/alias/alias.go new file mode 100644 index 0000000..551ff0c --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/alias/alias.go @@ -0,0 +1,31 @@ +// 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 !purego + +// Package alias implements memory aliasing tests. +package alias + +import "unsafe" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/alias/alias_purego.go b/vendor/golang.org/x/crypto/internal/alias/alias_purego.go new file mode 100644 index 0000000..6fe61b5 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/alias/alias_purego.go @@ -0,0 +1,34 @@ +// 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 purego + +// Package alias implements memory aliasing tests. +package alias + +// This is the Google App Engine standard variant based on reflect +// because the unsafe package and cgo are disallowed. + +import "reflect" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && + reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go new file mode 100644 index 0000000..8d99551 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go @@ -0,0 +1,9 @@ +// 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 (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego + +package poly1305 + +type mac struct{ macGeneric } diff --git a/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go new file mode 100644 index 0000000..4aaea81 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go @@ -0,0 +1,99 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package poly1305 implements Poly1305 one-time message authentication code as +// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. +// +// Poly1305 is a fast, one-time authentication function. It is infeasible for an +// attacker to generate an authenticator for a message without the key. However, a +// key must only be used for a single message. Authenticating two different +// messages with the same key allows an attacker to forge authenticators for other +// messages with the same key. +// +// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was +// used with a fixed key in order to generate one-time keys from an nonce. +// However, in this package AES isn't used and the one-time key is specified +// directly. +package poly1305 + +import "crypto/subtle" + +// TagSize is the size, in bytes, of a poly1305 authenticator. +const TagSize = 16 + +// Sum generates an authenticator for msg using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + h := New(key) + h.Write(m) + h.Sum(out[:0]) +} + +// Verify returns true if mac is a valid authenticator for m with the given key. +func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { + var tmp [16]byte + Sum(&tmp, m, key) + return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 +} + +// New returns a new MAC computing an authentication +// tag of all data written to it with the given key. +// This allows writing the message progressively instead +// of passing it as a single slice. Common users should use +// the Sum function instead. +// +// The key must be unique for each message, as authenticating +// two different messages with the same key allows an attacker +// to forge messages at will. +func New(key *[32]byte) *MAC { + m := &MAC{} + initialize(key, &m.macState) + return m +} + +// MAC is an io.Writer computing an authentication tag +// of the data written to it. +// +// MAC cannot be used like common hash.Hash implementations, +// because using a poly1305 key twice breaks its security. +// Therefore writing data to a running MAC after calling +// Sum or Verify causes it to panic. +type MAC struct { + mac // platform-dependent implementation + + finalized bool +} + +// Size returns the number of bytes Sum will return. +func (h *MAC) Size() int { return TagSize } + +// Write adds more data to the running message authentication code. +// It never returns an error. +// +// It must not be called after the first call of Sum or Verify. +func (h *MAC) Write(p []byte) (n int, err error) { + if h.finalized { + panic("poly1305: write to MAC after Sum or Verify") + } + return h.mac.Write(p) +} + +// Sum computes the authenticator of all data written to the +// message authentication code. +func (h *MAC) Sum(b []byte) []byte { + var mac [TagSize]byte + h.mac.Sum(&mac) + h.finalized = true + return append(b, mac[:]...) +} + +// Verify returns whether the authenticator of all data written to +// the message authentication code matches the expected value. +func (h *MAC) Verify(expected []byte) bool { + var mac [TagSize]byte + h.mac.Sum(&mac) + h.finalized = true + return subtle.ConstantTimeCompare(expected, mac[:]) == 1 +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s new file mode 100644 index 0000000..1337573 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s @@ -0,0 +1,93 @@ +// Code generated by command: go run sum_amd64_asm.go -out ../sum_amd64.s -pkg poly1305. DO NOT EDIT. + +//go:build gc && !purego + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOVQ state+0(FP), DI + MOVQ msg_base+8(FP), SI + MOVQ msg_len+16(FP), R15 + MOVQ (DI), R8 + MOVQ 8(DI), R9 + MOVQ 16(DI), R10 + MOVQ 24(DI), R11 + MOVQ 32(DI), R12 + CMPQ R15, $0x10 + JB bytes_between_0_and_15 + +loop: + ADDQ (SI), R8 + ADCQ 8(SI), R9 + ADCQ $0x01, R10 + LEAQ 16(SI), SI + +multiply: + MOVQ R11, AX + MULQ R8 + MOVQ AX, BX + MOVQ DX, CX + MOVQ R11, AX + MULQ R9 + ADDQ AX, CX + ADCQ $0x00, DX + MOVQ R11, R13 + IMULQ R10, R13 + ADDQ DX, R13 + MOVQ R12, AX + MULQ R8 + ADDQ AX, CX + ADCQ $0x00, DX + MOVQ DX, R8 + MOVQ R12, R14 + IMULQ R10, R14 + MOVQ R12, AX + MULQ R9 + ADDQ AX, R13 + ADCQ DX, R14 + ADDQ R8, R13 + ADCQ $0x00, R14 + MOVQ BX, R8 + MOVQ CX, R9 + MOVQ R13, R10 + ANDQ $0x03, R10 + MOVQ R13, BX + ANDQ $-4, BX + ADDQ BX, R8 + ADCQ R14, R9 + ADCQ $0x00, R10 + SHRQ $0x02, R14, R13 + SHRQ $0x02, R14 + ADDQ R13, R8 + ADCQ R14, R9 + ADCQ $0x00, R10 + SUBQ $0x10, R15 + CMPQ R15, $0x10 + JAE loop + +bytes_between_0_and_15: + TESTQ R15, R15 + JZ done + MOVQ $0x00000001, BX + XORQ CX, CX + XORQ R13, R13 + ADDQ R15, SI + +flush_buffer: + SHLQ $0x08, BX, CX + SHLQ $0x08, BX + MOVB -1(SI), R13 + XORQ R13, BX + DECQ SI + DECQ R15 + JNZ flush_buffer + ADDQ BX, R8 + ADCQ CX, R9 + ADCQ $0x00, R10 + MOVQ $0x00000010, R15 + JMP multiply + +done: + MOVQ R8, (DI) + MOVQ R9, 8(DI) + MOVQ R10, 16(DI) + RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go new file mode 100644 index 0000000..315b84a --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go @@ -0,0 +1,47 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le) + +package poly1305 + +//go:noescape +func update(state *macState, msg []byte) + +// mac is a wrapper for macGeneric that redirects calls that would have gone to +// updateGeneric to update. +// +// Its Write and Sum methods are otherwise identical to the macGeneric ones, but +// using function pointers would carry a major performance cost. +type mac struct{ macGeneric } + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + update(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + update(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +func (h *mac) Sum(out *[16]byte) { + state := h.macState + if h.offset > 0 { + update(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go new file mode 100644 index 0000000..ec2202b --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go @@ -0,0 +1,312 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file provides the generic implementation of Sum and MAC. Other files +// might provide optimized assembly implementations of some of this code. + +package poly1305 + +import ( + "encoding/binary" + "math/bits" +) + +// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag +// for a 64 bytes message is approximately +// +// s + m[0:16] * r⁴ + m[16:32] * r³ + m[32:48] * r² + m[48:64] * r mod 2¹³⁰ - 5 +// +// for some secret r and s. It can be computed sequentially like +// +// for len(msg) > 0: +// h += read(msg, 16) +// h *= r +// h %= 2¹³⁰ - 5 +// return h + s +// +// All the complexity is about doing performant constant-time math on numbers +// larger than any available numeric type. + +func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { + h := newMACGeneric(key) + h.Write(msg) + h.Sum(out) +} + +func newMACGeneric(key *[32]byte) macGeneric { + m := macGeneric{} + initialize(key, &m.macState) + return m +} + +// macState holds numbers in saturated 64-bit little-endian limbs. That is, +// the value of [x0, x1, x2] is x[0] + x[1] * 2⁶⁴ + x[2] * 2¹²⁸. +type macState struct { + // h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but + // can grow larger during and after rounds. It must, however, remain below + // 2 * (2¹³⁰ - 5). + h [3]uint64 + // r and s are the private key components. + r [2]uint64 + s [2]uint64 +} + +type macGeneric struct { + macState + + buffer [TagSize]byte + offset int +} + +// Write splits the incoming message into TagSize chunks, and passes them to +// update. It buffers incomplete chunks. +func (h *macGeneric) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + updateGeneric(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + updateGeneric(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +// Sum flushes the last incomplete chunk from the buffer, if any, and generates +// the MAC output. It does not modify its state, in order to allow for multiple +// calls to Sum, even if no Write is allowed after Sum. +func (h *macGeneric) Sum(out *[TagSize]byte) { + state := h.macState + if h.offset > 0 { + updateGeneric(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} + +// [rMask0, rMask1] is the specified Poly1305 clamping mask in little-endian. It +// clears some bits of the secret coefficient to make it possible to implement +// multiplication more efficiently. +const ( + rMask0 = 0x0FFFFFFC0FFFFFFF + rMask1 = 0x0FFFFFFC0FFFFFFC +) + +// initialize loads the 256-bit key into the two 128-bit secret values r and s. +func initialize(key *[32]byte, m *macState) { + m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 + m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 + m.s[0] = binary.LittleEndian.Uint64(key[16:24]) + m.s[1] = binary.LittleEndian.Uint64(key[24:32]) +} + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +func add128(a, b uint128) uint128 { + lo, c := bits.Add64(a.lo, b.lo, 0) + hi, c := bits.Add64(a.hi, b.hi, c) + if c != 0 { + panic("poly1305: unexpected overflow") + } + return uint128{lo, hi} +} + +func shiftRightBy2(a uint128) uint128 { + a.lo = a.lo>>2 | (a.hi&3)<<62 + a.hi = a.hi >> 2 + return a +} + +// updateGeneric absorbs msg into the state.h accumulator. For each chunk m of +// 128 bits of message, it computes +// +// h₊ = (h + m) * r mod 2¹³⁰ - 5 +// +// If the msg length is not a multiple of TagSize, it assumes the last +// incomplete chunk is the final one. +func updateGeneric(state *macState, msg []byte) { + h0, h1, h2 := state.h[0], state.h[1], state.h[2] + r0, r1 := state.r[0], state.r[1] + + for len(msg) > 0 { + var c uint64 + + // For the first step, h + m, we use a chain of bits.Add64 intrinsics. + // The resulting value of h might exceed 2¹³⁰ - 5, but will be partially + // reduced at the end of the multiplication below. + // + // The spec requires us to set a bit just above the message size, not to + // hide leading zeroes. For full chunks, that's 1 << 128, so we can just + // add 1 to the most significant (2¹²⁸) limb, h2. + if len(msg) >= TagSize { + h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0) + h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c) + h2 += c + 1 + + msg = msg[TagSize:] + } else { + var buf [TagSize]byte + copy(buf[:], msg) + buf[len(msg)] = 1 + + h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0) + h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c) + h2 += c + + msg = nil + } + + // Multiplication of big number limbs is similar to elementary school + // columnar multiplication. Instead of digits, there are 64-bit limbs. + // + // We are multiplying a 3 limbs number, h, by a 2 limbs number, r. + // + // h2 h1 h0 x + // r1 r0 = + // ---------------- + // h2r0 h1r0 h0r0 <-- individual 128-bit products + // + h2r1 h1r1 h0r1 + // ------------------------ + // m3 m2 m1 m0 <-- result in 128-bit overlapping limbs + // ------------------------ + // m3.hi m2.hi m1.hi m0.hi <-- carry propagation + // + m3.lo m2.lo m1.lo m0.lo + // ------------------------------- + // t4 t3 t2 t1 t0 <-- final result in 64-bit limbs + // + // The main difference from pen-and-paper multiplication is that we do + // carry propagation in a separate step, as if we wrote two digit sums + // at first (the 128-bit limbs), and then carried the tens all at once. + + h0r0 := mul64(h0, r0) + h1r0 := mul64(h1, r0) + h2r0 := mul64(h2, r0) + h0r1 := mul64(h0, r1) + h1r1 := mul64(h1, r1) + h2r1 := mul64(h2, r1) + + // Since h2 is known to be at most 7 (5 + 1 + 1), and r0 and r1 have their + // top 4 bits cleared by rMask{0,1}, we know that their product is not going + // to overflow 64 bits, so we can ignore the high part of the products. + // + // This also means that the product doesn't have a fifth limb (t4). + if h2r0.hi != 0 { + panic("poly1305: unexpected overflow") + } + if h2r1.hi != 0 { + panic("poly1305: unexpected overflow") + } + + m0 := h0r0 + m1 := add128(h1r0, h0r1) // These two additions don't overflow thanks again + m2 := add128(h2r0, h1r1) // to the 4 masked bits at the top of r0 and r1. + m3 := h2r1 + + t0 := m0.lo + t1, c := bits.Add64(m1.lo, m0.hi, 0) + t2, c := bits.Add64(m2.lo, m1.hi, c) + t3, _ := bits.Add64(m3.lo, m2.hi, c) + + // Now we have the result as 4 64-bit limbs, and we need to reduce it + // modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do + // a cheap partial reduction according to the reduction identity + // + // c * 2¹³⁰ + n = c * 5 + n mod 2¹³⁰ - 5 + // + // because 2¹³⁰ = 5 mod 2¹³⁰ - 5. Partial reduction since the result is + // likely to be larger than 2¹³⁰ - 5, but still small enough to fit the + // assumptions we make about h in the rest of the code. + // + // See also https://speakerdeck.com/gtank/engineering-prime-numbers?slide=23 + + // We split the final result at the 2¹³⁰ mark into h and cc, the carry. + // Note that the carry bits are effectively shifted left by 2, in other + // words, cc = c * 4 for the c in the reduction identity. + h0, h1, h2 = t0, t1, t2&maskLow2Bits + cc := uint128{t2 & maskNotLow2Bits, t3} + + // To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c. + + h0, c = bits.Add64(h0, cc.lo, 0) + h1, c = bits.Add64(h1, cc.hi, c) + h2 += c + + cc = shiftRightBy2(cc) + + h0, c = bits.Add64(h0, cc.lo, 0) + h1, c = bits.Add64(h1, cc.hi, c) + h2 += c + + // h2 is at most 3 + 1 + 1 = 5, making the whole of h at most + // + // 5 * 2¹²⁸ + (2¹²⁸ - 1) = 6 * 2¹²⁸ - 1 + } + + state.h[0], state.h[1], state.h[2] = h0, h1, h2 +} + +const ( + maskLow2Bits uint64 = 0x0000000000000003 + maskNotLow2Bits uint64 = ^maskLow2Bits +) + +// select64 returns x if v == 1 and y if v == 0, in constant time. +func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y } + +// [p0, p1, p2] is 2¹³⁰ - 5 in little endian order. +const ( + p0 = 0xFFFFFFFFFFFFFFFB + p1 = 0xFFFFFFFFFFFFFFFF + p2 = 0x0000000000000003 +) + +// finalize completes the modular reduction of h and computes +// +// out = h + s mod 2¹²⁸ +func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) { + h0, h1, h2 := h[0], h[1], h[2] + + // After the partial reduction in updateGeneric, h might be more than + // 2¹³⁰ - 5, but will be less than 2 * (2¹³⁰ - 5). To complete the reduction + // in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the + // result if the subtraction underflows, and t otherwise. + + hMinusP0, b := bits.Sub64(h0, p0, 0) + hMinusP1, b := bits.Sub64(h1, p1, b) + _, b = bits.Sub64(h2, p2, b) + + // h = h if h < p else h - p + h0 = select64(b, h0, hMinusP0) + h1 = select64(b, h1, hMinusP1) + + // Finally, we compute the last Poly1305 step + // + // tag = h + s mod 2¹²⁸ + // + // by just doing a wide addition with the 128 low bits of h and discarding + // the overflow. + h0, c := bits.Add64(h0, s[0], 0) + h1, _ = bits.Add64(h1, s[1], c) + + binary.LittleEndian.PutUint64(out[0:8], h0) + binary.LittleEndian.PutUint64(out[8:16], h1) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s new file mode 100644 index 0000000..bc8361d --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s @@ -0,0 +1,123 @@ +// 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 gc && !purego + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOVV state+0(FP), R4 + MOVV msg_base+8(FP), R5 + MOVV msg_len+16(FP), R6 + + MOVV $0x10, R7 + + MOVV (R4), R8 // h0 + MOVV 8(R4), R9 // h1 + MOVV 16(R4), R10 // h2 + MOVV 24(R4), R11 // r0 + MOVV 32(R4), R12 // r1 + + BLT R6, R7, bytes_between_0_and_15 + +loop: + MOVV (R5), R14 // msg[0:8] + MOVV 8(R5), R16 // msg[8:16] + ADDV R14, R8, R8 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow) + ADDV R16, R9, R27 + SGTU R14, R8, R24 // h0.carry + SGTU R9, R27, R28 + ADDV R27, R24, R9 // h1 + SGTU R27, R9, R24 + OR R24, R28, R24 // h1.carry + ADDV $0x01, R24, R24 + ADDV R10, R24, R10 // h2 + + ADDV $16, R5, R5 // msg = msg[16:] + +multiply: + MULV R8, R11, R14 // h0r0.lo + MULHVU R8, R11, R15 // h0r0.hi + MULV R9, R11, R13 // h1r0.lo + MULHVU R9, R11, R16 // h1r0.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MULV R10, R11, R25 + ADDV R16, R25, R25 + MULV R8, R12, R13 // h0r1.lo + MULHVU R8, R12, R16 // h0r1.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MOVV R16, R8 + MULV R10, R12, R26 // h2r1 + MULV R9, R12, R13 // h1r1.lo + MULHVU R9, R12, R16 // h1r1.hi + ADDV R13, R25, R25 + ADDV R16, R26, R27 + SGTU R13, R25, R24 + ADDV R27, R24, R26 + ADDV R8, R25, R25 + SGTU R8, R25, R24 + ADDV R24, R26, R26 + AND $3, R25, R10 + AND $-4, R25, R17 + ADDV R17, R14, R8 + ADDV R26, R15, R27 + SGTU R17, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + SLLV $62, R26, R27 + SRLV $2, R25, R28 + SRLV $2, R26, R26 + OR R27, R28, R25 + ADDV R25, R8, R8 + ADDV R26, R9, R27 + SGTU R25, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + + SUBV $16, R6, R6 + BGE R6, R7, loop + +bytes_between_0_and_15: + BEQ R6, R0, done + MOVV $1, R14 + XOR R15, R15 + ADDV R6, R5, R5 + +flush_buffer: + MOVBU -1(R5), R25 + SRLV $56, R14, R24 + SLLV $8, R15, R28 + SLLV $8, R14, R14 + OR R24, R28, R15 + XOR R25, R14, R14 + SUBV $1, R6, R6 + SUBV $1, R5, R5 + BNE R6, R0, flush_buffer + + ADDV R14, R8, R8 + SGTU R14, R8, R24 + ADDV R15, R9, R27 + SGTU R15, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R10, R24, R10 + + MOVV $16, R6 + JMP multiply + +done: + MOVV R8, (R4) + MOVV R9, 8(R4) + MOVV R10, 16(R4) + RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s new file mode 100644 index 0000000..6899a1d --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s @@ -0,0 +1,187 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego && (ppc64 || ppc64le) + +#include "textflag.h" + +// This was ported from the amd64 implementation. + +#ifdef GOARCH_ppc64le +#define LE_MOVD MOVD +#define LE_MOVWZ MOVWZ +#define LE_MOVHZ MOVHZ +#else +#define LE_MOVD MOVDBR +#define LE_MOVWZ MOVWBR +#define LE_MOVHZ MOVHBR +#endif + +#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \ + LE_MOVD (msg)( R0), t0; \ + LE_MOVD (msg)(R24), t1; \ + MOVD $1, t2; \ + ADDC t0, h0, h0; \ + ADDE t1, h1, h1; \ + ADDE t2, h2; \ + ADD $16, msg + +#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ + MULLD r0, h0, t0; \ + MULHDU r0, h0, t1; \ + MULLD r0, h1, t4; \ + MULHDU r0, h1, t5; \ + ADDC t4, t1, t1; \ + MULLD r0, h2, t2; \ + MULHDU r1, h0, t4; \ + MULLD r1, h0, h0; \ + ADDE t5, t2, t2; \ + ADDC h0, t1, t1; \ + MULLD h2, r1, t3; \ + ADDZE t4, h0; \ + MULHDU r1, h1, t5; \ + MULLD r1, h1, t4; \ + ADDC t4, t2, t2; \ + ADDE t5, t3, t3; \ + ADDC h0, t2, t2; \ + MOVD $-4, t4; \ + ADDZE t3; \ + RLDICL $0, t2, $62, h2; \ + AND t2, t4, h0; \ + ADDC t0, h0, h0; \ + ADDE t3, t1, h1; \ + SLD $62, t3, t4; \ + SRD $2, t2; \ + ADDZE h2; \ + OR t4, t2, t2; \ + SRD $2, t3; \ + ADDC t2, h0, h0; \ + ADDE t3, h1, h1; \ + ADDZE h2 + +// func update(state *[7]uint64, msg []byte) +TEXT ·update(SB), $0-32 + MOVD state+0(FP), R3 + MOVD msg_base+8(FP), R4 + MOVD msg_len+16(FP), R5 + + MOVD 0(R3), R8 // h0 + MOVD 8(R3), R9 // h1 + MOVD 16(R3), R10 // h2 + MOVD 24(R3), R11 // r0 + MOVD 32(R3), R12 // r1 + + MOVD $8, R24 + + CMP R5, $16 + BLT bytes_between_0_and_15 + +loop: + POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) + + PCALIGN $16 +multiply: + POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) + ADD $-16, R5 + CMP R5, $16 + BGE loop + +bytes_between_0_and_15: + CMP R5, $0 + BEQ done + MOVD $0, R16 // h0 + MOVD $0, R17 // h1 + +flush_buffer: + CMP R5, $8 + BLE just1 + + MOVD $8, R21 + SUB R21, R5, R21 + + // Greater than 8 -- load the rightmost remaining bytes in msg + // and put into R17 (h1) + LE_MOVD (R4)(R21), R17 + MOVD $16, R22 + + // Find the offset to those bytes + SUB R5, R22, R22 + SLD $3, R22 + + // Shift to get only the bytes in msg + SRD R22, R17, R17 + + // Put 1 at high end + MOVD $1, R23 + SLD $3, R21 + SLD R21, R23, R23 + OR R23, R17, R17 + + // Remainder is 8 + MOVD $8, R5 + +just1: + CMP R5, $8 + BLT less8 + + // Exactly 8 + LE_MOVD (R4), R16 + + CMP R17, $0 + + // Check if we've already set R17; if not + // set 1 to indicate end of msg. + BNE carry + MOVD $1, R17 + BR carry + +less8: + MOVD $0, R16 // h0 + MOVD $0, R22 // shift count + CMP R5, $4 + BLT less4 + LE_MOVWZ (R4), R16 + ADD $4, R4 + ADD $-4, R5 + MOVD $32, R22 + +less4: + CMP R5, $2 + BLT less2 + LE_MOVHZ (R4), R21 + SLD R22, R21, R21 + OR R16, R21, R16 + ADD $16, R22 + ADD $-2, R5 + ADD $2, R4 + +less2: + CMP R5, $0 + BEQ insert1 + MOVBZ (R4), R21 + SLD R22, R21, R21 + OR R16, R21, R16 + ADD $8, R22 + +insert1: + // Insert 1 at end of msg + MOVD $1, R21 + SLD R22, R21, R21 + OR R16, R21, R16 + +carry: + // Add new values to h0, h1, h2 + ADDC R16, R8 + ADDE R17, R9 + ADDZE R10, R10 + MOVD $16, R5 + ADD R5, R4 + BR multiply + +done: + // Save h0, h1, h2 in state + MOVD R8, 0(R3) + MOVD R9, 8(R3) + MOVD R10, 16(R3) + RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go new file mode 100644 index 0000000..e1d033a --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go @@ -0,0 +1,76 @@ +// 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 gc && !purego + +package poly1305 + +import ( + "golang.org/x/sys/cpu" +) + +// updateVX is an assembly implementation of Poly1305 that uses vector +// instructions. It must only be called if the vector facility (vx) is +// available. +// +//go:noescape +func updateVX(state *macState, msg []byte) + +// mac is a replacement for macGeneric that uses a larger buffer and redirects +// calls that would have gone to updateGeneric to updateVX if the vector +// facility is installed. +// +// A larger buffer is required for good performance because the vector +// implementation has a higher fixed cost per call than the generic +// implementation. +type mac struct { + macState + + buffer [16 * TagSize]byte // size must be a multiple of block size (16) + offset int +} + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < len(h.buffer) { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + if cpu.S390X.HasVX { + updateVX(&h.macState, h.buffer[:]) + } else { + updateGeneric(&h.macState, h.buffer[:]) + } + } + + tail := len(p) % len(h.buffer) // number of bytes to copy into buffer + body := len(p) - tail // number of bytes to process now + if body > 0 { + if cpu.S390X.HasVX { + updateVX(&h.macState, p[:body]) + } else { + updateGeneric(&h.macState, p[:body]) + } + } + h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0 + return nn, nil +} + +func (h *mac) Sum(out *[TagSize]byte) { + state := h.macState + remainder := h.buffer[:h.offset] + + // Use the generic implementation if we have 2 or fewer blocks left + // to sum. The vector implementation has a higher startup time. + if cpu.S390X.HasVX && len(remainder) > 2*TagSize { + updateVX(&state, remainder) + } else if len(remainder) > 0 { + updateGeneric(&state, remainder) + } + finalize(out, &state.h, &state.s) +} diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s new file mode 100644 index 0000000..0fe3a7c --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s @@ -0,0 +1,503 @@ +// 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 gc && !purego + +#include "textflag.h" + +// This implementation of Poly1305 uses the vector facility (vx) +// to process up to 2 blocks (32 bytes) per iteration using an +// algorithm based on the one described in: +// +// NEON crypto, Daniel J. Bernstein & Peter Schwabe +// https://cryptojedi.org/papers/neoncrypto-20120320.pdf +// +// This algorithm uses 5 26-bit limbs to represent a 130-bit +// value. These limbs are, for the most part, zero extended and +// placed into 64-bit vector register elements. Each vector +// register is 128-bits wide and so holds 2 of these elements. +// Using 26-bit limbs allows us plenty of headroom to accommodate +// accumulations before and after multiplication without +// overflowing either 32-bits (before multiplication) or 64-bits +// (after multiplication). +// +// In order to parallelise the operations required to calculate +// the sum we use two separate accumulators and then sum those +// in an extra final step. For compatibility with the generic +// implementation we perform this summation at the end of every +// updateVX call. +// +// To use two accumulators we must multiply the message blocks +// by r² rather than r. Only the final message block should be +// multiplied by r. +// +// Example: +// +// We want to calculate the sum (h) for a 64 byte message (m): +// +// h = m[0:16]r⁴ + m[16:32]r³ + m[32:48]r² + m[48:64]r +// +// To do this we split the calculation into the even indices +// and odd indices of the message. These form our SIMD 'lanes': +// +// h = m[ 0:16]r⁴ + m[32:48]r² + <- lane 0 +// m[16:32]r³ + m[48:64]r <- lane 1 +// +// To calculate this iteratively we refactor so that both lanes +// are written in terms of r² and r: +// +// h = (m[ 0:16]r² + m[32:48])r² + <- lane 0 +// (m[16:32]r² + m[48:64])r <- lane 1 +// ^ ^ +// | coefficients for second iteration +// coefficients for first iteration +// +// So in this case we would have two iterations. In the first +// both lanes are multiplied by r². In the second only the +// first lane is multiplied by r² and the second lane is +// instead multiplied by r. This gives use the odd and even +// powers of r that we need from the original equation. +// +// Notation: +// +// h - accumulator +// r - key +// m - message +// +// [a, b] - SIMD register holding two 64-bit values +// [a, b, c, d] - SIMD register holding four 32-bit values +// xᵢ[n] - limb n of variable x with bit width i +// +// Limbs are expressed in little endian order, so for 26-bit +// limbs x₂₆[4] will be the most significant limb and x₂₆[0] +// will be the least significant limb. + +// masking constants +#define MOD24 V0 // [0x0000000000ffffff, 0x0000000000ffffff] - mask low 24-bits +#define MOD26 V1 // [0x0000000003ffffff, 0x0000000003ffffff] - mask low 26-bits + +// expansion constants (see EXPAND macro) +#define EX0 V2 +#define EX1 V3 +#define EX2 V4 + +// key (r², r or 1 depending on context) +#define R_0 V5 +#define R_1 V6 +#define R_2 V7 +#define R_3 V8 +#define R_4 V9 + +// precalculated coefficients (5r², 5r or 0 depending on context) +#define R5_1 V10 +#define R5_2 V11 +#define R5_3 V12 +#define R5_4 V13 + +// message block (m) +#define M_0 V14 +#define M_1 V15 +#define M_2 V16 +#define M_3 V17 +#define M_4 V18 + +// accumulator (h) +#define H_0 V19 +#define H_1 V20 +#define H_2 V21 +#define H_3 V22 +#define H_4 V23 + +// temporary registers (for short-lived values) +#define T_0 V24 +#define T_1 V25 +#define T_2 V26 +#define T_3 V27 +#define T_4 V28 + +GLOBL ·constants<>(SB), RODATA, $0x30 +// EX0 +DATA ·constants<>+0x00(SB)/8, $0x0006050403020100 +DATA ·constants<>+0x08(SB)/8, $0x1016151413121110 +// EX1 +DATA ·constants<>+0x10(SB)/8, $0x060c0b0a09080706 +DATA ·constants<>+0x18(SB)/8, $0x161c1b1a19181716 +// EX2 +DATA ·constants<>+0x20(SB)/8, $0x0d0d0d0d0d0f0e0d +DATA ·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d + +// MULTIPLY multiplies each lane of f and g, partially reduced +// modulo 2¹³⁰ - 5. The result, h, consists of partial products +// in each lane that need to be reduced further to produce the +// final result. +// +// h₁₃₀ = (f₁₃₀g₁₃₀) % 2¹³⁰ + (5f₁₃₀g₁₃₀) / 2¹³⁰ +// +// Note that the multiplication by 5 of the high bits is +// achieved by precalculating the multiplication of four of the +// g coefficients by 5. These are g51-g54. +#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ + VMLOF f0, g0, h0 \ + VMLOF f0, g3, h3 \ + VMLOF f0, g1, h1 \ + VMLOF f0, g4, h4 \ + VMLOF f0, g2, h2 \ + VMLOF f1, g54, T_0 \ + VMLOF f1, g2, T_3 \ + VMLOF f1, g0, T_1 \ + VMLOF f1, g3, T_4 \ + VMLOF f1, g1, T_2 \ + VMALOF f2, g53, h0, h0 \ + VMALOF f2, g1, h3, h3 \ + VMALOF f2, g54, h1, h1 \ + VMALOF f2, g2, h4, h4 \ + VMALOF f2, g0, h2, h2 \ + VMALOF f3, g52, T_0, T_0 \ + VMALOF f3, g0, T_3, T_3 \ + VMALOF f3, g53, T_1, T_1 \ + VMALOF f3, g1, T_4, T_4 \ + VMALOF f3, g54, T_2, T_2 \ + VMALOF f4, g51, h0, h0 \ + VMALOF f4, g54, h3, h3 \ + VMALOF f4, g52, h1, h1 \ + VMALOF f4, g0, h4, h4 \ + VMALOF f4, g53, h2, h2 \ + VAG T_0, h0, h0 \ + VAG T_3, h3, h3 \ + VAG T_1, h1, h1 \ + VAG T_4, h4, h4 \ + VAG T_2, h2, h2 + +// REDUCE performs the following carry operations in four +// stages, as specified in Bernstein & Schwabe: +// +// 1: h₂₆[0]->h₂₆[1] h₂₆[3]->h₂₆[4] +// 2: h₂₆[1]->h₂₆[2] h₂₆[4]->h₂₆[0] +// 3: h₂₆[0]->h₂₆[1] h₂₆[2]->h₂₆[3] +// 4: h₂₆[3]->h₂₆[4] +// +// The result is that all of the limbs are limited to 26-bits +// except for h₂₆[1] and h₂₆[4] which are limited to 27-bits. +// +// Note that although each limb is aligned at 26-bit intervals +// they may contain values that exceed 2²⁶ - 1, hence the need +// to carry the excess bits in each limb. +#define REDUCE(h0, h1, h2, h3, h4) \ + VESRLG $26, h0, T_0 \ + VESRLG $26, h3, T_1 \ + VN MOD26, h0, h0 \ + VN MOD26, h3, h3 \ + VAG T_0, h1, h1 \ + VAG T_1, h4, h4 \ + VESRLG $26, h1, T_2 \ + VESRLG $26, h4, T_3 \ + VN MOD26, h1, h1 \ + VN MOD26, h4, h4 \ + VESLG $2, T_3, T_4 \ + VAG T_3, T_4, T_4 \ + VAG T_2, h2, h2 \ + VAG T_4, h0, h0 \ + VESRLG $26, h2, T_0 \ + VESRLG $26, h0, T_1 \ + VN MOD26, h2, h2 \ + VN MOD26, h0, h0 \ + VAG T_0, h3, h3 \ + VAG T_1, h1, h1 \ + VESRLG $26, h3, T_2 \ + VN MOD26, h3, h3 \ + VAG T_2, h4, h4 + +// EXPAND splits the 128-bit little-endian values in0 and in1 +// into 26-bit big-endian limbs and places the results into +// the first and second lane of d₂₆[0:4] respectively. +// +// The EX0, EX1 and EX2 constants are arrays of byte indices +// for permutation. The permutation both reverses the bytes +// in the input and ensures the bytes are copied into the +// destination limb ready to be shifted into their final +// position. +#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ + VPERM in0, in1, EX0, d0 \ + VPERM in0, in1, EX1, d2 \ + VPERM in0, in1, EX2, d4 \ + VESRLG $26, d0, d1 \ + VESRLG $30, d2, d3 \ + VESRLG $4, d2, d2 \ + VN MOD26, d0, d0 \ // [in0₂₆[0], in1₂₆[0]] + VN MOD26, d3, d3 \ // [in0₂₆[3], in1₂₆[3]] + VN MOD26, d1, d1 \ // [in0₂₆[1], in1₂₆[1]] + VN MOD24, d4, d4 \ // [in0₂₆[4], in1₂₆[4]] + VN MOD26, d2, d2 // [in0₂₆[2], in1₂₆[2]] + +// func updateVX(state *macState, msg []byte) +TEXT ·updateVX(SB), NOSPLIT, $0 + MOVD state+0(FP), R1 + LMG msg+8(FP), R2, R3 // R2=msg_base, R3=msg_len + + // load EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + // generate masks + VGMG $(64-24), $63, MOD24 // [0x00ffffff, 0x00ffffff] + VGMG $(64-26), $63, MOD26 // [0x03ffffff, 0x03ffffff] + + // load h (accumulator) and r (key) from state + VZERO T_1 // [0, 0] + VL 0(R1), T_0 // [h₆₄[0], h₆₄[1]] + VLEG $0, 16(R1), T_1 // [h₆₄[2], 0] + VL 24(R1), T_2 // [r₆₄[0], r₆₄[1]] + VPDI $0, T_0, T_2, T_3 // [h₆₄[0], r₆₄[0]] + VPDI $5, T_0, T_2, T_4 // [h₆₄[1], r₆₄[1]] + + // unpack h and r into 26-bit limbs + // note: h₆₄[2] may have the low 3 bits set, so h₂₆[4] is a 27-bit value + VN MOD26, T_3, H_0 // [h₂₆[0], r₂₆[0]] + VZERO H_1 // [0, 0] + VZERO H_3 // [0, 0] + VGMG $(64-12-14), $(63-12), T_0 // [0x03fff000, 0x03fff000] - 26-bit mask with low 12 bits masked out + VESLG $24, T_1, T_1 // [h₆₄[2]<<24, 0] + VERIMG $-26&63, T_3, MOD26, H_1 // [h₂₆[1], r₂₆[1]] + VESRLG $+52&63, T_3, H_2 // [h₂₆[2], r₂₆[2]] - low 12 bits only + VERIMG $-14&63, T_4, MOD26, H_3 // [h₂₆[1], r₂₆[1]] + VESRLG $40, T_4, H_4 // [h₂₆[4], r₂₆[4]] - low 24 bits only + VERIMG $+12&63, T_4, T_0, H_2 // [h₂₆[2], r₂₆[2]] - complete + VO T_1, H_4, H_4 // [h₂₆[4], r₂₆[4]] - complete + + // replicate r across all 4 vector elements + VREPF $3, H_0, R_0 // [r₂₆[0], r₂₆[0], r₂₆[0], r₂₆[0]] + VREPF $3, H_1, R_1 // [r₂₆[1], r₂₆[1], r₂₆[1], r₂₆[1]] + VREPF $3, H_2, R_2 // [r₂₆[2], r₂₆[2], r₂₆[2], r₂₆[2]] + VREPF $3, H_3, R_3 // [r₂₆[3], r₂₆[3], r₂₆[3], r₂₆[3]] + VREPF $3, H_4, R_4 // [r₂₆[4], r₂₆[4], r₂₆[4], r₂₆[4]] + + // zero out lane 1 of h + VLEIG $1, $0, H_0 // [h₂₆[0], 0] + VLEIG $1, $0, H_1 // [h₂₆[1], 0] + VLEIG $1, $0, H_2 // [h₂₆[2], 0] + VLEIG $1, $0, H_3 // [h₂₆[3], 0] + VLEIG $1, $0, H_4 // [h₂₆[4], 0] + + // calculate 5r (ignore least significant limb) + VREPIF $5, T_0 + VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r₂₆[1], 5r₂₆[1], 5r₂₆[1]] + VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r₂₆[2], 5r₂₆[2], 5r₂₆[2]] + VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r₂₆[3], 5r₂₆[3], 5r₂₆[3]] + VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r₂₆[4], 5r₂₆[4], 5r₂₆[4]] + + // skip r² calculation if we are only calculating one block + CMPBLE R3, $16, skip + + // calculate r² + MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, M_0, M_1, M_2, M_3, M_4) + REDUCE(M_0, M_1, M_2, M_3, M_4) + VGBM $0x0f0f, T_0 + VERIMG $0, M_0, T_0, R_0 // [r₂₆[0], r²₂₆[0], r₂₆[0], r²₂₆[0]] + VERIMG $0, M_1, T_0, R_1 // [r₂₆[1], r²₂₆[1], r₂₆[1], r²₂₆[1]] + VERIMG $0, M_2, T_0, R_2 // [r₂₆[2], r²₂₆[2], r₂₆[2], r²₂₆[2]] + VERIMG $0, M_3, T_0, R_3 // [r₂₆[3], r²₂₆[3], r₂₆[3], r²₂₆[3]] + VERIMG $0, M_4, T_0, R_4 // [r₂₆[4], r²₂₆[4], r₂₆[4], r²₂₆[4]] + + // calculate 5r² (ignore least significant limb) + VREPIF $5, T_0 + VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r²₂₆[1], 5r₂₆[1], 5r²₂₆[1]] + VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r²₂₆[2], 5r₂₆[2], 5r²₂₆[2]] + VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r²₂₆[3], 5r₂₆[3], 5r²₂₆[3]] + VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r²₂₆[4], 5r₂₆[4], 5r²₂₆[4]] + +loop: + CMPBLE R3, $32, b2 // 2 or fewer blocks remaining, need to change key coefficients + + // load next 2 blocks from message + VLM (R2), T_0, T_1 + + // update message slice + SUB $32, R3 + MOVD $32(R2), R2 + + // unpack message blocks into 26-bit big-endian limbs + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // add 2¹²⁸ to each message block value + VLEIB $4, $1, M_4 + VLEIB $12, $1, M_4 + +multiply: + // accumulate the incoming message + VAG H_0, M_0, M_0 + VAG H_3, M_3, M_3 + VAG H_1, M_1, M_1 + VAG H_4, M_4, M_4 + VAG H_2, M_2, M_2 + + // multiply the accumulator by the key coefficient + MULTIPLY(M_0, M_1, M_2, M_3, M_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) + + // carry and partially reduce the partial products + REDUCE(H_0, H_1, H_2, H_3, H_4) + + CMPBNE R3, $0, loop + +finish: + // sum lane 0 and lane 1 and put the result in lane 1 + VZERO T_0 + VSUMQG H_0, T_0, H_0 + VSUMQG H_3, T_0, H_3 + VSUMQG H_1, T_0, H_1 + VSUMQG H_4, T_0, H_4 + VSUMQG H_2, T_0, H_2 + + // reduce again after summation + // TODO(mundaym): there might be a more efficient way to do this + // now that we only have 1 active lane. For example, we could + // simultaneously pack the values as we reduce them. + REDUCE(H_0, H_1, H_2, H_3, H_4) + + // carry h[1] through to h[4] so that only h[4] can exceed 2²⁶ - 1 + // TODO(mundaym): in testing this final carry was unnecessary. + // Needs a proof before it can be removed though. + VESRLG $26, H_1, T_1 + VN MOD26, H_1, H_1 + VAQ T_1, H_2, H_2 + VESRLG $26, H_2, T_2 + VN MOD26, H_2, H_2 + VAQ T_2, H_3, H_3 + VESRLG $26, H_3, T_3 + VN MOD26, H_3, H_3 + VAQ T_3, H_4, H_4 + + // h is now < 2(2¹³⁰ - 5) + // Pack each lane in h₂₆[0:4] into h₁₂₈[0:1]. + VESLG $26, H_1, H_1 + VESLG $26, H_3, H_3 + VO H_0, H_1, H_0 + VO H_2, H_3, H_2 + VESLG $4, H_2, H_2 + VLEIB $7, $48, H_1 + VSLB H_1, H_2, H_2 + VO H_0, H_2, H_0 + VLEIB $7, $104, H_1 + VSLB H_1, H_4, H_3 + VO H_3, H_0, H_0 + VLEIB $7, $24, H_1 + VSRLB H_1, H_4, H_1 + + // update state + VSTEG $1, H_0, 0(R1) + VSTEG $0, H_0, 8(R1) + VSTEG $1, H_1, 16(R1) + RET + +b2: // 2 or fewer blocks remaining + CMPBLE R3, $16, b1 + + // Load the 2 remaining blocks (17-32 bytes remaining). + MOVD $-17(R3), R0 // index of final byte to load modulo 16 + VL (R2), T_0 // load full 16 byte block + VLL R0, 16(R2), T_1 // load final (possibly partial) block and pad with zeros to 16 bytes + + // The Poly1305 algorithm requires that a 1 bit be appended to + // each message block. If the final block is less than 16 bytes + // long then it is easiest to insert the 1 before the message + // block is split into 26-bit limbs. If, on the other hand, the + // final message block is 16 bytes long then we append the 1 bit + // after expansion as normal. + MOVBZ $1, R0 + MOVD $-16(R3), R3 // index of byte in last block to insert 1 at (could be 16) + CMPBEQ R3, $16, 2(PC) // skip the insertion if the final block is 16 bytes long + VLVGB R3, R0, T_1 // insert 1 into the byte at index R3 + + // Split both blocks into 26-bit limbs in the appropriate lanes. + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // Append a 1 byte to the end of the second to last block. + VLEIB $4, $1, M_4 + + // Append a 1 byte to the end of the last block only if it is a + // full 16 byte block. + CMPBNE R3, $16, 2(PC) + VLEIB $12, $1, M_4 + + // Finally, set up the coefficients for the final multiplication. + // We have previously saved r and 5r in the 32-bit even indexes + // of the R_[0-4] and R5_[1-4] coefficient registers. + // + // We want lane 0 to be multiplied by r² so that can be kept the + // same. We want lane 1 to be multiplied by r so we need to move + // the saved r value into the 32-bit odd index in lane 1 by + // rotating the 64-bit lane by 32. + VGBM $0x00ff, T_0 // [0, 0xffffffffffffffff] - mask lane 1 only + VERIMG $32, R_0, T_0, R_0 // [_, r²₂₆[0], _, r₂₆[0]] + VERIMG $32, R_1, T_0, R_1 // [_, r²₂₆[1], _, r₂₆[1]] + VERIMG $32, R_2, T_0, R_2 // [_, r²₂₆[2], _, r₂₆[2]] + VERIMG $32, R_3, T_0, R_3 // [_, r²₂₆[3], _, r₂₆[3]] + VERIMG $32, R_4, T_0, R_4 // [_, r²₂₆[4], _, r₂₆[4]] + VERIMG $32, R5_1, T_0, R5_1 // [_, 5r²₂₆[1], _, 5r₂₆[1]] + VERIMG $32, R5_2, T_0, R5_2 // [_, 5r²₂₆[2], _, 5r₂₆[2]] + VERIMG $32, R5_3, T_0, R5_3 // [_, 5r²₂₆[3], _, 5r₂₆[3]] + VERIMG $32, R5_4, T_0, R5_4 // [_, 5r²₂₆[4], _, 5r₂₆[4]] + + MOVD $0, R3 + BR multiply + +skip: + CMPBEQ R3, $0, finish + +b1: // 1 block remaining + + // Load the final block (1-16 bytes). This will be placed into + // lane 0. + MOVD $-1(R3), R0 + VLL R0, (R2), T_0 // pad to 16 bytes with zeros + + // The Poly1305 algorithm requires that a 1 bit be appended to + // each message block. If the final block is less than 16 bytes + // long then it is easiest to insert the 1 before the message + // block is split into 26-bit limbs. If, on the other hand, the + // final message block is 16 bytes long then we append the 1 bit + // after expansion as normal. + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_0 + + // Set the message block in lane 1 to the value 0 so that it + // can be accumulated without affecting the final result. + VZERO T_1 + + // Split the final message block into 26-bit limbs in lane 0. + // Lane 1 will be contain 0. + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // Append a 1 byte to the end of the last block only if it is a + // full 16 byte block. + CMPBNE R3, $16, 2(PC) + VLEIB $4, $1, M_4 + + // We have previously saved r and 5r in the 32-bit even indexes + // of the R_[0-4] and R5_[1-4] coefficient registers. + // + // We want lane 0 to be multiplied by r so we need to move the + // saved r value into the 32-bit odd index in lane 0. We want + // lane 1 to be set to the value 1. This makes multiplication + // a no-op. We do this by setting lane 1 in every register to 0 + // and then just setting the 32-bit index 3 in R_0 to 1. + VZERO T_0 + MOVD $0, R0 + MOVD $0x10111213, R12 + VLVGP R12, R0, T_1 // [_, 0x10111213, _, 0x00000000] + VPERM T_0, R_0, T_1, R_0 // [_, r₂₆[0], _, 0] + VPERM T_0, R_1, T_1, R_1 // [_, r₂₆[1], _, 0] + VPERM T_0, R_2, T_1, R_2 // [_, r₂₆[2], _, 0] + VPERM T_0, R_3, T_1, R_3 // [_, r₂₆[3], _, 0] + VPERM T_0, R_4, T_1, R_4 // [_, r₂₆[4], _, 0] + VPERM T_0, R5_1, T_1, R5_1 // [_, 5r₂₆[1], _, 0] + VPERM T_0, R5_2, T_1, R5_2 // [_, 5r₂₆[2], _, 0] + VPERM T_0, R5_3, T_1, R5_3 // [_, 5r₂₆[3], _, 0] + VPERM T_0, R5_4, T_1, R5_4 // [_, 5r₂₆[4], _, 0] + + // Set the value of lane 1 to be 1. + VLEIF $3, $1, R_0 // [_, r₂₆[0], _, 1] + + MOVD $0, R3 + BR multiply diff --git a/vendor/golang.org/x/crypto/nacl/box/box.go b/vendor/golang.org/x/crypto/nacl/box/box.go new file mode 100644 index 0000000..357bdc7 --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/box/box.go @@ -0,0 +1,182 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package box authenticates and encrypts small messages using public-key cryptography. + +Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate +messages. The length of messages is not hidden. + +It is the caller's responsibility to ensure the uniqueness of nonces—for +example, by using nonce 1 for the first message, nonce 2 for the second +message, etc. Nonces are long enough that randomly generated nonces have +negligible risk of collision. + +Messages should be small because: + +1. The whole message needs to be held in memory to be processed. + +2. Using large messages pressures implementations on small machines to decrypt +and process plaintext before authenticating it. This is very dangerous, and +this API does not allow it, but a protocol that uses excessive message sizes +might present some implementations with no other choice. + +3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. + +4. Performance may be improved by working with messages that fit into data caches. + +Thus large amounts of data should be chunked so that each message is small. +(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable +chunk size. + +This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. +Anonymous sealing/opening is an extension of NaCl defined by and interoperable +with libsodium: +https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes. +*/ +package box + +import ( + cryptorand "crypto/rand" + "io" + + "golang.org/x/crypto/blake2b" + "golang.org/x/crypto/curve25519" + "golang.org/x/crypto/nacl/secretbox" + "golang.org/x/crypto/salsa20/salsa" +) + +const ( + // Overhead is the number of bytes of overhead when boxing a message. + Overhead = secretbox.Overhead + + // AnonymousOverhead is the number of bytes of overhead when using anonymous + // sealed boxes. + AnonymousOverhead = Overhead + 32 +) + +// GenerateKey generates a new public/private key pair suitable for use with +// Seal and Open. +func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { + publicKey = new([32]byte) + privateKey = new([32]byte) + _, err = io.ReadFull(rand, privateKey[:]) + if err != nil { + publicKey = nil + privateKey = nil + return + } + + curve25519.ScalarBaseMult(publicKey, privateKey) + return +} + +var zeros [16]byte + +// Precompute calculates the shared key between peersPublicKey and privateKey +// and writes it to sharedKey. The shared key can be used with +// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing +// when using the same pair of keys repeatedly. +func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { + curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) + salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) +} + +// Seal appends an encrypted and authenticated copy of message to out, which +// will be Overhead bytes longer than the original and must not overlap it. The +// nonce must be unique for each distinct message for a given pair of keys. +func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { + var sharedKey [32]byte + Precompute(&sharedKey, peersPublicKey, privateKey) + return secretbox.Seal(out, message, nonce, &sharedKey) +} + +// SealAfterPrecomputation performs the same actions as Seal, but takes a +// shared key as generated by Precompute. +func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { + return secretbox.Seal(out, message, nonce, sharedKey) +} + +// Open authenticates and decrypts a box produced by Seal and appends the +// message to out, which must not overlap box. The output will be Overhead +// bytes smaller than box. +func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { + var sharedKey [32]byte + Precompute(&sharedKey, peersPublicKey, privateKey) + return secretbox.Open(out, box, nonce, &sharedKey) +} + +// OpenAfterPrecomputation performs the same actions as Open, but takes a +// shared key as generated by Precompute. +func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { + return secretbox.Open(out, box, nonce, sharedKey) +} + +// SealAnonymous appends an encrypted and authenticated copy of message to out, +// which will be AnonymousOverhead bytes longer than the original and must not +// overlap it. This differs from Seal in that the sender is not required to +// provide a private key. +func SealAnonymous(out, message []byte, recipient *[32]byte, rand io.Reader) ([]byte, error) { + if rand == nil { + rand = cryptorand.Reader + } + ephemeralPub, ephemeralPriv, err := GenerateKey(rand) + if err != nil { + return nil, err + } + + var nonce [24]byte + if err := sealNonce(ephemeralPub, recipient, &nonce); err != nil { + return nil, err + } + + if total := len(out) + AnonymousOverhead + len(message); cap(out) < total { + original := out + out = make([]byte, 0, total) + out = append(out, original...) + } + out = append(out, ephemeralPub[:]...) + + return Seal(out, message, &nonce, recipient, ephemeralPriv), nil +} + +// OpenAnonymous authenticates and decrypts a box produced by SealAnonymous and +// appends the message to out, which must not overlap box. The output will be +// AnonymousOverhead bytes smaller than box. +func OpenAnonymous(out, box []byte, publicKey, privateKey *[32]byte) (message []byte, ok bool) { + if len(box) < AnonymousOverhead { + return nil, false + } + + var ephemeralPub [32]byte + copy(ephemeralPub[:], box[:32]) + + var nonce [24]byte + if err := sealNonce(&ephemeralPub, publicKey, &nonce); err != nil { + return nil, false + } + + return Open(out, box[32:], &nonce, &ephemeralPub, privateKey) +} + +// sealNonce generates a 24 byte nonce that is a blake2b digest of the +// ephemeral public key and the receiver's public key. +func sealNonce(ephemeralPub, peersPublicKey *[32]byte, nonce *[24]byte) error { + h, err := blake2b.New(24, nil) + if err != nil { + return err + } + + if _, err = h.Write(ephemeralPub[:]); err != nil { + return err + } + + if _, err = h.Write(peersPublicKey[:]); err != nil { + return err + } + + h.Sum(nonce[:0]) + + return nil +} diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go new file mode 100644 index 0000000..1fe600a --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go @@ -0,0 +1,173 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package secretbox encrypts and authenticates small messages. + +Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with +secret-key cryptography. The length of messages is not hidden. + +It is the caller's responsibility to ensure the uniqueness of nonces—for +example, by using nonce 1 for the first message, nonce 2 for the second +message, etc. Nonces are long enough that randomly generated nonces have +negligible risk of collision. + +Messages should be small because: + +1. The whole message needs to be held in memory to be processed. + +2. Using large messages pressures implementations on small machines to decrypt +and process plaintext before authenticating it. This is very dangerous, and +this API does not allow it, but a protocol that uses excessive message sizes +might present some implementations with no other choice. + +3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. + +4. Performance may be improved by working with messages that fit into data caches. + +Thus large amounts of data should be chunked so that each message is small. +(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable +chunk size. + +This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. +*/ +package secretbox + +import ( + "golang.org/x/crypto/internal/alias" + "golang.org/x/crypto/internal/poly1305" + "golang.org/x/crypto/salsa20/salsa" +) + +// Overhead is the number of bytes of overhead when boxing a message. +const Overhead = poly1305.TagSize + +// setup produces a sub-key and Salsa20 counter given a nonce and key. +func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { + // We use XSalsa20 for encryption so first we need to generate a + // key and nonce with HSalsa20. + var hNonce [16]byte + copy(hNonce[:], nonce[:]) + salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) + + // The final 8 bytes of the original nonce form the new nonce. + copy(counter[:], nonce[16:]) +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// Seal appends an encrypted and authenticated copy of message to out, which +// must not overlap message. The key and nonce pair must be unique for each +// distinct message and the output will be Overhead bytes longer than message. +func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { + var subKey [32]byte + var counter [16]byte + setup(&subKey, &counter, nonce, key) + + // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since + // Salsa20 works with 64-byte blocks, we also generate 32 bytes of + // keystream as a side effect. + var firstBlock [64]byte + salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) + + var poly1305Key [32]byte + copy(poly1305Key[:], firstBlock[:]) + + ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) + if alias.AnyOverlap(out, message) { + panic("nacl: invalid buffer overlap") + } + + // We XOR up to 32 bytes of message with the keystream generated from + // the first block. + firstMessageBlock := message + if len(firstMessageBlock) > 32 { + firstMessageBlock = firstMessageBlock[:32] + } + + tagOut := out + out = out[poly1305.TagSize:] + for i, x := range firstMessageBlock { + out[i] = firstBlock[32+i] ^ x + } + message = message[len(firstMessageBlock):] + ciphertext := out + out = out[len(firstMessageBlock):] + + // Now encrypt the rest. + counter[8] = 1 + salsa.XORKeyStream(out, message, &counter, &subKey) + + var tag [poly1305.TagSize]byte + poly1305.Sum(&tag, ciphertext, &poly1305Key) + copy(tagOut, tag[:]) + + return ret +} + +// Open authenticates and decrypts a box produced by Seal and appends the +// message to out, which must not overlap box. The output will be Overhead +// bytes smaller than box. +func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { + if len(box) < Overhead { + return nil, false + } + + var subKey [32]byte + var counter [16]byte + setup(&subKey, &counter, nonce, key) + + // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since + // Salsa20 works with 64-byte blocks, we also generate 32 bytes of + // keystream as a side effect. + var firstBlock [64]byte + salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) + + var poly1305Key [32]byte + copy(poly1305Key[:], firstBlock[:]) + var tag [poly1305.TagSize]byte + copy(tag[:], box) + + if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { + return nil, false + } + + ret, out := sliceForAppend(out, len(box)-Overhead) + if alias.AnyOverlap(out, box) { + panic("nacl: invalid buffer overlap") + } + + // We XOR up to 32 bytes of box with the keystream generated from + // the first block. + box = box[Overhead:] + firstMessageBlock := box + if len(firstMessageBlock) > 32 { + firstMessageBlock = firstMessageBlock[:32] + } + for i, x := range firstMessageBlock { + out[i] = firstBlock[32+i] ^ x + } + + box = box[len(firstMessageBlock):] + out = out[len(firstMessageBlock):] + + // Now decrypt the rest. + counter[8] = 1 + salsa.XORKeyStream(out, box, &counter, &subKey) + + return ret, true +} diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go new file mode 100644 index 0000000..e6c645e --- /dev/null +++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go @@ -0,0 +1,793 @@ +// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses +// are signed messages attesting to the validity of a certificate for a small +// period of time. This is used to manage revocation for X.509 certificates. +package ocsp + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" + "errors" + "fmt" + "math/big" + "strconv" + "time" +) + +var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) + +// ResponseStatus contains the result of an OCSP request. See +// https://tools.ietf.org/html/rfc6960#section-2.3 +type ResponseStatus int + +const ( + Success ResponseStatus = 0 + Malformed ResponseStatus = 1 + InternalError ResponseStatus = 2 + TryLater ResponseStatus = 3 + // Status code four is unused in OCSP. See + // https://tools.ietf.org/html/rfc6960#section-4.2.1 + SignatureRequired ResponseStatus = 5 + Unauthorized ResponseStatus = 6 +) + +func (r ResponseStatus) String() string { + switch r { + case Success: + return "success" + case Malformed: + return "malformed" + case InternalError: + return "internal error" + case TryLater: + return "try later" + case SignatureRequired: + return "signature required" + case Unauthorized: + return "unauthorized" + default: + return "unknown OCSP status: " + strconv.Itoa(int(r)) + } +} + +// ResponseError is an error that may be returned by ParseResponse to indicate +// that the response itself is an error, not just that it's indicating that a +// certificate is revoked, unknown, etc. +type ResponseError struct { + Status ResponseStatus +} + +func (r ResponseError) Error() string { + return "ocsp: error from server: " + r.Status.String() +} + +// These are internal structures that reflect the ASN.1 structure of an OCSP +// response. See RFC 2560, section 4.2. + +type certID struct { + HashAlgorithm pkix.AlgorithmIdentifier + NameHash []byte + IssuerKeyHash []byte + SerialNumber *big.Int +} + +// https://tools.ietf.org/html/rfc2560#section-4.1.1 +type ocspRequest struct { + TBSRequest tbsRequest +} + +type tbsRequest struct { + Version int `asn1:"explicit,tag:0,default:0,optional"` + RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` + RequestList []request +} + +type request struct { + Cert certID +} + +type responseASN1 struct { + Status asn1.Enumerated + Response responseBytes `asn1:"explicit,tag:0,optional"` +} + +type responseBytes struct { + ResponseType asn1.ObjectIdentifier + Response []byte +} + +type basicResponse struct { + TBSResponseData responseData + SignatureAlgorithm pkix.AlgorithmIdentifier + Signature asn1.BitString + Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` +} + +type responseData struct { + Raw asn1.RawContent + Version int `asn1:"optional,default:0,explicit,tag:0"` + RawResponderID asn1.RawValue + ProducedAt time.Time `asn1:"generalized"` + Responses []singleResponse +} + +type singleResponse struct { + CertID certID + Good asn1.Flag `asn1:"tag:0,optional"` + Revoked revokedInfo `asn1:"tag:1,optional"` + Unknown asn1.Flag `asn1:"tag:2,optional"` + ThisUpdate time.Time `asn1:"generalized"` + NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` + SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` +} + +type revokedInfo struct { + RevocationTime time.Time `asn1:"generalized"` + Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` +} + +var ( + oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} + oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} + oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} + oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} + oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} + oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} + oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} + oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} + oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} + oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} + oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} + oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} +) + +var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ + crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), + crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), + crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), + crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), +} + +// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below +var signatureAlgorithmDetails = []struct { + algo x509.SignatureAlgorithm + oid asn1.ObjectIdentifier + pubKeyAlgo x509.PublicKeyAlgorithm + hash crypto.Hash +}{ + {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, + {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, + {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, + {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, + {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, + {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, + {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, + {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, + {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, + {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, + {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, + {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, +} + +// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below +func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { + var pubType x509.PublicKeyAlgorithm + + switch pub := pub.(type) { + case *rsa.PublicKey: + pubType = x509.RSA + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureSHA256WithRSA + sigAlgo.Parameters = asn1.RawValue{ + Tag: 5, + } + + case *ecdsa.PublicKey: + pubType = x509.ECDSA + + switch pub.Curve { + case elliptic.P224(), elliptic.P256(): + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 + case elliptic.P384(): + hashFunc = crypto.SHA384 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 + case elliptic.P521(): + hashFunc = crypto.SHA512 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 + default: + err = errors.New("x509: unknown elliptic curve") + } + + default: + err = errors.New("x509: only RSA and ECDSA keys supported") + } + + if err != nil { + return + } + + if requestedSigAlgo == 0 { + return + } + + found := false + for _, details := range signatureAlgorithmDetails { + if details.algo == requestedSigAlgo { + if details.pubKeyAlgo != pubType { + err = errors.New("x509: requested SignatureAlgorithm does not match private key type") + return + } + sigAlgo.Algorithm, hashFunc = details.oid, details.hash + if hashFunc == 0 { + err = errors.New("x509: cannot sign with hash function requested") + return + } + found = true + break + } + } + + if !found { + err = errors.New("x509: unknown SignatureAlgorithm") + } + + return +} + +// TODO(agl): this is taken from crypto/x509 and so should probably be exported +// from crypto/x509 or crypto/x509/pkix. +func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { + for _, details := range signatureAlgorithmDetails { + if oid.Equal(details.oid) { + return details.algo + } + } + return x509.UnknownSignatureAlgorithm +} + +// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. +func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { + for hash, oid := range hashOIDs { + if oid.Equal(target) { + return hash + } + } + return crypto.Hash(0) +} + +func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { + for hash, oid := range hashOIDs { + if hash == target { + return oid + } + } + return nil +} + +// This is the exposed reflection of the internal OCSP structures. + +// The status values that can be expressed in OCSP. See RFC 6960. +// These are used for the Response.Status field. +const ( + // Good means that the certificate is valid. + Good = 0 + // Revoked means that the certificate has been deliberately revoked. + Revoked = 1 + // Unknown means that the OCSP responder doesn't know about the certificate. + Unknown = 2 + // ServerFailed is unused and was never used (see + // https://go-review.googlesource.com/#/c/18944). ParseResponse will + // return a ResponseError when an error response is parsed. + ServerFailed = 3 +) + +// The enumerated reasons for revoking a certificate. See RFC 5280. +const ( + Unspecified = 0 + KeyCompromise = 1 + CACompromise = 2 + AffiliationChanged = 3 + Superseded = 4 + CessationOfOperation = 5 + CertificateHold = 6 + + RemoveFromCRL = 8 + PrivilegeWithdrawn = 9 + AACompromise = 10 +) + +// Request represents an OCSP request. See RFC 6960. +type Request struct { + HashAlgorithm crypto.Hash + IssuerNameHash []byte + IssuerKeyHash []byte + SerialNumber *big.Int +} + +// Marshal marshals the OCSP request to ASN.1 DER encoded form. +func (req *Request) Marshal() ([]byte, error) { + hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm) + if hashAlg == nil { + return nil, errors.New("Unknown hash algorithm") + } + return asn1.Marshal(ocspRequest{ + tbsRequest{ + Version: 0, + RequestList: []request{ + { + Cert: certID{ + pkix.AlgorithmIdentifier{ + Algorithm: hashAlg, + Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, + }, + req.IssuerNameHash, + req.IssuerKeyHash, + req.SerialNumber, + }, + }, + }, + }, + }) +} + +// Response represents an OCSP response containing a single SingleResponse. See +// RFC 6960. +type Response struct { + Raw []byte + + // Status is one of {Good, Revoked, Unknown} + Status int + SerialNumber *big.Int + ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time + RevocationReason int + Certificate *x509.Certificate + // TBSResponseData contains the raw bytes of the signed response. If + // Certificate is nil then this can be used to verify Signature. + TBSResponseData []byte + Signature []byte + SignatureAlgorithm x509.SignatureAlgorithm + + // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash. + // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512. + // If zero, the default is crypto.SHA1. + IssuerHash crypto.Hash + + // RawResponderName optionally contains the DER-encoded subject of the + // responder certificate. Exactly one of RawResponderName and + // ResponderKeyHash is set. + RawResponderName []byte + // ResponderKeyHash optionally contains the SHA-1 hash of the + // responder's public key. Exactly one of RawResponderName and + // ResponderKeyHash is set. + ResponderKeyHash []byte + + // Extensions contains raw X.509 extensions from the singleExtensions field + // of the OCSP response. When parsing certificates, this can be used to + // extract non-critical extensions that are not parsed by this package. When + // marshaling OCSP responses, the Extensions field is ignored, see + // ExtraExtensions. + Extensions []pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any marshaled + // OCSP response (in the singleExtensions field). Values override any + // extensions that would otherwise be produced based on the other fields. The + // ExtraExtensions field is not populated when parsing certificates, see + // Extensions. + ExtraExtensions []pkix.Extension +} + +// These are pre-serialized error responses for the various non-success codes +// defined by OCSP. The Unauthorized code in particular can be used by an OCSP +// responder that supports only pre-signed responses as a response to requests +// for certificates with unknown status. See RFC 5019. +var ( + MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} + InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} + TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} + SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} + UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} +) + +// CheckSignatureFrom checks that the signature in resp is a valid signature +// from issuer. This should only be used if resp.Certificate is nil. Otherwise, +// the OCSP response contained an intermediate certificate that created the +// signature. That signature is checked by ParseResponse and only +// resp.Certificate remains to be validated. +func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { + return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) +} + +// ParseError results from an invalid OCSP response. +type ParseError string + +func (p ParseError) Error() string { + return string(p) +} + +// ParseRequest parses an OCSP request in DER form. It only supports +// requests for a single certificate. Signed requests are not supported. +// If a request includes a signature, it will result in a ParseError. +func ParseRequest(bytes []byte) (*Request, error) { + var req ocspRequest + rest, err := asn1.Unmarshal(bytes, &req) + if err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, ParseError("trailing data in OCSP request") + } + + if len(req.TBSRequest.RequestList) == 0 { + return nil, ParseError("OCSP request contains no request body") + } + innerRequest := req.TBSRequest.RequestList[0] + + hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) + if hashFunc == crypto.Hash(0) { + return nil, ParseError("OCSP request uses unknown hash function") + } + + return &Request{ + HashAlgorithm: hashFunc, + IssuerNameHash: innerRequest.Cert.NameHash, + IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, + SerialNumber: innerRequest.Cert.SerialNumber, + }, nil +} + +// ParseResponse parses an OCSP response in DER form. The response must contain +// only one certificate status. To parse the status of a specific certificate +// from a response which may contain multiple statuses, use ParseResponseForCert +// instead. +// +// If the response contains an embedded certificate, then that certificate will +// be used to verify the response signature. If the response contains an +// embedded certificate and issuer is not nil, then issuer will be used to verify +// the signature on the embedded certificate. +// +// If the response does not contain an embedded certificate and issuer is not +// nil, then issuer will be used to verify the response signature. +// +// Invalid responses and parse failures will result in a ParseError. +// Error responses will result in a ResponseError. +func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { + return ParseResponseForCert(bytes, nil, issuer) +} + +// ParseResponseForCert acts identically to ParseResponse, except it supports +// parsing responses that contain multiple statuses. If the response contains +// multiple statuses and cert is not nil, then ParseResponseForCert will return +// the first status which contains a matching serial, otherwise it will return an +// error. If cert is nil, then the first status in the response will be returned. +func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { + var resp responseASN1 + rest, err := asn1.Unmarshal(bytes, &resp) + if err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, ParseError("trailing data in OCSP response") + } + + if status := ResponseStatus(resp.Status); status != Success { + return nil, ResponseError{status} + } + + if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { + return nil, ParseError("bad OCSP response type") + } + + var basicResp basicResponse + rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) + if err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, ParseError("trailing data in OCSP response") + } + + if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { + return nil, ParseError("OCSP response contains bad number of responses") + } + + var singleResp singleResponse + if cert == nil { + singleResp = basicResp.TBSResponseData.Responses[0] + } else { + match := false + for _, resp := range basicResp.TBSResponseData.Responses { + if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 { + singleResp = resp + match = true + break + } + } + if !match { + return nil, ParseError("no response matching the supplied certificate") + } + } + + ret := &Response{ + Raw: bytes, + TBSResponseData: basicResp.TBSResponseData.Raw, + Signature: basicResp.Signature.RightAlign(), + SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), + Extensions: singleResp.SingleExtensions, + SerialNumber: singleResp.CertID.SerialNumber, + ProducedAt: basicResp.TBSResponseData.ProducedAt, + ThisUpdate: singleResp.ThisUpdate, + NextUpdate: singleResp.NextUpdate, + } + + // Handle the ResponderID CHOICE tag. ResponderID can be flattened into + // TBSResponseData once https://go-review.googlesource.com/34503 has been + // released. + rawResponderID := basicResp.TBSResponseData.RawResponderID + switch rawResponderID.Tag { + case 1: // Name + var rdn pkix.RDNSequence + if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 { + return nil, ParseError("invalid responder name") + } + ret.RawResponderName = rawResponderID.Bytes + case 2: // KeyHash + if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 { + return nil, ParseError("invalid responder key hash") + } + default: + return nil, ParseError("invalid responder id tag") + } + + if len(basicResp.Certificates) > 0 { + // Responders should only send a single certificate (if they + // send any) that connects the responder's certificate to the + // original issuer. We accept responses with multiple + // certificates due to a number responders sending them[1], but + // ignore all but the first. + // + // [1] https://github.com/golang/go/issues/21527 + ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) + if err != nil { + return nil, err + } + + if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { + return nil, ParseError("bad signature on embedded certificate: " + err.Error()) + } + + if issuer != nil { + if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { + return nil, ParseError("bad OCSP signature: " + err.Error()) + } + } + } else if issuer != nil { + if err := ret.CheckSignatureFrom(issuer); err != nil { + return nil, ParseError("bad OCSP signature: " + err.Error()) + } + } + + for _, ext := range singleResp.SingleExtensions { + if ext.Critical { + return nil, ParseError("unsupported critical extension") + } + } + + for h, oid := range hashOIDs { + if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) { + ret.IssuerHash = h + break + } + } + if ret.IssuerHash == 0 { + return nil, ParseError("unsupported issuer hash algorithm") + } + + switch { + case bool(singleResp.Good): + ret.Status = Good + case bool(singleResp.Unknown): + ret.Status = Unknown + default: + ret.Status = Revoked + ret.RevokedAt = singleResp.Revoked.RevocationTime + ret.RevocationReason = int(singleResp.Revoked.Reason) + } + + return ret, nil +} + +// RequestOptions contains options for constructing OCSP requests. +type RequestOptions struct { + // Hash contains the hash function that should be used when + // constructing the OCSP request. If zero, SHA-1 will be used. + Hash crypto.Hash +} + +func (opts *RequestOptions) hash() crypto.Hash { + if opts == nil || opts.Hash == 0 { + // SHA-1 is nearly universally used in OCSP. + return crypto.SHA1 + } + return opts.Hash +} + +// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If +// opts is nil then sensible defaults are used. +func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { + hashFunc := opts.hash() + + // OCSP seems to be the only place where these raw hash identifiers are + // used. I took the following from + // http://msdn.microsoft.com/en-us/library/ff635603.aspx + _, ok := hashOIDs[hashFunc] + if !ok { + return nil, x509.ErrUnsupportedAlgorithm + } + + if !hashFunc.Available() { + return nil, x509.ErrUnsupportedAlgorithm + } + h := opts.hash().New() + + var publicKeyInfo struct { + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString + } + if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { + return nil, err + } + + h.Write(publicKeyInfo.PublicKey.RightAlign()) + issuerKeyHash := h.Sum(nil) + + h.Reset() + h.Write(issuer.RawSubject) + issuerNameHash := h.Sum(nil) + + req := &Request{ + HashAlgorithm: hashFunc, + IssuerNameHash: issuerNameHash, + IssuerKeyHash: issuerKeyHash, + SerialNumber: cert.SerialNumber, + } + return req.Marshal() +} + +// CreateResponse returns a DER-encoded OCSP response with the specified contents. +// The fields in the response are populated as follows: +// +// The responder cert is used to populate the responder's name field, and the +// certificate itself is provided alongside the OCSP response signature. +// +// The issuer cert is used to populate the IssuerNameHash and IssuerKeyHash fields. +// +// The template is used to populate the SerialNumber, Status, RevokedAt, +// RevocationReason, ThisUpdate, and NextUpdate fields. +// +// If template.IssuerHash is not set, SHA1 will be used. +// +// The ProducedAt date is automatically set to the current date, to the nearest minute. +func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { + var publicKeyInfo struct { + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString + } + if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { + return nil, err + } + + if template.IssuerHash == 0 { + template.IssuerHash = crypto.SHA1 + } + hashOID := getOIDFromHashAlgorithm(template.IssuerHash) + if hashOID == nil { + return nil, errors.New("unsupported issuer hash algorithm") + } + + if !template.IssuerHash.Available() { + return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash) + } + h := template.IssuerHash.New() + h.Write(publicKeyInfo.PublicKey.RightAlign()) + issuerKeyHash := h.Sum(nil) + + h.Reset() + h.Write(issuer.RawSubject) + issuerNameHash := h.Sum(nil) + + innerResponse := singleResponse{ + CertID: certID{ + HashAlgorithm: pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, + }, + NameHash: issuerNameHash, + IssuerKeyHash: issuerKeyHash, + SerialNumber: template.SerialNumber, + }, + ThisUpdate: template.ThisUpdate.UTC(), + NextUpdate: template.NextUpdate.UTC(), + SingleExtensions: template.ExtraExtensions, + } + + switch template.Status { + case Good: + innerResponse.Good = true + case Unknown: + innerResponse.Unknown = true + case Revoked: + innerResponse.Revoked = revokedInfo{ + RevocationTime: template.RevokedAt.UTC(), + Reason: asn1.Enumerated(template.RevocationReason), + } + } + + rawResponderID := asn1.RawValue{ + Class: 2, // context-specific + Tag: 1, // Name (explicit tag) + IsCompound: true, + Bytes: responderCert.RawSubject, + } + tbsResponseData := responseData{ + Version: 0, + RawResponderID: rawResponderID, + ProducedAt: time.Now().Truncate(time.Minute).UTC(), + Responses: []singleResponse{innerResponse}, + } + + tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) + if err != nil { + return nil, err + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + responseHash := hashFunc.New() + responseHash.Write(tbsResponseDataDER) + signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) + if err != nil { + return nil, err + } + + response := basicResponse{ + TBSResponseData: tbsResponseData, + SignatureAlgorithm: signatureAlgorithm, + Signature: asn1.BitString{ + Bytes: signature, + BitLength: 8 * len(signature), + }, + } + if template.Certificate != nil { + response.Certificates = []asn1.RawValue{ + {FullBytes: template.Certificate.Raw}, + } + } + responseDER, err := asn1.Marshal(response) + if err != nil { + return nil, err + } + + return asn1.Marshal(responseASN1{ + Status: asn1.Enumerated(Success), + Response: responseBytes{ + ResponseType: idPKIXOCSPBasic, + Response: responseDER, + }, + }) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go new file mode 100644 index 0000000..75df774 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go @@ -0,0 +1,150 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package salsa provides low-level access to functions in the Salsa family. +// +// Deprecated: this package exposes unsafe low-level operations. New applications +// should consider using the AEAD construction in golang.org/x/crypto/chacha20poly1305 +// instead. Existing users should migrate to golang.org/x/crypto/salsa20. +package salsa + +import "math/bits" + +// Sigma is the Salsa20 constant for 256-bit keys. +var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} + +// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte +// key k, and 16-byte constant c, and puts the result into the 32-byte array +// out. +func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { + x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 + x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 + x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 + x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 + x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 + x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 + x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 + x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 + x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 + x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 + x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 + x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 + x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 + x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 + x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 + + for i := 0; i < 20; i += 2 { + u := x0 + x12 + x4 ^= bits.RotateLeft32(u, 7) + u = x4 + x0 + x8 ^= bits.RotateLeft32(u, 9) + u = x8 + x4 + x12 ^= bits.RotateLeft32(u, 13) + u = x12 + x8 + x0 ^= bits.RotateLeft32(u, 18) + + u = x5 + x1 + x9 ^= bits.RotateLeft32(u, 7) + u = x9 + x5 + x13 ^= bits.RotateLeft32(u, 9) + u = x13 + x9 + x1 ^= bits.RotateLeft32(u, 13) + u = x1 + x13 + x5 ^= bits.RotateLeft32(u, 18) + + u = x10 + x6 + x14 ^= bits.RotateLeft32(u, 7) + u = x14 + x10 + x2 ^= bits.RotateLeft32(u, 9) + u = x2 + x14 + x6 ^= bits.RotateLeft32(u, 13) + u = x6 + x2 + x10 ^= bits.RotateLeft32(u, 18) + + u = x15 + x11 + x3 ^= bits.RotateLeft32(u, 7) + u = x3 + x15 + x7 ^= bits.RotateLeft32(u, 9) + u = x7 + x3 + x11 ^= bits.RotateLeft32(u, 13) + u = x11 + x7 + x15 ^= bits.RotateLeft32(u, 18) + + u = x0 + x3 + x1 ^= bits.RotateLeft32(u, 7) + u = x1 + x0 + x2 ^= bits.RotateLeft32(u, 9) + u = x2 + x1 + x3 ^= bits.RotateLeft32(u, 13) + u = x3 + x2 + x0 ^= bits.RotateLeft32(u, 18) + + u = x5 + x4 + x6 ^= bits.RotateLeft32(u, 7) + u = x6 + x5 + x7 ^= bits.RotateLeft32(u, 9) + u = x7 + x6 + x4 ^= bits.RotateLeft32(u, 13) + u = x4 + x7 + x5 ^= bits.RotateLeft32(u, 18) + + u = x10 + x9 + x11 ^= bits.RotateLeft32(u, 7) + u = x11 + x10 + x8 ^= bits.RotateLeft32(u, 9) + u = x8 + x11 + x9 ^= bits.RotateLeft32(u, 13) + u = x9 + x8 + x10 ^= bits.RotateLeft32(u, 18) + + u = x15 + x14 + x12 ^= bits.RotateLeft32(u, 7) + u = x12 + x15 + x13 ^= bits.RotateLeft32(u, 9) + u = x13 + x12 + x14 ^= bits.RotateLeft32(u, 13) + u = x14 + x13 + x15 ^= bits.RotateLeft32(u, 18) + } + out[0] = byte(x0) + out[1] = byte(x0 >> 8) + out[2] = byte(x0 >> 16) + out[3] = byte(x0 >> 24) + + out[4] = byte(x5) + out[5] = byte(x5 >> 8) + out[6] = byte(x5 >> 16) + out[7] = byte(x5 >> 24) + + out[8] = byte(x10) + out[9] = byte(x10 >> 8) + out[10] = byte(x10 >> 16) + out[11] = byte(x10 >> 24) + + out[12] = byte(x15) + out[13] = byte(x15 >> 8) + out[14] = byte(x15 >> 16) + out[15] = byte(x15 >> 24) + + out[16] = byte(x6) + out[17] = byte(x6 >> 8) + out[18] = byte(x6 >> 16) + out[19] = byte(x6 >> 24) + + out[20] = byte(x7) + out[21] = byte(x7 >> 8) + out[22] = byte(x7 >> 16) + out[23] = byte(x7 >> 24) + + out[24] = byte(x8) + out[25] = byte(x8 >> 8) + out[26] = byte(x8 >> 16) + out[27] = byte(x8 >> 24) + + out[28] = byte(x9) + out[29] = byte(x9 >> 8) + out[30] = byte(x9 >> 16) + out[31] = byte(x9 >> 24) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go new file mode 100644 index 0000000..7ec7bb3 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go @@ -0,0 +1,201 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package salsa + +import "math/bits" + +// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts +// the result into the 64-byte array out. The input and output may be the same array. +func Core208(out *[64]byte, in *[64]byte) { + j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 + j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 + j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 + j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 + j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 + j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 + j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 + j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 + j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 + j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 + j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 + j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 + j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 + j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 + j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 + + x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 + x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 + + for i := 0; i < 8; i += 2 { + u := x0 + x12 + x4 ^= bits.RotateLeft32(u, 7) + u = x4 + x0 + x8 ^= bits.RotateLeft32(u, 9) + u = x8 + x4 + x12 ^= bits.RotateLeft32(u, 13) + u = x12 + x8 + x0 ^= bits.RotateLeft32(u, 18) + + u = x5 + x1 + x9 ^= bits.RotateLeft32(u, 7) + u = x9 + x5 + x13 ^= bits.RotateLeft32(u, 9) + u = x13 + x9 + x1 ^= bits.RotateLeft32(u, 13) + u = x1 + x13 + x5 ^= bits.RotateLeft32(u, 18) + + u = x10 + x6 + x14 ^= bits.RotateLeft32(u, 7) + u = x14 + x10 + x2 ^= bits.RotateLeft32(u, 9) + u = x2 + x14 + x6 ^= bits.RotateLeft32(u, 13) + u = x6 + x2 + x10 ^= bits.RotateLeft32(u, 18) + + u = x15 + x11 + x3 ^= bits.RotateLeft32(u, 7) + u = x3 + x15 + x7 ^= bits.RotateLeft32(u, 9) + u = x7 + x3 + x11 ^= bits.RotateLeft32(u, 13) + u = x11 + x7 + x15 ^= bits.RotateLeft32(u, 18) + + u = x0 + x3 + x1 ^= bits.RotateLeft32(u, 7) + u = x1 + x0 + x2 ^= bits.RotateLeft32(u, 9) + u = x2 + x1 + x3 ^= bits.RotateLeft32(u, 13) + u = x3 + x2 + x0 ^= bits.RotateLeft32(u, 18) + + u = x5 + x4 + x6 ^= bits.RotateLeft32(u, 7) + u = x6 + x5 + x7 ^= bits.RotateLeft32(u, 9) + u = x7 + x6 + x4 ^= bits.RotateLeft32(u, 13) + u = x4 + x7 + x5 ^= bits.RotateLeft32(u, 18) + + u = x10 + x9 + x11 ^= bits.RotateLeft32(u, 7) + u = x11 + x10 + x8 ^= bits.RotateLeft32(u, 9) + u = x8 + x11 + x9 ^= bits.RotateLeft32(u, 13) + u = x9 + x8 + x10 ^= bits.RotateLeft32(u, 18) + + u = x15 + x14 + x12 ^= bits.RotateLeft32(u, 7) + u = x12 + x15 + x13 ^= bits.RotateLeft32(u, 9) + u = x13 + x12 + x14 ^= bits.RotateLeft32(u, 13) + u = x14 + x13 + x15 ^= bits.RotateLeft32(u, 18) + } + x0 += j0 + x1 += j1 + x2 += j2 + x3 += j3 + x4 += j4 + x5 += j5 + x6 += j6 + x7 += j7 + x8 += j8 + x9 += j9 + x10 += j10 + x11 += j11 + x12 += j12 + x13 += j13 + x14 += j14 + x15 += j15 + + out[0] = byte(x0) + out[1] = byte(x0 >> 8) + out[2] = byte(x0 >> 16) + out[3] = byte(x0 >> 24) + + out[4] = byte(x1) + out[5] = byte(x1 >> 8) + out[6] = byte(x1 >> 16) + out[7] = byte(x1 >> 24) + + out[8] = byte(x2) + out[9] = byte(x2 >> 8) + out[10] = byte(x2 >> 16) + out[11] = byte(x2 >> 24) + + out[12] = byte(x3) + out[13] = byte(x3 >> 8) + out[14] = byte(x3 >> 16) + out[15] = byte(x3 >> 24) + + out[16] = byte(x4) + out[17] = byte(x4 >> 8) + out[18] = byte(x4 >> 16) + out[19] = byte(x4 >> 24) + + out[20] = byte(x5) + out[21] = byte(x5 >> 8) + out[22] = byte(x5 >> 16) + out[23] = byte(x5 >> 24) + + out[24] = byte(x6) + out[25] = byte(x6 >> 8) + out[26] = byte(x6 >> 16) + out[27] = byte(x6 >> 24) + + out[28] = byte(x7) + out[29] = byte(x7 >> 8) + out[30] = byte(x7 >> 16) + out[31] = byte(x7 >> 24) + + out[32] = byte(x8) + out[33] = byte(x8 >> 8) + out[34] = byte(x8 >> 16) + out[35] = byte(x8 >> 24) + + out[36] = byte(x9) + out[37] = byte(x9 >> 8) + out[38] = byte(x9 >> 16) + out[39] = byte(x9 >> 24) + + out[40] = byte(x10) + out[41] = byte(x10 >> 8) + out[42] = byte(x10 >> 16) + out[43] = byte(x10 >> 24) + + out[44] = byte(x11) + out[45] = byte(x11 >> 8) + out[46] = byte(x11 >> 16) + out[47] = byte(x11 >> 24) + + out[48] = byte(x12) + out[49] = byte(x12 >> 8) + out[50] = byte(x12 >> 16) + out[51] = byte(x12 >> 24) + + out[52] = byte(x13) + out[53] = byte(x13 >> 8) + out[54] = byte(x13 >> 16) + out[55] = byte(x13 >> 24) + + out[56] = byte(x14) + out[57] = byte(x14 >> 8) + out[58] = byte(x14 >> 16) + out[59] = byte(x14 >> 24) + + out[60] = byte(x15) + out[61] = byte(x15 >> 8) + out[62] = byte(x15 >> 16) + out[63] = byte(x15 >> 24) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go new file mode 100644 index 0000000..e76b44f --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go @@ -0,0 +1,23 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && !purego && gc + +package salsa + +//go:noescape + +// salsa2020XORKeyStream is implemented in salsa20_amd64.s. +func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) + +// XORKeyStream crypts bytes from in to out using the given key and counters. +// In and out must overlap entirely or not at all. Counter +// contains the raw salsa20 counter bytes (both nonce and block counter). +func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { + if len(in) == 0 { + return + } + _ = out[len(in)-1] + salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s new file mode 100644 index 0000000..3883e0e --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s @@ -0,0 +1,880 @@ +// Code generated by command: go run salsa20_amd64_asm.go -out ../salsa20_amd64.s -pkg salsa. DO NOT EDIT. + +//go:build amd64 && !purego && gc + +// func salsa2020XORKeyStream(out *byte, in *byte, n uint64, nonce *byte, key *byte) +// Requires: SSE2 +TEXT ·salsa2020XORKeyStream(SB), $456-40 + // This needs up to 64 bytes at 360(R12); hence the non-obvious frame size. + MOVQ out+0(FP), DI + MOVQ in+8(FP), SI + MOVQ n+16(FP), DX + MOVQ nonce+24(FP), CX + MOVQ key+32(FP), R8 + MOVQ SP, R12 + ADDQ $0x1f, R12 + ANDQ $-32, R12 + MOVQ DX, R9 + MOVQ CX, DX + MOVQ R8, R10 + CMPQ R9, $0x00 + JBE DONE + MOVL 20(R10), CX + MOVL (R10), R8 + MOVL (DX), AX + MOVL 16(R10), R11 + MOVL CX, (R12) + MOVL R8, 4(R12) + MOVL AX, 8(R12) + MOVL R11, 12(R12) + MOVL 8(DX), CX + MOVL 24(R10), R8 + MOVL 4(R10), AX + MOVL 4(DX), R11 + MOVL CX, 16(R12) + MOVL R8, 20(R12) + MOVL AX, 24(R12) + MOVL R11, 28(R12) + MOVL 12(DX), CX + MOVL 12(R10), DX + MOVL 28(R10), R8 + MOVL 8(R10), AX + MOVL DX, 32(R12) + MOVL CX, 36(R12) + MOVL R8, 40(R12) + MOVL AX, 44(R12) + MOVQ $0x61707865, DX + MOVQ $0x3320646e, CX + MOVQ $0x79622d32, R8 + MOVQ $0x6b206574, AX + MOVL DX, 48(R12) + MOVL CX, 52(R12) + MOVL R8, 56(R12) + MOVL AX, 60(R12) + CMPQ R9, $0x00000100 + JB BYTESBETWEEN1AND255 + MOVOA 48(R12), X0 + PSHUFL $0x55, X0, X1 + PSHUFL $0xaa, X0, X2 + PSHUFL $0xff, X0, X3 + PSHUFL $0x00, X0, X0 + MOVOA X1, 64(R12) + MOVOA X2, 80(R12) + MOVOA X3, 96(R12) + MOVOA X0, 112(R12) + MOVOA (R12), X0 + PSHUFL $0xaa, X0, X1 + PSHUFL $0xff, X0, X2 + PSHUFL $0x00, X0, X3 + PSHUFL $0x55, X0, X0 + MOVOA X1, 128(R12) + MOVOA X2, 144(R12) + MOVOA X3, 160(R12) + MOVOA X0, 176(R12) + MOVOA 16(R12), X0 + PSHUFL $0xff, X0, X1 + PSHUFL $0x55, X0, X2 + PSHUFL $0xaa, X0, X0 + MOVOA X1, 192(R12) + MOVOA X2, 208(R12) + MOVOA X0, 224(R12) + MOVOA 32(R12), X0 + PSHUFL $0x00, X0, X1 + PSHUFL $0xaa, X0, X2 + PSHUFL $0xff, X0, X0 + MOVOA X1, 240(R12) + MOVOA X2, 256(R12) + MOVOA X0, 272(R12) + +BYTESATLEAST256: + MOVL 16(R12), DX + MOVL 36(R12), CX + MOVL DX, 288(R12) + MOVL CX, 304(R12) + SHLQ $0x20, CX + ADDQ CX, DX + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 292(R12) + MOVL CX, 308(R12) + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 296(R12) + MOVL CX, 312(R12) + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 300(R12) + MOVL CX, 316(R12) + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 16(R12) + MOVL CX, 36(R12) + MOVQ R9, 352(R12) + MOVQ $0x00000014, DX + MOVOA 64(R12), X0 + MOVOA 80(R12), X1 + MOVOA 96(R12), X2 + MOVOA 256(R12), X3 + MOVOA 272(R12), X4 + MOVOA 128(R12), X5 + MOVOA 144(R12), X6 + MOVOA 176(R12), X7 + MOVOA 192(R12), X8 + MOVOA 208(R12), X9 + MOVOA 224(R12), X10 + MOVOA 304(R12), X11 + MOVOA 112(R12), X12 + MOVOA 160(R12), X13 + MOVOA 240(R12), X14 + MOVOA 288(R12), X15 + +MAINLOOP1: + MOVOA X1, 320(R12) + MOVOA X2, 336(R12) + MOVOA X13, X1 + PADDL X12, X1 + MOVOA X1, X2 + PSLLL $0x07, X1 + PXOR X1, X14 + PSRLL $0x19, X2 + PXOR X2, X14 + MOVOA X7, X1 + PADDL X0, X1 + MOVOA X1, X2 + PSLLL $0x07, X1 + PXOR X1, X11 + PSRLL $0x19, X2 + PXOR X2, X11 + MOVOA X12, X1 + PADDL X14, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X15 + PSRLL $0x17, X2 + PXOR X2, X15 + MOVOA X0, X1 + PADDL X11, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X9 + PSRLL $0x17, X2 + PXOR X2, X9 + MOVOA X14, X1 + PADDL X15, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X13 + PSRLL $0x13, X2 + PXOR X2, X13 + MOVOA X11, X1 + PADDL X9, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X7 + PSRLL $0x13, X2 + PXOR X2, X7 + MOVOA X15, X1 + PADDL X13, X1 + MOVOA X1, X2 + PSLLL $0x12, X1 + PXOR X1, X12 + PSRLL $0x0e, X2 + PXOR X2, X12 + MOVOA 320(R12), X1 + MOVOA X12, 320(R12) + MOVOA X9, X2 + PADDL X7, X2 + MOVOA X2, X12 + PSLLL $0x12, X2 + PXOR X2, X0 + PSRLL $0x0e, X12 + PXOR X12, X0 + MOVOA X5, X2 + PADDL X1, X2 + MOVOA X2, X12 + PSLLL $0x07, X2 + PXOR X2, X3 + PSRLL $0x19, X12 + PXOR X12, X3 + MOVOA 336(R12), X2 + MOVOA X0, 336(R12) + MOVOA X6, X0 + PADDL X2, X0 + MOVOA X0, X12 + PSLLL $0x07, X0 + PXOR X0, X4 + PSRLL $0x19, X12 + PXOR X12, X4 + MOVOA X1, X0 + PADDL X3, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X10 + PSRLL $0x17, X12 + PXOR X12, X10 + MOVOA X2, X0 + PADDL X4, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X8 + PSRLL $0x17, X12 + PXOR X12, X8 + MOVOA X3, X0 + PADDL X10, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X5 + PSRLL $0x13, X12 + PXOR X12, X5 + MOVOA X4, X0 + PADDL X8, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X6 + PSRLL $0x13, X12 + PXOR X12, X6 + MOVOA X10, X0 + PADDL X5, X0 + MOVOA X0, X12 + PSLLL $0x12, X0 + PXOR X0, X1 + PSRLL $0x0e, X12 + PXOR X12, X1 + MOVOA 320(R12), X0 + MOVOA X1, 320(R12) + MOVOA X4, X1 + PADDL X0, X1 + MOVOA X1, X12 + PSLLL $0x07, X1 + PXOR X1, X7 + PSRLL $0x19, X12 + PXOR X12, X7 + MOVOA X8, X1 + PADDL X6, X1 + MOVOA X1, X12 + PSLLL $0x12, X1 + PXOR X1, X2 + PSRLL $0x0e, X12 + PXOR X12, X2 + MOVOA 336(R12), X12 + MOVOA X2, 336(R12) + MOVOA X14, X1 + PADDL X12, X1 + MOVOA X1, X2 + PSLLL $0x07, X1 + PXOR X1, X5 + PSRLL $0x19, X2 + PXOR X2, X5 + MOVOA X0, X1 + PADDL X7, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X10 + PSRLL $0x17, X2 + PXOR X2, X10 + MOVOA X12, X1 + PADDL X5, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X8 + PSRLL $0x17, X2 + PXOR X2, X8 + MOVOA X7, X1 + PADDL X10, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X4 + PSRLL $0x13, X2 + PXOR X2, X4 + MOVOA X5, X1 + PADDL X8, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X14 + PSRLL $0x13, X2 + PXOR X2, X14 + MOVOA X10, X1 + PADDL X4, X1 + MOVOA X1, X2 + PSLLL $0x12, X1 + PXOR X1, X0 + PSRLL $0x0e, X2 + PXOR X2, X0 + MOVOA 320(R12), X1 + MOVOA X0, 320(R12) + MOVOA X8, X0 + PADDL X14, X0 + MOVOA X0, X2 + PSLLL $0x12, X0 + PXOR X0, X12 + PSRLL $0x0e, X2 + PXOR X2, X12 + MOVOA X11, X0 + PADDL X1, X0 + MOVOA X0, X2 + PSLLL $0x07, X0 + PXOR X0, X6 + PSRLL $0x19, X2 + PXOR X2, X6 + MOVOA 336(R12), X2 + MOVOA X12, 336(R12) + MOVOA X3, X0 + PADDL X2, X0 + MOVOA X0, X12 + PSLLL $0x07, X0 + PXOR X0, X13 + PSRLL $0x19, X12 + PXOR X12, X13 + MOVOA X1, X0 + PADDL X6, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X15 + PSRLL $0x17, X12 + PXOR X12, X15 + MOVOA X2, X0 + PADDL X13, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X9 + PSRLL $0x17, X12 + PXOR X12, X9 + MOVOA X6, X0 + PADDL X15, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X11 + PSRLL $0x13, X12 + PXOR X12, X11 + MOVOA X13, X0 + PADDL X9, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X3 + PSRLL $0x13, X12 + PXOR X12, X3 + MOVOA X15, X0 + PADDL X11, X0 + MOVOA X0, X12 + PSLLL $0x12, X0 + PXOR X0, X1 + PSRLL $0x0e, X12 + PXOR X12, X1 + MOVOA X9, X0 + PADDL X3, X0 + MOVOA X0, X12 + PSLLL $0x12, X0 + PXOR X0, X2 + PSRLL $0x0e, X12 + PXOR X12, X2 + MOVOA 320(R12), X12 + MOVOA 336(R12), X0 + SUBQ $0x02, DX + JA MAINLOOP1 + PADDL 112(R12), X12 + PADDL 176(R12), X7 + PADDL 224(R12), X10 + PADDL 272(R12), X4 + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + PSHUFL $0x39, X12, X12 + PSHUFL $0x39, X7, X7 + PSHUFL $0x39, X10, X10 + PSHUFL $0x39, X4, X4 + XORL (SI), DX + XORL 4(SI), CX + XORL 8(SI), R8 + XORL 12(SI), R9 + MOVL DX, (DI) + MOVL CX, 4(DI) + MOVL R8, 8(DI) + MOVL R9, 12(DI) + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + PSHUFL $0x39, X12, X12 + PSHUFL $0x39, X7, X7 + PSHUFL $0x39, X10, X10 + PSHUFL $0x39, X4, X4 + XORL 64(SI), DX + XORL 68(SI), CX + XORL 72(SI), R8 + XORL 76(SI), R9 + MOVL DX, 64(DI) + MOVL CX, 68(DI) + MOVL R8, 72(DI) + MOVL R9, 76(DI) + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + PSHUFL $0x39, X12, X12 + PSHUFL $0x39, X7, X7 + PSHUFL $0x39, X10, X10 + PSHUFL $0x39, X4, X4 + XORL 128(SI), DX + XORL 132(SI), CX + XORL 136(SI), R8 + XORL 140(SI), R9 + MOVL DX, 128(DI) + MOVL CX, 132(DI) + MOVL R8, 136(DI) + MOVL R9, 140(DI) + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + XORL 192(SI), DX + XORL 196(SI), CX + XORL 200(SI), R8 + XORL 204(SI), R9 + MOVL DX, 192(DI) + MOVL CX, 196(DI) + MOVL R8, 200(DI) + MOVL R9, 204(DI) + PADDL 240(R12), X14 + PADDL 64(R12), X0 + PADDL 128(R12), X5 + PADDL 192(R12), X8 + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + PSHUFL $0x39, X14, X14 + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X5, X5 + PSHUFL $0x39, X8, X8 + XORL 16(SI), DX + XORL 20(SI), CX + XORL 24(SI), R8 + XORL 28(SI), R9 + MOVL DX, 16(DI) + MOVL CX, 20(DI) + MOVL R8, 24(DI) + MOVL R9, 28(DI) + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + PSHUFL $0x39, X14, X14 + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X5, X5 + PSHUFL $0x39, X8, X8 + XORL 80(SI), DX + XORL 84(SI), CX + XORL 88(SI), R8 + XORL 92(SI), R9 + MOVL DX, 80(DI) + MOVL CX, 84(DI) + MOVL R8, 88(DI) + MOVL R9, 92(DI) + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + PSHUFL $0x39, X14, X14 + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X5, X5 + PSHUFL $0x39, X8, X8 + XORL 144(SI), DX + XORL 148(SI), CX + XORL 152(SI), R8 + XORL 156(SI), R9 + MOVL DX, 144(DI) + MOVL CX, 148(DI) + MOVL R8, 152(DI) + MOVL R9, 156(DI) + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + XORL 208(SI), DX + XORL 212(SI), CX + XORL 216(SI), R8 + XORL 220(SI), R9 + MOVL DX, 208(DI) + MOVL CX, 212(DI) + MOVL R8, 216(DI) + MOVL R9, 220(DI) + PADDL 288(R12), X15 + PADDL 304(R12), X11 + PADDL 80(R12), X1 + PADDL 144(R12), X6 + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + PSHUFL $0x39, X15, X15 + PSHUFL $0x39, X11, X11 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X6, X6 + XORL 32(SI), DX + XORL 36(SI), CX + XORL 40(SI), R8 + XORL 44(SI), R9 + MOVL DX, 32(DI) + MOVL CX, 36(DI) + MOVL R8, 40(DI) + MOVL R9, 44(DI) + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + PSHUFL $0x39, X15, X15 + PSHUFL $0x39, X11, X11 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X6, X6 + XORL 96(SI), DX + XORL 100(SI), CX + XORL 104(SI), R8 + XORL 108(SI), R9 + MOVL DX, 96(DI) + MOVL CX, 100(DI) + MOVL R8, 104(DI) + MOVL R9, 108(DI) + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + PSHUFL $0x39, X15, X15 + PSHUFL $0x39, X11, X11 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X6, X6 + XORL 160(SI), DX + XORL 164(SI), CX + XORL 168(SI), R8 + XORL 172(SI), R9 + MOVL DX, 160(DI) + MOVL CX, 164(DI) + MOVL R8, 168(DI) + MOVL R9, 172(DI) + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + XORL 224(SI), DX + XORL 228(SI), CX + XORL 232(SI), R8 + XORL 236(SI), R9 + MOVL DX, 224(DI) + MOVL CX, 228(DI) + MOVL R8, 232(DI) + MOVL R9, 236(DI) + PADDL 160(R12), X13 + PADDL 208(R12), X9 + PADDL 256(R12), X3 + PADDL 96(R12), X2 + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + PSHUFL $0x39, X13, X13 + PSHUFL $0x39, X9, X9 + PSHUFL $0x39, X3, X3 + PSHUFL $0x39, X2, X2 + XORL 48(SI), DX + XORL 52(SI), CX + XORL 56(SI), R8 + XORL 60(SI), R9 + MOVL DX, 48(DI) + MOVL CX, 52(DI) + MOVL R8, 56(DI) + MOVL R9, 60(DI) + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + PSHUFL $0x39, X13, X13 + PSHUFL $0x39, X9, X9 + PSHUFL $0x39, X3, X3 + PSHUFL $0x39, X2, X2 + XORL 112(SI), DX + XORL 116(SI), CX + XORL 120(SI), R8 + XORL 124(SI), R9 + MOVL DX, 112(DI) + MOVL CX, 116(DI) + MOVL R8, 120(DI) + MOVL R9, 124(DI) + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + PSHUFL $0x39, X13, X13 + PSHUFL $0x39, X9, X9 + PSHUFL $0x39, X3, X3 + PSHUFL $0x39, X2, X2 + XORL 176(SI), DX + XORL 180(SI), CX + XORL 184(SI), R8 + XORL 188(SI), R9 + MOVL DX, 176(DI) + MOVL CX, 180(DI) + MOVL R8, 184(DI) + MOVL R9, 188(DI) + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + XORL 240(SI), DX + XORL 244(SI), CX + XORL 248(SI), R8 + XORL 252(SI), R9 + MOVL DX, 240(DI) + MOVL CX, 244(DI) + MOVL R8, 248(DI) + MOVL R9, 252(DI) + MOVQ 352(R12), R9 + SUBQ $0x00000100, R9 + ADDQ $0x00000100, SI + ADDQ $0x00000100, DI + CMPQ R9, $0x00000100 + JAE BYTESATLEAST256 + CMPQ R9, $0x00 + JBE DONE + +BYTESBETWEEN1AND255: + CMPQ R9, $0x40 + JAE NOCOPY + MOVQ DI, DX + LEAQ 360(R12), DI + MOVQ R9, CX + REP; MOVSB + LEAQ 360(R12), DI + LEAQ 360(R12), SI + +NOCOPY: + MOVQ R9, 352(R12) + MOVOA 48(R12), X0 + MOVOA (R12), X1 + MOVOA 16(R12), X2 + MOVOA 32(R12), X3 + MOVOA X1, X4 + MOVQ $0x00000014, CX + +MAINLOOP2: + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X3 + PXOR X6, X3 + PADDL X3, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X3, X3 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X1 + PSHUFL $0x4e, X2, X2 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X1, X1 + PXOR X6, X0 + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X1 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X1, X1 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X3 + PSHUFL $0x4e, X2, X2 + PXOR X6, X3 + PADDL X3, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X3, X3 + PXOR X6, X0 + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X3 + PXOR X6, X3 + PADDL X3, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X3, X3 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X1 + PSHUFL $0x4e, X2, X2 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X1, X1 + PXOR X6, X0 + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X1 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X1, X1 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X3 + PSHUFL $0x4e, X2, X2 + PXOR X6, X3 + SUBQ $0x04, CX + PADDL X3, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PXOR X7, X7 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X3, X3 + PXOR X6, X0 + JA MAINLOOP2 + PADDL 48(R12), X0 + PADDL (R12), X1 + PADDL 16(R12), X2 + PADDL 32(R12), X3 + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X2, X2 + PSHUFL $0x39, X3, X3 + XORL (SI), CX + XORL 48(SI), R8 + XORL 32(SI), R9 + XORL 16(SI), AX + MOVL CX, (DI) + MOVL R8, 48(DI) + MOVL R9, 32(DI) + MOVL AX, 16(DI) + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X2, X2 + PSHUFL $0x39, X3, X3 + XORL 20(SI), CX + XORL 4(SI), R8 + XORL 52(SI), R9 + XORL 36(SI), AX + MOVL CX, 20(DI) + MOVL R8, 4(DI) + MOVL R9, 52(DI) + MOVL AX, 36(DI) + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X2, X2 + PSHUFL $0x39, X3, X3 + XORL 40(SI), CX + XORL 24(SI), R8 + XORL 8(SI), R9 + XORL 56(SI), AX + MOVL CX, 40(DI) + MOVL R8, 24(DI) + MOVL R9, 8(DI) + MOVL AX, 56(DI) + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + XORL 60(SI), CX + XORL 44(SI), R8 + XORL 28(SI), R9 + XORL 12(SI), AX + MOVL CX, 60(DI) + MOVL R8, 44(DI) + MOVL R9, 28(DI) + MOVL AX, 12(DI) + MOVQ 352(R12), R9 + MOVL 16(R12), CX + MOVL 36(R12), R8 + ADDQ $0x01, CX + SHLQ $0x20, R8 + ADDQ R8, CX + MOVQ CX, R8 + SHRQ $0x20, R8 + MOVL CX, 16(R12) + MOVL R8, 36(R12) + CMPQ R9, $0x40 + JA BYTESATLEAST65 + JAE BYTESATLEAST64 + MOVQ DI, SI + MOVQ DX, DI + MOVQ R9, CX + REP; MOVSB + +BYTESATLEAST64: +DONE: + RET + +BYTESATLEAST65: + SUBQ $0x40, R9 + ADDQ $0x40, DI + ADDQ $0x40, SI + JMP BYTESBETWEEN1AND255 diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go new file mode 100644 index 0000000..9448760 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || purego || !gc + +package salsa + +// XORKeyStream crypts bytes from in to out using the given key and counters. +// In and out must overlap entirely or not at all. Counter +// contains the raw salsa20 counter bytes (both nonce and block counter). +func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { + genericXORKeyStream(out, in, counter, key) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go new file mode 100644 index 0000000..e5cdb9a --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go @@ -0,0 +1,233 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package salsa + +import "math/bits" + +const rounds = 20 + +// core applies the Salsa20 core function to 16-byte input in, 32-byte key k, +// and 16-byte constant c, and puts the result into 64-byte array out. +func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { + j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 + j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 + j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 + j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 + j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 + j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 + j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 + j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 + j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 + j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 + j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 + j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 + j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 + j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 + j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 + + x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 + x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 + + for i := 0; i < rounds; i += 2 { + u := x0 + x12 + x4 ^= bits.RotateLeft32(u, 7) + u = x4 + x0 + x8 ^= bits.RotateLeft32(u, 9) + u = x8 + x4 + x12 ^= bits.RotateLeft32(u, 13) + u = x12 + x8 + x0 ^= bits.RotateLeft32(u, 18) + + u = x5 + x1 + x9 ^= bits.RotateLeft32(u, 7) + u = x9 + x5 + x13 ^= bits.RotateLeft32(u, 9) + u = x13 + x9 + x1 ^= bits.RotateLeft32(u, 13) + u = x1 + x13 + x5 ^= bits.RotateLeft32(u, 18) + + u = x10 + x6 + x14 ^= bits.RotateLeft32(u, 7) + u = x14 + x10 + x2 ^= bits.RotateLeft32(u, 9) + u = x2 + x14 + x6 ^= bits.RotateLeft32(u, 13) + u = x6 + x2 + x10 ^= bits.RotateLeft32(u, 18) + + u = x15 + x11 + x3 ^= bits.RotateLeft32(u, 7) + u = x3 + x15 + x7 ^= bits.RotateLeft32(u, 9) + u = x7 + x3 + x11 ^= bits.RotateLeft32(u, 13) + u = x11 + x7 + x15 ^= bits.RotateLeft32(u, 18) + + u = x0 + x3 + x1 ^= bits.RotateLeft32(u, 7) + u = x1 + x0 + x2 ^= bits.RotateLeft32(u, 9) + u = x2 + x1 + x3 ^= bits.RotateLeft32(u, 13) + u = x3 + x2 + x0 ^= bits.RotateLeft32(u, 18) + + u = x5 + x4 + x6 ^= bits.RotateLeft32(u, 7) + u = x6 + x5 + x7 ^= bits.RotateLeft32(u, 9) + u = x7 + x6 + x4 ^= bits.RotateLeft32(u, 13) + u = x4 + x7 + x5 ^= bits.RotateLeft32(u, 18) + + u = x10 + x9 + x11 ^= bits.RotateLeft32(u, 7) + u = x11 + x10 + x8 ^= bits.RotateLeft32(u, 9) + u = x8 + x11 + x9 ^= bits.RotateLeft32(u, 13) + u = x9 + x8 + x10 ^= bits.RotateLeft32(u, 18) + + u = x15 + x14 + x12 ^= bits.RotateLeft32(u, 7) + u = x12 + x15 + x13 ^= bits.RotateLeft32(u, 9) + u = x13 + x12 + x14 ^= bits.RotateLeft32(u, 13) + u = x14 + x13 + x15 ^= bits.RotateLeft32(u, 18) + } + x0 += j0 + x1 += j1 + x2 += j2 + x3 += j3 + x4 += j4 + x5 += j5 + x6 += j6 + x7 += j7 + x8 += j8 + x9 += j9 + x10 += j10 + x11 += j11 + x12 += j12 + x13 += j13 + x14 += j14 + x15 += j15 + + out[0] = byte(x0) + out[1] = byte(x0 >> 8) + out[2] = byte(x0 >> 16) + out[3] = byte(x0 >> 24) + + out[4] = byte(x1) + out[5] = byte(x1 >> 8) + out[6] = byte(x1 >> 16) + out[7] = byte(x1 >> 24) + + out[8] = byte(x2) + out[9] = byte(x2 >> 8) + out[10] = byte(x2 >> 16) + out[11] = byte(x2 >> 24) + + out[12] = byte(x3) + out[13] = byte(x3 >> 8) + out[14] = byte(x3 >> 16) + out[15] = byte(x3 >> 24) + + out[16] = byte(x4) + out[17] = byte(x4 >> 8) + out[18] = byte(x4 >> 16) + out[19] = byte(x4 >> 24) + + out[20] = byte(x5) + out[21] = byte(x5 >> 8) + out[22] = byte(x5 >> 16) + out[23] = byte(x5 >> 24) + + out[24] = byte(x6) + out[25] = byte(x6 >> 8) + out[26] = byte(x6 >> 16) + out[27] = byte(x6 >> 24) + + out[28] = byte(x7) + out[29] = byte(x7 >> 8) + out[30] = byte(x7 >> 16) + out[31] = byte(x7 >> 24) + + out[32] = byte(x8) + out[33] = byte(x8 >> 8) + out[34] = byte(x8 >> 16) + out[35] = byte(x8 >> 24) + + out[36] = byte(x9) + out[37] = byte(x9 >> 8) + out[38] = byte(x9 >> 16) + out[39] = byte(x9 >> 24) + + out[40] = byte(x10) + out[41] = byte(x10 >> 8) + out[42] = byte(x10 >> 16) + out[43] = byte(x10 >> 24) + + out[44] = byte(x11) + out[45] = byte(x11 >> 8) + out[46] = byte(x11 >> 16) + out[47] = byte(x11 >> 24) + + out[48] = byte(x12) + out[49] = byte(x12 >> 8) + out[50] = byte(x12 >> 16) + out[51] = byte(x12 >> 24) + + out[52] = byte(x13) + out[53] = byte(x13 >> 8) + out[54] = byte(x13 >> 16) + out[55] = byte(x13 >> 24) + + out[56] = byte(x14) + out[57] = byte(x14 >> 8) + out[58] = byte(x14 >> 16) + out[59] = byte(x14 >> 24) + + out[60] = byte(x15) + out[61] = byte(x15 >> 8) + out[62] = byte(x15 >> 16) + out[63] = byte(x15 >> 24) +} + +// genericXORKeyStream is the generic implementation of XORKeyStream to be used +// when no assembly implementation is available. +func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { + var block [64]byte + var counterCopy [16]byte + copy(counterCopy[:], counter[:]) + + for len(in) >= 64 { + core(&block, &counterCopy, key, &Sigma) + for i, x := range block { + out[i] = in[i] ^ x + } + u := uint32(1) + for i := 8; i < 16; i++ { + u += uint32(counterCopy[i]) + counterCopy[i] = byte(u) + u >>= 8 + } + in = in[64:] + out = out[64:] + } + + if len(in) > 0 { + core(&block, &counterCopy, key, &Sigma) + for i, v := range in { + out[i] = v ^ block[i] + } + } +} diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS deleted file mode 100644 index 15167cd..0000000 --- a/vendor/golang.org/x/sys/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS deleted file mode 100644 index 1c4577e..0000000 --- a/vendor/golang.org/x/sys/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE index 6a66aea..2a7cf70 100644 --- a/vendor/golang.org/x/sys/LICENSE +++ b/vendor/golang.org/x/sys/LICENSE @@ -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. diff --git a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s index 06f84b8..269e173 100644 --- a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s +++ b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s new file mode 100644 index 0000000..ec2acfe --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s @@ -0,0 +1,17 @@ +// 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 darwin && amd64 && gc + +#include "textflag.h" + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctlbyname(SB) +GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/cpu/byteorder.go b/vendor/golang.org/x/sys/cpu/byteorder.go index ed8da8d..271055b 100644 --- a/vendor/golang.org/x/sys/cpu/byteorder.go +++ b/vendor/golang.org/x/sys/cpu/byteorder.go @@ -39,20 +39,26 @@ func (bigEndian) Uint64(b []byte) uint64 { uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 } -// hostByteOrder returns binary.LittleEndian on little-endian machines and -// binary.BigEndian on big-endian machines. +// hostByteOrder returns littleEndian on little-endian machines and +// bigEndian on big-endian machines. func hostByteOrder() byteOrder { switch runtime.GOARCH { case "386", "amd64", "amd64p32", + "alpha", "arm", "arm64", + "loong64", "mipsle", "mips64le", "mips64p32le", + "nios2", "ppc64le", - "riscv", "riscv64": + "riscv", "riscv64", + "sh": return littleEndian{} case "armbe", "arm64be", + "m68k", "mips", "mips64", "mips64p32", "ppc", "ppc64", "s390", "s390x", + "shbe", "sparc", "sparc64": return bigEndian{} } diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go index e44deb7..6354199 100644 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -6,6 +6,11 @@ // various CPU architectures. package cpu +import ( + "os" + "strings" +) + // Initialized reports whether the CPU features were initialized. // // For some GOOS/GOARCH combinations initialization of the CPU features depends @@ -24,26 +29,53 @@ type CacheLinePad struct{ _ [cacheLineSize]byte } // and HasAVX2 are only set if the OS supports XMM and YMM // registers in addition to the CPUID feature bit being set. var X86 struct { - _ CacheLinePad - HasAES bool // AES hardware implementation (AES NI) - HasADX bool // Multi-precision add-carry instruction extensions - HasAVX bool // Advanced vector extension - HasAVX2 bool // Advanced vector extension 2 - HasBMI1 bool // Bit manipulation instruction set 1 - HasBMI2 bool // Bit manipulation instruction set 2 - HasERMS bool // Enhanced REP for MOVSB and STOSB - HasFMA bool // Fused-multiply-add instructions - HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. - HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM - HasPOPCNT bool // Hamming weight instruction POPCNT. - HasRDRAND bool // RDRAND instruction (on-chip random number generator) - HasRDSEED bool // RDSEED instruction (on-chip random number generator) - HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) - HasSSE3 bool // Streaming SIMD extension 3 - HasSSSE3 bool // Supplemental streaming SIMD extension 3 - HasSSE41 bool // Streaming SIMD extension 4 and 4.1 - HasSSE42 bool // Streaming SIMD extension 4 and 4.2 - _ CacheLinePad + _ CacheLinePad + HasAES bool // AES hardware implementation (AES NI) + HasADX bool // Multi-precision add-carry instruction extensions + HasAVX bool // Advanced vector extension + HasAVX2 bool // Advanced vector extension 2 + HasAVX512 bool // Advanced vector extension 512 + HasAVX512F bool // Advanced vector extension 512 Foundation Instructions + HasAVX512CD bool // Advanced vector extension 512 Conflict Detection Instructions + HasAVX512ER bool // Advanced vector extension 512 Exponential and Reciprocal Instructions + HasAVX512PF bool // Advanced vector extension 512 Prefetch Instructions + HasAVX512VL bool // Advanced vector extension 512 Vector Length Extensions + HasAVX512BW bool // Advanced vector extension 512 Byte and Word Instructions + HasAVX512DQ bool // Advanced vector extension 512 Doubleword and Quadword Instructions + HasAVX512IFMA bool // Advanced vector extension 512 Integer Fused Multiply Add + HasAVX512VBMI bool // Advanced vector extension 512 Vector Byte Manipulation Instructions + HasAVX5124VNNIW bool // Advanced vector extension 512 Vector Neural Network Instructions Word variable precision + HasAVX5124FMAPS bool // Advanced vector extension 512 Fused Multiply Accumulation Packed Single precision + HasAVX512VPOPCNTDQ bool // Advanced vector extension 512 Double and quad word population count instructions + HasAVX512VPCLMULQDQ bool // Advanced vector extension 512 Vector carry-less multiply operations + HasAVX512VNNI bool // Advanced vector extension 512 Vector Neural Network Instructions + HasAVX512GFNI bool // Advanced vector extension 512 Galois field New Instructions + HasAVX512VAES bool // Advanced vector extension 512 Vector AES instructions + HasAVX512VBMI2 bool // Advanced vector extension 512 Vector Byte Manipulation Instructions 2 + HasAVX512BITALG bool // Advanced vector extension 512 Bit Algorithms + HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions + HasAMXTile bool // Advanced Matrix Extension Tile instructions + HasAMXInt8 bool // Advanced Matrix Extension Int8 instructions + HasAMXBF16 bool // Advanced Matrix Extension BFloat16 instructions + HasBMI1 bool // Bit manipulation instruction set 1 + HasBMI2 bool // Bit manipulation instruction set 2 + HasCX16 bool // Compare and exchange 16 Bytes + HasERMS bool // Enhanced REP for MOVSB and STOSB + HasFMA bool // Fused-multiply-add instructions + HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. + HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM + HasPOPCNT bool // Hamming weight instruction POPCNT. + HasRDRAND bool // RDRAND instruction (on-chip random number generator) + HasRDSEED bool // RDSEED instruction (on-chip random number generator) + HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) + HasSSE3 bool // Streaming SIMD extension 3 + HasSSSE3 bool // Supplemental streaming SIMD extension 3 + HasSSE41 bool // Streaming SIMD extension 4 and 4.1 + HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + HasAVXIFMA bool // Advanced vector extension Integer Fused Multiply Add + HasAVXVNNI bool // Advanced vector extension Vector Neural Network Instructions + HasAVXVNNIInt8 bool // Advanced vector extension Vector Neural Network Int8 instructions + _ CacheLinePad } // ARM64 contains the supported CPU features of the @@ -74,14 +106,17 @@ var ARM64 struct { HasASIMDDP bool // Advanced SIMD double precision instruction set HasSHA512 bool // SHA512 hardware implementation HasSVE bool // Scalable Vector Extensions + HasSVE2 bool // Scalable Vector Extensions 2 HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 + HasDIT bool // Data Independent Timing support + HasI8MM bool // Advanced SIMD Int8 matrix multiplication instructions _ CacheLinePad } // ARM contains the supported CPU features of the current ARM (32-bit) platform. // All feature flags are false if: -// 1. the current platform is not arm, or -// 2. the current operating system is not Linux. +// 1. the current platform is not arm, or +// 2. the current operating system is not Linux. var ARM struct { _ CacheLinePad HasSWP bool // SWP instruction support @@ -114,6 +149,18 @@ var ARM struct { _ CacheLinePad } +// The booleans in Loong64 contain the correspondingly named cpu feature bit. +// The struct is padded to avoid false sharing. +var Loong64 struct { + _ CacheLinePad + HasLSX bool // support 128-bit vector extension + HasLASX bool // support 256-bit vector extension + HasCRC32 bool // support CRC instruction + HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction + HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} instruction + _ CacheLinePad +} + // MIPS64X contains the supported CPU features of the current mips64/mips64le // platforms. If the current platform is not mips64/mips64le or the current // operating system is not Linux then all feature flags are false. @@ -129,14 +176,13 @@ var MIPS64X struct { // For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, // since there are no optional categories. There are some exceptions that also // require kernel support to work (DARN, SCV), so there are feature bits for -// those as well. The minimum processor requirement is POWER8 (ISA 2.07). -// The struct is padded to avoid false sharing. +// those as well. The struct is padded to avoid false sharing. var PPC64 struct { _ CacheLinePad HasDARN bool // Hardware random number generator (requires kernel enablement) HasSCV bool // Syscall vectored (requires kernel enablement) IsPOWER8 bool // ISA v2.07 (POWER8) - IsPOWER9 bool // ISA v3.00 (POWER9) + IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 _ CacheLinePad } @@ -169,3 +215,124 @@ var S390X struct { HasVXE bool // vector-enhancements facility 1 _ CacheLinePad } + +// RISCV64 contains the supported CPU features and performance characteristics for riscv64 +// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate +// the presence of RISC-V extensions. +// +// It is safe to assume that all the RV64G extensions are supported and so they are omitted from +// this structure. As riscv64 Go programs require at least RV64G, the code that populates +// this structure cannot run successfully if some of the RV64G extensions are missing. +// The struct is padded to avoid false sharing. +var RISCV64 struct { + _ CacheLinePad + HasFastMisaligned bool // Fast misaligned accesses + HasC bool // Compressed instruction-set extension + HasV bool // Vector extension compatible with RVV 1.0 + HasZba bool // Address generation instructions extension + HasZbb bool // Basic bit-manipulation extension + HasZbs bool // Single-bit instructions extension + HasZvbb bool // Vector Basic Bit-manipulation + HasZvbc bool // Vector Carryless Multiplication + HasZvkb bool // Vector Cryptography Bit-manipulation + HasZvkt bool // Vector Data-Independent Execution Latency + HasZvkg bool // Vector GCM/GMAC + HasZvkn bool // NIST Algorithm Suite (AES/SHA256/SHA512) + HasZvknc bool // NIST Algorithm Suite with carryless multiply + HasZvkng bool // NIST Algorithm Suite with GCM + HasZvks bool // ShangMi Algorithm Suite + HasZvksc bool // ShangMi Algorithm Suite with carryless multiplication + HasZvksg bool // ShangMi Algorithm Suite with GCM + _ CacheLinePad +} + +func init() { + archInit() + initOptions() + processOptions() +} + +// options contains the cpu debug options that can be used in GODEBUG. +// Options are arch dependent and are added by the arch specific initOptions functions. +// Features that are mandatory for the specific GOARCH should have the Required field set +// (e.g. SSE2 on amd64). +var options []option + +// Option names should be lower case. e.g. avx instead of AVX. +type option struct { + Name string + Feature *bool + Specified bool // whether feature value was specified in GODEBUG + Enable bool // whether feature should be enabled + Required bool // whether feature is mandatory and can not be disabled +} + +func processOptions() { + env := os.Getenv("GODEBUG") +field: + for env != "" { + field := "" + i := strings.IndexByte(env, ',') + if i < 0 { + field, env = env, "" + } else { + field, env = env[:i], env[i+1:] + } + if len(field) < 4 || field[:4] != "cpu." { + continue + } + i = strings.IndexByte(field, '=') + if i < 0 { + print("GODEBUG sys/cpu: no value specified for \"", field, "\"\n") + continue + } + key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" + + var enable bool + switch value { + case "on": + enable = true + case "off": + enable = false + default: + print("GODEBUG sys/cpu: value \"", value, "\" not supported for cpu option \"", key, "\"\n") + continue field + } + + if key == "all" { + for i := range options { + options[i].Specified = true + options[i].Enable = enable || options[i].Required + } + continue field + } + + for i := range options { + if options[i].Name == key { + options[i].Specified = true + options[i].Enable = enable + continue field + } + } + + print("GODEBUG sys/cpu: unknown cpu feature \"", key, "\"\n") + } + + for _, o := range options { + if !o.Specified { + continue + } + + if o.Enable && !*o.Feature { + print("GODEBUG sys/cpu: can not enable \"", o.Name, "\", missing CPU support\n") + continue + } + + if !o.Enable && o.Required { + print("GODEBUG sys/cpu: can not disable \"", o.Name, "\", required CPU feature\n") + continue + } + + *o.Feature = o.Enable + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go b/vendor/golang.org/x/sys/cpu/cpu_aix.go similarity index 89% rename from vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go rename to vendor/golang.org/x/sys/cpu/cpu_aix.go index be60272..9bf0c32 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_aix.go @@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix,ppc64 +//go:build aix package cpu -const cacheLineSize = 128 - const ( // getsystemcfg constants _SC_IMPL = 2 @@ -15,12 +13,13 @@ const ( _IMPL_POWER9 = 0x20000 ) -func init() { +func archInit() { impl := getsystemcfg(_SC_IMPL) if impl&_IMPL_POWER8 != 0 { PPC64.IsPOWER8 = true } if impl&_IMPL_POWER9 != 0 { + PPC64.IsPOWER8 = true PPC64.IsPOWER9 = true } diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go index 981af68..301b752 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_arm.go +++ b/vendor/golang.org/x/sys/cpu/cpu_arm.go @@ -38,3 +38,36 @@ const ( hwcap2_SHA2 = 1 << 3 hwcap2_CRC32 = 1 << 4 ) + +func initOptions() { + options = []option{ + {Name: "pmull", Feature: &ARM.HasPMULL}, + {Name: "sha1", Feature: &ARM.HasSHA1}, + {Name: "sha2", Feature: &ARM.HasSHA2}, + {Name: "swp", Feature: &ARM.HasSWP}, + {Name: "thumb", Feature: &ARM.HasTHUMB}, + {Name: "thumbee", Feature: &ARM.HasTHUMBEE}, + {Name: "tls", Feature: &ARM.HasTLS}, + {Name: "vfp", Feature: &ARM.HasVFP}, + {Name: "vfpd32", Feature: &ARM.HasVFPD32}, + {Name: "vfpv3", Feature: &ARM.HasVFPv3}, + {Name: "vfpv3d16", Feature: &ARM.HasVFPv3D16}, + {Name: "vfpv4", Feature: &ARM.HasVFPv4}, + {Name: "half", Feature: &ARM.HasHALF}, + {Name: "26bit", Feature: &ARM.Has26BIT}, + {Name: "fastmul", Feature: &ARM.HasFASTMUL}, + {Name: "fpa", Feature: &ARM.HasFPA}, + {Name: "edsp", Feature: &ARM.HasEDSP}, + {Name: "java", Feature: &ARM.HasJAVA}, + {Name: "iwmmxt", Feature: &ARM.HasIWMMXT}, + {Name: "crunch", Feature: &ARM.HasCRUNCH}, + {Name: "neon", Feature: &ARM.HasNEON}, + {Name: "idivt", Feature: &ARM.HasIDIVT}, + {Name: "idiva", Feature: &ARM.HasIDIVA}, + {Name: "lpae", Feature: &ARM.HasLPAE}, + {Name: "evtstrm", Feature: &ARM.HasEVTSTRM}, + {Name: "aes", Feature: &ARM.HasAES}, + {Name: "crc32", Feature: &ARM.HasCRC32}, + } + +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go index 9c87677..af2aa99 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -6,29 +6,70 @@ package cpu import "runtime" -const cacheLineSize = 64 +// cacheLineSize is used to prevent false sharing of cache lines. +// We choose 128 because Apple Silicon, a.k.a. M1, has 128-byte cache line size. +// It doesn't cost much and is much more future-proof. +const cacheLineSize = 128 + +func initOptions() { + options = []option{ + {Name: "fp", Feature: &ARM64.HasFP}, + {Name: "asimd", Feature: &ARM64.HasASIMD}, + {Name: "evstrm", Feature: &ARM64.HasEVTSTRM}, + {Name: "aes", Feature: &ARM64.HasAES}, + {Name: "fphp", Feature: &ARM64.HasFPHP}, + {Name: "jscvt", Feature: &ARM64.HasJSCVT}, + {Name: "lrcpc", Feature: &ARM64.HasLRCPC}, + {Name: "pmull", Feature: &ARM64.HasPMULL}, + {Name: "sha1", Feature: &ARM64.HasSHA1}, + {Name: "sha2", Feature: &ARM64.HasSHA2}, + {Name: "sha3", Feature: &ARM64.HasSHA3}, + {Name: "sha512", Feature: &ARM64.HasSHA512}, + {Name: "sm3", Feature: &ARM64.HasSM3}, + {Name: "sm4", Feature: &ARM64.HasSM4}, + {Name: "sve", Feature: &ARM64.HasSVE}, + {Name: "sve2", Feature: &ARM64.HasSVE2}, + {Name: "crc32", Feature: &ARM64.HasCRC32}, + {Name: "atomics", Feature: &ARM64.HasATOMICS}, + {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, + {Name: "cpuid", Feature: &ARM64.HasCPUID}, + {Name: "asimrdm", Feature: &ARM64.HasASIMDRDM}, + {Name: "fcma", Feature: &ARM64.HasFCMA}, + {Name: "dcpop", Feature: &ARM64.HasDCPOP}, + {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, + {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, + {Name: "dit", Feature: &ARM64.HasDIT}, + {Name: "i8mm", Feature: &ARM64.HasI8MM}, + } +} -func init() { +func archInit() { switch runtime.GOOS { - case "android", "darwin": - // Android and iOS don't seem to allow reading these registers. - // Fake the minimal features expected by - // TestARM64minimalFeatures. - ARM64.HasASIMD = true - ARM64.HasFP = true - case "linux": + case "freebsd": + readARM64Registers() + case "linux", "netbsd", "openbsd": doinit() default: - readARM64Registers() + // Many platforms don't seem to allow reading these registers. + setMinimalFeatures() } } +// setMinimalFeatures fakes the minimal ARM64 features expected by +// TestARM64minimalFeatures. +func setMinimalFeatures() { + ARM64.HasASIMD = true + ARM64.HasFP = true +} + func readARM64Registers() { Initialized = true - // ID_AA64ISAR0_EL1 - isar0 := getisar0() + parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0()) +} +func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { + // ID_AA64ISAR0_EL1 switch extractBits(isar0, 4, 7) { case 1: ARM64.HasAES = true @@ -86,8 +127,6 @@ func readARM64Registers() { } // ID_AA64ISAR1_EL1 - isar1 := getisar1() - switch extractBits(isar1, 0, 3) { case 1: ARM64.HasDCPOP = true @@ -108,9 +147,12 @@ func readARM64Registers() { ARM64.HasLRCPC = true } - // ID_AA64PFR0_EL1 - pfr0 := getpfr0() + switch extractBits(isar1, 52, 55) { + case 1: + ARM64.HasI8MM = true + } + // ID_AA64PFR0_EL1 switch extractBits(pfr0, 16, 19) { case 0: ARM64.HasFP = true @@ -130,6 +172,20 @@ func readARM64Registers() { switch extractBits(pfr0, 32, 35) { case 1: ARM64.HasSVE = true + + parseARM64SVERegister(getzfr0()) + } + + switch extractBits(pfr0, 48, 51) { + case 1: + ARM64.HasDIT = true + } +} + +func parseARM64SVERegister(zfr0 uint64) { + switch extractBits(zfr0, 0, 3) { + case 1: + ARM64.HasSVE2 = true } } diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s index a54436e..3b0450a 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_arm64.s +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.s @@ -2,30 +2,34 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" // func getisar0() uint64 TEXT ·getisar0(SB),NOSPLIT,$0-8 // get Instruction Set Attributes 0 into x0 - // mrs x0, ID_AA64ISAR0_EL1 = d5380600 - WORD $0xd5380600 + MRS ID_AA64ISAR0_EL1, R0 MOVD R0, ret+0(FP) RET // func getisar1() uint64 TEXT ·getisar1(SB),NOSPLIT,$0-8 // get Instruction Set Attributes 1 into x0 - // mrs x0, ID_AA64ISAR1_EL1 = d5380620 - WORD $0xd5380620 + MRS ID_AA64ISAR1_EL1, R0 MOVD R0, ret+0(FP) RET // func getpfr0() uint64 TEXT ·getpfr0(SB),NOSPLIT,$0-8 // get Processor Feature Register 0 into x0 - // mrs x0, ID_AA64PFR0_EL1 = d5380400 - WORD $0xd5380400 + MRS ID_AA64PFR0_EL1, R0 + MOVD R0, ret+0(FP) + RET + +// func getzfr0() uint64 +TEXT ·getzfr0(SB),NOSPLIT,$0-8 + // get SVE Feature Register 0 into x0 + MRS ID_AA64ZFR0_EL1, R0 MOVD R0, ret+0(FP) RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go new file mode 100644 index 0000000..b838cb9 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go @@ -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 darwin && amd64 && gc + +package cpu + +// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl +// call (see issue 43089). It also restricts AVX512 support for Darwin to +// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233). +// +// Background: +// Darwin implements a special mechanism to economize on thread state when +// AVX512 specific registers are not in use. This scheme minimizes state when +// preempting threads that haven't yet used any AVX512 instructions, but adds +// special requirements to check for AVX512 hardware support at runtime (e.g. +// via sysctl call or commpage inspection). See issue 43089 and link below for +// full background: +// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240 +// +// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0 +// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption +// of the AVX512 mask registers (K0-K7) upon signal return. For this reason +// AVX512 is considered unsafe to use on Darwin for kernel versions prior to +// 21.3.0, where a fix has been confirmed. See issue 49233 for full background. +func darwinSupportsAVX512() bool { + return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0) +} + +// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies +func darwinKernelVersionCheck(major, minor, patch int) bool { + var release [256]byte + err := darwinOSRelease(&release) + if err != nil { + return false + } + + var mmp [3]int + c := 0 +Loop: + for _, b := range release[:] { + switch { + case b >= '0' && b <= '9': + mmp[c] = 10*mmp[c] + int(b-'0') + case b == '.': + c++ + if c > 2 { + return false + } + case b == 0: + break Loop + default: + return false + } + } + if c != 2 { + return false + } + return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch) +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go index 7b88e86..6ac6e1e 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc package cpu func getisar0() uint64 func getisar1() uint64 func getpfr0() uint64 +func getzfr0() uint64 diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go index 568bcd0..c8ae6dd 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go index f7cb469..32a4451 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64 amd64p32 -// +build !gccgo +//go:build (386 || amd64 || amd64p32) && gc package cpu -// cpuid is implemented in cpu_x86.s for gc compiler +// cpuid is implemented in cpu_gc_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) -// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.s b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s similarity index 87% rename from vendor/golang.org/x/sys/cpu/cpu_x86.s rename to vendor/golang.org/x/sys/cpu/cpu_gc_x86.s index 47f0841..ce208ce 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.s +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64 amd64p32 -// +build !gccgo +//go:build (386 || amd64 || amd64p32) && gc #include "textflag.h" @@ -19,7 +18,7 @@ TEXT ·cpuid(SB), NOSPLIT, $0-24 RET // func xgetbv() (eax, edx uint32) -TEXT ·xgetbv(SB),NOSPLIT,$0-8 +TEXT ·xgetbv(SB), NOSPLIT, $0-8 MOVL $0, CX XGETBV MOVL AX, eax+0(FP) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go index 53ca8d6..7f19467 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build gccgo +//go:build gccgo package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go index aa986f7..9526d2c 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build gccgo +//go:build gccgo package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c index e363c7d..3f73a05 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64 amd64p32 -// +build gccgo +//go:build (386 || amd64 || amd64p32) && gccgo #include #include +#include // Need to wrap __get_cpuid_count because it's declared as static. int @@ -17,27 +17,21 @@ gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); } +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC push_options +#pragma GCC target("xsave") +#pragma clang attribute push (__attribute__((target("xsave"))), apply_to=function) + // xgetbv reads the contents of an XCR (Extended Control Register) // specified in the ECX register into registers EDX:EAX. // Currently, the only supported value for XCR is 0. -// -// TODO: Replace with a better alternative: -// -// #include -// -// #pragma GCC target("xsave") -// -// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { -// unsigned long long x = _xgetbv(0); -// *eax = x & 0xffffffff; -// *edx = (x >> 32) & 0xffffffff; -// } -// -// Note that _xgetbv is defined starting with GCC 8. void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { - __asm(" xorl %%ecx, %%ecx\n" - " xgetbv" - : "=a"(*eax), "=d"(*edx)); + uint64_t v = _xgetbv(0); + *eax = v & 0xffffffff; + *edx = v >> 32; } + +#pragma clang attribute pop +#pragma GCC pop_options diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go index ba49b91..170d21d 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64 amd64p32 -// +build gccgo +//go:build (386 || amd64 || amd64p32) && gccgo package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux.go b/vendor/golang.org/x/sys/cpu/cpu_linux.go index fe13918..743eb54 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !386,!amd64,!amd64p32,!arm64 +//go:build !386 && !amd64 && !amd64p32 && !arm64 package cpu -func init() { +func archInit() { if err := readHWCAP(); err != nil { return } diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go index 79a38a0..f1caf0f 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go @@ -4,6 +4,11 @@ package cpu +import ( + "strings" + "syscall" +) + // HWCAP/HWCAP2 bits. These are exposed by Linux. const ( hwcap_FP = 1 << 0 @@ -30,12 +35,51 @@ const ( hwcap_SHA512 = 1 << 21 hwcap_SVE = 1 << 22 hwcap_ASIMDFHM = 1 << 23 + hwcap_DIT = 1 << 24 + + hwcap2_SVE2 = 1 << 1 + hwcap2_I8MM = 1 << 13 ) +// linuxKernelCanEmulateCPUID reports whether we're running +// on Linux 4.11+. Ideally we'd like to ask the question about +// whether the current kernel contains +// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=77c97b4ee21290f5f083173d957843b615abbff2 +// but the version number will have to do. +func linuxKernelCanEmulateCPUID() bool { + var un syscall.Utsname + syscall.Uname(&un) + var sb strings.Builder + for _, b := range un.Release[:] { + if b == 0 { + break + } + sb.WriteByte(byte(b)) + } + major, minor, _, ok := parseRelease(sb.String()) + return ok && (major > 4 || major == 4 && minor >= 11) +} + func doinit() { if err := readHWCAP(); err != nil { - // failed to read /proc/self/auxv, try reading registers directly - readARM64Registers() + // We failed to read /proc/self/auxv. This can happen if the binary has + // been given extra capabilities(7) with /bin/setcap. + // + // When this happens, we have two options. If the Linux kernel is new + // enough (4.11+), we can read the arm64 registers directly which'll + // trap into the kernel and then return back to userspace. + // + // But on older kernels, such as Linux 4.4.180 as used on many Synology + // devices, calling readARM64Registers (specifically getisar0) will + // cause a SIGILL and we'll die. So for older kernels, parse /proc/cpuinfo + // instead. + // + // See golang/go#57336. + if linuxKernelCanEmulateCPUID() { + readARM64Registers() + } else { + readLinuxProcCPUInfo() + } return } @@ -64,6 +108,11 @@ func doinit() { ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) ARM64.HasSVE = isSet(hwCap, hwcap_SVE) ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) + ARM64.HasDIT = isSet(hwCap, hwcap_DIT) + + // HWCAP2 feature bits + ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2) + ARM64.HasI8MM = isSet(hwCap2, hwcap2_I8MM) } func isSet(hwc uint, value uint) bool { diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go new file mode 100644 index 0000000..4f34114 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go @@ -0,0 +1,22 @@ +// 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 cpu + +// HWCAP bits. These are exposed by the Linux kernel. +const ( + hwcap_LOONGARCH_LSX = 1 << 4 + hwcap_LOONGARCH_LASX = 1 << 5 +) + +func doinit() { + // TODO: Features that require kernel support like LSX and LASX can + // be detected here once needed in std library or by the compiler. + Loong64.HasLSX = hwcIsSet(hwCap, hwcap_LOONGARCH_LSX) + Loong64.HasLASX = hwcIsSet(hwCap, hwcap_LOONGARCH_LASX) +} + +func hwcIsSet(hwc uint, val uint) bool { + return hwc&val != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go index eb24e50..4686c1d 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build mips64 mips64le +//go:build linux && (mips64 || mips64le) package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go index 42b5d33..a428dec 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x +//go:build linux && !arm && !arm64 && !loong64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go index 6c8d975..197188e 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go @@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build ppc64 ppc64le +//go:build linux && (ppc64 || ppc64le) package cpu -const cacheLineSize = 128 - // HWCAP/HWCAP2 bits. These are exposed by the kernel. const ( // ISA Level diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go new file mode 100644 index 0000000..ad74153 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go @@ -0,0 +1,160 @@ +// 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 cpu + +import ( + "syscall" + "unsafe" +) + +// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe +// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available. +// +// A note on detection of the Vector extension using HWCAP. +// +// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. +// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe +// syscall is not available then neither is the Vector extension (which needs kernel support). +// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. +// However, some RISC-V board manufacturers ship boards with an older kernel on top of which +// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe +// patches. These kernels advertise support for the Vector extension using HWCAP. Falling +// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not +// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. +// +// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by +// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board +// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified +// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use +// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector +// extension are binary incompatible. HWCAP can then not be used in isolation to populate the +// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. +// +// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector +// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype +// register. This check would allow us to safely detect version 1.0 of the Vector extension +// with HWCAP, if riscv_hwprobe were not available. However, the check cannot +// be added until the assembler supports the Vector instructions. +// +// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the +// extensions it advertises support for are explicitly versioned. It's also worth noting that +// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba. +// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority +// of RISC-V extensions. +// +// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. + +// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must +// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall +// here. + +const ( + // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. + riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 + riscv_HWPROBE_IMA_C = 0x2 + riscv_HWPROBE_IMA_V = 0x4 + riscv_HWPROBE_EXT_ZBA = 0x8 + riscv_HWPROBE_EXT_ZBB = 0x10 + riscv_HWPROBE_EXT_ZBS = 0x20 + riscv_HWPROBE_EXT_ZVBB = 0x20000 + riscv_HWPROBE_EXT_ZVBC = 0x40000 + riscv_HWPROBE_EXT_ZVKB = 0x80000 + riscv_HWPROBE_EXT_ZVKG = 0x100000 + riscv_HWPROBE_EXT_ZVKNED = 0x200000 + riscv_HWPROBE_EXT_ZVKNHB = 0x800000 + riscv_HWPROBE_EXT_ZVKSED = 0x1000000 + riscv_HWPROBE_EXT_ZVKSH = 0x2000000 + riscv_HWPROBE_EXT_ZVKT = 0x4000000 + riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 + riscv_HWPROBE_MISALIGNED_FAST = 0x3 + riscv_HWPROBE_MISALIGNED_MASK = 0x7 +) + +const ( + // sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go. + sys_RISCV_HWPROBE = 258 +) + +// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. +type riscvHWProbePairs struct { + key int64 + value uint64 +} + +const ( + // CPU features + hwcap_RISCV_ISA_C = 1 << ('C' - 'A') +) + +func doinit() { + // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key + // field should be initialised with one of the key constants defined above, e.g., + // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. + // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. + + pairs := []riscvHWProbePairs{ + {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, + {riscv_HWPROBE_KEY_CPUPERF_0, 0}, + } + + // This call only indicates that extensions are supported if they are implemented on all cores. + if riscvHWProbe(pairs, 0) { + if pairs[0].key != -1 { + v := uint(pairs[0].value) + RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C) + RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) + RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) + RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) + RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) + RISCV64.HasZvbb = isSet(v, riscv_HWPROBE_EXT_ZVBB) + RISCV64.HasZvbc = isSet(v, riscv_HWPROBE_EXT_ZVBC) + RISCV64.HasZvkb = isSet(v, riscv_HWPROBE_EXT_ZVKB) + RISCV64.HasZvkg = isSet(v, riscv_HWPROBE_EXT_ZVKG) + RISCV64.HasZvkt = isSet(v, riscv_HWPROBE_EXT_ZVKT) + // Cryptography shorthand extensions + RISCV64.HasZvkn = isSet(v, riscv_HWPROBE_EXT_ZVKNED) && + isSet(v, riscv_HWPROBE_EXT_ZVKNHB) && RISCV64.HasZvkb && RISCV64.HasZvkt + RISCV64.HasZvknc = RISCV64.HasZvkn && RISCV64.HasZvbc + RISCV64.HasZvkng = RISCV64.HasZvkn && RISCV64.HasZvkg + RISCV64.HasZvks = isSet(v, riscv_HWPROBE_EXT_ZVKSED) && + isSet(v, riscv_HWPROBE_EXT_ZVKSH) && RISCV64.HasZvkb && RISCV64.HasZvkt + RISCV64.HasZvksc = RISCV64.HasZvks && RISCV64.HasZvbc + RISCV64.HasZvksg = RISCV64.HasZvks && RISCV64.HasZvkg + } + if pairs[1].key != -1 { + v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK + RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST + } + } + + // Let's double check with HWCAP if the C extension does not appear to be supported. + // This may happen if we're running on a kernel older than 6.4. + + if !RISCV64.HasC { + RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) + } +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} + +// riscvHWProbe is a simplified version of the generated wrapper function found in +// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the +// cpuCount and cpus parameters which we do not need. We always want to pass 0 for +// these parameters here so the kernel only reports the extensions that are present +// on all cores. +func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool { + var _zero uintptr + var p0 unsafe.Pointer + if len(pairs) > 0 { + p0 = unsafe.Pointer(&pairs[0]) + } else { + p0 = unsafe.Pointer(&_zero) + } + + _, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0) + return e1 == 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go index d579eae..1517ac6 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go @@ -4,8 +4,6 @@ package cpu -const cacheLineSize = 256 - const ( // bit mask values from /usr/include/bits/hwcap.h hwcap_ZARCH = 2 @@ -19,86 +17,7 @@ const ( hwcap_VXE = 8192 ) -// bitIsSet reports whether the bit at index is set. The bit index -// is in big endian order, so bit index 0 is the leftmost bit. -func bitIsSet(bits []uint64, index uint) bool { - return bits[index/64]&((1<<63)>>(index%64)) != 0 -} - -// function is the code for the named cryptographic function. -type function uint8 - -const ( - // KM{,A,C,CTR} function codes - aes128 function = 18 // AES-128 - aes192 function = 19 // AES-192 - aes256 function = 20 // AES-256 - - // K{I,L}MD function codes - sha1 function = 1 // SHA-1 - sha256 function = 2 // SHA-256 - sha512 function = 3 // SHA-512 - sha3_224 function = 32 // SHA3-224 - sha3_256 function = 33 // SHA3-256 - sha3_384 function = 34 // SHA3-384 - sha3_512 function = 35 // SHA3-512 - shake128 function = 36 // SHAKE-128 - shake256 function = 37 // SHAKE-256 - - // KLMD function codes - ghash function = 65 // GHASH -) - -// queryResult contains the result of a Query function -// call. Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type queryResult struct { - bits [2]uint64 -} - -// Has reports whether the given functions are present. -func (q *queryResult) Has(fns ...function) bool { - if len(fns) == 0 { - panic("no function codes provided") - } - for _, f := range fns { - if !bitIsSet(q.bits[:], uint(f)) { - return false - } - } - return true -} - -// facility is a bit index for the named facility. -type facility uint8 - -const ( - // cryptography facilities - msa4 facility = 77 // message-security-assist extension 4 - msa8 facility = 146 // message-security-assist extension 8 -) - -// facilityList contains the result of an STFLE call. -// Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type facilityList struct { - bits [4]uint64 -} - -// Has reports whether the given facilities are present. -func (s *facilityList) Has(fs ...facility) bool { - if len(fs) == 0 { - panic("no facility bits provided") - } - for _, f := range fs { - if !bitIsSet(s.bits[:], uint(f)) { - return false - } - } - return true -} - -func doinit() { +func initS390Xbase() { // test HWCAP bit vector has := func(featureMask uint) bool { return hwCap&featureMask == featureMask @@ -118,44 +37,4 @@ func doinit() { if S390X.HasVX { S390X.HasVXE = has(hwcap_VXE) } - - // We need implementations of stfle, km and so on - // to detect cryptographic features. - if !haveAsmFunctions() { - return - } - - // optional cryptographic functions - if S390X.HasMSA { - aes := []function{aes128, aes192, aes256} - - // cipher message - km, kmc := kmQuery(), kmcQuery() - S390X.HasAES = km.Has(aes...) - S390X.HasAESCBC = kmc.Has(aes...) - if S390X.HasSTFLE { - facilities := stfle() - if facilities.Has(msa4) { - kmctr := kmctrQuery() - S390X.HasAESCTR = kmctr.Has(aes...) - } - if facilities.Has(msa8) { - kma := kmaQuery() - S390X.HasAESGCM = kma.Has(aes...) - } - } - - // compute message digest - kimd := kimdQuery() // intermediate (no padding) - klmd := klmdQuery() // last (padding) - S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) - S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) - S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) - S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist - sha3 := []function{ - sha3_224, sha3_256, sha3_384, sha3_512, - shake128, shake256, - } - S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) - } } diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_loong64.go new file mode 100644 index 0000000..45ecb29 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_loong64.go @@ -0,0 +1,50 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build loong64 + +package cpu + +const cacheLineSize = 64 + +// Bit fields for CPUCFG registers, Related reference documents: +// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg +const ( + // CPUCFG1 bits + cpucfg1_CRC32 = 1 << 25 + + // CPUCFG2 bits + cpucfg2_LAM_BH = 1 << 27 + cpucfg2_LAMCAS = 1 << 28 +) + +func initOptions() { + options = []option{ + {Name: "lsx", Feature: &Loong64.HasLSX}, + {Name: "lasx", Feature: &Loong64.HasLASX}, + {Name: "crc32", Feature: &Loong64.HasCRC32}, + {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, + {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, + } + + // The CPUCFG data on Loong64 only reflects the hardware capabilities, + // not the kernel support status, so features such as LSX and LASX that + // require kernel support cannot be obtained from the CPUCFG data. + // + // These features only require hardware capability support and do not + // require kernel specific support, so they can be obtained directly + // through CPUCFG + cfg1 := get_cpucfg(1) + cfg2 := get_cpucfg(2) + + Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) + Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) + Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) +} + +func get_cpucfg(reg uint32) uint32 + +func cfgIsSet(cfg uint32, val uint32) bool { + return cfg&val != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.s b/vendor/golang.org/x/sys/cpu/cpu_loong64.s new file mode 100644 index 0000000..71cbaf1 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_loong64.s @@ -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. + +#include "textflag.h" + +// func get_cpucfg(reg uint32) uint32 +TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0 + MOVW reg+0(FP), R5 + // CPUCFG R5, R4 = 0x00006ca4 + WORD $0x00006ca4 + MOVW R4, ret+8(FP) + RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go index 6165f12..fedb00c 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go +++ b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go @@ -2,8 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build mips64 mips64le +//go:build mips64 || mips64le package cpu const cacheLineSize = 32 + +func initOptions() { + options = []option{ + {Name: "msa", Feature: &MIPS64X.HasMSA}, + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go index 1269eee..ffb4ec7 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go +++ b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build mips mipsle +//go:build mips || mipsle package cpu const cacheLineSize = 32 + +func initOptions() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go new file mode 100644 index 0000000..ebfb3fc --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go @@ -0,0 +1,173 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "syscall" + "unsafe" +) + +// Minimal copy of functionality from x/sys/unix so the cpu package can call +// sysctl without depending on x/sys/unix. + +const ( + _CTL_QUERY = -2 + + _SYSCTL_VERS_1 = 0x1000000 +) + +var _zero uintptr + +func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, errno := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(_p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen)) + if errno != 0 { + return errno + } + return nil +} + +type sysctlNode struct { + Flags uint32 + Num int32 + Name [32]int8 + Ver uint32 + __rsvd uint32 + Un [16]byte + _sysctl_size [8]byte + _sysctl_func [8]byte + _sysctl_parent [8]byte + _sysctl_desc [8]byte +} + +func sysctlNodes(mib []int32) ([]sysctlNode, error) { + var olen uintptr + + // Get a list of all sysctl nodes below the given MIB by performing + // a sysctl for the given MIB with CTL_QUERY appended. + mib = append(mib, _CTL_QUERY) + qnode := sysctlNode{Flags: _SYSCTL_VERS_1} + qp := (*byte)(unsafe.Pointer(&qnode)) + sz := unsafe.Sizeof(qnode) + if err := sysctl(mib, nil, &olen, qp, sz); err != nil { + return nil, err + } + + // Now that we know the size, get the actual nodes. + nodes := make([]sysctlNode, olen/sz) + np := (*byte)(unsafe.Pointer(&nodes[0])) + if err := sysctl(mib, np, &olen, qp, sz); err != nil { + return nil, err + } + + return nodes, nil +} + +func nametomib(name string) ([]int32, error) { + // Split name into components. + var parts []string + last := 0 + for i := 0; i < len(name); i++ { + if name[i] == '.' { + parts = append(parts, name[last:i]) + last = i + 1 + } + } + parts = append(parts, name[last:]) + + mib := []int32{} + // Discover the nodes and construct the MIB OID. + for partno, part := range parts { + nodes, err := sysctlNodes(mib) + if err != nil { + return nil, err + } + for _, node := range nodes { + n := make([]byte, 0) + for i := range node.Name { + if node.Name[i] != 0 { + n = append(n, byte(node.Name[i])) + } + } + if string(n) == part { + mib = append(mib, int32(node.Num)) + break + } + } + if len(mib) != partno+1 { + return nil, err + } + } + + return mib, nil +} + +// aarch64SysctlCPUID is struct aarch64_sysctl_cpu_id from NetBSD's +type aarch64SysctlCPUID struct { + midr uint64 /* Main ID Register */ + revidr uint64 /* Revision ID Register */ + mpidr uint64 /* Multiprocessor Affinity Register */ + aa64dfr0 uint64 /* A64 Debug Feature Register 0 */ + aa64dfr1 uint64 /* A64 Debug Feature Register 1 */ + aa64isar0 uint64 /* A64 Instruction Set Attribute Register 0 */ + aa64isar1 uint64 /* A64 Instruction Set Attribute Register 1 */ + aa64mmfr0 uint64 /* A64 Memory Model Feature Register 0 */ + aa64mmfr1 uint64 /* A64 Memory Model Feature Register 1 */ + aa64mmfr2 uint64 /* A64 Memory Model Feature Register 2 */ + aa64pfr0 uint64 /* A64 Processor Feature Register 0 */ + aa64pfr1 uint64 /* A64 Processor Feature Register 1 */ + aa64zfr0 uint64 /* A64 SVE Feature ID Register 0 */ + mvfr0 uint32 /* Media and VFP Feature Register 0 */ + mvfr1 uint32 /* Media and VFP Feature Register 1 */ + mvfr2 uint32 /* Media and VFP Feature Register 2 */ + pad uint32 + clidr uint64 /* Cache Level ID Register */ + ctr uint64 /* Cache Type Register */ +} + +func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) { + mib, err := nametomib(name) + if err != nil { + return nil, err + } + + out := aarch64SysctlCPUID{} + n := unsafe.Sizeof(out) + _, _, errno := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(len(mib)), + uintptr(unsafe.Pointer(&out)), + uintptr(unsafe.Pointer(&n)), + uintptr(0), + uintptr(0)) + if errno != 0 { + return nil, errno + } + return &out, nil +} + +func doinit() { + cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id") + if err != nil { + setMinimalFeatures() + return + } + parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0) + + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go new file mode 100644 index 0000000..85b64d5 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go @@ -0,0 +1,65 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "syscall" + "unsafe" +) + +// Minimal copy of functionality from x/sys/unix so the cpu package can call +// sysctl without depending on x/sys/unix. + +const ( + // From OpenBSD's sys/sysctl.h. + _CTL_MACHDEP = 7 + + // From OpenBSD's machine/cpu.h. + _CPU_ID_AA64ISAR0 = 2 + _CPU_ID_AA64ISAR1 = 3 +) + +// Implemented in the runtime package (runtime/sys_openbsd3.go) +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) + +//go:linkname syscall_syscall6 syscall.syscall6 + +func sysctl(mib []uint32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + _, _, errno := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(unsafe.Pointer(&mib[0])), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if errno != 0 { + return errno + } + return nil +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +func sysctlUint64(mib []uint32) (uint64, bool) { + var out uint64 + nout := unsafe.Sizeof(out) + if err := sysctl(mib, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); err != nil { + return 0, false + } + return out, true +} + +func doinit() { + setMinimalFeatures() + + // Get ID_AA64ISAR0 and ID_AA64ISAR1 from sysctl. + isar0, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR0}) + if !ok { + return + } + isar1, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR1}) + if !ok { + return + } + parseARM64SystemRegisters(isar0, isar1, 0) + + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s new file mode 100644 index 0000000..054ba05 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s @@ -0,0 +1,11 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) + +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm.go new file mode 100644 index 0000000..e9ecf2a --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_arm.go @@ -0,0 +1,9 @@ +// 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 !linux && arm + +package cpu + +func archInit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go index 3ffc4af..5341e7f 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux,arm64 +//go:build !linux && !netbsd && !openbsd && arm64 package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go new file mode 100644 index 0000000..5f8f241 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go @@ -0,0 +1,11 @@ +// 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 !linux && (mips64 || mips64le) + +package cpu + +func archInit() { + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go new file mode 100644 index 0000000..89608fb --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go @@ -0,0 +1,12 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !linux && (ppc64 || ppc64le) + +package cpu + +func archInit() { + PPC64.IsPOWER8 = true + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go new file mode 100644 index 0000000..5ab8780 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go @@ -0,0 +1,11 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux && riscv64 + +package cpu + +func archInit() { + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go new file mode 100644 index 0000000..a0fd7e2 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go @@ -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 386 || amd64p32 || (amd64 && (!darwin || !gc)) + +package cpu + +func darwinSupportsAVX512() bool { + panic("only implemented for gc && amd64 && darwin") +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go new file mode 100644 index 0000000..c14f12b --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go @@ -0,0 +1,16 @@ +// 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 ppc64 || ppc64le + +package cpu + +const cacheLineSize = 128 + +func initOptions() { + options = []option{ + {Name: "darn", Feature: &PPC64.HasDARN}, + {Name: "scv", Feature: &PPC64.HasSCV}, + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go index efe2b7a..0f617ae 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go @@ -2,8 +2,31 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build riscv64 +//go:build riscv64 package cpu -const cacheLineSize = 32 +const cacheLineSize = 64 + +func initOptions() { + options = []option{ + {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, + {Name: "c", Feature: &RISCV64.HasC}, + {Name: "v", Feature: &RISCV64.HasV}, + {Name: "zba", Feature: &RISCV64.HasZba}, + {Name: "zbb", Feature: &RISCV64.HasZbb}, + {Name: "zbs", Feature: &RISCV64.HasZbs}, + // RISC-V Cryptography Extensions + {Name: "zvbb", Feature: &RISCV64.HasZvbb}, + {Name: "zvbc", Feature: &RISCV64.HasZvbc}, + {Name: "zvkb", Feature: &RISCV64.HasZvkb}, + {Name: "zvkg", Feature: &RISCV64.HasZvkg}, + {Name: "zvkt", Feature: &RISCV64.HasZvkt}, + {Name: "zvkn", Feature: &RISCV64.HasZvkn}, + {Name: "zvknc", Feature: &RISCV64.HasZvknc}, + {Name: "zvkng", Feature: &RISCV64.HasZvkng}, + {Name: "zvks", Feature: &RISCV64.HasZvks}, + {Name: "zvksc", Feature: &RISCV64.HasZvksc}, + {Name: "zvksg", Feature: &RISCV64.HasZvksg}, + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_s390x.go new file mode 100644 index 0000000..5881b88 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.go @@ -0,0 +1,172 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 256 + +func initOptions() { + options = []option{ + {Name: "zarch", Feature: &S390X.HasZARCH, Required: true}, + {Name: "stfle", Feature: &S390X.HasSTFLE, Required: true}, + {Name: "ldisp", Feature: &S390X.HasLDISP, Required: true}, + {Name: "eimm", Feature: &S390X.HasEIMM, Required: true}, + {Name: "dfp", Feature: &S390X.HasDFP}, + {Name: "etf3eh", Feature: &S390X.HasETF3EH}, + {Name: "msa", Feature: &S390X.HasMSA}, + {Name: "aes", Feature: &S390X.HasAES}, + {Name: "aescbc", Feature: &S390X.HasAESCBC}, + {Name: "aesctr", Feature: &S390X.HasAESCTR}, + {Name: "aesgcm", Feature: &S390X.HasAESGCM}, + {Name: "ghash", Feature: &S390X.HasGHASH}, + {Name: "sha1", Feature: &S390X.HasSHA1}, + {Name: "sha256", Feature: &S390X.HasSHA256}, + {Name: "sha3", Feature: &S390X.HasSHA3}, + {Name: "sha512", Feature: &S390X.HasSHA512}, + {Name: "vx", Feature: &S390X.HasVX}, + {Name: "vxe", Feature: &S390X.HasVXE}, + } +} + +// bitIsSet reports whether the bit at index is set. The bit index +// is in big endian order, so bit index 0 is the leftmost bit. +func bitIsSet(bits []uint64, index uint) bool { + return bits[index/64]&((1<<63)>>(index%64)) != 0 +} + +// facility is a bit index for the named facility. +type facility uint8 + +const ( + // mandatory facilities + zarch facility = 1 // z architecture mode is active + stflef facility = 7 // store-facility-list-extended + ldisp facility = 18 // long-displacement + eimm facility = 21 // extended-immediate + + // miscellaneous facilities + dfp facility = 42 // decimal-floating-point + etf3eh facility = 30 // extended-translation 3 enhancement + + // cryptography facilities + msa facility = 17 // message-security-assist + msa3 facility = 76 // message-security-assist extension 3 + msa4 facility = 77 // message-security-assist extension 4 + msa5 facility = 57 // message-security-assist extension 5 + msa8 facility = 146 // message-security-assist extension 8 + msa9 facility = 155 // message-security-assist extension 9 + + // vector facilities + vx facility = 129 // vector facility + vxe facility = 135 // vector-enhancements 1 + vxe2 facility = 148 // vector-enhancements 2 +) + +// facilityList contains the result of an STFLE call. +// Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type facilityList struct { + bits [4]uint64 +} + +// Has reports whether the given facilities are present. +func (s *facilityList) Has(fs ...facility) bool { + if len(fs) == 0 { + panic("no facility bits provided") + } + for _, f := range fs { + if !bitIsSet(s.bits[:], uint(f)) { + return false + } + } + return true +} + +// function is the code for the named cryptographic function. +type function uint8 + +const ( + // KM{,A,C,CTR} function codes + aes128 function = 18 // AES-128 + aes192 function = 19 // AES-192 + aes256 function = 20 // AES-256 + + // K{I,L}MD function codes + sha1 function = 1 // SHA-1 + sha256 function = 2 // SHA-256 + sha512 function = 3 // SHA-512 + sha3_224 function = 32 // SHA3-224 + sha3_256 function = 33 // SHA3-256 + sha3_384 function = 34 // SHA3-384 + sha3_512 function = 35 // SHA3-512 + shake128 function = 36 // SHAKE-128 + shake256 function = 37 // SHAKE-256 + + // KLMD function codes + ghash function = 65 // GHASH +) + +// queryResult contains the result of a Query function +// call. Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type queryResult struct { + bits [2]uint64 +} + +// Has reports whether the given functions are present. +func (q *queryResult) Has(fns ...function) bool { + if len(fns) == 0 { + panic("no function codes provided") + } + for _, f := range fns { + if !bitIsSet(q.bits[:], uint(f)) { + return false + } + } + return true +} + +func doinit() { + initS390Xbase() + + // We need implementations of stfle, km and so on + // to detect cryptographic features. + if !haveAsmFunctions() { + return + } + + // optional cryptographic functions + if S390X.HasMSA { + aes := []function{aes128, aes192, aes256} + + // cipher message + km, kmc := kmQuery(), kmcQuery() + S390X.HasAES = km.Has(aes...) + S390X.HasAESCBC = kmc.Has(aes...) + if S390X.HasSTFLE { + facilities := stfle() + if facilities.Has(msa4) { + kmctr := kmctrQuery() + S390X.HasAESCTR = kmctr.Has(aes...) + } + if facilities.Has(msa8) { + kma := kmaQuery() + S390X.HasAESGCM = kma.Has(aes...) + } + } + + // compute message digest + kimd := kimdQuery() // intermediate (no padding) + klmd := klmdQuery() // last (padding) + S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) + S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) + S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) + S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist + sha3 := []function{ + sha3_224, sha3_256, sha3_384, sha3_512, + shake128, shake256, + } + S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/vendor/golang.org/x/sys/cpu/cpu_s390x.s index e5037d9..1fb4b70 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_s390x.s +++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/cpu/cpu_wasm.go b/vendor/golang.org/x/sys/cpu/cpu_wasm.go index 8681e87..384787e 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_wasm.go +++ b/vendor/golang.org/x/sys/cpu/cpu_wasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build wasm +//go:build wasm package cpu @@ -11,3 +11,7 @@ package cpu // rules are good enough. const cacheLineSize = 0 + +func initOptions() {} + +func archInit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go index d70d317..f5723d4 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -2,13 +2,142 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64 amd64p32 +//go:build 386 || amd64 || amd64p32 package cpu +import "runtime" + const cacheLineSize = 64 -func init() { +func initOptions() { + options = []option{ + {Name: "adx", Feature: &X86.HasADX}, + {Name: "aes", Feature: &X86.HasAES}, + {Name: "avx", Feature: &X86.HasAVX}, + {Name: "avx2", Feature: &X86.HasAVX2}, + {Name: "avx512", Feature: &X86.HasAVX512}, + {Name: "avx512f", Feature: &X86.HasAVX512F}, + {Name: "avx512cd", Feature: &X86.HasAVX512CD}, + {Name: "avx512er", Feature: &X86.HasAVX512ER}, + {Name: "avx512pf", Feature: &X86.HasAVX512PF}, + {Name: "avx512vl", Feature: &X86.HasAVX512VL}, + {Name: "avx512bw", Feature: &X86.HasAVX512BW}, + {Name: "avx512dq", Feature: &X86.HasAVX512DQ}, + {Name: "avx512ifma", Feature: &X86.HasAVX512IFMA}, + {Name: "avx512vbmi", Feature: &X86.HasAVX512VBMI}, + {Name: "avx512vnniw", Feature: &X86.HasAVX5124VNNIW}, + {Name: "avx5124fmaps", Feature: &X86.HasAVX5124FMAPS}, + {Name: "avx512vpopcntdq", Feature: &X86.HasAVX512VPOPCNTDQ}, + {Name: "avx512vpclmulqdq", Feature: &X86.HasAVX512VPCLMULQDQ}, + {Name: "avx512vnni", Feature: &X86.HasAVX512VNNI}, + {Name: "avx512gfni", Feature: &X86.HasAVX512GFNI}, + {Name: "avx512vaes", Feature: &X86.HasAVX512VAES}, + {Name: "avx512vbmi2", Feature: &X86.HasAVX512VBMI2}, + {Name: "avx512bitalg", Feature: &X86.HasAVX512BITALG}, + {Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, + {Name: "amxtile", Feature: &X86.HasAMXTile}, + {Name: "amxint8", Feature: &X86.HasAMXInt8}, + {Name: "amxbf16", Feature: &X86.HasAMXBF16}, + {Name: "bmi1", Feature: &X86.HasBMI1}, + {Name: "bmi2", Feature: &X86.HasBMI2}, + {Name: "cx16", Feature: &X86.HasCX16}, + {Name: "erms", Feature: &X86.HasERMS}, + {Name: "fma", Feature: &X86.HasFMA}, + {Name: "osxsave", Feature: &X86.HasOSXSAVE}, + {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ}, + {Name: "popcnt", Feature: &X86.HasPOPCNT}, + {Name: "rdrand", Feature: &X86.HasRDRAND}, + {Name: "rdseed", Feature: &X86.HasRDSEED}, + {Name: "sse3", Feature: &X86.HasSSE3}, + {Name: "sse41", Feature: &X86.HasSSE41}, + {Name: "sse42", Feature: &X86.HasSSE42}, + {Name: "ssse3", Feature: &X86.HasSSSE3}, + {Name: "avxifma", Feature: &X86.HasAVXIFMA}, + {Name: "avxvnni", Feature: &X86.HasAVXVNNI}, + {Name: "avxvnniint8", Feature: &X86.HasAVXVNNIInt8}, + + // These capabilities should always be enabled on amd64: + {Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"}, + } +} + +func archInit() { + + // From internal/cpu + const ( + // eax bits + cpuid_AVXVNNI = 1 << 4 + + // ecx bits + cpuid_SSE3 = 1 << 0 + cpuid_PCLMULQDQ = 1 << 1 + cpuid_AVX512VBMI = 1 << 1 + cpuid_AVX512VBMI2 = 1 << 6 + cpuid_SSSE3 = 1 << 9 + cpuid_AVX512GFNI = 1 << 8 + cpuid_AVX512VAES = 1 << 9 + cpuid_AVX512VNNI = 1 << 11 + cpuid_AVX512BITALG = 1 << 12 + cpuid_FMA = 1 << 12 + cpuid_AVX512VPOPCNTDQ = 1 << 14 + cpuid_SSE41 = 1 << 19 + cpuid_SSE42 = 1 << 20 + cpuid_POPCNT = 1 << 23 + cpuid_AES = 1 << 25 + cpuid_OSXSAVE = 1 << 27 + cpuid_AVX = 1 << 28 + + // "Extended Feature Flag" bits returned in EBX for CPUID EAX=0x7 ECX=0x0 + cpuid_BMI1 = 1 << 3 + cpuid_AVX2 = 1 << 5 + cpuid_BMI2 = 1 << 8 + cpuid_ERMS = 1 << 9 + cpuid_AVX512F = 1 << 16 + cpuid_AVX512DQ = 1 << 17 + cpuid_ADX = 1 << 19 + cpuid_AVX512CD = 1 << 28 + cpuid_SHA = 1 << 29 + cpuid_AVX512BW = 1 << 30 + cpuid_AVX512VL = 1 << 31 + + // "Extended Feature Flag" bits returned in ECX for CPUID EAX=0x7 ECX=0x0 + cpuid_AVX512_VBMI = 1 << 1 + cpuid_AVX512_VBMI2 = 1 << 6 + cpuid_GFNI = 1 << 8 + cpuid_AVX512VPCLMULQDQ = 1 << 10 + cpuid_AVX512_BITALG = 1 << 12 + + // edx bits + cpuid_FSRM = 1 << 4 + // edx bits for CPUID 0x80000001 + cpuid_RDTSCP = 1 << 27 + ) + // Additional constants not in internal/cpu + const ( + // eax=1: edx + cpuid_SSE2 = 1 << 26 + // eax=1: ecx + cpuid_CX16 = 1 << 13 + cpuid_RDRAND = 1 << 30 + // eax=7,ecx=0: ebx + cpuid_RDSEED = 1 << 18 + cpuid_AVX512IFMA = 1 << 21 + cpuid_AVX512PF = 1 << 26 + cpuid_AVX512ER = 1 << 27 + // eax=7,ecx=0: edx + cpuid_AVX5124VNNIW = 1 << 2 + cpuid_AVX5124FMAPS = 1 << 3 + cpuid_AMXBF16 = 1 << 22 + cpuid_AMXTile = 1 << 24 + cpuid_AMXInt8 = 1 << 25 + // eax=7,ecx=1: eax + cpuid_AVX512BF16 = 1 << 5 + cpuid_AVXIFMA = 1 << 23 + // eax=7,ecx=1: edx + cpuid_AVXVNNIInt8 = 1 << 4 + ) + Initialized = true maxID, _, _, _ := cpuid(0, 0) @@ -18,42 +147,90 @@ func init() { } _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(26, edx1) - - X86.HasSSE3 = isSet(0, ecx1) - X86.HasPCLMULQDQ = isSet(1, ecx1) - X86.HasSSSE3 = isSet(9, ecx1) - X86.HasFMA = isSet(12, ecx1) - X86.HasSSE41 = isSet(19, ecx1) - X86.HasSSE42 = isSet(20, ecx1) - X86.HasPOPCNT = isSet(23, ecx1) - X86.HasAES = isSet(25, ecx1) - X86.HasOSXSAVE = isSet(27, ecx1) - X86.HasRDRAND = isSet(30, ecx1) - - osSupportsAVX := false + X86.HasSSE2 = isSet(edx1, cpuid_SSE2) + + X86.HasSSE3 = isSet(ecx1, cpuid_SSE3) + X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ) + X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3) + X86.HasFMA = isSet(ecx1, cpuid_FMA) + X86.HasCX16 = isSet(ecx1, cpuid_CX16) + X86.HasSSE41 = isSet(ecx1, cpuid_SSE41) + X86.HasSSE42 = isSet(ecx1, cpuid_SSE42) + X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT) + X86.HasAES = isSet(ecx1, cpuid_AES) + X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE) + X86.HasRDRAND = isSet(ecx1, cpuid_RDRAND) + + var osSupportsAVX, osSupportsAVX512 bool // For XGETBV, OSXSAVE bit is required and sufficient. if X86.HasOSXSAVE { eax, _ := xgetbv() // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) + osSupportsAVX = isSet(eax, 1<<1) && isSet(eax, 1<<2) + + if runtime.GOOS == "darwin" { + // Darwin requires special AVX512 checks, see cpu_darwin_x86.go + osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() + } else { + // Check if OPMASK and ZMM registers have OS support. + osSupportsAVX512 = osSupportsAVX && isSet(eax, 1<<5) && isSet(eax, 1<<6) && isSet(eax, 1<<7) + } } - X86.HasAVX = isSet(28, ecx1) && osSupportsAVX + X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX if maxID < 7 { return } - _, ebx7, _, _ := cpuid(7, 0) - X86.HasBMI1 = isSet(3, ebx7) - X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX - X86.HasBMI2 = isSet(8, ebx7) - X86.HasERMS = isSet(9, ebx7) - X86.HasRDSEED = isSet(18, ebx7) - X86.HasADX = isSet(19, ebx7) + eax7, ebx7, ecx7, edx7 := cpuid(7, 0) + X86.HasBMI1 = isSet(ebx7, cpuid_BMI1) + X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX + X86.HasBMI2 = isSet(ebx7, cpuid_BMI2) + X86.HasERMS = isSet(ebx7, cpuid_ERMS) + X86.HasRDSEED = isSet(ebx7, cpuid_RDSEED) + X86.HasADX = isSet(ebx7, cpuid_ADX) + + X86.HasAVX512 = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512 // Because avx-512 foundation is the core required extension + if X86.HasAVX512 { + X86.HasAVX512F = true + X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD) + X86.HasAVX512ER = isSet(ebx7, cpuid_AVX512ER) + X86.HasAVX512PF = isSet(ebx7, cpuid_AVX512PF) + X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) + X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) + X86.HasAVX512DQ = isSet(ebx7, cpuid_AVX512DQ) + X86.HasAVX512IFMA = isSet(ebx7, cpuid_AVX512IFMA) + X86.HasAVX512VBMI = isSet(ecx7, cpuid_AVX512_VBMI) + X86.HasAVX5124VNNIW = isSet(edx7, cpuid_AVX5124VNNIW) + X86.HasAVX5124FMAPS = isSet(edx7, cpuid_AVX5124FMAPS) + X86.HasAVX512VPOPCNTDQ = isSet(ecx7, cpuid_AVX512VPOPCNTDQ) + X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ) + X86.HasAVX512VNNI = isSet(ecx7, cpuid_AVX512VNNI) + X86.HasAVX512GFNI = isSet(ecx7, cpuid_AVX512GFNI) + X86.HasAVX512VAES = isSet(ecx7, cpuid_AVX512VAES) + X86.HasAVX512VBMI2 = isSet(ecx7, cpuid_AVX512VBMI2) + X86.HasAVX512BITALG = isSet(ecx7, cpuid_AVX512BITALG) + } + + X86.HasAMXTile = isSet(edx7, cpuid_AMXTile) + X86.HasAMXInt8 = isSet(edx7, cpuid_AMXInt8) + X86.HasAMXBF16 = isSet(edx7, cpuid_AMXBF16) + + // These features depend on the second level of extended features. + if eax7 >= 1 { + eax71, _, _, edx71 := cpuid(7, 1) + if X86.HasAVX512 { + X86.HasAVX512BF16 = isSet(eax71, cpuid_AVX512BF16) + } + if X86.HasAVX { + X86.HasAVXIFMA = isSet(eax71, cpuid_AVXIFMA) + X86.HasAVXVNNI = isSet(eax71, cpuid_AVXVNNI) + X86.HasAVXVNNIInt8 = isSet(edx71, cpuid_AVXVNNIInt8) + } + } } -func isSet(bitpos uint, value uint32) bool { - return value&(1< 0 { + for len(a) >= 2 { + tag, val := a[0], uint(a[1]) + a = a[2:] + switch tag { + case _AT_HWCAP: + hwCap = val + case _AT_HWCAP2: + hwCap2 = val + } + } + return nil + } + + buf, err := os.ReadFile(procAuxv) if err != nil { // e.g. on android /proc/self/auxv is not accessible, so silently // ignore the error and leave Initialized = false. On some diff --git a/vendor/golang.org/x/sys/cpu/parse.go b/vendor/golang.org/x/sys/cpu/parse.go new file mode 100644 index 0000000..56a7e1a --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/parse.go @@ -0,0 +1,43 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import "strconv" + +// parseRelease parses a dot-separated version number. It follows the semver +// syntax, but allows the minor and patch versions to be elided. +// +// This is a copy of the Go runtime's parseRelease from +// https://golang.org/cl/209597. +func parseRelease(rel string) (major, minor, patch int, ok bool) { + // Strip anything after a dash or plus. + for i := range len(rel) { + if rel[i] == '-' || rel[i] == '+' { + rel = rel[:i] + break + } + } + + next := func() (int, bool) { + for i := range len(rel) { + if rel[i] == '.' { + ver, err := strconv.Atoi(rel[:i]) + rel = rel[i+1:] + return ver, err == nil + } + } + ver, err := strconv.Atoi(rel) + rel = "" + return ver, err == nil + } + if major, ok = next(); !ok || rel == "" { + return + } + if minor, ok = next(); !ok || rel == "" { + return + } + patch, ok = next() + return +} diff --git a/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go b/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go new file mode 100644 index 0000000..4cd64c7 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go @@ -0,0 +1,53 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && arm64 + +package cpu + +import ( + "errors" + "io" + "os" + "strings" +) + +func readLinuxProcCPUInfo() error { + f, err := os.Open("/proc/cpuinfo") + if err != nil { + return err + } + defer f.Close() + + var buf [1 << 10]byte // enough for first CPU + n, err := io.ReadFull(f, buf[:]) + if err != nil && err != io.ErrUnexpectedEOF { + return err + } + in := string(buf[:n]) + const features = "\nFeatures : " + i := strings.Index(in, features) + if i == -1 { + return errors.New("no CPU features found") + } + in = in[i+len(features):] + if i := strings.Index(in, "\n"); i != -1 { + in = in[:i] + } + m := map[string]*bool{} + + initOptions() // need it early here; it's harmless to call twice + for _, o := range options { + m[o.Name] = o.Feature + } + // The EVTSTRM field has alias "evstrm" in Go, but Linux calls it "evtstrm". + m["evtstrm"] = &ARM64.HasEVTSTRM + + for _, f := range strings.Fields(in) { + if p, ok := m[f]; ok { + *p = true + } + } + return nil +} diff --git a/vendor/golang.org/x/sys/cpu/runtime_auxv.go b/vendor/golang.org/x/sys/cpu/runtime_auxv.go new file mode 100644 index 0000000..5f92ac9 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/runtime_auxv.go @@ -0,0 +1,16 @@ +// 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 cpu + +// getAuxvFn is non-nil on Go 1.21+ (via runtime_auxv_go121.go init) +// on platforms that use auxv. +var getAuxvFn func() []uintptr + +func getAuxv() []uintptr { + if getAuxvFn == nil { + return nil + } + return getAuxvFn() +} diff --git a/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go b/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go new file mode 100644 index 0000000..4c9788e --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go @@ -0,0 +1,18 @@ +// 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.21 + +package cpu + +import ( + _ "unsafe" // for linkname +) + +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +func init() { + getAuxvFn = runtime_getAuxv +} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go b/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go new file mode 100644 index 0000000..1b9ccb0 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go @@ -0,0 +1,26 @@ +// 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. + +// Recreate a getsystemcfg syscall handler instead of +// using the one provided by x/sys/unix to avoid having +// the dependency between them. (See golang.org/issue/32102) +// Moreover, this file will be used during the building of +// gccgo's libgo and thus must not used a CGo method. + +//go:build aix && gccgo + +package cpu + +import ( + "syscall" +) + +//extern getsystemcfg +func gccgoGetsystemcfg(label uint32) (r uint64) + +func callgetsystemcfg(label int) (r1 uintptr, e1 syscall.Errno) { + r1 = uintptr(gccgoGetsystemcfg(uint32(label))) + e1 = syscall.GetErrno() + return +} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go index 78fe25e..e8b6cdb 100644 --- a/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go +++ b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go @@ -6,8 +6,7 @@ // system call on AIX without depending on x/sys/unix. // (See golang.org/issue/32102) -// +build aix,ppc64 -// +build !gccgo +//go:build aix && ppc64 && gc package cpu diff --git a/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go new file mode 100644 index 0000000..4d0888b --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go @@ -0,0 +1,98 @@ +// 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. + +// Minimal copy of x/sys/unix so the cpu package can make a +// system call on Darwin without depending on x/sys/unix. + +//go:build darwin && amd64 && gc + +package cpu + +import ( + "syscall" + "unsafe" +) + +type _C_int int32 + +// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419 +func darwinOSRelease(release *[256]byte) error { + // from x/sys/unix/zerrors_openbsd_amd64.go + const ( + CTL_KERN = 0x1 + KERN_OSRELEASE = 0x2 + ) + + mib := []_C_int{CTL_KERN, KERN_OSRELEASE} + n := unsafe.Sizeof(*release) + + return sysctl(mib, &release[0], &n, nil, 0) +} + +type Errno = syscall.Errno + +var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes. + +// from x/sys/unix/zsyscall_darwin_amd64.go L791-807 +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + if _, _, err := syscall_syscall6( + libc_sysctl_trampoline_addr, + uintptr(_p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen), + ); err != 0 { + return err + } + + return nil +} + +var libc_sysctl_trampoline_addr uintptr + +// adapted from internal/cpu/cpu_arm64_darwin.go +func darwinSysctlEnabled(name []byte) bool { + out := int32(0) + nout := unsafe.Sizeof(out) + if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil { + return false + } + return out > 0 +} + +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +var libc_sysctlbyname_trampoline_addr uintptr + +// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix +func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + if _, _, err := syscall_syscall6( + libc_sysctlbyname_trampoline_addr, + uintptr(unsafe.Pointer(name)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen), + 0, + ); err != 0 { + return err + } + + return nil +} + +//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib" + +// Implemented in the runtime package (runtime/sys_darwin.go) +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +//go:linkname syscall_syscall6 syscall.syscall6 diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md index ab433cc..6e08a76 100644 --- a/vendor/golang.org/x/sys/unix/README.md +++ b/vendor/golang.org/x/sys/unix/README.md @@ -76,7 +76,7 @@ arguments can be passed to the kernel. The third is for low-level use by the ForkExec wrapper. Unlike the first two, it does not call into the scheduler to let it know that a system call is running. -When porting Go to an new architecture/OS, this file must be implemented for +When porting Go to a new architecture/OS, this file must be implemented for each GOOS/GOARCH pair. ### mksysnum @@ -89,7 +89,7 @@ constants. Adding new syscall numbers is mostly done by running the build on a sufficiently new installation of the target OS (or updating the source checkouts for the -new build system). However, depending on the OS, you make need to update the +new build system). However, depending on the OS, you may need to update the parsing in mksysnum. ### mksyscall.go @@ -107,7 +107,7 @@ prototype can be exported (capitalized) or not. Adding a new syscall often just requires adding a new `//sys` function prototype with the desired arguments and a capitalized name so it is exported. However, if you want the interface to the syscall to be different, often one will make an -unexported `//sys` prototype, an then write a custom wrapper in +unexported `//sys` prototype, and then write a custom wrapper in `syscall_${GOOS}.go`. ### types files @@ -137,7 +137,7 @@ some `#if/#elif` macros in your include statements. This script is used to generate the system's various constants. This doesn't just include the error numbers and error strings, but also the signal numbers -an a wide variety of miscellaneous constants. The constants come from the list +and a wide variety of miscellaneous constants. The constants come from the list of include files in the `includes_${uname}` variable. A regex then picks out the desired `#define` statements, and generates the corresponding Go constants. The error numbers and strings are generated from `#include `, and the @@ -149,21 +149,21 @@ To add a constant, add the header that includes it to the appropriate variable. Then, edit the regex (if necessary) to match the desired constant. Avoid making the regex too broad to avoid matching unintended constants. -### mkmerge.go +### internal/mkmerge This program is used to extract duplicate const, func, and type declarations 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. ## Generated files -### `zerror_${GOOS}_${GOARCH}.go` +### `zerrors_${GOOS}_${GOARCH}.go` A file containing all of the system's generated error numbers, error strings, signal numbers, and constants. Generated by `mkerrors.sh` (see above). diff --git a/vendor/golang.org/x/sys/unix/affinity_linux.go b/vendor/golang.org/x/sys/unix/affinity_linux.go index 6e5c81a..3ea4703 100644 --- a/vendor/golang.org/x/sys/unix/affinity_linux.go +++ b/vendor/golang.org/x/sys/unix/affinity_linux.go @@ -38,8 +38,15 @@ func SchedSetaffinity(pid int, set *CPUSet) error { // Zero clears the set s, so that it contains no CPUs. func (s *CPUSet) Zero() { + clear(s[:]) +} + +// Fill adds all possible CPU bits to the set s. On Linux, [SchedSetaffinity] +// will silently ignore any invalid CPU bits in [CPUSet] so this is an +// efficient way of resetting the CPU affinity of a process. +func (s *CPUSet) Fill() { for i := range s { - s[i] = 0 + s[i] = ^cpuMask(0) } } diff --git a/vendor/golang.org/x/sys/unix/aliases.go b/vendor/golang.org/x/sys/unix/aliases.go index 951fce4..b0e4198 100644 --- a/vendor/golang.org/x/sys/unix/aliases.go +++ b/vendor/golang.org/x/sys/unix/aliases.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris -// +build go1.9 +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos package unix diff --git a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s index 06f84b8..269e173 100644 --- a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s +++ b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_386.s b/vendor/golang.org/x/sys/unix/asm_bsd_386.s similarity index 75% rename from vendor/golang.org/x/sys/unix/asm_darwin_386.s rename to vendor/golang.org/x/sys/unix/asm_bsd_386.s index 8a72783..a4fcef0 100644 --- a/vendor/golang.org/x/sys/unix/asm_darwin_386.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_386.s @@ -1,14 +1,12 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build (freebsd || netbsd || openbsd) && gc #include "textflag.h" -// -// System call support for 386, Darwin -// +// System call support for 386 BSD // Just jump to package syscall's implementation for all these functions. // The runtime may know about them. @@ -22,7 +20,7 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-40 TEXT ·Syscall9(SB),NOSPLIT,$0-52 JMP syscall·Syscall9(SB) -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 +TEXT ·RawSyscall(SB),NOSPLIT,$0-28 JMP syscall·RawSyscall(SB) TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s new file mode 100644 index 0000000..1e63615 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc + +#include "textflag.h" + +// System call support for AMD64 BSD + +// Just jump to package syscall's implementation for all these functions. +// The runtime may know about them. + +TEXT ·Syscall(SB),NOSPLIT,$0-56 + JMP syscall·Syscall(SB) + +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + JMP syscall·Syscall6(SB) + +TEXT ·Syscall9(SB),NOSPLIT,$0-104 + JMP syscall·Syscall9(SB) + +TEXT ·RawSyscall(SB),NOSPLIT,$0-56 + JMP syscall·RawSyscall(SB) + +TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 + JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s similarity index 79% rename from vendor/golang.org/x/sys/unix/asm_netbsd_arm.s rename to vendor/golang.org/x/sys/unix/asm_bsd_arm.s index e892857..6496c31 100644 --- a/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s @@ -1,14 +1,12 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build (freebsd || netbsd || openbsd) && gc #include "textflag.h" -// -// System call support for ARM, NetBSD -// +// System call support for ARM BSD // Just jump to package syscall's implementation for all these functions. // The runtime may know about them. diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s similarity index 78% rename from vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s rename to vendor/golang.org/x/sys/unix/asm_bsd_arm64.s index 2ede05c..4fd1f54 100644 --- a/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s @@ -1,14 +1,12 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build (darwin || freebsd || netbsd || openbsd) && gc #include "textflag.h" -// -// System call support for AMD64, NetBSD -// +// System call support for ARM64 BSD // Just jump to package syscall's implementation for all these functions. // The runtime may know about them. diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s b/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s similarity index 78% rename from vendor/golang.org/x/sys/unix/asm_darwin_amd64.s rename to vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s index 6321421..42f7eb9 100644 --- a/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s @@ -1,13 +1,13 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2022 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build (darwin || freebsd || netbsd || openbsd) && gc #include "textflag.h" // -// System call support for AMD64, Darwin +// System call support for ppc64, BSD // // Just jump to package syscall's implementation for all these functions. diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s similarity index 78% rename from vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s rename to vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s index 790ef77..f890266 100644 --- a/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s @@ -1,14 +1,12 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build (darwin || freebsd || netbsd || openbsd) && gc #include "textflag.h" -// -// System call support for AMD64, OpenBSD -// +// System call support for RISCV64 BSD // Just jump to package syscall's implementation for all these functions. // The runtime may know about them. diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s deleted file mode 100644 index 333242d..0000000 --- a/vendor/golang.org/x/sys/unix/asm_darwin_arm.s +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo -// +build arm,darwin - -#include "textflag.h" - -// -// System call support for ARM, Darwin -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-28 - B syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - B syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-52 - B syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - B syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - B syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s deleted file mode 100644 index 97e0174..0000000 --- a/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo -// +build arm64,darwin - -#include "textflag.h" - -// -// System call support for AMD64, Darwin -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-56 - B syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - B syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-104 - B syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - B syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - B syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s deleted file mode 100644 index 603dd57..0000000 --- a/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for AMD64, DragonFly -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-56 - JMP syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - JMP syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-104 - JMP syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - JMP syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_386.s b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s deleted file mode 100644 index c9a0a26..0000000 --- a/vendor/golang.org/x/sys/unix/asm_freebsd_386.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for 386, FreeBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-28 - JMP syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - JMP syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-52 - JMP syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - JMP syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s deleted file mode 100644 index 3517247..0000000 --- a/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for AMD64, FreeBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-56 - JMP syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - JMP syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-104 - JMP syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - JMP syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s deleted file mode 100644 index 9227c87..0000000 --- a/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for ARM, FreeBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-28 - B syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - B syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-52 - B syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - B syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - B syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s b/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s deleted file mode 100644 index d9318cb..0000000 --- a/vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s +++ /dev/null @@ -1,29 +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. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for ARM64, FreeBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-56 - JMP syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - JMP syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-104 - JMP syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - JMP syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_linux_386.s b/vendor/golang.org/x/sys/unix/asm_linux_386.s index 448bebb..3b47348 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_386.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s index c6468a9..67e29f3 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/vendor/golang.org/x/sys/unix/asm_linux_arm.s index cf0f357..d6ae269 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s index afe6fdf..01e5e25 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build arm64 -// +build !gccgo +//go:build linux && arm64 && gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_loong64.s b/vendor/golang.org/x/sys/unix/asm_linux_loong64.s new file mode 100644 index 0000000..2abf12f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/asm_linux_loong64.s @@ -0,0 +1,51 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && loong64 && gc + +#include "textflag.h" + + +// Just jump to package syscall's implementation for all these functions. +// The runtime may know about them. + +TEXT ·Syscall(SB),NOSPLIT,$0-56 + JMP syscall·Syscall(SB) + +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + JMP syscall·Syscall6(SB) + +TEXT ·SyscallNoError(SB),NOSPLIT,$0-48 + JAL runtime·entersyscall(SB) + MOVV a1+8(FP), R4 + MOVV a2+16(FP), R5 + MOVV a3+24(FP), R6 + MOVV R0, R7 + MOVV R0, R8 + MOVV R0, R9 + MOVV trap+0(FP), R11 // syscall entry + SYSCALL + MOVV R4, r1+32(FP) + MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 + JAL runtime·exitsyscall(SB) + RET + +TEXT ·RawSyscall(SB),NOSPLIT,$0-56 + JMP syscall·RawSyscall(SB) + +TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 + JMP syscall·RawSyscall6(SB) + +TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48 + MOVV a1+8(FP), R4 + MOVV a2+16(FP), R5 + MOVV a3+24(FP), R6 + MOVV R0, R7 + MOVV R0, R8 + MOVV R0, R9 + MOVV trap+0(FP), R11 // syscall entry + SYSCALL + MOVV R4, r1+32(FP) + MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 + RET diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s index ab9d638..f84bae7 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build mips64 mips64le -// +build !gccgo +//go:build linux && (mips64 || mips64le) && gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s index 99e5399..f08f628 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build mips mipsle -// +build !gccgo +//go:build linux && (mips || mipsle) && gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s index 88f7125..bdfc024 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build ppc64 ppc64le -// +build !gccgo +//go:build linux && (ppc64 || ppc64le) && gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s b/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s index 3cfefed..2e8c996 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build riscv64,!gccgo +//go:build riscv64 && gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s index a5a863c..2c394b1 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build s390x -// +build linux -// +build !gccgo +//go:build linux && s390x && gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_386.s b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s deleted file mode 100644 index 48bdcd7..0000000 --- a/vendor/golang.org/x/sys/unix/asm_netbsd_386.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for 386, NetBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-28 - JMP syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - JMP syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-52 - JMP syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - JMP syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s b/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s deleted file mode 100644 index 6f98ba5..0000000 --- a/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for ARM64, NetBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-56 - B syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - B syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-104 - B syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - B syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - B syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_386.s b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s deleted file mode 100644 index 00576f3..0000000 --- a/vendor/golang.org/x/sys/unix/asm_openbsd_386.s +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for 386, OpenBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-28 - JMP syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - JMP syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-52 - JMP syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - JMP syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - JMP syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s deleted file mode 100644 index 469bfa1..0000000 --- a/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s +++ /dev/null @@ -1,29 +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. - -// +build !gccgo - -#include "textflag.h" - -// -// System call support for ARM, OpenBSD -// - -// Just jump to package syscall's implementation for all these functions. -// The runtime may know about them. - -TEXT ·Syscall(SB),NOSPLIT,$0-28 - B syscall·Syscall(SB) - -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - B syscall·Syscall6(SB) - -TEXT ·Syscall9(SB),NOSPLIT,$0-52 - B syscall·Syscall9(SB) - -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - B syscall·RawSyscall(SB) - -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - B syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s b/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s similarity index 91% rename from vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s rename to vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s index 0cedea3..fab586a 100644 --- a/vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s +++ b/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" // -// System call support for arm64, OpenBSD +// System call support for mips64, OpenBSD // // Just jump to package syscall's implementation for all these functions. diff --git a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s index ded8260..f949ec5 100644 --- a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +//go:build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s new file mode 100644 index 0000000..813dfad --- /dev/null +++ b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s @@ -0,0 +1,382 @@ +// 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 && gc + +#include "textflag.h" + +#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 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) +#define SS_GO(x) 8(x) +#define SS_ERRNO(x) 16(x) +#define SS_ERRNOJR(x) 20(x) + +// Function Descriptor Offsets +#define __errno 0x156*16 +#define __err2ad 0x16C*16 + +// 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 + // Get library control area (LCA). + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + + // Get __errno FuncDesc. + 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) + + // 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 + +// 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) + + 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 + + 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 + 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, 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) + SVC_DELETE + MOVD R2, R15 // Restore go stack pointer + +error: + MOVD $0, ret+8(FP) // Return 0 on failure + +done: + 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 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 +TEXT ·gettid(SB), NOSPLIT, $0 + // Get library control area (LCA). + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + + // Get CEECAATHDID + MOVD CAA(R8), 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 diff --git a/vendor/golang.org/x/sys/unix/auxv.go b/vendor/golang.org/x/sys/unix/auxv.go new file mode 100644 index 0000000..37a8252 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/auxv.go @@ -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 +} diff --git a/vendor/golang.org/x/sys/unix/auxv_unsupported.go b/vendor/golang.org/x/sys/unix/auxv_unsupported.go new file mode 100644 index 0000000..1200487 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/auxv_unsupported.go @@ -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 +} diff --git a/vendor/golang.org/x/sys/unix/bpxsvc_zos.go b/vendor/golang.org/x/sys/unix/bpxsvc_zos.go new file mode 100644 index 0000000..39d647d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/bpxsvc_zos.go @@ -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 +} diff --git a/vendor/golang.org/x/sys/unix/bpxsvc_zos.s b/vendor/golang.org/x/sys/unix/bpxsvc_zos.s new file mode 100644 index 0000000..4bd4a17 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/bpxsvc_zos.s @@ -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 diff --git a/vendor/golang.org/x/sys/unix/cap_freebsd.go b/vendor/golang.org/x/sys/unix/cap_freebsd.go index df52048..a086578 100644 --- a/vendor/golang.org/x/sys/unix/cap_freebsd.go +++ b/vendor/golang.org/x/sys/unix/cap_freebsd.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd +//go:build freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/constants.go b/vendor/golang.org/x/sys/unix/constants.go index 3a6ac64..6fb7cb7 100644 --- a/vendor/golang.org/x/sys/unix/constants.go +++ b/vendor/golang.org/x/sys/unix/constants.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos package unix diff --git a/vendor/golang.org/x/sys/unix/dev_aix_ppc.go b/vendor/golang.org/x/sys/unix/dev_aix_ppc.go index 5e5fb45..d785134 100644 --- a/vendor/golang.org/x/sys/unix/dev_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/dev_aix_ppc.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix -// +build ppc +//go:build aix && ppc // Functions to access/create device major and minor numbers matching the // encoding used by AIX. diff --git a/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go b/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go index 8b40124..623a5e6 100644 --- a/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix -// +build ppc64 +//go:build aix && ppc64 // Functions to access/create device major and minor numbers matching the // encoding used AIX. diff --git a/vendor/golang.org/x/sys/unix/dev_zos.go b/vendor/golang.org/x/sys/unix/dev_zos.go new file mode 100644 index 0000000..bb6a64f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/dev_zos.go @@ -0,0 +1,28 @@ +// 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 + +// Functions to access/create device major and minor numbers matching the +// encoding used by z/OS. +// +// The information below is extracted and adapted from macros. + +package unix + +// Major returns the major component of a z/OS device number. +func Major(dev uint64) uint32 { + return uint32((dev >> 16) & 0x0000FFFF) +} + +// Minor returns the minor component of a z/OS device number. +func Minor(dev uint64) uint32 { + return uint32(dev & 0x0000FFFF) +} + +// Mkdev returns a z/OS device number generated from the given major and minor +// components. +func Mkdev(major, minor uint32) uint64 { + return (uint64(major) << 16) | uint64(minor) +} diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go index 304016b..1ebf117 100644 --- a/vendor/golang.org/x/sys/unix/dirent.go +++ b/vendor/golang.org/x/sys/unix/dirent.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos package unix diff --git a/vendor/golang.org/x/sys/unix/endian_big.go b/vendor/golang.org/x/sys/unix/endian_big.go index 5e92690..1095fd3 100644 --- a/vendor/golang.org/x/sys/unix/endian_big.go +++ b/vendor/golang.org/x/sys/unix/endian_big.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -// +build ppc64 s390x mips mips64 +//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/endian_little.go b/vendor/golang.org/x/sys/unix/endian_little.go index bcdb5d3..b9f0e27 100644 --- a/vendor/golang.org/x/sys/unix/endian_little.go +++ b/vendor/golang.org/x/sys/unix/endian_little.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64 +//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh package unix diff --git a/vendor/golang.org/x/sys/unix/env_unix.go b/vendor/golang.org/x/sys/unix/env_unix.go index 84178b0..a96da71 100644 --- a/vendor/golang.org/x/sys/unix/env_unix.go +++ b/vendor/golang.org/x/sys/unix/env_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // Unix environment variables. diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_386.go b/vendor/golang.org/x/sys/unix/errors_freebsd_386.go deleted file mode 100644 index 761db66..0000000 --- a/vendor/golang.org/x/sys/unix/errors_freebsd_386.go +++ /dev/null @@ -1,233 +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. - -// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep -// them here for backwards compatibility. - -package unix - -const ( - DLT_HHDLC = 0x79 - IFF_SMART = 0x20 - IFT_1822 = 0x2 - IFT_A12MPPSWITCH = 0x82 - IFT_AAL2 = 0xbb - IFT_AAL5 = 0x31 - IFT_ADSL = 0x5e - IFT_AFLANE8023 = 0x3b - IFT_AFLANE8025 = 0x3c - IFT_ARAP = 0x58 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ASYNC = 0x54 - IFT_ATM = 0x25 - IFT_ATMDXI = 0x69 - IFT_ATMFUNI = 0x6a - IFT_ATMIMA = 0x6b - IFT_ATMLOGICAL = 0x50 - IFT_ATMRADIO = 0xbd - IFT_ATMSUBINTERFACE = 0x86 - IFT_ATMVCIENDPT = 0xc2 - IFT_ATMVIRTUAL = 0x95 - IFT_BGPPOLICYACCOUNTING = 0xa2 - IFT_BSC = 0x53 - IFT_CCTEMUL = 0x3d - IFT_CEPT = 0x13 - IFT_CES = 0x85 - IFT_CHANNEL = 0x46 - IFT_CNR = 0x55 - IFT_COFFEE = 0x84 - IFT_COMPOSITELINK = 0x9b - IFT_DCN = 0x8d - IFT_DIGITALPOWERLINE = 0x8a - IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba - IFT_DLSW = 0x4a - IFT_DOCSCABLEDOWNSTREAM = 0x80 - IFT_DOCSCABLEMACLAYER = 0x7f - IFT_DOCSCABLEUPSTREAM = 0x81 - IFT_DS0 = 0x51 - IFT_DS0BUNDLE = 0x52 - IFT_DS1FDL = 0xaa - IFT_DS3 = 0x1e - IFT_DTM = 0x8c - IFT_DVBASILN = 0xac - IFT_DVBASIOUT = 0xad - IFT_DVBRCCDOWNSTREAM = 0x93 - IFT_DVBRCCMACLAYER = 0x92 - IFT_DVBRCCUPSTREAM = 0x94 - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_EPLRS = 0x57 - IFT_ESCON = 0x49 - IFT_ETHER = 0x6 - IFT_FAITH = 0xf2 - IFT_FAST = 0x7d - IFT_FASTETHER = 0x3e - IFT_FASTETHERFX = 0x45 - IFT_FDDI = 0xf - IFT_FIBRECHANNEL = 0x38 - IFT_FRAMERELAYINTERCONNECT = 0x3a - IFT_FRAMERELAYMPI = 0x5c - IFT_FRDLCIENDPT = 0xc1 - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_FRF16MFRBUNDLE = 0xa3 - IFT_FRFORWARD = 0x9e - IFT_G703AT2MB = 0x43 - IFT_G703AT64K = 0x42 - IFT_GIF = 0xf0 - IFT_GIGABITETHERNET = 0x75 - IFT_GR303IDT = 0xb2 - IFT_GR303RDT = 0xb1 - IFT_H323GATEKEEPER = 0xa4 - IFT_H323PROXY = 0xa5 - IFT_HDH1822 = 0x3 - IFT_HDLC = 0x76 - IFT_HDSL2 = 0xa8 - IFT_HIPERLAN2 = 0xb7 - IFT_HIPPI = 0x2f - IFT_HIPPIINTERFACE = 0x39 - IFT_HOSTPAD = 0x5a - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IBM370PARCHAN = 0x48 - IFT_IDSL = 0x9a - IFT_IEEE80211 = 0x47 - IFT_IEEE80212 = 0x37 - IFT_IEEE8023ADLAG = 0xa1 - IFT_IFGSN = 0x91 - IFT_IMT = 0xbe - IFT_INTERLEAVE = 0x7c - IFT_IP = 0x7e - IFT_IPFORWARD = 0x8e - IFT_IPOVERATM = 0x72 - IFT_IPOVERCDLC = 0x6d - IFT_IPOVERCLAW = 0x6e - IFT_IPSWITCH = 0x4e - IFT_IPXIP = 0xf9 - IFT_ISDN = 0x3f - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISDNS = 0x4b - IFT_ISDNU = 0x4c - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88025CRFPINT = 0x62 - IFT_ISO88025DTR = 0x56 - IFT_ISO88025FIBER = 0x73 - IFT_ISO88026 = 0xa - IFT_ISUP = 0xb3 - IFT_L3IPXVLAN = 0x89 - IFT_LAPB = 0x10 - IFT_LAPD = 0x4d - IFT_LAPF = 0x77 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MEDIAMAILOVERIP = 0x8b - IFT_MFSIGLINK = 0xa7 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_MPC = 0x71 - IFT_MPLS = 0xa6 - IFT_MPLSTUNNEL = 0x96 - IFT_MSDSL = 0x8f - IFT_MVL = 0xbf - IFT_MYRINET = 0x63 - IFT_NFAS = 0xaf - IFT_NSIP = 0x1b - IFT_OPTICALCHANNEL = 0xc3 - IFT_OPTICALTRANSPORT = 0xc4 - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PFLOG = 0xf6 - IFT_PFSYNC = 0xf7 - IFT_PLC = 0xae - IFT_POS = 0xab - IFT_PPPMULTILINKBUNDLE = 0x6c - IFT_PROPBWAP2MP = 0xb8 - IFT_PROPCNLS = 0x59 - IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 - IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 - IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 - IFT_PROPMUX = 0x36 - IFT_PROPWIRELESSP2P = 0x9d - IFT_PTPSERIAL = 0x16 - IFT_PVC = 0xf1 - IFT_QLLC = 0x44 - IFT_RADIOMAC = 0xbc - IFT_RADSL = 0x5f - IFT_REACHDSL = 0xc0 - IFT_RFC1483 = 0x9f - IFT_RS232 = 0x21 - IFT_RSRB = 0x4f - IFT_SDLC = 0x11 - IFT_SDSL = 0x60 - IFT_SHDSL = 0xa9 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETOVERHEADCHANNEL = 0xb9 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_SRP = 0x97 - IFT_SS7SIGLINK = 0x9c - IFT_STACKTOSTACK = 0x6f - IFT_STARLAN = 0xb - IFT_STF = 0xd7 - IFT_T1 = 0x12 - IFT_TDLC = 0x74 - IFT_TERMPAD = 0x5b - IFT_TR008 = 0xb0 - IFT_TRANSPHDLC = 0x7b - IFT_TUNNEL = 0x83 - IFT_ULTRA = 0x1d - IFT_USB = 0xa0 - IFT_V11 = 0x40 - IFT_V35 = 0x2d - IFT_V36 = 0x41 - IFT_V37 = 0x78 - IFT_VDSL = 0x61 - IFT_VIRTUALIPADDRESS = 0x70 - IFT_VOICEEM = 0x64 - IFT_VOICEENCAP = 0x67 - IFT_VOICEFXO = 0x65 - IFT_VOICEFXS = 0x66 - IFT_VOICEOVERATM = 0x98 - IFT_VOICEOVERFRAMERELAY = 0x99 - IFT_VOICEOVERIP = 0x68 - IFT_X213 = 0x5d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25HUNTGROUP = 0x7a - IFT_X25MLP = 0x79 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IPPROTO_MAXID = 0x34 - IPV6_FAITH = 0x1d - IPV6_MIN_MEMBERSHIPS = 0x1f - IP_FAITH = 0x16 - IP_MAX_SOURCE_FILTER = 0x400 - IP_MIN_MEMBERSHIPS = 0x1f - MAP_NORESERVE = 0x40 - MAP_RENAME = 0x20 - NET_RT_MAXID = 0x6 - RTF_PRCLONING = 0x10000 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RT_CACHING_CONTEXT = 0x1 - RT_NORTREF = 0x2 - SIOCADDRT = 0x8030720a - SIOCALIFADDR = 0x8118691b - SIOCDELRT = 0x8030720b - SIOCDLIFADDR = 0x8118691d - SIOCGLIFADDR = 0xc118691c - SIOCGLIFPHYADDR = 0xc118694b - SIOCSLIFPHYADDR = 0x8118694a -) diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go deleted file mode 100644 index 070f44b..0000000 --- a/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go +++ /dev/null @@ -1,233 +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. - -// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep -// them here for backwards compatibility. - -package unix - -const ( - DLT_HHDLC = 0x79 - IFF_SMART = 0x20 - IFT_1822 = 0x2 - IFT_A12MPPSWITCH = 0x82 - IFT_AAL2 = 0xbb - IFT_AAL5 = 0x31 - IFT_ADSL = 0x5e - IFT_AFLANE8023 = 0x3b - IFT_AFLANE8025 = 0x3c - IFT_ARAP = 0x58 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ASYNC = 0x54 - IFT_ATM = 0x25 - IFT_ATMDXI = 0x69 - IFT_ATMFUNI = 0x6a - IFT_ATMIMA = 0x6b - IFT_ATMLOGICAL = 0x50 - IFT_ATMRADIO = 0xbd - IFT_ATMSUBINTERFACE = 0x86 - IFT_ATMVCIENDPT = 0xc2 - IFT_ATMVIRTUAL = 0x95 - IFT_BGPPOLICYACCOUNTING = 0xa2 - IFT_BSC = 0x53 - IFT_CCTEMUL = 0x3d - IFT_CEPT = 0x13 - IFT_CES = 0x85 - IFT_CHANNEL = 0x46 - IFT_CNR = 0x55 - IFT_COFFEE = 0x84 - IFT_COMPOSITELINK = 0x9b - IFT_DCN = 0x8d - IFT_DIGITALPOWERLINE = 0x8a - IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba - IFT_DLSW = 0x4a - IFT_DOCSCABLEDOWNSTREAM = 0x80 - IFT_DOCSCABLEMACLAYER = 0x7f - IFT_DOCSCABLEUPSTREAM = 0x81 - IFT_DS0 = 0x51 - IFT_DS0BUNDLE = 0x52 - IFT_DS1FDL = 0xaa - IFT_DS3 = 0x1e - IFT_DTM = 0x8c - IFT_DVBASILN = 0xac - IFT_DVBASIOUT = 0xad - IFT_DVBRCCDOWNSTREAM = 0x93 - IFT_DVBRCCMACLAYER = 0x92 - IFT_DVBRCCUPSTREAM = 0x94 - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_EPLRS = 0x57 - IFT_ESCON = 0x49 - IFT_ETHER = 0x6 - IFT_FAITH = 0xf2 - IFT_FAST = 0x7d - IFT_FASTETHER = 0x3e - IFT_FASTETHERFX = 0x45 - IFT_FDDI = 0xf - IFT_FIBRECHANNEL = 0x38 - IFT_FRAMERELAYINTERCONNECT = 0x3a - IFT_FRAMERELAYMPI = 0x5c - IFT_FRDLCIENDPT = 0xc1 - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_FRF16MFRBUNDLE = 0xa3 - IFT_FRFORWARD = 0x9e - IFT_G703AT2MB = 0x43 - IFT_G703AT64K = 0x42 - IFT_GIF = 0xf0 - IFT_GIGABITETHERNET = 0x75 - IFT_GR303IDT = 0xb2 - IFT_GR303RDT = 0xb1 - IFT_H323GATEKEEPER = 0xa4 - IFT_H323PROXY = 0xa5 - IFT_HDH1822 = 0x3 - IFT_HDLC = 0x76 - IFT_HDSL2 = 0xa8 - IFT_HIPERLAN2 = 0xb7 - IFT_HIPPI = 0x2f - IFT_HIPPIINTERFACE = 0x39 - IFT_HOSTPAD = 0x5a - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IBM370PARCHAN = 0x48 - IFT_IDSL = 0x9a - IFT_IEEE80211 = 0x47 - IFT_IEEE80212 = 0x37 - IFT_IEEE8023ADLAG = 0xa1 - IFT_IFGSN = 0x91 - IFT_IMT = 0xbe - IFT_INTERLEAVE = 0x7c - IFT_IP = 0x7e - IFT_IPFORWARD = 0x8e - IFT_IPOVERATM = 0x72 - IFT_IPOVERCDLC = 0x6d - IFT_IPOVERCLAW = 0x6e - IFT_IPSWITCH = 0x4e - IFT_IPXIP = 0xf9 - IFT_ISDN = 0x3f - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISDNS = 0x4b - IFT_ISDNU = 0x4c - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88025CRFPINT = 0x62 - IFT_ISO88025DTR = 0x56 - IFT_ISO88025FIBER = 0x73 - IFT_ISO88026 = 0xa - IFT_ISUP = 0xb3 - IFT_L3IPXVLAN = 0x89 - IFT_LAPB = 0x10 - IFT_LAPD = 0x4d - IFT_LAPF = 0x77 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MEDIAMAILOVERIP = 0x8b - IFT_MFSIGLINK = 0xa7 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_MPC = 0x71 - IFT_MPLS = 0xa6 - IFT_MPLSTUNNEL = 0x96 - IFT_MSDSL = 0x8f - IFT_MVL = 0xbf - IFT_MYRINET = 0x63 - IFT_NFAS = 0xaf - IFT_NSIP = 0x1b - IFT_OPTICALCHANNEL = 0xc3 - IFT_OPTICALTRANSPORT = 0xc4 - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PFLOG = 0xf6 - IFT_PFSYNC = 0xf7 - IFT_PLC = 0xae - IFT_POS = 0xab - IFT_PPPMULTILINKBUNDLE = 0x6c - IFT_PROPBWAP2MP = 0xb8 - IFT_PROPCNLS = 0x59 - IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 - IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 - IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 - IFT_PROPMUX = 0x36 - IFT_PROPWIRELESSP2P = 0x9d - IFT_PTPSERIAL = 0x16 - IFT_PVC = 0xf1 - IFT_QLLC = 0x44 - IFT_RADIOMAC = 0xbc - IFT_RADSL = 0x5f - IFT_REACHDSL = 0xc0 - IFT_RFC1483 = 0x9f - IFT_RS232 = 0x21 - IFT_RSRB = 0x4f - IFT_SDLC = 0x11 - IFT_SDSL = 0x60 - IFT_SHDSL = 0xa9 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETOVERHEADCHANNEL = 0xb9 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_SRP = 0x97 - IFT_SS7SIGLINK = 0x9c - IFT_STACKTOSTACK = 0x6f - IFT_STARLAN = 0xb - IFT_STF = 0xd7 - IFT_T1 = 0x12 - IFT_TDLC = 0x74 - IFT_TERMPAD = 0x5b - IFT_TR008 = 0xb0 - IFT_TRANSPHDLC = 0x7b - IFT_TUNNEL = 0x83 - IFT_ULTRA = 0x1d - IFT_USB = 0xa0 - IFT_V11 = 0x40 - IFT_V35 = 0x2d - IFT_V36 = 0x41 - IFT_V37 = 0x78 - IFT_VDSL = 0x61 - IFT_VIRTUALIPADDRESS = 0x70 - IFT_VOICEEM = 0x64 - IFT_VOICEENCAP = 0x67 - IFT_VOICEFXO = 0x65 - IFT_VOICEFXS = 0x66 - IFT_VOICEOVERATM = 0x98 - IFT_VOICEOVERFRAMERELAY = 0x99 - IFT_VOICEOVERIP = 0x68 - IFT_X213 = 0x5d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25HUNTGROUP = 0x7a - IFT_X25MLP = 0x79 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IPPROTO_MAXID = 0x34 - IPV6_FAITH = 0x1d - IPV6_MIN_MEMBERSHIPS = 0x1f - IP_FAITH = 0x16 - IP_MAX_SOURCE_FILTER = 0x400 - IP_MIN_MEMBERSHIPS = 0x1f - MAP_NORESERVE = 0x40 - MAP_RENAME = 0x20 - NET_RT_MAXID = 0x6 - RTF_PRCLONING = 0x10000 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RT_CACHING_CONTEXT = 0x1 - RT_NORTREF = 0x2 - SIOCADDRT = 0x8040720a - SIOCALIFADDR = 0x8118691b - SIOCDELRT = 0x8040720b - SIOCDLIFADDR = 0x8118691d - SIOCGLIFADDR = 0xc118691c - SIOCGLIFPHYADDR = 0xc118694b - SIOCSLIFPHYADDR = 0x8118694a -) diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go deleted file mode 100644 index 856dca3..0000000 --- a/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go +++ /dev/null @@ -1,226 +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. - -package unix - -const ( - IFT_1822 = 0x2 - IFT_A12MPPSWITCH = 0x82 - IFT_AAL2 = 0xbb - IFT_AAL5 = 0x31 - IFT_ADSL = 0x5e - IFT_AFLANE8023 = 0x3b - IFT_AFLANE8025 = 0x3c - IFT_ARAP = 0x58 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ASYNC = 0x54 - IFT_ATM = 0x25 - IFT_ATMDXI = 0x69 - IFT_ATMFUNI = 0x6a - IFT_ATMIMA = 0x6b - IFT_ATMLOGICAL = 0x50 - IFT_ATMRADIO = 0xbd - IFT_ATMSUBINTERFACE = 0x86 - IFT_ATMVCIENDPT = 0xc2 - IFT_ATMVIRTUAL = 0x95 - IFT_BGPPOLICYACCOUNTING = 0xa2 - IFT_BSC = 0x53 - IFT_CCTEMUL = 0x3d - IFT_CEPT = 0x13 - IFT_CES = 0x85 - IFT_CHANNEL = 0x46 - IFT_CNR = 0x55 - IFT_COFFEE = 0x84 - IFT_COMPOSITELINK = 0x9b - IFT_DCN = 0x8d - IFT_DIGITALPOWERLINE = 0x8a - IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba - IFT_DLSW = 0x4a - IFT_DOCSCABLEDOWNSTREAM = 0x80 - IFT_DOCSCABLEMACLAYER = 0x7f - IFT_DOCSCABLEUPSTREAM = 0x81 - IFT_DS0 = 0x51 - IFT_DS0BUNDLE = 0x52 - IFT_DS1FDL = 0xaa - IFT_DS3 = 0x1e - IFT_DTM = 0x8c - IFT_DVBASILN = 0xac - IFT_DVBASIOUT = 0xad - IFT_DVBRCCDOWNSTREAM = 0x93 - IFT_DVBRCCMACLAYER = 0x92 - IFT_DVBRCCUPSTREAM = 0x94 - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_EPLRS = 0x57 - IFT_ESCON = 0x49 - IFT_ETHER = 0x6 - IFT_FAST = 0x7d - IFT_FASTETHER = 0x3e - IFT_FASTETHERFX = 0x45 - IFT_FDDI = 0xf - IFT_FIBRECHANNEL = 0x38 - IFT_FRAMERELAYINTERCONNECT = 0x3a - IFT_FRAMERELAYMPI = 0x5c - IFT_FRDLCIENDPT = 0xc1 - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_FRF16MFRBUNDLE = 0xa3 - IFT_FRFORWARD = 0x9e - IFT_G703AT2MB = 0x43 - IFT_G703AT64K = 0x42 - IFT_GIF = 0xf0 - IFT_GIGABITETHERNET = 0x75 - IFT_GR303IDT = 0xb2 - IFT_GR303RDT = 0xb1 - IFT_H323GATEKEEPER = 0xa4 - IFT_H323PROXY = 0xa5 - IFT_HDH1822 = 0x3 - IFT_HDLC = 0x76 - IFT_HDSL2 = 0xa8 - IFT_HIPERLAN2 = 0xb7 - IFT_HIPPI = 0x2f - IFT_HIPPIINTERFACE = 0x39 - IFT_HOSTPAD = 0x5a - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IBM370PARCHAN = 0x48 - IFT_IDSL = 0x9a - IFT_IEEE80211 = 0x47 - IFT_IEEE80212 = 0x37 - IFT_IEEE8023ADLAG = 0xa1 - IFT_IFGSN = 0x91 - IFT_IMT = 0xbe - IFT_INTERLEAVE = 0x7c - IFT_IP = 0x7e - IFT_IPFORWARD = 0x8e - IFT_IPOVERATM = 0x72 - IFT_IPOVERCDLC = 0x6d - IFT_IPOVERCLAW = 0x6e - IFT_IPSWITCH = 0x4e - IFT_ISDN = 0x3f - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISDNS = 0x4b - IFT_ISDNU = 0x4c - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88025CRFPINT = 0x62 - IFT_ISO88025DTR = 0x56 - IFT_ISO88025FIBER = 0x73 - IFT_ISO88026 = 0xa - IFT_ISUP = 0xb3 - IFT_L3IPXVLAN = 0x89 - IFT_LAPB = 0x10 - IFT_LAPD = 0x4d - IFT_LAPF = 0x77 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MEDIAMAILOVERIP = 0x8b - IFT_MFSIGLINK = 0xa7 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_MPC = 0x71 - IFT_MPLS = 0xa6 - IFT_MPLSTUNNEL = 0x96 - IFT_MSDSL = 0x8f - IFT_MVL = 0xbf - IFT_MYRINET = 0x63 - IFT_NFAS = 0xaf - IFT_NSIP = 0x1b - IFT_OPTICALCHANNEL = 0xc3 - IFT_OPTICALTRANSPORT = 0xc4 - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PFLOG = 0xf6 - IFT_PFSYNC = 0xf7 - IFT_PLC = 0xae - IFT_POS = 0xab - IFT_PPPMULTILINKBUNDLE = 0x6c - IFT_PROPBWAP2MP = 0xb8 - IFT_PROPCNLS = 0x59 - IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 - IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 - IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 - IFT_PROPMUX = 0x36 - IFT_PROPWIRELESSP2P = 0x9d - IFT_PTPSERIAL = 0x16 - IFT_PVC = 0xf1 - IFT_QLLC = 0x44 - IFT_RADIOMAC = 0xbc - IFT_RADSL = 0x5f - IFT_REACHDSL = 0xc0 - IFT_RFC1483 = 0x9f - IFT_RS232 = 0x21 - IFT_RSRB = 0x4f - IFT_SDLC = 0x11 - IFT_SDSL = 0x60 - IFT_SHDSL = 0xa9 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETOVERHEADCHANNEL = 0xb9 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_SRP = 0x97 - IFT_SS7SIGLINK = 0x9c - IFT_STACKTOSTACK = 0x6f - IFT_STARLAN = 0xb - IFT_STF = 0xd7 - IFT_T1 = 0x12 - IFT_TDLC = 0x74 - IFT_TERMPAD = 0x5b - IFT_TR008 = 0xb0 - IFT_TRANSPHDLC = 0x7b - IFT_TUNNEL = 0x83 - IFT_ULTRA = 0x1d - IFT_USB = 0xa0 - IFT_V11 = 0x40 - IFT_V35 = 0x2d - IFT_V36 = 0x41 - IFT_V37 = 0x78 - IFT_VDSL = 0x61 - IFT_VIRTUALIPADDRESS = 0x70 - IFT_VOICEEM = 0x64 - IFT_VOICEENCAP = 0x67 - IFT_VOICEFXO = 0x65 - IFT_VOICEFXS = 0x66 - IFT_VOICEOVERATM = 0x98 - IFT_VOICEOVERFRAMERELAY = 0x99 - IFT_VOICEOVERIP = 0x68 - IFT_X213 = 0x5d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25HUNTGROUP = 0x7a - IFT_X25MLP = 0x79 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - - // missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go - IFF_SMART = 0x20 - IFT_FAITH = 0xf2 - IFT_IPXIP = 0xf9 - IPPROTO_MAXID = 0x34 - IPV6_FAITH = 0x1d - IP_FAITH = 0x16 - MAP_NORESERVE = 0x40 - MAP_RENAME = 0x20 - NET_RT_MAXID = 0x6 - RTF_PRCLONING = 0x10000 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - SIOCADDRT = 0x8030720a - SIOCALIFADDR = 0x8118691b - SIOCDELRT = 0x8030720b - SIOCDLIFADDR = 0x8118691d - SIOCGLIFADDR = 0xc118691c - SIOCGLIFPHYADDR = 0xc118694b - SIOCSLIFPHYADDR = 0x8118694a -) diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go deleted file mode 100644 index 946dcf3..0000000 --- a/vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go +++ /dev/null @@ -1,17 +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. - -// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep -// them here for backwards compatibility. - -package unix - -const ( - DLT_HHDLC = 0x79 - IPV6_MIN_MEMBERSHIPS = 0x1f - IP_MAX_SOURCE_FILTER = 0x400 - IP_MIN_MEMBERSHIPS = 0x1f - RT_CACHING_CONTEXT = 0x1 - RT_NORTREF = 0x2 -) diff --git a/vendor/golang.org/x/sys/unix/fcntl.go b/vendor/golang.org/x/sys/unix/fcntl.go index 4dc5348..6200876 100644 --- a/vendor/golang.org/x/sys/unix/fcntl.go +++ b/vendor/golang.org/x/sys/unix/fcntl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build dragonfly freebsd linux netbsd openbsd +//go:build dragonfly || freebsd || linux || netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/fcntl_darwin.go b/vendor/golang.org/x/sys/unix/fcntl_darwin.go index 5868a4a..a9911c7 100644 --- a/vendor/golang.org/x/sys/unix/fcntl_darwin.go +++ b/vendor/golang.org/x/sys/unix/fcntl_darwin.go @@ -16,3 +16,9 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { _, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(lk)))) return err } + +// FcntlFstore performs a fcntl syscall for the F_PREALLOCATE command. +func FcntlFstore(fd uintptr, cmd int, fstore *Fstore_t) error { + _, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(fstore)))) + return err +} diff --git a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go index fc0e50e..13b4acd 100644 --- a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go +++ b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go @@ -1,9 +1,9 @@ -// +build linux,386 linux,arm linux,mips linux,mipsle - // 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 (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc) + package unix func init() { diff --git a/vendor/golang.org/x/sys/unix/fdset.go b/vendor/golang.org/x/sys/unix/fdset.go index b27be0a..62ed126 100644 --- a/vendor/golang.org/x/sys/unix/fdset.go +++ b/vendor/golang.org/x/sys/unix/fdset.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos package unix @@ -23,7 +23,5 @@ func (fds *FdSet) IsSet(fd int) bool { // Zero clears the set fds. func (fds *FdSet) Zero() { - for i := range fds.Bits { - fds.Bits[i] = 0 - } + clear(fds.Bits[:]) } diff --git a/vendor/golang.org/x/sys/unix/gccgo.go b/vendor/golang.org/x/sys/unix/gccgo.go index cd6f5a6..aca5721 100644 --- a/vendor/golang.org/x/sys/unix/gccgo.go +++ b/vendor/golang.org/x/sys/unix/gccgo.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build gccgo -// +build !aix +//go:build gccgo && !aix && !hurd package unix @@ -12,10 +11,8 @@ import "syscall" // We can't use the gc-syntax .s files for gccgo. On the plus side // much of the functionality can be written directly in Go. -//extern gccgoRealSyscallNoError func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr) -//extern gccgoRealSyscall func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr) func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) { diff --git a/vendor/golang.org/x/sys/unix/gccgo_c.c b/vendor/golang.org/x/sys/unix/gccgo_c.c index c44730c..d468b7b 100644 --- a/vendor/golang.org/x/sys/unix/gccgo_c.c +++ b/vendor/golang.org/x/sys/unix/gccgo_c.c @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build gccgo -// +build !aix +//go:build gccgo && !aix && !hurd #include #include @@ -21,6 +20,9 @@ struct ret { uintptr_t err; }; +struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) + __asm__(GOSYM_PREFIX GOPKGPATH ".realSyscall"); + struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) { @@ -32,6 +34,9 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp return r; } +uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) + __asm__(GOSYM_PREFIX GOPKGPATH ".realSyscallNoError"); + uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) { diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go index 251a977..972d61b 100644 --- a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build gccgo,linux,amd64 +//go:build gccgo && linux && amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/ifreq_linux.go b/vendor/golang.org/x/sys/unix/ifreq_linux.go new file mode 100644 index 0000000..309f5a2 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -0,0 +1,139 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux + +package unix + +import ( + "unsafe" +) + +// Helpers for dealing with ifreq since it contains a union and thus requires a +// lot of unsafe.Pointer casts to use properly. + +// An Ifreq is a type-safe wrapper around the raw ifreq struct. An Ifreq +// contains an interface name and a union of arbitrary data which can be +// accessed using the Ifreq's methods. To create an Ifreq, use the NewIfreq +// function. +// +// Use the Name method to access the stored interface name. The union data +// fields can be get and set using the following methods: +// - Uint16/SetUint16: flags +// - Uint32/SetUint32: ifindex, metric, mtu +type Ifreq struct{ raw ifreq } + +// NewIfreq creates an Ifreq with the input network interface name after +// validating the name does not exceed IFNAMSIZ-1 (trailing NULL required) +// bytes. +func NewIfreq(name string) (*Ifreq, error) { + // Leave room for terminating NULL byte. + if len(name) >= IFNAMSIZ { + return nil, EINVAL + } + + var ifr ifreq + copy(ifr.Ifrn[:], name) + + return &Ifreq{raw: ifr}, nil +} + +// TODO(mdlayher): get/set methods for hardware address sockaddr, char array, etc. + +// Name returns the interface name associated with the Ifreq. +func (ifr *Ifreq) Name() string { + return ByteSliceToString(ifr.raw.Ifrn[:]) +} + +// According to netdevice(7), only AF_INET addresses are returned for numerous +// sockaddr ioctls. For convenience, we expose these as Inet4Addr since the Port +// field and other data is always empty. + +// Inet4Addr returns the Ifreq union data from an embedded sockaddr as a C +// in_addr/Go []byte (4-byte IPv4 address) value. If the sockaddr family is not +// AF_INET, an error is returned. +func (ifr *Ifreq) Inet4Addr() ([]byte, error) { + raw := *(*RawSockaddrInet4)(unsafe.Pointer(&ifr.raw.Ifru[:SizeofSockaddrInet4][0])) + if raw.Family != AF_INET { + // Cannot safely interpret raw.Addr bytes as an IPv4 address. + return nil, EINVAL + } + + return raw.Addr[:], nil +} + +// SetInet4Addr sets a C in_addr/Go []byte (4-byte IPv4 address) value in an +// embedded sockaddr within the Ifreq's union data. v must be 4 bytes in length +// or an error will be returned. +func (ifr *Ifreq) SetInet4Addr(v []byte) error { + if len(v) != 4 { + return EINVAL + } + + var addr [4]byte + copy(addr[:], v) + + ifr.clear() + *(*RawSockaddrInet4)( + unsafe.Pointer(&ifr.raw.Ifru[:SizeofSockaddrInet4][0]), + ) = RawSockaddrInet4{ + // Always set IP family as ioctls would require it anyway. + Family: AF_INET, + Addr: addr, + } + + return nil +} + +// Uint16 returns the Ifreq union data as a C short/Go uint16 value. +func (ifr *Ifreq) Uint16() uint16 { + return *(*uint16)(unsafe.Pointer(&ifr.raw.Ifru[:2][0])) +} + +// SetUint16 sets a C short/Go uint16 value as the Ifreq's union data. +func (ifr *Ifreq) SetUint16(v uint16) { + ifr.clear() + *(*uint16)(unsafe.Pointer(&ifr.raw.Ifru[:2][0])) = v +} + +// Uint32 returns the Ifreq union data as a C int/Go uint32 value. +func (ifr *Ifreq) Uint32() uint32 { + return *(*uint32)(unsafe.Pointer(&ifr.raw.Ifru[:4][0])) +} + +// SetUint32 sets a C int/Go uint32 value as the Ifreq's union data. +func (ifr *Ifreq) SetUint32(v uint32) { + ifr.clear() + *(*uint32)(unsafe.Pointer(&ifr.raw.Ifru[:4][0])) = v +} + +// clear zeroes the ifreq's union field to prevent trailing garbage data from +// being sent to the kernel if an ifreq is reused. +func (ifr *Ifreq) clear() { + clear(ifr.raw.Ifru[:]) +} + +// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as +// IoctlGetEthtoolDrvinfo which use these APIs under the hood. + +// An ifreqData is an Ifreq which carries pointer data. To produce an ifreqData, +// use the Ifreq.withData method. +type ifreqData struct { + name [IFNAMSIZ]byte + // A type separate from ifreq is required in order to comply with the + // unsafe.Pointer rules since the "pointer-ness" of data would not be + // preserved if it were cast into the byte array of a raw ifreq. + data unsafe.Pointer + // Pad to the same size as ifreq. + _ [len(ifreq{}.Ifru) - SizeofPtr]byte +} + +// withData produces an ifreqData with the pointer p set for ioctls which require +// arbitrary pointer data. +func (ifr Ifreq) withData(p unsafe.Pointer) ifreqData { + return ifreqData{ + name: ifr.raw.Ifrn, + data: p, + } +} diff --git a/vendor/golang.org/x/sys/unix/ioctl_linux.go b/vendor/golang.org/x/sys/unix/ioctl_linux.go new file mode 100644 index 0000000..7ca4fa1 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -0,0 +1,334 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import "unsafe" + +// IoctlRetInt performs an ioctl operation specified by req on a device +// associated with opened file descriptor fd, and returns a non-negative +// integer that is returned by the ioctl syscall. +func IoctlRetInt(fd int, req uint) (int, error) { + ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0) + if err != 0 { + return 0, err + } + return int(ret), nil +} + +func IoctlGetUint32(fd int, req uint) (uint32, error) { + var value uint32 + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) + return value, err +} + +func IoctlGetRTCTime(fd int) (*RTCTime, error) { + var value RTCTime + err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value)) + return &value, err +} + +func IoctlSetRTCTime(fd int, value *RTCTime) error { + return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value)) +} + +func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { + var value RTCWkAlrm + err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value)) + return &value, err +} + +func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error { + return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value)) +} + +// IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network +// device specified by ifname. +func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { + ifr, err := NewIfreq(ifname) + if err != nil { + return nil, err + } + + value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO} + ifrd := ifr.withData(unsafe.Pointer(&value)) + + err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd) + 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. +func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { + var value WatchdogInfo + err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For +// more information, see: +// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. +func IoctlWatchdogKeepalive(fd int) error { + // arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr. + return ioctl(fd, WDIOC_KEEPALIVE, 0) +} + +// IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the +// range of data conveyed in value to the file associated with the file +// descriptor destFd. See the ioctl_ficlonerange(2) man page for details. +func IoctlFileCloneRange(destFd int, value *FileCloneRange) error { + return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value)) +} + +// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file +// associated with the file description srcFd to the file associated with the +// file descriptor destFd. See the ioctl_ficlone(2) man page for details. +func IoctlFileClone(destFd, srcFd int) error { + return ioctl(destFd, FICLONE, uintptr(srcFd)) +} + +type FileDedupeRange struct { + Src_offset uint64 + Src_length uint64 + Reserved1 uint16 + Reserved2 uint32 + Info []FileDedupeRangeInfo +} + +type FileDedupeRangeInfo struct { + Dest_fd int64 + Dest_offset uint64 + Bytes_deduped uint64 + Status int32 + Reserved uint32 +} + +// IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the +// range of data conveyed in value from the file associated with the file +// descriptor srcFd to the value.Info destinations. See the +// ioctl_fideduperange(2) man page for details. +func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error { + buf := make([]byte, SizeofRawFileDedupeRange+ + len(value.Info)*SizeofRawFileDedupeRangeInfo) + rawrange := (*RawFileDedupeRange)(unsafe.Pointer(&buf[0])) + rawrange.Src_offset = value.Src_offset + rawrange.Src_length = value.Src_length + rawrange.Dest_count = uint16(len(value.Info)) + rawrange.Reserved1 = value.Reserved1 + rawrange.Reserved2 = value.Reserved2 + + for i := range value.Info { + rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer( + uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) + + uintptr(i*SizeofRawFileDedupeRangeInfo))) + rawinfo.Dest_fd = value.Info[i].Dest_fd + rawinfo.Dest_offset = value.Info[i].Dest_offset + rawinfo.Bytes_deduped = value.Info[i].Bytes_deduped + rawinfo.Status = value.Info[i].Status + rawinfo.Reserved = value.Info[i].Reserved + } + + err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0])) + + // Output + for i := range value.Info { + rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer( + uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) + + uintptr(i*SizeofRawFileDedupeRangeInfo))) + value.Info[i].Dest_fd = rawinfo.Dest_fd + value.Info[i].Dest_offset = rawinfo.Dest_offset + value.Info[i].Bytes_deduped = rawinfo.Bytes_deduped + value.Info[i].Status = rawinfo.Status + value.Info[i].Reserved = rawinfo.Reserved + } + + return err +} + +func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error { + return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value)) +} + +func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) { + var value HIDRawDevInfo + err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value)) + return &value, err +} + +func IoctlHIDGetRawName(fd int) (string, error) { + var value [_HIDIOCGRAWNAME_LEN]byte + err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0])) + return ByteSliceToString(value[:]), err +} + +func IoctlHIDGetRawPhys(fd int) (string, error) { + var value [_HIDIOCGRAWPHYS_LEN]byte + err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0])) + return ByteSliceToString(value[:]), err +} + +func IoctlHIDGetRawUniq(fd int) (string, error) { + var value [_HIDIOCGRAWUNIQ_LEN]byte + err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0])) + return ByteSliceToString(value[:]), err +} + +// IoctlIfreq performs an ioctl using an Ifreq structure for input and/or +// output. See the netdevice(7) man page for details. +func IoctlIfreq(fd int, req uint, value *Ifreq) error { + // It is possible we will add more fields to *Ifreq itself later to prevent + // misuse, so pass the raw *ifreq directly. + return ioctlPtr(fd, req, unsafe.Pointer(&value.raw)) +} + +// TODO(mdlayher): export if and when IfreqData is exported. + +// ioctlIfreqData performs an ioctl using an ifreqData structure for input +// and/or output. See the netdevice(7) man page for details. +func ioctlIfreqData(fd int, req uint, value *ifreqData) error { + // The memory layout of IfreqData (type-safe) and ifreq (not type-safe) are + // identical so pass *IfreqData directly. + return ioctlPtr(fd, req, unsafe.Pointer(value)) +} + +// IoctlKCMClone attaches a new file descriptor to a multiplexor by cloning an +// existing KCM socket, returning a structure containing the file descriptor of +// the new socket. +func IoctlKCMClone(fd int) (*KCMClone, error) { + var info KCMClone + if err := ioctlPtr(fd, SIOCKCMCLONE, unsafe.Pointer(&info)); err != nil { + return nil, err + } + + return &info, nil +} + +// IoctlKCMAttach attaches a TCP socket and associated BPF program file +// descriptor to a multiplexor. +func IoctlKCMAttach(fd int, info KCMAttach) error { + return ioctlPtr(fd, SIOCKCMATTACH, unsafe.Pointer(&info)) +} + +// IoctlKCMUnattach unattaches a TCP socket file descriptor from a multiplexor. +func IoctlKCMUnattach(fd int, info KCMUnattach) error { + return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info)) +} + +// IoctlLoopGetStatus64 gets the status of the loop device associated with the +// file descriptor fd using the LOOP_GET_STATUS64 operation. +func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) { + var value LoopInfo64 + if err := ioctlPtr(fd, LOOP_GET_STATUS64, unsafe.Pointer(&value)); err != nil { + return nil, err + } + return &value, nil +} + +// IoctlLoopSetStatus64 sets the status of the loop device associated with the +// file descriptor fd using the LOOP_SET_STATUS64 operation. +func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error { + return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value)) +} + +// IoctlLoopConfigure configures all loop device parameters in a single step +func IoctlLoopConfigure(fd int, value *LoopConfig) error { + return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value)) +} diff --git a/vendor/golang.org/x/sys/unix/ioctl_signed.go b/vendor/golang.org/x/sys/unix/ioctl_signed.go new file mode 100644 index 0000000..5b0759b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ioctl_signed.go @@ -0,0 +1,69 @@ +// 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 aix || solaris + +package unix + +import ( + "unsafe" +) + +// ioctl itself should not be exposed directly, but additional get/set +// functions for specific types are permissible. + +// IoctlSetInt performs an ioctl operation which sets an integer value +// on fd, using the specified request number. +func IoctlSetInt(fd int, req int, value int) error { + return ioctl(fd, req, uintptr(value)) +} + +// IoctlSetPointerInt performs an ioctl operation which sets an +// integer value on fd, using the specified request number. The ioctl +// argument is called with a pointer to the integer value, rather than +// passing the integer value directly. +func IoctlSetPointerInt(fd int, req int, value int) error { + v := int32(value) + return ioctlPtr(fd, req, unsafe.Pointer(&v)) +} + +// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. +// +// To change fd's window size, the req argument should be TIOCSWINSZ. +func IoctlSetWinsize(fd int, req int, value *Winsize) error { + // TODO: if we get the chance, remove the req parameter and + // hardcode TIOCSWINSZ. + return ioctlPtr(fd, req, unsafe.Pointer(value)) +} + +// IoctlSetTermios performs an ioctl on fd with a *Termios. +// +// The req value will usually be TCSETA or TIOCSETA. +func IoctlSetTermios(fd int, req int, value *Termios) error { + // TODO: if we get the chance, remove the req parameter. + return ioctlPtr(fd, req, unsafe.Pointer(value)) +} + +// IoctlGetInt performs an ioctl operation which gets an integer value +// from fd, using the specified request number. +// +// A few ioctl requests use the return value as an output parameter; +// for those, IoctlRetInt should be used instead of this function. +func IoctlGetInt(fd int, req int) (int, error) { + var value int + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) + return value, err +} + +func IoctlGetWinsize(fd int, req int) (*Winsize, error) { + var value Winsize + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) + return &value, err +} + +func IoctlGetTermios(fd int, req int) (*Termios, error) { + var value Termios + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) + return &value, err +} diff --git a/vendor/golang.org/x/sys/unix/ioctl.go b/vendor/golang.org/x/sys/unix/ioctl_unsigned.go similarity index 69% rename from vendor/golang.org/x/sys/unix/ioctl.go rename to vendor/golang.org/x/sys/unix/ioctl_unsigned.go index 3559e5d..20f470b 100644 --- a/vendor/golang.org/x/sys/unix/ioctl.go +++ b/vendor/golang.org/x/sys/unix/ioctl_unsigned.go @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd package unix import ( - "runtime" "unsafe" ) @@ -20,15 +19,22 @@ func IoctlSetInt(fd int, req uint, value int) error { return ioctl(fd, req, uintptr(value)) } +// IoctlSetPointerInt performs an ioctl operation which sets an +// integer value on fd, using the specified request number. The ioctl +// argument is called with a pointer to the integer value, rather than +// passing the integer value directly. +func IoctlSetPointerInt(fd int, req uint, value int) error { + v := int32(value) + return ioctlPtr(fd, req, unsafe.Pointer(&v)) +} + // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // // To change fd's window size, the req argument should be TIOCSWINSZ. func IoctlSetWinsize(fd int, req uint, value *Winsize) error { // TODO: if we get the chance, remove the req parameter and // hardcode TIOCSWINSZ. - err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err + return ioctlPtr(fd, req, unsafe.Pointer(value)) } // IoctlSetTermios performs an ioctl on fd with a *Termios. @@ -36,9 +42,7 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error { // The req value will usually be TCSETA or TIOCSETA. func IoctlSetTermios(fd int, req uint, value *Termios) error { // TODO: if we get the chance, remove the req parameter. - err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err + return ioctlPtr(fd, req, unsafe.Pointer(value)) } // IoctlGetInt performs an ioctl operation which gets an integer value @@ -48,18 +52,18 @@ func IoctlSetTermios(fd int, req uint, value *Termios) error { // for those, IoctlRetInt should be used instead of this function. func IoctlGetInt(fd int, req uint) (int, error) { var value int - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) return value, err } func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { var value Winsize - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) return &value, err } func IoctlGetTermios(fd int, req uint) (*Termios, error) { var value Termios - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) return &value, err } diff --git a/vendor/golang.org/x/sys/unix/ioctl_zos.go b/vendor/golang.org/x/sys/unix/ioctl_zos.go new file mode 100644 index 0000000..c8b2a75 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ioctl_zos.go @@ -0,0 +1,71 @@ +// 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 ( + "runtime" + "unsafe" +) + +// ioctl itself should not be exposed directly, but additional get/set +// functions for specific types are permissible. + +// IoctlSetInt performs an ioctl operation which sets an integer value +// on fd, using the specified request number. +func IoctlSetInt(fd int, req int, value int) error { + return ioctl(fd, req, uintptr(value)) +} + +// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. +// +// To change fd's window size, the req argument should be TIOCSWINSZ. +func IoctlSetWinsize(fd int, req int, value *Winsize) error { + // TODO: if we get the chance, remove the req parameter and + // hardcode TIOCSWINSZ. + return ioctlPtr(fd, req, unsafe.Pointer(value)) +} + +// IoctlSetTermios performs an ioctl on fd with a *Termios. +// +// The req value is expected to be TCSETS, TCSETSW, or TCSETSF +func IoctlSetTermios(fd int, req int, value *Termios) error { + if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) { + return ENOSYS + } + err := Tcsetattr(fd, int(req), value) + runtime.KeepAlive(value) + return err +} + +// IoctlGetInt performs an ioctl operation which gets an integer value +// from fd, using the specified request number. +// +// A few ioctl requests use the return value as an output parameter; +// for those, IoctlRetInt should be used instead of this function. +func IoctlGetInt(fd int, req int) (int, error) { + var value int + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) + return value, err +} + +func IoctlGetWinsize(fd int, req int) (*Winsize, error) { + var value Winsize + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlGetTermios performs an ioctl on fd with a *Termios. +// +// The req value is expected to be TCGETS +func IoctlGetTermios(fd int, req int) (*Termios, error) { + var value Termios + if req != TCGETS { + return &value, ENOSYS + } + err := Tcgetattr(fd, &value) + return &value, err +} diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh index ece31e9..d0ed611 100644 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -49,8 +49,9 @@ esac if [[ "$GOOS" = "linux" ]]; then # Use the Docker-based build system # Files generated through docker (use $cmd so you can Ctl-C the build or run) + set -e $cmd docker build --tag generate:$GOOS $GOOS - $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS + $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS exit fi @@ -70,31 +71,15 @@ aix_ppc64) mksyscall="go run mksyscall_aix_ppc64.go -aix" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; -darwin_386) - mkerrors="$mkerrors -m32" - mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" - ;; darwin_amd64) mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" - ;; -darwin_arm) - mkerrors="$mkerrors" - mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" + mkasm="go run mkasm.go" ;; darwin_arm64) mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" mktypes="GOARCH=$GOARCH go tool cgo -godefs" - mkasm="go run mkasm_darwin.go" + mkasm="go run mkasm.go" ;; dragonfly_amd64) mkerrors="$mkerrors -m64" @@ -105,25 +90,30 @@ dragonfly_amd64) freebsd_386) mkerrors="$mkerrors -m32" mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; freebsd_amd64) mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; freebsd_arm) mkerrors="$mkerrors" mksyscall="go run mksyscall.go -l32 -arm" - mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" # Let the type of C char be signed for making the bare syscall # API consistent across platforms. mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" ;; freebsd_arm64) mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +freebsd_riscv64) + mkerrors="$mkerrors -m64" + mksysnum="go run mksysnum.go 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12'" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" ;; netbsd_386) @@ -153,33 +143,60 @@ netbsd_arm64) mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_386) + mkasm="go run mkasm.go" mkerrors="$mkerrors -m32" - mksyscall="go run mksyscall.go -l32 -openbsd" + mksyscall="go run mksyscall.go -l32 -openbsd -libc" mksysctl="go run mksysctl_openbsd.go" - mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_amd64) + mkasm="go run mkasm.go" mkerrors="$mkerrors -m64" - mksyscall="go run mksyscall.go -openbsd" + mksyscall="go run mksyscall.go -openbsd -libc" mksysctl="go run mksysctl_openbsd.go" - mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_arm) + mkasm="go run mkasm.go" mkerrors="$mkerrors" - mksyscall="go run mksyscall.go -l32 -openbsd -arm" + mksyscall="go run mksyscall.go -l32 -openbsd -arm -libc" mksysctl="go run mksysctl_openbsd.go" - mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" # Let the type of C char be signed for making the bare syscall # API consistent across platforms. mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" ;; openbsd_arm64) + mkasm="go run mkasm.go" + mkerrors="$mkerrors -m64" + mksyscall="go run mksyscall.go -openbsd -libc" + mksysctl="go run mksysctl_openbsd.go" + # Let the type of C char be signed for making the bare syscall + # API consistent across platforms. + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +openbsd_mips64) + mkasm="go run mkasm.go" + mkerrors="$mkerrors -m64" + mksyscall="go run mksyscall.go -openbsd -libc" + mksysctl="go run mksysctl_openbsd.go" + # Let the type of C char be signed for making the bare syscall + # API consistent across platforms. + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +openbsd_ppc64) + mkasm="go run mkasm.go" mkerrors="$mkerrors -m64" - mksyscall="go run mksyscall.go -openbsd" + mksyscall="go run mksyscall.go -openbsd -libc" + mksysctl="go run mksysctl_openbsd.go" + # Let the type of C char be signed for making the bare syscall + # API consistent across platforms. + mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" + ;; +openbsd_riscv64) + mkasm="go run mkasm.go" + mkerrors="$mkerrors -m64" + mksyscall="go run mksyscall.go -openbsd -libc" mksysctl="go run mksysctl_openbsd.go" - mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" # Let the type of C char be signed for making the bare syscall # API consistent across platforms. mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" @@ -194,7 +211,7 @@ illumos_amd64) mksyscall="go run mksyscall_solaris.go" mkerrors= mksysnum= - mktypes= + mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; *) echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 @@ -216,13 +233,6 @@ esac if [ "$GOOSARCH" == "aix_ppc64" ]; then # aix/ppc64 script generates files instead of writing to stdin. echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ; - elif [ "$GOOS" == "darwin" ]; then - # pre-1.12, direct syscalls - echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go"; - # 1.12 and later, syscalls via libSystem - echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; - # 1.13 and later, syscalls via libSystem (including syscallPtr) - echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go"; elif [ "$GOOS" == "illumos" ]; then # illumos code generation requires a --illumos switch echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go"; @@ -236,5 +246,5 @@ esac if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; fi - if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi + if [ -n "$mkasm" ]; then echo "$mkasm $GOOS $GOARCH"; fi ) | $run diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index bc076cf..fd39be4 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -54,22 +54,30 @@ includes_AIX=' includes_Darwin=' #define _DARWIN_C_SOURCE -#define KERNEL +#define KERNEL 1 #define _DARWIN_USE_64_BIT_INODE +#define __APPLE_USE_RFC_3542 #include +#include #include +#include +#include #include #include #include #include #include +#include +#include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -77,6 +85,9 @@ includes_Darwin=' #include #include #include + +// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk. +#define TIOCREMOTE 0x80047469 ' includes_DragonFly=' @@ -93,6 +104,7 @@ includes_DragonFly=' #include #include #include +#include #include #include #include @@ -107,8 +119,10 @@ includes_FreeBSD=' #include #include #include +#include #include #include +#include #include #include #include @@ -116,6 +130,7 @@ includes_FreeBSD=' #include #include #include +#include #include #include #include @@ -143,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 + // is broken on powerpc64, as it fails to include definitions of // these structures. We just include them copied from . #if defined(__powerpc__) @@ -187,22 +212,33 @@ struct ltchars { #include #include #include +#include #include #include +#include +#include #include #include +#include +#include +#include #include #include #include +#include +#include #include +#include #include #include +#include #include #include #include +#include #include #include -#include +#include #include #include #include @@ -212,17 +248,27 @@ struct ltchars { #include #include #include +#include +#include #include #include +#include #include +#include #include +#include #include #include +#include #include +#include #include #include +#include #include #include +#include +#include #include #include #include @@ -231,14 +277,17 @@ struct ltchars { #include #include #include +#include #include #include #include #include #include #include +#include #include +#include #include #if defined(__sparc__) @@ -250,10 +299,6 @@ struct ltchars { #include #endif -#ifndef MSG_FASTOPEN -#define MSG_FASTOPEN 0x20000000 -#endif - #ifndef PTRACE_GETREGS #define PTRACE_GETREGS 0xc #endif @@ -262,10 +307,6 @@ struct ltchars { #define PTRACE_SETREGS 0xd #endif -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - #ifdef SOL_BLUETOOTH // SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h // but it is already in bluetooth_linux.go @@ -282,10 +323,37 @@ struct ltchars { #undef TIPC_WAIT_FOREVER #define TIPC_WAIT_FOREVER 0xffffffff -// Copied from linux/l2tp.h -// Including linux/l2tp.h here causes conflicts between linux/in.h -// and netinet/in.h included via net/route.h above. -#define IPPROTO_L2TP 115 +// Copied from linux/netfilter/nf_nat.h +// Including linux/netfilter/nf_nat.h here causes conflicts between linux/in.h +// and netinet/in.h. +#define NF_NAT_RANGE_MAP_IPS (1 << 0) +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) +#define NF_NAT_RANGE_PERSISTENT (1 << 3) +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) +#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5) +#define NF_NAT_RANGE_NETMAP (1 << 6) +#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ + (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY) +#define NF_NAT_RANGE_MASK \ + (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \ + NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \ + NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \ + NF_NAT_RANGE_NETMAP) + +// Copied from linux/hid.h. +// Keep in sync with the size of the referenced fields. +#define _HIDIOCGRAWNAME_LEN 128 // sizeof_field(struct hid_device, name) +#define _HIDIOCGRAWPHYS_LEN 64 // sizeof_field(struct hid_device, phys) +#define _HIDIOCGRAWUNIQ_LEN 64 // sizeof_field(struct hid_device, uniq) + +#define _HIDIOCGRAWNAME HIDIOCGRAWNAME(_HIDIOCGRAWNAME_LEN) +#define _HIDIOCGRAWPHYS HIDIOCGRAWPHYS(_HIDIOCGRAWPHYS_LEN) +#define _HIDIOCGRAWUNIQ HIDIOCGRAWUNIQ(_HIDIOCGRAWUNIQ_LEN) + +// Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") +#define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME +#define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION ' includes_NetBSD=' @@ -295,6 +363,7 @@ includes_NetBSD=' #include #include #include +#include #include #include #include @@ -323,6 +392,7 @@ includes_OpenBSD=' #include #include #include +#include #include #include #include @@ -363,6 +433,7 @@ includes_SunOS=' #include #include #include +#include #include #include #include @@ -372,10 +443,11 @@ includes_SunOS=' #include #include #include +#include #include -#include #include #include +#include ' @@ -430,6 +502,7 @@ ccflags="$@" $2 !~ /^EPROC_/ && $2 !~ /^EQUIV_/ && $2 !~ /^EXPR_/ && + $2 !~ /^EVIOC/ && $2 ~ /^E[A-Z0-9_]+$/ || $2 ~ /^B[0-9_]+$/ || $2 ~ /^(OLD|NEW)DEV$/ || @@ -458,16 +531,25 @@ ccflags="$@" $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ || $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ || + $2 ~ /^(DT|EI|ELF|EV|NN|NT|PF|SHF|SHN|SHT|STB|STT|VER)_/ || $2 ~ /^O?XTABS$/ || $2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^IN_/ || + $2 ~ /^KCM/ || + $2 ~ /^LANDLOCK_/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || - $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|MCAST|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || + $2 == "LOOP_CONFIGURE" || + $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_/ || $2 ~ /^FALLOC_/ || - $2 == "ICMPV6_FILTER" || + $2 ~ /^ICMPV?6?_(FILTER|SEC)/ || $2 == "SOMAXCONN" || $2 == "NAME_MAX" || $2 == "IFNAMSIZ" || @@ -476,16 +558,20 @@ ccflags="$@" $2 ~ /^HW_MACHINE$/ || $2 ~ /^SYSCTL_VERS/ || $2 !~ "MNT_BITS" && - $2 ~ /^(MS|MNT|UMOUNT)_/ || + $2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ || $2 ~ /^NS_GET_/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || - $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ || + $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|PIOD|TFD)_/ || $2 ~ /^KEXEC_/ || $2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 ~ /^MODULE_INIT_/ || $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/ || $2 ~ /^TCGET/ || @@ -499,28 +585,36 @@ ccflags="$@" $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || $2 ~ /^CLONE_[A-Z_]+/ || - $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ && + $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+|BPF_F_LINK)$/ && $2 ~ /^(BPF|DLT)_/ || + $2 ~ /^AUDIT_/ || $2 ~ /^(CLOCK|TIMER)_/ || $2 ~ /^CAN_/ || $2 ~ /^CAP_/ || + $2 ~ /^CP_/ || + $2 ~ /^CPUSTATES$/ || + $2 ~ /^CTLIOCGINFO$/ || $2 ~ /^ALG_/ || + $2 ~ /^FI(CLONE|DEDUPERANGE)/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ || - $2 ~ /^FS_IOC_.*ENCRYPTION/ || + $2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ || + $2 ~ /^FS_VERITY_/ || $2 ~ /^FSCRYPT_/ || + $2 ~ /^DM_/ || $2 ~ /^GRND_/ || $2 ~ /^RND/ || $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || $2 ~ /^KEYCTL_/ || - $2 ~ /^PERF_EVENT_IOC_/ || - $2 ~ /^SECCOMP_MODE_/ || + $2 ~ /^PERF_/ || + $2 ~ /^SECCOMP_/ || + $2 ~ /^SEEK_/ || + $2 ~ /^SCHED_/ || $2 ~ /^SPLICE_/ || $2 ~ /^SYNC_FILE_RANGE_/ || - $2 !~ /^AUDIT_RECORD_MAGIC/ && $2 !~ /IOC_MAGIC/ && $2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ || $2 ~ /^(VM|VMADDR)_/ || - $2 ~ /^IOCTL_VM_SOCKETS_/ || + $2 ~ /^(IOCTL_VM_SOCKETS_|IOCTL_MEI_)/ || $2 ~ /^(TASKSTATS|TS)_/ || $2 ~ /^CGROUPSTATS_/ || $2 ~ /^GENL_/ || @@ -531,19 +625,35 @@ ccflags="$@" $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ || $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ || $2 ~ /^FSOPT_/ || - $2 ~ /^WDIOC_/ || + $2 ~ /^WDIO[CFS]_/ || $2 ~ /^NFN/ || + $2 !~ /^NFT_META_IIFTYPE/ && + $2 ~ /^NFT_/ || + $2 ~ /^NF_NAT_/ || $2 ~ /^XDP_/ || $2 ~ /^RWF_/ || $2 ~ /^(HDIO|WIN|SMART)_/ || $2 ~ /^CRYPTO_/ || $2 ~ /^TIPC_/ || + $2 !~ "DEVLINK_RELOAD_LIMITS_VALID_MASK" && $2 ~ /^DEVLINK_/ || + $2 ~ /^ETHTOOL_/ || + $2 ~ /^LWTUNNEL_IP/ || + $2 ~ /^ITIMER_/ || $2 !~ "WMESGLEN" && $2 ~ /^W[A-Z0-9]+$/ || + $2 ~ /^P_/ || $2 ~/^PPPIOC/ || $2 ~ /^FAN_|FANOTIFY_/ || - $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} + $2 == "HID_MAX_DESCRIPTOR_SIZE" || + $2 ~ /^_?HIDIOC/ || + $2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ || + $2 ~ /^MTD/ || + $2 ~ /^OTP/ || + $2 ~ /^MEM/ || + $2 ~ /^WG/ || + $2 ~ /^FIB_RULE_/ || + $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE|IOMIN$|IOOPT$|ALIGNOFF$|DISCARD|ROTATIONAL$|ZEROOUT$|GETDISKSEQ$)/ {printf("\t%s = C.%s\n", $2, $2)} $2 ~ /^__WCOREFLAG$/ {next} $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} @@ -564,7 +674,7 @@ errors=$( signals=$( echo '#include ' | $CC -x c - -E -dM $ccflags | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | - egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | + grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | sort ) @@ -574,13 +684,13 @@ echo '#include ' | $CC -x c - -E -dM $ccflags | sort >_error.grep echo '#include ' | $CC -x c - -E -dM $ccflags | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | - egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | + grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | sort >_signal.grep echo '// mkerrors.sh' "$@" echo '// Code generated by the command above; see README.md. DO NOT EDIT.' echo -echo "// +build ${GOARCH},${GOOS}" +echo "//go:build ${GOARCH} && ${GOOS}" echo go tool cgo -godefs -- "$@" _const.go >_error.out cat _error.out | grep -vf _error.grep | grep -vf _signal.grep @@ -659,7 +769,8 @@ main(void) e = errors[i].num; if(i > 0 && errors[i-1].num == e) continue; - strcpy(buf, strerror(e)); + strncpy(buf, strerror(e), sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; // lowercase first letter: Bad -> bad, but STREAM -> STREAM. if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) buf[0] += a - A; @@ -678,7 +789,8 @@ main(void) e = signals[i].num; if(i > 0 && signals[i-1].num == e) continue; - strcpy(buf, strsignal(e)); + strncpy(buf, strsignal(e), sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; // lowercase first letter: Bad -> bad, but STREAM -> STREAM. if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) buf[0] += a - A; diff --git a/vendor/golang.org/x/sys/unix/mmap_nomremap.go b/vendor/golang.org/x/sys/unix/mmap_nomremap.go new file mode 100644 index 0000000..7f602ff --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mmap_nomremap.go @@ -0,0 +1,13 @@ +// 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 aix || darwin || dragonfly || freebsd || openbsd || solaris || zos + +package unix + +var mapper = &mmapper{ + active: make(map[*byte][]byte), + mmap: mmap, + munmap: munmap, +} diff --git a/vendor/golang.org/x/sys/unix/mremap.go b/vendor/golang.org/x/sys/unix/mremap.go new file mode 100644 index 0000000..3a5e776 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mremap.go @@ -0,0 +1,57 @@ +// 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 linux || netbsd + +package unix + +import "unsafe" + +type mremapMmapper struct { + mmapper + mremap func(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) +} + +var mapper = &mremapMmapper{ + mmapper: mmapper{ + active: make(map[*byte][]byte), + mmap: mmap, + munmap: munmap, + }, + mremap: mremap, +} + +func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) { + if newLength <= 0 || len(oldData) == 0 || len(oldData) != cap(oldData) || flags&mremapFixed != 0 { + return nil, EINVAL + } + + pOld := &oldData[cap(oldData)-1] + m.Lock() + defer m.Unlock() + bOld := m.active[pOld] + if bOld == nil || &bOld[0] != &oldData[0] { + return nil, EINVAL + } + newAddr, errno := m.mremap(uintptr(unsafe.Pointer(&bOld[0])), uintptr(len(bOld)), uintptr(newLength), flags, 0) + if errno != nil { + return nil, errno + } + bNew := unsafe.Slice((*byte)(unsafe.Pointer(newAddr)), newLength) + pNew := &bNew[cap(bNew)-1] + if flags&mremapDontunmap == 0 { + delete(m.active, pOld) + } + m.active[pNew] = bNew + return bNew, nil +} + +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 +} diff --git a/vendor/golang.org/x/sys/unix/pagesize_unix.go b/vendor/golang.org/x/sys/unix/pagesize_unix.go index bc2f362..0482408 100644 --- a/vendor/golang.org/x/sys/unix/pagesize_unix.go +++ b/vendor/golang.org/x/sys/unix/pagesize_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // For Unix, get the pagesize from the runtime. diff --git a/vendor/golang.org/x/sys/unix/pledge_openbsd.go b/vendor/golang.org/x/sys/unix/pledge_openbsd.go index eb48294..6a09af5 100644 --- a/vendor/golang.org/x/sys/unix/pledge_openbsd.go +++ b/vendor/golang.org/x/sys/unix/pledge_openbsd.go @@ -8,54 +8,31 @@ import ( "errors" "fmt" "strconv" - "syscall" - "unsafe" ) // Pledge implements the pledge syscall. // -// The pledge syscall does not accept execpromises on OpenBSD releases -// before 6.3. -// -// execpromises must be empty when Pledge is called on OpenBSD -// releases predating 6.3, otherwise an error will be returned. +// This changes both the promises and execpromises; use PledgePromises or +// PledgeExecpromises to only change the promises or execpromises +// respectively. // // For more information see pledge(2). func Pledge(promises, execpromises string) error { - maj, min, err := majmin() - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - err = pledgeAvailable(maj, min, execpromises) + pptr, err := BytePtrFromString(promises) if err != nil { return err } - pptr, err := syscall.BytePtrFromString(promises) + exptr, err := BytePtrFromString(execpromises) if err != nil { return err } - // This variable will hold either a nil unsafe.Pointer or - // an unsafe.Pointer to a string (execpromises). - var expr unsafe.Pointer - - // If we're running on OpenBSD > 6.2, pass execpromises to the syscall. - if maj > 6 || (maj == 6 && min > 2) { - exptr, err := syscall.BytePtrFromString(execpromises) - if err != nil { - return err - } - expr = unsafe.Pointer(exptr) - } - - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) - if e != 0 { - return e - } - - return nil + return pledge(pptr, exptr) } // PledgePromises implements the pledge syscall. @@ -64,30 +41,16 @@ func Pledge(promises, execpromises string) error { // // For more information see pledge(2). func PledgePromises(promises string) error { - maj, min, err := majmin() - if err != nil { - return err - } - - err = pledgeAvailable(maj, min, "") - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - // This variable holds the execpromises and is always nil. - var expr unsafe.Pointer - - pptr, err := syscall.BytePtrFromString(promises) + pptr, err := BytePtrFromString(promises) if err != nil { return err } - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) - if e != 0 { - return e - } - - return nil + return pledge(pptr, nil) } // PledgeExecpromises implements the pledge syscall. @@ -96,30 +59,16 @@ func PledgePromises(promises string) error { // // For more information see pledge(2). func PledgeExecpromises(execpromises string) error { - maj, min, err := majmin() - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - err = pledgeAvailable(maj, min, execpromises) + exptr, err := BytePtrFromString(execpromises) if err != nil { return err } - // This variable holds the promises and is always nil. - var pptr unsafe.Pointer - - exptr, err := syscall.BytePtrFromString(execpromises) - if err != nil { - return err - } - - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0) - if e != 0 { - return e - } - - return nil + return pledge(nil, exptr) } // majmin returns major and minor version number for an OpenBSD system. @@ -147,16 +96,15 @@ func majmin() (major int, minor int, err error) { // pledgeAvailable checks for availability of the pledge(2) syscall // based on the running OpenBSD version. -func pledgeAvailable(maj, min int, execpromises string) error { - // If OpenBSD <= 5.9, pledge is not available. - if (maj == 5 && min != 9) || maj < 5 { - return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min) +func pledgeAvailable() error { + maj, min, err := majmin() + if err != nil { + return err } - // If OpenBSD <= 6.2 and execpromises is not empty, - // return an error - execpromises is not available before 6.3 - if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" { - return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min) + // Require OpenBSD 6.4 as a minimum. + if maj < 6 || (maj == 6 && min <= 3) { + return fmt.Errorf("cannot call Pledge on OpenBSD %d.%d", maj, min) } return nil diff --git a/vendor/golang.org/x/sys/unix/ptrace_darwin.go b/vendor/golang.org/x/sys/unix/ptrace_darwin.go new file mode 100644 index 0000000..3f0975f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ptrace_darwin.go @@ -0,0 +1,11 @@ +// 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 darwin && !ios + +package unix + +func ptrace(request int, pid int, addr uintptr, data uintptr) error { + return ptrace1(request, pid, addr, data) +} diff --git a/vendor/golang.org/x/sys/unix/ptrace_ios.go b/vendor/golang.org/x/sys/unix/ptrace_ios.go new file mode 100644 index 0000000..a4d35db --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ptrace_ios.go @@ -0,0 +1,11 @@ +// 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 ios + +package unix + +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + return ENOTSUP +} diff --git a/vendor/golang.org/x/sys/unix/race.go b/vendor/golang.org/x/sys/unix/race.go index 61712b5..714d2aa 100644 --- a/vendor/golang.org/x/sys/unix/race.go +++ b/vendor/golang.org/x/sys/unix/race.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin,race linux,race freebsd,race +//go:build (darwin && race) || (linux && race) || (freebsd && race) package unix diff --git a/vendor/golang.org/x/sys/unix/race0.go b/vendor/golang.org/x/sys/unix/race0.go index ad02667..4a9f663 100644 --- a/vendor/golang.org/x/sys/unix/race0.go +++ b/vendor/golang.org/x/sys/unix/race0.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly +//go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos package unix diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdents.go b/vendor/golang.org/x/sys/unix/readdirent_getdents.go index 3a90aa6..dbd2b6c 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdents.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdents.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix dragonfly freebsd linux netbsd openbsd +//go:build aix || dragonfly || freebsd || linux || netbsd || openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go index 5fdae40..b903c00 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin +//go:build darwin || zos package unix diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_linux.go b/vendor/golang.org/x/sys/unix/sockcmsg_linux.go index 8bf4570..5f63147 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_linux.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_linux.go @@ -34,3 +34,52 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) { 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 +} + +// ParseOrigDstAddr decodes a socket control message containing the original +// destination address. To receive such a message the IP_RECVORIGDSTADDR or +// IPV6_RECVORIGDSTADDR option must be enabled on the socket. +func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) { + switch { + case m.Header.Level == SOL_IP && m.Header.Type == IP_ORIGDSTADDR: + pp := (*RawSockaddrInet4)(unsafe.Pointer(&m.Data[0])) + sa := new(SockaddrInet4) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.Addr = pp.Addr + return sa, nil + + case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR: + pp := (*RawSockaddrInet6)(unsafe.Pointer(&m.Data[0])) + sa := new(SockaddrInet6) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.ZoneId = pp.Scope_id + sa.Addr = pp.Addr + return sa, nil + + default: + return nil, EINVAL + } +} diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go index 003916e..c3a62db 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // Socket control messages @@ -51,6 +51,20 @@ func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) { return msgs, nil } +// ParseOneSocketControlMessage parses a single socket control message from b, returning the message header, +// message data (a slice of b), and the remainder of b after that single message. +// When there are no remaining messages, len(remainder) == 0. +func ParseOneSocketControlMessage(b []byte) (hdr Cmsghdr, data []byte, remainder []byte, err error) { + h, dbuf, err := socketControlMessageHeaderAndData(b) + if err != nil { + return Cmsghdr{}, nil, nil, err + } + if i := cmsgAlignOf(int(h.Len)); i < len(b) { + remainder = b[i:] + } + return *h, dbuf, remainder, nil +} + func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) { h := (*Cmsghdr)(unsafe.Pointer(&b[0])) if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) { diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go index 7d08dae..4a1eab3 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin freebsd linux netbsd openbsd solaris +//go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos package unix @@ -20,7 +20,7 @@ func cmsgAlignOf(salen int) int { case "aix": // There is no alignment on AIX. salign = 1 - case "darwin", "illumos", "solaris": + case "darwin", "ios", "illumos", "solaris": // NOTE: It seems like 64-bit Darwin, Illumos and Solaris // kernels still require 32-bit aligned access to network // subsystem. @@ -32,6 +32,14 @@ func cmsgAlignOf(salen int) int { if runtime.GOARCH == "arm" { salign = 8 } + // NetBSD aarch64 requires 128-bit alignment. + if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" { + salign = 16 + } + case "zos": + // z/OS socket macros use [32-bit] sizeof(int) alignment, + // not pointer width. + salign = SizeofInt } return (salen + salign - 1) & ^(salign - 1) diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_zos.go b/vendor/golang.org/x/sys/unix/sockcmsg_zos.go new file mode 100644 index 0000000..3e53dbc --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sockcmsg_zos.go @@ -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 +} diff --git a/vendor/golang.org/x/sys/unix/str.go b/vendor/golang.org/x/sys/unix/str.go deleted file mode 100644 index 17fb698..0000000 --- a/vendor/golang.org/x/sys/unix/str.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris - -package unix - -func itoa(val int) string { // do it here rather than with fmt to avoid dependency - if val < 0 { - return "-" + uitoa(uint(-val)) - } - return uitoa(uint(val)) -} - -func uitoa(val uint) string { - var buf [32]byte // big enough for int64 - i := len(buf) - 1 - for val >= 10 { - buf[i] = byte(val%10 + '0') - i-- - val /= 10 - } - buf[i] = byte(val + '0') - return string(buf[i:]) -} diff --git a/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s b/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s new file mode 100644 index 0000000..3c4f33c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s @@ -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 + diff --git a/vendor/golang.org/x/sys/unix/syscall.go b/vendor/golang.org/x/sys/unix/syscall.go index fd4ee8e..5ea74da 100644 --- a/vendor/golang.org/x/sys/unix/syscall.go +++ b/vendor/golang.org/x/sys/unix/syscall.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // Package unix contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and @@ -24,7 +24,11 @@ // holds a value of type syscall.Errno. package unix // import "golang.org/x/sys/unix" -import "strings" +import ( + "bytes" + "strings" + "unsafe" +) // ByteSliceFromString returns a NUL-terminated slice of bytes // containing the text of s. If s contains a NUL byte at any @@ -49,5 +53,34 @@ func BytePtrFromString(s string) (*byte, error) { return &a[0], nil } +// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any +// bytes after the NUL removed. +func ByteSliceToString(s []byte) string { + if i := bytes.IndexByte(s, 0); i != -1 { + s = s[:i] + } + return string(s) +} + +// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string. +// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated +// at a zero byte; if the zero byte is not present, the program may crash. +func BytePtrToString(p *byte) string { + if p == nil { + return "" + } + if *p == 0 { + return "" + } + + // Find NUL terminator. + n := 0 + for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + 1) + } + + return string(unsafe.Slice(p, n)) +} + // Single-word zero for use when we need a valid pointer to 0 bytes. var _zero uintptr diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go index 9ad8a0d..6f15ba1 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix +//go:build aix // Aix system calls. // This file is compiled as ordinary Go code, @@ -19,7 +19,24 @@ import "unsafe" * Wrapped */ +func Access(path string, mode uint32) (err error) { + return Faccessat(AT_FDCWD, path, mode, 0) +} + +func Chmod(path string, mode uint32) (err error) { + return Fchmodat(AT_FDCWD, path, mode, 0) +} + +func Chown(path string, uid int, gid int) (err error) { + return Fchownat(AT_FDCWD, path, uid, gid, 0) +} + +func Creat(path string, mode uint32) (fd int, err error) { + return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) +} + //sys utimes(path string, times *[2]Timeval) (err error) + func Utimes(path string, tv []Timeval) error { if len(tv) != 2 { return EINVAL @@ -28,6 +45,7 @@ func Utimes(path string, tv []Timeval) error { } //sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) + func UtimesNano(path string, ts []Timespec) error { if len(ts) != 2 { return EINVAL @@ -53,9 +71,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -68,9 +84,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -92,7 +106,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -202,20 +217,63 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { - // Recvmsg not implemented on AIX - sa := new(SockaddrUnix) - return -1, -1, -1, sa, ENOSYS -} - -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) +func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { + var msg Msghdr + msg.Name = (*byte)(unsafe.Pointer(rsa)) + msg.Namelen = uint32(SizeofSockaddrAny) + var dummy byte + if len(oob) > 0 { + // receive at least one normal byte + if emptyIovecs(iov) { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] + } + msg.Control = (*byte)(unsafe.Pointer(&oob[0])) + msg.SetControllen(len(oob)) + } + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } + if n, err = recvmsg(fd, &msg, flags); n == -1 { + return + } + oobn = int(msg.Controllen) + recvflags = int(msg.Flags) return } -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - // SendmsgN not implemented on AIX - return -1, ENOSYS +func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { + var msg Msghdr + msg.Name = (*byte)(unsafe.Pointer(ptr)) + msg.Namelen = uint32(salen) + var dummy byte + var empty bool + if len(oob) > 0 { + // send at least one normal byte + empty = emptyIovecs(iov) + if empty { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] + } + msg.Control = (*byte)(unsafe.Pointer(&oob[0])) + msg.SetControllen(len(oob)) + } + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } + if n, err = sendmsg(fd, &msg, flags); err != nil { + return 0, err + } + if len(oob) > 0 && empty { + n = 0 + } + return n, nil } func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { @@ -234,9 +292,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { break } } - - bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] - sa.Name = string(bytes) + sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) return sa, nil case AF_INET: @@ -244,9 +300,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -255,9 +309,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -297,16 +349,18 @@ func direntNamlen(buf []byte) (uint64, bool) { } //sys getdirent(fd int, buf []byte) (n int, err error) + func Getdents(fd int, buf []byte) (n int, err error) { return getdirent(fd, buf) } //sys wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error) + func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 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) @@ -354,7 +408,8 @@ func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 } func (w WaitStatus) TrapCause() int { return -1 } -//sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctl(fd int, req int, arg uintptr) (err error) +//sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = ioctl // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX // There is no way to create a custom fcntl and to keep //sys fcntl easily, @@ -368,6 +423,12 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys fcntl(fd int, cmd int, arg int) (val int, err error) +//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range + +func Fsync(fd int) error { + return fsyncRange(fd, O_SYNC, 0, 0) +} + /* * Direct access */ @@ -384,7 +445,6 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Fdatasync(fd int) (err error) -//sys Fsync(fd int) (err error) // readdir_r //sysnb Getpgid(pid int) (pgid int, err error) @@ -403,8 +463,8 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys Mknod(path string, mode uint32, dev int) (err error) //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) -//sys Open(path string, mode int, perm uint32) (fd int, err error) = open64 -//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) +//sys Open(path string, mode int, perm uint32) (fd int, err error) = open64 +//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) @@ -423,12 +483,10 @@ func (w WaitStatus) TrapCause() int { return -1 } //sysnb Times(tms *Tms) (ticks uintptr, err error) //sysnb Umask(mask int) (oldmask int) //sysnb Uname(buf *Utsname) (err error) -//sys Unlink(path string) (err error) -//sys Unlinkat(dirfd int, path string, flags int) (err error) +//sys Unlink(path string) (err error) +//sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) //sys write(fd int, p []byte) (n int, err error) -//sys readlen(fd int, p *byte, np int) (n int, err error) = read -//sys writelen(fd int, p *byte, np int) (n int, err error) = write //sys Dup2(oldfd int, newfd int) (err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64 @@ -445,8 +503,8 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys Listen(s int, n int) (err error) //sys lstat(path string, stat *Stat_t) (err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = pread64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64 //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) //sysnb Setregid(rgid int, egid int) (err error) @@ -475,21 +533,6 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg //sys munmap(addr uintptr, length uintptr) (err error) - -var mapper = &mmapper{ - active: make(map[*byte][]byte), - mmap: mmap, - munmap: munmap, -} - -func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { - return mapper.Mmap(fd, offset, length, prot, flags) -} - -func Munmap(b []byte) (err error) { - return mapper.Munmap(b) -} - //sys Madvise(b []byte, advice int) (err error) //sys Mprotect(b []byte, prot int) (err error) //sys Mlock(b []byte) (err error) @@ -498,7 +541,7 @@ func Munmap(b []byte) (err error) { //sys Munlock(b []byte) (err error) //sys Munlockall() (err error) -//sysnb pipe(p *[2]_C_int) (err error) +//sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { if len(p) != 2 { @@ -506,8 +549,10 @@ func Pipe(p []int) (err error) { } var pp [2]_C_int err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return } @@ -527,6 +572,7 @@ func Poll(fds []PollFd, timeout int) (n int, err error) { //sys Getsystemcfg(label int) (n uint64) //sys umount(target string) (err error) + func Unmount(target string, flags int) (err error) { if flags != 0 { // AIX doesn't have any flags for umount. diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go index b3c8e33..1fdaa47 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix -// +build ppc +//go:build aix && ppc package unix //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = getrlimit64 -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) = setrlimit64 //sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek64 //sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go index 9a6e024..c87f9a9 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix -// +build ppc64 +//go:build aix && ppc64 package unix //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek //sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) = mmap64 diff --git a/vendor/golang.org/x/sys/unix/syscall_bsd.go b/vendor/golang.org/x/sys/unix/syscall_bsd.go index 68605db..a00c3e5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd netbsd openbsd +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // BSD system call wrappers shared by *BSD based systems // including OS X (Darwin) and FreeBSD. Like the other @@ -18,6 +18,21 @@ import ( "unsafe" ) +const ImplementsGetwd = true + +func Getwd() (string, error) { + var buf [PathMax]byte + _, err := Getcwd(buf[0:]) + if err != nil { + return "", err + } + n := clen(buf[:]) + if n < 1 { + return "", EINVAL + } + return string(buf[:n]), nil +} + /* * Wrapped */ @@ -147,9 +162,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -163,9 +176,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -194,9 +205,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Nlen = sa.Nlen sa.raw.Alen = sa.Alen sa.raw.Slen = sa.Slen - for i := 0; i < len(sa.raw.Data); i++ { - sa.raw.Data[i] = sa.Data[i] - } + sa.raw.Data = sa.Data return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil } @@ -212,9 +221,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa.Nlen = pp.Nlen sa.Alen = pp.Alen sa.Slen = pp.Slen - for i := 0; i < len(sa.Data); i++ { - sa.Data[i] = pp.Data[i] - } + sa.Data = pp.Data return sa, nil case AF_UNIX: @@ -237,8 +244,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { break } } - bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] - sa.Name = string(bytes) + sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) return sa, nil case AF_INET: @@ -246,9 +252,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -257,12 +261,10 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } - return nil, EAFNOSUPPORT + return anyToSockaddrGOOS(fd, rsa) } func Accept(fd int) (nfd int, sa Sockaddr, err error) { @@ -272,7 +274,7 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { if err != nil { return } - if runtime.GOOS == "darwin" && len == 0 { + if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && len == 0 { // Accepted socket has no address. // This is likely due to a bug in xnu kernels, // where instead of ECONNABORTED error socket @@ -303,7 +305,7 @@ func Getsockname(fd int) (sa Sockaddr, err error) { return anyToSockaddr(fd, &rsa) } -//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) +//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) // GetsockoptString returns the string value of the socket option opt for the // socket associated with fd at the given socket level. @@ -314,87 +316,69 @@ func GetsockoptString(fd, level, opt int) (string, error) { if err != nil { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } -//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) -//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) +//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) +//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) - var iov Iovec - if len(p) > 0 { - iov.Base = (*byte)(unsafe.Pointer(&p[0])) - iov.SetLen(len(p)) - } var dummy byte if len(oob) > 0 { // receive at least one normal byte - if len(p) == 0 { - iov.Base = &dummy - iov.SetLen(1) + if emptyIovecs(iov) { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] } msg.Control = (*byte)(unsafe.Pointer(&oob[0])) msg.SetControllen(len(oob)) } - msg.Iov = &iov - msg.Iovlen = 1 + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } if n, err = recvmsg(fd, &msg, flags); err != nil { return } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(fd, &rsa) - } return } //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) - var iov Iovec - if len(p) > 0 { - iov.Base = (*byte)(unsafe.Pointer(&p[0])) - iov.SetLen(len(p)) - } var dummy byte + var empty bool if len(oob) > 0 { // send at least one normal byte - if len(p) == 0 { - iov.Base = &dummy - iov.SetLen(1) + empty = emptyIovecs(iov) + if empty { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] } msg.Control = (*byte)(unsafe.Pointer(&oob[0])) msg.SetControllen(len(oob)) } - msg.Iov = &iov - msg.Iovlen = 1 + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } if n, err = sendmsg(fd, &msg, flags); err != nil { return 0, err } - if len(oob) > 0 && len(p) == 0 { + if len(oob) > 0 && empty { n = 0 } return n, nil @@ -527,6 +511,23 @@ func SysctlClockinfo(name string) (*Clockinfo, error) { return &ci, nil } +func SysctlTimeval(name string) (*Timeval, error) { + mib, err := sysctlmib(name) + if err != nil { + return nil, err + } + + var tv Timeval + n := uintptr(unsafe.Sizeof(tv)) + if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil { + return nil, err + } + if n != unsafe.Sizeof(tv) { + return nil, EIO + } + return &tv, nil +} + //sys utimes(path string, timeval *[2]Timeval) (err error) func Utimes(path string, tv []Timeval) error { @@ -550,12 +551,7 @@ func UtimesNano(path string, ts []Timespec) error { if len(ts) != 2 { return EINVAL } - // Darwin setattrlist can set nanosecond timestamps - err := setattrlistTimes(path, ts, 0) - if err != ENOSYS { - return err - } - err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) + err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) if err != ENOSYS { return err } @@ -575,10 +571,6 @@ func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { if len(ts) != 2 { return EINVAL } - err := setattrlistTimes(path, ts, flags) - if err != ENOSYS { - return err - } return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) } @@ -594,7 +586,7 @@ func Futimes(fd int, tv []Timeval) error { return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { if len(fds) == 0 { @@ -608,20 +600,6 @@ func Poll(fds []PollFd, timeout int) (n int, err error) { // Gethostuuid(uuid *byte, timeout *Timespec) (err error) // Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error) -var mapper = &mmapper{ - active: make(map[*byte][]byte), - mmap: mmap, - munmap: munmap, -} - -func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { - return mapper.Mmap(fd, offset, length, prot, flags) -} - -func Munmap(b []byte) (err error) { - return mapper.Munmap(b) -} - //sys Madvise(b []byte, behav int) (err error) //sys Mlock(b []byte) (err error) //sys Mlockall(flags int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go b/vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go deleted file mode 100644 index 6a15cba..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,go1.12,!go1.13 - -package unix - -import ( - "unsafe" -) - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - // To implement this using libSystem we'd need syscall_syscallPtr for - // fdopendir. However, syscallPtr was only added in Go 1.13, so we fall - // back to raw syscalls for this func on Go 1.12. - var p unsafe.Pointer - if len(buf) > 0 { - p = unsafe.Pointer(&buf[0]) - } else { - p = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - return n, errnoErr(e1) - } - return n, nil -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go b/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go deleted file mode 100644 index f911617..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,go1.13 - -package unix - -import "unsafe" - -//sys closedir(dir uintptr) (err error) -//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) - -func fdopendir(fd int) (dir uintptr, err error) { - r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0) - dir = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fdopendir_trampoline() - -//go:linkname libc_fdopendir libc_fdopendir -//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib" - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - // Simulate Getdirentries using fdopendir/readdir_r/closedir. - // We store the number of entries to skip in the seek - // offset of fd. See issue #31368. - // It's not the full required semantics, but should handle the case - // of calling Getdirentries or ReadDirent repeatedly. - // It won't handle assigning the results of lseek to *basep, or handle - // the directory being edited underfoot. - skip, err := Seek(fd, 0, 1 /* SEEK_CUR */) - if err != nil { - return 0, err - } - - // We need to duplicate the incoming file descriptor - // because the caller expects to retain control of it, but - // fdopendir expects to take control of its argument. - // Just Dup'ing the file descriptor is not enough, as the - // result shares underlying state. Use Openat to make a really - // new file descriptor referring to the same directory. - fd2, err := Openat(fd, ".", O_RDONLY, 0) - if err != nil { - return 0, err - } - d, err := fdopendir(fd2) - if err != nil { - Close(fd2) - return 0, err - } - defer closedir(d) - - var cnt int64 - for { - var entry Dirent - var entryp *Dirent - e := readdir_r(d, &entry, &entryp) - if e != 0 { - return n, errnoErr(e) - } - if entryp == nil { - break - } - if skip > 0 { - skip-- - cnt++ - continue - } - reclen := int(entry.Reclen) - if reclen > len(buf) { - // Not enough room. Return for now. - // The counter will let us know where we should start up again. - // Note: this strategy for suspending in the middle and - // restarting is O(n^2) in the length of the directory. Oh well. - break - } - // Copy entry into return buffer. - s := struct { - ptr unsafe.Pointer - siz int - cap int - }{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen} - copy(buf, *(*[]byte)(unsafe.Pointer(&s))) - buf = buf[reclen:] - n += reclen - cnt++ - } - // Set the seek offset of the input fd to record - // how many files we've already returned. - _, err = Seek(fd, cnt, 0 /* SEEK_SET */) - if err != nil { - return n, err - } - - return n, nil -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 9a5a6ee..7838ca5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -13,27 +13,99 @@ package unix import ( - "errors" + "fmt" "syscall" "unsafe" ) -const ImplementsGetwd = true - -func Getwd() (string, error) { - buf := make([]byte, 2048) - attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0) - if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 { - wd := string(attrs[0]) - // Sanity check that it's an absolute path and ends - // in a null byte, which we then strip. - if wd[0] == '/' && wd[len(wd)-1] == 0 { - return wd[:len(wd)-1], nil +//sys closedir(dir uintptr) (err error) +//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) + +func fdopendir(fd int) (dir uintptr, err error) { + r0, _, e1 := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(fd), 0, 0) + dir = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fdopendir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib" + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + // Simulate Getdirentries using fdopendir/readdir_r/closedir. + // We store the number of entries to skip in the seek + // offset of fd. See issue #31368. + // It's not the full required semantics, but should handle the case + // of calling Getdirentries or ReadDirent repeatedly. + // It won't handle assigning the results of lseek to *basep, or handle + // the directory being edited underfoot. + skip, err := Seek(fd, 0, 1 /* SEEK_CUR */) + if err != nil { + return 0, err + } + + // We need to duplicate the incoming file descriptor + // because the caller expects to retain control of it, but + // fdopendir expects to take control of its argument. + // Just Dup'ing the file descriptor is not enough, as the + // result shares underlying state. Use Openat to make a really + // new file descriptor referring to the same directory. + fd2, err := Openat(fd, ".", O_RDONLY, 0) + if err != nil { + return 0, err + } + d, err := fdopendir(fd2) + if err != nil { + Close(fd2) + return 0, err + } + defer closedir(d) + + var cnt int64 + for { + var entry Dirent + var entryp *Dirent + e := readdir_r(d, &entry, &entryp) + if e != 0 { + return n, errnoErr(e) } + if entryp == nil { + break + } + if skip > 0 { + skip-- + cnt++ + continue + } + + reclen := int(entry.Reclen) + if reclen > len(buf) { + // Not enough room. Return for now. + // The counter will let us know where we should start up again. + // Note: this strategy for suspending in the middle and + // restarting is O(n^2) in the length of the directory. Oh well. + break + } + + // Copy entry into return buffer. + s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen) + copy(buf, s) + + buf = buf[reclen:] + n += reclen + cnt++ + } + // Set the seek offset of the input fd to record + // how many files we've already returned. + _, err = Seek(fd, cnt, 0 /* SEEK_SET */) + if err != nil { + return n, err } - // If pkg/os/getwd.go gets ENOTSUP, it will fall back to the - // slow algorithm. - return "", ENOTSUP + + return n, nil } // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. @@ -49,6 +121,72 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +// SockaddrCtl implements the Sockaddr interface for AF_SYSTEM type sockets. +type SockaddrCtl struct { + ID uint32 + Unit uint32 + raw RawSockaddrCtl +} + +func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sc_len = SizeofSockaddrCtl + sa.raw.Sc_family = AF_SYSTEM + sa.raw.Ss_sysaddr = AF_SYS_CONTROL + sa.raw.Sc_id = sa.ID + sa.raw.Sc_unit = sa.Unit + return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil +} + +// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets. +// SockaddrVM provides access to Darwin VM sockets: a mechanism that enables +// bidirectional communication between a hypervisor and its guest virtual +// machines. +type SockaddrVM struct { + // CID and Port specify a context ID and port address for a VM socket. + // Guests have a unique CID, and hosts may have a well-known CID of: + // - VMADDR_CID_HYPERVISOR: refers to the hypervisor process. + // - VMADDR_CID_LOCAL: refers to local communication (loopback). + // - VMADDR_CID_HOST: refers to other processes on the host. + CID uint32 + Port uint32 + raw RawSockaddrVM +} + +func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Len = SizeofSockaddrVM + sa.raw.Family = AF_VSOCK + sa.raw.Port = sa.Port + sa.raw.Cid = sa.CID + + return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil +} + +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + switch rsa.Addr.Family { + case AF_SYSTEM: + pp := (*RawSockaddrCtl)(unsafe.Pointer(rsa)) + if pp.Ss_sysaddr == AF_SYS_CONTROL { + sa := new(SockaddrCtl) + sa.ID = pp.Sc_id + sa.Unit = pp.Sc_unit + return sa, nil + } + case AF_VSOCK: + pp := (*RawSockaddrVM)(unsafe.Pointer(rsa)) + sa := &SockaddrVM{ + CID: pp.Cid, + Port: pp.Port, + } + return sa, nil + } + return nil, EAFNOSUPPORT +} + +// Some external packages rely on SYS___SYSCTL being defined to implement their +// own sysctl wrappers. Provide it here, even though direct syscalls are no +// longer supported on darwin. +const SYS___SYSCTL = SYS_SYSCTL + // Translate "kern.hostname" to []_C_int{0,1,2,3}. func nametomib(name string) (mib []_C_int, err error) { const siz = unsafe.Sizeof(mib[0]) @@ -91,77 +229,20 @@ func direntNamlen(buf []byte) (uint64, bool) { func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } +func PtraceDenyAttach() (err error) { return ptrace(PT_DENY_ATTACH, 0, 0, 0) } -const ( - attrBitMapCount = 5 - attrCmnFullpath = 0x08000000 -) - -type attrList struct { - bitmapCount uint16 - _ uint16 - CommonAttr uint32 - VolAttr uint32 - DirAttr uint32 - FileAttr uint32 - Forkattr uint32 -} - -func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) { - if len(attrBuf) < 4 { - return nil, errors.New("attrBuf too small") - } - attrList.bitmapCount = attrBitMapCount - - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return nil, err - } - - if err := getattrlist(_p0, unsafe.Pointer(&attrList), unsafe.Pointer(&attrBuf[0]), uintptr(len(attrBuf)), int(options)); err != nil { - return nil, err - } - size := *(*uint32)(unsafe.Pointer(&attrBuf[0])) - - // dat is the section of attrBuf that contains valid data, - // without the 4 byte length header. All attribute offsets - // are relative to dat. - dat := attrBuf - if int(size) < len(attrBuf) { - dat = dat[:size] - } - dat = dat[4:] // remove length prefix - - for i := uint32(0); int(i) < len(dat); { - header := dat[i:] - if len(header) < 8 { - return attrs, errors.New("truncated attribute header") - } - datOff := *(*int32)(unsafe.Pointer(&header[0])) - attrLen := *(*uint32)(unsafe.Pointer(&header[4])) - if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) { - return attrs, errors.New("truncated results; attrBuf too small") - } - end := uint32(datOff) + attrLen - attrs = append(attrs, dat[datOff:end]) - i = end - if r := i % 4; r != 0 { - i += (4 - r) - } - } - return -} - -//sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) - -//sysnb pipe() (r int, w int, err error) +//sysnb pipe(p *[2]int32) (err error) func Pipe(p []int) (err error) { if len(p) != 2 { return EINVAL } - p[0], p[1], err = pipe() + var x [2]int32 + err = pipe(&x) + if err == nil { + p[0] = int(x[0]) + p[1] = int(x[1]) + } return } @@ -281,36 +362,7 @@ func Flistxattr(fd int, dest []byte) (sz int, err error) { return flistxattr(fd, xattrPointer(dest), len(dest), 0) } -func setattrlistTimes(path string, times []Timespec, flags int) error { - _p0, err := BytePtrFromString(path) - if err != nil { - return err - } - - var attrList attrList - attrList.bitmapCount = ATTR_BIT_MAP_COUNT - attrList.CommonAttr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME - - // order is mtime, atime: the opposite of Chtimes - attributes := [2]Timespec{times[1], times[0]} - options := 0 - if flags&AT_SYMLINK_NOFOLLOW != 0 { - options |= FSOPT_NOFOLLOW - } - return setattrlist( - _p0, - unsafe.Pointer(&attrList), - unsafe.Pointer(&attributes), - unsafe.Sizeof(attributes), - options) -} - -//sys setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) - -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error { - // Darwin doesn't support SYS_UTIMENSAT - return ENOSYS -} +//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) /* * Wrapped @@ -323,8 +375,46 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error { func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) } //sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL + +func IoctlCtlInfo(fd int, ctlInfo *CtlInfo) error { + return ioctlPtr(fd, CTLIOCGINFO, unsafe.Pointer(ctlInfo)) +} + +// IfreqMTU is struct ifreq used to get or set a network device's MTU. +type IfreqMTU struct { + Name [IFNAMSIZ]byte + MTU int32 +} + +// IoctlGetIfreqMTU performs the SIOCGIFMTU ioctl operation on fd to get the MTU +// of the network device specified by ifname. +func IoctlGetIfreqMTU(fd int, ifname string) (*IfreqMTU, error) { + var ifreq IfreqMTU + copy(ifreq.Name[:], ifname) + err := ioctlPtr(fd, SIOCGIFMTU, unsafe.Pointer(&ifreq)) + return &ifreq, err +} + +// IoctlSetIfreqMTU performs the SIOCSIFMTU ioctl operation on fd to set the MTU +// of the network device specified by ifreq.Name. +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 +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} @@ -382,8 +472,233 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e return } +func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) { + var value IPMreqn + vallen := _Socklen(SizeofIPMreqn) + errno := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) + return &value, errno +} + +func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) +} + +// GetsockoptXucred is a getsockopt wrapper that returns an Xucred struct. +// The usual level and opt are SOL_LOCAL and LOCAL_PEERCRED, respectively. +func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { + x := new(Xucred) + vallen := _Socklen(SizeofXucred) + err := getsockopt(fd, level, opt, unsafe.Pointer(x), &vallen) + return x, err +} + +func GetsockoptTCPConnectionInfo(fd, level, opt int) (*TCPConnectionInfo, error) { + var value TCPConnectionInfo + vallen := _Socklen(SizeofTCPConnectionInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) + return &value, err +} + +func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) { + mib, err := sysctlmib(name, args...) + if err != nil { + return nil, err + } + + var kinfo KinfoProc + n := uintptr(SizeofKinfoProc) + if err := sysctl(mib, (*byte)(unsafe.Pointer(&kinfo)), &n, nil, 0); err != nil { + return nil, err + } + if n != SizeofKinfoProc { + return nil, EIO + } + return &kinfo, nil +} + +func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { + mib, err := sysctlmib(name, args...) + if err != nil { + return nil, err + } + + for { + // Find size. + n := uintptr(0) + if err := sysctl(mib, nil, &n, nil, 0); err != nil { + return nil, err + } + if n == 0 { + return nil, nil + } + if n%SizeofKinfoProc != 0 { + return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc) + } + + // Read into buffer of that size. + buf := make([]KinfoProc, n/SizeofKinfoProc) + if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil { + if err == ENOMEM { + // Process table grew. Try again. + continue + } + return nil, err + } + if n%SizeofKinfoProc != 0 { + return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc) + } + + // The actual call may return less than the original reported required + // size so ensure we deal with that. + return buf[:n/SizeofKinfoProc], nil + } +} + +//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 +} + +const minIovec = 8 + +func Readv(fd int, iovs [][]byte) (n int, err error) { + 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) { + 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) { + 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) { + 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)) + } +} + +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //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) +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) +//sys shmdt(addr uintptr) (err error) +//sys shmget(key int, size int, flag int) (id int, err error) + /* * Exposed directly */ @@ -396,6 +711,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Chroot(path string) (err error) //sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) +//sys Clonefile(src string, dst string, flags int) (err error) +//sys Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) //sys Exchangedata(path1 string, path2 string, options int) (err error) @@ -407,10 +724,12 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) +//sys Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) +//sys Getcwd(buf []byte) (n int, err error) //sys Getdtablesize() (size int) //sysnb Getegid() (egid int) //sysnb Geteuid() (uid int) @@ -423,6 +742,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sysnb Getrlimit(which int, lim *Rlimit) (err error) //sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getsid(pid int) (sid int, err error) +//sysnb Gettimeofday(tp *Timeval) (err error) //sysnb Getuid() (uid int) //sysnb Issetugid() (tainted bool) //sys Kqueue() (fd int, err error) @@ -434,11 +754,12 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error) //sys Mknod(path string, mode uint32, dev int) (err error) +//sys Mount(fsType string, dir string, flags int, data unsafe.Pointer) (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) //sys Pathconf(path string, name int) (val int, err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) @@ -448,6 +769,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) +//sys Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error) //sys Setegid(egid int) (err error) //sysnb Seteuid(euid int) (err error) //sysnb Setgid(gid int) (err error) @@ -457,7 +779,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Setprivexec(flag int) (err error) //sysnb Setregid(rgid int, egid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error) -//sysnb Setrlimit(which int, lim *Rlimit) (err error) //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) //sysnb Setuid(uid int) (err error) @@ -471,197 +792,9 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Unmount(path string, flags int) (err 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 readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ -//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE - -/* - * Unimplemented - */ -// Profil -// Sigaction -// Sigprocmask -// Getlogin -// Sigpending -// Sigaltstack -// Ioctl -// Reboot -// Execve -// Vfork -// Sbrk -// Sstk -// Ovadvise -// Mincore -// Setitimer -// Swapon -// Select -// Sigsuspend -// Readv -// Writev -// Nfssvc -// Getfh -// Quotactl -// Mount -// Csops -// Waitid -// Add_profil -// Kdebug_trace -// Sigreturn -// Atsocket -// Kqueue_from_portset_np -// Kqueue_portset -// Getattrlist -// Setattrlist -// Getdirentriesattr -// Searchfs -// Delete -// Copyfile -// Watchevent -// Waitevent -// Modwatch -// Fsctl -// Initgroups -// Posix_spawn -// Nfsclnt -// Fhopen -// Minherit -// Semsys -// Msgsys -// Shmsys -// Semctl -// Semget -// Semop -// Msgctl -// Msgget -// Msgsnd -// Msgrcv -// Shmat -// Shmctl -// Shmdt -// Shmget -// Shm_open -// Shm_unlink -// Sem_open -// Sem_close -// Sem_unlink -// Sem_wait -// Sem_trywait -// Sem_post -// Sem_getvalue -// Sem_init -// Sem_destroy -// Open_extended -// Umask_extended -// Stat_extended -// Lstat_extended -// Fstat_extended -// Chmod_extended -// Fchmod_extended -// Access_extended -// Settid -// Gettid -// Setsgroups -// Getsgroups -// Setwgroups -// Getwgroups -// Mkfifo_extended -// Mkdir_extended -// Identitysvc -// Shared_region_check_np -// Shared_region_map_np -// __pthread_mutex_destroy -// __pthread_mutex_init -// __pthread_mutex_lock -// __pthread_mutex_trylock -// __pthread_mutex_unlock -// __pthread_cond_init -// __pthread_cond_destroy -// __pthread_cond_broadcast -// __pthread_cond_signal -// Setsid_with_pid -// __pthread_cond_timedwait -// Aio_fsync -// Aio_return -// Aio_suspend -// Aio_cancel -// Aio_error -// Aio_read -// Aio_write -// Lio_listio -// __pthread_cond_wait -// Iopolicysys -// __pthread_kill -// __pthread_sigmask -// __sigwait -// __disable_threadsignal -// __pthread_markcancel -// __pthread_canceled -// __semwait_signal -// Proc_info -// sendfile -// Stat64_extended -// Lstat64_extended -// Fstat64_extended -// __pthread_chdir -// __pthread_fchdir -// Audit -// Auditon -// Getauid -// Setauid -// Getaudit -// Setaudit -// Getaudit_addr -// Setaudit_addr -// Auditctl -// Bsdthread_create -// Bsdthread_terminate -// Stack_snapshot -// Bsdthread_register -// Workq_open -// Workq_ops -// __mac_execve -// __mac_syscall -// __mac_get_file -// __mac_set_file -// __mac_get_link -// __mac_set_link -// __mac_get_proc -// __mac_set_proc -// __mac_get_fd -// __mac_set_fd -// __mac_get_pid -// __mac_get_lcid -// __mac_get_lctx -// __mac_set_lctx -// Setlcid -// Read_nocancel -// Write_nocancel -// Open_nocancel -// Close_nocancel -// Wait4_nocancel -// Recvmsg_nocancel -// Sendmsg_nocancel -// Recvfrom_nocancel -// Accept_nocancel -// Fcntl_nocancel -// Select_nocancel -// Fsync_nocancel -// Connect_nocancel -// Sigsuspend_nocancel -// Readv_nocancel -// Writev_nocancel -// Sendto_nocancel -// Pread_nocancel -// Pwrite_nocancel -// Waitid_nocancel -// Poll_nocancel -// Msgsnd_nocancel -// Msgrcv_nocancel -// Sem_wait_nocancel -// Aio_suspend_nocancel -// __sigwait_nocancel -// __semwait_signal_nocancel -// __mac_mount -// __mac_get_mount -// __mac_getfsstat +//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) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go deleted file mode 100644 index 6b223f9..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,386,!go1.12 - -package unix - -//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_386.go b/vendor/golang.org/x/sys/unix/syscall_darwin_386.go deleted file mode 100644 index 707ba4f..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_386.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build 386,darwin - -package unix - -import ( - "syscall" -) - -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) - -func setTimespec(sec, nsec int64) Timespec { - return Timespec{Sec: int32(sec), Nsec: int32(nsec)} -} - -func setTimeval(sec, usec int64) Timeval { - return Timeval{Sec: int32(sec), Usec: int32(usec)} -} - -//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error) -func Gettimeofday(tv *Timeval) (err error) { - // The tv passed to gettimeofday must be non-nil - // but is otherwise unused. The answers come back - // in the two registers. - sec, usec, err := gettimeofday(tv) - tv.Sec = int32(sec) - tv.Usec = int32(usec) - return err -} - -func SetKevent(k *Kevent_t, fd, mode, flags int) { - k.Ident = uint32(fd) - k.Filter = int16(mode) - k.Flags = uint16(flags) -} - -func (iov *Iovec) SetLen(length int) { - iov.Len = uint32(length) -} - -func (msghdr *Msghdr) SetControllen(length int) { - msghdr.Controllen = uint32(length) -} - -func (msghdr *Msghdr) SetIovlen(length int) { - msghdr.Iovlen = int32(length) -} - -func (cmsg *Cmsghdr) SetLen(length int) { - cmsg.Len = uint32(length) -} - -func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) - -// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions -// of darwin/386 the syscall is called sysctl instead of __sysctl. -const SYS___SYSCTL = SYS_SYSCTL - -//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 -//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 -//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 -//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 -//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 -//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 -//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go deleted file mode 100644 index 68ebd6f..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,amd64,!go1.12 - -package unix - -//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go index fdbfb59..0eaecf5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go @@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,darwin +//go:build amd64 && darwin package unix -import ( - "syscall" -) - -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) +import "syscall" func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} @@ -20,17 +16,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: int32(usec)} } -//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error) -func Gettimeofday(tv *Timeval) (err error) { - // The tv passed to gettimeofday must be non-nil - // but is otherwise unused. The answers come back - // in the two registers. - sec, usec, err := gettimeofday(tv) - tv.Sec = sec - tv.Usec = usec - return err -} - func SetKevent(k *Kevent_t, fd, mode, flags int) { k.Ident = uint64(fd) k.Filter = int16(mode) @@ -55,14 +40,11 @@ func (cmsg *Cmsghdr) SetLen(length int) { func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) -// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions -// of darwin/amd64 the syscall is called sysctl instead of __sysctl. -const SYS___SYSCTL = SYS_SYSCTL - //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 +//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64 diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go deleted file mode 100644 index 0e3f25a..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,arm,!go1.12 - -package unix - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - return 0, ENOSYS -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go deleted file mode 100644 index f8bc4cf..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package unix - -import ( - "syscall" -) - -func ptrace(request int, pid int, addr uintptr, data uintptr) error { - return ENOTSUP -} - -func setTimespec(sec, nsec int64) Timespec { - return Timespec{Sec: int32(sec), Nsec: int32(nsec)} -} - -func setTimeval(sec, usec int64) Timeval { - return Timeval{Sec: int32(sec), Usec: int32(usec)} -} - -//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error) -func Gettimeofday(tv *Timeval) (err error) { - // The tv passed to gettimeofday must be non-nil - // but is otherwise unused. The answers come back - // in the two registers. - sec, usec, err := gettimeofday(tv) - tv.Sec = int32(sec) - tv.Usec = int32(usec) - return err -} - -func SetKevent(k *Kevent_t, fd, mode, flags int) { - k.Ident = uint32(fd) - k.Filter = int16(mode) - k.Flags = uint16(flags) -} - -func (iov *Iovec) SetLen(length int) { - iov.Len = uint32(length) -} - -func (msghdr *Msghdr) SetControllen(length int) { - msghdr.Controllen = uint32(length) -} - -func (msghdr *Msghdr) SetIovlen(length int) { - msghdr.Iovlen = int32(length) -} - -func (cmsg *Cmsghdr) SetLen(length int) { - cmsg.Len = uint32(length) -} - -func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic - -// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions -// of darwin/arm the syscall is called sysctl instead of __sysctl. -const SYS___SYSCTL = SYS_SYSCTL - -//sys Fstat(fd int, stat *Stat_t) (err error) -//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) -//sys Fstatfs(fd int, stat *Statfs_t) (err error) -//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT -//sys Lstat(path string, stat *Stat_t) (err error) -//sys Stat(path string, stat *Stat_t) (err error) -//sys Statfs(path string, stat *Statfs_t) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go deleted file mode 100644 index 01d4504..0000000 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin,arm64,!go1.12 - -package unix - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - return 0, ENOSYS -} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go index 5ede3ac..f36c670 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go @@ -2,17 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64,darwin +//go:build arm64 && darwin package unix -import ( - "syscall" -) - -func ptrace(request int, pid int, addr uintptr, data uintptr) error { - return ENOTSUP -} +import "syscall" func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} @@ -22,17 +16,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: int32(usec)} } -//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error) -func Gettimeofday(tv *Timeval) (err error) { - // The tv passed to gettimeofday must be non-nil - // but is otherwise unused. The answers come back - // in the two registers. - sec, usec, err := gettimeofday(tv) - tv.Sec = sec - tv.Usec = usec - return err -} - func SetKevent(k *Kevent_t, fd, mode, flags int) { k.Ident = uint64(fd) k.Filter = int16(mode) @@ -57,14 +40,11 @@ func (cmsg *Cmsghdr) SetLen(length int) { func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic -// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions -// of darwin/arm64 the syscall is called sysctl instead of __sysctl. -const SYS___SYSCTL = SYS_SYSCTL - //sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT //sys Lstat(path string, stat *Stat_t) (err error) +//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go index f34c86c..2f0fa76 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin,go1.12 +//go:build darwin package unix -import "unsafe" +import _ "unsafe" // Implemented in the runtime package (runtime/sys_darwin.go) func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) @@ -24,10 +24,3 @@ func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) //go:linkname syscall_rawSyscall syscall.rawSyscall //go:linkname syscall_rawSyscall6 syscall.rawSyscall6 //go:linkname syscall_syscallPtr syscall.syscallPtr - -// Find the entry point for f. See comments in runtime/proc.go for the -// function of the same name. -//go:nosplit -func funcPC(f func()) uintptr { - return **(**uintptr)(unsafe.Pointer(&f)) -} diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 8a195ae..be8c002 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -47,6 +47,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + // Translate "kern.hostname" to []_C_int{0,1,2,3}. func nametomib(name string) (mib []_C_int, err error) { const siz = unsafe.Sizeof(mib[0]) @@ -91,23 +95,44 @@ func direntNamlen(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) } -//sysnb pipe() (r int, w int, err error) +//sysnb pipe() (r int, w int, err error) func Pipe(p []int) (err error) { if len(p) != 2 { return EINVAL } - p[0], p[1], err = pipe() + r, w, err := pipe() + if err == nil { + p[0], p[1] = r, w + } return } +//sysnb pipe2(p *[2]_C_int, flags int) (r int, w int, err error) + +func Pipe2(p []int, flags int) (err error) { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + // pipe2 on dragonfly takes an fds array as an argument, but still + // returns the file descriptors. + r, w, err := pipe2(&pp, flags) + if err == nil { + p[0], p[1] = r, w + } + return err +} + //sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error) -func Pread(fd int, p []byte, offset int64) (n int, err error) { + +func pread(fd int, p []byte, offset int64) (n int, err error) { return extpread(fd, p, 0, offset) } //sys extpwrite(fd int, p []byte, flags int, offset int64) (n int, err error) -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + +func pwrite(fd int, p []byte, offset int64) (n int, err error) { return extpwrite(fd, p, 0, offset) } @@ -129,23 +154,8 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { var _p0 unsafe.Pointer var bufsize uintptr @@ -161,14 +171,10 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { return } -func setattrlistTimes(path string, times []Timespec, flags int) error { - // used on Darwin for UtimesNano - return ENOSYS -} - //sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL -//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error { err := sysctl(mib, old, oldlen, nil, 0) @@ -240,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 */ @@ -250,6 +268,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Chmod(path string, mode uint32) (err error) //sys Chown(path string, uid int, gid int) (err error) //sys Chroot(path string) (err error) +//sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) @@ -319,7 +338,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(which int, lim *Rlimit) (err error) //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) //sysnb Setuid(uid int) (err error) @@ -335,205 +353,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Unmount(path string, flags int) (err 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 readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ -//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE +//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 accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) - -/* - * Unimplemented - * TODO(jsing): Update this list for DragonFly. - */ -// Profil -// Sigaction -// Sigprocmask -// Getlogin -// Sigpending -// Sigaltstack -// Reboot -// Execve -// Vfork -// Sbrk -// Sstk -// Ovadvise -// Mincore -// Setitimer -// Swapon -// Select -// Sigsuspend -// Readv -// Writev -// Nfssvc -// Getfh -// Quotactl -// Mount -// Csops -// Waitid -// Add_profil -// Kdebug_trace -// Sigreturn -// Atsocket -// Kqueue_from_portset_np -// Kqueue_portset -// Getattrlist -// Setattrlist -// Getdirentriesattr -// Searchfs -// Delete -// Copyfile -// Watchevent -// Waitevent -// Modwatch -// Getxattr -// Fgetxattr -// Setxattr -// Fsetxattr -// Removexattr -// Fremovexattr -// Listxattr -// Flistxattr -// Fsctl -// Initgroups -// Posix_spawn -// Nfsclnt -// Fhopen -// Minherit -// Semsys -// Msgsys -// Shmsys -// Semctl -// Semget -// Semop -// Msgctl -// Msgget -// Msgsnd -// Msgrcv -// Shmat -// Shmctl -// Shmdt -// Shmget -// Shm_open -// Shm_unlink -// Sem_open -// Sem_close -// Sem_unlink -// Sem_wait -// Sem_trywait -// Sem_post -// Sem_getvalue -// Sem_init -// Sem_destroy -// Open_extended -// Umask_extended -// Stat_extended -// Lstat_extended -// Fstat_extended -// Chmod_extended -// Fchmod_extended -// Access_extended -// Settid -// Gettid -// Setsgroups -// Getsgroups -// Setwgroups -// Getwgroups -// Mkfifo_extended -// Mkdir_extended -// Identitysvc -// Shared_region_check_np -// Shared_region_map_np -// __pthread_mutex_destroy -// __pthread_mutex_init -// __pthread_mutex_lock -// __pthread_mutex_trylock -// __pthread_mutex_unlock -// __pthread_cond_init -// __pthread_cond_destroy -// __pthread_cond_broadcast -// __pthread_cond_signal -// Setsid_with_pid -// __pthread_cond_timedwait -// Aio_fsync -// Aio_return -// Aio_suspend -// Aio_cancel -// Aio_error -// Aio_read -// Aio_write -// Lio_listio -// __pthread_cond_wait -// Iopolicysys -// __pthread_kill -// __pthread_sigmask -// __sigwait -// __disable_threadsignal -// __pthread_markcancel -// __pthread_canceled -// __semwait_signal -// Proc_info -// Stat64_extended -// Lstat64_extended -// Fstat64_extended -// __pthread_chdir -// __pthread_fchdir -// Audit -// Auditon -// Getauid -// Setauid -// Getaudit -// Setaudit -// Getaudit_addr -// Setaudit_addr -// Auditctl -// Bsdthread_create -// Bsdthread_terminate -// Stack_snapshot -// Bsdthread_register -// Workq_open -// Workq_ops -// __mac_execve -// __mac_syscall -// __mac_get_file -// __mac_set_file -// __mac_get_link -// __mac_set_link -// __mac_get_proc -// __mac_set_proc -// __mac_get_fd -// __mac_set_fd -// __mac_get_pid -// __mac_get_lcid -// __mac_get_lctx -// __mac_set_lctx -// Setlcid -// Read_nocancel -// Write_nocancel -// Open_nocancel -// Close_nocancel -// Wait4_nocancel -// Recvmsg_nocancel -// Sendmsg_nocancel -// Recvfrom_nocancel -// Accept_nocancel -// Fcntl_nocancel -// Select_nocancel -// Fsync_nocancel -// Connect_nocancel -// Sigsuspend_nocancel -// Readv_nocancel -// Writev_nocancel -// Sendto_nocancel -// Pread_nocancel -// Pwrite_nocancel -// Waitid_nocancel -// Msgsnd_nocancel -// Msgrcv_nocancel -// Sem_wait_nocancel -// Aio_suspend_nocancel -// __sigwait_nocancel -// __semwait_signal_nocancel -// __mac_mount -// __mac_get_mount -// __mac_getfsstat diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go index a6b4830..14bab6b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,dragonfly +//go:build amd64 && dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 6932e7c..2b57e0f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -13,29 +13,17 @@ package unix import ( + "errors" "sync" "unsafe" ) -const ( - SYS_FSTAT_FREEBSD12 = 551 // { int fstat(int fd, _Out_ struct stat *sb); } - SYS_FSTATAT_FREEBSD12 = 552 // { int fstatat(int fd, _In_z_ char *path, \ - SYS_GETDIRENTRIES_FREEBSD12 = 554 // { ssize_t getdirentries(int fd, \ - SYS_STATFS_FREEBSD12 = 555 // { int statfs(_In_z_ char *path, \ - SYS_FSTATFS_FREEBSD12 = 556 // { int fstatfs(int fd, \ - SYS_GETFSSTAT_FREEBSD12 = 557 // { int getfsstat( \ - SYS_MKNODAT_FREEBSD12 = 559 // { int mknodat(int fd, _In_z_ char *path, \ -) - // See https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html. var ( osreldateOnce sync.Once osreldate uint32 ) -// INO64_FIRST from /usr/src/lib/libc/sys/compat-ino64.h -const _ino64First = 1200031 - func supportsABI(ver uint32) bool { osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") }) return osreldate >= ver @@ -54,6 +42,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + // Translate "kern.hostname" to []_C_int{0,1,2,3}. func nametomib(name string) (mib []_C_int, err error) { const siz = unsafe.Sizeof(mib[0]) @@ -106,8 +98,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } @@ -122,6 +116,15 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) } +// GetsockoptXucred is a getsockopt wrapper that returns an Xucred struct. +// The usual level and opt are SOL_LOCAL and LOCAL_PEERCRED, respectively. +func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { + x := new(Xucred) + vallen := _Socklen(SizeofXucred) + err := getsockopt(fd, level, opt, unsafe.Pointer(x), &vallen) + return x, err +} + func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny @@ -140,91 +143,53 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { var ( - _p0 unsafe.Pointer - bufsize uintptr - oldBuf []statfs_freebsd11_t - needsConvert bool + _p0 unsafe.Pointer + bufsize uintptr ) - if len(buf) > 0 { - if supportsABI(_ino64First) { - _p0 = unsafe.Pointer(&buf[0]) - bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) - } else { - n := len(buf) - oldBuf = make([]statfs_freebsd11_t, n) - _p0 = unsafe.Pointer(&oldBuf[0]) - bufsize = unsafe.Sizeof(statfs_freebsd11_t{}) * uintptr(n) - needsConvert = true - } + _p0 = unsafe.Pointer(&buf[0]) + bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } - var sysno uintptr = SYS_GETFSSTAT - if supportsABI(_ino64First) { - sysno = SYS_GETFSSTAT_FREEBSD12 - } - r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags)) + r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) n = int(r0) if e1 != 0 { err = e1 } - if e1 == 0 && needsConvert { - for i := range oldBuf { - buf[i].convertFrom(&oldBuf[i]) - } - } return } -func setattrlistTimes(path string, times []Timespec, flags int) error { - // used on Darwin for UtimesNano - return ENOSYS -} - -//sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL -//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} n := unsafe.Sizeof(uname.Sysname) - if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil { + // Suppress ENOMEM errors to be compatible with the C library __xuname() implementation. + if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } mib = []_C_int{CTL_KERN, KERN_HOSTNAME} n = unsafe.Sizeof(uname.Nodename) - if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } mib = []_C_int{CTL_KERN, KERN_OSRELEASE} n = unsafe.Sizeof(uname.Release) - if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } mib = []_C_int{CTL_KERN, KERN_VERSION} n = unsafe.Sizeof(uname.Version) - if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } @@ -242,7 +207,7 @@ func Uname(uname *Utsname) error { mib = []_C_int{CTL_HW, HW_MACHINE} n = unsafe.Sizeof(uname.Machine) - if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } @@ -250,87 +215,11 @@ func Uname(uname *Utsname) error { } func Stat(path string, st *Stat_t) (err error) { - var oldStat stat_freebsd11_t - if supportsABI(_ino64First) { - return fstatat_freebsd12(AT_FDCWD, path, st, 0) - } - err = stat(path, &oldStat) - if err != nil { - return err - } - - st.convertFrom(&oldStat) - return nil + return Fstatat(AT_FDCWD, path, st, 0) } func Lstat(path string, st *Stat_t) (err error) { - var oldStat stat_freebsd11_t - if supportsABI(_ino64First) { - return fstatat_freebsd12(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW) - } - err = lstat(path, &oldStat) - if err != nil { - return err - } - - st.convertFrom(&oldStat) - return nil -} - -func Fstat(fd int, st *Stat_t) (err error) { - var oldStat stat_freebsd11_t - if supportsABI(_ino64First) { - return fstat_freebsd12(fd, st) - } - err = fstat(fd, &oldStat) - if err != nil { - return err - } - - st.convertFrom(&oldStat) - return nil -} - -func Fstatat(fd int, path string, st *Stat_t, flags int) (err error) { - var oldStat stat_freebsd11_t - if supportsABI(_ino64First) { - return fstatat_freebsd12(fd, path, st, flags) - } - err = fstatat(fd, path, &oldStat, flags) - if err != nil { - return err - } - - st.convertFrom(&oldStat) - return nil -} - -func Statfs(path string, st *Statfs_t) (err error) { - var oldStatfs statfs_freebsd11_t - if supportsABI(_ino64First) { - return statfs_freebsd12(path, st) - } - err = statfs(path, &oldStatfs) - if err != nil { - return err - } - - st.convertFrom(&oldStatfs) - return nil -} - -func Fstatfs(fd int, st *Statfs_t) (err error) { - var oldStatfs statfs_freebsd11_t - if supportsABI(_ino64First) { - return fstatfs_freebsd12(fd, st) - } - err = fstatfs(fd, &oldStatfs) - if err != nil { - return err - } - - st.convertFrom(&oldStatfs) - return nil + return Fstatat(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW) } func Getdents(fd int, buf []byte) (n int, err error) { @@ -338,162 +227,25 @@ func Getdents(fd int, buf []byte) (n int, err error) { } func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - if supportsABI(_ino64First) { - if basep == nil || unsafe.Sizeof(*basep) == 8 { - return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep))) - } - // The freebsd12 syscall needs a 64-bit base. On 32-bit machines - // we can't just use the basep passed in. See #32498. - var base uint64 = uint64(*basep) - n, err = getdirentries_freebsd12(fd, buf, &base) - *basep = uintptr(base) - if base>>32 != 0 { - // We can't stuff the base back into a uintptr, so any - // future calls would be suspect. Generate an error. - // EIO is allowed by getdirentries. - err = EIO - } - return - } - - // The old syscall entries are smaller than the new. Use 1/4 of the original - // buffer size rounded up to DIRBLKSIZ (see /usr/src/lib/libc/sys/getdirentries.c). - oldBufLen := roundup(len(buf)/4, _dirblksiz) - oldBuf := make([]byte, oldBufLen) - n, err = getdirentries(fd, oldBuf, basep) - if err == nil && n > 0 { - n = convertFromDirents11(buf, oldBuf[:n]) + if basep == nil || unsafe.Sizeof(*basep) == 8 { + return getdirentries(fd, buf, (*uint64)(unsafe.Pointer(basep))) + } + // The syscall needs a 64-bit base. On 32-bit machines + // we can't just use the basep passed in. See #32498. + var base uint64 = uint64(*basep) + n, err = getdirentries(fd, buf, &base) + *basep = uintptr(base) + if base>>32 != 0 { + // We can't stuff the base back into a uintptr, so any + // future calls would be suspect. Generate an error. + // EIO is allowed by getdirentries. + err = EIO } return } func Mknod(path string, mode uint32, dev uint64) (err error) { - var oldDev int - if supportsABI(_ino64First) { - return mknodat_freebsd12(AT_FDCWD, path, mode, dev) - } - oldDev = int(dev) - return mknod(path, mode, oldDev) -} - -func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { - var oldDev int - if supportsABI(_ino64First) { - return mknodat_freebsd12(fd, path, mode, dev) - } - oldDev = int(dev) - return mknodat(fd, path, mode, oldDev) -} - -// round x to the nearest multiple of y, larger or equal to x. -// -// from /usr/include/sys/param.h Macros for counting and rounding. -// #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -func roundup(x, y int) int { - return ((x + y - 1) / y) * y -} - -func (s *Stat_t) convertFrom(old *stat_freebsd11_t) { - *s = Stat_t{ - Dev: uint64(old.Dev), - Ino: uint64(old.Ino), - Nlink: uint64(old.Nlink), - Mode: old.Mode, - Uid: old.Uid, - Gid: old.Gid, - Rdev: uint64(old.Rdev), - Atim: old.Atim, - Mtim: old.Mtim, - Ctim: old.Ctim, - Btim: old.Btim, - Size: old.Size, - Blocks: old.Blocks, - Blksize: old.Blksize, - Flags: old.Flags, - Gen: uint64(old.Gen), - } -} - -func (s *Statfs_t) convertFrom(old *statfs_freebsd11_t) { - *s = Statfs_t{ - Version: _statfsVersion, - Type: old.Type, - Flags: old.Flags, - Bsize: old.Bsize, - Iosize: old.Iosize, - Blocks: old.Blocks, - Bfree: old.Bfree, - Bavail: old.Bavail, - Files: old.Files, - Ffree: old.Ffree, - Syncwrites: old.Syncwrites, - Asyncwrites: old.Asyncwrites, - Syncreads: old.Syncreads, - Asyncreads: old.Asyncreads, - // Spare - Namemax: old.Namemax, - Owner: old.Owner, - Fsid: old.Fsid, - // Charspare - // Fstypename - // Mntfromname - // Mntonname - } - - sl := old.Fstypename[:] - n := clen(*(*[]byte)(unsafe.Pointer(&sl))) - copy(s.Fstypename[:], old.Fstypename[:n]) - - sl = old.Mntfromname[:] - n = clen(*(*[]byte)(unsafe.Pointer(&sl))) - copy(s.Mntfromname[:], old.Mntfromname[:n]) - - sl = old.Mntonname[:] - n = clen(*(*[]byte)(unsafe.Pointer(&sl))) - copy(s.Mntonname[:], old.Mntonname[:n]) -} - -func convertFromDirents11(buf []byte, old []byte) int { - const ( - fixedSize = int(unsafe.Offsetof(Dirent{}.Name)) - oldFixedSize = int(unsafe.Offsetof(dirent_freebsd11{}.Name)) - ) - - dstPos := 0 - srcPos := 0 - for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) { - var dstDirent Dirent - var srcDirent dirent_freebsd11 - - // If multiple direntries are written, sometimes when we reach the final one, - // we may have cap of old less than size of dirent_freebsd11. - copy((*[unsafe.Sizeof(srcDirent)]byte)(unsafe.Pointer(&srcDirent))[:], old[srcPos:]) - - reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8) - if dstPos+reclen > len(buf) { - break - } - - dstDirent.Fileno = uint64(srcDirent.Fileno) - dstDirent.Off = 0 - dstDirent.Reclen = uint16(reclen) - dstDirent.Type = srcDirent.Type - dstDirent.Pad0 = 0 - dstDirent.Namlen = uint16(srcDirent.Namlen) - dstDirent.Pad1 = 0 - - copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen]) - copy(buf[dstPos:], (*[unsafe.Sizeof(dstDirent)]byte)(unsafe.Pointer(&dstDirent))[:]) - padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen] - for i := range padding { - padding[i] = 0 - } - - dstPos += int(dstDirent.Reclen) - srcPos += int(srcDirent.Reclen) - } - - return dstPos + return Mknodat(AT_FDCWD, path, mode, dev) } func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { @@ -504,33 +256,51 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e } //sys ptrace(request int, pid int, addr uintptr, data int) (err error) +//sys ptracePtr(request int, pid int, addr unsafe.Pointer, data int) (err error) = SYS_PTRACE func PtraceAttach(pid int) (err error) { - return ptrace(PTRACE_ATTACH, pid, 0, 0) + return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceCont(pid int, signal int) (err error) { - return ptrace(PTRACE_CONT, pid, 1, signal) + return ptrace(PT_CONTINUE, pid, 1, signal) } func PtraceDetach(pid int) (err error) { - return ptrace(PTRACE_DETACH, pid, 1, 0) + return ptrace(PT_DETACH, pid, 1, 0) } func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) { - return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0) + return ptracePtr(PT_GETFPREGS, pid, unsafe.Pointer(fpregsout), 0) } func PtraceGetRegs(pid int, regsout *Reg) (err error) { - return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0) + return ptracePtr(PT_GETREGS, pid, unsafe.Pointer(regsout), 0) +} + +func PtraceIO(req int, pid int, offs uintptr, out []byte, countin int) (count int, err error) { + ioDesc := PtraceIoDesc{ + Op: int32(req), + Offs: offs, + } + if countin > 0 { + _ = out[:countin] // check bounds + ioDesc.Addr = &out[0] + } else if out != nil { + ioDesc.Addr = (*byte)(unsafe.Pointer(&_zero)) + } + ioDesc.SetLen(countin) + + err = ptracePtr(PT_IO, pid, unsafe.Pointer(&ioDesc), 0) + return int(ioDesc.Len), err } func PtraceLwpEvents(pid int, enable int) (err error) { - return ptrace(PTRACE_LWPEVENTS, pid, 0, enable) + return ptrace(PT_LWP_EVENTS, pid, 0, enable) } -func PtraceLwpInfo(pid int, info uintptr) (err error) { - return ptrace(PTRACE_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{}))) +func PtraceLwpInfo(pid int, info *PtraceLwpInfoStruct) (err error) { + return ptracePtr(PT_LWPINFO, pid, unsafe.Pointer(info), int(unsafe.Sizeof(*info))) } func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { @@ -550,11 +320,23 @@ func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) { } func PtraceSetRegs(pid int, regs *Reg) (err error) { - return ptrace(PTRACE_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0) + return ptracePtr(PT_SETREGS, pid, unsafe.Pointer(regs), 0) } func PtraceSingleStep(pid int) (err error) { - return ptrace(PTRACE_SINGLESTEP, pid, 1, 0) + return ptrace(PT_STEP, pid, 1, 0) +} + +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 } /* @@ -570,6 +352,7 @@ func PtraceSingleStep(pid int) (err error) { //sys Chmod(path string, mode uint32) (err error) //sys Chown(path string, uid int, gid int) (err error) //sys Chroot(path string) (err error) +//sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) @@ -596,16 +379,12 @@ func PtraceSingleStep(pid int) (err error) { //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) -//sys fstat(fd int, stat *stat_freebsd11_t) (err error) -//sys fstat_freebsd12(fd int, stat *Stat_t) (err error) -//sys fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) -//sys fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) -//sys fstatfs(fd int, stat *statfs_freebsd11_t) (err error) -//sys fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) +//sys Fstat(fd int, stat *Stat_t) (err error) +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) +//sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) -//sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) -//sys getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) +//sys getdirentries(fd int, buf []byte, basep *uint64) (n int, err error) //sys Getdtablesize() (size int) //sysnb Getegid() (egid int) //sysnb Geteuid() (uid int) @@ -627,19 +406,16 @@ func PtraceSingleStep(pid int) (err error) { //sys Link(path string, link string) (err error) //sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) //sys Listen(s int, backlog int) (err error) -//sys lstat(path string, stat *stat_freebsd11_t) (err error) //sys Mkdir(path string, mode uint32) (err error) //sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error) -//sys mknod(path string, mode uint32, dev int) (err error) -//sys mknodat(fd int, path string, mode uint32, dev int) (err error) -//sys mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) +//sys Mknodat(fd int, path string, mode uint32, dev uint64) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(fdat int, path string, mode int, perm uint32) (fd int, err error) //sys Pathconf(path string, name int) (val int, err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) @@ -659,13 +435,10 @@ func PtraceSingleStep(pid int) (err error) { //sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(which int, lim *Rlimit) (err error) //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) //sysnb Setuid(uid int) (err error) -//sys stat(path string, stat *stat_freebsd11_t) (err error) -//sys statfs(path string, stat *statfs_freebsd11_t) (err error) -//sys statfs_freebsd12(path string, stat *Statfs_t) (err error) +//sys Statfs(path string, stat *Statfs_t) (err error) //sys Symlink(path string, link string) (err error) //sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys Sync() (err error) @@ -676,199 +449,7 @@ func PtraceSingleStep(pid int) (err error) { //sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Unmount(path string, flags int) (err 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 readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ -//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE +//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 accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) - -/* - * Unimplemented - */ -// Profil -// Sigaction -// Sigprocmask -// Getlogin -// Sigpending -// Sigaltstack -// Ioctl -// Reboot -// Execve -// Vfork -// Sbrk -// Sstk -// Ovadvise -// Mincore -// Setitimer -// Swapon -// Select -// Sigsuspend -// Readv -// Writev -// Nfssvc -// Getfh -// Quotactl -// Mount -// Csops -// Waitid -// Add_profil -// Kdebug_trace -// Sigreturn -// Atsocket -// Kqueue_from_portset_np -// Kqueue_portset -// Getattrlist -// Setattrlist -// Getdents -// Getdirentriesattr -// Searchfs -// Delete -// Copyfile -// Watchevent -// Waitevent -// Modwatch -// Fsctl -// Initgroups -// Posix_spawn -// Nfsclnt -// Fhopen -// Minherit -// Semsys -// Msgsys -// Shmsys -// Semctl -// Semget -// Semop -// Msgctl -// Msgget -// Msgsnd -// Msgrcv -// Shmat -// Shmctl -// Shmdt -// Shmget -// Shm_open -// Shm_unlink -// Sem_open -// Sem_close -// Sem_unlink -// Sem_wait -// Sem_trywait -// Sem_post -// Sem_getvalue -// Sem_init -// Sem_destroy -// Open_extended -// Umask_extended -// Stat_extended -// Lstat_extended -// Fstat_extended -// Chmod_extended -// Fchmod_extended -// Access_extended -// Settid -// Gettid -// Setsgroups -// Getsgroups -// Setwgroups -// Getwgroups -// Mkfifo_extended -// Mkdir_extended -// Identitysvc -// Shared_region_check_np -// Shared_region_map_np -// __pthread_mutex_destroy -// __pthread_mutex_init -// __pthread_mutex_lock -// __pthread_mutex_trylock -// __pthread_mutex_unlock -// __pthread_cond_init -// __pthread_cond_destroy -// __pthread_cond_broadcast -// __pthread_cond_signal -// Setsid_with_pid -// __pthread_cond_timedwait -// Aio_fsync -// Aio_return -// Aio_suspend -// Aio_cancel -// Aio_error -// Aio_read -// Aio_write -// Lio_listio -// __pthread_cond_wait -// Iopolicysys -// __pthread_kill -// __pthread_sigmask -// __sigwait -// __disable_threadsignal -// __pthread_markcancel -// __pthread_canceled -// __semwait_signal -// Proc_info -// Stat64_extended -// Lstat64_extended -// Fstat64_extended -// __pthread_chdir -// __pthread_fchdir -// Audit -// Auditon -// Getauid -// Setauid -// Getaudit -// Setaudit -// Getaudit_addr -// Setaudit_addr -// Auditctl -// Bsdthread_create -// Bsdthread_terminate -// Stack_snapshot -// Bsdthread_register -// Workq_open -// Workq_ops -// __mac_execve -// __mac_syscall -// __mac_get_file -// __mac_set_file -// __mac_get_link -// __mac_set_link -// __mac_get_proc -// __mac_set_proc -// __mac_get_fd -// __mac_set_fd -// __mac_get_pid -// __mac_get_lcid -// __mac_get_lctx -// __mac_set_lctx -// Setlcid -// Read_nocancel -// Write_nocancel -// Open_nocancel -// Close_nocancel -// Wait4_nocancel -// Recvmsg_nocancel -// Sendmsg_nocancel -// Recvfrom_nocancel -// Accept_nocancel -// Fcntl_nocancel -// Select_nocancel -// Fsync_nocancel -// Connect_nocancel -// Sigsuspend_nocancel -// Readv_nocancel -// Writev_nocancel -// Sendto_nocancel -// Pread_nocancel -// Pwrite_nocancel -// Waitid_nocancel -// Poll_nocancel -// Msgsnd_nocancel -// Msgrcv_nocancel -// Sem_wait_nocancel -// Aio_suspend_nocancel -// __sigwait_nocancel -// __semwait_signal_nocancel -// __mac_mount -// __mac_get_mount -// __mac_getfsstat diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go index 72a506d..3967bca 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386,freebsd +//go:build 386 && freebsd package unix @@ -41,6 +41,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (d *PtraceIoDesc) SetLen(length int) { + d.Len = uint32(length) +} + func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { var writtenOut uint64 = 0 _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0) @@ -56,11 +60,5 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func PtraceGetFsBase(pid int, fsbase *int64) (err error) { - return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0) -} - -func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) { - ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)} - err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) - return int(ioDesc.Len), err + return ptracePtr(PT_GETFSBASE, pid, unsafe.Pointer(fsbase), 0) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go index d5e376a..eff19ad 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,freebsd +//go:build amd64 && freebsd package unix @@ -41,6 +41,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (d *PtraceIoDesc) SetLen(length int) { + d.Len = uint64(length) +} + func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { var writtenOut uint64 = 0 _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0, 0) @@ -56,11 +60,5 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func PtraceGetFsBase(pid int, fsbase *int64) (err error) { - return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0) -} - -func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) { - ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)} - err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) - return int(ioDesc.Len), err + return ptracePtr(PT_GETFSBASE, pid, unsafe.Pointer(fsbase), 0) } diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go index 4ea45bc..4f24b51 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm,freebsd +//go:build arm && freebsd package unix @@ -41,6 +41,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (d *PtraceIoDesc) SetLen(length int) { + d.Len = uint32(length) +} + func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { var writtenOut uint64 = 0 _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0) @@ -54,9 +58,3 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e } func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) - -func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) { - ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)} - err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) - return int(ioDesc.Len), err -} diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go index aa5326d..ac30759 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64,freebsd +//go:build arm64 && freebsd package unix @@ -41,6 +41,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (d *PtraceIoDesc) SetLen(length int) { + d.Len = uint64(length) +} + func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { var writtenOut uint64 = 0 _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0, 0) @@ -54,9 +58,3 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e } func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) - -func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) { - ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)} - err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) - return int(ioDesc.Len), err -} diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go new file mode 100644 index 0000000..aab725c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go @@ -0,0 +1,60 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build riscv64 && freebsd + +package unix + +import ( + "syscall" + "unsafe" +) + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: sec, Usec: usec} +} + +func SetKevent(k *Kevent_t, fd, mode, flags int) { + k.Ident = uint64(fd) + k.Filter = int16(mode) + k.Flags = uint16(flags) +} + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint64(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = uint32(length) +} + +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = int32(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint32(length) +} + +func (d *PtraceIoDesc) SetLen(length int) { + d.Len = uint64(length) +} + +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + var writtenOut uint64 = 0 + _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0, 0) + + written = int(writtenOut) + + if e1 != 0 { + err = e1 + } + return +} + +func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd.go b/vendor/golang.org/x/sys/unix/syscall_hurd.go new file mode 100644 index 0000000..a6a2d2f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_hurd.go @@ -0,0 +1,30 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build hurd + +package unix + +/* +#include +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)) + if r0 == -1 && er != nil { + err = er + } + return +} + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(uintptr(arg))) + if r0 == -1 && er != nil { + err = er + } + return +} diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd_386.go b/vendor/golang.org/x/sys/unix/syscall_hurd_386.go new file mode 100644 index 0000000..df89f9e --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_hurd_386.go @@ -0,0 +1,28 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 && hurd + +package unix + +const ( + TIOCGETA = 0x62251713 +) + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]uint8 + Ispeed int32 + Ospeed int32 +} diff --git a/vendor/golang.org/x/sys/unix/syscall_illumos.go b/vendor/golang.org/x/sys/unix/syscall_illumos.go index 99e62dc..a863f70 100644 --- a/vendor/golang.org/x/sys/unix/syscall_illumos.go +++ b/vendor/golang.org/x/sys/unix/syscall_illumos.go @@ -1,30 +1,31 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // illumos system calls not present on Solaris. -// +build amd64,illumos +//go:build amd64 && illumos package unix -import "unsafe" +import ( + "unsafe" +) func bytes2iovec(bs [][]byte) []Iovec { iovecs := make([]Iovec, len(bs)) for i, b := range bs { iovecs[i].SetLen(len(b)) if len(b) > 0 { - // somehow Iovec.Base on illumos is (*int8), not (*byte) - iovecs[i].Base = (*int8)(unsafe.Pointer(&b[0])) + iovecs[i].Base = &b[0] } else { - iovecs[i].Base = (*int8)(unsafe.Pointer(&_zero)) + iovecs[i].Base = (*byte)(unsafe.Pointer(&_zero)) } } return iovecs } -//sys readv(fd int, iovs []Iovec) (n int, err error) +//sys readv(fd int, iovs []Iovec) (n int, err error) func Readv(fd int, iovs [][]byte) (n int, err error) { iovecs := bytes2iovec(iovs) @@ -32,7 +33,7 @@ func Readv(fd int, iovs [][]byte) (n int, err error) { return n, err } -//sys preadv(fd int, iovs []Iovec, off int64) (n int, err error) +//sys preadv(fd int, iovs []Iovec, off int64) (n int, err error) func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) { iovecs := bytes2iovec(iovs) @@ -40,7 +41,7 @@ func Preadv(fd int, iovs [][]byte, off int64) (n int, err error) { return n, err } -//sys writev(fd int, iovs []Iovec) (n int, err error) +//sys writev(fd int, iovs []Iovec) (n int, err error) func Writev(fd int, iovs [][]byte) (n int, err error) { iovecs := bytes2iovec(iovs) @@ -48,10 +49,30 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { return n, err } -//sys pwritev(fd int, iovs []Iovec, off int64) (n int, err error) +//sys pwritev(fd int, iovs []Iovec, off int64) (n int, err error) func Pwritev(fd int, iovs [][]byte, off int64) (n int, err error) { iovecs := bytes2iovec(iovs) n, err = pwritev(fd, iovecs, off) return n, err } + +//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4 + +func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept4(fd, &rsa, &len, flags) + if err != nil { + return + } + if len > SizeofSockaddrAny { + panic("RawSockaddrAny too small") + } + sa, err = anyToSockaddr(fd, &rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index bbe1abb..06c0eea 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -13,8 +13,10 @@ package unix import ( "encoding/binary" - "runtime" + "slices" + "strconv" "syscall" + "time" "unsafe" ) @@ -38,6 +40,13 @@ func Creat(path string, mode uint32) (fd int, err error) { return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) } +func EpollCreate(size int) (fd int, err error) { + if size <= 0 { + return -1, EINVAL + } + return EpollCreate1(0) +} + //sys FanotifyInit(flags uint, event_f_flags uint) (fd int, err error) //sys fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error) @@ -53,61 +62,43 @@ func FanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname string) ( } //sys fchmodat(dirfd int, path string, mode uint32) (err error) - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - // Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior - // and check the flags. Otherwise the mode would be applied to the symlink - // destination which is not what the user expects. - if flags&^AT_SYMLINK_NOFOLLOW != 0 { - return EINVAL - } else if flags&AT_SYMLINK_NOFOLLOW != 0 { - return EOPNOTSUPP +//sys fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) error { + // Linux fchmodat doesn't support the flags parameter, but fchmodat2 does. + // Try fchmodat2 if flags are specified. + if flags != 0 { + err := fchmodat2(dirfd, path, mode, flags) + if err == ENOSYS { + // fchmodat2 isn't available. If the flags are known to be valid, + // return EOPNOTSUPP to indicate that fchmodat doesn't support them. + if flags&^(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 { + return EINVAL + } else if flags&(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 { + return EOPNOTSUPP + } + } + return err } return fchmodat(dirfd, path, mode) } -//sys ioctl(fd int, req uint, arg uintptr) (err error) - -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. - -// IoctlRetInt performs an ioctl operation specified by req on a device -// associated with opened file descriptor fd, and returns a non-negative -// integer that is returned by the ioctl syscall. -func IoctlRetInt(fd int, req uint) (int, error) { - ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0) - if err != 0 { - return 0, err - } - return int(ret), nil -} - -// IoctlSetPointerInt performs an ioctl operation which sets an -// integer value on fd, using the specified request number. The ioctl -// argument is called with a pointer to the integer value, rather than -// passing the integer value directly. -func IoctlSetPointerInt(fd int, req uint, value int) error { - v := int32(value) - return ioctl(fd, req, uintptr(unsafe.Pointer(&v))) +func InotifyInit() (fd int, err error) { + return InotifyInit1(0) } -func IoctlSetRTCTime(fd int, value *RTCTime) error { - err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err -} +//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL -func IoctlGetUint32(fd int, req uint) (uint32, error) { - var value uint32 - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - return value, err -} - -func IoctlGetRTCTime(fd int) (*RTCTime, error) { - var value RTCTime - err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) - return &value, err -} +// ioctl itself should not be exposed directly, but additional get/set functions +// for specific types are permissible. These are defined in ioctl.go and +// ioctl_linux.go. +// +// The third argument to ioctl is often a pointer but sometimes an integer. +// Callers should use ioctlPtr when the third argument is a pointer and ioctl +// when the third argument is an integer. +// +// TODO: some existing code incorrectly uses ioctl when it should use ioctlPtr. //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) @@ -133,6 +124,31 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) return openat(dirfd, path, flags|O_LARGEFILE, mode) } +//sys openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) + +func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) { + return openat2(dirfd, path, how, SizeofOpenHow) +} + +func Pipe(p []int) error { + return Pipe2(p, 0) +} + +//sysnb pipe2(p *[2]_C_int, flags int) (err error) + +func Pipe2(p []int, flags int) error { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + err := pipe2(&pp, flags) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return err +} + //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { @@ -142,6 +158,15 @@ func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error return ppoll(&fds[0], len(fds), timeout, sigmask) } +func Poll(fds []PollFd, timeout int) (n int, err error) { + var ts *Timespec + if timeout >= 0 { + ts = new(Timespec) + *ts = NsecToTimespec(int64(timeout) * 1e6) + } + return Ppoll(fds, ts, nil) +} + //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) func Readlink(path string, buf []byte) (n int, err error) { @@ -192,27 +217,7 @@ func Utimes(path string, tv []Timeval) error { //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) func UtimesNano(path string, ts []Timespec) error { - if ts == nil { - err := utimensat(AT_FDCWD, path, nil, 0) - if err != ENOSYS { - return err - } - return utimes(path, nil) - } - if len(ts) != 2 { - return EINVAL - } - err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) - if err != ENOSYS { - return err - } - // If the utimensat syscall isn't available (utimensat was added to Linux - // in 2.6.22, Released, 8 July 2007) then fall back to utimes - var tv [2]Timeval - for i := 0; i < 2; i++ { - tv[i] = NsecToTimeval(TimespecToNsec(ts[i])) - } - return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) + return UtimesNanoAt(AT_FDCWD, path, ts, 0) } func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { @@ -238,7 +243,7 @@ func Futimesat(dirfd int, path string, tv []Timeval) error { func Futimes(fd int, tv []Timeval) (err error) { // Believe it or not, this is the best we can do on Linux // (and is what glibc does). - return Utimes("/proc/self/fd/"+itoa(fd), tv) + return Utimes("/proc/self/fd/"+strconv.Itoa(fd), tv) } const ImplementsGetwd = true @@ -255,6 +260,13 @@ func Getwd() (wd string, err error) { if n < 1 || n > len(buf) || buf[n-1] != 0 { return "", EINVAL } + // In some cases, Linux can return a path that starts with the + // "(unreachable)" prefix, which can potentially be a valid relative + // path. To work around that, return ENOENT if path is not absolute. + if buf[0] != '/' { + return "", ENOENT + } + return string(buf[0 : n-1]), nil } @@ -364,6 +376,8 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, return } +//sys Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) + func Mkfifo(path string, mode uint32) error { return Mknod(path, mode|S_IFIFO, 0) } @@ -380,9 +394,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -395,9 +407,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -408,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. @@ -416,7 +426,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -446,9 +457,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Hatype = sa.Hatype sa.raw.Pkttype = sa.Pkttype sa.raw.Halen = sa.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil } @@ -499,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)) @@ -514,24 +523,24 @@ func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) { // // Server example: // -// fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) -// _ = unix.Bind(fd, &unix.SockaddrRFCOMM{ -// Channel: 1, -// Addr: [6]uint8{0, 0, 0, 0, 0, 0}, // BDADDR_ANY or 00:00:00:00:00:00 -// }) -// _ = Listen(fd, 1) -// nfd, sa, _ := Accept(fd) -// fmt.Printf("conn addr=%v fd=%d", sa.(*unix.SockaddrRFCOMM).Addr, nfd) -// Read(nfd, buf) +// fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) +// _ = unix.Bind(fd, &unix.SockaddrRFCOMM{ +// Channel: 1, +// Addr: [6]uint8{0, 0, 0, 0, 0, 0}, // BDADDR_ANY or 00:00:00:00:00:00 +// }) +// _ = Listen(fd, 1) +// nfd, sa, _ := Accept(fd) +// fmt.Printf("conn addr=%v fd=%d", sa.(*unix.SockaddrRFCOMM).Addr, nfd) +// Read(nfd, buf) // // Client example: // -// fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) -// _ = Connect(fd, &SockaddrRFCOMM{ -// Channel: 1, -// Addr: [6]byte{0x11, 0x22, 0x33, 0xaa, 0xbb, 0xcc}, // CC:BB:AA:33:22:11 -// }) -// Write(fd, []byte(`hello`)) +// fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) +// _ = Connect(fd, &SockaddrRFCOMM{ +// Channel: 1, +// Addr: [6]byte{0x11, 0x22, 0x33, 0xaa, 0xbb, 0xcc}, // CC:BB:AA:33:22:11 +// }) +// Write(fd, []byte(`hello`)) type SockaddrRFCOMM struct { // Addr represents a bluetooth address, byte ordering is little-endian. Addr [6]uint8 @@ -558,12 +567,12 @@ func (sa *SockaddrRFCOMM) sockaddr() (unsafe.Pointer, _Socklen, error) { // The SockaddrCAN struct must be bound to the socket file descriptor // using Bind before the CAN socket can be used. // -// // Read one raw CAN frame -// fd, _ := Socket(AF_CAN, SOCK_RAW, CAN_RAW) -// addr := &SockaddrCAN{Ifindex: index} -// Bind(fd, addr) -// frame := make([]byte, 16) -// Read(fd, frame) +// // Read one raw CAN frame +// fd, _ := Socket(AF_CAN, SOCK_RAW, CAN_RAW) +// addr := &SockaddrCAN{Ifindex: index} +// Bind(fd, addr) +// frame := make([]byte, 16) +// Read(fd, frame) // // The full SocketCAN documentation can be found in the linux kernel // archives at: https://www.kernel.org/doc/Documentation/networking/can.txt @@ -581,16 +590,46 @@ 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 } +// SockaddrCANJ1939 implements the Sockaddr interface for AF_CAN using J1939 +// protocol (https://en.wikipedia.org/wiki/SAE_J1939). For more information +// on the purposes of the fields, check the official linux kernel documentation +// available here: https://www.kernel.org/doc/Documentation/networking/j1939.rst +type SockaddrCANJ1939 struct { + Ifindex int + Name uint64 + PGN uint32 + Addr uint8 + raw RawSockaddrCAN +} + +func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) { + if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { + return nil, 0, EINVAL + } + sa.raw.Family = AF_CAN + sa.raw.Ifindex = int32(sa.Ifindex) + n := (*[8]byte)(unsafe.Pointer(&sa.Name)) + for i := range 8 { + sa.raw.Addr[i] = n[i] + } + p := (*[4]byte)(unsafe.Pointer(&sa.PGN)) + for i := range 4 { + sa.raw.Addr[i+8] = p[i] + } + sa.raw.Addr[12] = sa.Addr + return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil +} + // SockaddrALG implements the Sockaddr interface for AF_ALG type sockets. // SockaddrALG enables userspace access to the Linux kernel's cryptography // subsystem. The Type and Name fields specify which type of hash or cipher @@ -604,13 +643,13 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) { // Here is an example of using an AF_ALG socket with SHA1 hashing. // The initial socket setup process is as follows: // -// // Open a socket to perform SHA1 hashing. -// fd, _ := unix.Socket(unix.AF_ALG, unix.SOCK_SEQPACKET, 0) -// addr := &unix.SockaddrALG{Type: "hash", Name: "sha1"} -// unix.Bind(fd, addr) -// // Note: unix.Accept does not work at this time; must invoke accept() -// // manually using unix.Syscall. -// hashfd, _, _ := unix.Syscall(unix.SYS_ACCEPT, uintptr(fd), 0, 0) +// // Open a socket to perform SHA1 hashing. +// fd, _ := unix.Socket(unix.AF_ALG, unix.SOCK_SEQPACKET, 0) +// addr := &unix.SockaddrALG{Type: "hash", Name: "sha1"} +// unix.Bind(fd, addr) +// // Note: unix.Accept does not work at this time; must invoke accept() +// // manually using unix.Syscall. +// hashfd, _, _ := unix.Syscall(unix.SYS_ACCEPT, uintptr(fd), 0, 0) // // Once a file descriptor has been returned from Accept, it may be used to // perform SHA1 hashing. The descriptor is not safe for concurrent use, but @@ -619,39 +658,39 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) { // When hashing a small byte slice or string, a single Write and Read may // be used: // -// // Assume hashfd is already configured using the setup process. -// hash := os.NewFile(hashfd, "sha1") -// // Hash an input string and read the results. Each Write discards -// // previous hash state. Read always reads the current state. -// b := make([]byte, 20) -// for i := 0; i < 2; i++ { -// io.WriteString(hash, "Hello, world.") -// hash.Read(b) -// fmt.Println(hex.EncodeToString(b)) -// } -// // Output: -// // 2ae01472317d1935a84797ec1983ae243fc6aa28 -// // 2ae01472317d1935a84797ec1983ae243fc6aa28 +// // Assume hashfd is already configured using the setup process. +// hash := os.NewFile(hashfd, "sha1") +// // Hash an input string and read the results. Each Write discards +// // previous hash state. Read always reads the current state. +// b := make([]byte, 20) +// for i := 0; i < 2; i++ { +// io.WriteString(hash, "Hello, world.") +// hash.Read(b) +// fmt.Println(hex.EncodeToString(b)) +// } +// // Output: +// // 2ae01472317d1935a84797ec1983ae243fc6aa28 +// // 2ae01472317d1935a84797ec1983ae243fc6aa28 // // For hashing larger byte slices, or byte streams such as those read from // a file or socket, use Sendto with MSG_MORE to instruct the kernel to update // the hash digest instead of creating a new one for a given chunk and finalizing it. // -// // Assume hashfd and addr are already configured using the setup process. -// hash := os.NewFile(hashfd, "sha1") -// // Hash the contents of a file. -// f, _ := os.Open("/tmp/linux-4.10-rc7.tar.xz") -// b := make([]byte, 4096) -// for { -// n, err := f.Read(b) -// if err == io.EOF { -// break -// } -// unix.Sendto(hashfd, b[:n], unix.MSG_MORE, addr) -// } -// hash.Read(b) -// fmt.Println(hex.EncodeToString(b)) -// // Output: 85cdcad0c06eef66f805ecce353bec9accbeecc5 +// // Assume hashfd and addr are already configured using the setup process. +// hash := os.NewFile(hashfd, "sha1") +// // Hash the contents of a file. +// f, _ := os.Open("/tmp/linux-4.10-rc7.tar.xz") +// b := make([]byte, 4096) +// for { +// n, err := f.Read(b) +// if err == io.EOF { +// break +// } +// unix.Sendto(hashfd, b[:n], unix.MSG_MORE, addr) +// } +// hash.Read(b) +// fmt.Println(hex.EncodeToString(b)) +// // Output: 85cdcad0c06eef66f805ecce353bec9accbeecc5 // // For more information, see: http://www.chronox.de/crypto-API/crypto/userspace-if.html. type SockaddrALG struct { @@ -664,10 +703,10 @@ type SockaddrALG struct { func (sa *SockaddrALG) sockaddr() (unsafe.Pointer, _Socklen, error) { // Leave room for NUL byte terminator. - if len(sa.Type) > 13 { + if len(sa.Type) > len(sa.raw.Type)-1 { return nil, 0, EINVAL } - if len(sa.Name) > 63 { + if len(sa.Name) > len(sa.raw.Name)-1 { return nil, 0, EINVAL } @@ -675,17 +714,8 @@ func (sa *SockaddrALG) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Feat = sa.Feature sa.raw.Mask = sa.Mask - typ, err := ByteSliceFromString(sa.Type) - if err != nil { - return nil, 0, err - } - name, err := ByteSliceFromString(sa.Name) - if err != nil { - return nil, 0, err - } - - copy(sa.raw.Type[:], typ) - copy(sa.raw.Name[:], name) + copy(sa.raw.Type[:], sa.Type) + copy(sa.raw.Name[:], sa.Name) return unsafe.Pointer(&sa.raw), SizeofSockaddrALG, nil } @@ -698,16 +728,19 @@ type SockaddrVM struct { // CID and Port specify a context ID and port address for a VM socket. // Guests have a unique CID, and hosts may have a well-known CID of: // - VMADDR_CID_HYPERVISOR: refers to the hypervisor process. + // - VMADDR_CID_LOCAL: refers to local communication (loopback). // - VMADDR_CID_HOST: refers to other processes on the host. - CID uint32 - Port uint32 - raw RawSockaddrVM + CID uint32 + Port uint32 + Flags uint8 + raw RawSockaddrVM } func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_VSOCK sa.raw.Port = sa.Port sa.raw.Cid = sa.CID + sa.raw.Flags = sa.Flags return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil } @@ -768,9 +801,7 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) { // one. The kernel expects SID to be in network byte order. binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID) copy(sa.raw[8:14], sa.Remote) - for i := 14; i < 14+IFNAMSIZ; i++ { - sa.raw[i] = 0 - } + clear(sa.raw[14 : 14+IFNAMSIZ]) copy(sa.raw[14:], sa.Dev) return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil } @@ -830,12 +861,10 @@ func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) { if sa.Addr == nil { return nil, 0, EINVAL } - sa.raw.Family = AF_TIPC sa.raw.Scope = int8(sa.Scope) sa.raw.Addrtype = sa.Addr.tipcAddrtype() sa.raw.Addr = sa.Addr.tipcAddr() - return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil } @@ -849,9 +878,7 @@ type SockaddrL2TPIP struct { func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_INET sa.raw.Conn_id = sa.ConnId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil } @@ -867,12 +894,83 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_INET6 sa.raw.Conn_id = sa.ConnId sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil } +// SockaddrIUCV implements the Sockaddr interface for AF_IUCV sockets. +type SockaddrIUCV struct { + UserID string + Name string + raw RawSockaddrIUCV +} + +func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Family = AF_IUCV + // 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 := range 8 { + sa.raw.Nodeid[i] = ' ' + sa.raw.User_id[i] = ' ' + sa.raw.Name[i] = ' ' + } + if len(sa.UserID) > 8 || len(sa.Name) > 8 { + return nil, 0, EINVAL + } + for i, b := range []byte(sa.UserID[:]) { + sa.raw.User_id[i] = int8(b) + } + for i, b := range []byte(sa.Name[:]) { + sa.raw.Name[i] = int8(b) + } + return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil +} + +type SockaddrNFC struct { + DeviceIdx uint32 + TargetIdx uint32 + NFCProtocol uint32 + raw RawSockaddrNFC +} + +func (sa *SockaddrNFC) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sa_family = AF_NFC + sa.raw.Dev_idx = sa.DeviceIdx + sa.raw.Target_idx = sa.TargetIdx + sa.raw.Nfc_protocol = sa.NFCProtocol + return unsafe.Pointer(&sa.raw), SizeofSockaddrNFC, nil +} + +type SockaddrNFCLLCP struct { + DeviceIdx uint32 + TargetIdx uint32 + NFCProtocol uint32 + DestinationSAP uint8 + SourceSAP uint8 + ServiceName string + raw RawSockaddrNFCLLCP +} + +func (sa *SockaddrNFCLLCP) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sa_family = AF_NFC + sa.raw.Dev_idx = sa.DeviceIdx + sa.raw.Target_idx = sa.TargetIdx + sa.raw.Nfc_protocol = sa.NFCProtocol + sa.raw.Dsap = sa.DestinationSAP + sa.raw.Ssap = sa.SourceSAP + if len(sa.ServiceName) > len(sa.raw.Service_name) { + return nil, 0, EINVAL + } + copy(sa.raw.Service_name[:], sa.ServiceName) + sa.raw.SetServiceNameLen(len(sa.ServiceName)) + return unsafe.Pointer(&sa.raw), SizeofSockaddrNFCLLCP, nil +} + +var socketProtocol = func(fd int) (int, error) { + return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) +} + func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_NETLINK: @@ -892,9 +990,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa.Hatype = pp.Hatype sa.Pkttype = pp.Pkttype sa.Halen = pp.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_UNIX: @@ -918,12 +1014,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { for n < len(pp.Path) && pp.Path[n] != 0 { n++ } - bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] - sa.Name = string(bytes) + sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) return sa, nil case AF_INET: - proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) + proto, err := socketProtocol(fd) if err != nil { return nil, err } @@ -933,23 +1028,19 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa)) sa := new(SockaddrL2TPIP) sa.ConnId = pp.Conn_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil default: pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } case AF_INET6: - proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) + proto, err := socketProtocol(fd) if err != nil { return nil, err } @@ -960,9 +1051,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrL2TPIP6) sa.ConnId = pp.Conn_id sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil default: pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) @@ -970,21 +1059,20 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } case AF_VSOCK: pp := (*RawSockaddrVM)(unsafe.Pointer(rsa)) sa := &SockaddrVM{ - CID: pp.Cid, - Port: pp.Port, + CID: pp.Cid, + Port: pp.Port, + Flags: pp.Flags, } return sa, nil case AF_BLUETOOTH: - proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) + proto, err := socketProtocol(fd) if err != nil { return nil, err } @@ -1053,6 +1141,92 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } return sa, nil + case AF_IUCV: + pp := (*RawSockaddrIUCV)(unsafe.Pointer(rsa)) + + var user [8]byte + var name [8]byte + + for i := range 8 { + user[i] = byte(pp.User_id[i]) + name[i] = byte(pp.Name[i]) + } + + sa := &SockaddrIUCV{ + UserID: string(user[:]), + Name: string(name[:]), + } + return sa, nil + + case AF_CAN: + proto, err := socketProtocol(fd) + if err != nil { + return nil, err + } + + pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa)) + + switch proto { + case CAN_J1939: + sa := &SockaddrCANJ1939{ + Ifindex: int(pp.Ifindex), + } + name := (*[8]byte)(unsafe.Pointer(&sa.Name)) + for i := range 8 { + name[i] = pp.Addr[i] + } + pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN)) + for i := range 4 { + pgn[i] = pp.Addr[i+8] + } + addr := (*[1]byte)(unsafe.Pointer(&sa.Addr)) + addr[0] = pp.Addr[12] + return sa, nil + default: + sa := &SockaddrCAN{ + Ifindex: int(pp.Ifindex), + } + rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) + for i := range 4 { + rx[i] = pp.Addr[i] + } + tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) + for i := range 4 { + tx[i] = pp.Addr[i+4] + } + return sa, nil + } + case AF_NFC: + proto, err := socketProtocol(fd) + if err != nil { + return nil, err + } + switch proto { + case NFC_SOCKPROTO_RAW: + pp := (*RawSockaddrNFC)(unsafe.Pointer(rsa)) + sa := &SockaddrNFC{ + DeviceIdx: pp.Dev_idx, + TargetIdx: pp.Target_idx, + NFCProtocol: pp.Nfc_protocol, + } + return sa, nil + case NFC_SOCKPROTO_LLCP: + pp := (*RawSockaddrNFCLLCP)(unsafe.Pointer(rsa)) + if uint64(pp.Service_name_len) > uint64(len(pp.Service_name)) { + return nil, EINVAL + } + sa := &SockaddrNFCLLCP{ + DeviceIdx: pp.Dev_idx, + TargetIdx: pp.Target_idx, + NFCProtocol: pp.Nfc_protocol, + DestinationSAP: pp.Dsap, + SourceSAP: pp.Ssap, + ServiceName: string(pp.Service_name[:pp.Service_name_len]), + } + return sa, nil + default: + return nil, EINVAL + } } return nil, EAFNOSUPPORT } @@ -1060,7 +1234,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { func Accept(fd int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny - nfd, err = accept(fd, &rsa, &len) + nfd, err = accept4(fd, &rsa, &len, 0) if err != nil { return } @@ -1120,6 +1294,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) { @@ -1135,7 +1351,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { return "", err } } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } func GetsockoptTpacketStats(fd, level, opt int) (*TpacketStats, error) { @@ -1182,6 +1398,17 @@ func SetsockoptTpacketReq3(fd, level, opt int, tp *TpacketReq3) error { return setsockopt(fd, level, opt, unsafe.Pointer(tp), unsafe.Sizeof(*tp)) } +func SetsockoptTCPRepairOpt(fd, level, opt int, o []TCPRepairOpt) (err error) { + if len(o) == 0 { + return EINVAL + } + return setsockopt(fd, level, opt, unsafe.Pointer(&o[0]), uintptr(SizeofTCPRepairOpt*len(o))) +} + +func SetsockoptTCPMD5Sig(fd, level, opt int, s *TCPMD5Sig) error { + return setsockopt(fd, level, opt, unsafe.Pointer(s), unsafe.Sizeof(*s)) +} + // Keyctl Commands (http://man7.org/linux/man-pages/man2/keyctl.2.html) // KeyctlInt calls keyctl commands in which each argument is an int. @@ -1314,22 +1541,16 @@ func KeyctlRestrictKeyring(ringid int, keyType string, restriction string) error return keyctlRestrictKeyringByType(KEYCTL_RESTRICT_KEYRING, ringid, keyType, restriction) } -//sys keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL -//sys keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL +//sys keyctlRestrictKeyringByType(cmd int, arg2 int, keyType string, restriction string) (err error) = SYS_KEYCTL +//sys keyctlRestrictKeyring(cmd int, arg2 int) (err error) = SYS_KEYCTL -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) - var iov Iovec - if len(p) > 0 { - iov.Base = &p[0] - iov.SetLen(len(p)) - } var dummy byte if len(oob) > 0 { - if len(p) == 0 { + if emptyIovecs(iov) { var sockType int sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) if err != nil { @@ -1337,53 +1558,36 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } // receive at least one normal byte if sockType != SOCK_DGRAM { - iov.Base = &dummy - iov.SetLen(1) + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] } } msg.Control = &oob[0] msg.SetControllen(len(oob)) } - msg.Iov = &iov - msg.Iovlen = 1 + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } if n, err = recvmsg(fd, &msg, flags); err != nil { return } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(fd, &rsa) - } return } -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - var err error - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(ptr) msg.Namelen = uint32(salen) - var iov Iovec - if len(p) > 0 { - iov.Base = &p[0] - iov.SetLen(len(p)) - } var dummy byte + var empty bool if len(oob) > 0 { - if len(p) == 0 { + empty = emptyIovecs(iov) + if empty { var sockType int sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) if err != nil { @@ -1391,19 +1595,23 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) } // send at least one normal byte if sockType != SOCK_DGRAM { - iov.Base = &dummy - iov.SetLen(1) + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] } } msg.Control = &oob[0] msg.SetControllen(len(oob)) } - msg.Iov = &iov - msg.Iovlen = 1 + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } if n, err = sendmsg(fd, &msg, flags); err != nil { return 0, err } - if len(oob) > 0 && len(p) == 0 { + if len(oob) > 0 && empty { n = 0 } return n, nil @@ -1415,6 +1623,7 @@ func BindToDevice(fd int, device string) (err error) { } //sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) +//sys ptracePtr(request int, pid int, addr uintptr, data unsafe.Pointer) (err error) = SYS_PTRACE func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) { // The peek requests are machine-size oriented, so we wrap it @@ -1432,7 +1641,7 @@ func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err erro // boundary. n := 0 if addr%SizeofPtr != 0 { - err = ptrace(req, pid, addr-addr%SizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) + err = ptracePtr(req, pid, addr-addr%SizeofPtr, unsafe.Pointer(&buf[0])) if err != nil { return 0, err } @@ -1444,7 +1653,7 @@ func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err erro for len(out) > 0 { // We use an internal buffer to guarantee alignment. // It's not documented if this is necessary, but we're paranoid. - err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) + err = ptracePtr(req, pid, addr+uintptr(n), unsafe.Pointer(&buf[0])) if err != nil { return n, err } @@ -1476,7 +1685,7 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c n := 0 if addr%SizeofPtr != 0 { var buf [SizeofPtr]byte - err = ptrace(peekReq, pid, addr-addr%SizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) + err = ptracePtr(peekReq, pid, addr-addr%SizeofPtr, unsafe.Pointer(&buf[0])) if err != nil { return 0, err } @@ -1503,7 +1712,7 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c // Trailing edge. if len(data) > 0 { var buf [SizeofPtr]byte - err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) + err = ptracePtr(peekReq, pid, addr+uintptr(n), unsafe.Pointer(&buf[0])) if err != nil { return n, err } @@ -1531,12 +1740,23 @@ func PtracePokeUser(pid int, addr uintptr, data []byte) (count int, err error) { return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, pid, addr, data) } +// elfNT_PRSTATUS is a copy of the debug/elf.NT_PRSTATUS constant so +// x/sys/unix doesn't need to depend on debug/elf and thus +// compress/zlib, debug/dwarf, and other packages. +const elfNT_PRSTATUS = 1 + func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + var iov Iovec + iov.Base = (*byte)(unsafe.Pointer(regsout)) + iov.SetLen(int(unsafe.Sizeof(*regsout))) + return ptracePtr(PTRACE_GETREGSET, pid, uintptr(elfNT_PRSTATUS), unsafe.Pointer(&iov)) } func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + var iov Iovec + iov.Base = (*byte)(unsafe.Pointer(regs)) + iov.SetLen(int(unsafe.Sizeof(*regs))) + return ptracePtr(PTRACE_SETREGSET, pid, uintptr(elfNT_PRSTATUS), unsafe.Pointer(&iov)) } func PtraceSetOptions(pid int, options int) (err error) { @@ -1545,7 +1765,7 @@ func PtraceSetOptions(pid int, options int) (err error) { func PtraceGetEventMsg(pid int) (msg uint, err error) { var data _C_long - err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data))) + err = ptracePtr(PTRACE_GETEVENTMSG, pid, 0, unsafe.Pointer(&data)) msg = uint(data) return } @@ -1605,6 +1825,16 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri return mount(source, target, fstype, flags, datap) } +//sys mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR + +// MountSetattr is a wrapper for mount_setattr(2). +// https://man7.org/linux/man-pages/man2/mount_setattr.2.html +// +// Requires kernel >= 5.12. +func MountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr) error { + return mountSetattr(dirfd, pathname, flags, attr, unsafe.Sizeof(*attr)) +} + func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) @@ -1626,13 +1856,21 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error) //sys Chdir(path string) (err error) //sys Chroot(path string) (err error) +//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) //sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) //sys DeleteModule(name string, flags int) (err error) //sys Dup(oldfd int) (fd int, err error) + +func Dup2(oldfd, newfd int) error { + return Dup3(oldfd, newfd, 0) +} + //sys Dup3(oldfd int, newfd int, flags int) (err error) //sysnb EpollCreate1(flag int) (fd int, err error) //sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) @@ -1650,6 +1888,108 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Fremovexattr(fd int, attr string) (err error) //sys Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) //sys Fsync(fd int) (err error) +//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error) +//sys Fsopen(fsName string, flags int) (fd int, err error) +//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error) + +//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) + +func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) { + var keyp *byte + if keyp, err = BytePtrFromString(key); err != nil { + return + } + return fsconfig(fd, cmd, keyp, value, aux) +} + +// FsconfigSetFlag is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_FLAG. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +func FsconfigSetFlag(fd int, key string) (err error) { + return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0) +} + +// FsconfigSetString is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_STRING. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// value is the parameter value to set. +func FsconfigSetString(fd int, key string, value string) (err error) { + var valuep *byte + if valuep, err = BytePtrFromString(value); err != nil { + return + } + return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0) +} + +// FsconfigSetBinary is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_BINARY. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// value is the parameter value to set. +func FsconfigSetBinary(fd int, key string, value []byte) (err error) { + if len(value) == 0 { + return EINVAL + } + return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value)) +} + +// FsconfigSetPath is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_PATH. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// path is a non-empty path for specified key. +// atfd is a file descriptor at which to start lookup from or AT_FDCWD. +func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) { + var valuep *byte + if valuep, err = BytePtrFromString(path); err != nil { + return + } + return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd) +} + +// FsconfigSetPathEmpty is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as +// FconfigSetPath but with AT_PATH_EMPTY implied. +func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) { + var valuep *byte + if valuep, err = BytePtrFromString(path); err != nil { + return + } + return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd) +} + +// FsconfigSetFd is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_FD. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// value is a file descriptor to be assigned to specified key. +func FsconfigSetFd(fd int, key string, value int) (err error) { + return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value) +} + +// FsconfigCreate is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_CMD_CREATE. +// +// fd is the filesystem context to act upon. +func FsconfigCreate(fd int) (err error) { + return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0) +} + +// FsconfigReconfigure is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_CMD_RECONFIGURE. +// +// fd is the filesystem context to act upon. +func FsconfigReconfigure(fd int) (err error) { + return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0) +} + //sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 //sysnb Getpgid(pid int) (pgid int, err error) @@ -1661,7 +2001,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) @@ -1680,12 +2039,13 @@ func Getpgrp() (pid int) { //sys MemfdCreate(name string, flags int) (fd int, err error) //sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) +//sys MoveMount(fromDirfd int, fromPathName string, toDirfd int, toPathName string, flags int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) +//sys OpenTree(dfd int, fileName string, flags uint) (r int, err error) //sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT -//sysnb prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 -//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) -//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6 +//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) +//sys pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Removexattr(path string, attr string) (err error) //sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) @@ -1697,6 +2057,15 @@ func Getpgrp() (pid int) { //sysnb Settimeofday(tv *Timeval) (err error) //sys Setns(fd int, nstype int) (err error) +//go:linkname syscall_prlimit syscall.prlimit +func syscall_prlimit(pid, resource int, newlimit, old *syscall.Rlimit) error + +func Prlimit(pid, resource int, newlimit, old *Rlimit) error { + // Just call the syscall version, because as of Go 1.21 + // it will affect starting a new process. + return syscall_prlimit(pid, resource, (*syscall.Rlimit)(newlimit), (*syscall.Rlimit)(old)) +} + // PrctlRetInt performs a prctl operation specified by option and further // optional arguments arg2 through arg5 depending on option. It returns a // non-negative integer that is returned by the prctl syscall. @@ -1708,17 +2077,28 @@ func PrctlRetInt(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uint return int(ret), nil } -// issue 1435. -// On linux Setuid and Setgid only affects the current thread, not the process. -// This does not match what most callers expect so we must return an error -// here rather than letting the caller think that the call succeeded. - func Setuid(uid int) (err error) { - return EOPNOTSUPP + return syscall.Setuid(uid) +} + +func Setgid(gid int) (err error) { + return syscall.Setgid(gid) } -func Setgid(uid int) (err error) { - return EOPNOTSUPP +func Setreuid(ruid, euid int) (err error) { + return syscall.Setreuid(ruid, euid) +} + +func Setregid(rgid, egid int) (err error) { + return syscall.Setregid(rgid, egid) +} + +func Setresuid(ruid, euid, suid int) (err error) { + return syscall.Setresuid(ruid, euid, suid) +} + +func Setresgid(rgid, egid, sgid int) (err error) { + return syscall.Setresgid(rgid, egid, sgid) } // SetfsgidRetGid sets fsgid for current thread and returns previous fsgid set. @@ -1757,6 +2137,9 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) { //sys Syncfs(fd int) (err error) //sysnb Sysinfo(info *Sysinfo_t) (err error) //sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) +//sysnb TimerfdCreate(clockid int, flags int) (fd int, err error) +//sysnb TimerfdGettime(fd int, currValue *ItimerSpec) (err error) +//sysnb TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error) //sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error) //sysnb Times(tms *Tms) (ticks uintptr, err error) //sysnb Umask(mask int) (oldmask int) @@ -1765,8 +2148,6 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) { //sys Unshare(flags int) (err error) //sys write(fd int, p []byte) (n int, err error) //sys exitThread(code int) (err error) = SYS_EXIT -//sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ -//sys writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE //sys readv(fd int, iovs []Iovec) (n int, err error) = SYS_READV //sys writev(fd int, iovs []Iovec) (n int, err error) = SYS_WRITEV //sys preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV @@ -1774,36 +2155,46 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) { //sys preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2 //sys pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2 -func bytes2iovec(bs [][]byte) []Iovec { - iovecs := make([]Iovec, len(bs)) - for i, b := range bs { - iovecs[i].SetLen(len(b)) +// minIovec is the size of the small initial allocation used by +// Readv, Writev, etc. +// +// This small allocation gets stack allocated, which lets the +// common use case of len(iovs) <= minIovs avoid more expensive +// heap allocations. +const minIovec = 8 + +// appendBytes converts bs to Iovecs and appends them to vecs. +func appendBytes(vecs []Iovec, bs [][]byte) []Iovec { + for _, b := range bs { + var v Iovec + v.SetLen(len(b)) if len(b) > 0 { - iovecs[i].Base = &b[0] + v.Base = &b[0] } else { - iovecs[i].Base = (*byte)(unsafe.Pointer(&_zero)) + v.Base = (*byte)(unsafe.Pointer(&_zero)) } + vecs = append(vecs, v) } - return iovecs + return vecs } -// offs2lohi splits offs into its lower and upper unsigned long. On 64-bit -// systems, hi will always be 0. On 32-bit systems, offs will be split in half. -// preadv/pwritev chose this calling convention so they don't need to add a -// padding-register for alignment on ARM. +// offs2lohi splits offs into its low and high order bits. func offs2lohi(offs int64) (lo, hi uintptr) { - return uintptr(offs), uintptr(uint64(offs) >> SizeofLong) + const longBits = SizeofLong * 8 + return uintptr(offs), uintptr(uint64(offs) >> (longBits - 1) >> 1) // two shifts to avoid false positive in vet } func Readv(fd int, iovs [][]byte) (n int, err error) { - iovecs := bytes2iovec(iovs) + 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) { - iovecs := bytes2iovec(iovs) + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) lo, hi := offs2lohi(offset) n, err = preadv(fd, iovecs, lo, hi) readvRacedetect(iovecs, n, err) @@ -1811,7 +2202,8 @@ func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Preadv2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) { - iovecs := bytes2iovec(iovs) + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) lo, hi := offs2lohi(offset) n, err = preadv2(fd, iovecs, lo, hi, flags) readvRacedetect(iovecs, n, err) @@ -1823,10 +2215,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) @@ -1838,7 +2227,8 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { } func Writev(fd int, iovs [][]byte) (n int, err error) { - iovecs := bytes2iovec(iovs) + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) } @@ -1848,7 +2238,8 @@ func Writev(fd int, iovs [][]byte) (n int, err error) { } func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - iovecs := bytes2iovec(iovs) + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) } @@ -1859,7 +2250,8 @@ func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { } func Pwritev2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) { - iovecs := bytes2iovec(iovs) + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) } @@ -1874,10 +2266,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) @@ -1887,21 +2276,7 @@ func writevRacedetect(iovecs []Iovec, n int) { // mmap varies by architecture; see syscall_linux_*.go. //sys munmap(addr uintptr, length uintptr) (err error) - -var mapper = &mmapper{ - active: make(map[*byte][]byte), - mmap: mmap, - munmap: munmap, -} - -func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { - return mapper.Mmap(fd, offset, length, prot, flags) -} - -func Munmap(b []byte) (err error) { - return mapper.Munmap(b) -} - +//sys mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) //sys Madvise(b []byte, advice int) (err error) //sys Mprotect(b []byte, prot int) (err error) //sys Mlock(b []byte) (err error) @@ -1910,6 +2285,12 @@ func Munmap(b []byte) (err error) { //sys Munlock(b []byte) (err error) //sys Munlockall() (err error) +const ( + mremapFixed = MREMAP_FIXED + mremapDontunmap = MREMAP_DONTUNMAP + mremapMaymove = MREMAP_MAYMOVE +) + // Vmsplice splices user pages from a slice of Iovecs into a pipe specified by fd, // using the specified flags. func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) { @@ -1926,11 +2307,33 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) { return int(n), nil } +func isGroupMember(gid int) bool { + groups, err := Getgroups() + if err != nil { + return false + } + + return slices.Contains(groups, gid) +} + +func isCapDacOverrideSet() bool { + hdr := CapUserHeader{Version: LINUX_CAPABILITY_VERSION_3} + data := [2]CapUserData{} + err := Capget(&hdr, &data[0]) + + return err == nil && data[0].Effective&(1<> 3) & 7 } else { fmode = st.Mode & 7 @@ -1997,8 +2406,8 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { return EACCES } -//sys nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) = SYS_NAME_TO_HANDLE_AT -//sys openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error) = SYS_OPEN_BY_HANDLE_AT +//sys nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) = SYS_NAME_TO_HANDLE_AT +//sys openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error) = SYS_OPEN_BY_HANDLE_AT // fileHandle is the argument to nameToHandleAt and openByHandleAt. We // originally tried to generate it via unix/linux/types.go with "type @@ -2035,7 +2444,7 @@ func (fh *FileHandle) Bytes() []byte { if n == 0 { return nil } - return (*[1 << 30]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&fh.fileHandle.Type)) + 4))[:n:n] + return unsafe.Slice((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&fh.fileHandle.Type))+4)), n) } // NameToHandleAt wraps the name_to_handle_at system call; it obtains @@ -2084,108 +2493,159 @@ func Klogset(typ int, arg int) (err error) { return nil } -/* - * Unimplemented - */ -// AfsSyscall -// Alarm -// ArchPrctl -// Brk -// ClockNanosleep -// ClockSettime -// Clone -// EpollCtlOld -// EpollPwait -// EpollWaitOld -// Execve -// Fork -// Futex -// GetKernelSyms -// GetMempolicy -// GetRobustList -// GetThreadArea -// Getitimer -// Getpmsg -// IoCancel -// IoDestroy -// IoGetevents -// IoSetup -// IoSubmit -// IoprioGet -// IoprioSet -// KexecLoad -// LookupDcookie -// Mbind -// MigratePages -// Mincore -// ModifyLdt -// Mount -// MovePages -// MqGetsetattr -// MqNotify -// MqOpen -// MqTimedreceive -// MqTimedsend -// MqUnlink -// Mremap -// Msgctl -// Msgget -// Msgrcv -// Msgsnd -// Nfsservctl -// Personality -// Pselect6 -// Ptrace -// Putpmsg -// Quotactl -// Readahead -// Readv -// RemapFilePages -// RestartSyscall -// RtSigaction -// RtSigpending -// RtSigprocmask -// RtSigqueueinfo -// RtSigreturn -// RtSigsuspend -// RtSigtimedwait -// SchedGetPriorityMax -// SchedGetPriorityMin -// SchedGetparam -// SchedGetscheduler -// SchedRrGetInterval -// SchedSetparam -// SchedYield -// Security -// Semctl -// Semget -// Semop -// Semtimedop -// SetMempolicy -// SetRobustList -// SetThreadArea -// SetTidAddress -// Shmat -// Shmctl -// Shmdt -// Shmget -// Sigaltstack -// Swapoff -// Swapon -// Sysfs -// TimerCreate -// TimerDelete -// TimerGetoverrun -// TimerGettime -// TimerSettime -// Timerfd -// Tkill (obsolete) -// Tuxcall -// Umount2 -// Uselib -// Utimensat -// Vfork -// Vhangup -// Vserver -// Waitid -// _Sysctl +// RemoteIovec is Iovec with the pointer replaced with an integer. +// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer +// refers to a location in a different process' address space, which +// would confuse the Go garbage collector. +type RemoteIovec struct { + Base uintptr + Len int +} + +//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV +//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV + +//sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN +//sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD +//sys PidfdSendSignal(pidfd int, sig Signal, info *Siginfo, flags int) (err error) = SYS_PIDFD_SEND_SIGNAL + +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) +//sys shmdt(addr uintptr) (err error) +//sys shmget(key int, size int, flag int) (id int, err error) + +//sys getitimer(which int, currValue *Itimerval) (err error) +//sys setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error) + +// MakeItimerval creates an Itimerval from interval and value durations. +func MakeItimerval(interval, value time.Duration) Itimerval { + return Itimerval{ + Interval: NsecToTimeval(interval.Nanoseconds()), + Value: NsecToTimeval(value.Nanoseconds()), + } +} + +// A value which may be passed to the which parameter for Getitimer and +// Setitimer. +type ItimerWhich int + +// Possible which values for Getitimer and Setitimer. +const ( + ItimerReal ItimerWhich = ITIMER_REAL + ItimerVirtual ItimerWhich = ITIMER_VIRTUAL + ItimerProf ItimerWhich = ITIMER_PROF +) + +// Getitimer wraps getitimer(2) to return the current value of the timer +// specified by which. +func Getitimer(which ItimerWhich) (Itimerval, error) { + var it Itimerval + if err := getitimer(int(which), &it); err != nil { + return Itimerval{}, err + } + + return it, nil +} + +// Setitimer wraps setitimer(2) to arm or disarm the timer specified by which. +// It returns the previous value of the timer. +// +// If the Itimerval argument is the zero value, the timer will be disarmed. +func Setitimer(which ItimerWhich, it Itimerval) (Itimerval, error) { + var prev Itimerval + if err := setitimer(int(which), &it, &prev); err != nil { + return Itimerval{}, err + } + + return prev, nil +} + +//sysnb rtSigprocmask(how int, set *Sigset_t, oldset *Sigset_t, sigsetsize uintptr) (err error) = SYS_RT_SIGPROCMASK + +func PthreadSigmask(how int, set, oldset *Sigset_t) error { + if oldset != nil { + // Explicitly clear in case Sigset_t is larger than _C__NSIG. + *oldset = Sigset_t{} + } + return rtSigprocmask(how, set, oldset, _C__NSIG/8) +} + +//sysnb getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) +//sysnb getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) + +func Getresuid() (ruid, euid, suid int) { + var r, e, s _C_int + getresuid(&r, &e, &s) + return int(r), int(e), int(s) +} + +func Getresgid() (rgid, egid, sgid int) { + var r, e, s _C_int + getresgid(&r, &e, &s) + return int(r), int(e), int(s) +} + +// Pselect is a wrapper around the Linux pselect6 system call. +// This version does not modify the timeout argument. +func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + // Per https://man7.org/linux/man-pages/man2/select.2.html#NOTES, + // The Linux pselect6() system call modifies its timeout argument. + // [Not modifying the argument] is the behavior required by POSIX.1-2001. + var mutableTimeout *Timespec + if timeout != nil { + mutableTimeout = new(Timespec) + *mutableTimeout = *timeout + } + + // The final argument of the pselect6() system call is not a + // sigset_t * pointer, but is instead a structure + var kernelMask *sigset_argpack + if sigmask != nil { + wordBits := 32 << (^uintptr(0) >> 63) // see math.intSize + + // A sigset stores one bit per signal, + // offset by 1 (because signal 0 does not exist). + // So the number of words needed is ⌈__C_NSIG - 1 / wordBits⌉. + sigsetWords := (_C__NSIG - 1 + wordBits - 1) / (wordBits) + + sigsetBytes := uintptr(sigsetWords * (wordBits / 8)) + kernelMask = &sigset_argpack{ + ss: sigmask, + ssLen: sigsetBytes, + } + } + + return pselect6(nfd, r, w, e, mutableTimeout, kernelMask) +} + +//sys schedSetattr(pid int, attr *SchedAttr, flags uint) (err error) +//sys schedGetattr(pid int, attr *SchedAttr, size uint, flags uint) (err error) + +// SchedSetAttr is a wrapper for sched_setattr(2) syscall. +// https://man7.org/linux/man-pages/man2/sched_setattr.2.html +func SchedSetAttr(pid int, attr *SchedAttr, flags uint) error { + if attr == nil { + return EINVAL + } + attr.Size = SizeofSchedAttr + return schedSetattr(pid, attr, flags) +} + +// SchedGetAttr is a wrapper for sched_getattr(2) syscall. +// https://man7.org/linux/man-pages/man2/sched_getattr.2.html +func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { + attr := &SchedAttr{} + if err := schedGetattr(pid, attr, SizeofSchedAttr, flags); err != nil { + return nil, err + } + return attr, nil +} + +//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) +//sys Mseal(b []byte, flags uint) (err error) + +//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY + +func SetMemPolicy(mode int, mask *CPUSet) error { + return setMemPolicy(mode, mask, _CPU_SETSIZE) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index a8374b6..506dafa 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP) -// so that go vet can check that they are correct. - -// +build 386,linux +//go:build 386 && linux package unix @@ -21,36 +18,8 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // 64-bit file system and 32-bit uid calls // (386 default is 32-bit file system and 16-bit uid). -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64 //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 @@ -61,21 +30,16 @@ func Pipe2(p []int, flags int) (err error) { //sysnb Geteuid() (euid int) = SYS_GETEUID32 //sysnb Getgid() (gid int) = SYS_GETGID32 //sysnb Getuid() (uid int) = SYS_GETUID32 -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 //sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32 //sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32 -//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32 -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32 -//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32 -//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32 //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) @@ -101,13 +65,13 @@ type rlimit32 struct { Max uint32 } -//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT +//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT const rlimInf32 = ^uint32(0) const rlimInf64 = ^uint64(0) func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -132,33 +96,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { return } -//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) - if err != ENOSYS { - return err - } - - rl := rlimit32{} - if rlim.Cur == rlimInf64 { - rl.Cur = rlimInf32 - } else if rlim.Cur < uint64(rlimInf32) { - rl.Cur = uint32(rlim.Cur) - } else { - return EINVAL - } - if rlim.Max == rlimInf64 { - rl.Max = rlimInf32 - } else if rlim.Max < uint64(rlimInf32) { - rl.Max = uint32(rlim.Max) - } else { - return EINVAL - } - - return setrlimit(resource, &rl) -} - func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { newoffset, errno := seek(fd, offset, whence) if errno != 0 { @@ -204,14 +141,6 @@ const ( _SENDMMSG = 20 ) -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - fd, e := socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) - if e != 0 { - err = e - } - return -} - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { fd, e := socketcall(_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) if e != 0 { @@ -380,11 +309,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go b/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go new file mode 100644 index 0000000..38d5564 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go @@ -0,0 +1,12 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && (386 || amd64 || mips || mipsle || mips64 || mipsle || ppc64 || ppc64le || ppc || s390x || sparc64) + +package unix + +// SYS_ALARM is not defined on arm or riscv, but is available for other GOARCH +// values. + +//sys Alarm(seconds uint) (remaining uint, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 8ed1d54..d557cf8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,linux +//go:build amd64 && linux package unix -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -20,17 +18,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb inotifyInit() (fd int, err error) - -func InotifyInit() (fd int, err error) { - // First try inotify_init1, because Android's seccomp policy blocks the latter. - fd, err = InotifyInit1(0) - if err == ENOSYS { - fd, err = inotifyInit() - } - return -} - //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -40,9 +27,10 @@ func Lstat(path string, stat *Stat_t) (err error) { return Fstatat(AT_FDCWD, path, stat, AT_SYMLINK_NOFOLLOW) } +//sys MemfdSecret(flags int) (fd int, err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK @@ -51,17 +39,12 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err if timeout != nil { ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} } - return Pselect(nfd, r, w, e, ts, nil) + return pselect6(nfd, r, w, e, ts, nil) } //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) @@ -74,7 +57,6 @@ func Stat(path string, stat *Stat_t) (err error) { //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -125,32 +107,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Rip } func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc } @@ -171,13 +127,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go index 21a4946..facdb83 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,linux -// +build !gccgo +//go:build amd64 && linux && gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index 99ae613..cd2dd79 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm,linux +//go:build arm && linux package unix import ( - "syscall" "unsafe" ) @@ -19,40 +18,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - // Try pipe2 first for Android O, then try pipe for kernel 2.6.23. - err = pipe2(&pp, 0) - if err == ENOSYS { - err = pipe(&pp) - } - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -// Underlying system call writes to newoffset via pointer. -// Implemented in assembly to avoid allocation. -func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno) - func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { newoffset, errno := seek(fd, offset, whence) if errno != 0 { @@ -61,7 +26,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return newoffset, nil } -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -80,8 +44,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // 64-bit file system and 32-bit uid calls // (16-bit uid calls are not always supported in newer kernels) -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 @@ -90,7 +52,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { //sysnb Geteuid() (euid int) = SYS_GETEUID32 //sysnb Getgid() (gid int) = SYS_GETGID32 //sysnb Getuid() (uid int) = SYS_GETUID32 -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 @@ -100,10 +61,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32 //sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32 -//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32 -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32 -//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32 -//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32 //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 @@ -134,8 +91,8 @@ func Utime(path string, buf *Utimbuf) error { //sys utimes(path string, times *[2]Timeval) (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 //sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64 @@ -182,13 +139,13 @@ type rlimit32 struct { Max uint32 } -//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_UGETRLIMIT +//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_UGETRLIMIT const rlimInf32 = ^uint32(0) const rlimInf64 = ^uint64(0) func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -213,33 +170,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { return } -//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) - if err != ENOSYS { - return err - } - - rl := rlimit32{} - if rlim.Cur == rlimInf64 { - rl.Cur = rlimInf32 - } else if rlim.Cur < uint64(rlimInf32) { - rl.Cur = uint32(rlim.Cur) - } else { - return EINVAL - } - if rlim.Max == rlimInf64 { - rl.Max = rlimInf32 - } else if rlim.Max < uint64(rlimInf32) { - rl.Max = uint32(rlim.Max) - } else { - return EINVAL - } - - return setrlimit(resource, &rl) -} - func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) } func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) } @@ -260,13 +190,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } //sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 807a0b2..745e5c7 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -2,19 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64,linux +//go:build arm64 && linux package unix import "unsafe" -func EpollCreate(size int) (fd int, err error) { - if size <= 0 { - return -1, EINVAL - } - return EpollCreate1(0) -} - //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -25,11 +18,12 @@ func EpollCreate(size int) (fd int, err error) { //sysnb Getegid() (egid int) //sysnb Geteuid() (euid int) //sysnb Getgid() (gid int) -//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) +//sysnb getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) //sys Listen(s int, n int) (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys MemfdSecret(flags int) (fd int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK @@ -38,17 +32,12 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err if timeout != nil { ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} } - return Pselect(nfd, r, w, e, ts, nil) + return pselect6(nfd, r, w, e, ts, nil) } //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) @@ -72,7 +61,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { return ENOSYS } -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -144,28 +132,13 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL +// Getrlimit prefers the prlimit64 system call. See issue 38604. +func Getrlimit(resource int, rlim *Rlimit) error { + err := Prlimit(0, resource, nil, rlim) + if err != ENOSYS { + return err } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return + return getrlimit(resource, rlim) } func (r *PtraceRegs) PC() uint64 { return r.Pc } @@ -188,12 +161,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -func Dup2(oldfd int, newfd int) (err error) { - return Dup3(oldfd, newfd, 0) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } func Pause() error { @@ -201,18 +170,6 @@ func Pause() error { return err } -func Poll(fds []PollFd, timeout int) (n int, err error) { - var ts *Timespec - if timeout >= 0 { - ts = new(Timespec) - *ts = NsecToTimespec(int64(timeout) * 1e6) - } - if len(fds) == 0 { - return ppoll(nil, 0, ts, nil) - } - return ppoll(&fds[0], len(fds), ts, nil) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { @@ -225,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 diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc.go index c26e6ec..ffc4c2b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,!gccgo +//go:build linux && gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go index 070bd38..9ebfdcf 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,!gccgo,386 +//go:build linux && gc && 386 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go new file mode 100644 index 0000000..5f2b57c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go @@ -0,0 +1,13 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm && gc && linux + +package unix + +import "syscall" + +// Underlying system call writes to newoffset via pointer. +// Implemented in assembly to avoid allocation. +func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go index 308eb7a..d1a3ad8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,gccgo,386 +//go:build linux && gccgo && 386 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go index aa7fc9e..f2f6742 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,gccgo,arm +//go:build linux && gccgo && arm package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go new file mode 100644 index 0000000..dd2262a --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go @@ -0,0 +1,218 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build loong64 && linux + +package unix + +import "unsafe" + +//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 +//sys Fchown(fd int, uid int, gid int) (err error) +//sys Fstatfs(fd int, buf *Statfs_t) (err error) +//sys Ftruncate(fd int, length int64) (err error) +//sysnb Getegid() (egid int) +//sysnb Geteuid() (euid int) +//sysnb Getgid() (gid int) +//sysnb Getuid() (uid int) +//sys Listen(s int, n int) (err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK + +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + var ts *Timespec + if timeout != nil { + ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} + } + return pselect6(nfd, r, w, e, ts, nil) +} + +//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) +//sys setfsgid(gid int) (prev int, err error) +//sys setfsuid(uid int) (prev int, err error) +//sys Shutdown(fd int, how int) (err error) +//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) + +func timespecFromStatxTimestamp(x StatxTimestamp) Timespec { + return Timespec{ + Sec: x.Sec, + Nsec: int64(x.Nsec), + } +} + +func Fstatat(fd int, path string, stat *Stat_t, flags int) error { + var r Statx_t + // Do it the glibc way, add AT_NO_AUTOMOUNT. + if err := Statx(fd, path, AT_NO_AUTOMOUNT|flags, STATX_BASIC_STATS, &r); err != nil { + return err + } + + stat.Dev = Mkdev(r.Dev_major, r.Dev_minor) + stat.Ino = r.Ino + stat.Mode = uint32(r.Mode) + stat.Nlink = r.Nlink + stat.Uid = r.Uid + stat.Gid = r.Gid + stat.Rdev = Mkdev(r.Rdev_major, r.Rdev_minor) + // hope we don't get to process files so large to overflow these size + // fields... + stat.Size = int64(r.Size) + stat.Blksize = int32(r.Blksize) + stat.Blocks = int64(r.Blocks) + stat.Atim = timespecFromStatxTimestamp(r.Atime) + stat.Mtim = timespecFromStatxTimestamp(r.Mtime) + stat.Ctim = timespecFromStatxTimestamp(r.Ctime) + + return nil +} + +func Fstat(fd int, stat *Stat_t) (err error) { + return Fstatat(fd, "", stat, AT_EMPTY_PATH) +} + +func Stat(path string, stat *Stat_t) (err error) { + return Fstatat(AT_FDCWD, path, stat, 0) +} + +func Lchown(path string, uid int, gid int) (err error) { + return Fchownat(AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW) +} + +func Lstat(path string, stat *Stat_t) (err error) { + return Fstatat(AT_FDCWD, path, stat, AT_SYMLINK_NOFOLLOW) +} + +//sys Statfs(path string, buf *Statfs_t) (err error) +//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) +//sys Truncate(path string, length int64) (err error) + +func Ustat(dev int, ubuf *Ustat_t) (err error) { + return ENOSYS +} + +//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) +//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) +//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) +//sysnb getgroups(n int, list *_Gid_t) (nn int, err error) +//sysnb setgroups(n int, list *_Gid_t) (err error) +//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) +//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) +//sysnb socket(domain int, typ int, proto int) (fd int, err error) +//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) +//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) +//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) +//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) +//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) +//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) +//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) +//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) + +//sysnb Gettimeofday(tv *Timeval) (err error) + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: sec, Usec: usec} +} + +func Getrlimit(resource int, rlim *Rlimit) (err error) { + err = Prlimit(0, resource, nil, rlim) + return +} + +func futimesat(dirfd int, path string, tv *[2]Timeval) (err error) { + if tv == nil { + return utimensat(dirfd, path, nil, 0) + } + + ts := []Timespec{ + NsecToTimespec(TimevalToNsec(tv[0])), + NsecToTimespec(TimevalToNsec(tv[1])), + } + return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) +} + +func Time(t *Time_t) (Time_t, error) { + var tv Timeval + err := Gettimeofday(&tv) + if err != nil { + return 0, err + } + if t != nil { + *t = Time_t(tv.Sec) + } + return Time_t(tv.Sec), nil +} + +func Utime(path string, buf *Utimbuf) error { + tv := []Timeval{ + {Sec: buf.Actime}, + {Sec: buf.Modtime}, + } + return Utimes(path, tv) +} + +func utimes(path string, tv *[2]Timeval) (err error) { + if tv == nil { + return utimensat(AT_FDCWD, path, nil, 0) + } + + ts := []Timespec{ + NsecToTimespec(TimevalToNsec(tv[0])), + NsecToTimespec(TimevalToNsec(tv[1])), + } + return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) +} + +func (r *PtraceRegs) PC() uint64 { return r.Era } + +func (r *PtraceRegs) SetPC(era uint64) { r.Era = era } + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint64(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = uint64(length) +} + +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint64(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint64(length) +} + +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + +func Pause() error { + _, err := ppoll(nil, 0, nil, nil) + return err +} + +func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0) +} + +//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) + +func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { + cmdlineLen := len(cmdline) + if cmdlineLen > 0 { + // Account for the additional NULL byte added by + // BytePtrFromString in kexecFileLoad. The kexec_file_load + // syscall expects a NULL-terminated string. + cmdlineLen++ + } + return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) +} + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index af77e6e..70963a9 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build mips64 mips64le +//go:build linux && (mips64 || mips64le) package unix -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -22,8 +19,8 @@ package unix //sys Lchown(path string, uid int, gid int) (err error) //sys Listen(s int, n int) (err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK @@ -32,24 +29,18 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err if timeout != nil { ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} } - return Pselect(nfd, r, w, e, ts, nil) + return pselect6(nfd, r, w, e, ts, nil) } //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Statfs(path string, buf *Statfs_t) (err error) //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -93,30 +84,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } @@ -216,15 +183,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index e286c6b..c218ebd 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build mips mipsle +//go:build linux && (mips || mipsle) package unix @@ -14,8 +13,6 @@ import ( func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -26,23 +23,18 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sysnb Getuid() (uid int) //sys Lchown(path string, uid int, gid int) (err error) //sys Listen(s int, n int) (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -59,7 +51,6 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) @@ -112,29 +103,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe() (p1 int, p2 int, err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - p[0], p[1], err = pipe() - return -} - //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { @@ -153,10 +121,10 @@ type rlimit32 struct { Max uint32 } -//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT +//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -181,33 +149,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { return } -//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) - if err != ENOSYS { - return err - } - - rl := rlimit32{} - if rlim.Cur == rlimInf64 { - rl.Cur = rlimInf32 - } else if rlim.Cur < uint64(rlimInf32) { - rl.Cur = uint32(rlim.Cur) - } else { - return EINVAL - } - if rlim.Max == rlimInf64 { - rl.Max = rlimInf32 - } else if rlim.Max < uint64(rlimInf32) { - rl.Max = uint32(rlim.Max) - } else { - return EINVAL - } - - return setrlimit(resource, &rl) -} - func (r *PtraceRegs) PC() uint64 { return r.Epc } func (r *PtraceRegs) SetPC(pc uint64) { r.Epc = pc } @@ -228,11 +169,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go new file mode 100644 index 0000000..e6c4850 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -0,0 +1,204 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && ppc + +package unix + +import ( + "syscall" + "unsafe" +) + +//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) +//sys Fchown(fd int, uid int, gid int) (err error) +//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 +//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 +//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64 +//sysnb Getegid() (egid int) +//sysnb Geteuid() (euid int) +//sysnb Getgid() (gid int) +//sysnb Getuid() (uid int) +//sys Ioperm(from int, num int, on int) (err error) +//sys Iopl(level int) (err error) +//sys Lchown(path string, uid int, gid int) (err error) +//sys Listen(s int, n int) (err error) +//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 +//sys Pause() (err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) +//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT +//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 +//sys setfsgid(gid int) (prev int, err error) +//sys setfsuid(uid int) (prev int, err error) +//sys Shutdown(fd int, how int) (err error) +//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) +//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 +//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 +//sys Ustat(dev int, ubuf *Ustat_t) (err error) +//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) +//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) +//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) +//sysnb getgroups(n int, list *_Gid_t) (nn int, err error) +//sysnb setgroups(n int, list *_Gid_t) (err error) +//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) +//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) +//sysnb socket(domain int, typ int, proto int) (fd int, err error) +//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) +//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) +//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) +//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) +//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) +//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) +//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) + +//sys futimesat(dirfd int, path string, times *[2]Timeval) (err error) +//sysnb Gettimeofday(tv *Timeval) (err error) +//sysnb Time(t *Time_t) (tt Time_t, err error) +//sys Utime(path string, buf *Utimbuf) (err error) +//sys utimes(path string, times *[2]Timeval) (err error) + +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64_64, uintptr(fd), uintptr(advice), uintptr(offset>>32), uintptr(offset), uintptr(length>>32), uintptr(length)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func seek(fd int, offset int64, whence int) (int64, syscall.Errno) { + var newoffset int64 + offsetLow := uint32(offset & 0xffffffff) + offsetHigh := uint32((offset >> 32) & 0xffffffff) + _, _, err := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offsetHigh), uintptr(offsetLow), uintptr(unsafe.Pointer(&newoffset)), uintptr(whence), 0) + return newoffset, err +} + +func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { + newoffset, errno := seek(fd, offset, whence) + if errno != 0 { + return 0, errno + } + return newoffset, nil +} + +func Fstatfs(fd int, buf *Statfs_t) (err error) { + _, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) + if e != 0 { + err = e + } + return +} + +func Statfs(path string, buf *Statfs_t) (err error) { + pathp, err := BytePtrFromString(path) + if err != nil { + return err + } + _, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) + if e != 0 { + err = e + } + return +} + +//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) + +func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { + page := uintptr(offset / 4096) + if offset != int64(page)*4096 { + return 0, EINVAL + } + return mmap2(addr, length, prot, flags, fd, page) +} + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: int32(sec), Nsec: int32(nsec)} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: int32(sec), Usec: int32(usec)} +} + +type rlimit32 struct { + Cur uint32 + Max uint32 +} + +//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_UGETRLIMIT + +const rlimInf32 = ^uint32(0) +const rlimInf64 = ^uint64(0) + +func Getrlimit(resource int, rlim *Rlimit) (err error) { + err = Prlimit(0, resource, nil, rlim) + if err != ENOSYS { + return err + } + + rl := rlimit32{} + err = getrlimit(resource, &rl) + if err != nil { + return + } + + if rl.Cur == rlimInf32 { + rlim.Cur = rlimInf64 + } else { + rlim.Cur = uint64(rl.Cur) + } + + if rl.Max == rlimInf32 { + rlim.Max = rlimInf64 + } else { + rlim.Max = uint64(rl.Max) + } + return +} + +func (r *PtraceRegs) PC() uint32 { return r.Nip } + +func (r *PtraceRegs) SetPC(pc uint32) { r.Nip = pc } + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint32(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = uint32(length) +} + +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint32(length) +} + +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + +//sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 + +func SyncFileRange(fd int, off int64, n int64, flags int) error { + // The sync_file_range and sync_file_range2 syscalls differ only in the + // order of their arguments. + return syncFileRange2(fd, flags, off, n) +} + +//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) + +func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { + cmdlineLen := len(cmdline) + if cmdlineLen > 0 { + // Account for the additional NULL byte added by + // BytePtrFromString in kexecFileLoad. The kexec_file_load + // syscall expects a NULL-terminated string. + cmdlineLen++ + } + return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index ca0345a..7286a9a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build ppc64 ppc64le +//go:build linux && (ppc64 || ppc64le) package unix -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -21,33 +18,26 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, buf *Statfs_t) (err error) //sys Truncate(path string, length int64) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -99,39 +89,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index abdabba..8cf3670 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -2,19 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build riscv64,linux +//go:build riscv64 && linux package unix import "unsafe" -func EpollCreate(size int) (fd int, err error) { - if size <= 0 { - return -1, EINVAL - } - return EpollCreate1(0) -} - //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -28,8 +21,9 @@ func EpollCreate(size int) (fd int, err error) { //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) //sys Listen(s int, n int) (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys MemfdSecret(flags int) (fd int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { @@ -37,17 +31,12 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err if timeout != nil { ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} } - return Pselect(nfd, r, w, e, ts, nil) + return pselect6(nfd, r, w, e, ts, nil) } //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) @@ -71,7 +60,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { return ENOSYS } -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -143,30 +131,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } @@ -187,12 +151,8 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -func Dup2(oldfd int, newfd int) (err error) { - return Dup3(oldfd, newfd, 0) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } func Pause() error { @@ -200,18 +160,6 @@ func Pause() error { return err } -func Poll(fds []PollFd, timeout int) (n int, err error) { - var ts *Timespec - if timeout >= 0 { - ts = new(Timespec) - *ts = NsecToTimespec(int64(timeout) * 1e6) - } - if len(fds) == 0 { - return ppoll(nil, 0, ts, nil) - } - return ppoll(&fds[0], len(fds), ts, nil) -} - func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0) } @@ -228,3 +176,16 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } + +//sys riscvHWProbe(pairs []RISCVHWProbePairs, cpuCount uintptr, cpus *CPUSet, flags uint) (err error) + +func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error) { + var setSize uintptr + + if set != nil { + setSize = uintptr(unsafe.Sizeof(*set)) + } + return riscvHWProbe(pairs, setSize, set, flags) +} + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index 533e930..66f3121 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build s390x,linux +//go:build s390x && linux package unix @@ -10,8 +10,6 @@ import ( "unsafe" ) -//sys Dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -24,23 +22,17 @@ import ( //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, buf *Statfs_t) (err error) @@ -76,30 +68,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0. - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } @@ -128,6 +96,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + // Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct. // mmap2 also requires arguments to be passed in a struct; it is currently not exposed in . func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { @@ -167,15 +139,6 @@ const ( netSendMMsg = 20 ) -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (int, error) { - args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))} - fd, _, err := Syscall(SYS_SOCKETCALL, netAccept, uintptr(unsafe.Pointer(&args)), 0) - if err != 0 { - return 0, err - } - return int(fd), nil -} - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (int, error) { args := [4]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)} fd, _, err := Syscall(SYS_SOCKETCALL, netAccept4, uintptr(unsafe.Pointer(&args)), 0) @@ -249,7 +212,7 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen } func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error { - args := [4]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val)} + args := [5]uintptr{uintptr(s), uintptr(level), uintptr(name), uintptr(val), vallen} _, _, err := Syscall(SYS_SOCKETCALL, netSetSockOpt, uintptr(unsafe.Pointer(&args)), 0) if err != 0 { return err @@ -319,15 +282,6 @@ func Shutdown(s, how int) error { return nil } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index d890a22..11d1f16 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build sparc64,linux +//go:build sparc64 && linux package unix //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 -//sys Dup2(oldfd int, newfd int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 @@ -19,31 +18,24 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 +//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys setfsgid(gid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error) -//sysnb Setregid(rgid int, egid int) (err error) -//sysnb Setresgid(rgid int, egid int, sgid int) (err error) -//sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, buf *Statfs_t) (err error) //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) @@ -115,37 +107,6 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) } diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 45b50a6..34a4676 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -13,7 +13,6 @@ package unix import ( - "runtime" "syscall" "unsafe" ) @@ -31,6 +30,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) { @@ -106,16 +109,41 @@ func direntNamlen(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) } -//sysnb pipe() (fd1 int, fd2 int, err error) +func SysctlUvmexp(name string) (*Uvmexp, error) { + mib, err := sysctlmib(name) + if err != nil { + return nil, err + } + + n := uintptr(SizeofUvmexp) + var u Uvmexp + if err := sysctl(mib, (*byte)(unsafe.Pointer(&u)), &n, nil, 0); err != nil { + return nil, err + } + return &u, nil +} + func Pipe(p []int) (err error) { + return Pipe2(p, 0) +} + +//sysnb pipe2(p *[2]_C_int, flags int) (err error) + +func Pipe2(p []int, flags int) error { if len(p) != 2 { return EINVAL } - p[0], p[1], err = pipe() - return + var pp [2]_C_int + err := pipe2(&pp, flags) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return err } -//sys Getdents(fd int, buf []byte) (n int, err error) +//sys Getdents(fd int, buf []byte) (n int, err error) + func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { n, err = Getdents(fd, buf) if err != nil || basep == nil { @@ -141,41 +169,21 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - // TODO func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { return -1, ENOSYS } -func setattrlistTimes(path string, times []Timespec, flags int) error { - // used on Darwin for UtimesNano - return ENOSYS -} - //sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL -//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL func IoctlGetPtmget(fd int, req uint) (*Ptmget, error) { var value Ptmget - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) - runtime.KeepAlive(value) + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) return &value, err } @@ -240,6 +248,23 @@ func Statvfs(path string, buf *Statvfs_t) (err error) { return Statvfs1(path, buf, ST_WAIT) } +func Getvfsstat(buf []Statvfs_t, flags int) (n int, err error) { + var ( + _p0 unsafe.Pointer + bufsize uintptr + ) + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + bufsize = unsafe.Sizeof(Statvfs_t{}) * uintptr(len(buf)) + } + r0, _, e1 := Syscall(SYS_GETVFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + /* * Exposed directly */ @@ -250,6 +275,7 @@ func Statvfs(path string, buf *Statvfs_t) (err error) { //sys Chmod(path string, mode uint32) (err error) //sys Chown(path string, uid int, gid int) (err error) //sys Chroot(path string) (err error) +//sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) @@ -313,8 +339,8 @@ func Statvfs(path string, buf *Statvfs_t) (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) //sys Pathconf(path string, name int) (val int, err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) @@ -331,7 +357,6 @@ func Statvfs(path string, buf *Statvfs_t) (err error) { //sys Setpriority(which int, who int, prio int) (err error) //sysnb Setregid(rgid int, egid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error) -//sysnb Setrlimit(which int, lim *Rlimit) (err error) //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) //sysnb Setuid(uid int) (err error) @@ -348,267 +373,16 @@ func Statvfs(path string, buf *Statvfs_t) (err 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 readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ -//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) -/* - * Unimplemented - */ -// ____semctl13 -// __clone -// __fhopen40 -// __fhstat40 -// __fhstatvfs140 -// __fstat30 -// __getcwd -// __getfh30 -// __getlogin -// __lstat30 -// __mount50 -// __msgctl13 -// __msync13 -// __ntp_gettime30 -// __posix_chown -// __posix_fchown -// __posix_lchown -// __posix_rename -// __setlogin -// __shmctl13 -// __sigaction_sigtramp -// __sigaltstack14 -// __sigpending14 -// __sigprocmask14 -// __sigsuspend14 -// __sigtimedwait -// __stat30 -// __syscall -// __vfork14 -// _ksem_close -// _ksem_destroy -// _ksem_getvalue -// _ksem_init -// _ksem_open -// _ksem_post -// _ksem_trywait -// _ksem_unlink -// _ksem_wait -// _lwp_continue -// _lwp_create -// _lwp_ctl -// _lwp_detach -// _lwp_exit -// _lwp_getname -// _lwp_getprivate -// _lwp_kill -// _lwp_park -// _lwp_self -// _lwp_setname -// _lwp_setprivate -// _lwp_suspend -// _lwp_unpark -// _lwp_unpark_all -// _lwp_wait -// _lwp_wakeup -// _pset_bind -// _sched_getaffinity -// _sched_getparam -// _sched_setaffinity -// _sched_setparam -// acct -// aio_cancel -// aio_error -// aio_fsync -// aio_read -// aio_return -// aio_suspend -// aio_write -// break -// clock_getres -// clock_gettime -// clock_settime -// compat_09_ogetdomainname -// compat_09_osetdomainname -// compat_09_ouname -// compat_10_omsgsys -// compat_10_osemsys -// compat_10_oshmsys -// compat_12_fstat12 -// compat_12_getdirentries -// compat_12_lstat12 -// compat_12_msync -// compat_12_oreboot -// compat_12_oswapon -// compat_12_stat12 -// compat_13_sigaction13 -// compat_13_sigaltstack13 -// compat_13_sigpending13 -// compat_13_sigprocmask13 -// compat_13_sigreturn13 -// compat_13_sigsuspend13 -// compat_14___semctl -// compat_14_msgctl -// compat_14_shmctl -// compat_16___sigaction14 -// compat_16___sigreturn14 -// compat_20_fhstatfs -// compat_20_fstatfs -// compat_20_getfsstat -// compat_20_statfs -// compat_30___fhstat30 -// compat_30___fstat13 -// compat_30___lstat13 -// compat_30___stat13 -// compat_30_fhopen -// compat_30_fhstat -// compat_30_fhstatvfs1 -// compat_30_getdents -// compat_30_getfh -// compat_30_ntp_gettime -// compat_30_socket -// compat_40_mount -// compat_43_fstat43 -// compat_43_lstat43 -// compat_43_oaccept -// compat_43_ocreat -// compat_43_oftruncate -// compat_43_ogetdirentries -// compat_43_ogetdtablesize -// compat_43_ogethostid -// compat_43_ogethostname -// compat_43_ogetkerninfo -// compat_43_ogetpagesize -// compat_43_ogetpeername -// compat_43_ogetrlimit -// compat_43_ogetsockname -// compat_43_okillpg -// compat_43_olseek -// compat_43_ommap -// compat_43_oquota -// compat_43_orecv -// compat_43_orecvfrom -// compat_43_orecvmsg -// compat_43_osend -// compat_43_osendmsg -// compat_43_osethostid -// compat_43_osethostname -// compat_43_osetrlimit -// compat_43_osigblock -// compat_43_osigsetmask -// compat_43_osigstack -// compat_43_osigvec -// compat_43_otruncate -// compat_43_owait -// compat_43_stat43 -// execve -// extattr_delete_fd -// extattr_delete_file -// extattr_delete_link -// extattr_get_fd -// extattr_get_file -// extattr_get_link -// extattr_list_fd -// extattr_list_file -// extattr_list_link -// extattr_set_fd -// extattr_set_file -// extattr_set_link -// extattrctl -// fchroot -// fdatasync -// fgetxattr -// fktrace -// flistxattr -// fork -// fremovexattr -// fsetxattr -// fstatvfs1 -// fsync_range -// getcontext -// getitimer -// getvfsstat -// getxattr -// ktrace -// lchflags -// lchmod -// lfs_bmapv -// lfs_markv -// lfs_segclean -// lfs_segwait -// lgetxattr -// lio_listio -// listxattr -// llistxattr -// lremovexattr -// lseek -// lsetxattr -// lutimes -// madvise -// mincore -// minherit -// modctl -// mq_close -// mq_getattr -// mq_notify -// mq_open -// mq_receive -// mq_send -// mq_setattr -// mq_timedreceive -// mq_timedsend -// mq_unlink -// mremap -// msgget -// msgrcv -// msgsnd -// nfssvc -// ntp_adjtime -// pmc_control -// pmc_get_info -// pollts -// preadv -// profil -// pselect -// pset_assign -// pset_create -// pset_destroy -// ptrace -// pwritev -// quotactl -// rasctl -// readv -// reboot -// removexattr -// sa_enable -// sa_preempt -// sa_register -// sa_setconcurrency -// sa_stacks -// sa_yield -// sbrk -// sched_yield -// semconfig -// semget -// semop -// setcontext -// setitimer -// setxattr -// shmat -// shmdt -// shmget -// sstk -// statvfs1 -// swapctl -// sysarch -// syscall -// timer_create -// timer_delete -// timer_getoverrun -// timer_gettime -// timer_settime -// undelete -// utrace -// uuidgen -// vadvise -// vfork -// writev +const ( + mremapFixed = MAP_FIXED + mremapDontunmap = 0 + mremapMaymove = 0 +) + +//sys mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) = SYS_MREMAP + +func mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (uintptr, error) { + return mremapNetBSD(oldaddr, oldlength, newaddr, newlength, flags) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go index 24da8b5..7a5eb57 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386,netbsd +//go:build 386 && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go index 25a0ac8..62d8957 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,netbsd +//go:build amd64 && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go index 21591ec..ce6a068 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm,netbsd +//go:build arm && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go index 8047496..d46d689 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64,netbsd +//go:build arm64 && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index a266e92..b86ded5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -31,6 +31,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func nametomib(name string) (mib []_C_int, err error) { @@ -77,18 +81,22 @@ func Pipe(p []int) (err error) { } //sysnb pipe2(p *[2]_C_int, flags int) (err error) + func Pipe2(p []int, flags int) error { if len(p) != 2 { return EINVAL } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } -//sys Getdents(fd int, buf []byte) (n int, err error) +//sys Getdents(fd int, buf []byte) (n int, err error) + func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { n, err = Getdents(fd, buf) if err != nil || basep == nil { @@ -114,23 +122,8 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) @@ -144,28 +137,48 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e } func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { - var _p0 unsafe.Pointer + var bufptr *Statfs_t var bufsize uintptr if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) + bufptr = &buf[0] bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } - r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = e1 - } - return + return getfsstat(bufptr, bufsize, flags) } -func setattrlistTimes(path string, times []Timespec, flags int) error { - // used on Darwin for UtimesNano - return ENOSYS +//sysnb getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) +//sysnb getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) + +func Getresuid() (ruid, euid, suid int) { + var r, e, s _C_int + getresuid(&r, &e, &s) + return int(r), int(e), int(s) +} + +func Getresgid() (rgid, egid, sgid int) { + var r, e, s _C_int + getresgid(&r, &e, &s) + return int(r), int(e), int(s) } //sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL + +//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL + +//sys fcntl(fd int, cmd int, arg int) (n int, err error) +//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) = SYS_FCNTL + +// FcntlInt performs a fcntl syscall on fd with the provided command and argument. +func FcntlInt(fd uintptr, cmd, arg int) (int, error) { + return fcntl(int(fd), cmd, arg) +} -//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. +func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { + _, err := fcntlPtr(int(fd), cmd, unsafe.Pointer(lk)) + return err +} //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) @@ -232,6 +245,7 @@ func Uname(uname *Utsname) error { //sys Chmod(path string, mode uint32) (err error) //sys Chown(path string, uid int, gid int) (err error) //sys Chroot(path string) (err error) +//sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) @@ -279,12 +293,13 @@ 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) //sys Pathconf(path string, name int) (val int, err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) @@ -304,7 +319,6 @@ func Uname(uname *Utsname) error { //sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error) -//sysnb Setrlimit(which int, lim *Rlimit) (err error) //sysnb Setrtable(rtable int) (err error) //sysnb Setsid() (pid int, err error) //sysnb Settimeofday(tp *Timeval) (err error) @@ -322,80 +336,7 @@ func Uname(uname *Utsname) 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 readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ -//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE +//sys getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) - -/* - * Unimplemented - */ -// __getcwd -// __semctl -// __syscall -// __sysctl -// adjfreq -// break -// clock_getres -// clock_gettime -// clock_settime -// closefrom -// execve -// fhopen -// fhstat -// fhstatfs -// fork -// futimens -// getfh -// getgid -// getitimer -// getlogin -// getresgid -// getresuid -// getthrid -// ktrace -// lfs_bmapv -// lfs_markv -// lfs_segclean -// lfs_segwait -// mincore -// minherit -// mount -// mquery -// msgctl -// msgget -// msgrcv -// msgsnd -// nfssvc -// nnpfspioctl -// preadv -// profil -// pwritev -// quotactl -// readv -// reboot -// renameat -// rfork -// sched_yield -// semget -// semop -// setgroups -// setitimer -// setsockopt -// shmat -// shmctl -// shmdt -// shmget -// sigaction -// sigaltstack -// sigpending -// sigprocmask -// sigreturn -// sigsuspend -// sysarch -// syscall -// threxit -// thrsigdivert -// thrsleep -// thrwakeup -// vfork -// writev +//sys pledge(promises *byte, execpromises *byte) (err error) +//sys unveil(path *byte, flags *byte) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go index 42b5a0e..9ddc89f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386,openbsd +//go:build 386 && openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go index 6ea4b48..70a3c96 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,openbsd +//go:build amd64 && openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go index 1c3d26f..265caa8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm,openbsd +//go:build arm && openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go index a8c458c..ac4fda1 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64,openbsd +//go:build arm64 && openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go new file mode 100644 index 0000000..0a451e6 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go @@ -0,0 +1,26 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build openbsd + +package unix + +import _ "unsafe" + +// Implemented in the runtime package (runtime/sys_openbsd3.go) +func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func syscall_syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2 uintptr, err Errno) +func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +//go:linkname syscall_syscall syscall.syscall +//go:linkname syscall_syscall6 syscall.syscall6 +//go:linkname syscall_syscall10 syscall.syscall10 +//go:linkname syscall_rawSyscall syscall.rawSyscall +//go:linkname syscall_rawSyscall6 syscall.rawSyscall6 + +func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) { + return syscall_syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, 0) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_mips64.go new file mode 100644 index 0000000..1378489 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_mips64.go @@ -0,0 +1,39 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: sec, Usec: usec} +} + +func SetKevent(k *Kevent_t, fd, mode, flags int) { + k.Ident = uint64(fd) + k.Filter = int16(mode) + k.Flags = uint16(flags) +} + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint64(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = uint32(length) +} + +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint32(length) +} + +// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions +// of OpenBSD the syscall is called sysctl instead of __sysctl. +const SYS___SYSCTL = SYS_SYSCTL diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go new file mode 100644 index 0000000..30a308c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go @@ -0,0 +1,41 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64 && openbsd + +package unix + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: sec, Usec: usec} +} + +func SetKevent(k *Kevent_t, fd, mode, flags int) { + k.Ident = uint64(fd) + k.Filter = int16(mode) + k.Flags = uint16(flags) +} + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint64(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = uint32(length) +} + +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint32(length) +} + +// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions +// of openbsd/ppc64 the syscall is called sysctl instead of __sysctl. +const SYS___SYSCTL = SYS_SYSCTL diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go new file mode 100644 index 0000000..ea95433 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go @@ -0,0 +1,41 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build riscv64 && openbsd + +package unix + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { + return Timeval{Sec: sec, Usec: usec} +} + +func SetKevent(k *Kevent_t, fd, mode, flags int) { + k.Ident = uint64(fd) + k.Filter = int16(mode) + k.Flags = uint16(flags) +} + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint64(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = uint32(length) +} + +func (msghdr *Msghdr) SetIovlen(length int) { + msghdr.Iovlen = uint32(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint32(length) +} + +// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions +// of openbsd/riscv64 the syscall is called sysctl instead of __sysctl. +const SYS___SYSCTL = SYS_SYSCTL diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index 0e2a696..18a3d9b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -13,6 +13,10 @@ package unix import ( + "fmt" + "os" + "runtime" + "sync" "syscall" "unsafe" ) @@ -62,11 +66,28 @@ func Pipe(p []int) (err error) { if n != 0 { return err } - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return nil } +//sysnb pipe2(p *[2]_C_int, flags int) (err error) + +func Pipe2(p []int, flags int) error { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + err := pipe2(&pp, flags) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return err +} + func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { if sa.Port < 0 || sa.Port > 0xFFFF { return nil, 0, EINVAL @@ -75,9 +96,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -90,9 +109,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -111,7 +128,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -140,7 +158,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { if err != nil { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } const ImplementsGetwd = true @@ -391,8 +409,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { for n < len(pp.Path) && pp.Path[n] != 0 { n++ } - bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] - sa.Name = string(bytes) + sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) return sa, nil case AF_INET: @@ -400,9 +417,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -411,9 +426,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -438,77 +451,59 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) - var iov Iovec - if len(p) > 0 { - iov.Base = (*int8)(unsafe.Pointer(&p[0])) - iov.SetLen(len(p)) - } - var dummy int8 + var dummy byte if len(oob) > 0 { // receive at least one normal byte - if len(p) == 0 { - iov.Base = &dummy - iov.SetLen(1) + if emptyIovecs(iov) { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] } msg.Accrightslen = int32(len(oob)) } - msg.Iov = &iov - msg.Iovlen = 1 + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } if n, err = recvmsg(fd, &msg, flags); n == -1 { return } oobn = int(msg.Accrightslen) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(fd, &rsa) - } - return -} - -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) return } //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) - var iov Iovec - if len(p) > 0 { - iov.Base = (*int8)(unsafe.Pointer(&p[0])) - iov.SetLen(len(p)) - } - var dummy int8 + var dummy byte + var empty bool if len(oob) > 0 { // send at least one normal byte - if len(p) == 0 { - iov.Base = &dummy - iov.SetLen(1) + empty = emptyIovecs(iov) + if empty { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] } msg.Accrightslen = int32(len(oob)) } - msg.Iov = &iov - msg.Iovlen = 1 + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } if n, err = sendmsg(fd, &msg, flags); err != nil { return 0, err } - if len(oob) > 0 && len(p) == 0 { + if len(oob) > 0 && empty { n = 0 } return n, nil @@ -551,19 +546,30 @@ func Minor(dev uint64) uint32 { * Expose the ioctl function */ -//sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl +//sys ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl + +func ioctl(fd int, req int, arg uintptr) (err error) { + _, err = ioctlRet(fd, req, arg) + return err +} + +func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) { + _, err = ioctlPtrRet(fd, req, arg) + return err +} -func IoctlSetTermio(fd int, req uint, value *Termio) (err error) { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) +func IoctlSetTermio(fd int, req int, value *Termio) error { + return ioctlPtr(fd, req, unsafe.Pointer(value)) } -func IoctlGetTermio(fd int, req uint) (*Termio, error) { +func IoctlGetTermio(fd int, req int) (*Termio, error) { var value Termio - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) return &value, err } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { if len(fds) == 0 { @@ -588,6 +594,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Chmod(path string, mode uint32) (err error) //sys Chown(path string, uid int, gid int) (err error) //sys Chroot(path string) (err error) +//sys ClockGettime(clockid int32, time *Timespec) (err error) //sys Close(fd int) (err error) //sys Creat(path string, mode uint32) (fd int, err error) //sys Dup(fd int) (nfd int, err error) @@ -616,12 +623,13 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Getpriority(which int, who int) (n int, err error) //sysnb Getrlimit(which int, lim *Rlimit) (err error) //sysnb Getrusage(who int, rusage *Rusage) (err error) +//sysnb Getsid(pid int) (sid int, err error) //sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Getuid() (uid int) //sys Kill(pid int, signum syscall.Signal) (err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Link(path string, link string) (err error) -//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten +//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen //sys Lstat(path string, stat *Stat_t) (err error) //sys Madvise(b []byte, advice int) (err error) //sys Mkdir(path string, mode uint32) (err error) @@ -641,8 +649,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) //sys Pathconf(path string, name int) (val int, err error) //sys Pause() (err error) -//sys Pread(fd int, p []byte, offset int64) (n int, err error) -//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys pread(fd int, p []byte, offset int64) (n int, err error) +//sys pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Rename(from string, to string) (err error) @@ -658,7 +666,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Setpriority(which int, who int, prio int) (err error) //sysnb Setregid(rgid int, egid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error) -//sysnb Setrlimit(which int, lim *Rlimit) (err error) //sysnb Setsid() (pid int, err error) //sysnb Setuid(uid int) (err error) //sys Shutdown(s int, how int) (err error) = libsocket.shutdown @@ -666,6 +673,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Statvfs(path string, vfsstat *Statvfs_t) (err error) //sys Symlink(path string, link string) (err error) //sys Sync() (err error) +//sys Sysconf(which int) (n int64, err error) //sysnb Times(tms *Tms) (ticks uintptr, err error) //sys Truncate(path string, length int64) (err error) //sys Fsync(fd int) (err error) @@ -691,34 +699,493 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) - n = int(r0) - if e1 != 0 { - err = e1 +// Event Ports + +type fileObjCookie struct { + fobj *fileObj + cookie interface{} +} + +// EventPort provides a safe abstraction on top of Solaris/illumos Event Ports. +type EventPort struct { + port int + mu sync.Mutex + fds map[uintptr]*fileObjCookie + paths map[string]*fileObjCookie + // The user cookie presents an interesting challenge from a memory management perspective. + // There are two paths by which we can discover that it is no longer in use: + // 1. The user calls port_dissociate before any events fire + // 2. An event fires and we return it to the user + // The tricky situation is if the event has fired in the kernel but + // the user hasn't requested/received it yet. + // If the user wants to port_dissociate before the event has been processed, + // we should handle things gracefully. To do so, we need to keep an extra + // reference to the cookie around until the event is processed + // thus the otherwise seemingly extraneous "cookies" map + // The key of this map is a pointer to the corresponding fCookie + cookies map[*fileObjCookie]struct{} +} + +// PortEvent is an abstraction of the port_event C struct. +// Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD +// to see if Path or Fd was the event source. The other will be +// uninitialized. +type PortEvent struct { + Cookie interface{} + Events int32 + Fd uintptr + Path string + Source uint16 + fobj *fileObj +} + +// NewEventPort creates a new EventPort including the +// underlying call to port_create(3c). +func NewEventPort() (*EventPort, error) { + port, err := port_create() + if err != nil { + return nil, err } - return + e := &EventPort{ + port: port, + fds: make(map[uintptr]*fileObjCookie), + paths: make(map[string]*fileObjCookie), + cookies: make(map[*fileObjCookie]struct{}), + } + return e, nil } -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) - n = int(r0) - if e1 != 0 { - err = e1 +//sys port_create() (n int, err error) +//sys port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error) +//sys port_dissociate(port int, source int, object uintptr) (n int, err error) +//sys port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error) +//sys port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error) + +// Close closes the event port. +func (e *EventPort) Close() error { + e.mu.Lock() + defer e.mu.Unlock() + err := Close(e.port) + if err != nil { + return err } - return + e.fds = nil + e.paths = nil + e.cookies = nil + return nil +} + +// PathIsWatched checks to see if path is associated with this EventPort. +func (e *EventPort) PathIsWatched(path string) bool { + e.mu.Lock() + defer e.mu.Unlock() + _, found := e.paths[path] + return found +} + +// FdIsWatched checks to see if fd is associated with this EventPort. +func (e *EventPort) FdIsWatched(fd uintptr) bool { + e.mu.Lock() + defer e.mu.Unlock() + _, found := e.fds[fd] + return found +} + +// AssociatePath wraps port_associate(3c) for a filesystem path including +// creating the necessary file_obj from the provided stat information. +func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error { + e.mu.Lock() + defer e.mu.Unlock() + if _, found := e.paths[path]; found { + return fmt.Errorf("%v is already associated with this Event Port", path) + } + fCookie, err := createFileObjCookie(path, stat, cookie) + if err != nil { + return err + } + _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie))) + if err != nil { + return err + } + e.paths[path] = fCookie + e.cookies[fCookie] = struct{}{} + return nil +} + +// DissociatePath wraps port_dissociate(3c) for a filesystem path. +func (e *EventPort) DissociatePath(path string) error { + e.mu.Lock() + defer e.mu.Unlock() + f, ok := e.paths[path] + if !ok { + return fmt.Errorf("%v is not associated with this Event Port", path) + } + _, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj))) + // If the path is no longer associated with this event port (ENOENT) + // we should delete it from our map. We can still return ENOENT to the caller. + // But we need to save the cookie + if err != nil && err != ENOENT { + return err + } + if err == nil { + // dissociate was successful, safe to delete the cookie + fCookie := e.paths[path] + delete(e.cookies, fCookie) + } + delete(e.paths, path) + return err +} + +// AssociateFd wraps calls to port_associate(3c) on file descriptors. +func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error { + e.mu.Lock() + defer e.mu.Unlock() + if _, found := e.fds[fd]; found { + return fmt.Errorf("%v is already associated with this Event Port", fd) + } + fCookie, err := createFileObjCookie("", nil, cookie) + if err != nil { + return err + } + _, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie))) + if err != nil { + return err + } + e.fds[fd] = fCookie + e.cookies[fCookie] = struct{}{} + return nil +} + +// DissociateFd wraps calls to port_dissociate(3c) on file descriptors. +func (e *EventPort) DissociateFd(fd uintptr) error { + e.mu.Lock() + defer e.mu.Unlock() + _, ok := e.fds[fd] + if !ok { + return fmt.Errorf("%v is not associated with this Event Port", fd) + } + _, err := port_dissociate(e.port, PORT_SOURCE_FD, fd) + if err != nil && err != ENOENT { + return err + } + if err == nil { + // dissociate was successful, safe to delete the cookie + fCookie := e.fds[fd] + delete(e.cookies, fCookie) + } + delete(e.fds, fd) + return err +} + +func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) { + fCookie := new(fileObjCookie) + fCookie.cookie = cookie + if name != "" && stat != nil { + fCookie.fobj = new(fileObj) + bs, err := ByteSliceFromString(name) + if err != nil { + return nil, err + } + fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0])) + s := stat.Sys().(*syscall.Stat_t) + fCookie.fobj.Atim.Sec = s.Atim.Sec + fCookie.fobj.Atim.Nsec = s.Atim.Nsec + fCookie.fobj.Mtim.Sec = s.Mtim.Sec + fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec + fCookie.fobj.Ctim.Sec = s.Ctim.Sec + fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec + } + return fCookie, nil +} + +// GetOne wraps port_get(3c) and returns a single PortEvent. +func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) { + pe := new(portEvent) + _, err := port_get(e.port, pe, t) + if err != nil { + return nil, err + } + p := new(PortEvent) + e.mu.Lock() + defer e.mu.Unlock() + err = e.peIntToExt(pe, p) + if err != nil { + return nil, err + } + return p, nil +} + +// peIntToExt converts a cgo portEvent struct into the friendlier PortEvent +// NOTE: Always call this function while holding the e.mu mutex +func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error { + if e.cookies == nil { + return fmt.Errorf("this EventPort is already closed") + } + peExt.Events = peInt.Events + peExt.Source = peInt.Source + fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User)) + _, found := e.cookies[fCookie] + + if !found { + panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254") + } + peExt.Cookie = fCookie.cookie + delete(e.cookies, fCookie) + + switch peInt.Source { + case PORT_SOURCE_FD: + peExt.Fd = uintptr(peInt.Object) + // Only remove the fds entry if it exists and this cookie matches + if fobj, ok := e.fds[peExt.Fd]; ok { + if fobj == fCookie { + delete(e.fds, peExt.Fd) + } + } + case PORT_SOURCE_FILE: + peExt.fobj = fCookie.fobj + peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name))) + // Only remove the paths entry if it exists and this cookie matches + if fobj, ok := e.paths[peExt.Path]; ok { + if fobj == fCookie { + delete(e.paths, peExt.Path) + } + } + } + return nil +} + +// Pending wraps port_getn(3c) and returns how many events are pending. +func (e *EventPort) Pending() (int, error) { + var n uint32 = 0 + _, err := port_getn(e.port, nil, 0, &n, nil) + return int(n), err +} + +// Get wraps port_getn(3c) and fills a slice of PortEvent. +// It will block until either min events have been received +// or the timeout has been exceeded. It will return how many +// events were actually received along with any error information. +func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) { + if min == 0 { + return 0, fmt.Errorf("need to request at least one event or use Pending() instead") + } + if len(s) < min { + return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min) + } + got := uint32(min) + max := uint32(len(s)) + var err error + ps := make([]portEvent, max) + _, err = port_getn(e.port, &ps[0], max, &got, timeout) + // got will be trustworthy with ETIME, but not any other error. + if err != nil && err != ETIME { + return 0, err + } + e.mu.Lock() + defer e.mu.Unlock() + valid := 0 + for i := 0; i < int(got); i++ { + err2 := e.peIntToExt(&ps[i], &s[i]) + if err2 != nil { + if valid == 0 && err == nil { + // If err2 is the only error and there are no valid events + // to return, return it to the caller. + err = err2 + } + break + } + valid = i + 1 + } + return valid, err +} + +//sys putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error) + +func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) { + var clp, datap *strbuf + if len(cl) > 0 { + clp = &strbuf{ + Len: int32(len(cl)), + Buf: (*int8)(unsafe.Pointer(&cl[0])), + } + } + if len(data) > 0 { + datap = &strbuf{ + Len: int32(len(data)), + Buf: (*int8)(unsafe.Pointer(&data[0])), + } + } + return putmsg(fd, clp, datap, flags) +} + +//sys getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error) + +func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) { + var clp, datap *strbuf + if len(cl) > 0 { + clp = &strbuf{ + Maxlen: int32(len(cl)), + Buf: (*int8)(unsafe.Pointer(&cl[0])), + } + } + if len(data) > 0 { + datap = &strbuf{ + Maxlen: int32(len(data)), + Buf: (*int8)(unsafe.Pointer(&data[0])), + } + } + + if err = getmsg(fd, clp, datap, &flags); err != nil { + return nil, nil, 0, err + } + + if len(cl) > 0 { + retCl = cl[:clp.Len] + } + if len(data) > 0 { + retData = data[:datap.Len] + } + return retCl, retData, flags, nil +} + +func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) { + return ioctlRet(fd, req, uintptr(arg)) +} + +func IoctlSetString(fd int, req int, val string) error { + bs := make([]byte, len(val)+1) + copy(bs[:len(bs)-1], val) + err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0])) + runtime.KeepAlive(&bs[0]) + return err +} + +// Lifreq Helpers + +func (l *Lifreq) SetName(name string) error { + if len(name) >= len(l.Name) { + return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1) + } + for i := range name { + l.Name[i] = int8(name[i]) + } + return nil +} + +func (l *Lifreq) SetLifruInt(d int) { + *(*int)(unsafe.Pointer(&l.Lifru[0])) = d +} + +func (l *Lifreq) GetLifruInt() int { + return *(*int)(unsafe.Pointer(&l.Lifru[0])) +} + +func (l *Lifreq) SetLifruUint(d uint) { + *(*uint)(unsafe.Pointer(&l.Lifru[0])) = d +} + +func (l *Lifreq) GetLifruUint() uint { + return *(*uint)(unsafe.Pointer(&l.Lifru[0])) +} + +func IoctlLifreq(fd int, req int, l *Lifreq) error { + return ioctlPtr(fd, req, unsafe.Pointer(l)) +} + +// Strioctl Helpers + +func (s *Strioctl) SetInt(i int) { + s.Len = int32(unsafe.Sizeof(i)) + s.Dp = (*int8)(unsafe.Pointer(&i)) +} + +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) } -var mapper = &mmapper{ - active: make(map[*byte][]byte), - mmap: mmap, - munmap: munmap, +func (u *Ucred) Getrgid() int { + defer runtime.KeepAlive(u) + return ucredGetrgid(u.ucred) } -func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { - return mapper.Mmap(fd, offset, length, prot, flags) +func (u *Ucred) Getsgid() int { + defer runtime.KeepAlive(u) + return ucredGetsgid(u.ucred) } -func Munmap(b []byte) (err error) { - return mapper.Munmap(b) +func (u *Ucred) Getpid() int { + defer runtime.KeepAlive(u) + return ucredGetpid(u.ucred) } diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go index b22a34d..e02d8ce 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,solaris +//go:build amd64 && solaris package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix.go b/vendor/golang.org/x/sys/unix/syscall_unix.go index 8f710d0..4e92e5a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris package unix @@ -113,15 +113,8 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d return nil, errno } - // Slice memory layout - var sl = struct { - addr uintptr - len int - cap int - }{addr, length, length} - - // Use unsafe to turn sl into a []byte. - b := *(*[]byte)(unsafe.Pointer(&sl)) + // Use unsafe to convert addr into a []byte. + b := unsafe.Slice((*byte)(unsafe.Pointer(addr)), length) // Register mapping in m and return it. p := &b[cap(b)-1] @@ -153,6 +146,23 @@ func (m *mmapper) Munmap(data []byte) (err error) { return nil } +func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { + return mapper.Mmap(fd, offset, length, prot, flags) +} + +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 { @@ -177,6 +187,30 @@ func Write(fd int, p []byte) (n int, err error) { return } +func Pread(fd int, p []byte, offset int64) (n int, err error) { + n, err = pread(fd, p, offset) + if raceenabled { + if n > 0 { + raceWriteRange(unsafe.Pointer(&p[0]), n) + } + if err == nil { + raceAcquire(unsafe.Pointer(&ioSync)) + } + } + return +} + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = pwrite(fd, p, offset) + if raceenabled && n > 0 { + raceReadRange(unsafe.Pointer(&p[0]), n) + } + return +} + // For testing: clients can set this flag to force // creation of IPv6 sockets to return EAFNOSUPPORT. var SocketDisableIPv6 bool @@ -313,12 +347,142 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } +// Recvmsg receives a message from a socket using the recvmsg system call. The +// received non-control data will be written to p, and any "out of band" +// control data will be written to oob. The flags are passed to recvmsg. +// +// The results are: +// - n is the number of non-control data bytes read into p +// - oobn is the number of control data bytes read into oob; this may be interpreted using [ParseSocketControlMessage] +// - recvflags is flags returned by recvmsg +// - from is the address of the sender +// +// If the underlying socket type is not SOCK_DGRAM, a received message +// containing oob data and a single '\0' of non-control data is treated as if +// the message contained only control data, i.e. n will be zero on return. +func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { + var iov [1]Iovec + if len(p) > 0 { + iov[0].Base = &p[0] + iov[0].SetLen(len(p)) + } + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, iov[:], oob, flags, &rsa) + // source address is only specified if the socket is unconnected + if rsa.Addr.Family != AF_UNSPEC { + from, err = anyToSockaddr(fd, &rsa) + } + return +} + +// RecvmsgBuffers receives a message from a socket using the recvmsg system +// call. This function is equivalent to Recvmsg, but non-control data read is +// scattered into the buffers slices. +func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { + iov := make([]Iovec, len(buffers)) + for i := range buffers { + if len(buffers[i]) > 0 { + iov[i].Base = &buffers[i][0] + iov[i].SetLen(len(buffers[i])) + } else { + iov[i].Base = (*byte)(unsafe.Pointer(&_zero)) + } + } + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, iov, oob, flags, &rsa) + if err == nil && rsa.Addr.Family != AF_UNSPEC { + from, err = anyToSockaddr(fd, &rsa) + } + return +} + +// Sendmsg sends a message on a socket to an address using the sendmsg system +// call. This function is equivalent to SendmsgN, but does not return the +// number of bytes actually sent. +func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { + _, err = SendmsgN(fd, p, oob, to, flags) + return +} + +// SendmsgN sends a message on a socket to an address using the sendmsg system +// call. p contains the non-control data to send, and oob contains the "out of +// band" control data. The flags are passed to sendmsg. The number of +// non-control bytes actually written to the socket is returned. +// +// Some socket types do not support sending control data without accompanying +// non-control data. If p is empty, and oob contains control data, and the +// underlying socket type is not SOCK_DGRAM, p will be treated as containing a +// single '\0' and the return value will indicate zero bytes sent. +// +// The Go function Recvmsg, if called with an empty p and a non-empty oob, +// will read and ignore this additional '\0'. If the message is received by +// code that does not use Recvmsg, or that does not use Go at all, that code +// will need to be written to expect and ignore the additional '\0'. +// +// If you need to send non-empty oob with p actually empty, and if the +// underlying socket type supports it, you can do so via a raw system call as +// follows: +// +// msg := &unix.Msghdr{ +// Control: &oob[0], +// } +// msg.SetControllen(len(oob)) +// n, _, errno := unix.Syscall(unix.SYS_SENDMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), flags) +func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { + var iov [1]Iovec + if len(p) > 0 { + iov[0].Base = &p[0] + iov[0].SetLen(len(p)) + } + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } + } + return sendmsgN(fd, iov[:], oob, ptr, salen, flags) +} + +// SendmsgBuffers sends a message on a socket to an address using the sendmsg +// system call. This function is equivalent to SendmsgN, but the non-control +// data is gathered from buffers. +func SendmsgBuffers(fd int, buffers [][]byte, oob []byte, to Sockaddr, flags int) (n int, err error) { + iov := make([]Iovec, len(buffers)) + for i := range buffers { + if len(buffers[i]) > 0 { + iov[i].Base = &buffers[i][0] + iov[i].SetLen(len(buffers[i])) + } else { + iov[i].Base = (*byte)(unsafe.Pointer(&_zero)) + } + } + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } + } + return sendmsgN(fd, iov, oob, ptr, salen, flags) +} + +func Send(s int, buf []byte, flags int) (err error) { + return sendto(s, buf, flags, nil, 0) +} + func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { - ptr, n, err := to.sockaddr() - if err != nil { - return err + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return err + } } - return sendto(fd, p, flags, ptr, n) + return sendto(fd, p, flags, ptr, salen) } func SetsockoptByte(fd, level, opt int, value byte) (err error) { @@ -393,6 +557,9 @@ func SetNonblock(fd int, nonblocking bool) (err error) { if err != nil { return err } + if (flag&O_NONBLOCK != 0) == nonblocking { + return nil + } if nonblocking { flag |= O_NONBLOCK } else { @@ -429,3 +596,20 @@ func Lutimes(path string, tv []Timeval) error { } return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW) } + +// emptyIovecs reports whether there are no bytes in the slice of Iovec. +func emptyIovecs(iov []Iovec) bool { + for i := range iov { + if iov[i].Len > 0 { + return false + } + } + return true +} + +// Setrlimit sets a resource limit. +func Setrlimit(resource int, rlim *Rlimit) error { + // Just call the syscall version, because as of Go 1.21 + // it will affect starting a new process. + return syscall.Setrlimit(resource, (*syscall.Rlimit)(rlim)) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_gc.go b/vendor/golang.org/x/sys/unix/syscall_unix_gc.go index 1c70d1b..05c95bc 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix_gc.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd linux netbsd openbsd solaris -// +build !gccgo,!ppc64le,!ppc64 +//go:build (darwin || dragonfly || freebsd || (linux && !ppc64 && !ppc64le) || netbsd || openbsd || solaris) && gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go index 86dc765..23f39b7 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build ppc64le ppc64 -// +build !gccgo +//go:build linux && (ppc64le || ppc64) && gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go new file mode 100644 index 0000000..7bf5c04 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -0,0 +1,3213 @@ +// 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 + +// Many of the following syscalls are not available on all versions of z/OS. +// Some missing calls have legacy implementations/simulations but others +// will be missing completely. To achieve consistent failing behaviour on +// legacy systems, we first test the function pointer via a safeloading +// mechanism to see if the function exists on a given system. Then execution +// is branched to either continue the function call, or return an error. + +package unix + +import ( + "bytes" + "fmt" + "os" + "reflect" + "regexp" + "runtime" + "sort" + "strings" + "sync" + "syscall" + "unsafe" +) + +//go:noescape +func initZosLibVec() + +//go:noescape +func GetZosLibVec() uintptr + +func init() { + initZosLibVec() + r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACE\x00"))[0]))) + if r0 != 0 { + n, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0) + ZosTraceLevel = int(n) + r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACEFD\x00"))[0]))) + if r0 != 0 { + fd, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0) + f := os.NewFile(fd, "zostracefile") + if f != nil { + ZosTracefile = f + } + } + + } +} + +//go:noescape +func CallLeFuncWithErr(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno) + +//go:noescape +func CallLeFuncWithPtrReturn(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno) + +// ------------------------------- +// pointer validity test +// good pointer returns 0 +// bad pointer returns 1 +// +//go:nosplit +func ptrtest(uintptr) uint64 + +// Load memory at ptr location with error handling if the location is invalid +// +//go:noescape +func safeload(ptr uintptr) (value uintptr, error uintptr) + +const ( + entrypointLocationOffset = 8 // From function descriptor + + xplinkEyecatcher = 0x00c300c500c500f1 // ".C.E.E.1" + eyecatcherOffset = 16 // From function entrypoint (negative) + ppa1LocationOffset = 8 // From function entrypoint (negative) + + nameLenOffset = 0x14 // From PPA1 start + nameOffset = 0x16 // From PPA1 start +) + +func getPpaOffset(funcptr uintptr) int64 { + entrypoint, err := safeload(funcptr + entrypointLocationOffset) + if err != 0 { + return -1 + } + + // XPLink functions have ".C.E.E.1" as the first 8 bytes (EBCDIC) + val, err := safeload(entrypoint - eyecatcherOffset) + if err != 0 { + return -1 + } + if val != xplinkEyecatcher { + return -1 + } + + ppaoff, err := safeload(entrypoint - ppa1LocationOffset) + if err != 0 { + return -1 + } + + ppaoff >>= 32 + return int64(ppaoff) +} + +//------------------------------- +// function descriptor pointer validity test +// good pointer returns 0 +// bad pointer returns 1 + +// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName +// have correct funcName pass to the funcptrtest function +func funcptrtest(funcptr uintptr, funcName string) uint64 { + entrypoint, err := safeload(funcptr + entrypointLocationOffset) + if err != 0 { + return 1 + } + + ppaoff := getPpaOffset(funcptr) + if ppaoff == -1 { + return 1 + } + + // PPA1 offset value is from the start of the entire function block, not the entrypoint + ppa1 := (entrypoint - eyecatcherOffset) + uintptr(ppaoff) + + nameLen, err := safeload(ppa1 + nameLenOffset) + if err != 0 { + return 1 + } + + nameLen >>= 48 + if nameLen > 128 { + return 1 + } + + // no function name input to argument end here + if funcName == "" { + return 0 + } + + var funcname [128]byte + for i := 0; i < int(nameLen); i += 8 { + v, err := safeload(ppa1 + nameOffset + uintptr(i)) + if err != 0 { + return 1 + } + funcname[i] = byte(v >> 56) + funcname[i+1] = byte(v >> 48) + funcname[i+2] = byte(v >> 40) + funcname[i+3] = byte(v >> 32) + funcname[i+4] = byte(v >> 24) + funcname[i+5] = byte(v >> 16) + funcname[i+6] = byte(v >> 8) + funcname[i+7] = byte(v) + } + + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l + []uintptr{uintptr(unsafe.Pointer(&funcname[0])), nameLen}) + + name := string(funcname[:nameLen]) + if name != funcName { + return 1 + } + + return 0 +} + +// For detection of capabilities on a system. +// Is function descriptor f a valid function? +func isValidLeFunc(f uintptr) error { + ret := funcptrtest(f, "") + if ret != 0 { + return fmt.Errorf("Bad pointer, not an LE function ") + } + return nil +} + +// Retrieve function name from descriptor +func getLeFuncName(f uintptr) (string, error) { + // assume it has been checked, only check ppa1 validity here + entry := ((*[2]uintptr)(unsafe.Pointer(f)))[1] + preamp := ((*[4]uint32)(unsafe.Pointer(entry - eyecatcherOffset))) + + offsetPpa1 := preamp[2] + if offsetPpa1 > 0x0ffff { + return "", fmt.Errorf("PPA1 offset seems too big 0x%x\n", offsetPpa1) + } + + ppa1 := uintptr(unsafe.Pointer(preamp)) + uintptr(offsetPpa1) + res := ptrtest(ppa1) + if res != 0 { + return "", fmt.Errorf("PPA1 address not valid") + } + + size := *(*uint16)(unsafe.Pointer(ppa1 + nameLenOffset)) + if size > 128 { + return "", fmt.Errorf("Function name seems too long, length=%d\n", size) + } + + var name [128]byte + funcname := (*[128]byte)(unsafe.Pointer(ppa1 + nameOffset)) + copy(name[0:size], funcname[0:size]) + + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l + []uintptr{uintptr(unsafe.Pointer(&name[0])), uintptr(size)}) + + return string(name[:size]), nil +} + +// Check z/OS version +func zosLeVersion() (version, release uint32) { + p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32 + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88))) + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8))) + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984))) + vrm := *(*uint32)(unsafe.Pointer(p1 + 80)) + version = (vrm & 0x00ff0000) >> 16 + release = (vrm & 0x0000ff00) >> 8 + return +} + +// returns a zos C FILE * for stdio fd 0, 1, 2 +func ZosStdioFilep(fd int32) uintptr { + return uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(uint64(*(*uint32)(unsafe.Pointer(uintptr(1208)))) + 80))) + uint64((fd+2)<<3)))))))) +} + +func copyStat(stat *Stat_t, statLE *Stat_LE_t) { + stat.Dev = uint64(statLE.Dev) + stat.Ino = uint64(statLE.Ino) + stat.Nlink = uint64(statLE.Nlink) + stat.Mode = uint32(statLE.Mode) + stat.Uid = uint32(statLE.Uid) + stat.Gid = uint32(statLE.Gid) + stat.Rdev = uint64(statLE.Rdev) + stat.Size = statLE.Size + stat.Atim.Sec = int64(statLE.Atim) + stat.Atim.Nsec = 0 //zos doesn't return nanoseconds + stat.Mtim.Sec = int64(statLE.Mtim) + stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds + stat.Ctim.Sec = int64(statLE.Ctim) + stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds + stat.Blksize = int64(statLE.Blksize) + stat.Blocks = statLE.Blocks +} + +func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64) +func svcLoad(name *byte) unsafe.Pointer +func svcUnload(name *byte, fnptr unsafe.Pointer) int64 + +func (d *Dirent) NameString() string { + if d == nil { + return "" + } + s := string(d.Name[:]) + idx := strings.IndexByte(s, 0) + if idx == -1 { + return s + } else { + return s[:idx] + } +} + +func DecodeData(dest []byte, sz int, val uint64) { + for i := 0; i < sz; i++ { + dest[sz-1-i] = byte((val >> (uint64(i * 8))) & 0xff) + } +} + +func EncodeData(data []byte) uint64 { + var value uint64 + sz := len(data) + for i := 0; i < sz; i++ { + value |= uint64(data[i]) << uint64(((sz - i - 1) * 8)) + } + return value +} + +func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { + if sa.Port < 0 || sa.Port > 0xFFFF { + return nil, 0, EINVAL + } + sa.raw.Len = SizeofSockaddrInet4 + sa.raw.Family = AF_INET + p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } + return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil +} + +func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { + if sa.Port < 0 || sa.Port > 0xFFFF { + return nil, 0, EINVAL + } + sa.raw.Len = SizeofSockaddrInet6 + sa.raw.Family = AF_INET6 + p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + sa.raw.Scope_id = sa.ZoneId + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } + return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil +} + +func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { + name := sa.Name + n := len(name) + if n >= len(sa.raw.Path) || n == 0 { + return nil, 0, EINVAL + } + sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL + sa.raw.Family = AF_UNIX + for i := 0; i < n; i++ { + sa.raw.Path[i] = int8(name[i]) + } + return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil +} + +func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { + // TODO(neeilan): Implement use of first param (fd) + switch rsa.Addr.Family { + case AF_UNIX: + pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) + sa := new(SockaddrUnix) + // For z/OS, only replace NUL with @ when the + // length is not zero. + if pp.Len != 0 && pp.Path[0] == 0 { + // "Abstract" Unix domain socket. + // Rewrite leading NUL as @ for textual display. + // (This is the standard convention.) + // Not friendly to overwrite in place, + // but the callers below don't care. + pp.Path[0] = '@' + } + + // Assume path ends at NUL. + // + // For z/OS, the length of the name is a field + // in the structure. To be on the safe side, we + // will still scan the name for a NUL but only + // to the length provided in the structure. + // + // This is not technically the Linux semantics for + // abstract Unix domain sockets--they are supposed + // to be uninterpreted fixed-size binary blobs--but + // everyone uses this convention. + n := 0 + for n < int(pp.Len) && pp.Path[n] != 0 { + n++ + } + sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) + return sa, nil + + case AF_INET: + pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) + sa := new(SockaddrInet4) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } + return sa, nil + + case AF_INET6: + pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) + sa := new(SockaddrInet6) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.ZoneId = pp.Scope_id + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } + return sa, nil + } + return nil, EAFNOSUPPORT +} + +func Accept(fd int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept(fd, &rsa, &len) + if err != nil { + return + } + // TODO(neeilan): Remove 0 in call + sa, err = anyToSockaddr(0, &rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} + +func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept4(fd, &rsa, &len, flags) + if err != nil { + return + } + if len > SizeofSockaddrAny { + panic("RawSockaddrAny too small") + } + // TODO(neeilan): Remove 0 in call + sa, err = anyToSockaddr(0, &rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} + +func Ctermid() (tty string, err error) { + var termdev [1025]byte + runtime.EnterSyscall() + r0, err2, err1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___CTERMID_A<<4, uintptr(unsafe.Pointer(&termdev[0]))) + runtime.ExitSyscall() + if r0 == 0 { + return "", fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) + } + s := string(termdev[:]) + idx := strings.Index(s, string(rune(0))) + if idx == -1 { + tty = s + } else { + tty = s[:idx] + } + return +} + +func (iov *Iovec) SetLen(length int) { + iov.Len = uint64(length) +} + +func (msghdr *Msghdr) SetControllen(length int) { + msghdr.Controllen = int32(length) +} + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = int32(length) +} + +//sys fcntl(fd int, cmd int, arg int) (val int, err error) +//sys Flistxattr(fd int, dest []byte) (sz int, err error) = SYS___FLISTXATTR_A +//sys Fremovexattr(fd int, attr string) (err error) = SYS___FREMOVEXATTR_A +//sys read(fd int, p []byte) (n int, err error) +//sys write(fd int, p []byte) (n int, err error) + +//sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) = SYS___FGETXATTR_A +//sys Fsetxattr(fd int, attr string, data []byte, flag int) (err error) = SYS___FSETXATTR_A + +//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A +//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = SYS___ACCEPT4_A +//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A +//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A +//sysnb getgroups(n int, list *_Gid_t) (nn int, err error) +//sysnb setgroups(n int, list *_Gid_t) (err error) +//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) +//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) +//sysnb socket(domain int, typ int, proto int) (fd int, err error) +//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) +//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A +//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A +//sys Removexattr(path string, attr string) (err error) = SYS___REMOVEXATTR_A +//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A +//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A +//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A +//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A +//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP +//sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP +//sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL +//sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) = SYS_SHMAT +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) = SYS_SHMCTL64 +//sys shmdt(addr uintptr) (err error) = SYS_SHMDT +//sys shmget(key int, size int, flag int) (id int, err error) = SYS_SHMGET + +//sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A +//sys Chdir(path string) (err error) = SYS___CHDIR_A +//sys Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A +//sys Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A +//sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A +//sys Dup(oldfd int) (fd int, err error) +//sys Dup2(oldfd int, newfd int) (err error) +//sys Dup3(oldfd int, newfd int, flags int) (err error) = SYS_DUP3 +//sys Dirfd(dirp uintptr) (fd int, err error) = SYS_DIRFD +//sys EpollCreate(size int) (fd int, err error) = SYS_EPOLL_CREATE +//sys EpollCreate1(flags int) (fd int, err error) = SYS_EPOLL_CREATE1 +//sys EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) = SYS_EPOLL_CTL +//sys EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) = SYS_EPOLL_PWAIT +//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_WAIT +//sys Errno2() (er2 int) = SYS___ERRNO2 +//sys Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD +//sys Exit(code int) +//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FACCESSAT_A + +func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) { + return Faccessat(dirfd, path, mode, flags) +} + +//sys Fchdir(fd int) (err error) +//sys Fchmod(fd int, mode uint32) (err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FCHMODAT_A +//sys Fchown(fd int, uid int, gid int) (err error) +//sys Fchownat(fd int, path string, uid int, gid int, flags int) (err error) = SYS___FCHOWNAT_A +//sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL +//sys Fdatasync(fd int) (err error) = SYS_FDATASYNC +//sys fstat(fd int, stat *Stat_LE_t) (err error) +//sys fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) = SYS___FSTATAT_A + +func Fstat(fd int, stat *Stat_t) (err error) { + var statLE Stat_LE_t + err = fstat(fd, &statLE) + copyStat(stat, &statLE) + return +} + +func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { + var statLE Stat_LE_t + err = fstatat(dirfd, path, &statLE, flags) + copyStat(stat, &statLE) + return +} + +func impl_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest))) + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_GetxattrAddr() *(func(path string, attr string, dest []byte) (sz int, err error)) + +var Getxattr = enter_Getxattr + +func enter_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + funcref := get_GetxattrAddr() + if validGetxattr() { + *funcref = impl_Getxattr + } else { + *funcref = error_Getxattr + } + return (*funcref)(path, attr, dest) +} + +func error_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + return -1, ENOSYS +} + +func validGetxattr() bool { + if funcptrtest(GetZosLibVec()+SYS___GETXATTR_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___GETXATTR_A<<4); err == nil { + return name == "__getxattr_a" + } + } + return false +} + +//sys Lgetxattr(link string, attr string, dest []byte) (sz int, err error) = SYS___LGETXATTR_A +//sys Lsetxattr(path string, attr string, data []byte, flags int) (err error) = SYS___LSETXATTR_A + +func impl_Setxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error)) + +var Setxattr = enter_Setxattr + +func enter_Setxattr(path string, attr string, data []byte, flags int) (err error) { + funcref := get_SetxattrAddr() + if validSetxattr() { + *funcref = impl_Setxattr + } else { + *funcref = error_Setxattr + } + return (*funcref)(path, attr, data, flags) +} + +func error_Setxattr(path string, attr string, data []byte, flags int) (err error) { + return ENOSYS +} + +func validSetxattr() bool { + if funcptrtest(GetZosLibVec()+SYS___SETXATTR_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___SETXATTR_A<<4); err == nil { + return name == "__setxattr_a" + } + } + return false +} + +//sys Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS +//sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS +//sys Fsync(fd int) (err error) +//sys Futimes(fd int, tv []Timeval) (err error) = SYS_FUTIMES +//sys Futimesat(dirfd int, path string, tv []Timeval) (err error) = SYS___FUTIMESAT_A +//sys Ftruncate(fd int, length int64) (err error) +//sys Getrandom(buf []byte, flags int) (n int, err error) = SYS_GETRANDOM +//sys InotifyInit() (fd int, err error) = SYS_INOTIFY_INIT +//sys InotifyInit1(flags int) (fd int, err error) = SYS_INOTIFY_INIT1 +//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) = SYS___INOTIFY_ADD_WATCH_A +//sys InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) = SYS_INOTIFY_RM_WATCH +//sys Listxattr(path string, dest []byte) (sz int, err error) = SYS___LISTXATTR_A +//sys Llistxattr(path string, dest []byte) (sz int, err error) = SYS___LLISTXATTR_A +//sys Lremovexattr(path string, attr string) (err error) = SYS___LREMOVEXATTR_A +//sys Lutimes(path string, tv []Timeval) (err error) = SYS___LUTIMES_A +//sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT +//sys Msync(b []byte, flags int) (err error) = SYS_MSYNC +//sys Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) = SYS___CONSOLE2 + +// Pipe2 begin + +//go:nosplit +func getPipe2Addr() *(func([]int, int) error) + +var Pipe2 = pipe2Enter + +func pipe2Enter(p []int, flags int) (err error) { + if funcptrtest(GetZosLibVec()+SYS_PIPE2<<4, "") == 0 { + *getPipe2Addr() = pipe2Impl + } else { + *getPipe2Addr() = pipe2Error + } + return (*getPipe2Addr())(p, flags) +} + +func pipe2Impl(p []int, flags int) (err error) { + var pp [2]_C_int + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE2<<4, uintptr(unsafe.Pointer(&pp[0])), uintptr(flags)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } else { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return +} +func pipe2Error(p []int, flags int) (err error) { + return fmt.Errorf("Pipe2 is not available on this system") +} + +// Pipe2 end + +//sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL + +func Readdir(dir uintptr) (dirent *Dirent, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_A<<4, uintptr(dir)) + runtime.ExitSyscall() + dirent = (*Dirent)(unsafe.Pointer(r0)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//sys Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) = SYS___READDIR_R_A +//sys Statfs(path string, buf *Statfs_t) (err error) = SYS___STATFS_A +//sys Syncfs(fd int) (err error) = SYS_SYNCFS +//sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES +//sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT +//sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A + +//sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A +//sys unmount_LE(filesystem string, mtm int) (err error) = SYS___UMOUNT_A +//sys Chroot(path string) (err error) = SYS___CHROOT_A +//sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT +//sysnb Uname(buf *Utsname) (err error) = SYS_____OSNAME_A +//sys Unshare(flags int) (err error) = SYS_UNSHARE + +func Ptsname(fd int) (name string, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___PTSNAME_A<<4, uintptr(fd)) + runtime.ExitSyscall() + if r0 == 0 { + err = errnoErr2(e1, e2) + } else { + name = u2s(unsafe.Pointer(r0)) + } + return +} + +func u2s(cstr unsafe.Pointer) string { + str := (*[1024]uint8)(cstr) + i := 0 + for str[i] != 0 { + i++ + } + return string(str[:i]) +} + +func Close(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd)) + runtime.ExitSyscall() + for i := 0; e1 == EAGAIN && i < 10; i++ { + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_USLEEP<<4, uintptr(10)) + runtime.ExitSyscall() + runtime.EnterSyscall() + r0, e2, e1 = CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd)) + runtime.ExitSyscall() + } + if r0 != 0 { + err = errnoErr2(e1, e2) + } + return +} + +// Dummy function: there are no semantics for Madvise on z/OS +func Madvise(b []byte, advice int) (err error) { + return +} + +func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { + return mapper.Mmap(fd, offset, length, prot, flags) +} + +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) +} + +//sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A +//sysnb Getgid() (gid int) +//sysnb Getpid() (pid int) +//sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID + +func Getpgrp() (pid int) { + pid, _ = Getpgid(0) + return +} + +//sysnb Getppid() (pid int) +//sys Getpriority(which int, who int) (prio int, err error) +//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT + +//sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE + +func Getrusage(who int, rusage *Rusage) (err error) { + var ruz rusage_zos + err = getrusage(who, &ruz) + //Only the first two fields of Rusage are set + rusage.Utime.Sec = ruz.Utime.Sec + rusage.Utime.Usec = int64(ruz.Utime.Usec) + rusage.Stime.Sec = ruz.Stime.Sec + rusage.Stime.Usec = int64(ruz.Stime.Usec) + return +} + +//sys Getegid() (egid int) = SYS_GETEGID +//sys Geteuid() (euid int) = SYS_GETEUID +//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID +//sysnb Getuid() (uid int) +//sysnb Kill(pid int, sig Signal) (err error) +//sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A +//sys Link(path string, link string) (err error) = SYS___LINK_A +//sys Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) = SYS___LINKAT_A +//sys Listen(s int, n int) (err error) +//sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A + +func Lstat(path string, stat *Stat_t) (err error) { + var statLE Stat_LE_t + err = lstat(path, &statLE) + copyStat(stat, &statLE) + return +} + +// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/ +func isSpecialPath(path []byte) (v bool) { + var special = [4][8]byte{ + {'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'}, + {'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'}, + {'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'}, + {'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}} + + var i, j int + for i = 0; i < len(special); i++ { + for j = 0; j < len(special[i]); j++ { + if path[j] != special[i][j] { + break + } + } + if j == len(special[i]) { + return true + } + } + return false +} + +func realpath(srcpath string, abspath []byte) (pathlen int, errno int) { + var source [1024]byte + copy(source[:], srcpath) + source[len(srcpath)] = 0 + ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___REALPATH_A<<4, //__realpath_a() + []uintptr{uintptr(unsafe.Pointer(&source[0])), + uintptr(unsafe.Pointer(&abspath[0]))}) + if ret != 0 { + index := bytes.IndexByte(abspath[:], byte(0)) + if index != -1 { + return index, 0 + } + } else { + errptr := (*int)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) //__errno() + return 0, *errptr + } + return 0, 245 // EBADDATA 245 +} + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + n = int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___READLINK_A<<4, + []uintptr{uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))})) + runtime.KeepAlive(unsafe.Pointer(_p0)) + if n == -1 { + value := *(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) + err = errnoErr(Errno(value)) + } else { + if buf[0] == '$' { + if isSpecialPath(buf[1:9]) { + cnt, err1 := realpath(path, buf) + if err1 == 0 { + n = cnt + } + } + } + } + return +} + +func impl_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + return n, err + } else { + if buf[0] == '$' { + if isSpecialPath(buf[1:9]) { + cnt, err1 := realpath(path, buf) + if err1 == 0 { + n = cnt + } + } + } + } + return +} + +//go:nosplit +func get_ReadlinkatAddr() *(func(dirfd int, path string, buf []byte) (n int, err error)) + +var Readlinkat = enter_Readlinkat + +func enter_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + funcref := get_ReadlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___READLINKAT_A<<4, "") == 0 { + *funcref = impl_Readlinkat + } else { + *funcref = error_Readlinkat + } + return (*funcref)(dirfd, path, buf) +} + +func error_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +//sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A +//sys Mkdirat(dirfd int, path string, mode uint32) (err error) = SYS___MKDIRAT_A +//sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A +//sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A +//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) = SYS___MKNODAT_A +//sys PivotRoot(newroot string, oldroot string) (err error) = SYS___PIVOT_ROOT_A +//sys Pread(fd int, p []byte, offset int64) (n int, err error) +//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) = SYS___PRCTL_A +//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT +//sys Rename(from string, to string) (err error) = SYS___RENAME_A +//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) = SYS___RENAMEAT_A +//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) = SYS___RENAMEAT2_A +//sys Rmdir(path string) (err error) = SYS___RMDIR_A +//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK +//sys Setegid(egid int) (err error) = SYS_SETEGID +//sys Seteuid(euid int) (err error) = SYS_SETEUID +//sys Sethostname(p []byte) (err error) = SYS___SETHOSTNAME_A +//sys Setns(fd int, nstype int) (err error) = SYS_SETNS +//sys Setpriority(which int, who int, prio int) (err error) +//sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID +//sysnb Setrlimit(resource int, lim *Rlimit) (err error) +//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID +//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID +//sysnb Setsid() (pid int, err error) = SYS_SETSID +//sys Setuid(uid int) (err error) = SYS_SETUID +//sys Setgid(uid int) (err error) = SYS_SETGID +//sys Shutdown(fd int, how int) (err error) +//sys stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A + +func Stat(path string, sta *Stat_t) (err error) { + var statLE Stat_LE_t + err = stat(path, &statLE) + copyStat(sta, &statLE) + return +} + +//sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A +//sys Symlinkat(oldPath string, dirfd int, newPath string) (err error) = SYS___SYMLINKAT_A +//sys Sync() = SYS_SYNC +//sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A +//sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR +//sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR +//sys Umask(mask int) (oldmask int) +//sys Unlink(path string) (err error) = SYS___UNLINK_A +//sys Unlinkat(dirfd int, path string, flags int) (err error) = SYS___UNLINKAT_A +//sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A + +//sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A + +func Open(path string, mode int, perm uint32) (fd int, err error) { + if mode&O_ACCMODE == 0 { + mode |= O_RDONLY + } + return open(path, mode, perm) +} + +//sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) = SYS___OPENAT_A + +func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + if flags&O_ACCMODE == 0 { + flags |= O_RDONLY + } + return openat(dirfd, path, flags, mode) +} + +//sys openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) = SYS___OPENAT2_A + +func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) { + if how.Flags&O_ACCMODE == 0 { + how.Flags |= O_RDONLY + } + return openat2(dirfd, path, how, SizeofOpenHow) +} + +func ZosFdToPath(dirfd int) (path string, err error) { + var buffer [1024]byte + runtime.EnterSyscall() + ret, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_IOCTL<<4, uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))) + runtime.ExitSyscall() + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + CallLeFuncWithErr(GetZosLibVec()+SYS___E2A_L<<4, uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)) + return string(buffer[:zb]), nil + } + return "", errnoErr2(e1, e2) +} + +//sys remove(path string) (err error) + +func Remove(path string) error { + return remove(path) +} + +const ImplementsGetwd = true + +func Getcwd(buf []byte) (n int, err error) { + var p unsafe.Pointer + if len(buf) > 0 { + p = unsafe.Pointer(&buf[0]) + } else { + p = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___GETCWD_A<<4, uintptr(p), uintptr(len(buf))) + runtime.ExitSyscall() + n = clen(buf) + 1 + if r0 == 0 { + err = errnoErr2(e1, e2) + } + return +} + +func Getwd() (wd string, err error) { + var buf [PathMax]byte + n, err := Getcwd(buf[0:]) + if err != nil { + return "", err + } + // Getcwd returns the number of bytes written to buf, including the NUL. + if n < 1 || n > len(buf) || buf[n-1] != 0 { + return "", EINVAL + } + return string(buf[0 : n-1]), nil +} + +func Getgroups() (gids []int, err error) { + n, err := getgroups(0, nil) + if err != nil { + return nil, err + } + if n == 0 { + return nil, nil + } + + // Sanity check group count. Max is 1<<16 on Linux. + if n < 0 || n > 1<<20 { + return nil, EINVAL + } + + a := make([]_Gid_t, n) + n, err = getgroups(n, &a[0]) + if err != nil { + return nil, err + } + gids = make([]int, n) + for i, v := range a[0:n] { + gids[i] = int(v) + } + return +} + +func Setgroups(gids []int) (err error) { + if len(gids) == 0 { + return setgroups(0, nil) + } + + a := make([]_Gid_t, len(gids)) + for i, v := range gids { + a[i] = _Gid_t(v) + } + return setgroups(len(a), &a[0]) +} + +func gettid() uint64 + +func Gettid() (tid int) { + return int(gettid()) +} + +type WaitStatus uint32 + +// Wait status is 7 bits at bottom, either 0 (exited), +// 0x7F (stopped), or a signal number that caused an exit. +// The 0x80 bit is whether there was a core dump. +// An extra number (exit code, signal causing a stop) +// is in the high bits. At least that's the idea. +// There are various irregularities. For example, the +// "continued" status is 0xFFFF, distinguishing itself +// from stopped via the core dump bit. + +const ( + mask = 0x7F + core = 0x80 + exited = 0x00 + stopped = 0x7F + shift = 8 +) + +func (w WaitStatus) Exited() bool { return w&mask == exited } + +func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } + +func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } + +func (w WaitStatus) Continued() bool { return w == 0xFFFF } + +func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } + +func (w WaitStatus) ExitStatus() int { + if !w.Exited() { + return -1 + } + return int(w>>shift) & 0xFF +} + +func (w WaitStatus) Signal() Signal { + if !w.Signaled() { + return -1 + } + return Signal(w & mask) +} + +func (w WaitStatus) StopSignal() Signal { + if !w.Stopped() { + return -1 + } + return Signal(w>>shift) & 0xFF +} + +func (w WaitStatus) TrapCause() int { return -1 } + +//sys waitid(idType int, id int, info *Siginfo, options int) (err error) + +func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) { + return waitid(idType, id, info, options) +} + +//sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) + +func impl_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAIT4<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage))) + runtime.ExitSyscall() + wpid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Wait4Addr() *(func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)) + +var Wait4 = enter_Wait4 + +func enter_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + funcref := get_Wait4Addr() + if funcptrtest(GetZosLibVec()+SYS_WAIT4<<4, "") == 0 { + *funcref = impl_Wait4 + } else { + *funcref = legacyWait4 + } + return (*funcref)(pid, wstatus, options, rusage) +} + +func legacyWait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + // TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want. + // At the moment rusage will not be touched. + var status _C_int + wpid, err = waitpid(pid, &status, options) + if wstatus != nil { + *wstatus = WaitStatus(status) + } + return +} + +//sysnb gettimeofday(tv *timeval_zos) (err error) + +func Gettimeofday(tv *Timeval) (err error) { + var tvz timeval_zos + err = gettimeofday(&tvz) + tv.Sec = tvz.Sec + tv.Usec = int64(tvz.Usec) + return +} + +func Time(t *Time_t) (tt Time_t, err error) { + var tv Timeval + err = Gettimeofday(&tv) + if err != nil { + return 0, err + } + if t != nil { + *t = Time_t(tv.Sec) + } + return Time_t(tv.Sec), nil +} + +func setTimespec(sec, nsec int64) Timespec { + return Timespec{Sec: sec, Nsec: nsec} +} + +func setTimeval(sec, usec int64) Timeval { //fix + return Timeval{Sec: sec, Usec: usec} +} + +//sysnb pipe(p *[2]_C_int) (err error) + +func Pipe(p []int) (err error) { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + err = pipe(&pp) + p[0] = int(pp[0]) + p[1] = int(pp[1]) + return +} + +//sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A + +func Utimes(path string, tv []Timeval) (err error) { + if tv == nil { + return utimes(path, nil) + } + if len(tv) != 2 { + return EINVAL + } + return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) +} + +//sys utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) = SYS___UTIMENSAT_A + +func validUtimensat() bool { + if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___UTIMENSAT_A<<4); err == nil { + return name == "__utimensat_a" + } + } + return false +} + +// Begin UtimesNano + +//go:nosplit +func get_UtimesNanoAddr() *(func(path string, ts []Timespec) (err error)) + +var UtimesNano = enter_UtimesNano + +func enter_UtimesNano(path string, ts []Timespec) (err error) { + funcref := get_UtimesNanoAddr() + if validUtimensat() { + *funcref = utimesNanoImpl + } else { + *funcref = legacyUtimesNano + } + return (*funcref)(path, ts) +} + +func utimesNanoImpl(path string, ts []Timespec) (err error) { + if ts == nil { + return utimensat(AT_FDCWD, path, nil, 0) + } + if len(ts) != 2 { + return EINVAL + } + return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) +} + +func legacyUtimesNano(path string, ts []Timespec) (err error) { + if len(ts) != 2 { + return EINVAL + } + // Not as efficient as it could be because Timespec and + // Timeval have different types in the different OSes + tv := [2]Timeval{ + NsecToTimeval(TimespecToNsec(ts[0])), + NsecToTimeval(TimespecToNsec(ts[1])), + } + return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) +} + +// End UtimesNano + +// Begin UtimesNanoAt + +//go:nosplit +func get_UtimesNanoAtAddr() *(func(dirfd int, path string, ts []Timespec, flags int) (err error)) + +var UtimesNanoAt = enter_UtimesNanoAt + +func enter_UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) { + funcref := get_UtimesNanoAtAddr() + if validUtimensat() { + *funcref = utimesNanoAtImpl + } else { + *funcref = legacyUtimesNanoAt + } + return (*funcref)(dirfd, path, ts, flags) +} + +func utimesNanoAtImpl(dirfd int, path string, ts []Timespec, flags int) (err error) { + if ts == nil { + return utimensat(dirfd, path, nil, flags) + } + if len(ts) != 2 { + return EINVAL + } + return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) +} + +func legacyUtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) { + if path[0] != '/' { + dirPath, err := ZosFdToPath(dirfd) + if err != nil { + return err + } + path = dirPath + "/" + path + } + if flags == AT_SYMLINK_NOFOLLOW { + if len(ts) != 2 { + return EINVAL + } + + if ts[0].Nsec >= 5e8 { + ts[0].Sec++ + } + ts[0].Nsec = 0 + if ts[1].Nsec >= 5e8 { + ts[1].Sec++ + } + ts[1].Nsec = 0 + + // Not as efficient as it could be because Timespec and + // Timeval have different types in the different OSes + tv := []Timeval{ + NsecToTimeval(TimespecToNsec(ts[0])), + NsecToTimeval(TimespecToNsec(ts[1])), + } + return Lutimes(path, tv) + } + return UtimesNano(path, ts) +} + +// End UtimesNanoAt + +func Getsockname(fd int) (sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + if err = getsockname(fd, &rsa, &len); err != nil { + return + } + // TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS ) + return anyToSockaddr(0, &rsa) +} + +const ( + // identifier constants + nwmHeaderIdentifier = 0xd5e6d4c8 + nwmFilterIdentifier = 0xd5e6d4c6 + nwmTCPConnIdentifier = 0xd5e6d4c3 + nwmRecHeaderIdentifier = 0xd5e6d4d9 + nwmIPStatsIdentifier = 0xd5e6d4c9d7e2e340 + nwmIPGStatsIdentifier = 0xd5e6d4c9d7c7e2e3 + nwmTCPStatsIdentifier = 0xd5e6d4e3c3d7e2e3 + nwmUDPStatsIdentifier = 0xd5e6d4e4c4d7e2e3 + nwmICMPGStatsEntry = 0xd5e6d4c9c3d4d7c7 + nwmICMPTStatsEntry = 0xd5e6d4c9c3d4d7e3 + + // nwmHeader constants + nwmVersion1 = 1 + nwmVersion2 = 2 + nwmCurrentVer = 2 + + nwmTCPConnType = 1 + nwmGlobalStatsType = 14 + + // nwmFilter constants + nwmFilterLclAddrMask = 0x20000000 // Local address + nwmFilterSrcAddrMask = 0x20000000 // Source address + nwmFilterLclPortMask = 0x10000000 // Local port + nwmFilterSrcPortMask = 0x10000000 // Source port + + // nwmConnEntry constants + nwmTCPStateClosed = 1 + nwmTCPStateListen = 2 + nwmTCPStateSynSent = 3 + nwmTCPStateSynRcvd = 4 + nwmTCPStateEstab = 5 + nwmTCPStateFinWait1 = 6 + nwmTCPStateFinWait2 = 7 + nwmTCPStateClosWait = 8 + nwmTCPStateLastAck = 9 + nwmTCPStateClosing = 10 + nwmTCPStateTimeWait = 11 + nwmTCPStateDeletTCB = 12 + + // Existing constants on linux + BPF_TCP_CLOSE = 1 + BPF_TCP_LISTEN = 2 + BPF_TCP_SYN_SENT = 3 + BPF_TCP_SYN_RECV = 4 + BPF_TCP_ESTABLISHED = 5 + BPF_TCP_FIN_WAIT1 = 6 + BPF_TCP_FIN_WAIT2 = 7 + BPF_TCP_CLOSE_WAIT = 8 + BPF_TCP_LAST_ACK = 9 + BPF_TCP_CLOSING = 10 + BPF_TCP_TIME_WAIT = 11 + BPF_TCP_NEW_SYN_RECV = -1 + BPF_TCP_MAX_STATES = -2 +) + +type nwmTriplet struct { + offset uint32 + length uint32 + number uint32 +} + +type nwmQuadruplet struct { + offset uint32 + length uint32 + number uint32 + match uint32 +} + +type nwmHeader struct { + ident uint32 + length uint32 + version uint16 + nwmType uint16 + bytesNeeded uint32 + options uint32 + _ [16]byte + inputDesc nwmTriplet + outputDesc nwmQuadruplet +} + +type nwmFilter struct { + ident uint32 + flags uint32 + resourceName [8]byte + resourceId uint32 + listenerId uint32 + local [28]byte // union of sockaddr4 and sockaddr6 + remote [28]byte // union of sockaddr4 and sockaddr6 + _ uint16 + _ uint16 + asid uint16 + _ [2]byte + tnLuName [8]byte + tnMonGrp uint32 + tnAppl [8]byte + applData [40]byte + nInterface [16]byte + dVipa [16]byte + dVipaPfx uint16 + dVipaPort uint16 + dVipaFamily byte + _ [3]byte + destXCF [16]byte + destXCFPfx uint16 + destXCFFamily byte + _ [1]byte + targIP [16]byte + targIPPfx uint16 + targIPFamily byte + _ [1]byte + _ [20]byte +} + +type nwmRecHeader struct { + ident uint32 + length uint32 + number byte + _ [3]byte +} + +type nwmTCPStatsEntry struct { + ident uint64 + currEstab uint32 + activeOpened uint32 + passiveOpened uint32 + connClosed uint32 + estabResets uint32 + attemptFails uint32 + passiveDrops uint32 + timeWaitReused uint32 + inSegs uint64 + predictAck uint32 + predictData uint32 + inDupAck uint32 + inBadSum uint32 + inBadLen uint32 + inShort uint32 + inDiscOldTime uint32 + inAllBeforeWin uint32 + inSomeBeforeWin uint32 + inAllAfterWin uint32 + inSomeAfterWin uint32 + inOutOfOrder uint32 + inAfterClose uint32 + inWinProbes uint32 + inWinUpdates uint32 + outWinUpdates uint32 + outSegs uint64 + outDelayAcks uint32 + outRsts uint32 + retransSegs uint32 + retransTimeouts uint32 + retransDrops uint32 + pmtuRetrans uint32 + pmtuErrors uint32 + outWinProbes uint32 + probeDrops uint32 + keepAliveProbes uint32 + keepAliveDrops uint32 + finwait2Drops uint32 + acceptCount uint64 + inBulkQSegs uint64 + inDiscards uint64 + connFloods uint32 + connStalls uint32 + cfgEphemDef uint16 + ephemInUse uint16 + ephemHiWater uint16 + flags byte + _ [1]byte + ephemExhaust uint32 + smcRCurrEstabLnks uint32 + smcRLnkActTimeOut uint32 + smcRActLnkOpened uint32 + smcRPasLnkOpened uint32 + smcRLnksClosed uint32 + smcRCurrEstab uint32 + smcRActiveOpened uint32 + smcRPassiveOpened uint32 + smcRConnClosed uint32 + smcRInSegs uint64 + smcROutSegs uint64 + smcRInRsts uint32 + smcROutRsts uint32 + smcDCurrEstabLnks uint32 + smcDActLnkOpened uint32 + smcDPasLnkOpened uint32 + smcDLnksClosed uint32 + smcDCurrEstab uint32 + smcDActiveOpened uint32 + smcDPassiveOpened uint32 + smcDConnClosed uint32 + smcDInSegs uint64 + smcDOutSegs uint64 + smcDInRsts uint32 + smcDOutRsts uint32 +} + +type nwmConnEntry struct { + ident uint32 + local [28]byte // union of sockaddr4 and sockaddr6 + remote [28]byte // union of sockaddr4 and sockaddr6 + startTime [8]byte // uint64, changed to prevent padding from being inserted + lastActivity [8]byte // uint64 + bytesIn [8]byte // uint64 + bytesOut [8]byte // uint64 + inSegs [8]byte // uint64 + outSegs [8]byte // uint64 + state uint16 + activeOpen byte + flag01 byte + outBuffered uint32 + inBuffered uint32 + maxSndWnd uint32 + reXmtCount uint32 + congestionWnd uint32 + ssThresh uint32 + roundTripTime uint32 + roundTripVar uint32 + sendMSS uint32 + sndWnd uint32 + rcvBufSize uint32 + sndBufSize uint32 + outOfOrderCount uint32 + lcl0WindowCount uint32 + rmt0WindowCount uint32 + dupacks uint32 + flag02 byte + sockOpt6Cont byte + asid uint16 + resourceName [8]byte + resourceId uint32 + subtask uint32 + sockOpt byte + sockOpt6 byte + clusterConnFlag byte + proto byte + targetAppl [8]byte + luName [8]byte + clientUserId [8]byte + logMode [8]byte + timeStamp uint32 + timeStampAge uint32 + serverResourceId uint32 + intfName [16]byte + ttlsStatPol byte + ttlsStatConn byte + ttlsSSLProt uint16 + ttlsNegCiph [2]byte + ttlsSecType byte + ttlsFIPS140Mode byte + ttlsUserID [8]byte + applData [40]byte + inOldestTime [8]byte // uint64 + outOldestTime [8]byte // uint64 + tcpTrustedPartner byte + _ [3]byte + bulkDataIntfName [16]byte + ttlsNegCiph4 [4]byte + smcReason uint32 + lclSMCLinkId uint32 + rmtSMCLinkId uint32 + smcStatus byte + smcFlags byte + _ [2]byte + rcvWnd uint32 + lclSMCBufSz uint32 + rmtSMCBufSz uint32 + ttlsSessID [32]byte + ttlsSessIDLen int16 + _ [1]byte + smcDStatus byte + smcDReason uint32 +} + +var svcNameTable [][]byte = [][]byte{ + []byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4 +} + +const ( + svc_EZBNMIF4 = 0 +) + +func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) { + jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*" + responseBuffer := [4096]byte{0} + var bufferAlet, reasonCode uint32 = 0, 0 + var bufferLen, returnValue, returnCode int32 = 4096, 0, 0 + + dsa := [18]uint64{0} + var argv [7]unsafe.Pointer + argv[0] = unsafe.Pointer(&jobname[0]) + argv[1] = unsafe.Pointer(&responseBuffer[0]) + argv[2] = unsafe.Pointer(&bufferAlet) + argv[3] = unsafe.Pointer(&bufferLen) + argv[4] = unsafe.Pointer(&returnValue) + argv[5] = unsafe.Pointer(&returnCode) + argv[6] = unsafe.Pointer(&reasonCode) + + request := (*struct { + header nwmHeader + filter nwmFilter + })(unsafe.Pointer(&responseBuffer[0])) + + EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0]) + if EZBNMIF4 == nil { + return nil, errnoErr(EINVAL) + } + + // GetGlobalStats EZBNMIF4 call + request.header.ident = nwmHeaderIdentifier + request.header.length = uint32(unsafe.Sizeof(request.header)) + request.header.version = nwmCurrentVer + request.header.nwmType = nwmGlobalStatsType + request.header.options = 0x80000000 + + svcCall(EZBNMIF4, &argv[0], &dsa[0]) + + // outputDesc field is filled by EZBNMIF4 on success + if returnCode != 0 || request.header.outputDesc.offset == 0 { + return nil, errnoErr(EINVAL) + } + + // Check that EZBNMIF4 returned a nwmRecHeader + recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset])) + if recHeader.ident != nwmRecHeaderIdentifier { + return nil, errnoErr(EINVAL) + } + + // Parse nwmTriplets to get offsets of returned entries + var sections []*uint64 + var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0])) + for i := uint32(0); i < uint32(recHeader.number); i++ { + offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc)) + sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset])) + for j := uint32(0); j < sectionDesc.number; j++ { + offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length + sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset]))) + } + } + + // Find nwmTCPStatsEntry in returned entries + var tcpStats *nwmTCPStatsEntry = nil + for _, ptr := range sections { + switch *ptr { + case nwmTCPStatsIdentifier: + if tcpStats != nil { + return nil, errnoErr(EINVAL) + } + tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr)) + case nwmIPStatsIdentifier: + case nwmIPGStatsIdentifier: + case nwmUDPStatsIdentifier: + case nwmICMPGStatsEntry: + case nwmICMPTStatsEntry: + default: + return nil, errnoErr(EINVAL) + } + } + if tcpStats == nil { + return nil, errnoErr(EINVAL) + } + + // GetConnectionDetail EZBNMIF4 call + responseBuffer = [4096]byte{0} + dsa = [18]uint64{0} + bufferAlet, reasonCode = 0, 0 + bufferLen, returnValue, returnCode = 4096, 0, 0 + nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process + nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12))) + argv[0] = unsafe.Pointer(uintptr(*nameptr)) + + request.header.ident = nwmHeaderIdentifier + request.header.length = uint32(unsafe.Sizeof(request.header)) + request.header.version = nwmCurrentVer + request.header.nwmType = nwmTCPConnType + request.header.options = 0x80000000 + + request.filter.ident = nwmFilterIdentifier + + var localSockaddr RawSockaddrAny + socklen := _Socklen(SizeofSockaddrAny) + err := getsockname(fd, &localSockaddr, &socklen) + if err != nil { + return nil, errnoErr(EINVAL) + } + if localSockaddr.Addr.Family == AF_INET { + localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr)) + localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0])) + localSockFilter.Family = AF_INET + var i int + for i = 0; i < 4; i++ { + if localSockaddr.Addr[i] != 0 { + break + } + } + if i != 4 { + request.filter.flags |= nwmFilterLclAddrMask + for i = 0; i < 4; i++ { + localSockFilter.Addr[i] = localSockaddr.Addr[i] + } + } + if localSockaddr.Port != 0 { + request.filter.flags |= nwmFilterLclPortMask + localSockFilter.Port = localSockaddr.Port + } + } else if localSockaddr.Addr.Family == AF_INET6 { + localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr)) + localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0])) + localSockFilter.Family = AF_INET6 + var i int + for i = 0; i < 16; i++ { + if localSockaddr.Addr[i] != 0 { + break + } + } + if i != 16 { + request.filter.flags |= nwmFilterLclAddrMask + for i = 0; i < 16; i++ { + localSockFilter.Addr[i] = localSockaddr.Addr[i] + } + } + if localSockaddr.Port != 0 { + request.filter.flags |= nwmFilterLclPortMask + localSockFilter.Port = localSockaddr.Port + } + } + + svcCall(EZBNMIF4, &argv[0], &dsa[0]) + + // outputDesc field is filled by EZBNMIF4 on success + if returnCode != 0 || request.header.outputDesc.offset == 0 { + return nil, errnoErr(EINVAL) + } + + // Check that EZBNMIF4 returned a nwmConnEntry + conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset])) + if conn.ident != nwmTCPConnIdentifier { + return nil, errnoErr(EINVAL) + } + + // Copy data from the returned data structures into tcpInfo + // Stats from nwmConnEntry are specific to that connection. + // Stats from nwmTCPStatsEntry are global (to the interface?) + // Fields may not be an exact match. Some fields have no equivalent. + var tcpinfo TCPInfo + tcpinfo.State = uint8(conn.state) + tcpinfo.Ca_state = 0 // dummy + tcpinfo.Retransmits = uint8(tcpStats.retransSegs) + tcpinfo.Probes = uint8(tcpStats.outWinProbes) + tcpinfo.Backoff = 0 // dummy + tcpinfo.Options = 0 // dummy + tcpinfo.Rto = tcpStats.retransTimeouts + tcpinfo.Ato = tcpStats.outDelayAcks + tcpinfo.Snd_mss = conn.sendMSS + tcpinfo.Rcv_mss = conn.sendMSS // dummy + tcpinfo.Unacked = 0 // dummy + tcpinfo.Sacked = 0 // dummy + tcpinfo.Lost = 0 // dummy + tcpinfo.Retrans = conn.reXmtCount + tcpinfo.Fackets = 0 // dummy + tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0]))) + tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0]))) + tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0]))) + tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0]))) + tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate + tcpinfo.Rcv_ssthresh = conn.ssThresh + tcpinfo.Rtt = conn.roundTripTime + tcpinfo.Rttvar = conn.roundTripVar + tcpinfo.Snd_ssthresh = conn.ssThresh // dummy + tcpinfo.Snd_cwnd = conn.congestionWnd + tcpinfo.Advmss = conn.sendMSS // dummy + tcpinfo.Reordering = 0 // dummy + tcpinfo.Rcv_rtt = conn.roundTripTime // dummy + tcpinfo.Rcv_space = conn.sendMSS // dummy + tcpinfo.Total_retrans = conn.reXmtCount + + svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4) + + return &tcpinfo, nil +} + +// 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) { + buf := make([]byte, 256) + vallen := _Socklen(len(buf)) + err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen) + if err != nil { + return "", err + } + + return ByteSliceToString(buf[:vallen]), nil +} + +func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { + var msg Msghdr + var rsa RawSockaddrAny + msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Namelen = SizeofSockaddrAny + var iov Iovec + if len(p) > 0 { + iov.Base = (*byte)(unsafe.Pointer(&p[0])) + iov.SetLen(len(p)) + } + var dummy byte + if len(oob) > 0 { + // receive at least one normal byte + if len(p) == 0 { + iov.Base = &dummy + iov.SetLen(1) + } + msg.Control = (*byte)(unsafe.Pointer(&oob[0])) + msg.SetControllen(len(oob)) + } + msg.Iov = &iov + msg.Iovlen = 1 + if n, err = recvmsg(fd, &msg, flags); err != nil { + return + } + oobn = int(msg.Controllen) + recvflags = int(msg.Flags) + // source address is only specified if the socket is unconnected + if rsa.Addr.Family != AF_UNSPEC { + // TODO(neeilan): Remove 0 arg added to get this compiling on z/OS + from, err = anyToSockaddr(0, &rsa) + } + return +} + +func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { + _, err = SendmsgN(fd, p, oob, to, flags) + return +} + +func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + var err error + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } + } + var msg Msghdr + msg.Name = (*byte)(unsafe.Pointer(ptr)) + msg.Namelen = int32(salen) + var iov Iovec + if len(p) > 0 { + iov.Base = (*byte)(unsafe.Pointer(&p[0])) + iov.SetLen(len(p)) + } + var dummy byte + if len(oob) > 0 { + // send at least one normal byte + if len(p) == 0 { + iov.Base = &dummy + iov.SetLen(1) + } + msg.Control = (*byte)(unsafe.Pointer(&oob[0])) + msg.SetControllen(len(oob)) + } + msg.Iov = &iov + msg.Iovlen = 1 + if n, err = sendmsg(fd, &msg, flags); err != nil { + return 0, err + } + if len(oob) > 0 && len(p) == 0 { + n = 0 + } + return n, nil +} + +func Opendir(name string) (uintptr, error) { + p, err := BytePtrFromString(name) + if err != nil { + return 0, err + } + err = nil + runtime.EnterSyscall() + dir, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___OPENDIR_A<<4, uintptr(unsafe.Pointer(p))) + runtime.ExitSyscall() + runtime.KeepAlive(unsafe.Pointer(p)) + if dir == 0 { + err = errnoErr2(e1, e2) + } + return dir, err +} + +// clearsyscall.Errno resets the errno value to 0. +func clearErrno() + +func Closedir(dir uintptr) error { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSEDIR<<4, dir) + runtime.ExitSyscall() + if r0 != 0 { + return errnoErr2(e1, e2) + } + return nil +} + +func Seekdir(dir uintptr, pos int) { + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_SEEKDIR<<4, dir, uintptr(pos)) + runtime.ExitSyscall() +} + +func Telldir(dir uintptr) (int, error) { + p, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TELLDIR<<4, dir) + pos := int(p) + if int64(p) == -1 { + return pos, errnoErr2(e1, e2) + } + return pos, nil +} + +// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. +func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { + // struct flock is packed on z/OS. We can't emulate that in Go so + // instead we pack it here. + var flock [24]byte + *(*int16)(unsafe.Pointer(&flock[0])) = lk.Type + *(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence + *(*int64)(unsafe.Pointer(&flock[4])) = lk.Start + *(*int64)(unsafe.Pointer(&flock[12])) = lk.Len + *(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock))) + runtime.ExitSyscall() + lk.Type = *(*int16)(unsafe.Pointer(&flock[0])) + lk.Whence = *(*int16)(unsafe.Pointer(&flock[2])) + lk.Start = *(*int64)(unsafe.Pointer(&flock[4])) + lk.Len = *(*int64)(unsafe.Pointer(&flock[12])) + lk.Pid = *(*int32)(unsafe.Pointer(&flock[20])) + if r0 == 0 { + return nil + } + return errnoErr2(e1, e2) +} + +func impl_Flock(fd int, how int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FLOCK<<4, uintptr(fd), uintptr(how)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FlockAddr() *(func(fd int, how int) (err error)) + +var Flock = enter_Flock + +func validFlock(fp uintptr) bool { + if funcptrtest(GetZosLibVec()+SYS_FLOCK<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS_FLOCK<<4); err == nil { + return name == "flock" + } + } + return false +} + +func enter_Flock(fd int, how int) (err error) { + funcref := get_FlockAddr() + if validFlock(GetZosLibVec() + SYS_FLOCK<<4) { + *funcref = impl_Flock + } else { + *funcref = legacyFlock + } + return (*funcref)(fd, how) +} + +func legacyFlock(fd int, how int) error { + + var flock_type int16 + var fcntl_cmd int + + switch how { + case LOCK_SH | LOCK_NB: + flock_type = F_RDLCK + fcntl_cmd = F_SETLK + case LOCK_EX | LOCK_NB: + flock_type = F_WRLCK + fcntl_cmd = F_SETLK + case LOCK_EX: + flock_type = F_WRLCK + fcntl_cmd = F_SETLKW + case LOCK_UN: + flock_type = F_UNLCK + fcntl_cmd = F_SETLKW + default: + } + + flock := Flock_t{ + Type: int16(flock_type), + Whence: int16(0), + Start: int64(0), + Len: int64(0), + Pid: int32(Getppid()), + } + + err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock) + return err +} + +func Mlock(b []byte) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) + } + return +} + +func Mlock2(b []byte, flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) + } + return +} + +func Mlockall(flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) + } + return +} + +func Munlock(b []byte) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) + } + return +} + +func Munlockall() (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) + } + return +} + +func ClockGettime(clockid int32, ts *Timespec) error { + + var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise + var nsec_per_sec int64 = 1000000000 + + if ts == nil { + return EFAULT + } + if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC { + var nanotime int64 = runtime.Nanotime1() + ts.Sec = nanotime / nsec_per_sec + ts.Nsec = nanotime % nsec_per_sec + } else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID { + var tm Tms + _, err := Times(&tm) + if err != nil { + return EFAULT + } + ts.Sec = int64(tm.Utime / ticks_per_sec) + ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec) + } else { + return EINVAL + } + return nil +} + +// Chtag + +//go:nosplit +func get_ChtagAddr() *(func(path string, ccsid uint64, textbit uint64) error) + +var Chtag = enter_Chtag + +func enter_Chtag(path string, ccsid uint64, textbit uint64) error { + funcref := get_ChtagAddr() + if validSetxattr() { + *funcref = impl_Chtag + } else { + *funcref = legacy_Chtag + } + return (*funcref)(path, ccsid, textbit) +} + +func legacy_Chtag(path string, ccsid uint64, textbit uint64) error { + tag := ccsid<<16 | textbit<<15 + var tag_buff [8]byte + DecodeData(tag_buff[:], 8, tag) + return Setxattr(path, "filetag", tag_buff[:], XATTR_REPLACE) +} + +func impl_Chtag(path string, ccsid uint64, textbit uint64) error { + tag := ccsid<<16 | textbit<<15 + var tag_buff [4]byte + DecodeData(tag_buff[:], 4, tag) + return Setxattr(path, "system.filetag", tag_buff[:], XATTR_REPLACE) +} + +// End of Chtag + +// Nanosleep + +//go:nosplit +func get_NanosleepAddr() *(func(time *Timespec, leftover *Timespec) error) + +var Nanosleep = enter_Nanosleep + +func enter_Nanosleep(time *Timespec, leftover *Timespec) error { + funcref := get_NanosleepAddr() + if funcptrtest(GetZosLibVec()+SYS_NANOSLEEP<<4, "") == 0 { + *funcref = impl_Nanosleep + } else { + *funcref = legacyNanosleep + } + return (*funcref)(time, leftover) +} + +func impl_Nanosleep(time *Timespec, leftover *Timespec) error { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_NANOSLEEP<<4, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover))) + runtime.ExitSyscall() + if int64(r0) == -1 { + return errnoErr2(e1, e2) + } + return nil +} + +func legacyNanosleep(time *Timespec, leftover *Timespec) error { + t0 := runtime.Nanotime1() + var secrem uint32 + var nsecrem uint32 + total := time.Sec*1000000000 + time.Nsec + elapsed := runtime.Nanotime1() - t0 + var rv int32 + var rc int32 + var err error + // repeatedly sleep for 1 second until less than 1 second left + for total-elapsed > 1000000000 { + rv, rc, _ = BpxCondTimedWait(uint32(1), uint32(0), uint32(CW_CONDVAR), &secrem, &nsecrem) + if rv != 0 && rc != 112 { // 112 is EAGAIN + if leftover != nil && rc == 120 { // 120 is EINTR + leftover.Sec = int64(secrem) + leftover.Nsec = int64(nsecrem) + } + err = Errno(rc) + return err + } + elapsed = runtime.Nanotime1() - t0 + } + // sleep the remainder + if total > elapsed { + rv, rc, _ = BpxCondTimedWait(uint32(0), uint32(total-elapsed), uint32(CW_CONDVAR), &secrem, &nsecrem) + } + if leftover != nil && rc == 120 { + leftover.Sec = int64(secrem) + leftover.Nsec = int64(nsecrem) + } + if rv != 0 && rc != 112 { + err = Errno(rc) + } + return err +} + +// End of Nanosleep + +var ( + Stdin = 0 + Stdout = 1 + Stderr = 2 +) + +// Do the interface allocations only once for common +// Errno values. +var ( + errEAGAIN error = syscall.EAGAIN + errEINVAL error = syscall.EINVAL + errENOENT error = syscall.ENOENT +) + +var ZosTraceLevel int +var ZosTracefile *os.File + +var ( + signalNameMapOnce sync.Once + signalNameMap map[string]syscall.Signal +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e Errno) error { + switch e { + case 0: + return nil + case EAGAIN: + return errEAGAIN + case EINVAL: + return errEINVAL + case ENOENT: + return errENOENT + } + return e +} + +var reg *regexp.Regexp + +// enhanced with zos specific errno2 +func errnoErr2(e Errno, e2 uintptr) error { + switch e { + case 0: + return nil + case EAGAIN: + return errEAGAIN + /* + Allow the retrieval of errno2 for EINVAL and ENOENT on zos + case EINVAL: + return errEINVAL + case ENOENT: + return errENOENT + */ + } + if ZosTraceLevel > 0 { + var name string + if reg == nil { + reg = regexp.MustCompile("(^unix\\.[^/]+$|.*\\/unix\\.[^/]+$)") + } + i := 1 + pc, file, line, ok := runtime.Caller(i) + if ok { + name = runtime.FuncForPC(pc).Name() + } + for ok && reg.MatchString(runtime.FuncForPC(pc).Name()) { + i += 1 + pc, file, line, ok = runtime.Caller(i) + } + if ok { + if ZosTracefile == nil { + ZosConsolePrintf("From %s:%d\n", file, line) + ZosConsolePrintf("%s: %s (errno2=0x%x)\n", name, e.Error(), e2) + } else { + fmt.Fprintf(ZosTracefile, "From %s:%d\n", file, line) + fmt.Fprintf(ZosTracefile, "%s: %s (errno2=0x%x)\n", name, e.Error(), e2) + } + } else { + if ZosTracefile == nil { + ZosConsolePrintf("%s (errno2=0x%x)\n", e.Error(), e2) + } else { + fmt.Fprintf(ZosTracefile, "%s (errno2=0x%x)\n", e.Error(), e2) + } + } + } + return e +} + +// ErrnoName returns the error name for error number e. +func ErrnoName(e Errno) string { + i := sort.Search(len(errorList), func(i int) bool { + return errorList[i].num >= e + }) + if i < len(errorList) && errorList[i].num == e { + return errorList[i].name + } + return "" +} + +// SignalName returns the signal name for signal number s. +func SignalName(s syscall.Signal) string { + i := sort.Search(len(signalList), func(i int) bool { + return signalList[i].num >= s + }) + if i < len(signalList) && signalList[i].num == s { + return signalList[i].name + } + return "" +} + +// SignalNum returns the syscall.Signal for signal named s, +// or 0 if a signal with such name is not found. +// The signal name should start with "SIG". +func SignalNum(s string) syscall.Signal { + signalNameMapOnce.Do(func() { + signalNameMap = make(map[string]syscall.Signal, len(signalList)) + for _, signal := range signalList { + signalNameMap[signal.name] = signal.num + } + }) + return signalNameMap[s] +} + +// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. +func clen(n []byte) int { + i := bytes.IndexByte(n, 0) + if i == -1 { + i = len(n) + } + return i +} + +// Mmap manager, for use by operating system-specific implementations. + +type mmapper struct { + sync.Mutex + active map[*byte][]byte // active mappings; key is last byte in mapping + mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) + munmap func(addr uintptr, length uintptr) error +} + +func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { + if length <= 0 { + return nil, EINVAL + } + + // Set __MAP_64 by default + flags |= __MAP_64 + + // Map the requested memory. + addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) + if errno != nil { + return nil, errno + } + + // Slice memory layout + var sl = struct { + addr uintptr + len int + cap int + }{addr, length, length} + + // Use unsafe to turn sl into a []byte. + b := *(*[]byte)(unsafe.Pointer(&sl)) + + // Register mapping in m and return it. + p := &b[cap(b)-1] + m.Lock() + defer m.Unlock() + m.active[p] = b + return b, nil +} + +func (m *mmapper) Munmap(data []byte) (err error) { + if len(data) == 0 || len(data) != cap(data) { + return EINVAL + } + + // Find the base of the mapping. + p := &data[cap(data)-1] + m.Lock() + defer m.Unlock() + b := m.active[p] + if b == nil || &b[0] != &data[0] { + return EINVAL + } + + // Unmap the memory and update m. + if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { + return errno + } + delete(m.active, p) + return nil +} + +func Read(fd int, p []byte) (n int, err error) { + n, err = read(fd, p) + if raceenabled { + if n > 0 { + raceWriteRange(unsafe.Pointer(&p[0]), n) + } + if err == nil { + raceAcquire(unsafe.Pointer(&ioSync)) + } + } + return +} + +func Write(fd int, p []byte) (n int, err error) { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = write(fd, p) + if raceenabled && n > 0 { + raceReadRange(unsafe.Pointer(&p[0]), n) + } + return +} + +// For testing: clients can set this flag to force +// creation of IPv6 sockets to return EAFNOSUPPORT. +var SocketDisableIPv6 bool + +// Sockaddr represents a socket address. +type Sockaddr interface { + sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs +} + +// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets. +type SockaddrInet4 struct { + Port int + Addr [4]byte + raw RawSockaddrInet4 +} + +// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets. +type SockaddrInet6 struct { + Port int + ZoneId uint32 + Addr [16]byte + raw RawSockaddrInet6 +} + +// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets. +type SockaddrUnix struct { + Name string + raw RawSockaddrUnix +} + +func Bind(fd int, sa Sockaddr) (err error) { + ptr, n, err := sa.sockaddr() + if err != nil { + return err + } + return bind(fd, ptr, n) +} + +func Connect(fd int, sa Sockaddr) (err error) { + ptr, n, err := sa.sockaddr() + if err != nil { + return err + } + return connect(fd, ptr, n) +} + +func Getpeername(fd int) (sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + if err = getpeername(fd, &rsa, &len); err != nil { + return + } + return anyToSockaddr(fd, &rsa) +} + +func GetsockoptByte(fd, level, opt int) (value byte, err error) { + var n byte + vallen := _Socklen(1) + err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) + return n, err +} + +func GetsockoptInt(fd, level, opt int) (value int, err error) { + var n int32 + vallen := _Socklen(4) + err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) + return int(n), err +} + +func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { + vallen := _Socklen(4) + err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + return value, err +} + +func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { + var value IPMreq + vallen := _Socklen(SizeofIPMreq) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) + return &value, err +} + +func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { + var value IPv6Mreq + vallen := _Socklen(SizeofIPv6Mreq) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) + return &value, err +} + +func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { + var value IPv6MTUInfo + vallen := _Socklen(SizeofIPv6MTUInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) + return &value, err +} + +func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { + var value ICMPv6Filter + vallen := _Socklen(SizeofICMPv6Filter) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) + return &value, err +} + +func GetsockoptLinger(fd, level, opt int) (*Linger, error) { + var linger Linger + vallen := _Socklen(SizeofLinger) + err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen) + return &linger, err +} + +func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) { + var tv Timeval + vallen := _Socklen(unsafe.Sizeof(tv)) + err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen) + return &tv, err +} + +func GetsockoptUint64(fd, level, opt int) (value uint64, err error) { + var n uint64 + vallen := _Socklen(8) + err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) + return n, err +} + +func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { + return + } + if rsa.Addr.Family != AF_UNSPEC { + from, err = anyToSockaddr(fd, &rsa) + } + return +} + +func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { + ptr, n, err := to.sockaddr() + if err != nil { + return err + } + return sendto(fd, p, flags, ptr, n) +} + +func SetsockoptByte(fd, level, opt int, value byte) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) +} + +func SetsockoptInt(fd, level, opt int, value int) (err error) { + var n = int32(value) + return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4) +} + +func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) +} + +func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) +} + +func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) +} + +func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { + return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) +} + +func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) +} + +func SetsockoptString(fd, level, opt int, s string) (err error) { + var p unsafe.Pointer + if len(s) > 0 { + p = unsafe.Pointer(&[]byte(s)[0]) + } + return setsockopt(fd, level, opt, p, uintptr(len(s))) +} + +func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) +} + +func SetsockoptUint64(fd, level, opt int, value uint64) (err error) { + return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8) +} + +func Socket(domain, typ, proto int) (fd int, err error) { + if domain == AF_INET6 && SocketDisableIPv6 { + return -1, EAFNOSUPPORT + } + fd, err = socket(domain, typ, proto) + return +} + +func Socketpair(domain, typ, proto int) (fd [2]int, err error) { + var fdx [2]int32 + err = socketpair(domain, typ, proto, &fdx) + if err == nil { + fd[0] = int(fdx[0]) + fd[1] = int(fdx[1]) + } + return +} + +var ioSync int64 + +func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } + +func SetNonblock(fd int, nonblocking bool) (err error) { + flag, err := fcntl(fd, F_GETFL, 0) + if err != nil { + return err + } + if nonblocking { + flag |= O_NONBLOCK + } else { + flag &= ^O_NONBLOCK + } + _, err = fcntl(fd, F_SETFL, flag) + return err +} + +// Exec calls execve(2), which replaces the calling executable in the process +// tree. argv0 should be the full path to an executable ("/bin/ls") and the +// executable name should also be the first argument in argv (["ls", "-l"]). +// envv are the environment variables that should be passed to the new +// process (["USER=go", "PWD=/tmp"]). +func Exec(argv0 string, argv []string, envv []string) error { + return syscall.Exec(argv0, argv, envv) +} + +func Getag(path string) (ccsid uint16, flag uint16, err error) { + var val [8]byte + sz, err := Getxattr(path, "ccsid", val[:]) + if err != nil { + return + } + ccsid = uint16(EncodeData(val[0:sz])) + sz, err = Getxattr(path, "flags", val[:]) + if err != nil { + return + } + flag = uint16(EncodeData(val[0:sz]) >> 15) + return +} + +// Mount begin +func impl_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(source) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(target) + if err != nil { + return + } + var _p2 *byte + _p2, err = BytePtrFromString(fstype) + if err != nil { + return + } + var _p3 *byte + _p3, err = BytePtrFromString(data) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT1_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(_p3))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MountAddr() *(func(source string, target string, fstype string, flags uintptr, data string) (err error)) + +var Mount = enter_Mount + +func enter_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { + funcref := get_MountAddr() + if validMount() { + *funcref = impl_Mount + } else { + *funcref = legacyMount + } + return (*funcref)(source, target, fstype, flags, data) +} + +func legacyMount(source string, target string, fstype string, flags uintptr, data string) (err error) { + if needspace := 8 - len(fstype); needspace <= 0 { + fstype = fstype[0:8] + } else { + fstype += " "[0:needspace] + } + return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data) +} + +func validMount() bool { + if funcptrtest(GetZosLibVec()+SYS___MOUNT1_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___MOUNT1_A<<4); err == nil { + return name == "__mount1_a" + } + } + return false +} + +// Mount end + +// Unmount begin +func impl_Unmount(target string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(target) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT2_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnmountAddr() *(func(target string, flags int) (err error)) + +var Unmount = enter_Unmount + +func enter_Unmount(target string, flags int) (err error) { + funcref := get_UnmountAddr() + if funcptrtest(GetZosLibVec()+SYS___UMOUNT2_A<<4, "") == 0 { + *funcref = impl_Unmount + } else { + *funcref = legacyUnmount + } + return (*funcref)(target, flags) +} + +func legacyUnmount(name string, mtm int) (err error) { + // mountpoint is always a full path and starts with a '/' + // check if input string is not a mountpoint but a filesystem name + if name[0] != '/' { + return unmount_LE(name, mtm) + } + // treat name as mountpoint + b2s := func(arr []byte) string { + var str string + for i := 0; i < len(arr); i++ { + if arr[i] == 0 { + str = string(arr[:i]) + break + } + } + return str + } + var buffer struct { + header W_Mnth + fsinfo [64]W_Mntent + } + fs_count, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) + if err == nil { + err = EINVAL + for i := 0; i < fs_count; i++ { + if b2s(buffer.fsinfo[i].Mountpoint[:]) == name { + err = unmount_LE(b2s(buffer.fsinfo[i].Fsname[:]), mtm) + break + } + } + } else if fs_count == 0 { + err = EINVAL + } + return err +} + +// Unmount end + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false + } + return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true +} + +func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) { + var d Dirent + + d.Ino = uint64(dirent.Ino) + offset, err := Telldir(dir) + if err != nil { + return d, err + } + + d.Off = int64(offset) + s := string(bytes.Split(dirent.Name[:], []byte{0})[0]) + copy(d.Name[:], s) + + d.Reclen = uint16(24 + len(d.NameString())) + var st Stat_t + path = path + "/" + s + err = Lstat(path, &st) + if err != nil { + return d, err + } + + d.Type = uint8(st.Mode >> 24) + return d, err +} + +func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { + // Simulation of Getdirentries port from the Darwin implementation. + // COMMENTS FROM DARWIN: + // It's not the full required semantics, but should handle the case + // of calling Getdirentries or ReadDirent repeatedly. + // It won't handle assigning the results of lseek to *basep, or handle + // the directory being edited underfoot. + + skip, err := Seek(fd, 0, 1 /* SEEK_CUR */) + if err != nil { + return 0, err + } + + // Get path from fd to avoid unavailable call (fdopendir) + path, err := ZosFdToPath(fd) + if err != nil { + return 0, err + } + d, err := Opendir(path) + if err != nil { + return 0, err + } + defer Closedir(d) + + var cnt int64 + for { + var entryLE direntLE + var entrypLE *direntLE + e := Readdir_r(d, &entryLE, &entrypLE) + if e != nil { + return n, e + } + if entrypLE == nil { + break + } + if skip > 0 { + skip-- + cnt++ + continue + } + + // Dirent on zos has a different structure + entry, e := direntLeToDirentUnix(&entryLE, d, path) + if e != nil { + return n, e + } + + reclen := int(entry.Reclen) + if reclen > len(buf) { + // Not enough room. Return for now. + // The counter will let us know where we should start up again. + // Note: this strategy for suspending in the middle and + // restarting is O(n^2) in the length of the directory. Oh well. + break + } + + // Copy entry into return buffer. + s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen) + copy(buf, s) + + buf = buf[reclen:] + n += reclen + cnt++ + } + // Set the seek offset of the input fd to record + // how many files we've already returned. + _, err = Seek(fd, cnt, 0 /* SEEK_SET */) + if err != nil { + return n, err + } + + return n, nil +} + +func Err2ad() (eadd *int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4) + eadd = (*int)(unsafe.Pointer(r0)) + return +} + +func ZosConsolePrintf(format string, v ...interface{}) (int, error) { + type __cmsg struct { + _ uint16 + _ [2]uint8 + __msg_length uint32 + __msg uintptr + _ [4]uint8 + } + msg := fmt.Sprintf(format, v...) + strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data) + len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len + cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)} + cmd := uint32(0) + runtime.EnterSyscall() + rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd))) + runtime.ExitSyscall() + if rc != 0 { + return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) + } + return 0, nil +} +func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) { + if nullterm { + ebcdicBytes = []byte(str + "\x00") + } else { + ebcdicBytes = []byte(str) + } + A2e(ebcdicBytes) + return +} +func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) { + res := make([]byte, len(b)) + copy(res, b) + E2a(res) + if trimRight { + str = string(bytes.TrimRight(res, " \x00")) + } else { + str = string(res) + } + return +} + +func fdToPath(dirfd int) (path string, err error) { + var buffer [1024]byte + // w_ctrl() + ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, + []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + // __e2a_l() + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, + []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) + return string(buffer[:zb]), nil + } + // __errno() + errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, + []uintptr{})))) + // __errno2() + errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, + []uintptr{})) + // strerror_r() + ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, + []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) + } else { + return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) + } +} + +func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error)) + +var Mkfifoat = enter_Mkfifoat + +func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + funcref := get_MkfifoatAddr() + if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 { + *funcref = impl_Mkfifoat + } else { + *funcref = legacy_Mkfifoat + } + return (*funcref)(dirfd, path, mode) +} + +func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + dirname, err := ZosFdToPath(dirfd) + if err != nil { + return err + } + return Mkfifo(dirname+"/"+path, mode) +} + +//sys Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT +//sys Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT +//sys Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT + +func fcntlAsIs(fd uintptr, cmd int, arg uintptr) (val int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg) + runtime.ExitSyscall() + val = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +func Fcntl(fd uintptr, cmd int, op interface{}) (ret int, err error) { + switch op.(type) { + case *Flock_t: + err = FcntlFlock(fd, cmd, op.(*Flock_t)) + if err != nil { + ret = -1 + } + return + case int: + return FcntlInt(fd, cmd, op.(int)) + case *F_cnvrt: + return fcntlAsIs(fd, cmd, uintptr(unsafe.Pointer(op.(*F_cnvrt)))) + case unsafe.Pointer: + return fcntlAsIs(fd, cmd, uintptr(op.(unsafe.Pointer))) + default: + return -1, EINVAL + } + return +} + +func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + return sendfile(outfd, infd, offset, count) +} + +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + // TODO: use LE call instead if the call is implemented + originalOffset, err := Seek(infd, 0, SEEK_CUR) + if err != nil { + return -1, err + } + //start reading data from in_fd + if offset != nil { + _, err := Seek(infd, *offset, SEEK_SET) + if err != nil { + return -1, err + } + } + + buf := make([]byte, count) + readBuf := make([]byte, 0) + var n int = 0 + for i := 0; i < count; i += n { + n, err := Read(infd, buf) + if n == 0 { + if err != nil { + return -1, err + } else { // EOF + break + } + } + readBuf = append(readBuf, buf...) + buf = buf[0:0] + } + + n2, err := Write(outfd, readBuf) + if err != nil { + return -1, err + } + + //When sendfile() returns, this variable will be set to the + // offset of the byte following the last byte that was read. + if offset != nil { + *offset = *offset + int64(n) + // If offset is not NULL, then sendfile() does not modify the file + // offset of in_fd + _, err := Seek(infd, originalOffset, SEEK_SET) + if err != nil { + return -1, err + } + } + return n2, nil +} diff --git a/vendor/golang.org/x/sys/unix/sysvshm_linux.go b/vendor/golang.org/x/sys/unix/sysvshm_linux.go new file mode 100644 index 0000000..4fcd38d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sysvshm_linux.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux + +package unix + +import "runtime" + +// SysvShmCtl performs control operations on the shared memory segment +// specified by id. +func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) { + if runtime.GOARCH == "arm" || + runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" { + cmd |= ipc_64 + } + + return shmctl(id, cmd, desc) +} diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/vendor/golang.org/x/sys/unix/sysvshm_unix.go new file mode 100644 index 0000000..672d6b0 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -0,0 +1,51 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin && !ios) || linux || zos + +package unix + +import "unsafe" + +// SysvShmAttach attaches the Sysv shared memory segment associated with the +// shared memory identifier id. +func SysvShmAttach(id int, addr uintptr, flag int) ([]byte, error) { + addr, errno := shmat(id, addr, flag) + if errno != nil { + return nil, errno + } + + // Retrieve the size of the shared memory to enable slice creation + var info SysvShmDesc + + _, err := SysvShmCtl(id, IPC_STAT, &info) + if err != nil { + // release the shared memory if we can't find the size + + // ignoring error from shmdt as there's nothing sensible to return here + shmdt(addr) + return nil, err + } + + // Use unsafe to convert addr into a []byte. + b := unsafe.Slice((*byte)(unsafe.Pointer(addr)), int(info.Segsz)) + return b, nil +} + +// SysvShmDetach unmaps the shared memory slice returned from SysvShmAttach. +// +// It is not safe to use the slice after calling this function. +func SysvShmDetach(data []byte) error { + if len(data) == 0 { + return EINVAL + } + + return shmdt(uintptr(unsafe.Pointer(&data[0]))) +} + +// SysvShmGet returns the Sysv shared memory identifier associated with key. +// If the IPC_CREAT flag is specified a new segment is created. +func SysvShmGet(key, size, flag int) (id int, err error) { + return shmget(key, size, flag) +} diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go new file mode 100644 index 0000000..8b7977a --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin && !ios) || zos + +package unix + +// SysvShmCtl performs control operations on the shared memory segment +// specified by id. +func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) { + return shmctl(id, cmd, desc) +} diff --git a/vendor/golang.org/x/sys/unix/timestruct.go b/vendor/golang.org/x/sys/unix/timestruct.go index 4a672f5..7997b19 100644 --- a/vendor/golang.org/x/sys/unix/timestruct.go +++ b/vendor/golang.org/x/sys/unix/timestruct.go @@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos package unix import "time" -// TimespecToNsec converts a Timespec value into a number of -// nanoseconds since the Unix epoch. -func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } +// TimespecToNsec returns the time stored in ts as nanoseconds. +func TimespecToNsec(ts Timespec) int64 { return ts.Nano() } -// NsecToTimespec takes a number of nanoseconds since the Unix epoch -// and returns the corresponding Timespec value. +// NsecToTimespec converts a number of nanoseconds into a Timespec. func NsecToTimespec(nsec int64) Timespec { sec := nsec / 1e9 nsec = nsec % 1e9 @@ -42,12 +40,10 @@ func TimeToTimespec(t time.Time) (Timespec, error) { return ts, nil } -// TimevalToNsec converts a Timeval value into a number of nanoseconds -// since the Unix epoch. -func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 } +// TimevalToNsec returns the time stored in tv as nanoseconds. +func TimevalToNsec(tv Timeval) int64 { return tv.Nano() } -// NsecToTimeval takes a number of nanoseconds since the Unix epoch -// and returns the corresponding Timeval value. +// NsecToTimeval converts a number of nanoseconds into a Timeval. func NsecToTimeval(nsec int64) Timeval { nsec += 999 // round up to microsecond usec := nsec % 1e9 / 1e3 @@ -59,24 +55,22 @@ func NsecToTimeval(nsec int64) Timeval { return setTimeval(sec, usec) } -// Unix returns ts as the number of seconds and nanoseconds elapsed since the -// Unix epoch. +// Unix returns the time stored in ts as seconds plus nanoseconds. func (ts *Timespec) Unix() (sec int64, nsec int64) { return int64(ts.Sec), int64(ts.Nsec) } -// Unix returns tv as the number of seconds and nanoseconds elapsed since the -// Unix epoch. +// Unix returns the time stored in tv as seconds plus nanoseconds. func (tv *Timeval) Unix() (sec int64, nsec int64) { return int64(tv.Sec), int64(tv.Usec) * 1000 } -// Nano returns ts as the number of nanoseconds elapsed since the Unix epoch. +// Nano returns the time stored in ts as nanoseconds. func (ts *Timespec) Nano() int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } -// Nano returns tv as the number of nanoseconds elapsed since the Unix epoch. +// Nano returns the time stored in tv as nanoseconds. func (tv *Timeval) Nano() int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 } diff --git a/vendor/golang.org/x/sys/unix/unveil_openbsd.go b/vendor/golang.org/x/sys/unix/unveil_openbsd.go index 168d5ae..cb7e598 100644 --- a/vendor/golang.org/x/sys/unix/unveil_openbsd.go +++ b/vendor/golang.org/x/sys/unix/unveil_openbsd.go @@ -4,39 +4,48 @@ package unix -import ( - "syscall" - "unsafe" -) +import "fmt" // Unveil implements the unveil syscall. // For more information see unveil(2). // Note that the special case of blocking further // unveil calls is handled by UnveilBlock. func Unveil(path string, flags string) error { - pathPtr, err := syscall.BytePtrFromString(path) - if err != nil { + if err := supportsUnveil(); err != nil { return err } - flagsPtr, err := syscall.BytePtrFromString(flags) + pathPtr, err := BytePtrFromString(path) if err != nil { return err } - _, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(unsafe.Pointer(pathPtr)), uintptr(unsafe.Pointer(flagsPtr)), 0) - if e != 0 { - return e + flagsPtr, err := BytePtrFromString(flags) + if err != nil { + return err } - return nil + return unveil(pathPtr, flagsPtr) } // UnveilBlock blocks future unveil calls. // For more information see unveil(2). func UnveilBlock() error { - // Both pointers must be nil. - var pathUnsafe, flagsUnsafe unsafe.Pointer - _, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(pathUnsafe), uintptr(flagsUnsafe), 0) - if e != 0 { - return e + if err := supportsUnveil(); err != nil { + return err } + return unveil(nil, nil) +} + +// supportsUnveil checks for availability of the unveil(2) system call based +// on the running OpenBSD version. +func supportsUnveil() error { + maj, min, err := majmin() + if err != nil { + return err + } + + // unveil is not available before 6.4 + if maj < 6 || (maj == 6 && min <= 3) { + return fmt.Errorf("cannot call Unveil on OpenBSD %d.%d", maj, min) + } + return nil } diff --git a/vendor/golang.org/x/sys/unix/vgetrandom_linux.go b/vendor/golang.org/x/sys/unix/vgetrandom_linux.go new file mode 100644 index 0000000..07ac8e0 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/vgetrandom_linux.go @@ -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) diff --git a/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go b/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go new file mode 100644 index 0000000..297e97b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go @@ -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 +} diff --git a/vendor/golang.org/x/sys/unix/xattr_bsd.go b/vendor/golang.org/x/sys/unix/xattr_bsd.go index 30c1d71..e168793 100644 --- a/vendor/golang.org/x/sys/unix/xattr_bsd.go +++ b/vendor/golang.org/x/sys/unix/xattr_bsd.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd netbsd +//go:build freebsd || netbsd package unix @@ -35,9 +35,14 @@ func xattrnamespace(fullattr string) (ns int, attr string, err error) { func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) { if len(dest) > idx { return unsafe.Pointer(&dest[idx]) - } else { - return unsafe.Pointer(_zero) } + if dest != nil { + // extattr_get_file and extattr_list_file treat NULL differently from + // a non-NULL pointer of length zero. Preserve the property of nilness, + // even if we can't use dest directly. + return unsafe.Pointer(&_zero) + } + return nil } // FreeBSD and NetBSD implement their own syscalls to handle extended attributes @@ -159,13 +164,12 @@ func Lremovexattr(link string, attr string) (err error) { } func Listxattr(file string, dest []byte) (sz int, err error) { - d := initxattrdest(dest, 0) destsiz := len(dest) // FreeBSD won't allow you to list xattrs from multiple namespaces - s := 0 + s, pos := 0, 0 for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} { - stmp, e := ExtattrListFile(file, nsid, uintptr(d), destsiz) + stmp, e := ListxattrNS(file, nsid, dest[pos:]) /* Errors accessing system attrs are ignored so that * we can implement the Linux-like behavior of omitting errors that @@ -174,66 +178,102 @@ func Listxattr(file string, dest []byte) (sz int, err error) { * Linux will still error if we ask for user attributes on a file that * we don't have read permissions on, so don't ignore those errors */ - if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER { - continue - } else if e != nil { + if e != nil { + if e == EPERM && nsid != EXTATTR_NAMESPACE_USER { + continue + } return s, e } s += stmp - destsiz -= s - if destsiz < 0 { - destsiz = 0 + pos = s + if pos > destsiz { + pos = destsiz } - d = initxattrdest(dest, s) } return s, nil } -func Flistxattr(fd int, dest []byte) (sz int, err error) { +func ListxattrNS(file string, nsid int, dest []byte) (sz int, err error) { d := initxattrdest(dest, 0) destsiz := len(dest) - s := 0 + s, e := ExtattrListFile(file, nsid, uintptr(d), destsiz) + if e != nil { + return 0, err + } + + return s, nil +} + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + destsiz := len(dest) + + s, pos := 0, 0 for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} { - stmp, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz) - if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER { - continue - } else if e != nil { + stmp, e := FlistxattrNS(fd, nsid, dest[pos:]) + + if e != nil { + if e == EPERM && nsid != EXTATTR_NAMESPACE_USER { + continue + } return s, e } s += stmp - destsiz -= s - if destsiz < 0 { - destsiz = 0 + pos = s + if pos > destsiz { + pos = destsiz } - d = initxattrdest(dest, s) } return s, nil } -func Llistxattr(link string, dest []byte) (sz int, err error) { +func FlistxattrNS(fd int, nsid int, dest []byte) (sz int, err error) { d := initxattrdest(dest, 0) destsiz := len(dest) - s := 0 + s, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz) + if e != nil { + return 0, err + } + + return s, nil +} + +func Llistxattr(link string, dest []byte) (sz int, err error) { + destsiz := len(dest) + + s, pos := 0, 0 for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} { - stmp, e := ExtattrListLink(link, nsid, uintptr(d), destsiz) - if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER { - continue - } else if e != nil { + stmp, e := LlistxattrNS(link, nsid, dest[pos:]) + + if e != nil { + if e == EPERM && nsid != EXTATTR_NAMESPACE_USER { + continue + } return s, e } s += stmp - destsiz -= s - if destsiz < 0 { - destsiz = 0 + pos = s + if pos > destsiz { + pos = destsiz } - d = initxattrdest(dest, s) + } + + return s, nil +} + +func LlistxattrNS(link string, nsid int, dest []byte) (sz int, err error) { + d := initxattrdest(dest, 0) + destsiz := len(dest) + + s, e := ExtattrListLink(link, nsid, uintptr(d), destsiz) + if e != nil { + return 0, err } return s, nil diff --git a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go index 104994b..2fb219d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go @@ -1,7 +1,7 @@ // mkerrors.sh -maix32 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc,aix +//go:build ppc && aix // Created by cgo -godefs - DO NOT EDIT // cgo -godefs -- -maix32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go index 4fc8d30..b0e6f5c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go @@ -1,7 +1,7 @@ // mkerrors.sh -maix64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64,aix +//go:build ppc64 && aix // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -maix64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index e3ff2ee..d73c465 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,darwin +//go:build amd64 && darwin // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -11,1475 +11,1613 @@ package unix import "syscall" const ( - AF_APPLETALK = 0x10 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1c - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1e - AF_IPX = 0x17 - AF_ISDN = 0x1c - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x28 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 - AF_NS = 0x6 - AF_OSI = 0x7 - AF_PPP = 0x22 - AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 - AF_ROUTE = 0x11 - AF_SIP = 0x18 - AF_SNA = 0xb - AF_SYSTEM = 0x20 - AF_UNIX = 0x1 - AF_UNSPEC = 0x0 - AF_UTUN = 0x26 - ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x41c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff - B0 = 0x0 - B110 = 0x6e - B115200 = 0x1c200 - B1200 = 0x4b0 - B134 = 0x86 - B14400 = 0x3840 - B150 = 0x96 - B1800 = 0x708 - B19200 = 0x4b00 - B200 = 0xc8 - B230400 = 0x38400 - B2400 = 0x960 - B28800 = 0x7080 - B300 = 0x12c - B38400 = 0x9600 - B4800 = 0x12c0 - B50 = 0x32 - B57600 = 0xe100 - B600 = 0x258 - B7200 = 0x1c20 - B75 = 0x4b - B76800 = 0x12c00 - B9600 = 0x2580 - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 - BIOCGETIF = 0x4020426b - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCPROMISC = 0x20004269 - BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e - BIOCSETIF = 0x8020426c - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0x0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0x0 - BPF_IND = 0x40 - BPF_JA = 0x0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0x0 - BPF_LD = 0x0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0x0 - BPF_TXA = 0x80 - BPF_W = 0x0 - BPF_X = 0x8 - BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 - CFLUSH = 0xf - CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 - CREAD = 0x800 - CRTSCTS = 0x30000 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - CTL_HW = 0x6 - CTL_KERN = 0x1 - CTL_MAXNAME = 0xc - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0xf5 - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 - DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 - DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - ECHO = 0x8 - ECHOCTL = 0x40 - ECHOE = 0x2 - ECHOK = 0x4 - ECHOKE = 0x1 - ECHONL = 0x10 - ECHOPRT = 0x20 - EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xf - EVFILT_THREADMARKER = 0xf - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 - EXTA = 0x4b00 - EXTB = 0x9600 - EXTPROC = 0x800 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 - FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 - F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a - F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e - F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d - F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0x8 - F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 - F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 - F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 - F_WRLCK = 0x3 - HUPCL = 0x4000 - HW_MACHINE = 0x1 - ICANON = 0x100 - ICMP6_FILTER = 0x12 - ICRNL = 0x100 - IEXTEN = 0x400 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_DEBUG = 0x4 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PROMISC = 0x100 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IFT_1822 = 0x2 - IFT_AAL5 = 0x31 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ATM = 0x25 - IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff - IFT_CEPT = 0x13 - IFT_DS3 = 0x1e - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_ETHER = 0x6 - IFT_FAITH = 0x38 - IFT_FDDI = 0xf - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 - IFT_HDH1822 = 0x3 - IFT_HIPPI = 0x2f - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88026 = 0xa - IFT_L2VLAN = 0x87 - IFT_LAPB = 0x10 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_NSIP = 0x1b - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PDP = 0xff - IFT_PFLOG = 0xf5 - IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe - IFT_PPP = 0x17 - IFT_PROPMUX = 0x36 - IFT_PROPVIRTUAL = 0x35 - IFT_PTPSERIAL = 0x16 - IFT_RS232 = 0x21 - IFT_SDLC = 0x11 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_STARLAN = 0xb - IFT_STF = 0x39 - IFT_T1 = 0x12 - IFT_ULTRA = 0x1d - IFT_V35 = 0x2d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0x0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0x0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x300 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0x0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_RECVTCLASS = 0x23 - IPV6_RTHDR_LOOSE = 0x0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0x0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 - IPV6_UNICAST_HOPS = 0x4 - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 - IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 - IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0x0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a - IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 - IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - KERN_HOSTNAME = 0xa - KERN_OSRELEASE = 0x2 - KERN_OSTYPE = 0x1 - KERN_VERSION = 0x4 - LOCK_EX = 0x2 - LOCK_NB = 0x4 - LOCK_SH = 0x1 - LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 - MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 - MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa - MADV_RANDOM = 0x1 - MADV_SEQUENTIAL = 0x2 - MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 - MAP_ANON = 0x1000 - MAP_ANONYMOUS = 0x1000 - MAP_COPY = 0x2 - MAP_FILE = 0x0 - MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 - MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 - MAP_SHARED = 0x1 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 - MNT_EXPORTED = 0x100 - MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 - MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 - MNT_NODEV = 0x10 - MNT_NOEXEC = 0x4 - MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 - MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 - MNT_QUOTA = 0x2000 - MNT_RDONLY = 0x1 - MNT_RELOAD = 0x40000 - MNT_ROOTFS = 0x4000 - MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 - MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0x17f0f5ff - MNT_WAIT = 0x1 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 - MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 - NAME_MAX = 0xff - NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 - NET_RT_FLAGS = 0x2 - NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xa - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 - NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 - NOFLSH = 0x80000000 - NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 - NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 - NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 - NOTE_DELETE = 0x1 - NOTE_EXEC = 0x20000000 - NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 - NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 - NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 - NOTE_LINK = 0x10 - NOTE_LOWAT = 0x1 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 - NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 - NOTE_RENAME = 0x20 - NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 - NOTE_TRACK = 0x1 - NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 - NOTE_WRITE = 0x2 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - OXTABS = 0x4 - O_ACCMODE = 0x3 - O_ALERT = 0x20000000 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 - O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 - O_EXCL = 0x800 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x20000 - O_NOFOLLOW = 0x100 - O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 - O_RDONLY = 0x0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_WRONLY = 0x1 - PARENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - PENDIN = 0x20000000 - PRIO_PGRP = 0x1 - PRIO_PROCESS = 0x0 - PRIO_USER = 0x2 - PROT_EXEC = 0x4 - PROT_NONE = 0x0 - PROT_READ = 0x1 - PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 - RLIMIT_CORE = 0x4 - RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 - RLIMIT_DATA = 0x2 - RLIMIT_FSIZE = 0x1 - RLIMIT_MEMLOCK = 0x6 - RLIMIT_NOFILE = 0x8 - RLIMIT_NPROC = 0x7 - RLIMIT_RSS = 0x5 - RLIMIT_STACK = 0x3 - RLIM_INFINITY = 0x7fffffffffffffff - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0x0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DELCLONE = 0x80 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_GATEWAY = 0x2 - RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 - RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 - RTF_STATIC = 0x800 - RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_GET2 = 0x14 - RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RUSAGE_CHILDREN = -0x1 - RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 - SHUT_RD = 0x0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIOCADDMULTI = 0x80206931 - SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 - SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 - SIOCDELMULTI = 0x80206932 - SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 - SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 - SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 - SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 - SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 - SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 - TCIFLUSH = 0x1 - TCIOFF = 0x3 - TCIOFLUSH = 0x3 - TCION = 0x4 - TCOFLUSH = 0x2 - TCOOFF = 0x1 - TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 - TCSAFLUSH = 0x2 - TIOCCBRK = 0x2000747a - TIOCCDTR = 0x20007478 - TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 - TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 - TIOCEXCL = 0x2000740d - TIOCEXT = 0x80047460 - TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 - TIOCGETD = 0x4004741a - TIOCGPGRP = 0x40047477 - TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 - TIOCMBIC = 0x8004746b - TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a - TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b - TIOCMSET = 0x8004746d - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_DTR = 0x2 - TIOCM_LE = 0x1 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_RTS = 0x4 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x20007471 - TIOCNXCL = 0x2000740e - TIOCOUTQ = 0x40047473 - TIOCPKT = 0x80047470 - TIOCPKT_DATA = 0x0 - TIOCPKT_DOSTOP = 0x20 - TIOCPKT_FLUSHREAD = 0x1 - TIOCPKT_FLUSHWRITE = 0x2 - TIOCPKT_IOCTL = 0x40 - TIOCPKT_NOSTOP = 0x10 - TIOCPKT_START = 0x8 - TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 - TIOCREMOTE = 0x80047469 - TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 - TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 - TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 - TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f - TIOCSPGRP = 0x80047476 - TIOCSTART = 0x2000746e - TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 - TIOCSTOP = 0x2000746f - TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 - TIOCUCNTL = 0x80047466 - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 - VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - VWERASE = 0x4 - WCONTINUED = 0x10 - WCOREFLAG = 0x80 - WEXITED = 0x4 - WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 - WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + AF_APPLETALK = 0x10 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1c + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1e + AF_IPX = 0x17 + AF_ISDN = 0x1c + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x29 + AF_NATM = 0x1f + AF_NDRV = 0x1b + AF_NETBIOS = 0x21 + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PPP = 0x22 + AF_PUP = 0x4 + AF_RESERVED_36 = 0x24 + AF_ROUTE = 0x11 + AF_SIP = 0x18 + AF_SNA = 0xb + AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_UTUN = 0x26 + AF_VSOCK = 0x28 + ALTWERASE = 0x200 + ATTR_BIT_MAP_COUNT = 0x5 + ATTR_CMN_ACCESSMASK = 0x20000 + ATTR_CMN_ACCTIME = 0x1000 + ATTR_CMN_ADDEDTIME = 0x10000000 + ATTR_CMN_BKUPTIME = 0x2000 + ATTR_CMN_CHGTIME = 0x800 + ATTR_CMN_CRTIME = 0x200 + ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 + ATTR_CMN_DEVID = 0x2 + ATTR_CMN_DOCUMENT_ID = 0x100000 + ATTR_CMN_ERROR = 0x20000000 + ATTR_CMN_EXTENDED_SECURITY = 0x400000 + ATTR_CMN_FILEID = 0x2000000 + ATTR_CMN_FLAGS = 0x40000 + ATTR_CMN_FNDRINFO = 0x4000 + ATTR_CMN_FSID = 0x4 + ATTR_CMN_FULLPATH = 0x8000000 + ATTR_CMN_GEN_COUNT = 0x80000 + ATTR_CMN_GRPID = 0x10000 + ATTR_CMN_GRPUUID = 0x1000000 + ATTR_CMN_MODTIME = 0x400 + ATTR_CMN_NAME = 0x1 + ATTR_CMN_NAMEDATTRCOUNT = 0x80000 + ATTR_CMN_NAMEDATTRLIST = 0x100000 + ATTR_CMN_OBJID = 0x20 + ATTR_CMN_OBJPERMANENTID = 0x40 + ATTR_CMN_OBJTAG = 0x10 + ATTR_CMN_OBJTYPE = 0x8 + ATTR_CMN_OWNERID = 0x8000 + ATTR_CMN_PARENTID = 0x4000000 + ATTR_CMN_PAROBJID = 0x80 + ATTR_CMN_RETURNED_ATTRS = 0x80000000 + ATTR_CMN_SCRIPT = 0x100 + ATTR_CMN_SETMASK = 0x51c7ff00 + ATTR_CMN_USERACCESS = 0x200000 + ATTR_CMN_UUID = 0x800000 + ATTR_CMN_VALIDMASK = 0xffffffff + ATTR_CMN_VOLSETMASK = 0x6700 + ATTR_FILE_ALLOCSIZE = 0x4 + ATTR_FILE_CLUMPSIZE = 0x10 + ATTR_FILE_DATAALLOCSIZE = 0x400 + ATTR_FILE_DATAEXTENTS = 0x800 + ATTR_FILE_DATALENGTH = 0x200 + ATTR_FILE_DEVTYPE = 0x20 + ATTR_FILE_FILETYPE = 0x40 + ATTR_FILE_FORKCOUNT = 0x80 + ATTR_FILE_FORKLIST = 0x100 + ATTR_FILE_IOBLOCKSIZE = 0x8 + ATTR_FILE_LINKCOUNT = 0x1 + ATTR_FILE_RSRCALLOCSIZE = 0x2000 + ATTR_FILE_RSRCEXTENTS = 0x4000 + ATTR_FILE_RSRCLENGTH = 0x1000 + ATTR_FILE_SETMASK = 0x20 + ATTR_FILE_TOTALSIZE = 0x2 + ATTR_FILE_VALIDMASK = 0x37ff + ATTR_VOL_ALLOCATIONCLUMP = 0x40 + ATTR_VOL_ATTRIBUTES = 0x40000000 + ATTR_VOL_CAPABILITIES = 0x20000 + ATTR_VOL_DIRCOUNT = 0x400 + ATTR_VOL_ENCODINGSUSED = 0x10000 + ATTR_VOL_FILECOUNT = 0x200 + ATTR_VOL_FSTYPE = 0x1 + ATTR_VOL_INFO = 0x80000000 + ATTR_VOL_IOBLOCKSIZE = 0x80 + ATTR_VOL_MAXOBJCOUNT = 0x800 + ATTR_VOL_MINALLOCATION = 0x20 + ATTR_VOL_MOUNTEDDEVICE = 0x8000 + ATTR_VOL_MOUNTFLAGS = 0x4000 + ATTR_VOL_MOUNTPOINT = 0x1000 + ATTR_VOL_NAME = 0x2000 + ATTR_VOL_OBJCOUNT = 0x100 + ATTR_VOL_QUOTA_SIZE = 0x10000000 + ATTR_VOL_RESERVED_SIZE = 0x20000000 + ATTR_VOL_SETMASK = 0x80002000 + ATTR_VOL_SIGNATURE = 0x2 + ATTR_VOL_SIZE = 0x4 + ATTR_VOL_SPACEAVAIL = 0x10 + ATTR_VOL_SPACEFREE = 0x8 + ATTR_VOL_SPACEUSED = 0x800000 + ATTR_VOL_UUID = 0x40000 + ATTR_VOL_VALIDMASK = 0xf087ffff + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc00c4279 + BIOCGETIF = 0x4020426b + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDLT = 0x80044278 + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x8010427e + BIOCSETIF = 0x8020426c + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + BS0 = 0x0 + BS1 = 0x8000 + BSDLY = 0x8000 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_MONOTONIC = 0x6 + CLOCK_MONOTONIC_RAW = 0x4 + CLOCK_MONOTONIC_RAW_APPROX = 0x5 + CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x10 + CLOCK_UPTIME_RAW = 0x8 + 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 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x10a + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NULL = 0x0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_DARWIN = 0x10a + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WIHART = 0xdf + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EVFILT_AIO = -0x3 + EVFILT_EXCEPT = -0xf + EVFILT_FS = -0x9 + EVFILT_MACHPORT = -0x8 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x11 + EVFILT_THREADMARKER = 0x11 + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xa + EVFILT_VM = -0xc + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DISPATCH2 = 0x180 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG0 = 0x1000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_OOBAND = 0x2000 + EV_POLL = 0x1000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EV_UDATA_SPECIFIC = 0x100 + EV_VANISHED = 0x200 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FF0 = 0x0 + FF1 = 0x4000 + FFDLY = 0x4000 + FLUSHO = 0x800000 + FSOPT_ATTR_CMN_EXTENDED = 0x20 + FSOPT_NOFOLLOW = 0x1 + FSOPT_NOINMEMUPDATE = 0x2 + FSOPT_PACK_INVAL_ATTRS = 0x8 + FSOPT_REPORT_FULLSIZE = 0x4 + FSOPT_RETURN_REALDEV = 0x200 + F_ADDFILESIGS = 0x3d + F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 + F_ADDFILESIGS_INFO = 0x67 + F_ADDFILESIGS_RETURN = 0x61 + F_ADDFILESUPPL = 0x68 + F_ADDSIGS = 0x3b + F_ALLOCATEALL = 0x4 + F_ALLOCATECONTIG = 0x2 + F_BARRIERFSYNC = 0x55 + F_CHECK_LV = 0x62 + F_CHKCLEAN = 0x29 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x43 + F_FINDSIGS = 0x4e + F_FLUSH_DATA = 0x28 + F_FREEZE_FS = 0x35 + F_FULLFSYNC = 0x33 + F_GETCODEDIR = 0x48 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETLKPID = 0x42 + F_GETNOSIGPIPE = 0x4a + F_GETOWN = 0x5 + F_GETPATH = 0x32 + F_GETPATH_MTMINFO = 0x47 + F_GETPATH_NOFIRMLINK = 0x66 + F_GETPROTECTIONCLASS = 0x3f + F_GETPROTECTIONLEVEL = 0x4d + F_GETSIGSINFO = 0x69 + F_GLOBAL_NOCACHE = 0x37 + F_LOG2PHYS = 0x31 + F_LOG2PHYS_EXT = 0x41 + F_NOCACHE = 0x30 + F_NODIRECT = 0x3e + F_OK = 0x0 + F_PATHPKG_CHECK = 0x34 + F_PEOFPOSMODE = 0x3 + F_PREALLOCATE = 0x2a + F_PUNCHHOLE = 0x63 + F_RDADVISE = 0x2c + F_RDAHEAD = 0x2d + F_RDLCK = 0x1 + F_SETBACKINGSTORE = 0x46 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETLKWTIMEOUT = 0xa + F_SETNOSIGPIPE = 0x49 + F_SETOWN = 0x6 + F_SETPROTECTIONCLASS = 0x40 + F_SETSIZE = 0x2b + F_SINGLE_WRITER = 0x4c + F_SPECULATIVE_READ = 0x65 + F_THAW_FS = 0x36 + F_TRANSCODEKEY = 0x4b + F_TRIM_ACTIVE_FILE = 0x64 + F_UNLCK = 0x2 + F_VOLPOSMODE = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOTRAILERS = 0x20 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_6LOWPAN = 0x40 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CELLULAR = 0xff + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PKTAP = 0xfe + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LINKLOCALNETNUM = 0xa9fe0000 + IN_LOOPBACKNET = 0x7f + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x400473d1 + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0xfe + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_2292DSTOPTS = 0x17 + IPV6_2292HOPLIMIT = 0x14 + IPV6_2292HOPOPTS = 0x16 + IPV6_2292NEXTHOP = 0x15 + IPV6_2292PKTINFO = 0x13 + IPV6_2292PKTOPTIONS = 0x19 + IPV6_2292RTHDR = 0x18 + IPV6_3542DSTOPTS = 0x32 + IPV6_3542HOPLIMIT = 0x2f + IPV6_3542HOPOPTS = 0x31 + IPV6_3542NEXTHOP = 0x30 + IPV6_3542PKTINFO = 0x2e + IPV6_3542RTHDR = 0x33 + IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 + IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 + IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDV6ONLY = 0x1b + IPV6_BOUND_IF = 0x7d + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOW_ECN_MASK = 0x3000 + IPV6_FRAGTTL = 0x3c + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x3d + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x23 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x39 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x24 + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BLOCK_SOURCE = 0x48 + IP_BOUND_IF = 0x19 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x1c + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW_ADD = 0x28 + IP_FW_DEL = 0x29 + IP_FW_FLUSH = 0x2a + IP_FW_GET = 0x2c + IP_FW_RESETLOG = 0x2d + IP_FW_ZERO = 0x2b + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_IFINDEX = 0x42 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_NAT__XXX = 0x37 + IP_OFFMASK = 0x1fff + IP_OLD_FW_ADD = 0x32 + IP_OLD_FW_DEL = 0x33 + IP_OLD_FW_FLUSH = 0x34 + IP_OLD_FW_GET = 0x36 + IP_OLD_FW_RESETLOG = 0x38 + IP_OLD_FW_ZERO = 0x35 + IP_OPTIONS = 0x1 + IP_PKTINFO = 0x1a + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVPKTINFO = 0x1a + IP_RECVRETOPTS = 0x6 + IP_RECVTOS = 0x1b + IP_RECVTTL = 0x18 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_STRIPHDR = 0x17 + IP_TOS = 0x3 + IP_TRAFFIC_MGT_BACKGROUND = 0x41 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + ISIG = 0x80 + ISTRIP = 0x20 + IUTF8 = 0x4000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_PEERCRED = 0x1 + LOCAL_PEEREPID = 0x3 + LOCAL_PEEREUUID = 0x5 + LOCAL_PEERPID = 0x2 + LOCAL_PEERTOKEN = 0x6 + LOCAL_PEERUUID = 0x4 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_CAN_REUSE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_FREE_REUSABLE = 0x7 + MADV_FREE_REUSE = 0x8 + MADV_NORMAL = 0x0 + MADV_PAGEOUT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MADV_ZERO_WIRED_PAGES = 0x6 + MAP_32BIT = 0x8000 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_HASSEMAPHORE = 0x200 + MAP_JIT = 0x800 + MAP_NOCACHE = 0x400 + MAP_NOEXTEND = 0x100 + MAP_NORESERVE = 0x40 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x20 + MAP_RESERVED0080 = 0x80 + MAP_RESILIENT_CODESIGN = 0x2000 + MAP_RESILIENT_MEDIA = 0x4000 + MAP_SHARED = 0x1 + MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 + MAP_UNIX03 = 0x40000 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x400000 + MNT_CMDFLAGS = 0xf0000 + MNT_CPROTECT = 0x80 + MNT_DEFWRITE = 0x2000000 + MNT_DONTBROWSE = 0x100000 + MNT_DOVOLFS = 0x8000 + MNT_DWAIT = 0x4 + MNT_EXPORTED = 0x100 + MNT_EXT_ROOT_DATA_VOL = 0x1 + MNT_FORCE = 0x80000 + MNT_IGNORE_OWNERSHIP = 0x200000 + MNT_JOURNALED = 0x800000 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NOATIME = 0x10000000 + MNT_NOBLOCK = 0x20000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOSUID = 0x8 + MNT_NOUSERXATTR = 0x1000000 + MNT_NOWAIT = 0x2 + MNT_QUARANTINE = 0x400 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_REMOVABLE = 0x200 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x40000000 + MNT_STRICTATIME = 0x80000000 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNKNOWNPERMISSIONS = 0x200000 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0xd7f0f7ff + MNT_WAIT = 0x1 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_FLUSH = 0x400 + MSG_HAVEMORE = 0x2000 + MSG_HOLD = 0x800 + MSG_NEEDSA = 0x10000 + MSG_NOSIGNAL = 0x80000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_RCVMORE = 0x4000 + MSG_SEND = 0x1000 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITSTREAM = 0x200 + MS_ASYNC = 0x1 + MS_DEACTIVATE = 0x8 + MS_INVALIDATE = 0x2 + MS_KILLPAGES = 0x4 + MS_SYNC = 0x10 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_DUMP2 = 0x7 + NET_RT_FLAGS = 0x2 + NET_RT_FLAGS_PRIV = 0xa + NET_RT_IFLIST = 0x3 + NET_RT_IFLIST2 = 0x6 + NET_RT_MAXID = 0xb + NET_RT_STAT = 0x4 + NET_RT_TRASH = 0x5 + NFDBITS = 0x20 + NL0 = 0x0 + NL1 = 0x100 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSOLUTE = 0x8 + NOTE_ATTRIB = 0x8 + NOTE_BACKGROUND = 0x40 + NOTE_CHILD = 0x4 + NOTE_CRITICAL = 0x20 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXITSTATUS = 0x4000000 + NOTE_EXIT_CSERROR = 0x40000 + NOTE_EXIT_DECRYPTFAIL = 0x10000 + NOTE_EXIT_DETAIL = 0x2000000 + NOTE_EXIT_DETAIL_MASK = 0x70000 + NOTE_EXIT_MEMORY = 0x20000 + NOTE_EXIT_REPARENTED = 0x80000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FORK = 0x40000000 + NOTE_FUNLOCK = 0x100 + NOTE_LEEWAY = 0x10 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MACHTIME = 0x100 + NOTE_MACH_CONTINUOUS_TIME = 0x80 + NOTE_NONE = 0x80 + NOTE_NSECONDS = 0x4 + NOTE_OOB = 0x2 + NOTE_PCTRLMASK = -0x100000 + NOTE_PDATAMASK = 0xfffff + NOTE_REAP = 0x10000000 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_SIGNAL = 0x8000000 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x2 + NOTE_VM_ERROR = 0x10000000 + NOTE_VM_PRESSURE = 0x80000000 + NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 + NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OFDEL = 0x20000 + OFILL = 0x80 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_ALERT = 0x20000000 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x1000000 + O_CREAT = 0x200 + O_DIRECTORY = 0x100000 + O_DP_GETRAWENCRYPTED = 0x1 + O_DP_GETRAWUNENCRYPTED = 0x2 + O_DSYNC = 0x400000 + O_EVTONLY = 0x8000 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x20000 + O_NOFOLLOW = 0x100 + O_NOFOLLOW_ANY = 0x20000000 + O_NONBLOCK = 0x4 + O_POPUP = 0x80000000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYMLINK = 0x200000 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PT_ATTACH = 0xa + PT_ATTACHEXC = 0xe + PT_CONTINUE = 0x7 + PT_DENY_ATTACH = 0x1f + PT_DETACH = 0xb + PT_FIRSTMACH = 0x20 + PT_FORCEQUOTA = 0x1e + PT_KILL = 0x8 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_READ_U = 0x3 + PT_SIGEXC = 0xc + PT_STEP = 0x9 + PT_THUPDATE = 0xd + PT_TRACE_ME = 0x0 + 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 + RLIMIT_CPU_USAGE_MONITOR = 0x2 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CLONING = 0x100 + RTF_CONDEMNED = 0x2000000 + RTF_DEAD = 0x20000000 + RTF_DELCLONE = 0x80 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 + RTF_HOST = 0x4 + RTF_IFREF = 0x4000000 + RTF_IFSCOPE = 0x1000000 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_NOIFREF = 0x2000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_PROXY = 0x8000000 + RTF_REJECT = 0x8 + RTF_ROUTER = 0x10000000 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_WASCLONED = 0x20000 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_GET2 = 0x14 + RTM_IFINFO = 0xe + RTM_IFINFO2 = 0x12 + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_NEWMADDR2 = 0x13 + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + 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 + SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 + SF_APPEND = 0x40000 + SF_ARCHIVED = 0x10000 + SF_DATALESS = 0x40000000 + SF_FIRMLINK = 0x800000 + SF_IMMUTABLE = 0x20000 + SF_NOUNLINK = 0x100000 + SF_RESTRICTED = 0x80000 + SF_SETTABLE = 0x3fff0000 + SF_SUPPORTED = 0x9f0000 + SF_SYNTHETIC = 0xc0000000 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCARPIPLL = 0xc0206928 + SIOCATMARK = 0x40047307 + SIOCAUTOADDR = 0xc0206926 + SIOCAUTONETMASK = 0x80206927 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFPHYADDR = 0x80206941 + SIOCGDRVSPEC = 0xc028697b + SIOCGETVLAN = 0xc020697f + SIOCGHIWAT = 0x40047301 + SIOCGIF6LOWPAN = 0xc02069c5 + SIOCGIFADDR = 0xc0206921 + SIOCGIFALTMTU = 0xc0206948 + SIOCGIFASYNCMAP = 0xc020697c + SIOCGIFBOND = 0xc0206947 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020695b + SIOCGIFCONF = 0xc00c6924 + SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFFUNCTIONALTYPE = 0xc02069ad + SIOCGIFGENERIC = 0xc020693a + SIOCGIFKPI = 0xc0206987 + SIOCGIFMAC = 0xc0206982 + SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206940 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc020693f + SIOCGIFSTATUS = 0xc331693d + SIOCGIFVLAN = 0xc020697f + SIOCGIFWAKEFLAGS = 0xc0206988 + SIOCGIFXMEDIA = 0xc02c6948 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCIFCREATE = 0xc0206978 + SIOCIFCREATE2 = 0xc020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106981 + SIOCRSLVMULTI = 0xc010693b + SIOCSDRVSPEC = 0x8028697b + SIOCSETVLAN = 0x8020697e + SIOCSHIWAT = 0x80047300 + SIOCSIF6LOWPAN = 0x802069c4 + SIOCSIFADDR = 0x8020690c + SIOCSIFALTMTU = 0x80206945 + SIOCSIFASYNCMAP = 0x8020697d + SIOCSIFBOND = 0x80206946 + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020695a + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFKPI = 0x80206986 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206983 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x8040693e + SIOCSIFPHYS = 0x80206936 + SIOCSIFVLAN = 0x8020697e + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_DONTTRUNC = 0x2000 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1010 + SO_LINGER = 0x80 + SO_LINGER_SEC = 0x1080 + SO_NETSVC_MARKING_LEVEL = 0x1119 + SO_NET_SERVICE_TYPE = 0x1116 + SO_NKE = 0x1021 + SO_NOADDRERR = 0x1023 + SO_NOSIGPIPE = 0x1022 + SO_NOTIFYCONFLICT = 0x1026 + SO_NP_EXTENSIONS = 0x1083 + SO_NREAD = 0x1020 + SO_NUMRCVPKT = 0x1112 + SO_NWRITE = 0x1024 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1011 + SO_RANDOMPORT = 0x1082 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSESHAREUID = 0x1025 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TIMESTAMP_MONOTONIC = 0x800 + SO_TRACKER_ATTRIBUTE_FLAGS_APP_APPROVED = 0x1 + SO_TRACKER_ATTRIBUTE_FLAGS_DOMAIN_SHORT = 0x4 + SO_TRACKER_ATTRIBUTE_FLAGS_TRACKER = 0x2 + SO_TRACKER_TRANSPARENCY_VERSION = 0x3 + SO_TYPE = 0x1008 + SO_UPCALLCLOSEWAIT = 0x1027 + SO_USELOOPBACK = 0x40 + SO_WANTMORE = 0x4000 + SO_WANTOOBFLAG = 0x8000 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0x4 + TABDLY = 0xc04 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_CC = 0xb + TCPOPT_CCECHO = 0xd + TCPOPT_CCNEW = 0xc + TCPOPT_EOL = 0x0 + TCPOPT_FASTOPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_CONNECTIONTIMEOUT = 0x20 + TCP_CONNECTION_INFO = 0x106 + TCP_ENABLE_ECN = 0x104 + TCP_FASTOPEN = 0x105 + TCP_KEEPALIVE = 0x10 + TCP_KEEPCNT = 0x102 + TCP_KEEPINTVL = 0x101 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NOTSENT_LOWAT = 0x201 + TCP_RXT_CONNDROPTIME = 0x80 + TCP_RXT_FINDROP = 0x100 + TCP_SENDMOREACKS = 0x103 + TCSAFLUSH = 0x2 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDCDTIMESTAMP = 0x40107458 + TIOCDRAIN = 0x2000745e + TIOCDSIMICROCODE = 0x20007455 + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x40487413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGWINSZ = 0x40087468 + TIOCIXOFF = 0x20007480 + TIOCIXON = 0x20007481 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMODG = 0x40047403 + TIOCMODS = 0x80047404 + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTYGNAME = 0x40807453 + TIOCPTYGRANT = 0x20007454 + TIOCPTYUNLK = 0x20007452 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCONS = 0x20007463 + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x80487414 + TIOCSETAF = 0x80487416 + TIOCSETAW = 0x80487415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2000745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + UF_APPEND = 0x4 + UF_COMPRESSED = 0x20 + UF_DATAVAULT = 0x80 + UF_HIDDEN = 0x8000 + UF_IMMUTABLE = 0x2 + UF_NODUMP = 0x1 + UF_OPAQUE = 0x8 + UF_SETTABLE = 0xffff + UF_TRACKED = 0x40 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMADDR_CID_ANY = 0xffffffff + VMADDR_CID_HOST = 0x2 + VMADDR_CID_HYPERVISOR = 0x0 + VMADDR_CID_RESERVED = 0x1 + VMADDR_PORT_ANY = 0xffffffff + VMIN = 0x10 + VM_LOADAVG = 0x2 + VM_MACHFACTOR = 0x4 + VM_MAXID = 0x6 + VM_METER = 0x1 + VM_SWAPUSAGE = 0x5 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VT0 = 0x0 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x10 + WCOREFLAG = 0x80 + WEXITED = 0x4 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WORDSIZE = 0x40 + WSTOPPED = 0x8 + WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index cbd8ed1..4a55a40 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,darwin +//go:build arm64 && darwin // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -11,1475 +11,1613 @@ package unix import "syscall" const ( - AF_APPLETALK = 0x10 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1c - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1e - AF_IPX = 0x17 - AF_ISDN = 0x1c - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x28 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 - AF_NS = 0x6 - AF_OSI = 0x7 - AF_PPP = 0x22 - AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 - AF_ROUTE = 0x11 - AF_SIP = 0x18 - AF_SNA = 0xb - AF_SYSTEM = 0x20 - AF_UNIX = 0x1 - AF_UNSPEC = 0x0 - AF_UTUN = 0x26 - ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x41c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff - B0 = 0x0 - B110 = 0x6e - B115200 = 0x1c200 - B1200 = 0x4b0 - B134 = 0x86 - B14400 = 0x3840 - B150 = 0x96 - B1800 = 0x708 - B19200 = 0x4b00 - B200 = 0xc8 - B230400 = 0x38400 - B2400 = 0x960 - B28800 = 0x7080 - B300 = 0x12c - B38400 = 0x9600 - B4800 = 0x12c0 - B50 = 0x32 - B57600 = 0xe100 - B600 = 0x258 - B7200 = 0x1c20 - B75 = 0x4b - B76800 = 0x12c00 - B9600 = 0x2580 - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 - BIOCGETIF = 0x4020426b - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCPROMISC = 0x20004269 - BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e - BIOCSETIF = 0x8020426c - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0x0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0x0 - BPF_IND = 0x40 - BPF_JA = 0x0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0x0 - BPF_LD = 0x0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0x0 - BPF_TXA = 0x80 - BPF_W = 0x0 - BPF_X = 0x8 - BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 - CFLUSH = 0xf - CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 - CREAD = 0x800 - CRTSCTS = 0x30000 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - CTL_HW = 0x6 - CTL_KERN = 0x1 - CTL_MAXNAME = 0xc - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0xf5 - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 - DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 - DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - ECHO = 0x8 - ECHOCTL = 0x40 - ECHOE = 0x2 - ECHOK = 0x4 - ECHOKE = 0x1 - ECHONL = 0x10 - ECHOPRT = 0x20 - EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xf - EVFILT_THREADMARKER = 0xf - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 - EXTA = 0x4b00 - EXTB = 0x9600 - EXTPROC = 0x800 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 - FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 - F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a - F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e - F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d - F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0x8 - F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 - F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 - F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 - F_WRLCK = 0x3 - HUPCL = 0x4000 - HW_MACHINE = 0x1 - ICANON = 0x100 - ICMP6_FILTER = 0x12 - ICRNL = 0x100 - IEXTEN = 0x400 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_DEBUG = 0x4 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PROMISC = 0x100 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IFT_1822 = 0x2 - IFT_AAL5 = 0x31 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ATM = 0x25 - IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff - IFT_CEPT = 0x13 - IFT_DS3 = 0x1e - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_ETHER = 0x6 - IFT_FAITH = 0x38 - IFT_FDDI = 0xf - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 - IFT_HDH1822 = 0x3 - IFT_HIPPI = 0x2f - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88026 = 0xa - IFT_L2VLAN = 0x87 - IFT_LAPB = 0x10 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_NSIP = 0x1b - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PDP = 0xff - IFT_PFLOG = 0xf5 - IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe - IFT_PPP = 0x17 - IFT_PROPMUX = 0x36 - IFT_PROPVIRTUAL = 0x35 - IFT_PTPSERIAL = 0x16 - IFT_RS232 = 0x21 - IFT_SDLC = 0x11 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_STARLAN = 0xb - IFT_STF = 0x39 - IFT_T1 = 0x12 - IFT_ULTRA = 0x1d - IFT_V35 = 0x2d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0x0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0x0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x300 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0x0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_RECVTCLASS = 0x23 - IPV6_RTHDR_LOOSE = 0x0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0x0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 - IPV6_UNICAST_HOPS = 0x4 - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 - IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 - IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0x0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a - IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 - IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - KERN_HOSTNAME = 0xa - KERN_OSRELEASE = 0x2 - KERN_OSTYPE = 0x1 - KERN_VERSION = 0x4 - LOCK_EX = 0x2 - LOCK_NB = 0x4 - LOCK_SH = 0x1 - LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 - MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 - MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa - MADV_RANDOM = 0x1 - MADV_SEQUENTIAL = 0x2 - MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 - MAP_ANON = 0x1000 - MAP_ANONYMOUS = 0x1000 - MAP_COPY = 0x2 - MAP_FILE = 0x0 - MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 - MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 - MAP_SHARED = 0x1 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 - MNT_EXPORTED = 0x100 - MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 - MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 - MNT_NODEV = 0x10 - MNT_NOEXEC = 0x4 - MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 - MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 - MNT_QUOTA = 0x2000 - MNT_RDONLY = 0x1 - MNT_RELOAD = 0x40000 - MNT_ROOTFS = 0x4000 - MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 - MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0x17f0f5ff - MNT_WAIT = 0x1 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 - MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 - NAME_MAX = 0xff - NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 - NET_RT_FLAGS = 0x2 - NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xa - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 - NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 - NOFLSH = 0x80000000 - NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 - NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 - NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 - NOTE_DELETE = 0x1 - NOTE_EXEC = 0x20000000 - NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 - NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 - NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 - NOTE_LINK = 0x10 - NOTE_LOWAT = 0x1 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 - NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 - NOTE_RENAME = 0x20 - NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 - NOTE_TRACK = 0x1 - NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 - NOTE_WRITE = 0x2 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - OXTABS = 0x4 - O_ACCMODE = 0x3 - O_ALERT = 0x20000000 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 - O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 - O_EXCL = 0x800 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x20000 - O_NOFOLLOW = 0x100 - O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 - O_RDONLY = 0x0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_WRONLY = 0x1 - PARENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - PENDIN = 0x20000000 - PRIO_PGRP = 0x1 - PRIO_PROCESS = 0x0 - PRIO_USER = 0x2 - PROT_EXEC = 0x4 - PROT_NONE = 0x0 - PROT_READ = 0x1 - PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 - RLIMIT_CORE = 0x4 - RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 - RLIMIT_DATA = 0x2 - RLIMIT_FSIZE = 0x1 - RLIMIT_MEMLOCK = 0x6 - RLIMIT_NOFILE = 0x8 - RLIMIT_NPROC = 0x7 - RLIMIT_RSS = 0x5 - RLIMIT_STACK = 0x3 - RLIM_INFINITY = 0x7fffffffffffffff - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0x0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DELCLONE = 0x80 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_GATEWAY = 0x2 - RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 - RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 - RTF_STATIC = 0x800 - RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_GET2 = 0x14 - RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RUSAGE_CHILDREN = -0x1 - RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 - SHUT_RD = 0x0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIOCADDMULTI = 0x80206931 - SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 - SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 - SIOCDELMULTI = 0x80206932 - SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 - SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 - SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 - SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 - SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 - SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 - TCIFLUSH = 0x1 - TCIOFF = 0x3 - TCIOFLUSH = 0x3 - TCION = 0x4 - TCOFLUSH = 0x2 - TCOOFF = 0x1 - TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 - TCSAFLUSH = 0x2 - TIOCCBRK = 0x2000747a - TIOCCDTR = 0x20007478 - TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 - TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 - TIOCEXCL = 0x2000740d - TIOCEXT = 0x80047460 - TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 - TIOCGETD = 0x4004741a - TIOCGPGRP = 0x40047477 - TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 - TIOCMBIC = 0x8004746b - TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a - TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b - TIOCMSET = 0x8004746d - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_DTR = 0x2 - TIOCM_LE = 0x1 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_RTS = 0x4 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x20007471 - TIOCNXCL = 0x2000740e - TIOCOUTQ = 0x40047473 - TIOCPKT = 0x80047470 - TIOCPKT_DATA = 0x0 - TIOCPKT_DOSTOP = 0x20 - TIOCPKT_FLUSHREAD = 0x1 - TIOCPKT_FLUSHWRITE = 0x2 - TIOCPKT_IOCTL = 0x40 - TIOCPKT_NOSTOP = 0x10 - TIOCPKT_START = 0x8 - TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 - TIOCREMOTE = 0x80047469 - TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 - TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 - TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 - TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f - TIOCSPGRP = 0x80047476 - TIOCSTART = 0x2000746e - TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 - TIOCSTOP = 0x2000746f - TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 - TIOCUCNTL = 0x80047466 - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 - VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - VWERASE = 0x4 - WCONTINUED = 0x10 - WCOREFLAG = 0x80 - WEXITED = 0x4 - WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 - WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + AF_APPLETALK = 0x10 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1c + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1e + AF_IPX = 0x17 + AF_ISDN = 0x1c + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x29 + AF_NATM = 0x1f + AF_NDRV = 0x1b + AF_NETBIOS = 0x21 + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PPP = 0x22 + AF_PUP = 0x4 + AF_RESERVED_36 = 0x24 + AF_ROUTE = 0x11 + AF_SIP = 0x18 + AF_SNA = 0xb + AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_UTUN = 0x26 + AF_VSOCK = 0x28 + ALTWERASE = 0x200 + ATTR_BIT_MAP_COUNT = 0x5 + ATTR_CMN_ACCESSMASK = 0x20000 + ATTR_CMN_ACCTIME = 0x1000 + ATTR_CMN_ADDEDTIME = 0x10000000 + ATTR_CMN_BKUPTIME = 0x2000 + ATTR_CMN_CHGTIME = 0x800 + ATTR_CMN_CRTIME = 0x200 + ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 + ATTR_CMN_DEVID = 0x2 + ATTR_CMN_DOCUMENT_ID = 0x100000 + ATTR_CMN_ERROR = 0x20000000 + ATTR_CMN_EXTENDED_SECURITY = 0x400000 + ATTR_CMN_FILEID = 0x2000000 + ATTR_CMN_FLAGS = 0x40000 + ATTR_CMN_FNDRINFO = 0x4000 + ATTR_CMN_FSID = 0x4 + ATTR_CMN_FULLPATH = 0x8000000 + ATTR_CMN_GEN_COUNT = 0x80000 + ATTR_CMN_GRPID = 0x10000 + ATTR_CMN_GRPUUID = 0x1000000 + ATTR_CMN_MODTIME = 0x400 + ATTR_CMN_NAME = 0x1 + ATTR_CMN_NAMEDATTRCOUNT = 0x80000 + ATTR_CMN_NAMEDATTRLIST = 0x100000 + ATTR_CMN_OBJID = 0x20 + ATTR_CMN_OBJPERMANENTID = 0x40 + ATTR_CMN_OBJTAG = 0x10 + ATTR_CMN_OBJTYPE = 0x8 + ATTR_CMN_OWNERID = 0x8000 + ATTR_CMN_PARENTID = 0x4000000 + ATTR_CMN_PAROBJID = 0x80 + ATTR_CMN_RETURNED_ATTRS = 0x80000000 + ATTR_CMN_SCRIPT = 0x100 + ATTR_CMN_SETMASK = 0x51c7ff00 + ATTR_CMN_USERACCESS = 0x200000 + ATTR_CMN_UUID = 0x800000 + ATTR_CMN_VALIDMASK = 0xffffffff + ATTR_CMN_VOLSETMASK = 0x6700 + ATTR_FILE_ALLOCSIZE = 0x4 + ATTR_FILE_CLUMPSIZE = 0x10 + ATTR_FILE_DATAALLOCSIZE = 0x400 + ATTR_FILE_DATAEXTENTS = 0x800 + ATTR_FILE_DATALENGTH = 0x200 + ATTR_FILE_DEVTYPE = 0x20 + ATTR_FILE_FILETYPE = 0x40 + ATTR_FILE_FORKCOUNT = 0x80 + ATTR_FILE_FORKLIST = 0x100 + ATTR_FILE_IOBLOCKSIZE = 0x8 + ATTR_FILE_LINKCOUNT = 0x1 + ATTR_FILE_RSRCALLOCSIZE = 0x2000 + ATTR_FILE_RSRCEXTENTS = 0x4000 + ATTR_FILE_RSRCLENGTH = 0x1000 + ATTR_FILE_SETMASK = 0x20 + ATTR_FILE_TOTALSIZE = 0x2 + ATTR_FILE_VALIDMASK = 0x37ff + ATTR_VOL_ALLOCATIONCLUMP = 0x40 + ATTR_VOL_ATTRIBUTES = 0x40000000 + ATTR_VOL_CAPABILITIES = 0x20000 + ATTR_VOL_DIRCOUNT = 0x400 + ATTR_VOL_ENCODINGSUSED = 0x10000 + ATTR_VOL_FILECOUNT = 0x200 + ATTR_VOL_FSTYPE = 0x1 + ATTR_VOL_INFO = 0x80000000 + ATTR_VOL_IOBLOCKSIZE = 0x80 + ATTR_VOL_MAXOBJCOUNT = 0x800 + ATTR_VOL_MINALLOCATION = 0x20 + ATTR_VOL_MOUNTEDDEVICE = 0x8000 + ATTR_VOL_MOUNTFLAGS = 0x4000 + ATTR_VOL_MOUNTPOINT = 0x1000 + ATTR_VOL_NAME = 0x2000 + ATTR_VOL_OBJCOUNT = 0x100 + ATTR_VOL_QUOTA_SIZE = 0x10000000 + ATTR_VOL_RESERVED_SIZE = 0x20000000 + ATTR_VOL_SETMASK = 0x80002000 + ATTR_VOL_SIGNATURE = 0x2 + ATTR_VOL_SIZE = 0x4 + ATTR_VOL_SPACEAVAIL = 0x10 + ATTR_VOL_SPACEFREE = 0x8 + ATTR_VOL_SPACEUSED = 0x800000 + ATTR_VOL_UUID = 0x40000 + ATTR_VOL_VALIDMASK = 0xf087ffff + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc00c4279 + BIOCGETIF = 0x4020426b + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDLT = 0x80044278 + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x8010427e + BIOCSETIF = 0x8020426c + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + BS0 = 0x0 + BS1 = 0x8000 + BSDLY = 0x8000 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_MONOTONIC = 0x6 + CLOCK_MONOTONIC_RAW = 0x4 + CLOCK_MONOTONIC_RAW_APPROX = 0x5 + CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x10 + CLOCK_UPTIME_RAW = 0x8 + 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 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x10a + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NULL = 0x0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_DARWIN = 0x10a + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WIHART = 0xdf + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EVFILT_AIO = -0x3 + EVFILT_EXCEPT = -0xf + EVFILT_FS = -0x9 + EVFILT_MACHPORT = -0x8 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x11 + EVFILT_THREADMARKER = 0x11 + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xa + EVFILT_VM = -0xc + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DISPATCH2 = 0x180 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG0 = 0x1000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_OOBAND = 0x2000 + EV_POLL = 0x1000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EV_UDATA_SPECIFIC = 0x100 + EV_VANISHED = 0x200 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FF0 = 0x0 + FF1 = 0x4000 + FFDLY = 0x4000 + FLUSHO = 0x800000 + FSOPT_ATTR_CMN_EXTENDED = 0x20 + FSOPT_NOFOLLOW = 0x1 + FSOPT_NOINMEMUPDATE = 0x2 + FSOPT_PACK_INVAL_ATTRS = 0x8 + FSOPT_REPORT_FULLSIZE = 0x4 + FSOPT_RETURN_REALDEV = 0x200 + F_ADDFILESIGS = 0x3d + F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 + F_ADDFILESIGS_INFO = 0x67 + F_ADDFILESIGS_RETURN = 0x61 + F_ADDFILESUPPL = 0x68 + F_ADDSIGS = 0x3b + F_ALLOCATEALL = 0x4 + F_ALLOCATECONTIG = 0x2 + F_BARRIERFSYNC = 0x55 + F_CHECK_LV = 0x62 + F_CHKCLEAN = 0x29 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x43 + F_FINDSIGS = 0x4e + F_FLUSH_DATA = 0x28 + F_FREEZE_FS = 0x35 + F_FULLFSYNC = 0x33 + F_GETCODEDIR = 0x48 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETLKPID = 0x42 + F_GETNOSIGPIPE = 0x4a + F_GETOWN = 0x5 + F_GETPATH = 0x32 + F_GETPATH_MTMINFO = 0x47 + F_GETPATH_NOFIRMLINK = 0x66 + F_GETPROTECTIONCLASS = 0x3f + F_GETPROTECTIONLEVEL = 0x4d + F_GETSIGSINFO = 0x69 + F_GLOBAL_NOCACHE = 0x37 + F_LOG2PHYS = 0x31 + F_LOG2PHYS_EXT = 0x41 + F_NOCACHE = 0x30 + F_NODIRECT = 0x3e + F_OK = 0x0 + F_PATHPKG_CHECK = 0x34 + F_PEOFPOSMODE = 0x3 + F_PREALLOCATE = 0x2a + F_PUNCHHOLE = 0x63 + F_RDADVISE = 0x2c + F_RDAHEAD = 0x2d + F_RDLCK = 0x1 + F_SETBACKINGSTORE = 0x46 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETLKWTIMEOUT = 0xa + F_SETNOSIGPIPE = 0x49 + F_SETOWN = 0x6 + F_SETPROTECTIONCLASS = 0x40 + F_SETSIZE = 0x2b + F_SINGLE_WRITER = 0x4c + F_SPECULATIVE_READ = 0x65 + F_THAW_FS = 0x36 + F_TRANSCODEKEY = 0x4b + F_TRIM_ACTIVE_FILE = 0x64 + F_UNLCK = 0x2 + F_VOLPOSMODE = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOTRAILERS = 0x20 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_6LOWPAN = 0x40 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CELLULAR = 0xff + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PKTAP = 0xfe + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LINKLOCALNETNUM = 0xa9fe0000 + IN_LOOPBACKNET = 0x7f + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x400473d1 + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0xfe + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_2292DSTOPTS = 0x17 + IPV6_2292HOPLIMIT = 0x14 + IPV6_2292HOPOPTS = 0x16 + IPV6_2292NEXTHOP = 0x15 + IPV6_2292PKTINFO = 0x13 + IPV6_2292PKTOPTIONS = 0x19 + IPV6_2292RTHDR = 0x18 + IPV6_3542DSTOPTS = 0x32 + IPV6_3542HOPLIMIT = 0x2f + IPV6_3542HOPOPTS = 0x31 + IPV6_3542NEXTHOP = 0x30 + IPV6_3542PKTINFO = 0x2e + IPV6_3542RTHDR = 0x33 + IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 + IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 + IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDV6ONLY = 0x1b + IPV6_BOUND_IF = 0x7d + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOW_ECN_MASK = 0x3000 + IPV6_FRAGTTL = 0x3c + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x3d + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x23 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x39 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x24 + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BLOCK_SOURCE = 0x48 + IP_BOUND_IF = 0x19 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x1c + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW_ADD = 0x28 + IP_FW_DEL = 0x29 + IP_FW_FLUSH = 0x2a + IP_FW_GET = 0x2c + IP_FW_RESETLOG = 0x2d + IP_FW_ZERO = 0x2b + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_IFINDEX = 0x42 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_NAT__XXX = 0x37 + IP_OFFMASK = 0x1fff + IP_OLD_FW_ADD = 0x32 + IP_OLD_FW_DEL = 0x33 + IP_OLD_FW_FLUSH = 0x34 + IP_OLD_FW_GET = 0x36 + IP_OLD_FW_RESETLOG = 0x38 + IP_OLD_FW_ZERO = 0x35 + IP_OPTIONS = 0x1 + IP_PKTINFO = 0x1a + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVPKTINFO = 0x1a + IP_RECVRETOPTS = 0x6 + IP_RECVTOS = 0x1b + IP_RECVTTL = 0x18 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_STRIPHDR = 0x17 + IP_TOS = 0x3 + IP_TRAFFIC_MGT_BACKGROUND = 0x41 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + ISIG = 0x80 + ISTRIP = 0x20 + IUTF8 = 0x4000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_PEERCRED = 0x1 + LOCAL_PEEREPID = 0x3 + LOCAL_PEEREUUID = 0x5 + LOCAL_PEERPID = 0x2 + LOCAL_PEERTOKEN = 0x6 + LOCAL_PEERUUID = 0x4 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_CAN_REUSE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_FREE_REUSABLE = 0x7 + MADV_FREE_REUSE = 0x8 + MADV_NORMAL = 0x0 + MADV_PAGEOUT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MADV_ZERO_WIRED_PAGES = 0x6 + MAP_32BIT = 0x8000 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_HASSEMAPHORE = 0x200 + MAP_JIT = 0x800 + MAP_NOCACHE = 0x400 + MAP_NOEXTEND = 0x100 + MAP_NORESERVE = 0x40 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x20 + MAP_RESERVED0080 = 0x80 + MAP_RESILIENT_CODESIGN = 0x2000 + MAP_RESILIENT_MEDIA = 0x4000 + MAP_SHARED = 0x1 + MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 + MAP_UNIX03 = 0x40000 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x400000 + MNT_CMDFLAGS = 0xf0000 + MNT_CPROTECT = 0x80 + MNT_DEFWRITE = 0x2000000 + MNT_DONTBROWSE = 0x100000 + MNT_DOVOLFS = 0x8000 + MNT_DWAIT = 0x4 + MNT_EXPORTED = 0x100 + MNT_EXT_ROOT_DATA_VOL = 0x1 + MNT_FORCE = 0x80000 + MNT_IGNORE_OWNERSHIP = 0x200000 + MNT_JOURNALED = 0x800000 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NOATIME = 0x10000000 + MNT_NOBLOCK = 0x20000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOSUID = 0x8 + MNT_NOUSERXATTR = 0x1000000 + MNT_NOWAIT = 0x2 + MNT_QUARANTINE = 0x400 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_REMOVABLE = 0x200 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x40000000 + MNT_STRICTATIME = 0x80000000 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNKNOWNPERMISSIONS = 0x200000 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0xd7f0f7ff + MNT_WAIT = 0x1 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_FLUSH = 0x400 + MSG_HAVEMORE = 0x2000 + MSG_HOLD = 0x800 + MSG_NEEDSA = 0x10000 + MSG_NOSIGNAL = 0x80000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_RCVMORE = 0x4000 + MSG_SEND = 0x1000 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITSTREAM = 0x200 + MS_ASYNC = 0x1 + MS_DEACTIVATE = 0x8 + MS_INVALIDATE = 0x2 + MS_KILLPAGES = 0x4 + MS_SYNC = 0x10 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_DUMP2 = 0x7 + NET_RT_FLAGS = 0x2 + NET_RT_FLAGS_PRIV = 0xa + NET_RT_IFLIST = 0x3 + NET_RT_IFLIST2 = 0x6 + NET_RT_MAXID = 0xb + NET_RT_STAT = 0x4 + NET_RT_TRASH = 0x5 + NFDBITS = 0x20 + NL0 = 0x0 + NL1 = 0x100 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSOLUTE = 0x8 + NOTE_ATTRIB = 0x8 + NOTE_BACKGROUND = 0x40 + NOTE_CHILD = 0x4 + NOTE_CRITICAL = 0x20 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXITSTATUS = 0x4000000 + NOTE_EXIT_CSERROR = 0x40000 + NOTE_EXIT_DECRYPTFAIL = 0x10000 + NOTE_EXIT_DETAIL = 0x2000000 + NOTE_EXIT_DETAIL_MASK = 0x70000 + NOTE_EXIT_MEMORY = 0x20000 + NOTE_EXIT_REPARENTED = 0x80000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FORK = 0x40000000 + NOTE_FUNLOCK = 0x100 + NOTE_LEEWAY = 0x10 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MACHTIME = 0x100 + NOTE_MACH_CONTINUOUS_TIME = 0x80 + NOTE_NONE = 0x80 + NOTE_NSECONDS = 0x4 + NOTE_OOB = 0x2 + NOTE_PCTRLMASK = -0x100000 + NOTE_PDATAMASK = 0xfffff + NOTE_REAP = 0x10000000 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_SIGNAL = 0x8000000 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x2 + NOTE_VM_ERROR = 0x10000000 + NOTE_VM_PRESSURE = 0x80000000 + NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 + NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OFDEL = 0x20000 + OFILL = 0x80 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_ALERT = 0x20000000 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x1000000 + O_CREAT = 0x200 + O_DIRECTORY = 0x100000 + O_DP_GETRAWENCRYPTED = 0x1 + O_DP_GETRAWUNENCRYPTED = 0x2 + O_DSYNC = 0x400000 + O_EVTONLY = 0x8000 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x20000 + O_NOFOLLOW = 0x100 + O_NOFOLLOW_ANY = 0x20000000 + O_NONBLOCK = 0x4 + O_POPUP = 0x80000000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYMLINK = 0x200000 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PT_ATTACH = 0xa + PT_ATTACHEXC = 0xe + PT_CONTINUE = 0x7 + PT_DENY_ATTACH = 0x1f + PT_DETACH = 0xb + PT_FIRSTMACH = 0x20 + PT_FORCEQUOTA = 0x1e + PT_KILL = 0x8 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_READ_U = 0x3 + PT_SIGEXC = 0xc + PT_STEP = 0x9 + PT_THUPDATE = 0xd + PT_TRACE_ME = 0x0 + 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 + RLIMIT_CPU_USAGE_MONITOR = 0x2 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CLONING = 0x100 + RTF_CONDEMNED = 0x2000000 + RTF_DEAD = 0x20000000 + RTF_DELCLONE = 0x80 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 + RTF_HOST = 0x4 + RTF_IFREF = 0x4000000 + RTF_IFSCOPE = 0x1000000 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_NOIFREF = 0x2000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_PROXY = 0x8000000 + RTF_REJECT = 0x8 + RTF_ROUTER = 0x10000000 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_WASCLONED = 0x20000 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_GET2 = 0x14 + RTM_IFINFO = 0xe + RTM_IFINFO2 = 0x12 + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_NEWMADDR2 = 0x13 + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + 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 + SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 + SF_APPEND = 0x40000 + SF_ARCHIVED = 0x10000 + SF_DATALESS = 0x40000000 + SF_FIRMLINK = 0x800000 + SF_IMMUTABLE = 0x20000 + SF_NOUNLINK = 0x100000 + SF_RESTRICTED = 0x80000 + SF_SETTABLE = 0x3fff0000 + SF_SUPPORTED = 0x9f0000 + SF_SYNTHETIC = 0xc0000000 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCARPIPLL = 0xc0206928 + SIOCATMARK = 0x40047307 + SIOCAUTOADDR = 0xc0206926 + SIOCAUTONETMASK = 0x80206927 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFPHYADDR = 0x80206941 + SIOCGDRVSPEC = 0xc028697b + SIOCGETVLAN = 0xc020697f + SIOCGHIWAT = 0x40047301 + SIOCGIF6LOWPAN = 0xc02069c5 + SIOCGIFADDR = 0xc0206921 + SIOCGIFALTMTU = 0xc0206948 + SIOCGIFASYNCMAP = 0xc020697c + SIOCGIFBOND = 0xc0206947 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020695b + SIOCGIFCONF = 0xc00c6924 + SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFFUNCTIONALTYPE = 0xc02069ad + SIOCGIFGENERIC = 0xc020693a + SIOCGIFKPI = 0xc0206987 + SIOCGIFMAC = 0xc0206982 + SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206940 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc020693f + SIOCGIFSTATUS = 0xc331693d + SIOCGIFVLAN = 0xc020697f + SIOCGIFWAKEFLAGS = 0xc0206988 + SIOCGIFXMEDIA = 0xc02c6948 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCIFCREATE = 0xc0206978 + SIOCIFCREATE2 = 0xc020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106981 + SIOCRSLVMULTI = 0xc010693b + SIOCSDRVSPEC = 0x8028697b + SIOCSETVLAN = 0x8020697e + SIOCSHIWAT = 0x80047300 + SIOCSIF6LOWPAN = 0x802069c4 + SIOCSIFADDR = 0x8020690c + SIOCSIFALTMTU = 0x80206945 + SIOCSIFASYNCMAP = 0x8020697d + SIOCSIFBOND = 0x80206946 + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020695a + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFKPI = 0x80206986 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206983 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x8040693e + SIOCSIFPHYS = 0x80206936 + SIOCSIFVLAN = 0x8020697e + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_DONTTRUNC = 0x2000 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1010 + SO_LINGER = 0x80 + SO_LINGER_SEC = 0x1080 + SO_NETSVC_MARKING_LEVEL = 0x1119 + SO_NET_SERVICE_TYPE = 0x1116 + SO_NKE = 0x1021 + SO_NOADDRERR = 0x1023 + SO_NOSIGPIPE = 0x1022 + SO_NOTIFYCONFLICT = 0x1026 + SO_NP_EXTENSIONS = 0x1083 + SO_NREAD = 0x1020 + SO_NUMRCVPKT = 0x1112 + SO_NWRITE = 0x1024 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1011 + SO_RANDOMPORT = 0x1082 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSESHAREUID = 0x1025 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TIMESTAMP_MONOTONIC = 0x800 + SO_TRACKER_ATTRIBUTE_FLAGS_APP_APPROVED = 0x1 + SO_TRACKER_ATTRIBUTE_FLAGS_DOMAIN_SHORT = 0x4 + SO_TRACKER_ATTRIBUTE_FLAGS_TRACKER = 0x2 + SO_TRACKER_TRANSPARENCY_VERSION = 0x3 + SO_TYPE = 0x1008 + SO_UPCALLCLOSEWAIT = 0x1027 + SO_USELOOPBACK = 0x40 + SO_WANTMORE = 0x4000 + SO_WANTOOBFLAG = 0x8000 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0x4 + TABDLY = 0xc04 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_CC = 0xb + TCPOPT_CCECHO = 0xd + TCPOPT_CCNEW = 0xc + TCPOPT_EOL = 0x0 + TCPOPT_FASTOPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_CONNECTIONTIMEOUT = 0x20 + TCP_CONNECTION_INFO = 0x106 + TCP_ENABLE_ECN = 0x104 + TCP_FASTOPEN = 0x105 + TCP_KEEPALIVE = 0x10 + TCP_KEEPCNT = 0x102 + TCP_KEEPINTVL = 0x101 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NOTSENT_LOWAT = 0x201 + TCP_RXT_CONNDROPTIME = 0x80 + TCP_RXT_FINDROP = 0x100 + TCP_SENDMOREACKS = 0x103 + TCSAFLUSH = 0x2 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDCDTIMESTAMP = 0x40107458 + TIOCDRAIN = 0x2000745e + TIOCDSIMICROCODE = 0x20007455 + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x40487413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGWINSZ = 0x40087468 + TIOCIXOFF = 0x20007480 + TIOCIXON = 0x20007481 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMODG = 0x40047403 + TIOCMODS = 0x80047404 + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTYGNAME = 0x40807453 + TIOCPTYGRANT = 0x20007454 + TIOCPTYUNLK = 0x20007452 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCONS = 0x20007463 + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x80487414 + TIOCSETAF = 0x80487416 + TIOCSETAW = 0x80487415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2000745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + UF_APPEND = 0x4 + UF_COMPRESSED = 0x20 + UF_DATAVAULT = 0x80 + UF_HIDDEN = 0x8000 + UF_IMMUTABLE = 0x2 + UF_NODUMP = 0x1 + UF_OPAQUE = 0x8 + UF_SETTABLE = 0xffff + UF_TRACKED = 0x40 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMADDR_CID_ANY = 0xffffffff + VMADDR_CID_HOST = 0x2 + VMADDR_CID_HYPERVISOR = 0x0 + VMADDR_CID_RESERVED = 0x1 + VMADDR_PORT_ANY = 0xffffffff + VMIN = 0x10 + VM_LOADAVG = 0x2 + VM_MACHFACTOR = 0x4 + VM_MAXID = 0x6 + VM_METER = 0x1 + VM_SWAPUSAGE = 0x5 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VT0 = 0x0 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x10 + WCOREFLAG = 0x80 + WEXITED = 0x4 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WORDSIZE = 0x40 + WSTOPPED = 0x8 + WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index 6130471..c0e0f86 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,dragonfly +//go:build amd64 && dragonfly // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -62,6 +62,7 @@ const ( B28800 = 0x7080 B300 = 0x12c B38400 = 0x9600 + B460800 = 0x70800 B4800 = 0x12c0 B50 = 0x32 B57600 = 0xe100 @@ -69,12 +70,15 @@ const ( B7200 = 0x1c20 B75 = 0x4b B76800 = 0x12c00 + B921600 = 0xe1000 B9600 = 0x2580 + BIOCFEEDBACK = 0x8004427d BIOCFLUSH = 0x20004268 BIOCGBLEN = 0x40044266 BIOCGDLT = 0x4004426a BIOCGDLTLIST = 0xc0104279 BIOCGETIF = 0x4020426b + BIOCGFEEDBACK = 0x4004427c BIOCGHDRCMPLT = 0x40044274 BIOCGRSIG = 0x40044272 BIOCGRTIMEOUT = 0x4010426e @@ -88,6 +92,7 @@ const ( BIOCSETF = 0x80104267 BIOCSETIF = 0x8020426c BIOCSETWF = 0x8010427b + BIOCSFEEDBACK = 0x8004427d BIOCSHDRCMPLT = 0x80044275 BIOCSRSIG = 0x80044273 BIOCSRTIMEOUT = 0x8010426d @@ -125,6 +130,7 @@ const ( BPF_MINBUFSIZE = 0x20 BPF_MINOR_VERSION = 0x1 BPF_MISC = 0x7 + BPF_MOD = 0x90 BPF_MSH = 0xa0 BPF_MUL = 0x20 BPF_NEG = 0x80 @@ -139,6 +145,7 @@ const ( BPF_TXA = 0x80 BPF_W = 0x0 BPF_X = 0x8 + BPF_XOR = 0xa0 BRKINT = 0x2 CFLUSH = 0xf CLOCAL = 0x8000 @@ -156,6 +163,12 @@ const ( CLOCK_UPTIME_FAST = 0x8 CLOCK_UPTIME_PRECISE = 0x7 CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x30000 CS5 = 0x0 @@ -175,6 +188,7 @@ const ( DLT_A429 = 0xb8 DLT_A653_ICM = 0xb9 DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde DLT_APPLE_IP_OVER_IEEE1394 = 0x8a DLT_ARCNET = 0x7 DLT_ARCNET_LINUX = 0x81 @@ -184,22 +198,33 @@ const ( DLT_AX25 = 0x3 DLT_AX25_KISS = 0xca DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_BREDR_BB = 0xff DLT_BLUETOOTH_HCI_H4 = 0xbb DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_BLUETOOTH_LE_LL = 0xfb + DLT_BLUETOOTH_LE_LL_WITH_PHDR = 0x100 + DLT_BLUETOOTH_LINUX_MONITOR = 0xfe DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 DLT_CHAOS = 0x5 DLT_CHDLC = 0x68 DLT_CISCO_IOS = 0x76 DLT_C_HDLC = 0x68 DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb DLT_ECONET = 0x73 DLT_EN10MB = 0x1 DLT_EN3MB = 0x2 DLT_ENC = 0x6d + DLT_EPON = 0x103 DLT_ERF = 0xc5 DLT_ERF_ETH = 0xaf DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 DLT_FDDI = 0xa DLT_FLEXRAY = 0xd2 DLT_FRELAY = 0x6b @@ -209,6 +234,8 @@ const ( DLT_GPF_F = 0xab DLT_GPF_T = 0xaa DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 DLT_HHDLC = 0x79 DLT_IBM_SN = 0x92 DLT_IBM_SP = 0x91 @@ -218,18 +245,28 @@ const ( DLT_IEEE802_11_RADIO_AVS = 0xa3 DLT_IEEE802_15_4 = 0xc3 DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 DLT_IEEE802_15_4_NONASK_PHY = 0xd7 DLT_IEEE802_16_MAC_CPS = 0xbc DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_INFINIBAND = 0xf7 DLT_IPFILTER = 0x74 DLT_IPMB = 0xc7 DLT_IPMB_LINUX = 0xd1 + DLT_IPMI_HPM_2 = 0x104 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 DLT_IP_OVER_FC = 0x7a + DLT_ISO_14443 = 0x108 DLT_JUNIPER_ATM1 = 0x89 DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee DLT_JUNIPER_CHDLC = 0xb5 DLT_JUNIPER_ES = 0x84 DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea DLT_JUNIPER_FRELAY = 0xb4 DLT_JUNIPER_GGSN = 0x85 DLT_JUNIPER_ISM = 0xc2 @@ -242,25 +279,40 @@ const ( DLT_JUNIPER_PPPOE = 0xa7 DLT_JUNIPER_PPPOE_ATM = 0xa8 DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 DLT_JUNIPER_ST = 0xc8 DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 DLT_LAPB_WITH_DIR = 0xcf DLT_LAPD = 0xcb DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 DLT_LINUX_IRDA = 0x90 DLT_LINUX_LAPD = 0xb1 DLT_LINUX_SLL = 0x71 DLT_LOOP = 0x6c DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x109 + DLT_MATCHING_MIN = 0x68 DLT_MFR = 0xb6 DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb DLT_MTP2 = 0x8c DLT_MTP2_WITH_PHDR = 0x8b DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NETLINK = 0xfd + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 DLT_NULL = 0x0 DLT_PCI_EXP = 0x7d DLT_PFLOG = 0x75 DLT_PFSYNC = 0x12 + DLT_PKTAP = 0x102 DLT_PPI = 0xc0 DLT_PPP = 0x9 DLT_PPP_BSDOS = 0x10 @@ -269,22 +321,51 @@ const ( DLT_PPP_SERIAL = 0x32 DLT_PPP_WITH_DIR = 0xcc DLT_PRISM_HEADER = 0x77 + DLT_PROFIBUS_DL = 0x101 DLT_PRONET = 0x4 DLT_RAIF1 = 0xc6 DLT_RAW = 0xc + DLT_RDS = 0x109 DLT_REDBACK_SMARTEDGE = 0x20 DLT_RIO = 0x7c + DLT_RTAC_SERIAL = 0xfa DLT_SCCP = 0x8e + DLT_SCTP = 0xf8 DLT_SITA = 0xc4 DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed DLT_SUNATM = 0x7b DLT_SYMANTEC_FIREWALL = 0x63 DLT_TZSP = 0x80 DLT_USB = 0xba + DLT_USBPCAP = 0xf9 + DLT_USB_FREEBSD = 0xba DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WATTSTOPPER_DLM = 0x107 + DLT_WIHART = 0xdf + DLT_WIRESHARK_UPPER_PDU = 0xfc DLT_X2E_SERIAL = 0xd5 DLT_X2E_XORAYA = 0xd6 + DLT_ZWAVE_R1_R2 = 0x105 + DLT_ZWAVE_R3 = 0x106 DT_BLK = 0x6 DT_CHR = 0x2 DT_DBF = 0xf @@ -323,10 +404,11 @@ const ( EV_EOF = 0x8000 EV_ERROR = 0x4000 EV_FLAG1 = 0x2000 + EV_HUP = 0x800 EV_NODATA = 0x1000 EV_ONESHOT = 0x10 EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTEXIT_LWP = 0x10000 @@ -365,8 +447,9 @@ const ( IFF_ALLMULTI = 0x200 IFF_ALTPHYS = 0x4000 IFF_BROADCAST = 0x2 - IFF_CANTCHANGE = 0x118e72 + IFF_CANTCHANGE = 0x318e72 IFF_DEBUG = 0x4 + IFF_IDIRECT = 0x200000 IFF_LINK0 = 0x1000 IFF_LINK1 = 0x2000 IFF_LINK2 = 0x4000 @@ -441,7 +524,6 @@ const ( IFT_EPLRS = 0x57 IFT_ESCON = 0x49 IFT_ETHER = 0x6 - IFT_FAITH = 0xf2 IFT_FAST = 0x7d IFT_FASTETHER = 0x3e IFT_FASTETHERFX = 0x45 @@ -614,6 +696,7 @@ const ( IN_CLASSD_NET = 0xf0000000 IN_CLASSD_NSHIFT = 0x1c IN_LOOPBACKNET = 0x7f + IN_RFC3021_MASK = 0xfffffffe IPPROTO_3PC = 0x22 IPPROTO_ADFS = 0x44 IPPROTO_AH = 0x33 @@ -735,7 +818,6 @@ const ( IPV6_DEFHLIM = 0x40 IPV6_DONTFRAG = 0x3e IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FRAGTTL = 0x78 @@ -747,7 +829,6 @@ const ( IPV6_HLIMDEC = 0x1 IPV6_HOPLIMIT = 0x2f IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c IPV6_JOIN_GROUP = 0xc IPV6_LEAVE_GROUP = 0xd IPV6_MAXHLIM = 0xff @@ -795,16 +876,22 @@ const ( IP_DUMMYNET_DEL = 0x3d IP_DUMMYNET_FLUSH = 0x3e IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 IP_FW_ADD = 0x32 IP_FW_DEL = 0x33 IP_FW_FLUSH = 0x34 IP_FW_GET = 0x36 IP_FW_RESETLOG = 0x37 + IP_FW_TBL_ADD = 0x2a + IP_FW_TBL_CREATE = 0x28 + IP_FW_TBL_DEL = 0x2b + IP_FW_TBL_DESTROY = 0x29 + IP_FW_TBL_EXPIRE = 0x2f + IP_FW_TBL_FLUSH = 0x2c + IP_FW_TBL_GET = 0x2d + IP_FW_TBL_ZERO = 0x2e IP_FW_X = 0x31 IP_FW_ZERO = 0x35 IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 IP_MAXPACKET = 0xffff IP_MAX_MEMBERSHIPS = 0x14 IP_MF = 0x2000 @@ -1080,12 +1167,10 @@ const ( RTM_MISS = 0x7 RTM_NEWADDR = 0xc RTM_NEWMADDR = 0xf - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x6 + RTM_VERSION = 0x7 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 RTV_IWCAPSEGS = 0x400 @@ -1106,13 +1191,13 @@ const ( SHUT_RDWR = 0x2 SHUT_WR = 0x1 SIOCADDMULTI = 0x80206931 - SIOCADDRT = 0x8040720a SIOCAIFADDR = 0x8040691a + SIOCAIFGROUP = 0x80286987 SIOCALIFADDR = 0x8118691b SIOCATMARK = 0x40047307 SIOCDELMULTI = 0x80206932 - SIOCDELRT = 0x8040720b SIOCDIFADDR = 0x80206919 + SIOCDIFGROUP = 0x80286989 SIOCDIFPHYADDR = 0x80206949 SIOCDLIFADDR = 0x8118691d SIOCGDRVSPEC = 0xc028697b @@ -1120,6 +1205,7 @@ const ( SIOCGETVIFCNT = 0xc028720f SIOCGHIWAT = 0x40047301 SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc0406929 SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCAP = 0xc020691f SIOCGIFCONF = 0xc0106924 @@ -1128,6 +1214,7 @@ const ( SIOCGIFFLAGS = 0xc0206911 SIOCGIFGENERIC = 0xc020693a SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 SIOCGIFINDEX = 0xc0206920 SIOCGIFMEDIA = 0xc0306938 SIOCGIFMETRIC = 0xc0206917 @@ -1194,6 +1281,7 @@ const ( SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x2000 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_SNDBUF = 0x1001 @@ -1233,6 +1321,9 @@ const ( S_IXGRP = 0x8 S_IXOTH = 0x1 S_IXUSR = 0x40 + TAB0 = 0x0 + TAB3 = 0x4 + TABDLY = 0x4 TCIFLUSH = 0x1 TCIOFF = 0x3 TCIOFLUSH = 0x3 @@ -1259,6 +1350,8 @@ const ( TCP_NOPUSH = 0x4 TCP_SIGNATURE_ENABLE = 0x10 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 TIOCCONS = 0x80047462 @@ -1272,7 +1365,6 @@ const ( TIOCGETD = 0x4004741a TIOCGPGRP = 0x40047477 TIOCGSID = 0x40047463 - TIOCGSIZE = 0x40087468 TIOCGWINSZ = 0x40087468 TIOCISPTMASTER = 0x20007455 TIOCMBIC = 0x8004746b @@ -1317,7 +1409,6 @@ const ( TIOCSETD = 0x8004741b TIOCSIG = 0x2000745f TIOCSPGRP = 0x80047476 - TIOCSSIZE = 0x80087467 TIOCSTART = 0x2000746e TIOCSTAT = 0x20007465 TIOCSTI = 0x80017472 @@ -1326,6 +1417,8 @@ const ( TIOCTIMESTAMP = 0x40107459 TIOCUCNTL = 0x80047466 TOSTOP = 0x400000 + UTIME_NOW = -0x1 + UTIME_OMIT = -0x2 VCHECKPT = 0x13 VDISCARD = 0xf VDSUSP = 0xb @@ -1350,9 +1443,12 @@ const ( VWERASE = 0x4 WCONTINUED = 0x4 WCOREFLAG = 0x80 + WEXITED = 0x10 WLINUXCLONE = 0x80000000 WNOHANG = 0x1 - WSTOPPED = 0x7f + WNOWAIT = 0x8 + WSTOPPED = 0x2 + WTRAPPED = 0x20 WUNTRACED = 0x2 ) @@ -1452,11 +1548,6 @@ const ( ETIMEDOUT = syscall.Errno(0x3c) ETOOMANYREFS = syscall.Errno(0x3b) ETXTBSY = syscall.Errno(0x1a) - EUNUSED94 = syscall.Errno(0x5e) - EUNUSED95 = syscall.Errno(0x5f) - EUNUSED96 = syscall.Errno(0x60) - EUNUSED97 = syscall.Errno(0x61) - EUNUSED98 = syscall.Errno(0x62) EUSERS = syscall.Errno(0x44) EWOULDBLOCK = syscall.Errno(0x23) EXDEV = syscall.Errno(0x12) @@ -1600,12 +1691,7 @@ var errorList = [...]struct { {91, "ENOLINK", "link has been severed"}, {92, "EPROTO", "protocol error"}, {93, "ENOMEDIUM", "no medium found"}, - {94, "EUNUSED94", "unknown error: 94"}, - {95, "EUNUSED95", "unknown error: 95"}, - {96, "EUNUSED96", "unknown error: 96"}, - {97, "EUNUSED97", "unknown error: 97"}, - {98, "EUNUSED98", "unknown error: 98"}, - {99, "ELAST", "unknown error: 99"}, + {99, "EASYNC", "unknown error: 99"}, } // Signal table diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index 8482458..6c69239 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go @@ -1,7 +1,7 @@ // mkerrors.sh -m32 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,freebsd +//go:build 386 && freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go @@ -150,6 +150,7 @@ const ( BIOCSETF = 0x80084267 BIOCSETFNR = 0x80084282 BIOCSETIF = 0x8020426c + BIOCSETVLANPCP = 0x80044285 BIOCSETWF = 0x8008427b BIOCSETZBUF = 0x800c4281 BIOCSHDRCMPLT = 0x80044275 @@ -339,6 +340,12 @@ const ( CLOCK_UPTIME_FAST = 0x8 CLOCK_UPTIME_PRECISE = 0x7 CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x30000 CS5 = 0x0 @@ -440,7 +447,7 @@ const ( DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 DLT_INFINIBAND = 0xf7 DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 + DLT_IPMB_KONTRON = 0xc7 DLT_IPMB_LINUX = 0xd1 DLT_IPMI_HPM_2 = 0x104 DLT_IPNET = 0xe2 @@ -480,10 +487,11 @@ const ( DLT_LINUX_LAPD = 0xb1 DLT_LINUX_PPP_WITHDIRECTION = 0xa6 DLT_LINUX_SLL = 0x71 + DLT_LINUX_SLL2 = 0x114 DLT_LOOP = 0x6c DLT_LORATAP = 0x10e DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x113 + DLT_MATCHING_MAX = 0x114 DLT_MATCHING_MIN = 0x68 DLT_MFR = 0xb6 DLT_MOST = 0xd3 @@ -727,6 +735,7 @@ const ( IPPROTO_CMTP = 0x26 IPPROTO_CPHB = 0x49 IPPROTO_CPNX = 0x48 + IPPROTO_DCCP = 0x21 IPPROTO_DDP = 0x25 IPPROTO_DGP = 0x56 IPPROTO_DIVERT = 0x102 @@ -807,7 +816,6 @@ const ( IPPROTO_SCTP = 0x84 IPPROTO_SDRP = 0x2a IPPROTO_SEND = 0x103 - IPPROTO_SEP = 0x21 IPPROTO_SHIM6 = 0x8c IPPROTO_SKIP = 0x39 IPPROTO_SPACER = 0x7fff @@ -904,6 +912,7 @@ const ( IPV6_V6ONLY = 0x1b IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 + IPV6_VLAN_PCP = 0x4b IP_ADD_MEMBERSHIP = 0xc IP_ADD_SOURCE_MEMBERSHIP = 0x46 IP_BINDANY = 0x18 @@ -982,8 +991,12 @@ const ( IP_TOS = 0x3 IP_TTL = 0x4 IP_UNBLOCK_SOURCE = 0x49 + IP_VLAN_PCP = 0x4b ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -991,6 +1004,10 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1167,6 +1184,8 @@ const ( O_NONBLOCK = 0x4 O_RDONLY = 0x0 O_RDWR = 0x2 + O_RESOLVE_BENEATH = 0x800000 + O_SEARCH = 0x40000 O_SHLOCK = 0x10 O_SYNC = 0x80 O_TRUNC = 0x400 @@ -1177,6 +1196,10 @@ const ( PARMRK = 0x8 PARODD = 0x2000 PENDIN = 0x20000000 + PIOD_READ_D = 0x1 + PIOD_READ_I = 0x3 + PIOD_WRITE_D = 0x2 + PIOD_WRITE_I = 0x4 PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 @@ -1184,6 +1207,60 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 + PTRACE_DEFAULT = 0x1 + PTRACE_EXEC = 0x1 + PTRACE_FORK = 0x8 + PTRACE_LWP = 0x10 + PTRACE_SCE = 0x2 + PTRACE_SCX = 0x4 + PTRACE_SYSCALL = 0x6 + PTRACE_VFORK = 0x20 + PT_ATTACH = 0xa + PT_CLEARSTEP = 0x10 + PT_CONTINUE = 0x7 + PT_DETACH = 0xb + PT_FIRSTMACH = 0x40 + PT_FOLLOW_FORK = 0x17 + PT_GETDBREGS = 0x25 + PT_GETFPREGS = 0x23 + PT_GETFSBASE = 0x47 + PT_GETGSBASE = 0x49 + PT_GETLWPLIST = 0xf + PT_GETNUMLWPS = 0xe + PT_GETREGS = 0x21 + PT_GETXMMREGS = 0x40 + PT_GETXSTATE = 0x45 + PT_GETXSTATE_INFO = 0x44 + PT_GET_EVENT_MASK = 0x19 + PT_GET_SC_ARGS = 0x1b + PT_GET_SC_RET = 0x1c + PT_IO = 0xc + PT_KILL = 0x8 + PT_LWPINFO = 0xd + PT_LWP_EVENTS = 0x18 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_RESUME = 0x13 + PT_SETDBREGS = 0x26 + PT_SETFPREGS = 0x24 + PT_SETFSBASE = 0x48 + PT_SETGSBASE = 0x4a + PT_SETREGS = 0x22 + PT_SETSTEP = 0x11 + PT_SETXMMREGS = 0x41 + PT_SETXSTATE = 0x46 + PT_SET_EVENT_MASK = 0x1a + PT_STEP = 0x9 + PT_SUSPEND = 0x12 + PT_SYSCALL = 0x16 + PT_TO_SCE = 0x14 + PT_TO_SCX = 0x15 + PT_TRACE_ME = 0x0 + PT_VM_ENTRY = 0x29 + PT_VM_TIMESTAMP = 0x28 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + P_ZONEID = 0xc RLIMIT_AS = 0xa RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1285,6 +1362,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1303,10 +1385,12 @@ const ( SIOCGHWADDR = 0xc020693e SIOCGI2C = 0xc020693d SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc044692d SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCAP = 0xc020691f SIOCGIFCONF = 0xc0086924 SIOCGIFDESCR = 0xc020692a + SIOCGIFDOWNREASON = 0xc058699a SIOCGIFDSTADDR = 0xc0206922 SIOCGIFFIB = 0xc020695c SIOCGIFFLAGS = 0xc0206911 @@ -1369,6 +1453,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 @@ -1396,6 +1481,7 @@ const ( SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x20000 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_REUSEPORT_LB = 0x10000 @@ -1454,22 +1540,40 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_FAST_OPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_PAD = 0x0 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_WINDOW = 0x3 TCP_BBR_ACK_COMP_ALG = 0x448 + TCP_BBR_ALGORITHM = 0x43b TCP_BBR_DRAIN_INC_EXTRA = 0x43c TCP_BBR_DRAIN_PG = 0x42e TCP_BBR_EXTRA_GAIN = 0x449 + TCP_BBR_EXTRA_STATE = 0x453 + TCP_BBR_FLOOR_MIN_TSO = 0x454 + TCP_BBR_HDWR_PACE = 0x451 + TCP_BBR_HOLD_TARGET = 0x436 TCP_BBR_IWINTSO = 0x42b TCP_BBR_LOWGAIN_FD = 0x436 TCP_BBR_LOWGAIN_HALF = 0x435 TCP_BBR_LOWGAIN_THRESH = 0x434 TCP_BBR_MAX_RTO = 0x439 TCP_BBR_MIN_RTO = 0x438 + TCP_BBR_MIN_TOPACEOUT = 0x455 TCP_BBR_ONE_RETRAN = 0x431 TCP_BBR_PACE_CROSS = 0x442 TCP_BBR_PACE_DEL_TAR = 0x43f + TCP_BBR_PACE_OH = 0x435 TCP_BBR_PACE_PER_SEC = 0x43e TCP_BBR_PACE_SEG_MAX = 0x440 TCP_BBR_PACE_SEG_MIN = 0x441 + TCP_BBR_POLICER_DETECT = 0x457 TCP_BBR_PROBE_RTT_GAIN = 0x44d TCP_BBR_PROBE_RTT_INT = 0x430 TCP_BBR_PROBE_RTT_LEN = 0x44e @@ -1478,12 +1582,18 @@ const ( TCP_BBR_REC_OVER_HPTS = 0x43a TCP_BBR_RETRAN_WTSO = 0x44b TCP_BBR_RWND_IS_APP = 0x42f + TCP_BBR_SEND_IWND_IN_TSO = 0x44f TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d TCP_BBR_STARTUP_LOSS_EXIT = 0x432 TCP_BBR_STARTUP_PG = 0x42d + TCP_BBR_TMR_PACE_OH = 0x448 + TCP_BBR_TSLIMITS = 0x434 + TCP_BBR_TSTMP_RAISES = 0x456 TCP_BBR_UNLIMITED = 0x43b TCP_BBR_USEDEL_RATE = 0x437 TCP_BBR_USE_LOWGAIN = 0x433 + TCP_BBR_USE_RACK_CHEAT = 0x450 + TCP_BBR_UTTER_MAX_TSO = 0x452 TCP_CA_NAME_MAX = 0x10 TCP_CCALGOOPT = 0x41 TCP_CONGESTION = 0x40 @@ -1523,6 +1633,7 @@ const ( TCP_PCAP_OUT = 0x800 TCP_RACK_EARLY_RECOV = 0x423 TCP_RACK_EARLY_SEG = 0x424 + TCP_RACK_GP_INCREASE = 0x446 TCP_RACK_IDLE_REDUCE_HIGH = 0x444 TCP_RACK_MIN_PACE = 0x445 TCP_RACK_MIN_PACE_SEG = 0x446 @@ -1536,7 +1647,6 @@ const ( TCP_RACK_PRR_SENDALOT = 0x421 TCP_RACK_REORD_FADE = 0x426 TCP_RACK_REORD_THRESH = 0x425 - TCP_RACK_SESS_CWV = 0x42a TCP_RACK_TLP_INC_VAR = 0x429 TCP_RACK_TLP_REDUCE = 0x41c TCP_RACK_TLP_THRESH = 0x427 @@ -1676,12 +1786,13 @@ const ( EIDRM = syscall.Errno(0x52) EILSEQ = syscall.Errno(0x56) EINPROGRESS = syscall.Errno(0x24) + EINTEGRITY = syscall.Errno(0x61) EINTR = syscall.Errno(0x4) EINVAL = syscall.Errno(0x16) EIO = syscall.Errno(0x5) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x60) + ELAST = syscall.Errno(0x61) ELOOP = syscall.Errno(0x3e) EMFILE = syscall.Errno(0x18) EMLINK = syscall.Errno(0x1f) @@ -1824,7 +1935,7 @@ var errorList = [...]struct { {32, "EPIPE", "broken pipe"}, {33, "EDOM", "numerical argument out of domain"}, {34, "ERANGE", "result too large"}, - {35, "EAGAIN", "resource temporarily unavailable"}, + {35, "EWOULDBLOCK", "resource temporarily unavailable"}, {36, "EINPROGRESS", "operation now in progress"}, {37, "EALREADY", "operation already in progress"}, {38, "ENOTSOCK", "socket operation on non-socket"}, @@ -1886,6 +1997,7 @@ var errorList = [...]struct { {94, "ECAPMODE", "not permitted in capability mode"}, {95, "ENOTRECOVERABLE", "state not recoverable"}, {96, "EOWNERDEAD", "previous owner died"}, + {97, "EINTEGRITY", "integrity check failed"}, } // Signal table diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go index 4acd101..dd9163f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,freebsd +//go:build amd64 && freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -150,6 +150,7 @@ const ( BIOCSETF = 0x80104267 BIOCSETFNR = 0x80104282 BIOCSETIF = 0x8020426c + BIOCSETVLANPCP = 0x80044285 BIOCSETWF = 0x8010427b BIOCSETZBUF = 0x80184281 BIOCSHDRCMPLT = 0x80044275 @@ -339,6 +340,12 @@ const ( CLOCK_UPTIME_FAST = 0x8 CLOCK_UPTIME_PRECISE = 0x7 CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x30000 CS5 = 0x0 @@ -440,7 +447,7 @@ const ( DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 DLT_INFINIBAND = 0xf7 DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 + DLT_IPMB_KONTRON = 0xc7 DLT_IPMB_LINUX = 0xd1 DLT_IPMI_HPM_2 = 0x104 DLT_IPNET = 0xe2 @@ -480,10 +487,11 @@ const ( DLT_LINUX_LAPD = 0xb1 DLT_LINUX_PPP_WITHDIRECTION = 0xa6 DLT_LINUX_SLL = 0x71 + DLT_LINUX_SLL2 = 0x114 DLT_LOOP = 0x6c DLT_LORATAP = 0x10e DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x113 + DLT_MATCHING_MAX = 0x114 DLT_MATCHING_MIN = 0x68 DLT_MFR = 0xb6 DLT_MOST = 0xd3 @@ -727,6 +735,7 @@ const ( IPPROTO_CMTP = 0x26 IPPROTO_CPHB = 0x49 IPPROTO_CPNX = 0x48 + IPPROTO_DCCP = 0x21 IPPROTO_DDP = 0x25 IPPROTO_DGP = 0x56 IPPROTO_DIVERT = 0x102 @@ -807,7 +816,6 @@ const ( IPPROTO_SCTP = 0x84 IPPROTO_SDRP = 0x2a IPPROTO_SEND = 0x103 - IPPROTO_SEP = 0x21 IPPROTO_SHIM6 = 0x8c IPPROTO_SKIP = 0x39 IPPROTO_SPACER = 0x7fff @@ -904,6 +912,7 @@ const ( IPV6_V6ONLY = 0x1b IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 + IPV6_VLAN_PCP = 0x4b IP_ADD_MEMBERSHIP = 0xc IP_ADD_SOURCE_MEMBERSHIP = 0x46 IP_BINDANY = 0x18 @@ -982,8 +991,12 @@ const ( IP_TOS = 0x3 IP_TTL = 0x4 IP_UNBLOCK_SOURCE = 0x49 + IP_VLAN_PCP = 0x4b ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -991,6 +1004,10 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1168,6 +1185,8 @@ const ( O_NONBLOCK = 0x4 O_RDONLY = 0x0 O_RDWR = 0x2 + O_RESOLVE_BENEATH = 0x800000 + O_SEARCH = 0x40000 O_SHLOCK = 0x10 O_SYNC = 0x80 O_TRUNC = 0x400 @@ -1178,6 +1197,10 @@ const ( PARMRK = 0x8 PARODD = 0x2000 PENDIN = 0x20000000 + PIOD_READ_D = 0x1 + PIOD_READ_I = 0x3 + PIOD_WRITE_D = 0x2 + PIOD_WRITE_I = 0x4 PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 @@ -1185,6 +1208,58 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 + PTRACE_DEFAULT = 0x1 + PTRACE_EXEC = 0x1 + PTRACE_FORK = 0x8 + PTRACE_LWP = 0x10 + PTRACE_SCE = 0x2 + PTRACE_SCX = 0x4 + PTRACE_SYSCALL = 0x6 + PTRACE_VFORK = 0x20 + PT_ATTACH = 0xa + PT_CLEARSTEP = 0x10 + PT_CONTINUE = 0x7 + PT_DETACH = 0xb + PT_FIRSTMACH = 0x40 + PT_FOLLOW_FORK = 0x17 + PT_GETDBREGS = 0x25 + PT_GETFPREGS = 0x23 + PT_GETFSBASE = 0x47 + PT_GETGSBASE = 0x49 + PT_GETLWPLIST = 0xf + PT_GETNUMLWPS = 0xe + PT_GETREGS = 0x21 + PT_GETXSTATE = 0x45 + PT_GETXSTATE_INFO = 0x44 + PT_GET_EVENT_MASK = 0x19 + PT_GET_SC_ARGS = 0x1b + PT_GET_SC_RET = 0x1c + PT_IO = 0xc + PT_KILL = 0x8 + PT_LWPINFO = 0xd + PT_LWP_EVENTS = 0x18 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_RESUME = 0x13 + PT_SETDBREGS = 0x26 + PT_SETFPREGS = 0x24 + PT_SETFSBASE = 0x48 + PT_SETGSBASE = 0x4a + PT_SETREGS = 0x22 + PT_SETSTEP = 0x11 + PT_SETXSTATE = 0x46 + PT_SET_EVENT_MASK = 0x1a + PT_STEP = 0x9 + PT_SUSPEND = 0x12 + PT_SYSCALL = 0x16 + PT_TO_SCE = 0x14 + PT_TO_SCX = 0x15 + PT_TRACE_ME = 0x0 + PT_VM_ENTRY = 0x29 + PT_VM_TIMESTAMP = 0x28 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + P_ZONEID = 0xc RLIMIT_AS = 0xa RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1286,6 +1361,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1304,10 +1384,12 @@ const ( SIOCGHWADDR = 0xc020693e SIOCGI2C = 0xc020693d SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc044692d SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCAP = 0xc020691f SIOCGIFCONF = 0xc0106924 SIOCGIFDESCR = 0xc020692a + SIOCGIFDOWNREASON = 0xc058699a SIOCGIFDSTADDR = 0xc0206922 SIOCGIFFIB = 0xc020695c SIOCGIFFLAGS = 0xc0206911 @@ -1370,6 +1452,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 @@ -1397,6 +1480,7 @@ const ( SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x20000 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_REUSEPORT_LB = 0x10000 @@ -1455,22 +1539,40 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_FAST_OPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_PAD = 0x0 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_WINDOW = 0x3 TCP_BBR_ACK_COMP_ALG = 0x448 + TCP_BBR_ALGORITHM = 0x43b TCP_BBR_DRAIN_INC_EXTRA = 0x43c TCP_BBR_DRAIN_PG = 0x42e TCP_BBR_EXTRA_GAIN = 0x449 + TCP_BBR_EXTRA_STATE = 0x453 + TCP_BBR_FLOOR_MIN_TSO = 0x454 + TCP_BBR_HDWR_PACE = 0x451 + TCP_BBR_HOLD_TARGET = 0x436 TCP_BBR_IWINTSO = 0x42b TCP_BBR_LOWGAIN_FD = 0x436 TCP_BBR_LOWGAIN_HALF = 0x435 TCP_BBR_LOWGAIN_THRESH = 0x434 TCP_BBR_MAX_RTO = 0x439 TCP_BBR_MIN_RTO = 0x438 + TCP_BBR_MIN_TOPACEOUT = 0x455 TCP_BBR_ONE_RETRAN = 0x431 TCP_BBR_PACE_CROSS = 0x442 TCP_BBR_PACE_DEL_TAR = 0x43f + TCP_BBR_PACE_OH = 0x435 TCP_BBR_PACE_PER_SEC = 0x43e TCP_BBR_PACE_SEG_MAX = 0x440 TCP_BBR_PACE_SEG_MIN = 0x441 + TCP_BBR_POLICER_DETECT = 0x457 TCP_BBR_PROBE_RTT_GAIN = 0x44d TCP_BBR_PROBE_RTT_INT = 0x430 TCP_BBR_PROBE_RTT_LEN = 0x44e @@ -1479,12 +1581,18 @@ const ( TCP_BBR_REC_OVER_HPTS = 0x43a TCP_BBR_RETRAN_WTSO = 0x44b TCP_BBR_RWND_IS_APP = 0x42f + TCP_BBR_SEND_IWND_IN_TSO = 0x44f TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d TCP_BBR_STARTUP_LOSS_EXIT = 0x432 TCP_BBR_STARTUP_PG = 0x42d + TCP_BBR_TMR_PACE_OH = 0x448 + TCP_BBR_TSLIMITS = 0x434 + TCP_BBR_TSTMP_RAISES = 0x456 TCP_BBR_UNLIMITED = 0x43b TCP_BBR_USEDEL_RATE = 0x437 TCP_BBR_USE_LOWGAIN = 0x433 + TCP_BBR_USE_RACK_CHEAT = 0x450 + TCP_BBR_UTTER_MAX_TSO = 0x452 TCP_CA_NAME_MAX = 0x10 TCP_CCALGOOPT = 0x41 TCP_CONGESTION = 0x40 @@ -1524,6 +1632,7 @@ const ( TCP_PCAP_OUT = 0x800 TCP_RACK_EARLY_RECOV = 0x423 TCP_RACK_EARLY_SEG = 0x424 + TCP_RACK_GP_INCREASE = 0x446 TCP_RACK_IDLE_REDUCE_HIGH = 0x444 TCP_RACK_MIN_PACE = 0x445 TCP_RACK_MIN_PACE_SEG = 0x446 @@ -1537,7 +1646,6 @@ const ( TCP_RACK_PRR_SENDALOT = 0x421 TCP_RACK_REORD_FADE = 0x426 TCP_RACK_REORD_THRESH = 0x425 - TCP_RACK_SESS_CWV = 0x42a TCP_RACK_TLP_INC_VAR = 0x429 TCP_RACK_TLP_REDUCE = 0x41c TCP_RACK_TLP_THRESH = 0x427 @@ -1675,12 +1783,13 @@ const ( EIDRM = syscall.Errno(0x52) EILSEQ = syscall.Errno(0x56) EINPROGRESS = syscall.Errno(0x24) + EINTEGRITY = syscall.Errno(0x61) EINTR = syscall.Errno(0x4) EINVAL = syscall.Errno(0x16) EIO = syscall.Errno(0x5) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x60) + ELAST = syscall.Errno(0x61) ELOOP = syscall.Errno(0x3e) EMFILE = syscall.Errno(0x18) EMLINK = syscall.Errno(0x1f) @@ -1823,7 +1932,7 @@ var errorList = [...]struct { {32, "EPIPE", "broken pipe"}, {33, "EDOM", "numerical argument out of domain"}, {34, "ERANGE", "result too large"}, - {35, "EAGAIN", "resource temporarily unavailable"}, + {35, "EWOULDBLOCK", "resource temporarily unavailable"}, {36, "EINPROGRESS", "operation now in progress"}, {37, "EALREADY", "operation already in progress"}, {38, "ENOTSOCK", "socket operation on non-socket"}, @@ -1885,6 +1994,7 @@ var errorList = [...]struct { {94, "ECAPMODE", "not permitted in capability mode"}, {95, "ENOTRECOVERABLE", "state not recoverable"}, {96, "EOWNERDEAD", "previous owner died"}, + {97, "EINTEGRITY", "integrity check failed"}, } // Signal table diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go index e471987..493a2a7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go @@ -1,7 +1,7 @@ // mkerrors.sh // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,freebsd +//go:build arm && freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go @@ -150,6 +150,7 @@ const ( BIOCSETF = 0x80084267 BIOCSETFNR = 0x80084282 BIOCSETIF = 0x8020426c + BIOCSETVLANPCP = 0x80044285 BIOCSETWF = 0x8008427b BIOCSETZBUF = 0x800c4281 BIOCSHDRCMPLT = 0x80044275 @@ -339,6 +340,12 @@ const ( CLOCK_UPTIME_FAST = 0x8 CLOCK_UPTIME_PRECISE = 0x7 CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x30000 CS5 = 0x0 @@ -355,7 +362,7 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0x18 CTL_NET = 0x4 - DIOCGATTR = 0xc144648e + DIOCGATTR = 0xc148648e DIOCGDELETE = 0x80106488 DIOCGFLUSH = 0x20006487 DIOCGFRONTSTUFF = 0x40086486 @@ -370,7 +377,7 @@ const ( DIOCGSTRIPESIZE = 0x4008648b DIOCSKERNELDUMP = 0x804c6490 DIOCSKERNELDUMP_FREEBSD11 = 0x80046485 - DIOCZONECMD = 0xc06c648f + DIOCZONECMD = 0xc078648f DLT_A429 = 0xb8 DLT_A653_ICM = 0xb9 DLT_AIRONET_HEADER = 0x78 @@ -400,7 +407,9 @@ const ( DLT_C_HDLC_WITH_DIR = 0xcd DLT_DBUS = 0xe7 DLT_DECT = 0xdd + DLT_DISPLAYPORT_AUX = 0x113 DLT_DOCSIS = 0x8f + DLT_DOCSIS31_XRA31 = 0x111 DLT_DVB_CI = 0xeb DLT_ECONET = 0x73 DLT_EN10MB = 0x1 @@ -410,6 +419,7 @@ const ( DLT_ERF = 0xc5 DLT_ERF_ETH = 0xaf DLT_ERF_POS = 0xb0 + DLT_ETHERNET_MPACKET = 0x112 DLT_FC_2 = 0xe0 DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 DLT_FDDI = 0xa @@ -437,7 +447,7 @@ const ( DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 DLT_INFINIBAND = 0xf7 DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 + DLT_IPMB_KONTRON = 0xc7 DLT_IPMB_LINUX = 0xd1 DLT_IPMI_HPM_2 = 0x104 DLT_IPNET = 0xe2 @@ -477,9 +487,11 @@ const ( DLT_LINUX_LAPD = 0xb1 DLT_LINUX_PPP_WITHDIRECTION = 0xa6 DLT_LINUX_SLL = 0x71 + DLT_LINUX_SLL2 = 0x114 DLT_LOOP = 0x6c + DLT_LORATAP = 0x10e DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x109 + DLT_MATCHING_MAX = 0x114 DLT_MATCHING_MIN = 0x68 DLT_MFR = 0xb6 DLT_MOST = 0xd3 @@ -495,7 +507,9 @@ const ( DLT_NFC_LLCP = 0xf5 DLT_NFLOG = 0xef DLT_NG40 = 0xf4 + DLT_NORDIC_BLE = 0x110 DLT_NULL = 0x0 + DLT_OPENFLOW = 0x10b DLT_PCI_EXP = 0x7d DLT_PFLOG = 0x75 DLT_PFSYNC = 0x79 @@ -519,15 +533,18 @@ const ( DLT_RTAC_SERIAL = 0xfa DLT_SCCP = 0x8e DLT_SCTP = 0xf8 + DLT_SDLC = 0x10c DLT_SITA = 0xc4 DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xd DLT_STANAG_5066_D_PDU = 0xed DLT_SUNATM = 0x7b DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TI_LLN_SNIFFER = 0x10d DLT_TZSP = 0x80 DLT_USB = 0xba DLT_USBPCAP = 0xf9 + DLT_USB_DARWIN = 0x10a DLT_USB_FREEBSD = 0xba DLT_USB_LINUX = 0xbd DLT_USB_LINUX_MMAPPED = 0xdc @@ -547,6 +564,7 @@ const ( DLT_USER7 = 0x9a DLT_USER8 = 0x9b DLT_USER9 = 0x9c + DLT_VSOCK = 0x10f DLT_WATTSTOPPER_DLM = 0x107 DLT_WIHART = 0xdf DLT_WIRESHARK_UPPER_PDU = 0xfc @@ -571,6 +589,7 @@ const ( ECHONL = 0x10 ECHOPRT = 0x20 EVFILT_AIO = -0x3 + EVFILT_EMPTY = -0xd EVFILT_FS = -0x9 EVFILT_LIO = -0xa EVFILT_PROC = -0x5 @@ -578,11 +597,12 @@ const ( EVFILT_READ = -0x1 EVFILT_SENDFILE = -0xc EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xc + EVFILT_SYSCOUNT = 0xd EVFILT_TIMER = -0x7 EVFILT_USER = -0xb EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 + EVNAMEMAP_NAME_SIZE = 0x40 EV_ADD = 0x1 EV_CLEAR = 0x20 EV_DELETE = 0x2 @@ -599,6 +619,7 @@ const ( EV_RECEIPT = 0x40 EV_SYSFLAGS = 0xf000 EXTA = 0x4b00 + EXTATTR_MAXNAMELEN = 0xff EXTATTR_NAMESPACE_EMPTY = 0x0 EXTATTR_NAMESPACE_SYSTEM = 0x2 EXTATTR_NAMESPACE_USER = 0x1 @@ -640,6 +661,7 @@ const ( IEXTEN = 0x400 IFAN_ARRIVAL = 0x0 IFAN_DEPARTURE = 0x1 + IFCAP_WOL_MAGIC = 0x2000 IFF_ALLMULTI = 0x200 IFF_ALTPHYS = 0x4000 IFF_BROADCAST = 0x2 @@ -656,6 +678,7 @@ const ( IFF_MONITOR = 0x40000 IFF_MULTICAST = 0x8000 IFF_NOARP = 0x80 + IFF_NOGROUP = 0x800000 IFF_OACTIVE = 0x400 IFF_POINTOPOINT = 0x10 IFF_PPROMISC = 0x20000 @@ -712,6 +735,7 @@ const ( IPPROTO_CMTP = 0x26 IPPROTO_CPHB = 0x49 IPPROTO_CPNX = 0x48 + IPPROTO_DCCP = 0x21 IPPROTO_DDP = 0x25 IPPROTO_DGP = 0x56 IPPROTO_DIVERT = 0x102 @@ -792,7 +816,6 @@ const ( IPPROTO_SCTP = 0x84 IPPROTO_SDRP = 0x2a IPPROTO_SEND = 0x103 - IPPROTO_SEP = 0x21 IPPROTO_SHIM6 = 0x8c IPPROTO_SKIP = 0x39 IPPROTO_SPACER = 0x7fff @@ -830,6 +853,7 @@ const ( IPV6_DSTOPTS = 0x32 IPV6_FLOWID = 0x43 IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_LEN = 0x14 IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FLOWTYPE = 0x44 IPV6_FRAGTTL = 0x78 @@ -850,13 +874,13 @@ const ( IPV6_MAX_GROUP_SRC_FILTER = 0x200 IPV6_MAX_MEMBERSHIPS = 0xfff IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f IPV6_MMTU = 0x500 IPV6_MSFILTER = 0x4a IPV6_MULTICAST_HOPS = 0xa IPV6_MULTICAST_IF = 0x9 IPV6_MULTICAST_LOOP = 0xb IPV6_NEXTHOP = 0x30 + IPV6_ORIGDSTADDR = 0x48 IPV6_PATHMTU = 0x2c IPV6_PKTINFO = 0x2e IPV6_PORTRANGE = 0xe @@ -868,6 +892,7 @@ const ( IPV6_RECVFLOWID = 0x46 IPV6_RECVHOPLIMIT = 0x25 IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVORIGDSTADDR = 0x48 IPV6_RECVPATHMTU = 0x2b IPV6_RECVPKTINFO = 0x24 IPV6_RECVRSSBUCKETID = 0x47 @@ -887,6 +912,7 @@ const ( IPV6_V6ONLY = 0x1b IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 + IPV6_VLAN_PCP = 0x4b IP_ADD_MEMBERSHIP = 0xc IP_ADD_SOURCE_MEMBERSHIP = 0x46 IP_BINDANY = 0x18 @@ -928,10 +954,8 @@ const ( IP_MAX_MEMBERSHIPS = 0xfff IP_MAX_SOCK_MUTE_FILTER = 0x80 IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MAX_SOURCE_FILTER = 0x400 IP_MF = 0x2000 IP_MINTTL = 0x42 - IP_MIN_MEMBERSHIPS = 0x1f IP_MSFILTER = 0x4a IP_MSS = 0x240 IP_MULTICAST_IF = 0x9 @@ -941,6 +965,7 @@ const ( IP_OFFMASK = 0x1fff IP_ONESBCAST = 0x17 IP_OPTIONS = 0x1 + IP_ORIGDSTADDR = 0x1b IP_PORTRANGE = 0x13 IP_PORTRANGE_DEFAULT = 0x0 IP_PORTRANGE_HIGH = 0x1 @@ -949,6 +974,7 @@ const ( IP_RECVFLOWID = 0x5d IP_RECVIF = 0x14 IP_RECVOPTS = 0x5 + IP_RECVORIGDSTADDR = 0x1b IP_RECVRETOPTS = 0x6 IP_RECVRSSBUCKETID = 0x5e IP_RECVTOS = 0x44 @@ -965,8 +991,12 @@ const ( IP_TOS = 0x3 IP_TTL = 0x4 IP_UNBLOCK_SOURCE = 0x49 + IP_VLAN_PCP = 0x4b ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -974,6 +1004,10 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1010,6 +1044,15 @@ const ( MAP_RESERVED0100 = 0x100 MAP_SHARED = 0x1 MAP_STACK = 0x400 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MNT_ACLS = 0x8000000 @@ -1050,10 +1093,12 @@ const ( MNT_SUSPEND = 0x4 MNT_SYNCHRONOUS = 0x2 MNT_UNION = 0x20 + MNT_UNTRUSTED = 0x800000000 MNT_UPDATE = 0x10000 - MNT_UPDATEMASK = 0x2d8d0807e + MNT_UPDATEMASK = 0xad8d0807e MNT_USER = 0x8000 - MNT_VISFLAGMASK = 0x3fef0ffff + MNT_VERIFIED = 0x400000000 + MNT_VISFLAGMASK = 0xffef0ffff MNT_WAIT = 0x1 MSG_CMSG_CLOEXEC = 0x40000 MSG_COMPAT = 0x8000 @@ -1082,6 +1127,7 @@ const ( NFDBITS = 0x20 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 + NOTE_ABSTIME = 0x10 NOTE_ATTRIB = 0x8 NOTE_CHILD = 0x4 NOTE_CLOSE = 0x100 @@ -1138,6 +1184,8 @@ const ( O_NONBLOCK = 0x4 O_RDONLY = 0x0 O_RDWR = 0x2 + O_RESOLVE_BENEATH = 0x800000 + O_SEARCH = 0x40000 O_SHLOCK = 0x10 O_SYNC = 0x80 O_TRUNC = 0x400 @@ -1148,6 +1196,10 @@ const ( PARMRK = 0x8 PARODD = 0x2000 PENDIN = 0x20000000 + PIOD_READ_D = 0x1 + PIOD_READ_I = 0x3 + PIOD_WRITE_D = 0x2 + PIOD_WRITE_I = 0x4 PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 @@ -1155,6 +1207,53 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 + PTRACE_DEFAULT = 0x1 + PTRACE_EXEC = 0x1 + PTRACE_FORK = 0x8 + PTRACE_LWP = 0x10 + PTRACE_SCE = 0x2 + PTRACE_SCX = 0x4 + PTRACE_SYSCALL = 0x6 + PTRACE_VFORK = 0x20 + PT_ATTACH = 0xa + PT_CLEARSTEP = 0x10 + PT_CONTINUE = 0x7 + PT_DETACH = 0xb + PT_FIRSTMACH = 0x40 + PT_FOLLOW_FORK = 0x17 + PT_GETDBREGS = 0x25 + PT_GETFPREGS = 0x23 + PT_GETLWPLIST = 0xf + PT_GETNUMLWPS = 0xe + PT_GETREGS = 0x21 + PT_GETVFPREGS = 0x40 + PT_GET_EVENT_MASK = 0x19 + PT_GET_SC_ARGS = 0x1b + PT_GET_SC_RET = 0x1c + PT_IO = 0xc + PT_KILL = 0x8 + PT_LWPINFO = 0xd + PT_LWP_EVENTS = 0x18 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_RESUME = 0x13 + PT_SETDBREGS = 0x26 + PT_SETFPREGS = 0x24 + PT_SETREGS = 0x22 + PT_SETSTEP = 0x11 + PT_SETVFPREGS = 0x41 + PT_SET_EVENT_MASK = 0x1a + PT_STEP = 0x9 + PT_SUSPEND = 0x12 + PT_SYSCALL = 0x16 + PT_TO_SCE = 0x14 + PT_TO_SCX = 0x15 + PT_TRACE_ME = 0x0 + PT_VM_ENTRY = 0x29 + PT_VM_TIMESTAMP = 0x28 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + P_ZONEID = 0xc RLIMIT_AS = 0xa RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1236,7 +1335,6 @@ const ( RTV_WEIGHT = 0x100 RT_ALL_FIBS = -0x1 RT_BLACKHOLE = 0x40 - RT_CACHING_CONTEXT = 0x1 RT_DEFAULT_FIB = 0x0 RT_HAS_GW = 0x80 RT_HAS_HEADER = 0x10 @@ -1246,15 +1344,22 @@ const ( RT_LLE_CACHE = 0x100 RT_MAY_LOOP = 0x8 RT_MAY_LOOP_BIT = 0x3 - RT_NORTREF = 0x2 RT_REJECT = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 RUSAGE_THREAD = 0x1 SCM_BINTIME = 0x4 SCM_CREDS = 0x3 + SCM_MONOTONIC = 0x6 + SCM_REALTIME = 0x5 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 + SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1273,10 +1378,12 @@ const ( SIOCGHWADDR = 0xc020693e SIOCGI2C = 0xc020693d SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc044692d SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCAP = 0xc020691f SIOCGIFCONF = 0xc0086924 SIOCGIFDESCR = 0xc020692a + SIOCGIFDOWNREASON = 0xc058699a SIOCGIFDSTADDR = 0xc0206922 SIOCGIFFIB = 0xc020695c SIOCGIFFLAGS = 0xc0206911 @@ -1292,8 +1399,11 @@ const ( SIOCGIFPDSTADDR = 0xc0206948 SIOCGIFPHYS = 0xc0206935 SIOCGIFPSRCADDR = 0xc0206947 + SIOCGIFRSSHASH = 0xc0186997 + SIOCGIFRSSKEY = 0xc0946996 SIOCGIFSTATUS = 0xc331693b SIOCGIFXMEDIA = 0xc028698b + SIOCGLANPCP = 0xc0206998 SIOCGLOWAT = 0x40047303 SIOCGPGRP = 0x40047309 SIOCGPRIVATE_0 = 0xc0206950 @@ -1324,6 +1434,7 @@ const ( SIOCSIFPHYS = 0x80206936 SIOCSIFRVNET = 0xc020695b SIOCSIFVNET = 0xc020695a + SIOCSLANPCP = 0x80206999 SIOCSLOWAT = 0x80047302 SIOCSPGRP = 0x80047308 SIOCSTUNFIB = 0x8020695f @@ -1335,6 +1446,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 @@ -1342,6 +1454,7 @@ const ( SO_BINTIME = 0x2000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1019 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 @@ -1350,6 +1463,7 @@ const ( SO_LISTENINCQLEN = 0x1013 SO_LISTENQLEN = 0x1012 SO_LISTENQLIMIT = 0x1011 + SO_MAX_PACING_RATE = 0x1018 SO_NOSIGPIPE = 0x800 SO_NO_DDP = 0x8000 SO_NO_OFFLOAD = 0x4000 @@ -1360,13 +1474,22 @@ const ( SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x20000 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 + SO_REUSEPORT_LB = 0x10000 SO_SETFIB = 0x1014 SO_SNDBUF = 0x1001 SO_SNDLOWAT = 0x1003 SO_SNDTIMEO = 0x1005 SO_TIMESTAMP = 0x400 + SO_TS_BINTIME = 0x1 + SO_TS_CLOCK = 0x1017 + SO_TS_CLOCK_MAX = 0x3 + SO_TS_DEFAULT = 0x0 + SO_TS_MONOTONIC = 0x3 + SO_TS_REALTIME = 0x2 + SO_TS_REALTIME_MICRO = 0x0 SO_TYPE = 0x1008 SO_USELOOPBACK = 0x40 SO_USER_COOKIE = 0x1015 @@ -1410,10 +1533,69 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_FAST_OPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_PAD = 0x0 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_WINDOW = 0x3 + TCP_BBR_ACK_COMP_ALG = 0x448 + TCP_BBR_ALGORITHM = 0x43b + TCP_BBR_DRAIN_INC_EXTRA = 0x43c + TCP_BBR_DRAIN_PG = 0x42e + TCP_BBR_EXTRA_GAIN = 0x449 + TCP_BBR_EXTRA_STATE = 0x453 + TCP_BBR_FLOOR_MIN_TSO = 0x454 + TCP_BBR_HDWR_PACE = 0x451 + TCP_BBR_HOLD_TARGET = 0x436 + TCP_BBR_IWINTSO = 0x42b + TCP_BBR_LOWGAIN_FD = 0x436 + TCP_BBR_LOWGAIN_HALF = 0x435 + TCP_BBR_LOWGAIN_THRESH = 0x434 + TCP_BBR_MAX_RTO = 0x439 + TCP_BBR_MIN_RTO = 0x438 + TCP_BBR_MIN_TOPACEOUT = 0x455 + TCP_BBR_ONE_RETRAN = 0x431 + TCP_BBR_PACE_CROSS = 0x442 + TCP_BBR_PACE_DEL_TAR = 0x43f + TCP_BBR_PACE_OH = 0x435 + TCP_BBR_PACE_PER_SEC = 0x43e + TCP_BBR_PACE_SEG_MAX = 0x440 + TCP_BBR_PACE_SEG_MIN = 0x441 + TCP_BBR_POLICER_DETECT = 0x457 + TCP_BBR_PROBE_RTT_GAIN = 0x44d + TCP_BBR_PROBE_RTT_INT = 0x430 + TCP_BBR_PROBE_RTT_LEN = 0x44e + TCP_BBR_RACK_RTT_USE = 0x44a + TCP_BBR_RECFORCE = 0x42c + TCP_BBR_REC_OVER_HPTS = 0x43a + TCP_BBR_RETRAN_WTSO = 0x44b + TCP_BBR_RWND_IS_APP = 0x42f + TCP_BBR_SEND_IWND_IN_TSO = 0x44f + TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d + TCP_BBR_STARTUP_LOSS_EXIT = 0x432 + TCP_BBR_STARTUP_PG = 0x42d + TCP_BBR_TMR_PACE_OH = 0x448 + TCP_BBR_TSLIMITS = 0x434 + TCP_BBR_TSTMP_RAISES = 0x456 + TCP_BBR_UNLIMITED = 0x43b + TCP_BBR_USEDEL_RATE = 0x437 + TCP_BBR_USE_LOWGAIN = 0x433 + TCP_BBR_USE_RACK_CHEAT = 0x450 + TCP_BBR_UTTER_MAX_TSO = 0x452 TCP_CA_NAME_MAX = 0x10 TCP_CCALGOOPT = 0x41 TCP_CONGESTION = 0x40 + TCP_DATA_AFTER_CLOSE = 0x44c + TCP_DELACK = 0x48 TCP_FASTOPEN = 0x401 + TCP_FASTOPEN_MAX_COOKIE_LEN = 0x10 + TCP_FASTOPEN_MIN_COOKIE_LEN = 0x4 + TCP_FASTOPEN_PSK_LEN = 0x10 TCP_FUNCTION_BLK = 0x2000 TCP_FUNCTION_NAME_LEN_MAX = 0x20 TCP_INFO = 0x20 @@ -1421,6 +1603,12 @@ const ( TCP_KEEPIDLE = 0x100 TCP_KEEPINIT = 0x80 TCP_KEEPINTVL = 0x200 + TCP_LOG = 0x22 + TCP_LOGBUF = 0x23 + TCP_LOGDUMP = 0x25 + TCP_LOGDUMPID = 0x26 + TCP_LOGID = 0x24 + TCP_LOG_ID_LEN = 0x40 TCP_MAXBURST = 0x4 TCP_MAXHLEN = 0x3c TCP_MAXOLEN = 0x28 @@ -1436,8 +1624,30 @@ const ( TCP_NOPUSH = 0x4 TCP_PCAP_IN = 0x1000 TCP_PCAP_OUT = 0x800 + TCP_RACK_EARLY_RECOV = 0x423 + TCP_RACK_EARLY_SEG = 0x424 + TCP_RACK_GP_INCREASE = 0x446 + TCP_RACK_IDLE_REDUCE_HIGH = 0x444 + TCP_RACK_MIN_PACE = 0x445 + TCP_RACK_MIN_PACE_SEG = 0x446 + TCP_RACK_MIN_TO = 0x422 + TCP_RACK_PACE_ALWAYS = 0x41f + TCP_RACK_PACE_MAX_SEG = 0x41e + TCP_RACK_PACE_REDUCE = 0x41d + TCP_RACK_PKT_DELAY = 0x428 + TCP_RACK_PROP = 0x41b + TCP_RACK_PROP_RATE = 0x420 + TCP_RACK_PRR_SENDALOT = 0x421 + TCP_RACK_REORD_FADE = 0x426 + TCP_RACK_REORD_THRESH = 0x425 + TCP_RACK_TLP_INC_VAR = 0x429 + TCP_RACK_TLP_REDUCE = 0x41c + TCP_RACK_TLP_THRESH = 0x427 + TCP_RACK_TLP_USE = 0x447 TCP_VENDOR = 0x80000000 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 TIOCCONS = 0x80047462 @@ -1501,6 +1711,8 @@ const ( TIOCTIMESTAMP = 0x40107459 TIOCUCNTL = 0x80047466 TOSTOP = 0x400000 + UTIME_NOW = -0x1 + UTIME_OMIT = -0x2 VDISCARD = 0xf VDSUSP = 0xb VEOF = 0x0 @@ -1565,12 +1777,13 @@ const ( EIDRM = syscall.Errno(0x52) EILSEQ = syscall.Errno(0x56) EINPROGRESS = syscall.Errno(0x24) + EINTEGRITY = syscall.Errno(0x61) EINTR = syscall.Errno(0x4) EINVAL = syscall.Errno(0x16) EIO = syscall.Errno(0x5) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x60) + ELAST = syscall.Errno(0x61) ELOOP = syscall.Errno(0x3e) EMFILE = syscall.Errno(0x18) EMLINK = syscall.Errno(0x1f) @@ -1713,7 +1926,7 @@ var errorList = [...]struct { {32, "EPIPE", "broken pipe"}, {33, "EDOM", "numerical argument out of domain"}, {34, "ERANGE", "result too large"}, - {35, "EAGAIN", "resource temporarily unavailable"}, + {35, "EWOULDBLOCK", "resource temporarily unavailable"}, {36, "EINPROGRESS", "operation now in progress"}, {37, "EALREADY", "operation already in progress"}, {38, "ENOTSOCK", "socket operation on non-socket"}, @@ -1775,6 +1988,7 @@ var errorList = [...]struct { {94, "ECAPMODE", "not permitted in capability mode"}, {95, "ENOTRECOVERABLE", "state not recoverable"}, {96, "EOWNERDEAD", "previous owner died"}, + {97, "EINTEGRITY", "integrity check failed"}, } // Signal table diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go index 5e49769..8b437b3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,freebsd +//go:build arm64 && freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -150,6 +150,7 @@ const ( BIOCSETF = 0x80104267 BIOCSETFNR = 0x80104282 BIOCSETIF = 0x8020426c + BIOCSETVLANPCP = 0x80044285 BIOCSETWF = 0x8010427b BIOCSETZBUF = 0x80184281 BIOCSHDRCMPLT = 0x80044275 @@ -339,6 +340,12 @@ const ( CLOCK_UPTIME_FAST = 0x8 CLOCK_UPTIME_PRECISE = 0x7 CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x30000 CS5 = 0x0 @@ -440,7 +447,7 @@ const ( DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 DLT_INFINIBAND = 0xf7 DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 + DLT_IPMB_KONTRON = 0xc7 DLT_IPMB_LINUX = 0xd1 DLT_IPMI_HPM_2 = 0x104 DLT_IPNET = 0xe2 @@ -480,10 +487,11 @@ const ( DLT_LINUX_LAPD = 0xb1 DLT_LINUX_PPP_WITHDIRECTION = 0xa6 DLT_LINUX_SLL = 0x71 + DLT_LINUX_SLL2 = 0x114 DLT_LOOP = 0x6c DLT_LORATAP = 0x10e DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x113 + DLT_MATCHING_MAX = 0x114 DLT_MATCHING_MIN = 0x68 DLT_MFR = 0xb6 DLT_MOST = 0xd3 @@ -727,6 +735,7 @@ const ( IPPROTO_CMTP = 0x26 IPPROTO_CPHB = 0x49 IPPROTO_CPNX = 0x48 + IPPROTO_DCCP = 0x21 IPPROTO_DDP = 0x25 IPPROTO_DGP = 0x56 IPPROTO_DIVERT = 0x102 @@ -807,7 +816,6 @@ const ( IPPROTO_SCTP = 0x84 IPPROTO_SDRP = 0x2a IPPROTO_SEND = 0x103 - IPPROTO_SEP = 0x21 IPPROTO_SHIM6 = 0x8c IPPROTO_SKIP = 0x39 IPPROTO_SPACER = 0x7fff @@ -904,6 +912,7 @@ const ( IPV6_V6ONLY = 0x1b IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 + IPV6_VLAN_PCP = 0x4b IP_ADD_MEMBERSHIP = 0xc IP_ADD_SOURCE_MEMBERSHIP = 0x46 IP_BINDANY = 0x18 @@ -982,8 +991,12 @@ const ( IP_TOS = 0x3 IP_TTL = 0x4 IP_UNBLOCK_SOURCE = 0x49 + IP_VLAN_PCP = 0x4b ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -991,6 +1004,10 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1168,6 +1185,8 @@ const ( O_NONBLOCK = 0x4 O_RDONLY = 0x0 O_RDWR = 0x2 + O_RESOLVE_BENEATH = 0x800000 + O_SEARCH = 0x40000 O_SHLOCK = 0x10 O_SYNC = 0x80 O_TRUNC = 0x400 @@ -1178,6 +1197,10 @@ const ( PARMRK = 0x8 PARODD = 0x2000 PENDIN = 0x20000000 + PIOD_READ_D = 0x1 + PIOD_READ_I = 0x3 + PIOD_WRITE_D = 0x2 + PIOD_WRITE_I = 0x4 PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 @@ -1185,6 +1208,51 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 + PTRACE_DEFAULT = 0x1 + PTRACE_EXEC = 0x1 + PTRACE_FORK = 0x8 + PTRACE_LWP = 0x10 + PTRACE_SCE = 0x2 + PTRACE_SCX = 0x4 + PTRACE_SYSCALL = 0x6 + PTRACE_VFORK = 0x20 + PT_ATTACH = 0xa + PT_CLEARSTEP = 0x10 + PT_CONTINUE = 0x7 + PT_DETACH = 0xb + PT_FIRSTMACH = 0x40 + PT_FOLLOW_FORK = 0x17 + PT_GETDBREGS = 0x25 + PT_GETFPREGS = 0x23 + PT_GETLWPLIST = 0xf + PT_GETNUMLWPS = 0xe + PT_GETREGS = 0x21 + PT_GET_EVENT_MASK = 0x19 + PT_GET_SC_ARGS = 0x1b + PT_GET_SC_RET = 0x1c + PT_IO = 0xc + PT_KILL = 0x8 + PT_LWPINFO = 0xd + PT_LWP_EVENTS = 0x18 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_RESUME = 0x13 + PT_SETDBREGS = 0x26 + PT_SETFPREGS = 0x24 + PT_SETREGS = 0x22 + PT_SETSTEP = 0x11 + PT_SET_EVENT_MASK = 0x1a + PT_STEP = 0x9 + PT_SUSPEND = 0x12 + PT_SYSCALL = 0x16 + PT_TO_SCE = 0x14 + PT_TO_SCX = 0x15 + PT_TRACE_ME = 0x0 + PT_VM_ENTRY = 0x29 + PT_VM_TIMESTAMP = 0x28 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + P_ZONEID = 0xc RLIMIT_AS = 0xa RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1286,6 +1354,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1304,10 +1377,12 @@ const ( SIOCGHWADDR = 0xc020693e SIOCGI2C = 0xc020693d SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc044692d SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCAP = 0xc020691f SIOCGIFCONF = 0xc0106924 SIOCGIFDESCR = 0xc020692a + SIOCGIFDOWNREASON = 0xc058699a SIOCGIFDSTADDR = 0xc0206922 SIOCGIFFIB = 0xc020695c SIOCGIFFLAGS = 0xc0206911 @@ -1370,6 +1445,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 @@ -1397,6 +1473,7 @@ const ( SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x20000 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_REUSEPORT_LB = 0x10000 @@ -1455,22 +1532,40 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_FAST_OPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_PAD = 0x0 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_WINDOW = 0x3 TCP_BBR_ACK_COMP_ALG = 0x448 + TCP_BBR_ALGORITHM = 0x43b TCP_BBR_DRAIN_INC_EXTRA = 0x43c TCP_BBR_DRAIN_PG = 0x42e TCP_BBR_EXTRA_GAIN = 0x449 + TCP_BBR_EXTRA_STATE = 0x453 + TCP_BBR_FLOOR_MIN_TSO = 0x454 + TCP_BBR_HDWR_PACE = 0x451 + TCP_BBR_HOLD_TARGET = 0x436 TCP_BBR_IWINTSO = 0x42b TCP_BBR_LOWGAIN_FD = 0x436 TCP_BBR_LOWGAIN_HALF = 0x435 TCP_BBR_LOWGAIN_THRESH = 0x434 TCP_BBR_MAX_RTO = 0x439 TCP_BBR_MIN_RTO = 0x438 + TCP_BBR_MIN_TOPACEOUT = 0x455 TCP_BBR_ONE_RETRAN = 0x431 TCP_BBR_PACE_CROSS = 0x442 TCP_BBR_PACE_DEL_TAR = 0x43f + TCP_BBR_PACE_OH = 0x435 TCP_BBR_PACE_PER_SEC = 0x43e TCP_BBR_PACE_SEG_MAX = 0x440 TCP_BBR_PACE_SEG_MIN = 0x441 + TCP_BBR_POLICER_DETECT = 0x457 TCP_BBR_PROBE_RTT_GAIN = 0x44d TCP_BBR_PROBE_RTT_INT = 0x430 TCP_BBR_PROBE_RTT_LEN = 0x44e @@ -1479,12 +1574,18 @@ const ( TCP_BBR_REC_OVER_HPTS = 0x43a TCP_BBR_RETRAN_WTSO = 0x44b TCP_BBR_RWND_IS_APP = 0x42f + TCP_BBR_SEND_IWND_IN_TSO = 0x44f TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d TCP_BBR_STARTUP_LOSS_EXIT = 0x432 TCP_BBR_STARTUP_PG = 0x42d + TCP_BBR_TMR_PACE_OH = 0x448 + TCP_BBR_TSLIMITS = 0x434 + TCP_BBR_TSTMP_RAISES = 0x456 TCP_BBR_UNLIMITED = 0x43b TCP_BBR_USEDEL_RATE = 0x437 TCP_BBR_USE_LOWGAIN = 0x433 + TCP_BBR_USE_RACK_CHEAT = 0x450 + TCP_BBR_UTTER_MAX_TSO = 0x452 TCP_CA_NAME_MAX = 0x10 TCP_CCALGOOPT = 0x41 TCP_CONGESTION = 0x40 @@ -1524,6 +1625,7 @@ const ( TCP_PCAP_OUT = 0x800 TCP_RACK_EARLY_RECOV = 0x423 TCP_RACK_EARLY_SEG = 0x424 + TCP_RACK_GP_INCREASE = 0x446 TCP_RACK_IDLE_REDUCE_HIGH = 0x444 TCP_RACK_MIN_PACE = 0x445 TCP_RACK_MIN_PACE_SEG = 0x446 @@ -1537,7 +1639,6 @@ const ( TCP_RACK_PRR_SENDALOT = 0x421 TCP_RACK_REORD_FADE = 0x426 TCP_RACK_REORD_THRESH = 0x425 - TCP_RACK_SESS_CWV = 0x42a TCP_RACK_TLP_INC_VAR = 0x429 TCP_RACK_TLP_REDUCE = 0x41c TCP_RACK_TLP_THRESH = 0x427 @@ -1676,12 +1777,13 @@ const ( EIDRM = syscall.Errno(0x52) EILSEQ = syscall.Errno(0x56) EINPROGRESS = syscall.Errno(0x24) + EINTEGRITY = syscall.Errno(0x61) EINTR = syscall.Errno(0x4) EINVAL = syscall.Errno(0x16) EIO = syscall.Errno(0x5) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x60) + ELAST = syscall.Errno(0x61) ELOOP = syscall.Errno(0x3e) EMFILE = syscall.Errno(0x18) EMLINK = syscall.Errno(0x1f) @@ -1824,7 +1926,7 @@ var errorList = [...]struct { {32, "EPIPE", "broken pipe"}, {33, "EDOM", "numerical argument out of domain"}, {34, "ERANGE", "result too large"}, - {35, "EAGAIN", "resource temporarily unavailable"}, + {35, "EWOULDBLOCK", "resource temporarily unavailable"}, {36, "EINPROGRESS", "operation now in progress"}, {37, "EALREADY", "operation already in progress"}, {38, "ENOTSOCK", "socket operation on non-socket"}, @@ -1886,6 +1988,7 @@ var errorList = [...]struct { {94, "ECAPMODE", "not permitted in capability mode"}, {95, "ENOTRECOVERABLE", "state not recoverable"}, {96, "EOWNERDEAD", "previous owner died"}, + {97, "EINTEGRITY", "integrity check failed"}, } // Signal table diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go new file mode 100644 index 0000000..67c02dd --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go @@ -0,0 +1,2147 @@ +// mkerrors.sh -m64 +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build riscv64 && freebsd + +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs -- -m64 _const.go + +package unix + +import "syscall" + +const ( + AF_APPLETALK = 0x10 + AF_ARP = 0x23 + AF_ATM = 0x1e + AF_BLUETOOTH = 0x24 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1a + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_HYPERV = 0x2b + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1c + AF_INET6_SDP = 0x2a + AF_INET_SDP = 0x28 + AF_IPX = 0x17 + AF_ISDN = 0x1a + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x2b + AF_NATM = 0x1d + AF_NETBIOS = 0x6 + AF_NETGRAPH = 0x20 + AF_OSI = 0x7 + AF_PUP = 0x4 + AF_ROUTE = 0x11 + AF_SCLUSTER = 0x22 + AF_SIP = 0x18 + AF_SLOW = 0x21 + AF_SNA = 0xb + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_VENDOR00 = 0x27 + AF_VENDOR01 = 0x29 + AF_VENDOR03 = 0x2d + AF_VENDOR04 = 0x2f + AF_VENDOR05 = 0x31 + AF_VENDOR06 = 0x33 + AF_VENDOR07 = 0x35 + AF_VENDOR08 = 0x37 + AF_VENDOR09 = 0x39 + AF_VENDOR10 = 0x3b + AF_VENDOR11 = 0x3d + AF_VENDOR12 = 0x3f + AF_VENDOR13 = 0x41 + AF_VENDOR14 = 0x43 + AF_VENDOR15 = 0x45 + AF_VENDOR16 = 0x47 + AF_VENDOR17 = 0x49 + AF_VENDOR18 = 0x4b + AF_VENDOR19 = 0x4d + AF_VENDOR20 = 0x4f + AF_VENDOR21 = 0x51 + AF_VENDOR22 = 0x53 + AF_VENDOR23 = 0x55 + AF_VENDOR24 = 0x57 + AF_VENDOR25 = 0x59 + AF_VENDOR26 = 0x5b + AF_VENDOR27 = 0x5d + AF_VENDOR28 = 0x5f + AF_VENDOR29 = 0x61 + AF_VENDOR30 = 0x63 + AF_VENDOR31 = 0x65 + AF_VENDOR32 = 0x67 + AF_VENDOR33 = 0x69 + AF_VENDOR34 = 0x6b + AF_VENDOR35 = 0x6d + AF_VENDOR36 = 0x6f + AF_VENDOR37 = 0x71 + AF_VENDOR38 = 0x73 + AF_VENDOR39 = 0x75 + AF_VENDOR40 = 0x77 + AF_VENDOR41 = 0x79 + AF_VENDOR42 = 0x7b + AF_VENDOR43 = 0x7d + AF_VENDOR44 = 0x7f + AF_VENDOR45 = 0x81 + AF_VENDOR46 = 0x83 + AF_VENDOR47 = 0x85 + ALTWERASE = 0x200 + B0 = 0x0 + B1000000 = 0xf4240 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1500000 = 0x16e360 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B2000000 = 0x1e8480 + B230400 = 0x38400 + B2400 = 0x960 + B2500000 = 0x2625a0 + B28800 = 0x7080 + B300 = 0x12c + B3000000 = 0x2dc6c0 + B3500000 = 0x3567e0 + B38400 = 0x9600 + B4000000 = 0x3d0900 + B460800 = 0x70800 + B4800 = 0x12c0 + B50 = 0x32 + B500000 = 0x7a120 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B921600 = 0xe1000 + B9600 = 0x2580 + BIOCFEEDBACK = 0x8004427c + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDIRECTION = 0x40044276 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc0104279 + BIOCGETBUFMODE = 0x4004427d + BIOCGETIF = 0x4020426b + BIOCGETZMAX = 0x4008427f + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCGTSTAMP = 0x40044283 + BIOCIMMEDIATE = 0x80044270 + BIOCLOCK = 0x2000427a + BIOCPROMISC = 0x20004269 + BIOCROTZBUF = 0x40184280 + BIOCSBLEN = 0xc0044266 + BIOCSDIRECTION = 0x80044277 + BIOCSDLT = 0x80044278 + BIOCSETBUFMODE = 0x8004427e + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x80104282 + BIOCSETIF = 0x8020426c + BIOCSETVLANPCP = 0x80044285 + BIOCSETWF = 0x8010427b + BIOCSETZBUF = 0x80184281 + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCSTSTAMP = 0x80044284 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x8 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_BUFMODE_BUFFER = 0x1 + BPF_BUFMODE_ZBUF = 0x2 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MOD = 0x90 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_T_BINTIME = 0x2 + BPF_T_BINTIME_FAST = 0x102 + BPF_T_BINTIME_MONOTONIC = 0x202 + BPF_T_BINTIME_MONOTONIC_FAST = 0x302 + BPF_T_FAST = 0x100 + BPF_T_FLAG_MASK = 0x300 + BPF_T_FORMAT_MASK = 0x3 + BPF_T_MICROTIME = 0x0 + BPF_T_MICROTIME_FAST = 0x100 + BPF_T_MICROTIME_MONOTONIC = 0x200 + BPF_T_MICROTIME_MONOTONIC_FAST = 0x300 + BPF_T_MONOTONIC = 0x200 + BPF_T_MONOTONIC_FAST = 0x300 + BPF_T_NANOTIME = 0x1 + BPF_T_NANOTIME_FAST = 0x101 + BPF_T_NANOTIME_MONOTONIC = 0x201 + BPF_T_NANOTIME_MONOTONIC_FAST = 0x301 + BPF_T_NONE = 0x3 + BPF_T_NORMAL = 0x0 + BPF_W = 0x0 + BPF_X = 0x8 + BPF_XOR = 0xa0 + BRKINT = 0x2 + CAP_ACCEPT = 0x200000020000000 + CAP_ACL_CHECK = 0x400000000010000 + CAP_ACL_DELETE = 0x400000000020000 + CAP_ACL_GET = 0x400000000040000 + CAP_ACL_SET = 0x400000000080000 + CAP_ALL0 = 0x20007ffffffffff + CAP_ALL1 = 0x4000000001fffff + CAP_BIND = 0x200000040000000 + CAP_BINDAT = 0x200008000000400 + CAP_CHFLAGSAT = 0x200000000001400 + CAP_CONNECT = 0x200000080000000 + CAP_CONNECTAT = 0x200010000000400 + CAP_CREATE = 0x200000000000040 + CAP_EVENT = 0x400000000000020 + CAP_EXTATTR_DELETE = 0x400000000001000 + CAP_EXTATTR_GET = 0x400000000002000 + CAP_EXTATTR_LIST = 0x400000000004000 + CAP_EXTATTR_SET = 0x400000000008000 + CAP_FCHDIR = 0x200000000000800 + CAP_FCHFLAGS = 0x200000000001000 + CAP_FCHMOD = 0x200000000002000 + CAP_FCHMODAT = 0x200000000002400 + CAP_FCHOWN = 0x200000000004000 + CAP_FCHOWNAT = 0x200000000004400 + CAP_FCNTL = 0x200000000008000 + CAP_FCNTL_ALL = 0x78 + CAP_FCNTL_GETFL = 0x8 + CAP_FCNTL_GETOWN = 0x20 + CAP_FCNTL_SETFL = 0x10 + CAP_FCNTL_SETOWN = 0x40 + CAP_FEXECVE = 0x200000000000080 + CAP_FLOCK = 0x200000000010000 + CAP_FPATHCONF = 0x200000000020000 + CAP_FSCK = 0x200000000040000 + CAP_FSTAT = 0x200000000080000 + CAP_FSTATAT = 0x200000000080400 + CAP_FSTATFS = 0x200000000100000 + CAP_FSYNC = 0x200000000000100 + CAP_FTRUNCATE = 0x200000000000200 + CAP_FUTIMES = 0x200000000200000 + CAP_FUTIMESAT = 0x200000000200400 + CAP_GETPEERNAME = 0x200000100000000 + CAP_GETSOCKNAME = 0x200000200000000 + CAP_GETSOCKOPT = 0x200000400000000 + CAP_IOCTL = 0x400000000000080 + CAP_IOCTLS_ALL = 0x7fffffffffffffff + CAP_KQUEUE = 0x400000000100040 + CAP_KQUEUE_CHANGE = 0x400000000100000 + CAP_KQUEUE_EVENT = 0x400000000000040 + CAP_LINKAT_SOURCE = 0x200020000000400 + CAP_LINKAT_TARGET = 0x200000000400400 + CAP_LISTEN = 0x200000800000000 + CAP_LOOKUP = 0x200000000000400 + CAP_MAC_GET = 0x400000000000001 + CAP_MAC_SET = 0x400000000000002 + CAP_MKDIRAT = 0x200000000800400 + CAP_MKFIFOAT = 0x200000001000400 + CAP_MKNODAT = 0x200000002000400 + CAP_MMAP = 0x200000000000010 + CAP_MMAP_R = 0x20000000000001d + CAP_MMAP_RW = 0x20000000000001f + CAP_MMAP_RWX = 0x20000000000003f + CAP_MMAP_RX = 0x20000000000003d + CAP_MMAP_W = 0x20000000000001e + CAP_MMAP_WX = 0x20000000000003e + CAP_MMAP_X = 0x20000000000003c + CAP_PDGETPID = 0x400000000000200 + CAP_PDKILL = 0x400000000000800 + CAP_PDWAIT = 0x400000000000400 + CAP_PEELOFF = 0x200001000000000 + CAP_POLL_EVENT = 0x400000000000020 + CAP_PREAD = 0x20000000000000d + CAP_PWRITE = 0x20000000000000e + CAP_READ = 0x200000000000001 + CAP_RECV = 0x200000000000001 + CAP_RENAMEAT_SOURCE = 0x200000004000400 + CAP_RENAMEAT_TARGET = 0x200040000000400 + CAP_RIGHTS_VERSION = 0x0 + CAP_RIGHTS_VERSION_00 = 0x0 + CAP_SEEK = 0x20000000000000c + CAP_SEEK_TELL = 0x200000000000004 + CAP_SEM_GETVALUE = 0x400000000000004 + CAP_SEM_POST = 0x400000000000008 + CAP_SEM_WAIT = 0x400000000000010 + CAP_SEND = 0x200000000000002 + CAP_SETSOCKOPT = 0x200002000000000 + CAP_SHUTDOWN = 0x200004000000000 + CAP_SOCK_CLIENT = 0x200007780000003 + CAP_SOCK_SERVER = 0x200007f60000003 + CAP_SYMLINKAT = 0x200000008000400 + CAP_TTYHOOK = 0x400000000000100 + CAP_UNLINKAT = 0x200000010000400 + CAP_UNUSED0_44 = 0x200080000000000 + CAP_UNUSED0_57 = 0x300000000000000 + CAP_UNUSED1_22 = 0x400000000200000 + CAP_UNUSED1_57 = 0x500000000000000 + CAP_WRITE = 0x200000000000002 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_BOOTTIME = 0x5 + CLOCK_MONOTONIC = 0x4 + CLOCK_MONOTONIC_COARSE = 0xc + CLOCK_MONOTONIC_FAST = 0xc + CLOCK_MONOTONIC_PRECISE = 0xb + CLOCK_PROCESS_CPUTIME_ID = 0xf + CLOCK_PROF = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_REALTIME_COARSE = 0xa + CLOCK_REALTIME_FAST = 0xa + CLOCK_REALTIME_PRECISE = 0x9 + CLOCK_SECOND = 0xd + CLOCK_THREAD_CPUTIME_ID = 0xe + CLOCK_UPTIME = 0x5 + CLOCK_UPTIME_FAST = 0x8 + CLOCK_UPTIME_PRECISE = 0x7 + CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0x18 + CTL_NET = 0x4 + DIOCGATTR = 0xc148648e + DIOCGDELETE = 0x80106488 + DIOCGFLUSH = 0x20006487 + DIOCGFWHEADS = 0x40046483 + DIOCGFWSECTORS = 0x40046482 + DIOCGIDENT = 0x41006489 + DIOCGKERNELDUMP = 0xc0986492 + DIOCGMEDIASIZE = 0x40086481 + DIOCGPHYSPATH = 0x4400648d + DIOCGPROVIDERNAME = 0x4400648a + DIOCGSECTORSIZE = 0x40046480 + DIOCGSTRIPEOFFSET = 0x4008648c + DIOCGSTRIPESIZE = 0x4008648b + DIOCSKERNELDUMP = 0x80986491 + DIOCSKERNELDUMP_FREEBSD11 = 0x80046485 + DIOCSKERNELDUMP_FREEBSD12 = 0x80506490 + DIOCZONECMD = 0xc080648f + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_BREDR_BB = 0xff + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_BLUETOOTH_LE_LL = 0xfb + DLT_BLUETOOTH_LE_LL_WITH_PHDR = 0x100 + DLT_BLUETOOTH_LINUX_MONITOR = 0xfe + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_CLASS_NETBSD_RAWAF = 0x2240000 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DISPLAYPORT_AUX = 0x113 + DLT_DOCSIS = 0x8f + DLT_DOCSIS31_XRA31 = 0x111 + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_EPON = 0x103 + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_ETHERNET_MPACKET = 0x112 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_INFINIBAND = 0xf7 + DLT_IPFILTER = 0x74 + DLT_IPMB_KONTRON = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPMI_HPM_2 = 0x104 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_ISO_14443 = 0x108 + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LINUX_SLL2 = 0x114 + DLT_LOOP = 0x6c + DLT_LORATAP = 0x10e + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x114 + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NETLINK = 0xfd + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NORDIC_BLE = 0x110 + DLT_NULL = 0x0 + DLT_OPENFLOW = 0x10b + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x79 + DLT_PKTAP = 0x102 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0xe + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PROFIBUS_DL = 0x101 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RDS = 0x109 + DLT_REDBACK_SMARTEDGE = 0x20 + DLT_RIO = 0x7c + DLT_RTAC_SERIAL = 0xfa + DLT_SCCP = 0x8e + DLT_SCTP = 0xf8 + DLT_SDLC = 0x10c + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xd + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TI_LLN_SNIFFER = 0x10d + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USBPCAP = 0xf9 + DLT_USB_DARWIN = 0x10a + DLT_USB_FREEBSD = 0xba + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_VSOCK = 0x10f + DLT_WATTSTOPPER_DLM = 0x107 + DLT_WIHART = 0xdf + DLT_WIRESHARK_UPPER_PDU = 0xfc + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DLT_ZWAVE_R1_R2 = 0x105 + DLT_ZWAVE_R3 = 0x106 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EHE_DEAD_PRIORITY = -0x1 + EVFILT_AIO = -0x3 + EVFILT_EMPTY = -0xd + EVFILT_FS = -0x9 + EVFILT_LIO = -0xa + EVFILT_PROC = -0x5 + EVFILT_PROCDESC = -0x8 + EVFILT_READ = -0x1 + EVFILT_SENDFILE = -0xc + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0xd + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xb + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EVNAMEMAP_NAME_SIZE = 0x40 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DROP = 0x1000 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG1 = 0x2000 + EV_FLAG2 = 0x4000 + EV_FORCEONESHOT = 0x100 + EV_ONESHOT = 0x10 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EXTA = 0x4b00 + EXTATTR_MAXNAMELEN = 0xff + EXTATTR_NAMESPACE_EMPTY = 0x0 + EXTATTR_NAMESPACE_SYSTEM = 0x2 + EXTATTR_NAMESPACE_USER = 0x1 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_NONE = -0xc8 + FD_SETSIZE = 0x400 + FLUSHO = 0x800000 + F_ADD_SEALS = 0x13 + F_CANCEL = 0x5 + F_DUP2FD = 0xa + F_DUP2FD_CLOEXEC = 0x12 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x11 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0xb + F_GETOWN = 0x5 + F_GET_SEALS = 0x14 + F_ISUNIONSTACK = 0x15 + F_KINFO = 0x16 + F_OGETLK = 0x7 + F_OK = 0x0 + F_OSETLK = 0x8 + F_OSETLKW = 0x9 + F_RDAHEAD = 0x10 + F_RDLCK = 0x1 + F_READAHEAD = 0xf + F_SEAL_GROW = 0x4 + F_SEAL_SEAL = 0x1 + F_SEAL_SHRINK = 0x2 + F_SEAL_WRITE = 0x8 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0xc + F_SETLKW = 0xd + F_SETLK_REMOTE = 0xe + F_SETOWN = 0x6 + F_UNLCK = 0x2 + F_UNLCKSYS = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFAN_ARRIVAL = 0x0 + IFAN_DEPARTURE = 0x1 + IFCAP_WOL_MAGIC = 0x2000 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_CANTCHANGE = 0x218f72 + IFF_CANTCONFIG = 0x10000 + IFF_DEBUG = 0x4 + IFF_DRV_OACTIVE = 0x400 + IFF_DRV_RUNNING = 0x40 + IFF_DYING = 0x200000 + IFF_KNOWSEPOCH = 0x20 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MONITOR = 0x40000 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOGROUP = 0x800000 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PPROMISC = 0x20000 + IFF_PROMISC = 0x100 + IFF_RENAMING = 0x400000 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_STATICARP = 0x80000 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_IEEE1394 = 0x90 + IFT_INFINIBAND = 0xc7 + IFT_L2VLAN = 0x87 + IFT_L3IPVLAN = 0x88 + IFT_PPP = 0x17 + IFT_PROPVIRTUAL = 0x35 + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LOOPBACKNET = 0x7f + IN_NETMASK_DEFAULT = 0xffffff00 + IN_RFC3021_MASK = 0xfffffffe + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CARP = 0x70 + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DCCP = 0x21 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0x102 + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HIP = 0x8b + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MEAS = 0x13 + IPPROTO_MH = 0x87 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MOBILE = 0x37 + IPPROTO_MPLS = 0x89 + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OLD_DIVERT = 0xfe + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PFSYNC = 0xf0 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_RESERVED_253 = 0xfd + IPPROTO_RESERVED_254 = 0xfe + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEND = 0x103 + IPPROTO_SHIM6 = 0x8c + IPPROTO_SKIP = 0x39 + IPPROTO_SPACER = 0x7fff + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TLSP = 0x38 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_UDPLITE = 0x88 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDANY = 0x40 + IPV6_BINDMULTI = 0x41 + IPV6_BINDV6ONLY = 0x1b + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FLOWID = 0x43 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_LEN = 0x14 + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOWTYPE = 0x44 + IPV6_FRAGTTL = 0x78 + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_ORIGDSTADDR = 0x48 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVFLOWID = 0x46 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVORIGDSTADDR = 0x48 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x24 + IPV6_RECVRSSBUCKETID = 0x47 + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x39 + IPV6_RSSBUCKETID = 0x45 + IPV6_RSS_LISTEN_BUCKET = 0x42 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x23 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x3d + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IPV6_VLAN_PCP = 0x4b + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BINDANY = 0x18 + IP_BINDMULTI = 0x19 + IP_BLOCK_SOURCE = 0x48 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x43 + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET3 = 0x31 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FLOWID = 0x5a + IP_FLOWTYPE = 0x5b + IP_FW3 = 0x30 + IP_FW_ADD = 0x32 + IP_FW_DEL = 0x33 + IP_FW_FLUSH = 0x34 + IP_FW_GET = 0x36 + IP_FW_NAT_CFG = 0x38 + IP_FW_NAT_DEL = 0x39 + IP_FW_NAT_GET_CONFIG = 0x3a + IP_FW_NAT_GET_LOG = 0x3b + IP_FW_RESETLOG = 0x37 + IP_FW_TABLE_ADD = 0x28 + IP_FW_TABLE_DEL = 0x29 + IP_FW_TABLE_FLUSH = 0x2a + IP_FW_TABLE_GETSIZE = 0x2b + IP_FW_TABLE_LIST = 0x2c + IP_FW_ZERO = 0x35 + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MINTTL = 0x42 + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_OFFMASK = 0x1fff + IP_ONESBCAST = 0x17 + IP_OPTIONS = 0x1 + IP_ORIGDSTADDR = 0x1b + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVFLOWID = 0x5d + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVORIGDSTADDR = 0x1b + IP_RECVRETOPTS = 0x6 + IP_RECVRSSBUCKETID = 0x5e + IP_RECVTOS = 0x44 + IP_RECVTTL = 0x41 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSSBUCKETID = 0x5c + IP_RSS_LISTEN_BUCKET = 0x1a + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_SENDSRCADDR = 0x7 + IP_TOS = 0x3 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + IP_VLAN_PCP = 0x4b + ISIG = 0x80 + ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_CREDS_PERSISTENT = 0x3 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_AUTOSYNC = 0x7 + MADV_CORE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_NOCORE = 0x8 + MADV_NORMAL = 0x0 + MADV_NOSYNC = 0x6 + MADV_PROTECT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MAP_32BIT = 0x80000 + MAP_ALIGNED_SUPER = 0x1000000 + MAP_ALIGNMENT_MASK = -0x1000000 + MAP_ALIGNMENT_SHIFT = 0x18 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_EXCL = 0x4000 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_GUARD = 0x2000 + MAP_HASSEMAPHORE = 0x200 + MAP_NOCORE = 0x20000 + MAP_NOSYNC = 0x800 + MAP_PREFAULT_READ = 0x40000 + MAP_PRIVATE = 0x2 + MAP_RESERVED0020 = 0x20 + MAP_RESERVED0040 = 0x40 + MAP_RESERVED0080 = 0x80 + MAP_RESERVED0100 = 0x100 + MAP_SHARED = 0x1 + MAP_STACK = 0x400 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MFD_ALLOW_SEALING = 0x2 + MFD_CLOEXEC = 0x1 + MFD_HUGETLB = 0x4 + MFD_HUGE_16GB = -0x78000000 + MFD_HUGE_16MB = 0x60000000 + MFD_HUGE_1GB = 0x78000000 + MFD_HUGE_1MB = 0x50000000 + MFD_HUGE_256MB = 0x70000000 + MFD_HUGE_2GB = 0x7c000000 + MFD_HUGE_2MB = 0x54000000 + MFD_HUGE_32MB = 0x64000000 + MFD_HUGE_512KB = 0x4c000000 + MFD_HUGE_512MB = 0x74000000 + MFD_HUGE_64KB = 0x40000000 + MFD_HUGE_8MB = 0x5c000000 + MFD_HUGE_MASK = 0xfc000000 + MFD_HUGE_SHIFT = 0x1a + MNT_ACLS = 0x8000000 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x200000000 + MNT_BYFSID = 0x8000000 + MNT_CMDFLAGS = 0x300d0f0000 + MNT_DEFEXPORTED = 0x200 + MNT_DELEXPORT = 0x20000 + MNT_EMPTYDIR = 0x2000000000 + MNT_EXKERB = 0x800 + MNT_EXPORTANON = 0x400 + MNT_EXPORTED = 0x100 + MNT_EXPUBLIC = 0x20000000 + MNT_EXRDONLY = 0x80 + MNT_EXTLS = 0x4000000000 + MNT_EXTLSCERT = 0x8000000000 + MNT_EXTLSCERTUSER = 0x10000000000 + MNT_FORCE = 0x80000 + MNT_GJOURNAL = 0x2000000 + MNT_IGNORE = 0x800000 + MNT_LAZY = 0x3 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NFS4ACLS = 0x10 + MNT_NOATIME = 0x10000000 + MNT_NOCLUSTERR = 0x40000000 + MNT_NOCLUSTERW = 0x80000000 + MNT_NOCOVER = 0x1000000000 + MNT_NOEXEC = 0x4 + MNT_NONBUSY = 0x4000000 + MNT_NOSUID = 0x8 + MNT_NOSYMFOLLOW = 0x400000 + MNT_NOWAIT = 0x2 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x1000000 + MNT_SOFTDEP = 0x200000 + MNT_SUIDDIR = 0x100000 + MNT_SUJ = 0x100000000 + MNT_SUSPEND = 0x4 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNTRUSTED = 0x800000000 + MNT_UPDATE = 0x10000 + MNT_UPDATEMASK = 0xad8d0807e + MNT_USER = 0x8000 + MNT_VERIFIED = 0x400000000 + MNT_VISFLAGMASK = 0xffef0ffff + MNT_WAIT = 0x1 + MSG_CMSG_CLOEXEC = 0x40000 + MSG_COMPAT = 0x8000 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_NBIO = 0x4000 + MSG_NOSIGNAL = 0x20000 + MSG_NOTIFICATION = 0x2000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITFORONE = 0x80000 + MS_ASYNC = 0x1 + MS_INVALIDATE = 0x2 + MS_SYNC = 0x0 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_FLAGS = 0x2 + NET_RT_IFLIST = 0x3 + NET_RT_IFLISTL = 0x5 + NET_RT_IFMALIST = 0x4 + NET_RT_NHGRP = 0x7 + NET_RT_NHOP = 0x6 + NFDBITS = 0x40 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSTIME = 0x10 + NOTE_ATTRIB = 0x8 + NOTE_CHILD = 0x4 + NOTE_CLOSE = 0x100 + NOTE_CLOSE_WRITE = 0x200 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FILE_POLL = 0x2 + NOTE_FORK = 0x40000000 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MSECONDS = 0x2 + NOTE_NSECONDS = 0x8 + NOTE_OPEN = 0x80 + NOTE_PCTRLMASK = 0xf0000000 + NOTE_PDATAMASK = 0xfffff + NOTE_READ = 0x400 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x4 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x100000 + O_CREAT = 0x200 + O_DIRECT = 0x10000 + O_DIRECTORY = 0x20000 + O_DSYNC = 0x1000000 + O_EMPTY_PATH = 0x2000000 + O_EXCL = 0x800 + O_EXEC = 0x40000 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x8000 + O_NOFOLLOW = 0x100 + O_NONBLOCK = 0x4 + O_PATH = 0x400000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_RESOLVE_BENEATH = 0x800000 + O_SEARCH = 0x40000 + O_SHLOCK = 0x10 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_TTY_INIT = 0x80000 + O_VERIFY = 0x200000 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PIOD_READ_D = 0x1 + PIOD_READ_I = 0x3 + PIOD_WRITE_D = 0x2 + PIOD_WRITE_I = 0x4 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PTRACE_DEFAULT = 0x1 + PTRACE_EXEC = 0x1 + PTRACE_FORK = 0x8 + PTRACE_LWP = 0x10 + PTRACE_SCE = 0x2 + PTRACE_SCX = 0x4 + PTRACE_SYSCALL = 0x6 + PTRACE_VFORK = 0x20 + PT_ATTACH = 0xa + PT_CLEARSTEP = 0x10 + PT_CONTINUE = 0x7 + PT_COREDUMP = 0x1d + PT_DETACH = 0xb + PT_FIRSTMACH = 0x40 + PT_FOLLOW_FORK = 0x17 + PT_GETDBREGS = 0x25 + PT_GETFPREGS = 0x23 + PT_GETLWPLIST = 0xf + PT_GETNUMLWPS = 0xe + PT_GETREGS = 0x21 + PT_GET_EVENT_MASK = 0x19 + PT_GET_SC_ARGS = 0x1b + PT_GET_SC_RET = 0x1c + PT_IO = 0xc + PT_KILL = 0x8 + PT_LWPINFO = 0xd + PT_LWP_EVENTS = 0x18 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_RESUME = 0x13 + PT_SETDBREGS = 0x26 + PT_SETFPREGS = 0x24 + PT_SETREGS = 0x22 + PT_SETSTEP = 0x11 + PT_SET_EVENT_MASK = 0x1a + PT_STEP = 0x9 + PT_SUSPEND = 0x12 + PT_SYSCALL = 0x16 + PT_TO_SCE = 0x14 + PT_TO_SCX = 0x15 + PT_TRACE_ME = 0x0 + PT_VM_ENTRY = 0x29 + PT_VM_TIMESTAMP = 0x28 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + P_ZONEID = 0xc + RLIMIT_AS = 0xa + RLIMIT_CORE = 0x4 + RLIMIT_CPU = 0x0 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_FIXEDMTU = 0x80000 + RTF_FMASK = 0x1004d808 + RTF_GATEWAY = 0x2 + RTF_GWFLAG_COMPAT = 0x80000000 + RTF_HOST = 0x4 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_PINNED = 0x100000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_REJECT = 0x8 + RTF_STATIC = 0x800 + RTF_STICKY = 0x10000000 + RTF_UP = 0x1 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_IEEE80211 = 0x12 + RTM_IFANNOUNCE = 0x11 + RTM_IFINFO = 0xe + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RTV_WEIGHT = 0x100 + RT_ALL_FIBS = -0x1 + RT_BLACKHOLE = 0x40 + RT_DEFAULT_FIB = 0x0 + RT_DEFAULT_WEIGHT = 0x1 + RT_HAS_GW = 0x80 + RT_HAS_HEADER = 0x10 + RT_HAS_HEADER_BIT = 0x4 + RT_L2_ME = 0x4 + RT_L2_ME_BIT = 0x2 + RT_LLE_CACHE = 0x100 + RT_MAX_WEIGHT = 0xffffff + RT_MAY_LOOP = 0x8 + RT_MAY_LOOP_BIT = 0x3 + RT_REJECT = 0x20 + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 + RUSAGE_THREAD = 0x1 + SCM_BINTIME = 0x4 + SCM_CREDS = 0x3 + SCM_CREDS2 = 0x8 + SCM_MONOTONIC = 0x6 + SCM_REALTIME = 0x5 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCAIFGROUP = 0x80286987 + SIOCATMARK = 0x40047307 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFGROUP = 0x80286989 + SIOCDIFPHYADDR = 0x80206949 + SIOCGDRVSPEC = 0xc028697b + SIOCGETSGCNT = 0xc0207210 + SIOCGETVIFCNT = 0xc028720f + SIOCGHIWAT = 0x40047301 + SIOCGHWADDR = 0xc020693e + SIOCGI2C = 0xc020693d + SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc044692d + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020691f + SIOCGIFCONF = 0xc0106924 + SIOCGIFDATA = 0x8020692c + SIOCGIFDESCR = 0xc020692a + SIOCGIFDOWNREASON = 0xc058699a + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFIB = 0xc020695c + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFGENERIC = 0xc020693a + SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 + SIOCGIFINDEX = 0xc0206920 + SIOCGIFMAC = 0xc0206926 + SIOCGIFMEDIA = 0xc0306938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206948 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc0206947 + SIOCGIFRSSHASH = 0xc0186997 + SIOCGIFRSSKEY = 0xc0946996 + SIOCGIFSTATUS = 0xc331693b + SIOCGIFXMEDIA = 0xc030698b + SIOCGLANPCP = 0xc0206998 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCGPRIVATE_0 = 0xc0206950 + SIOCGPRIVATE_1 = 0xc0206951 + SIOCGTUNFIB = 0xc020695e + SIOCIFCREATE = 0xc020697a + SIOCIFCREATE2 = 0xc020697c + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106978 + SIOCSDRVSPEC = 0x8028697b + SIOCSHIWAT = 0x80047300 + SIOCSIFADDR = 0x8020690c + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020691e + SIOCSIFDESCR = 0x80206929 + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFIB = 0x8020695d + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206927 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNAME = 0x80206928 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x80406946 + SIOCSIFPHYS = 0x80206936 + SIOCSIFRVNET = 0xc020695b + SIOCSIFVNET = 0xc020695a + SIOCSLANPCP = 0x80206999 + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SIOCSTUNFIB = 0x8020695f + SOCK_CLOEXEC = 0x10000000 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_NONBLOCK = 0x20000000 + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_ACCEPTFILTER = 0x1000 + SO_BINTIME = 0x2000 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DOMAIN = 0x1019 + SO_DONTROUTE = 0x10 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1009 + SO_LINGER = 0x80 + SO_LISTENINCQLEN = 0x1013 + SO_LISTENQLEN = 0x1012 + SO_LISTENQLIMIT = 0x1011 + SO_MAX_PACING_RATE = 0x1018 + SO_NOSIGPIPE = 0x800 + SO_NO_DDP = 0x8000 + SO_NO_OFFLOAD = 0x4000 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1010 + SO_PROTOCOL = 0x1016 + SO_PROTOTYPE = 0x1016 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x20000 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSEPORT_LB = 0x10000 + SO_SETFIB = 0x1014 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TS_BINTIME = 0x1 + SO_TS_CLOCK = 0x1017 + SO_TS_CLOCK_MAX = 0x3 + SO_TS_DEFAULT = 0x0 + SO_TS_MONOTONIC = 0x3 + SO_TS_REALTIME = 0x2 + SO_TS_REALTIME_MICRO = 0x0 + SO_TYPE = 0x1008 + SO_USELOOPBACK = 0x40 + SO_USER_COOKIE = 0x1015 + SO_VENDOR = 0x80000000 + S_BLKSIZE = 0x200 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB3 = 0x4 + TABDLY = 0x4 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_FAST_OPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_PAD = 0x0 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_WINDOW = 0x3 + TCP_BBR_ACK_COMP_ALG = 0x448 + TCP_BBR_ALGORITHM = 0x43b + TCP_BBR_DRAIN_INC_EXTRA = 0x43c + TCP_BBR_DRAIN_PG = 0x42e + TCP_BBR_EXTRA_GAIN = 0x449 + TCP_BBR_EXTRA_STATE = 0x453 + TCP_BBR_FLOOR_MIN_TSO = 0x454 + TCP_BBR_HDWR_PACE = 0x451 + TCP_BBR_HOLD_TARGET = 0x436 + TCP_BBR_IWINTSO = 0x42b + TCP_BBR_LOWGAIN_FD = 0x436 + TCP_BBR_LOWGAIN_HALF = 0x435 + TCP_BBR_LOWGAIN_THRESH = 0x434 + TCP_BBR_MAX_RTO = 0x439 + TCP_BBR_MIN_RTO = 0x438 + TCP_BBR_MIN_TOPACEOUT = 0x455 + TCP_BBR_ONE_RETRAN = 0x431 + TCP_BBR_PACE_CROSS = 0x442 + TCP_BBR_PACE_DEL_TAR = 0x43f + TCP_BBR_PACE_OH = 0x435 + TCP_BBR_PACE_PER_SEC = 0x43e + TCP_BBR_PACE_SEG_MAX = 0x440 + TCP_BBR_PACE_SEG_MIN = 0x441 + TCP_BBR_POLICER_DETECT = 0x457 + TCP_BBR_PROBE_RTT_GAIN = 0x44d + TCP_BBR_PROBE_RTT_INT = 0x430 + TCP_BBR_PROBE_RTT_LEN = 0x44e + TCP_BBR_RACK_INIT_RATE = 0x458 + TCP_BBR_RACK_RTT_USE = 0x44a + TCP_BBR_RECFORCE = 0x42c + TCP_BBR_REC_OVER_HPTS = 0x43a + TCP_BBR_RETRAN_WTSO = 0x44b + TCP_BBR_RWND_IS_APP = 0x42f + TCP_BBR_SEND_IWND_IN_TSO = 0x44f + TCP_BBR_STARTUP_EXIT_EPOCH = 0x43d + TCP_BBR_STARTUP_LOSS_EXIT = 0x432 + TCP_BBR_STARTUP_PG = 0x42d + TCP_BBR_TMR_PACE_OH = 0x448 + TCP_BBR_TSLIMITS = 0x434 + TCP_BBR_TSTMP_RAISES = 0x456 + TCP_BBR_UNLIMITED = 0x43b + TCP_BBR_USEDEL_RATE = 0x437 + TCP_BBR_USE_LOWGAIN = 0x433 + TCP_BBR_USE_RACK_CHEAT = 0x450 + TCP_BBR_USE_RACK_RR = 0x450 + TCP_BBR_UTTER_MAX_TSO = 0x452 + TCP_CA_NAME_MAX = 0x10 + TCP_CCALGOOPT = 0x41 + TCP_CONGESTION = 0x40 + TCP_DATA_AFTER_CLOSE = 0x44c + TCP_DEFER_OPTIONS = 0x470 + TCP_DELACK = 0x48 + TCP_FASTOPEN = 0x401 + TCP_FASTOPEN_MAX_COOKIE_LEN = 0x10 + TCP_FASTOPEN_MIN_COOKIE_LEN = 0x4 + TCP_FASTOPEN_PSK_LEN = 0x10 + TCP_FAST_RSM_HACK = 0x471 + TCP_FIN_IS_RST = 0x49 + TCP_FUNCTION_BLK = 0x2000 + TCP_FUNCTION_NAME_LEN_MAX = 0x20 + TCP_HDWR_RATE_CAP = 0x46a + TCP_HDWR_UP_ONLY = 0x46c + TCP_IDLE_REDUCE = 0x46 + TCP_INFO = 0x20 + TCP_IWND_NB = 0x2b + TCP_IWND_NSEG = 0x2c + TCP_KEEPCNT = 0x400 + TCP_KEEPIDLE = 0x100 + TCP_KEEPINIT = 0x80 + TCP_KEEPINTVL = 0x200 + TCP_LOG = 0x22 + TCP_LOGBUF = 0x23 + TCP_LOGDUMP = 0x25 + TCP_LOGDUMPID = 0x26 + TCP_LOGID = 0x24 + TCP_LOGID_CNT = 0x2e + TCP_LOG_ID_LEN = 0x40 + TCP_LOG_LIMIT = 0x4a + TCP_LOG_TAG = 0x2f + TCP_MAXBURST = 0x4 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXPEAKRATE = 0x45 + TCP_MAXSEG = 0x2 + TCP_MAXUNACKTIME = 0x44 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MD5SIG = 0x10 + TCP_MINMSS = 0xd8 + TCP_MSS = 0x218 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NO_PRR = 0x462 + TCP_PACING_RATE_CAP = 0x46b + TCP_PCAP_IN = 0x1000 + TCP_PCAP_OUT = 0x800 + TCP_PERF_INFO = 0x4e + TCP_PROC_ACCOUNTING = 0x4c + TCP_RACK_ABC_VAL = 0x46d + TCP_RACK_CHEAT_NOT_CONF_RATE = 0x459 + TCP_RACK_DO_DETECTION = 0x449 + TCP_RACK_EARLY_RECOV = 0x423 + TCP_RACK_EARLY_SEG = 0x424 + TCP_RACK_FORCE_MSEG = 0x45d + TCP_RACK_GP_INCREASE = 0x446 + TCP_RACK_GP_INCREASE_CA = 0x45a + TCP_RACK_GP_INCREASE_REC = 0x45c + TCP_RACK_GP_INCREASE_SS = 0x45b + TCP_RACK_IDLE_REDUCE_HIGH = 0x444 + TCP_RACK_MBUF_QUEUE = 0x41a + TCP_RACK_MEASURE_CNT = 0x46f + TCP_RACK_MIN_PACE = 0x445 + TCP_RACK_MIN_PACE_SEG = 0x446 + TCP_RACK_MIN_TO = 0x422 + TCP_RACK_NONRXT_CFG_RATE = 0x463 + TCP_RACK_NO_PUSH_AT_MAX = 0x466 + TCP_RACK_PACE_ALWAYS = 0x41f + TCP_RACK_PACE_MAX_SEG = 0x41e + TCP_RACK_PACE_RATE_CA = 0x45e + TCP_RACK_PACE_RATE_REC = 0x460 + TCP_RACK_PACE_RATE_SS = 0x45f + TCP_RACK_PACE_REDUCE = 0x41d + TCP_RACK_PACE_TO_FILL = 0x467 + TCP_RACK_PACING_BETA = 0x472 + TCP_RACK_PACING_BETA_ECN = 0x473 + TCP_RACK_PKT_DELAY = 0x428 + TCP_RACK_PROFILE = 0x469 + TCP_RACK_PROP = 0x41b + TCP_RACK_PROP_RATE = 0x420 + TCP_RACK_PRR_SENDALOT = 0x421 + TCP_RACK_REORD_FADE = 0x426 + TCP_RACK_REORD_THRESH = 0x425 + TCP_RACK_RR_CONF = 0x459 + TCP_RACK_TIMER_SLOP = 0x474 + TCP_RACK_TLP_INC_VAR = 0x429 + TCP_RACK_TLP_REDUCE = 0x41c + TCP_RACK_TLP_THRESH = 0x427 + TCP_RACK_TLP_USE = 0x447 + TCP_REC_ABC_VAL = 0x46e + TCP_REMOTE_UDP_ENCAPS_PORT = 0x47 + TCP_REUSPORT_LB_NUMA = 0x402 + TCP_REUSPORT_LB_NUMA_CURDOM = -0x1 + TCP_REUSPORT_LB_NUMA_NODOM = -0x2 + TCP_RXTLS_ENABLE = 0x29 + TCP_RXTLS_MODE = 0x2a + TCP_SHARED_CWND_ALLOWED = 0x4b + TCP_SHARED_CWND_ENABLE = 0x464 + TCP_SHARED_CWND_TIME_LIMIT = 0x468 + TCP_STATS = 0x21 + TCP_TIMELY_DYN_ADJ = 0x465 + TCP_TLS_MODE_IFNET = 0x2 + TCP_TLS_MODE_NONE = 0x0 + TCP_TLS_MODE_SW = 0x1 + TCP_TLS_MODE_TOE = 0x3 + TCP_TXTLS_ENABLE = 0x27 + TCP_TXTLS_MODE = 0x28 + TCP_USER_LOG = 0x30 + TCP_USE_CMP_ACKS = 0x4d + TCP_VENDOR = 0x80000000 + TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDRAIN = 0x2000745e + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x402c7413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGPTN = 0x4004740f + TIOCGSID = 0x40047463 + TIOCGWINSZ = 0x40087468 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DCD = 0x40 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTMASTER = 0x2000741c + TIOCSBRK = 0x2000747b + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x802c7414 + TIOCSETAF = 0x802c7416 + TIOCSETAW = 0x802c7415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2004745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + UTIME_NOW = -0x1 + UTIME_OMIT = -0x2 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VERASE2 = 0x7 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMIN = 0x10 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x4 + WCOREFLAG = 0x80 + WEXITED = 0x10 + WLINUXCLONE = 0x80000000 + WNOHANG = 0x1 + WNOWAIT = 0x8 + WSTOPPED = 0x2 + WTRAPPED = 0x20 + WUNTRACED = 0x2 +) + +// Errors +const ( + E2BIG = syscall.Errno(0x7) + EACCES = syscall.Errno(0xd) + EADDRINUSE = syscall.Errno(0x30) + EADDRNOTAVAIL = syscall.Errno(0x31) + EAFNOSUPPORT = syscall.Errno(0x2f) + EAGAIN = syscall.Errno(0x23) + EALREADY = syscall.Errno(0x25) + EAUTH = syscall.Errno(0x50) + EBADF = syscall.Errno(0x9) + EBADMSG = syscall.Errno(0x59) + EBADRPC = syscall.Errno(0x48) + EBUSY = syscall.Errno(0x10) + ECANCELED = syscall.Errno(0x55) + ECAPMODE = syscall.Errno(0x5e) + ECHILD = syscall.Errno(0xa) + ECONNABORTED = syscall.Errno(0x35) + ECONNREFUSED = syscall.Errno(0x3d) + ECONNRESET = syscall.Errno(0x36) + EDEADLK = syscall.Errno(0xb) + EDESTADDRREQ = syscall.Errno(0x27) + EDOM = syscall.Errno(0x21) + EDOOFUS = syscall.Errno(0x58) + EDQUOT = syscall.Errno(0x45) + EEXIST = syscall.Errno(0x11) + EFAULT = syscall.Errno(0xe) + EFBIG = syscall.Errno(0x1b) + EFTYPE = syscall.Errno(0x4f) + EHOSTDOWN = syscall.Errno(0x40) + EHOSTUNREACH = syscall.Errno(0x41) + EIDRM = syscall.Errno(0x52) + EILSEQ = syscall.Errno(0x56) + EINPROGRESS = syscall.Errno(0x24) + EINTEGRITY = syscall.Errno(0x61) + EINTR = syscall.Errno(0x4) + EINVAL = syscall.Errno(0x16) + EIO = syscall.Errno(0x5) + EISCONN = syscall.Errno(0x38) + EISDIR = syscall.Errno(0x15) + ELAST = syscall.Errno(0x61) + ELOOP = syscall.Errno(0x3e) + EMFILE = syscall.Errno(0x18) + EMLINK = syscall.Errno(0x1f) + EMSGSIZE = syscall.Errno(0x28) + EMULTIHOP = syscall.Errno(0x5a) + ENAMETOOLONG = syscall.Errno(0x3f) + ENEEDAUTH = syscall.Errno(0x51) + ENETDOWN = syscall.Errno(0x32) + ENETRESET = syscall.Errno(0x34) + ENETUNREACH = syscall.Errno(0x33) + ENFILE = syscall.Errno(0x17) + ENOATTR = syscall.Errno(0x57) + ENOBUFS = syscall.Errno(0x37) + ENODEV = syscall.Errno(0x13) + ENOENT = syscall.Errno(0x2) + ENOEXEC = syscall.Errno(0x8) + ENOLCK = syscall.Errno(0x4d) + ENOLINK = syscall.Errno(0x5b) + ENOMEM = syscall.Errno(0xc) + ENOMSG = syscall.Errno(0x53) + ENOPROTOOPT = syscall.Errno(0x2a) + ENOSPC = syscall.Errno(0x1c) + ENOSYS = syscall.Errno(0x4e) + ENOTBLK = syscall.Errno(0xf) + ENOTCAPABLE = syscall.Errno(0x5d) + ENOTCONN = syscall.Errno(0x39) + ENOTDIR = syscall.Errno(0x14) + ENOTEMPTY = syscall.Errno(0x42) + ENOTRECOVERABLE = syscall.Errno(0x5f) + ENOTSOCK = syscall.Errno(0x26) + ENOTSUP = syscall.Errno(0x2d) + ENOTTY = syscall.Errno(0x19) + ENXIO = syscall.Errno(0x6) + EOPNOTSUPP = syscall.Errno(0x2d) + EOVERFLOW = syscall.Errno(0x54) + EOWNERDEAD = syscall.Errno(0x60) + EPERM = syscall.Errno(0x1) + EPFNOSUPPORT = syscall.Errno(0x2e) + EPIPE = syscall.Errno(0x20) + EPROCLIM = syscall.Errno(0x43) + EPROCUNAVAIL = syscall.Errno(0x4c) + EPROGMISMATCH = syscall.Errno(0x4b) + EPROGUNAVAIL = syscall.Errno(0x4a) + EPROTO = syscall.Errno(0x5c) + EPROTONOSUPPORT = syscall.Errno(0x2b) + EPROTOTYPE = syscall.Errno(0x29) + ERANGE = syscall.Errno(0x22) + EREMOTE = syscall.Errno(0x47) + EROFS = syscall.Errno(0x1e) + ERPCMISMATCH = syscall.Errno(0x49) + ESHUTDOWN = syscall.Errno(0x3a) + ESOCKTNOSUPPORT = syscall.Errno(0x2c) + ESPIPE = syscall.Errno(0x1d) + ESRCH = syscall.Errno(0x3) + ESTALE = syscall.Errno(0x46) + ETIMEDOUT = syscall.Errno(0x3c) + ETOOMANYREFS = syscall.Errno(0x3b) + ETXTBSY = syscall.Errno(0x1a) + EUSERS = syscall.Errno(0x44) + EWOULDBLOCK = syscall.Errno(0x23) + EXDEV = syscall.Errno(0x12) +) + +// Signals +const ( + SIGABRT = syscall.Signal(0x6) + SIGALRM = syscall.Signal(0xe) + SIGBUS = syscall.Signal(0xa) + SIGCHLD = syscall.Signal(0x14) + SIGCONT = syscall.Signal(0x13) + SIGEMT = syscall.Signal(0x7) + SIGFPE = syscall.Signal(0x8) + SIGHUP = syscall.Signal(0x1) + SIGILL = syscall.Signal(0x4) + SIGINFO = syscall.Signal(0x1d) + SIGINT = syscall.Signal(0x2) + SIGIO = syscall.Signal(0x17) + SIGIOT = syscall.Signal(0x6) + SIGKILL = syscall.Signal(0x9) + SIGLIBRT = syscall.Signal(0x21) + SIGLWP = syscall.Signal(0x20) + SIGPIPE = syscall.Signal(0xd) + SIGPROF = syscall.Signal(0x1b) + SIGQUIT = syscall.Signal(0x3) + SIGSEGV = syscall.Signal(0xb) + SIGSTOP = syscall.Signal(0x11) + SIGSYS = syscall.Signal(0xc) + SIGTERM = syscall.Signal(0xf) + SIGTHR = syscall.Signal(0x20) + SIGTRAP = syscall.Signal(0x5) + SIGTSTP = syscall.Signal(0x12) + SIGTTIN = syscall.Signal(0x15) + SIGTTOU = syscall.Signal(0x16) + SIGURG = syscall.Signal(0x10) + SIGUSR1 = syscall.Signal(0x1e) + SIGUSR2 = syscall.Signal(0x1f) + SIGVTALRM = syscall.Signal(0x1a) + SIGWINCH = syscall.Signal(0x1c) + SIGXCPU = syscall.Signal(0x18) + SIGXFSZ = syscall.Signal(0x19) +) + +// Error table +var errorList = [...]struct { + num syscall.Errno + name string + desc string +}{ + {1, "EPERM", "operation not permitted"}, + {2, "ENOENT", "no such file or directory"}, + {3, "ESRCH", "no such process"}, + {4, "EINTR", "interrupted system call"}, + {5, "EIO", "input/output error"}, + {6, "ENXIO", "device not configured"}, + {7, "E2BIG", "argument list too long"}, + {8, "ENOEXEC", "exec format error"}, + {9, "EBADF", "bad file descriptor"}, + {10, "ECHILD", "no child processes"}, + {11, "EDEADLK", "resource deadlock avoided"}, + {12, "ENOMEM", "cannot allocate memory"}, + {13, "EACCES", "permission denied"}, + {14, "EFAULT", "bad address"}, + {15, "ENOTBLK", "block device required"}, + {16, "EBUSY", "device busy"}, + {17, "EEXIST", "file exists"}, + {18, "EXDEV", "cross-device link"}, + {19, "ENODEV", "operation not supported by device"}, + {20, "ENOTDIR", "not a directory"}, + {21, "EISDIR", "is a directory"}, + {22, "EINVAL", "invalid argument"}, + {23, "ENFILE", "too many open files in system"}, + {24, "EMFILE", "too many open files"}, + {25, "ENOTTY", "inappropriate ioctl for device"}, + {26, "ETXTBSY", "text file busy"}, + {27, "EFBIG", "file too large"}, + {28, "ENOSPC", "no space left on device"}, + {29, "ESPIPE", "illegal seek"}, + {30, "EROFS", "read-only file system"}, + {31, "EMLINK", "too many links"}, + {32, "EPIPE", "broken pipe"}, + {33, "EDOM", "numerical argument out of domain"}, + {34, "ERANGE", "result too large"}, + {35, "EWOULDBLOCK", "resource temporarily unavailable"}, + {36, "EINPROGRESS", "operation now in progress"}, + {37, "EALREADY", "operation already in progress"}, + {38, "ENOTSOCK", "socket operation on non-socket"}, + {39, "EDESTADDRREQ", "destination address required"}, + {40, "EMSGSIZE", "message too long"}, + {41, "EPROTOTYPE", "protocol wrong type for socket"}, + {42, "ENOPROTOOPT", "protocol not available"}, + {43, "EPROTONOSUPPORT", "protocol not supported"}, + {44, "ESOCKTNOSUPPORT", "socket type not supported"}, + {45, "EOPNOTSUPP", "operation not supported"}, + {46, "EPFNOSUPPORT", "protocol family not supported"}, + {47, "EAFNOSUPPORT", "address family not supported by protocol family"}, + {48, "EADDRINUSE", "address already in use"}, + {49, "EADDRNOTAVAIL", "can't assign requested address"}, + {50, "ENETDOWN", "network is down"}, + {51, "ENETUNREACH", "network is unreachable"}, + {52, "ENETRESET", "network dropped connection on reset"}, + {53, "ECONNABORTED", "software caused connection abort"}, + {54, "ECONNRESET", "connection reset by peer"}, + {55, "ENOBUFS", "no buffer space available"}, + {56, "EISCONN", "socket is already connected"}, + {57, "ENOTCONN", "socket is not connected"}, + {58, "ESHUTDOWN", "can't send after socket shutdown"}, + {59, "ETOOMANYREFS", "too many references: can't splice"}, + {60, "ETIMEDOUT", "operation timed out"}, + {61, "ECONNREFUSED", "connection refused"}, + {62, "ELOOP", "too many levels of symbolic links"}, + {63, "ENAMETOOLONG", "file name too long"}, + {64, "EHOSTDOWN", "host is down"}, + {65, "EHOSTUNREACH", "no route to host"}, + {66, "ENOTEMPTY", "directory not empty"}, + {67, "EPROCLIM", "too many processes"}, + {68, "EUSERS", "too many users"}, + {69, "EDQUOT", "disc quota exceeded"}, + {70, "ESTALE", "stale NFS file handle"}, + {71, "EREMOTE", "too many levels of remote in path"}, + {72, "EBADRPC", "RPC struct is bad"}, + {73, "ERPCMISMATCH", "RPC version wrong"}, + {74, "EPROGUNAVAIL", "RPC prog. not avail"}, + {75, "EPROGMISMATCH", "program version wrong"}, + {76, "EPROCUNAVAIL", "bad procedure for program"}, + {77, "ENOLCK", "no locks available"}, + {78, "ENOSYS", "function not implemented"}, + {79, "EFTYPE", "inappropriate file type or format"}, + {80, "EAUTH", "authentication error"}, + {81, "ENEEDAUTH", "need authenticator"}, + {82, "EIDRM", "identifier removed"}, + {83, "ENOMSG", "no message of desired type"}, + {84, "EOVERFLOW", "value too large to be stored in data type"}, + {85, "ECANCELED", "operation canceled"}, + {86, "EILSEQ", "illegal byte sequence"}, + {87, "ENOATTR", "attribute not found"}, + {88, "EDOOFUS", "programming error"}, + {89, "EBADMSG", "bad message"}, + {90, "EMULTIHOP", "multihop attempted"}, + {91, "ENOLINK", "link has been severed"}, + {92, "EPROTO", "protocol error"}, + {93, "ENOTCAPABLE", "capabilities insufficient"}, + {94, "ECAPMODE", "not permitted in capability mode"}, + {95, "ENOTRECOVERABLE", "state not recoverable"}, + {96, "EOWNERDEAD", "previous owner died"}, + {97, "EINTEGRITY", "integrity check failed"}, +} + +// Signal table +var signalList = [...]struct { + num syscall.Signal + name string + desc string +}{ + {1, "SIGHUP", "hangup"}, + {2, "SIGINT", "interrupt"}, + {3, "SIGQUIT", "quit"}, + {4, "SIGILL", "illegal instruction"}, + {5, "SIGTRAP", "trace/BPT trap"}, + {6, "SIGIOT", "abort trap"}, + {7, "SIGEMT", "EMT trap"}, + {8, "SIGFPE", "floating point exception"}, + {9, "SIGKILL", "killed"}, + {10, "SIGBUS", "bus error"}, + {11, "SIGSEGV", "segmentation fault"}, + {12, "SIGSYS", "bad system call"}, + {13, "SIGPIPE", "broken pipe"}, + {14, "SIGALRM", "alarm clock"}, + {15, "SIGTERM", "terminated"}, + {16, "SIGURG", "urgent I/O condition"}, + {17, "SIGSTOP", "suspended (signal)"}, + {18, "SIGTSTP", "suspended"}, + {19, "SIGCONT", "continued"}, + {20, "SIGCHLD", "child exited"}, + {21, "SIGTTIN", "stopped (tty input)"}, + {22, "SIGTTOU", "stopped (tty output)"}, + {23, "SIGIO", "I/O possible"}, + {24, "SIGXCPU", "cputime limit exceeded"}, + {25, "SIGXFSZ", "filesize limit exceeded"}, + {26, "SIGVTALRM", "virtual timer expired"}, + {27, "SIGPROF", "profiling timer expired"}, + {28, "SIGWINCH", "window size changes"}, + {29, "SIGINFO", "information request"}, + {30, "SIGUSR1", "user defined signal 1"}, + {31, "SIGUSR2", "user defined signal 2"}, + {32, "SIGTHR", "unknown signal"}, + {33, "SIGLIBRT", "unknown signal"}, +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 84c599c..120a7b3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1,6 +1,6 @@ -// Code generated by mkmerge.go; DO NOT EDIT. +// Code generated by mkmerge; DO NOT EDIT. -// +build linux +//go:build linux package unix @@ -37,7 +37,8 @@ const ( AF_KEY = 0xf AF_LLC = 0x1a AF_LOCAL = 0x1 - AF_MAX = 0x2d + AF_MAX = 0x2e + AF_MCTP = 0x2d AF_MPLS = 0x1c AF_NETBEUI = 0xd AF_NETLINK = 0x10 @@ -65,8 +66,10 @@ const ( ALG_OP_ENCRYPT = 0x1 ALG_SET_AEAD_ASSOCLEN = 0x4 ALG_SET_AEAD_AUTHSIZE = 0x5 + ALG_SET_DRBG_ENTROPY = 0x6 ALG_SET_IV = 0x2 ALG_SET_KEY = 0x1 + ALG_SET_KEY_BY_KEY_SERIAL = 0x7 ALG_SET_OP = 0x3 ANON_INODE_FS_MAGIC = 0x9041934 ARPHRD_6LOWPAN = 0x339 @@ -114,6 +117,7 @@ const ( ARPHRD_LAPB = 0x204 ARPHRD_LOCALTLK = 0x305 ARPHRD_LOOPBACK = 0x304 + ARPHRD_MCTP = 0x122 ARPHRD_METRICOM = 0x17 ARPHRD_NETLINK = 0x338 ARPHRD_NETROM = 0x0 @@ -136,6 +140,312 @@ const ( ARPHRD_VOID = 0xffff ARPHRD_VSOCKMON = 0x33a ARPHRD_X25 = 0x10f + AUDIT_ADD = 0x3eb + AUDIT_ADD_RULE = 0x3f3 + AUDIT_ALWAYS = 0x2 + AUDIT_ANOM_ABEND = 0x6a5 + AUDIT_ANOM_CREAT = 0x6a7 + AUDIT_ANOM_LINK = 0x6a6 + AUDIT_ANOM_PROMISCUOUS = 0x6a4 + AUDIT_ARCH = 0xb + AUDIT_ARCH_AARCH64 = 0xc00000b7 + AUDIT_ARCH_ALPHA = 0xc0009026 + AUDIT_ARCH_ARCOMPACT = 0x4000005d + AUDIT_ARCH_ARCOMPACTBE = 0x5d + AUDIT_ARCH_ARCV2 = 0x400000c3 + AUDIT_ARCH_ARCV2BE = 0xc3 + AUDIT_ARCH_ARM = 0x40000028 + AUDIT_ARCH_ARMEB = 0x28 + AUDIT_ARCH_C6X = 0x4000008c + AUDIT_ARCH_C6XBE = 0x8c + AUDIT_ARCH_CRIS = 0x4000004c + AUDIT_ARCH_CSKY = 0x400000fc + AUDIT_ARCH_FRV = 0x5441 + AUDIT_ARCH_H8300 = 0x2e + AUDIT_ARCH_HEXAGON = 0xa4 + AUDIT_ARCH_I386 = 0x40000003 + AUDIT_ARCH_IA64 = 0xc0000032 + AUDIT_ARCH_LOONGARCH32 = 0x40000102 + AUDIT_ARCH_LOONGARCH64 = 0xc0000102 + AUDIT_ARCH_M32R = 0x58 + AUDIT_ARCH_M68K = 0x4 + AUDIT_ARCH_MICROBLAZE = 0xbd + AUDIT_ARCH_MIPS = 0x8 + AUDIT_ARCH_MIPS64 = 0x80000008 + AUDIT_ARCH_MIPS64N32 = 0xa0000008 + AUDIT_ARCH_MIPSEL = 0x40000008 + AUDIT_ARCH_MIPSEL64 = 0xc0000008 + AUDIT_ARCH_MIPSEL64N32 = 0xe0000008 + AUDIT_ARCH_NDS32 = 0x400000a7 + AUDIT_ARCH_NDS32BE = 0xa7 + AUDIT_ARCH_NIOS2 = 0x40000071 + AUDIT_ARCH_OPENRISC = 0x5c + AUDIT_ARCH_PARISC = 0xf + AUDIT_ARCH_PARISC64 = 0x8000000f + AUDIT_ARCH_PPC = 0x14 + AUDIT_ARCH_PPC64 = 0x80000015 + AUDIT_ARCH_PPC64LE = 0xc0000015 + AUDIT_ARCH_RISCV32 = 0x400000f3 + AUDIT_ARCH_RISCV64 = 0xc00000f3 + AUDIT_ARCH_S390 = 0x16 + AUDIT_ARCH_S390X = 0x80000016 + AUDIT_ARCH_SH = 0x2a + AUDIT_ARCH_SH64 = 0x8000002a + AUDIT_ARCH_SHEL = 0x4000002a + AUDIT_ARCH_SHEL64 = 0xc000002a + AUDIT_ARCH_SPARC = 0x2 + AUDIT_ARCH_SPARC64 = 0x8000002b + AUDIT_ARCH_TILEGX = 0xc00000bf + AUDIT_ARCH_TILEGX32 = 0x400000bf + AUDIT_ARCH_TILEPRO = 0x400000bc + AUDIT_ARCH_UNICORE = 0x4000006e + AUDIT_ARCH_X86_64 = 0xc000003e + AUDIT_ARCH_XTENSA = 0x5e + AUDIT_ARG0 = 0xc8 + AUDIT_ARG1 = 0xc9 + AUDIT_ARG2 = 0xca + AUDIT_ARG3 = 0xcb + AUDIT_AVC = 0x578 + AUDIT_AVC_PATH = 0x57a + AUDIT_BITMASK_SIZE = 0x40 + AUDIT_BIT_MASK = 0x8000000 + AUDIT_BIT_TEST = 0x48000000 + AUDIT_BPF = 0x536 + AUDIT_BPRM_FCAPS = 0x529 + AUDIT_CAPSET = 0x52a + AUDIT_CLASS_CHATTR = 0x2 + AUDIT_CLASS_CHATTR_32 = 0x3 + AUDIT_CLASS_DIR_WRITE = 0x0 + AUDIT_CLASS_DIR_WRITE_32 = 0x1 + AUDIT_CLASS_READ = 0x4 + AUDIT_CLASS_READ_32 = 0x5 + AUDIT_CLASS_SIGNAL = 0x8 + AUDIT_CLASS_SIGNAL_32 = 0x9 + AUDIT_CLASS_WRITE = 0x6 + AUDIT_CLASS_WRITE_32 = 0x7 + AUDIT_COMPARE_AUID_TO_EUID = 0x10 + AUDIT_COMPARE_AUID_TO_FSUID = 0xe + AUDIT_COMPARE_AUID_TO_OBJ_UID = 0x5 + AUDIT_COMPARE_AUID_TO_SUID = 0xf + AUDIT_COMPARE_EGID_TO_FSGID = 0x17 + AUDIT_COMPARE_EGID_TO_OBJ_GID = 0x4 + AUDIT_COMPARE_EGID_TO_SGID = 0x18 + AUDIT_COMPARE_EUID_TO_FSUID = 0x12 + AUDIT_COMPARE_EUID_TO_OBJ_UID = 0x3 + AUDIT_COMPARE_EUID_TO_SUID = 0x11 + AUDIT_COMPARE_FSGID_TO_OBJ_GID = 0x9 + AUDIT_COMPARE_FSUID_TO_OBJ_UID = 0x8 + AUDIT_COMPARE_GID_TO_EGID = 0x14 + AUDIT_COMPARE_GID_TO_FSGID = 0x15 + AUDIT_COMPARE_GID_TO_OBJ_GID = 0x2 + AUDIT_COMPARE_GID_TO_SGID = 0x16 + AUDIT_COMPARE_SGID_TO_FSGID = 0x19 + AUDIT_COMPARE_SGID_TO_OBJ_GID = 0x7 + AUDIT_COMPARE_SUID_TO_FSUID = 0x13 + AUDIT_COMPARE_SUID_TO_OBJ_UID = 0x6 + AUDIT_COMPARE_UID_TO_AUID = 0xa + AUDIT_COMPARE_UID_TO_EUID = 0xb + AUDIT_COMPARE_UID_TO_FSUID = 0xc + AUDIT_COMPARE_UID_TO_OBJ_UID = 0x1 + AUDIT_COMPARE_UID_TO_SUID = 0xd + AUDIT_CONFIG_CHANGE = 0x519 + AUDIT_CWD = 0x51b + AUDIT_DAEMON_ABORT = 0x4b2 + AUDIT_DAEMON_CONFIG = 0x4b3 + AUDIT_DAEMON_END = 0x4b1 + AUDIT_DAEMON_START = 0x4b0 + AUDIT_DEL = 0x3ec + AUDIT_DEL_RULE = 0x3f4 + AUDIT_DEVMAJOR = 0x64 + AUDIT_DEVMINOR = 0x65 + AUDIT_DIR = 0x6b + AUDIT_DM_CTRL = 0x53a + AUDIT_DM_EVENT = 0x53b + AUDIT_EGID = 0x6 + AUDIT_EOE = 0x528 + AUDIT_EQUAL = 0x40000000 + AUDIT_EUID = 0x2 + AUDIT_EVENT_LISTENER = 0x537 + AUDIT_EXE = 0x70 + AUDIT_EXECVE = 0x51d + AUDIT_EXIT = 0x67 + AUDIT_FAIL_PANIC = 0x2 + AUDIT_FAIL_PRINTK = 0x1 + AUDIT_FAIL_SILENT = 0x0 + AUDIT_FANOTIFY = 0x533 + AUDIT_FD_PAIR = 0x525 + AUDIT_FEATURE_BITMAP_ALL = 0x7f + AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT = 0x1 + AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME = 0x2 + AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND = 0x8 + AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH = 0x4 + AUDIT_FEATURE_BITMAP_FILTER_FS = 0x40 + AUDIT_FEATURE_BITMAP_LOST_RESET = 0x20 + AUDIT_FEATURE_BITMAP_SESSIONID_FILTER = 0x10 + AUDIT_FEATURE_CHANGE = 0x530 + AUDIT_FEATURE_LOGINUID_IMMUTABLE = 0x1 + AUDIT_FEATURE_ONLY_UNSET_LOGINUID = 0x0 + AUDIT_FEATURE_VERSION = 0x1 + AUDIT_FIELD_COMPARE = 0x6f + AUDIT_FILETYPE = 0x6c + AUDIT_FILTERKEY = 0xd2 + AUDIT_FILTER_ENTRY = 0x2 + AUDIT_FILTER_EXCLUDE = 0x5 + AUDIT_FILTER_EXIT = 0x4 + AUDIT_FILTER_FS = 0x6 + AUDIT_FILTER_PREPEND = 0x10 + AUDIT_FILTER_TASK = 0x1 + AUDIT_FILTER_TYPE = 0x5 + AUDIT_FILTER_URING_EXIT = 0x7 + AUDIT_FILTER_USER = 0x0 + AUDIT_FILTER_WATCH = 0x3 + AUDIT_FIRST_KERN_ANOM_MSG = 0x6a4 + AUDIT_FIRST_USER_MSG = 0x44c + AUDIT_FIRST_USER_MSG2 = 0x834 + AUDIT_FSGID = 0x8 + AUDIT_FSTYPE = 0x1a + AUDIT_FSUID = 0x4 + AUDIT_GET = 0x3e8 + AUDIT_GET_FEATURE = 0x3fb + AUDIT_GID = 0x5 + AUDIT_GREATER_THAN = 0x20000000 + AUDIT_GREATER_THAN_OR_EQUAL = 0x60000000 + AUDIT_INODE = 0x66 + AUDIT_INTEGRITY_DATA = 0x708 + AUDIT_INTEGRITY_EVM_XATTR = 0x70e + AUDIT_INTEGRITY_HASH = 0x70b + AUDIT_INTEGRITY_METADATA = 0x709 + AUDIT_INTEGRITY_PCR = 0x70c + 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 + AUDIT_LANDLOCK_ACCESS = 0x58f + AUDIT_LANDLOCK_DOMAIN = 0x590 + AUDIT_LAST_FEATURE = 0x1 + AUDIT_LAST_KERN_ANOM_MSG = 0x707 + AUDIT_LAST_USER_MSG = 0x4af + AUDIT_LAST_USER_MSG2 = 0xbb7 + AUDIT_LESS_THAN = 0x10000000 + AUDIT_LESS_THAN_OR_EQUAL = 0x50000000 + AUDIT_LIST = 0x3ea + AUDIT_LIST_RULES = 0x3f5 + AUDIT_LOGIN = 0x3ee + AUDIT_LOGINUID = 0x9 + AUDIT_LOGINUID_SET = 0x18 + AUDIT_MAC_CALIPSO_ADD = 0x58a + AUDIT_MAC_CALIPSO_DEL = 0x58b + AUDIT_MAC_CIPSOV4_ADD = 0x57f + AUDIT_MAC_CIPSOV4_DEL = 0x580 + AUDIT_MAC_CONFIG_CHANGE = 0x57d + AUDIT_MAC_IPSEC_ADDSA = 0x583 + AUDIT_MAC_IPSEC_ADDSPD = 0x585 + AUDIT_MAC_IPSEC_DELSA = 0x584 + AUDIT_MAC_IPSEC_DELSPD = 0x586 + AUDIT_MAC_IPSEC_EVENT = 0x587 + AUDIT_MAC_MAP_ADD = 0x581 + AUDIT_MAC_MAP_DEL = 0x582 + AUDIT_MAC_POLICY_LOAD = 0x57b + AUDIT_MAC_STATUS = 0x57c + AUDIT_MAC_UNLBL_ALLOW = 0x57e + AUDIT_MAC_UNLBL_STCADD = 0x588 + AUDIT_MAC_UNLBL_STCDEL = 0x589 + AUDIT_MAKE_EQUIV = 0x3f7 + AUDIT_MAX_FIELDS = 0x40 + AUDIT_MAX_FIELD_COMPARE = 0x19 + AUDIT_MAX_KEY_LEN = 0x100 + AUDIT_MESSAGE_TEXT_MAX = 0x2170 + AUDIT_MMAP = 0x52b + AUDIT_MQ_GETSETATTR = 0x523 + AUDIT_MQ_NOTIFY = 0x522 + AUDIT_MQ_OPEN = 0x520 + AUDIT_MQ_SENDRECV = 0x521 + AUDIT_MSGTYPE = 0xc + AUDIT_NEGATE = 0x80000000 + AUDIT_NETFILTER_CFG = 0x52d + AUDIT_NETFILTER_PKT = 0x52c + AUDIT_NEVER = 0x0 + AUDIT_NLGRP_MAX = 0x1 + AUDIT_NOT_EQUAL = 0x30000000 + AUDIT_NR_FILTERS = 0x8 + AUDIT_OBJ_GID = 0x6e + AUDIT_OBJ_LEV_HIGH = 0x17 + AUDIT_OBJ_LEV_LOW = 0x16 + AUDIT_OBJ_PID = 0x526 + AUDIT_OBJ_ROLE = 0x14 + AUDIT_OBJ_TYPE = 0x15 + AUDIT_OBJ_UID = 0x6d + AUDIT_OBJ_USER = 0x13 + AUDIT_OPENAT2 = 0x539 + AUDIT_OPERATORS = 0x78000000 + AUDIT_PATH = 0x516 + AUDIT_PERM = 0x6a + AUDIT_PERM_ATTR = 0x8 + AUDIT_PERM_EXEC = 0x1 + AUDIT_PERM_READ = 0x4 + AUDIT_PERM_WRITE = 0x2 + AUDIT_PERS = 0xa + AUDIT_PID = 0x0 + AUDIT_POSSIBLE = 0x1 + AUDIT_PPID = 0x12 + AUDIT_PROCTITLE = 0x52f + AUDIT_REPLACE = 0x531 + AUDIT_SADDR_FAM = 0x71 + AUDIT_SECCOMP = 0x52e + AUDIT_SELINUX_ERR = 0x579 + AUDIT_SESSIONID = 0x19 + AUDIT_SET = 0x3e9 + AUDIT_SET_FEATURE = 0x3fa + AUDIT_SGID = 0x7 + AUDIT_SID_UNSET = 0xffffffff + AUDIT_SIGNAL_INFO = 0x3f2 + AUDIT_SOCKADDR = 0x51a + AUDIT_SOCKETCALL = 0x518 + AUDIT_STATUS_BACKLOG_LIMIT = 0x10 + AUDIT_STATUS_BACKLOG_WAIT_TIME = 0x20 + AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL = 0x80 + AUDIT_STATUS_ENABLED = 0x1 + AUDIT_STATUS_FAILURE = 0x2 + AUDIT_STATUS_LOST = 0x40 + AUDIT_STATUS_PID = 0x4 + AUDIT_STATUS_RATE_LIMIT = 0x8 + AUDIT_SUBJ_CLR = 0x11 + AUDIT_SUBJ_ROLE = 0xe + AUDIT_SUBJ_SEN = 0x10 + AUDIT_SUBJ_TYPE = 0xf + AUDIT_SUBJ_USER = 0xd + AUDIT_SUCCESS = 0x68 + AUDIT_SUID = 0x3 + AUDIT_SYSCALL = 0x514 + AUDIT_SYSCALL_CLASSES = 0x10 + AUDIT_TIME_ADJNTPVAL = 0x535 + AUDIT_TIME_INJOFFSET = 0x534 + AUDIT_TRIM = 0x3f6 + AUDIT_TTY = 0x527 + AUDIT_TTY_GET = 0x3f8 + AUDIT_TTY_SET = 0x3f9 + AUDIT_UID = 0x1 + AUDIT_UID_UNSET = 0xffffffff + AUDIT_UNUSED_BITS = 0x7fffc00 + AUDIT_URINGOP = 0x538 + AUDIT_USER = 0x3ed + AUDIT_USER_AVC = 0x453 + AUDIT_USER_TTY = 0x464 + AUDIT_VERSION_BACKLOG_LIMIT = 0x1 + AUDIT_VERSION_BACKLOG_WAIT_TIME = 0x2 + AUDIT_VERSION_LATEST = 0x7f + AUDIT_WATCH = 0x69 + AUDIT_WATCH_INS = 0x3ef + AUDIT_WATCH_LIST = 0x3f1 + AUDIT_WATCH_REM = 0x3f0 AUTOFS_SUPER_MAGIC = 0x187 B0 = 0x0 B110 = 0x3 @@ -153,88 +463,56 @@ const ( B600 = 0x8 B75 = 0x2 B9600 = 0xd - BALLOON_KVM_MAGIC = 0x13661366 + BCACHEFS_SUPER_MAGIC = 0xca451a4e BDEVFS_MAGIC = 0x62646576 BINDERFS_SUPER_MAGIC = 0x6c6f6f70 BINFMTFS_MAGIC = 0x42494e4d BPF_A = 0x10 BPF_ABS = 0x20 BPF_ADD = 0x0 - BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff - BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 0x38 BPF_ALU = 0x4 BPF_ALU64 = 0x7 BPF_AND = 0x50 - BPF_ANY = 0x0 BPF_ARSH = 0xc0 + BPF_ATOMIC = 0xc0 BPF_B = 0x10 BPF_BUILD_ID_SIZE = 0x14 BPF_CALL = 0x80 - BPF_DEVCG_ACC_MKNOD = 0x1 - BPF_DEVCG_ACC_READ = 0x2 - BPF_DEVCG_ACC_WRITE = 0x4 - BPF_DEVCG_DEV_BLOCK = 0x1 - BPF_DEVCG_DEV_CHAR = 0x2 + BPF_CMPXCHG = 0xf1 BPF_DIV = 0x30 BPF_DW = 0x18 BPF_END = 0xd0 - BPF_EXIST = 0x2 BPF_EXIT = 0x90 - BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG = 0x1 - BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP = 0x4 - BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL = 0x2 + BPF_FETCH = 0x1 BPF_FROM_BE = 0x8 BPF_FROM_LE = 0x0 BPF_FS_MAGIC = 0xcafe4a11 - BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = 0x2 - BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = 0x4 - BPF_F_ADJ_ROOM_ENCAP_L4_GRE = 0x8 - BPF_F_ADJ_ROOM_ENCAP_L4_UDP = 0x10 - BPF_F_ADJ_ROOM_FIXED_GSO = 0x1 + BPF_F_AFTER = 0x10 BPF_F_ALLOW_MULTI = 0x2 BPF_F_ALLOW_OVERRIDE = 0x1 BPF_F_ANY_ALIGNMENT = 0x2 - BPF_F_CLONE = 0x200 - BPF_F_CTXLEN_MASK = 0xfffff00000000 - BPF_F_CURRENT_CPU = 0xffffffff - BPF_F_CURRENT_NETNS = -0x1 - BPF_F_DONT_FRAGMENT = 0x4 - BPF_F_FAST_STACK_CMP = 0x200 - BPF_F_HDR_FIELD_MASK = 0xf - BPF_F_INDEX_MASK = 0xffffffff - BPF_F_INGRESS = 0x1 - BPF_F_INVALIDATE_HASH = 0x2 - BPF_F_LOCK = 0x4 - BPF_F_MARK_ENFORCE = 0x40 - BPF_F_MARK_MANGLED_0 = 0x20 - BPF_F_MMAPABLE = 0x400 - BPF_F_NO_COMMON_LRU = 0x2 - BPF_F_NO_PREALLOC = 0x1 - BPF_F_NUMA_NODE = 0x4 - BPF_F_PSEUDO_HDR = 0x10 + BPF_F_BEFORE = 0x8 + BPF_F_ID = 0x20 + BPF_F_NETFILTER_IP_DEFRAG = 0x1 + BPF_F_PREORDER = 0x40 BPF_F_QUERY_EFFECTIVE = 0x1 - BPF_F_RDONLY = 0x8 - BPF_F_RDONLY_PROG = 0x80 - BPF_F_RECOMPUTE_CSUM = 0x1 - BPF_F_REUSE_STACKID = 0x400 - BPF_F_SEQ_NUMBER = 0x8 - BPF_F_SKIP_FIELD_MASK = 0xff - BPF_F_STACK_BUILD_ID = 0x20 + BPF_F_REDIRECT_FLAGS = 0x19 + BPF_F_REPLACE = 0x4 + BPF_F_SLEEPABLE = 0x10 BPF_F_STRICT_ALIGNMENT = 0x1 - BPF_F_SYSCTL_BASE_NAME = 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_TUNINFO_IPV6 = 0x1 - BPF_F_USER_BUILD_ID = 0x800 - BPF_F_USER_STACK = 0x100 - BPF_F_WRONLY = 0x10 - BPF_F_WRONLY_PROG = 0x100 - BPF_F_ZERO_CSUM_TX = 0x2 - BPF_F_ZERO_SEED = 0x40 + BPF_F_TEST_XDP_LIVE_FRAMES = 0x2 + BPF_F_XDP_DEV_BOUND_ONLY = 0x40 + BPF_F_XDP_HAS_FRAGS = 0x20 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 BPF_JA = 0x0 + BPF_JCOND = 0xe0 BPF_JEQ = 0x10 BPF_JGE = 0x30 BPF_JGT = 0x20 @@ -253,10 +531,12 @@ const ( BPF_LDX = 0x1 BPF_LEN = 0x80 BPF_LL_OFF = -0x200000 + BPF_LOAD_ACQ = 0x100 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 BPF_MEM = 0x60 + BPF_MEMSX = 0x80 BPF_MEMWORDS = 0x10 BPF_MINOR_VERSION = 0x1 BPF_MISC = 0x7 @@ -266,21 +546,20 @@ const ( BPF_MUL = 0x20 BPF_NEG = 0x80 BPF_NET_OFF = -0x100000 - BPF_NOEXIST = 0x1 BPF_OBJ_NAME_LEN = 0x10 BPF_OR = 0x40 + BPF_PSEUDO_BTF_ID = 0x3 BPF_PSEUDO_CALL = 0x1 + BPF_PSEUDO_FUNC = 0x4 + BPF_PSEUDO_KFUNC_CALL = 0x2 BPF_PSEUDO_MAP_FD = 0x1 + BPF_PSEUDO_MAP_IDX = 0x5 + BPF_PSEUDO_MAP_IDX_VALUE = 0x6 BPF_PSEUDO_MAP_VALUE = 0x2 BPF_RET = 0x6 BPF_RSH = 0x70 - BPF_SK_STORAGE_GET_F_CREATE = 0x1 - BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf - BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 - BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 - BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 - BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 BPF_ST = 0x2 + BPF_STORE_REL = 0x110 BPF_STX = 0x3 BPF_SUB = 0x10 BPF_TAG_SIZE = 0x8 @@ -291,36 +570,121 @@ const ( BPF_W = 0x0 BPF_X = 0x8 BPF_XADD = 0xc0 + BPF_XCHG = 0xe1 BPF_XOR = 0xa0 BRKINT = 0x2 BS0 = 0x0 BTRFS_SUPER_MAGIC = 0x9123683e BTRFS_TEST_MAGIC = 0x73727279 + BUS_BLUETOOTH = 0x5 + BUS_HIL = 0x4 + BUS_USB = 0x3 + BUS_VIRTUAL = 0x6 CAN_BCM = 0x2 + CAN_BUS_OFF_THRESHOLD = 0x100 + CAN_CTRLMODE_3_SAMPLES = 0x4 + CAN_CTRLMODE_BERR_REPORTING = 0x10 + CAN_CTRLMODE_CC_LEN8_DLC = 0x100 + CAN_CTRLMODE_FD = 0x20 + CAN_CTRLMODE_FD_NON_ISO = 0x80 + CAN_CTRLMODE_LISTENONLY = 0x2 + CAN_CTRLMODE_LOOPBACK = 0x1 + CAN_CTRLMODE_ONE_SHOT = 0x8 + CAN_CTRLMODE_PRESUME_ACK = 0x40 + CAN_CTRLMODE_TDC_AUTO = 0x200 + CAN_CTRLMODE_TDC_MANUAL = 0x400 CAN_EFF_FLAG = 0x80000000 CAN_EFF_ID_BITS = 0x1d CAN_EFF_MASK = 0x1fffffff + CAN_ERROR_PASSIVE_THRESHOLD = 0x80 + CAN_ERROR_WARNING_THRESHOLD = 0x60 + CAN_ERR_ACK = 0x20 + CAN_ERR_BUSERROR = 0x80 + CAN_ERR_BUSOFF = 0x40 + CAN_ERR_CNT = 0x200 + CAN_ERR_CRTL = 0x4 + CAN_ERR_CRTL_ACTIVE = 0x40 + CAN_ERR_CRTL_RX_OVERFLOW = 0x1 + CAN_ERR_CRTL_RX_PASSIVE = 0x10 + CAN_ERR_CRTL_RX_WARNING = 0x4 + CAN_ERR_CRTL_TX_OVERFLOW = 0x2 + CAN_ERR_CRTL_TX_PASSIVE = 0x20 + CAN_ERR_CRTL_TX_WARNING = 0x8 + CAN_ERR_CRTL_UNSPEC = 0x0 + CAN_ERR_DLC = 0x8 CAN_ERR_FLAG = 0x20000000 + CAN_ERR_LOSTARB = 0x2 + CAN_ERR_LOSTARB_UNSPEC = 0x0 CAN_ERR_MASK = 0x1fffffff + CAN_ERR_PROT = 0x8 + CAN_ERR_PROT_ACTIVE = 0x40 + CAN_ERR_PROT_BIT = 0x1 + CAN_ERR_PROT_BIT0 = 0x8 + CAN_ERR_PROT_BIT1 = 0x10 + CAN_ERR_PROT_FORM = 0x2 + CAN_ERR_PROT_LOC_ACK = 0x19 + CAN_ERR_PROT_LOC_ACK_DEL = 0x1b + CAN_ERR_PROT_LOC_CRC_DEL = 0x18 + CAN_ERR_PROT_LOC_CRC_SEQ = 0x8 + CAN_ERR_PROT_LOC_DATA = 0xa + CAN_ERR_PROT_LOC_DLC = 0xb + CAN_ERR_PROT_LOC_EOF = 0x1a + CAN_ERR_PROT_LOC_ID04_00 = 0xe + CAN_ERR_PROT_LOC_ID12_05 = 0xf + CAN_ERR_PROT_LOC_ID17_13 = 0x7 + CAN_ERR_PROT_LOC_ID20_18 = 0x6 + CAN_ERR_PROT_LOC_ID28_21 = 0x2 + CAN_ERR_PROT_LOC_IDE = 0x5 + CAN_ERR_PROT_LOC_INTERM = 0x12 + CAN_ERR_PROT_LOC_RES0 = 0x9 + CAN_ERR_PROT_LOC_RES1 = 0xd + CAN_ERR_PROT_LOC_RTR = 0xc + CAN_ERR_PROT_LOC_SOF = 0x3 + CAN_ERR_PROT_LOC_SRTR = 0x4 + CAN_ERR_PROT_LOC_UNSPEC = 0x0 + CAN_ERR_PROT_OVERLOAD = 0x20 + CAN_ERR_PROT_STUFF = 0x4 + CAN_ERR_PROT_TX = 0x80 + CAN_ERR_PROT_UNSPEC = 0x0 + CAN_ERR_RESTARTED = 0x100 + CAN_ERR_TRX = 0x10 + CAN_ERR_TRX_CANH_NO_WIRE = 0x4 + CAN_ERR_TRX_CANH_SHORT_TO_BAT = 0x5 + CAN_ERR_TRX_CANH_SHORT_TO_GND = 0x7 + CAN_ERR_TRX_CANH_SHORT_TO_VCC = 0x6 + CAN_ERR_TRX_CANL_NO_WIRE = 0x40 + CAN_ERR_TRX_CANL_SHORT_TO_BAT = 0x50 + CAN_ERR_TRX_CANL_SHORT_TO_CANH = 0x80 + CAN_ERR_TRX_CANL_SHORT_TO_GND = 0x70 + CAN_ERR_TRX_CANL_SHORT_TO_VCC = 0x60 + CAN_ERR_TRX_UNSPEC = 0x0 + CAN_ERR_TX_TIMEOUT = 0x1 CAN_INV_FILTER = 0x20000000 CAN_ISOTP = 0x6 CAN_J1939 = 0x7 CAN_MAX_DLC = 0x8 CAN_MAX_DLEN = 0x8 + CAN_MAX_RAW_DLC = 0xf CAN_MCNET = 0x5 CAN_MTU = 0x10 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 + CAN_TERMINATION_DISABLED = 0x0 CAN_TP16 = 0x3 CAN_TP20 = 0x4 CAP_AUDIT_CONTROL = 0x1e CAP_AUDIT_READ = 0x25 CAP_AUDIT_WRITE = 0x1d CAP_BLOCK_SUSPEND = 0x24 + CAP_BPF = 0x27 + CAP_CHECKPOINT_RESTORE = 0x28 CAP_CHOWN = 0x0 CAP_DAC_OVERRIDE = 0x1 CAP_DAC_READ_SEARCH = 0x2 @@ -329,7 +693,7 @@ const ( CAP_IPC_LOCK = 0xe CAP_IPC_OWNER = 0xf CAP_KILL = 0x5 - CAP_LAST_CAP = 0x25 + CAP_LAST_CAP = 0x28 CAP_LEASE = 0x1c CAP_LINUX_IMMUTABLE = 0x9 CAP_MAC_ADMIN = 0x21 @@ -339,6 +703,7 @@ const ( CAP_NET_BIND_SERVICE = 0xa CAP_NET_BROADCAST = 0xb CAP_NET_RAW = 0xd + CAP_PERFMON = 0x26 CAP_SETFCAP = 0x1f CAP_SETGID = 0x6 CAP_SETPCAP = 0x8 @@ -356,9 +721,11 @@ const ( CAP_SYS_TIME = 0x19 CAP_SYS_TTY_CONFIG = 0x1a CAP_WAKE_ALARM = 0x23 + CEPH_SUPER_MAGIC = 0xc36400 CFLUSH = 0xf CGROUP2_SUPER_MAGIC = 0x63677270 CGROUP_SUPER_MAGIC = 0x27e0eb + CIFS_SUPER_MAGIC = 0xff534d42 CLOCK_BOOTTIME = 0x7 CLOCK_BOOTTIME_ALARM = 0x9 CLOCK_DEFAULT = 0x0 @@ -377,18 +744,21 @@ const ( CLOCK_TXINT = 0x3 CLONE_ARGS_SIZE_VER0 = 0x40 CLONE_ARGS_SIZE_VER1 = 0x50 + CLONE_ARGS_SIZE_VER2 = 0x58 CLONE_CHILD_CLEARTID = 0x200000 CLONE_CHILD_SETTID = 0x1000000 CLONE_CLEAR_SIGHAND = 0x100000000 CLONE_DETACHED = 0x400000 CLONE_FILES = 0x400 CLONE_FS = 0x200 + CLONE_INTO_CGROUP = 0x200000000 CLONE_IO = 0x80000000 CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 CLONE_NEWPID = 0x20000000 + CLONE_NEWTIME = 0x80 CLONE_NEWUSER = 0x10000000 CLONE_NEWUTS = 0x4000000 CLONE_PARENT = 0x8000 @@ -421,26 +791,197 @@ const ( DEBUGFS_MAGIC = 0x64626720 DEVLINK_CMD_ESWITCH_MODE_GET = 0x1d DEVLINK_CMD_ESWITCH_MODE_SET = 0x1e + DEVLINK_FLASH_OVERWRITE_IDENTIFIERS = 0x2 + DEVLINK_FLASH_OVERWRITE_SETTINGS = 0x1 DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" DEVLINK_GENL_NAME = "devlink" DEVLINK_GENL_VERSION = 0x1 + DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO = 0x4 + DEVLINK_PORT_FN_CAP_IPSEC_PACKET = 0x8 + DEVLINK_PORT_FN_CAP_MIGRATABLE = 0x2 + DEVLINK_PORT_FN_CAP_ROCE = 0x1 DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 + DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS = 0x3 + DEVMEM_MAGIC = 0x454d444d DEVPTS_SUPER_MAGIC = 0x1cd1 DMA_BUF_MAGIC = 0x444d4142 + DM_ACTIVE_PRESENT_FLAG = 0x20 + DM_BUFFER_FULL_FLAG = 0x100 + DM_CONTROL_NODE = "control" + DM_DATA_OUT_FLAG = 0x10000 + DM_DEFERRED_REMOVE = 0x20000 + DM_DEV_ARM_POLL = 0xc138fd10 + DM_DEV_CREATE = 0xc138fd03 + DM_DEV_REMOVE = 0xc138fd04 + DM_DEV_RENAME = 0xc138fd05 + DM_DEV_SET_GEOMETRY = 0xc138fd0f + DM_DEV_STATUS = 0xc138fd07 + DM_DEV_SUSPEND = 0xc138fd06 + DM_DEV_WAIT = 0xc138fd08 + DM_DIR = "mapper" + DM_GET_TARGET_VERSION = 0xc138fd11 + DM_IMA_MEASUREMENT_FLAG = 0x80000 + DM_INACTIVE_PRESENT_FLAG = 0x40 + DM_INTERNAL_SUSPEND_FLAG = 0x40000 + DM_IOCTL = 0xfd + DM_LIST_DEVICES = 0xc138fd02 + DM_LIST_VERSIONS = 0xc138fd0d + DM_MAX_TYPE_NAME = 0x10 + DM_NAME_LEN = 0x80 + DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID = 0x2 + DM_NAME_LIST_FLAG_HAS_UUID = 0x1 + DM_NOFLUSH_FLAG = 0x800 + DM_PERSISTENT_DEV_FLAG = 0x8 + DM_QUERY_INACTIVE_TABLE_FLAG = 0x1000 + DM_READONLY_FLAG = 0x1 + DM_REMOVE_ALL = 0xc138fd01 + DM_SECURE_DATA_FLAG = 0x8000 + DM_SKIP_BDGET_FLAG = 0x200 + DM_SKIP_LOCKFS_FLAG = 0x400 + DM_STATUS_TABLE_FLAG = 0x10 + DM_SUSPEND_FLAG = 0x2 + DM_TABLE_CLEAR = 0xc138fd0a + DM_TABLE_DEPS = 0xc138fd0b + DM_TABLE_LOAD = 0xc138fd09 + DM_TABLE_STATUS = 0xc138fd0c + DM_TARGET_MSG = 0xc138fd0e + DM_UEVENT_GENERATED_FLAG = 0x2000 + DM_UUID_FLAG = 0x4000 + DM_UUID_LEN = 0x81 + DM_VERSION = 0xc138fd00 + DM_VERSION_EXTRA = "-ioctl (2025-04-28)" + DM_VERSION_MAJOR = 0x4 + DM_VERSION_MINOR = 0x32 + DM_VERSION_PATCHLEVEL = 0x0 + DT_ADDRRNGHI = 0x6ffffeff + DT_ADDRRNGLO = 0x6ffffe00 DT_BLK = 0x6 DT_CHR = 0x2 + DT_DEBUG = 0x15 DT_DIR = 0x4 + DT_ENCODING = 0x20 DT_FIFO = 0x1 + DT_FINI = 0xd + DT_FLAGS_1 = 0x6ffffffb + DT_GNU_HASH = 0x6ffffef5 + DT_HASH = 0x4 + DT_HIOS = 0x6ffff000 + DT_HIPROC = 0x7fffffff + DT_INIT = 0xc + DT_JMPREL = 0x17 DT_LNK = 0xa + DT_LOOS = 0x6000000d + DT_LOPROC = 0x70000000 + DT_NEEDED = 0x1 + DT_NULL = 0x0 + DT_PLTGOT = 0x3 + DT_PLTREL = 0x14 + DT_PLTRELSZ = 0x2 DT_REG = 0x8 + DT_REL = 0x11 + DT_RELA = 0x7 + DT_RELACOUNT = 0x6ffffff9 + DT_RELAENT = 0x9 + DT_RELASZ = 0x8 + DT_RELCOUNT = 0x6ffffffa + DT_RELENT = 0x13 + DT_RELSZ = 0x12 + DT_RPATH = 0xf DT_SOCK = 0xc + DT_SONAME = 0xe + DT_STRSZ = 0xa + DT_STRTAB = 0x5 + DT_SYMBOLIC = 0x10 + DT_SYMENT = 0xb + DT_SYMTAB = 0x6 + DT_TEXTREL = 0x16 DT_UNKNOWN = 0x0 + DT_VALRNGHI = 0x6ffffdff + DT_VALRNGLO = 0x6ffffd00 + DT_VERDEF = 0x6ffffffc + DT_VERDEFNUM = 0x6ffffffd + DT_VERNEED = 0x6ffffffe + DT_VERNEEDNUM = 0x6fffffff + DT_VERSYM = 0x6ffffff0 DT_WHT = 0xe ECHO = 0x8 ECRYPTFS_SUPER_MAGIC = 0xf15f EFD_SEMAPHORE = 0x1 EFIVARFS_MAGIC = 0xde5e81e4 EFS_SUPER_MAGIC = 0x414a53 + EI_CLASS = 0x4 + EI_DATA = 0x5 + EI_MAG0 = 0x0 + EI_MAG1 = 0x1 + EI_MAG2 = 0x2 + EI_MAG3 = 0x3 + EI_NIDENT = 0x10 + EI_OSABI = 0x7 + EI_PAD = 0x8 + EI_VERSION = 0x6 + ELFCLASS32 = 0x1 + ELFCLASS64 = 0x2 + ELFCLASSNONE = 0x0 + ELFCLASSNUM = 0x3 + ELFDATA2LSB = 0x1 + ELFDATA2MSB = 0x2 + ELFDATANONE = 0x0 + ELFMAG = "\177ELF" + ELFMAG0 = 0x7f + ELFMAG1 = 'E' + ELFMAG2 = 'L' + ELFMAG3 = 'F' + ELFOSABI_LINUX = 0x3 + ELFOSABI_NONE = 0x0 + EM_386 = 0x3 + EM_486 = 0x6 + EM_68K = 0x4 + EM_860 = 0x7 + EM_88K = 0x5 + EM_AARCH64 = 0xb7 + EM_ALPHA = 0x9026 + EM_ALTERA_NIOS2 = 0x71 + EM_ARCOMPACT = 0x5d + EM_ARCV2 = 0xc3 + EM_ARM = 0x28 + EM_BLACKFIN = 0x6a + EM_BPF = 0xf7 + EM_CRIS = 0x4c + EM_CSKY = 0xfc + EM_CYGNUS_M32R = 0x9041 + EM_CYGNUS_MN10300 = 0xbeef + EM_FRV = 0x5441 + EM_H8_300 = 0x2e + EM_HEXAGON = 0xa4 + EM_IA_64 = 0x32 + EM_LOONGARCH = 0x102 + EM_M32 = 0x1 + EM_M32R = 0x58 + EM_MICROBLAZE = 0xbd + EM_MIPS = 0x8 + EM_MIPS_RS3_LE = 0xa + EM_MIPS_RS4_BE = 0xa + EM_MN10300 = 0x59 + EM_NDS32 = 0xa7 + EM_NONE = 0x0 + EM_OPENRISC = 0x5c + EM_PARISC = 0xf + EM_PPC = 0x14 + EM_PPC64 = 0x15 + EM_RISCV = 0xf3 + EM_S390 = 0x16 + EM_S390_OLD = 0xa390 + EM_SH = 0x2a + EM_SPARC = 0x2 + EM_SPARC32PLUS = 0x12 + EM_SPARCV9 = 0x2b + EM_SPU = 0x17 + EM_TILEGX = 0xbf + EM_TILEPRO = 0xbc + EM_TI_C6000 = 0x8c + EM_UNICORE = 0x6e + EM_X86_64 = 0x3e + EM_XTENSA = 0x5e ENCODING_DEFAULT = 0x0 ENCODING_FM_MARK = 0x3 ENCODING_FM_SPACE = 0x4 @@ -465,7 +1006,117 @@ const ( EPOLL_CTL_ADD = 0x1 EPOLL_CTL_DEL = 0x2 EPOLL_CTL_MOD = 0x3 + EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 + 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 + ETHTOOL_FEC_NONE = 0x1 + ETHTOOL_FEC_OFF = 0x4 + ETHTOOL_FEC_RS = 0x8 + ETHTOOL_FLAG_ALL = 0x7 + ETHTOOL_FLASHDEV = 0x33 + ETHTOOL_FLASH_MAX_FILENAME = 0x80 + ETHTOOL_FWVERS_LEN = 0x20 + ETHTOOL_F_COMPAT = 0x4 + ETHTOOL_F_UNSUPPORTED = 0x1 + ETHTOOL_F_WISH = 0x2 + ETHTOOL_GCHANNELS = 0x3c + ETHTOOL_GCOALESCE = 0xe + ETHTOOL_GDRVINFO = 0x3 + ETHTOOL_GEEE = 0x44 + ETHTOOL_GEEPROM = 0xb + ETHTOOL_GENL_NAME = "ethtool" + ETHTOOL_GENL_VERSION = 0x1 + ETHTOOL_GET_DUMP_DATA = 0x40 + ETHTOOL_GET_DUMP_FLAG = 0x3f + ETHTOOL_GET_TS_INFO = 0x41 + ETHTOOL_GFEATURES = 0x3a + ETHTOOL_GFECPARAM = 0x50 + ETHTOOL_GFLAGS = 0x25 + ETHTOOL_GGRO = 0x2b + ETHTOOL_GGSO = 0x23 + ETHTOOL_GLINK = 0xa + ETHTOOL_GLINKSETTINGS = 0x4c + ETHTOOL_GMODULEEEPROM = 0x43 + ETHTOOL_GMODULEINFO = 0x42 + ETHTOOL_GMSGLVL = 0x7 + ETHTOOL_GPAUSEPARAM = 0x12 + ETHTOOL_GPERMADDR = 0x20 + ETHTOOL_GPFLAGS = 0x27 + ETHTOOL_GPHYSTATS = 0x4a + ETHTOOL_GREGS = 0x4 + ETHTOOL_GRINGPARAM = 0x10 + ETHTOOL_GRSSH = 0x46 + ETHTOOL_GRXCLSRLALL = 0x30 + ETHTOOL_GRXCLSRLCNT = 0x2e + ETHTOOL_GRXCLSRULE = 0x2f + ETHTOOL_GRXCSUM = 0x14 + ETHTOOL_GRXFH = 0x29 + ETHTOOL_GRXFHINDIR = 0x38 + ETHTOOL_GRXNTUPLE = 0x36 + ETHTOOL_GRXRINGS = 0x2d + ETHTOOL_GSET = 0x1 + ETHTOOL_GSG = 0x18 + ETHTOOL_GSSET_INFO = 0x37 + ETHTOOL_GSTATS = 0x1d + ETHTOOL_GSTRINGS = 0x1b + ETHTOOL_GTSO = 0x1e + ETHTOOL_GTUNABLE = 0x48 + ETHTOOL_GTXCSUM = 0x16 + ETHTOOL_GUFO = 0x21 + ETHTOOL_GWOL = 0x5 + ETHTOOL_MCGRP_MONITOR_NAME = "monitor" + ETHTOOL_NWAY_RST = 0x9 + ETHTOOL_PERQUEUE = 0x4b + ETHTOOL_PHYS_ID = 0x1c + ETHTOOL_PHY_EDPD_DFLT_TX_MSECS = 0xffff + ETHTOOL_PHY_EDPD_DISABLE = 0x0 + ETHTOOL_PHY_EDPD_NO_TX = 0xfffe + ETHTOOL_PHY_FAST_LINK_DOWN_OFF = 0xff + ETHTOOL_PHY_FAST_LINK_DOWN_ON = 0x0 + ETHTOOL_PHY_GTUNABLE = 0x4e + ETHTOOL_PHY_STUNABLE = 0x4f + ETHTOOL_RESET = 0x34 + ETHTOOL_RXNTUPLE_ACTION_CLEAR = -0x2 + ETHTOOL_RXNTUPLE_ACTION_DROP = -0x1 + ETHTOOL_RX_FLOW_SPEC_RING = 0xffffffff + ETHTOOL_RX_FLOW_SPEC_RING_VF = 0xff00000000 + ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF = 0x20 + ETHTOOL_SCHANNELS = 0x3d + ETHTOOL_SCOALESCE = 0xf + ETHTOOL_SEEE = 0x45 + ETHTOOL_SEEPROM = 0xc + ETHTOOL_SET_DUMP = 0x3e + ETHTOOL_SFEATURES = 0x3b + ETHTOOL_SFECPARAM = 0x51 + ETHTOOL_SFLAGS = 0x26 + ETHTOOL_SGRO = 0x2c + ETHTOOL_SGSO = 0x24 + ETHTOOL_SLINKSETTINGS = 0x4d + ETHTOOL_SMSGLVL = 0x8 + ETHTOOL_SPAUSEPARAM = 0x13 + ETHTOOL_SPFLAGS = 0x28 + ETHTOOL_SRINGPARAM = 0x11 + ETHTOOL_SRSSH = 0x47 + ETHTOOL_SRXCLSRLDEL = 0x31 + ETHTOOL_SRXCLSRLINS = 0x32 + ETHTOOL_SRXCSUM = 0x15 + ETHTOOL_SRXFH = 0x2a + ETHTOOL_SRXFHINDIR = 0x39 + ETHTOOL_SRXNTUPLE = 0x35 + ETHTOOL_SSET = 0x2 + ETHTOOL_SSG = 0x19 + ETHTOOL_STSO = 0x1f + ETHTOOL_STUNABLE = 0x49 + ETHTOOL_STXCSUM = 0x17 + ETHTOOL_SUFO = 0x22 + ETHTOOL_SWOL = 0x6 + ETHTOOL_TEST = 0x1a ETH_P_1588 = 0x88f7 ETH_P_8021AD = 0x88a8 ETH_P_8021AH = 0x88e7 @@ -490,6 +1141,8 @@ const ( ETH_P_CAIF = 0xf7 ETH_P_CAN = 0xc ETH_P_CANFD = 0xd + ETH_P_CANXL = 0xe + ETH_P_CFM = 0x8902 ETH_P_CONTROL = 0x16 ETH_P_CUST = 0x6006 ETH_P_DDCMP = 0x6 @@ -500,10 +1153,12 @@ const ( ETH_P_DNA_RT = 0x6003 ETH_P_DSA = 0x1b ETH_P_DSA_8021Q = 0xdadb + ETH_P_DSA_A5PSW = 0xe001 ETH_P_ECONET = 0x18 ETH_P_EDSA = 0xdada ETH_P_ERSPAN = 0x88be ETH_P_ERSPAN2 = 0x22eb + ETH_P_ETHERCAT = 0x88a4 ETH_P_FCOE = 0x8906 ETH_P_FIP = 0x8914 ETH_P_HDLC = 0x19 @@ -525,9 +1180,11 @@ const ( ETH_P_LOOPBACK = 0x9000 ETH_P_MACSEC = 0x88e5 ETH_P_MAP = 0xf9 + ETH_P_MCTP = 0xfa ETH_P_MOBITEX = 0x15 ETH_P_MPLS_MC = 0x8848 ETH_P_MPLS_UC = 0x8847 + ETH_P_MRP = 0x88e3 ETH_P_MVRP = 0x88f5 ETH_P_NCSI = 0x88f8 ETH_P_NSH = 0x894f @@ -539,6 +1196,7 @@ const ( ETH_P_PPP_MP = 0x8 ETH_P_PPP_SES = 0x8864 ETH_P_PREAUTH = 0x88c7 + ETH_P_PROFINET = 0x8892 ETH_P_PRP = 0x88fb ETH_P_PUP = 0x200 ETH_P_PUPAT = 0x201 @@ -546,6 +1204,7 @@ const ( ETH_P_QINQ2 = 0x9200 ETH_P_QINQ3 = 0x9300 ETH_P_RARP = 0x8035 + ETH_P_REALTEK = 0x8899 ETH_P_SCA = 0x6007 ETH_P_SLOW = 0x8809 ETH_P_SNAP = 0x5 @@ -559,13 +1218,40 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + ET_CORE = 0x4 + ET_DYN = 0x3 + ET_EXEC = 0x2 + ET_HIPROC = 0xffff + ET_LOPROC = 0xff00 + ET_NONE = 0x0 + ET_REL = 0x1 + EV_ABS = 0x3 + EV_CNT = 0x20 + EV_CURRENT = 0x1 + EV_FF = 0x15 + EV_FF_STATUS = 0x17 + EV_KEY = 0x1 + EV_LED = 0x11 + EV_MAX = 0x1f + EV_MSC = 0x4 + EV_NONE = 0x0 + EV_NUM = 0x2 + EV_PWR = 0x16 + EV_REL = 0x2 + EV_REP = 0x14 + EV_SND = 0x12 + EV_SW = 0x5 + EV_SYN = 0x0 + EV_VERSION = 0x10001 EXABYTE_ENABLE_NEST = 0xf0 + EXFAT_SUPER_MAGIC = 0x2011bab0 EXT2_SUPER_MAGIC = 0xef53 EXT3_SUPER_MAGIC = 0xef53 EXT4_SUPER_MAGIC = 0xef53 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 @@ -597,19 +1283,39 @@ const ( FAN_DELETE_SELF = 0x400 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 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_MNT = 0x7 + 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 + FAN_INFO = 0x20 FAN_MARK_ADD = 0x1 FAN_MARK_DONT_FOLLOW = 0x4 + FAN_MARK_EVICTABLE = 0x200 FAN_MARK_FILESYSTEM = 0x100 FAN_MARK_FLUSH = 0x80 + FAN_MARK_IGNORE = 0x400 FAN_MARK_IGNORED_MASK = 0x20 FAN_MARK_IGNORED_SURV_MODIFY = 0x40 + FAN_MARK_IGNORE_SURV = 0x440 FAN_MARK_INODE = 0x0 + FAN_MARK_MNTNS = 0x110 FAN_MARK_MOUNT = 0x10 FAN_MARK_ONLYDIR = 0x8 FAN_MARK_REMOVE = 0x2 + FAN_MNT_ATTACH = 0x1000000 + FAN_MNT_DETACH = 0x2000000 FAN_MODIFY = 0x2 FAN_MOVE = 0xc0 FAN_MOVED_FROM = 0x40 @@ -617,19 +1323,41 @@ const ( FAN_MOVE_SELF = 0x800 FAN_NOFD = -0x1 FAN_NONBLOCK = 0x2 + FAN_NOPIDFD = -0x1 FAN_ONDIR = 0x40000000 FAN_OPEN = 0x20 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_MNT = 0x4000 + FAN_REPORT_NAME = 0x800 + FAN_REPORT_PIDFD = 0x80 + FAN_REPORT_TARGET_FID = 0x1000 FAN_REPORT_TID = 0x100 + FAN_RESPONSE_INFO_AUDIT_RULE = 0x1 + FAN_RESPONSE_INFO_NONE = 0x0 FAN_UNLIMITED_MARKS = 0x20 FAN_UNLIMITED_QUEUE = 0x10 FD_CLOEXEC = 0x1 FD_SETSIZE = 0x400 FF0 = 0x0 + FIB_RULE_DEV_DETACHED = 0x8 + FIB_RULE_FIND_SADDR = 0x10000 + FIB_RULE_IIF_DETACHED = 0x8 + FIB_RULE_INVERT = 0x2 + FIB_RULE_OIF_DETACHED = 0x10 + FIB_RULE_PERMANENT = 0x1 + FIB_RULE_UNRESOLVED = 0x4 + FIDEDUPERANGE = 0xc0189436 + FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED = 0x1 FSCRYPT_KEY_DESCRIPTOR_SIZE = 0x8 FSCRYPT_KEY_DESC_PREFIX = "fscrypt:" FSCRYPT_KEY_DESC_PREFIX_SIZE = 0x8 @@ -647,14 +1375,17 @@ const ( FSCRYPT_MODE_AES_128_CBC = 0x5 FSCRYPT_MODE_AES_128_CTS = 0x6 FSCRYPT_MODE_AES_256_CTS = 0x4 + FSCRYPT_MODE_AES_256_HCTR2 = 0xa FSCRYPT_MODE_AES_256_XTS = 0x1 + FSCRYPT_MODE_SM4_CTS = 0x8 + FSCRYPT_MODE_SM4_XTS = 0x7 FSCRYPT_POLICY_FLAGS_PAD_16 = 0x2 FSCRYPT_POLICY_FLAGS_PAD_32 = 0x3 FSCRYPT_POLICY_FLAGS_PAD_4 = 0x0 FSCRYPT_POLICY_FLAGS_PAD_8 = 0x1 FSCRYPT_POLICY_FLAGS_PAD_MASK = 0x3 - FSCRYPT_POLICY_FLAGS_VALID = 0xf FSCRYPT_POLICY_FLAG_DIRECT_KEY = 0x4 + FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 = 0x10 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 = 0x8 FSCRYPT_POLICY_V1 = 0x0 FSCRYPT_POLICY_V2 = 0x2 @@ -666,11 +1397,11 @@ const ( FS_ENCRYPTION_MODE_AES_256_GCM = 0x2 FS_ENCRYPTION_MODE_AES_256_XTS = 0x1 FS_ENCRYPTION_MODE_INVALID = 0x0 - FS_ENCRYPTION_MODE_SPECK128_256_CTS = 0x8 - FS_ENCRYPTION_MODE_SPECK128_256_XTS = 0x7 FS_IOC_ADD_ENCRYPTION_KEY = 0xc0506617 FS_IOC_GET_ENCRYPTION_KEY_STATUS = 0xc080661a FS_IOC_GET_ENCRYPTION_POLICY_EX = 0xc0096616 + FS_IOC_MEASURE_VERITY = 0xc0046686 + FS_IOC_READ_VERITY_METADATA = 0xc0286687 FS_IOC_REMOVE_ENCRYPTION_KEY = 0xc0406618 FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS = 0xc0406619 FS_KEY_DESCRIPTOR_SIZE = 0x8 @@ -682,11 +1413,20 @@ const ( FS_POLICY_FLAGS_PAD_4 = 0x0 FS_POLICY_FLAGS_PAD_8 = 0x1 FS_POLICY_FLAGS_PAD_MASK = 0x3 - FS_POLICY_FLAGS_VALID = 0xf + FS_POLICY_FLAGS_VALID = 0x7 + FS_VERITY_FL = 0x100000 + FS_VERITY_HASH_ALG_SHA256 = 0x1 + FS_VERITY_HASH_ALG_SHA512 = 0x2 + FS_VERITY_METADATA_TYPE_DESCRIPTOR = 0x2 + FS_VERITY_METADATA_TYPE_MERKLE_TREE = 0x1 + FS_VERITY_METADATA_TYPE_SIGNATURE = 0x3 + 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 @@ -703,6 +1443,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 @@ -733,6 +1474,7 @@ const ( GENL_NAMSIZ = 0x10 GENL_START_ALLOC = 0x13 GENL_UNS_ADMIN_PERM = 0x10 + GRND_INSECURE = 0x4 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 HDIO_DRIVE_CMD = 0x31f @@ -775,11 +1517,11 @@ const ( HDIO_SET_XFER = 0x306 HDIO_TRISTATE_HWIF = 0x31b HDIO_UNREGISTER_HWIF = 0x32a + HID_MAX_DESCRIPTOR_SIZE = 0x1000 HOSTFS_SUPER_MAGIC = 0xc0ffee HPFS_SUPER_MAGIC = 0xf995e849 HUGETLBFS_MAGIC = 0x958458f6 IBSHIFT = 0x10 - ICMPV6_FILTER = 0x1 ICRNL = 0x100 IFA_F_DADFAILED = 0x8 IFA_F_DEPRECATED = 0x20 @@ -794,7 +1536,7 @@ const ( IFA_F_STABLE_PRIVACY = 0x800 IFA_F_TEMPORARY = 0x1 IFA_F_TENTATIVE = 0x40 - IFA_MAX = 0xa + IFA_MAX = 0xb IFF_ALLMULTI = 0x200 IFF_ATTACH_QUEUE = 0x200 IFF_AUTOMEDIA = 0x4000 @@ -814,6 +1556,7 @@ const ( IFF_NOARP = 0x80 IFF_NOFILTER = 0x1000 IFF_NOTRAILERS = 0x20 + IFF_NO_CARRIER = 0x40 IFF_NO_PI = 0x1000 IFF_ONE_QUEUE = 0x2000 IFF_PERSIST = 0x800 @@ -872,6 +1615,8 @@ const ( IN_OPEN = 0x20 IN_Q_OVERFLOW = 0x4000 IN_UNMOUNT = 0x2000 + IOCTL_MEI_CONNECT_CLIENT = 0xc0104801 + IOCTL_MEI_CONNECT_CLIENT_VTAG = 0xc0144804 IPPROTO_AH = 0x33 IPPROTO_BEETPH = 0x5e IPPROTO_COMP = 0x6c @@ -880,6 +1625,7 @@ const ( IPPROTO_EGP = 0x8 IPPROTO_ENCAP = 0x62 IPPROTO_ESP = 0x32 + IPPROTO_ETHERNET = 0x8f IPPROTO_FRAGMENT = 0x2c IPPROTO_GRE = 0x2f IPPROTO_HOPOPTS = 0x0 @@ -893,6 +1639,7 @@ const ( IPPROTO_L2TP = 0x73 IPPROTO_MH = 0x87 IPPROTO_MPLS = 0x89 + IPPROTO_MPTCP = 0x106 IPPROTO_MTP = 0x5c IPPROTO_NONE = 0x3b IPPROTO_PIM = 0x67 @@ -901,6 +1648,7 @@ const ( IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e IPPROTO_SCTP = 0x84 + IPPROTO_SMC = 0x100 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 @@ -948,6 +1696,7 @@ const ( IPV6_PMTUDISC_WANT = 0x1 IPV6_RECVDSTOPTS = 0x3a IPV6_RECVERR = 0x19 + IPV6_RECVERR_RFC4884 = 0x1f IPV6_RECVFRAGSIZE = 0x4d IPV6_RECVHOPLIMIT = 0x33 IPV6_RECVHOPOPTS = 0x35 @@ -970,6 +1719,8 @@ const ( IPV6_UNICAST_HOPS = 0x10 IPV6_UNICAST_IF = 0x4c IPV6_V6ONLY = 0x1a + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 IPV6_XFRM_POLICY = 0x23 IP_ADD_MEMBERSHIP = 0x23 IP_ADD_SOURCE_MEMBERSHIP = 0x27 @@ -984,6 +1735,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 @@ -1010,7 +1762,9 @@ 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 IP_RECVOPTS = 0x6 IP_RECVORIGDSTADDR = 0x14 @@ -1028,30 +1782,40 @@ const ( IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IUTF8 = 0x4000 IXANY = 0x800 JFFS2_SUPER_MAGIC = 0x72b6 + KCMPROTO_CONNECTED = 0x0 + KCM_RECV_DISABLE = 0x1 KEXEC_ARCH_386 = 0x30000 KEXEC_ARCH_68K = 0x40000 KEXEC_ARCH_AARCH64 = 0xb70000 KEXEC_ARCH_ARM = 0x280000 KEXEC_ARCH_DEFAULT = 0x0 KEXEC_ARCH_IA_64 = 0x320000 + KEXEC_ARCH_LOONGARCH = 0x1020000 KEXEC_ARCH_MASK = 0xffff0000 KEXEC_ARCH_MIPS = 0x80000 KEXEC_ARCH_MIPS_LE = 0xa0000 KEXEC_ARCH_PARISC = 0xf0000 KEXEC_ARCH_PPC = 0x140000 KEXEC_ARCH_PPC64 = 0x150000 + KEXEC_ARCH_RISCV = 0xf30000 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 KEXEC_ON_CRASH = 0x1 KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 + KEXEC_UPDATE_ELFCOREHDR = 0x4 KEYCTL_ASSUME_AUTHORITY = 0x10 KEYCTL_CAPABILITIES = 0x1f KEYCTL_CAPS0_BIG_KEY = 0x10 @@ -1062,6 +1826,7 @@ const ( KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2 KEYCTL_CAPS0_PUBLIC_KEY = 0x8 KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40 + KEYCTL_CAPS1_NOTIFICATIONS = 0x4 KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1 KEYCTL_CAPS1_NS_KEY_TAG = 0x2 KEYCTL_CHOWN = 0x4 @@ -1099,6 +1864,7 @@ const ( KEYCTL_SUPPORTS_VERIFY = 0x8 KEYCTL_UNLINK = 0x9 KEYCTL_UPDATE = 0x2 + KEYCTL_WATCH_KEY = 0x20 KEY_REQKEY_DEFL_DEFAULT = 0x0 KEY_REQKEY_DEFL_GROUP_KEYRING = 0x6 KEY_REQKEY_DEFL_NO_CHANGE = -0x1 @@ -1116,6 +1882,31 @@ const ( KEY_SPEC_THREAD_KEYRING = -0x1 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 + LANDLOCK_ACCESS_FS_MAKE_FIFO = 0x400 + LANDLOCK_ACCESS_FS_MAKE_REG = 0x100 + LANDLOCK_ACCESS_FS_MAKE_SOCK = 0x200 + LANDLOCK_ACCESS_FS_MAKE_SYM = 0x1000 + LANDLOCK_ACCESS_FS_READ_DIR = 0x8 + LANDLOCK_ACCESS_FS_READ_FILE = 0x4 + LANDLOCK_ACCESS_FS_REFER = 0x2000 + LANDLOCK_ACCESS_FS_REMOVE_DIR = 0x10 + LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20 + LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000 + LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 + LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 + LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 + LANDLOCK_CREATE_RULESET_ERRATA = 0x2 + LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 + LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 + 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 @@ -1131,6 +1922,7 @@ const ( LOCK_SH = 0x1 LOCK_UN = 0x8 LOOP_CLR_FD = 0x4c01 + LOOP_CONFIGURE = 0x4c0a LOOP_CTL_ADD = 0x4c80 LOOP_CTL_GET_FREE = 0x4c82 LOOP_CTL_REMOVE = 0x4c81 @@ -1142,14 +1934,24 @@ const ( LOOP_SET_FD = 0x4c00 LOOP_SET_STATUS = 0x4c02 LOOP_SET_STATUS64 = 0x4c04 + LOOP_SET_STATUS_CLEARABLE_FLAGS = 0x4 + LOOP_SET_STATUS_SETTABLE_FLAGS = 0xc LO_KEY_SIZE = 0x20 LO_NAME_SIZE = 0x40 + LWTUNNEL_IP6_MAX = 0x8 + LWTUNNEL_IP_MAX = 0x8 + LWTUNNEL_IP_OPTS_MAX = 0x3 + LWTUNNEL_IP_OPT_ERSPAN_MAX = 0x4 + LWTUNNEL_IP_OPT_GENEVE_MAX = 0x3 + LWTUNNEL_IP_OPT_VXLAN_MAX = 0x1 MADV_COLD = 0x14 + MADV_COLLAPSE = 0x19 MADV_DODUMP = 0x11 MADV_DOFORK = 0xb MADV_DONTDUMP = 0x10 MADV_DONTFORK = 0xa MADV_DONTNEED = 0x4 + MADV_DONTNEED_LOCKED = 0x18 MADV_FREE = 0x8 MADV_HUGEPAGE = 0xe MADV_HWPOISON = 0x64 @@ -1158,15 +1960,31 @@ const ( MADV_NOHUGEPAGE = 0xf MADV_NORMAL = 0x0 MADV_PAGEOUT = 0x15 + MADV_POPULATE_READ = 0x16 + MADV_POPULATE_WRITE = 0x17 MADV_RANDOM = 0x1 MADV_REMOVE = 0x9 MADV_SEQUENTIAL = 0x2 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 @@ -1182,10 +2000,15 @@ const ( MCAST_LEAVE_SOURCE_GROUP = 0x2f MCAST_MSFILTER = 0x30 MCAST_UNBLOCK_SOURCE = 0x2c + MEMGETREGIONINFO = 0xc0104d08 + MEMREADOOB64 = 0xc0184d16 + MEMWRITE = 0xc0304d18 + MEMWRITEOOB64 = 0xc0184d15 MFD_ALLOW_SEALING = 0x2 MFD_CLOEXEC = 0x1 + MFD_EXEC = 0x10 MFD_HUGETLB = 0x4 - MFD_HUGE_16GB = -0x78000000 + MFD_HUGE_16GB = 0x88000000 MFD_HUGE_16MB = 0x60000000 MFD_HUGE_1GB = 0x78000000 MFD_HUGE_1MB = 0x50000000 @@ -1199,6 +2022,7 @@ const ( MFD_HUGE_8MB = 0x5c000000 MFD_HUGE_MASK = 0x3f MFD_HUGE_SHIFT = 0x1a + MFD_NOEXEC_SEAL = 0x8 MINIX2_SUPER_MAGIC = 0x2468 MINIX2_SUPER_MAGIC2 = 0x2478 MINIX3_SUPER_MAGIC = 0x4d5a @@ -1207,8 +2031,27 @@ 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 + MOUNT_ATTR_IDMAP = 0x100000 + MOUNT_ATTR_NOATIME = 0x10 + MOUNT_ATTR_NODEV = 0x4 + MOUNT_ATTR_NODIRATIME = 0x80 + MOUNT_ATTR_NOEXEC = 0x8 + MOUNT_ATTR_NOSUID = 0x2 + MOUNT_ATTR_NOSYMFOLLOW = 0x200000 + MOUNT_ATTR_RDONLY = 0x1 + MOUNT_ATTR_RELATIME = 0x0 + MOUNT_ATTR_SIZE_VER0 = 0x20 + MOUNT_ATTR_STRICTATIME = 0x20 + MOUNT_ATTR__ATIME = 0x70 + MREMAP_DONTUNMAP = 0x4 + MREMAP_FIXED = 0x2 + MREMAP_MAYMOVE = 0x1 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 @@ -1226,6 +2069,7 @@ const ( MSG_PEEK = 0x2 MSG_PROXY = 0x10 MSG_RST = 0x1000 + MSG_SOCK_DEVMEM = 0x2000000 MSG_SYN = 0x400 MSG_TRUNC = 0x20 MSG_TRYHARD = 0x4 @@ -1252,6 +2096,7 @@ const ( MS_NOREMOTELOCK = 0x8000000 MS_NOSEC = 0x10000000 MS_NOSUID = 0x2 + MS_NOSYMFOLLOW = 0x100 MS_NOUSER = -0x80000000 MS_POSIXACL = 0x10000 MS_PRIVATE = 0x40000 @@ -1269,7 +2114,35 @@ const ( MS_SYNCHRONOUS = 0x10 MS_UNBINDABLE = 0x20000 MS_VERBOSE = 0x8000 + MTD_ABSENT = 0x0 + MTD_BIT_WRITEABLE = 0x800 + MTD_CAP_NANDFLASH = 0x400 + MTD_CAP_NORFLASH = 0xc00 + MTD_CAP_NVRAM = 0x1c00 + MTD_CAP_RAM = 0x1c00 + MTD_CAP_ROM = 0x0 + MTD_DATAFLASH = 0x6 MTD_INODE_FS_MAGIC = 0x11307854 + MTD_MAX_ECCPOS_ENTRIES = 0x40 + MTD_MAX_OOBFREE_ENTRIES = 0x8 + MTD_MLCNANDFLASH = 0x8 + MTD_NANDECC_AUTOPLACE = 0x2 + MTD_NANDECC_AUTOPL_USR = 0x4 + MTD_NANDECC_OFF = 0x0 + MTD_NANDECC_PLACE = 0x1 + MTD_NANDECC_PLACEONLY = 0x3 + MTD_NANDFLASH = 0x4 + MTD_NORFLASH = 0x3 + MTD_NO_ERASE = 0x1000 + MTD_OTP_FACTORY = 0x1 + MTD_OTP_OFF = 0x0 + MTD_OTP_USER = 0x2 + MTD_POWERUP_LOCK = 0x2000 + MTD_RAM = 0x1 + MTD_ROM = 0x2 + MTD_SLC_ON_MLC_EMULATION = 0x4000 + MTD_UBIVOLUME = 0x7 + MTD_WRITEABLE = 0x400 NAME_MAX = 0xff NCP_SUPER_MAGIC = 0x564c NETLINK_ADD_MEMBERSHIP = 0x1 @@ -1309,6 +2182,60 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFC_ATR_REQ_GB_MAXSIZE = 0x30 + 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 + NFC_DIRECTION_RX = 0x0 + NFC_DIRECTION_TX = 0x1 + NFC_FIRMWARE_NAME_MAXSIZE = 0x20 + NFC_GB_MAXSIZE = 0x30 + NFC_GENL_MCAST_EVENT_NAME = "events" + NFC_GENL_NAME = "nfc" + NFC_GENL_VERSION = 0x1 + NFC_HEADER_SIZE = 0x1 + NFC_ISO15693_UID_MAXSIZE = 0x8 + NFC_LLCP_MAX_SERVICE_NAME = 0x3f + NFC_LLCP_MIUX = 0x1 + NFC_LLCP_REMOTE_LTO = 0x3 + NFC_LLCP_REMOTE_MIU = 0x2 + NFC_LLCP_REMOTE_RW = 0x4 + NFC_LLCP_RW = 0x0 + NFC_NFCID1_MAXSIZE = 0xa + NFC_NFCID2_MAXSIZE = 0x8 + NFC_NFCID3_MAXSIZE = 0xa + NFC_PROTO_FELICA = 0x3 + NFC_PROTO_FELICA_MASK = 0x8 + NFC_PROTO_ISO14443 = 0x4 + NFC_PROTO_ISO14443_B = 0x6 + NFC_PROTO_ISO14443_B_MASK = 0x40 + NFC_PROTO_ISO14443_MASK = 0x10 + NFC_PROTO_ISO15693 = 0x7 + NFC_PROTO_ISO15693_MASK = 0x80 + NFC_PROTO_JEWEL = 0x1 + NFC_PROTO_JEWEL_MASK = 0x2 + NFC_PROTO_MAX = 0x8 + NFC_PROTO_MIFARE = 0x2 + NFC_PROTO_MIFARE_MASK = 0x4 + NFC_PROTO_NFC_DEP = 0x5 + NFC_PROTO_NFC_DEP_MASK = 0x20 + NFC_RAW_HEADER_SIZE = 0x2 + NFC_RF_INITIATOR = 0x0 + NFC_RF_NONE = 0x2 + NFC_RF_TARGET = 0x1 + NFC_SENSB_RES_MAXSIZE = 0xc + NFC_SENSF_RES_MAXSIZE = 0x12 + NFC_SE_DISABLED = 0x0 + NFC_SE_EMBEDDED = 0x2 + NFC_SE_ENABLED = 0x1 + NFC_SE_UICC = 0x1 + NFC_SOCKPROTO_LLCP = 0x1 + NFC_SOCKPROTO_MAX = 0x2 + NFC_SOCKPROTO_RAW = 0x0 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1326,11 +2253,12 @@ const ( NFNL_MSG_BATCH_END = 0x11 NFNL_NFA_NEST = 0x8000 NFNL_SUBSYS_ACCT = 0x7 - NFNL_SUBSYS_COUNT = 0xc + NFNL_SUBSYS_COUNT = 0xd NFNL_SUBSYS_CTHELPER = 0x9 NFNL_SUBSYS_CTNETLINK = 0x1 NFNL_SUBSYS_CTNETLINK_EXP = 0x2 NFNL_SUBSYS_CTNETLINK_TIMEOUT = 0x8 + NFNL_SUBSYS_HOOK = 0xc NFNL_SUBSYS_IPSET = 0x6 NFNL_SUBSYS_NFTABLES = 0xa NFNL_SUBSYS_NFT_COMPAT = 0xb @@ -1339,6 +2267,61 @@ 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 + NFT_DATA_RESERVED_MASK = 0xffffff00 + NFT_DATA_VALUE_MAXLEN = 0x40 + NFT_EXTHDR_OP_MAX = 0x4 + NFT_FIB_RESULT_MAX = 0x3 + NFT_INNER_MASK = 0xf + NFT_LOGLEVEL_MAX = 0x8 + NFT_NAME_MAXLEN = 0x100 + NFT_NG_MAX = 0x1 + NFT_OBJECT_CONNLIMIT = 0x5 + NFT_OBJECT_COUNTER = 0x1 + NFT_OBJECT_CT_EXPECT = 0x9 + NFT_OBJECT_CT_HELPER = 0x3 + NFT_OBJECT_CT_TIMEOUT = 0x7 + NFT_OBJECT_LIMIT = 0x4 + NFT_OBJECT_MAX = 0xa + NFT_OBJECT_QUOTA = 0x2 + NFT_OBJECT_SECMARK = 0x8 + NFT_OBJECT_SYNPROXY = 0xa + NFT_OBJECT_TUNNEL = 0x6 + NFT_OBJECT_UNSPEC = 0x0 + NFT_OBJ_MAXNAMELEN = 0x100 + NFT_OSF_MAXGENRELEN = 0x10 + NFT_QUEUE_FLAG_BYPASS = 0x1 + NFT_QUEUE_FLAG_CPU_FANOUT = 0x2 + NFT_QUEUE_FLAG_MASK = 0x3 + NFT_REG32_COUNT = 0x10 + NFT_REG32_SIZE = 0x4 + NFT_REG_MAX = 0x4 + NFT_REG_SIZE = 0x10 + NFT_REJECT_ICMPX_MAX = 0x3 + NFT_RT_MAX = 0x4 + NFT_SECMARK_CTX_MAXLEN = 0x1000 + NFT_SET_MAXNAMELEN = 0x100 + NFT_SOCKET_MAX = 0x3 + NFT_TABLE_F_MASK = 0x7 + NFT_TABLE_MAXNAMELEN = 0x100 + NFT_TRACETYPE_MAX = 0x3 + NFT_TUNNEL_F_MASK = 0x7 + NFT_TUNNEL_MAX = 0x1 + NFT_TUNNEL_MODE_MAX = 0x2 + NFT_USERDATA_MAXLEN = 0x100 + NFT_XFRM_KEY_MAX = 0x6 + NF_NAT_RANGE_MAP_IPS = 0x1 + NF_NAT_RANGE_MASK = 0x7f + NF_NAT_RANGE_NETMAP = 0x40 + NF_NAT_RANGE_PERSISTENT = 0x8 + NF_NAT_RANGE_PROTO_OFFSET = 0x20 + NF_NAT_RANGE_PROTO_RANDOM = 0x4 + NF_NAT_RANGE_PROTO_RANDOM_ALL = 0x14 + NF_NAT_RANGE_PROTO_RANDOM_FULLY = 0x10 + NF_NAT_RANGE_PROTO_SPECIFIED = 0x2 NILFS_SUPER_MAGIC = 0x3434 NL0 = 0x0 NL1 = 0x100 @@ -1357,6 +2340,7 @@ const ( NLM_F_ACK_TLVS = 0x200 NLM_F_APPEND = 0x800 NLM_F_ATOMIC = 0x400 + NLM_F_BULK = 0x200 NLM_F_CAPPED = 0x100 NLM_F_CREATE = 0x400 NLM_F_DUMP = 0x300 @@ -1370,7 +2354,167 @@ const ( NLM_F_REPLACE = 0x100 NLM_F_REQUEST = 0x1 NLM_F_ROOT = 0x100 + NN_386_IOPERM = "LINUX" + NN_386_TLS = "LINUX" + NN_ARC_V2 = "LINUX" + NN_ARM_FPMR = "LINUX" + NN_ARM_GCS = "LINUX" + NN_ARM_HW_BREAK = "LINUX" + NN_ARM_HW_WATCH = "LINUX" + NN_ARM_PACA_KEYS = "LINUX" + NN_ARM_PACG_KEYS = "LINUX" + NN_ARM_PAC_ENABLED_KEYS = "LINUX" + NN_ARM_PAC_MASK = "LINUX" + NN_ARM_POE = "LINUX" + NN_ARM_SSVE = "LINUX" + NN_ARM_SVE = "LINUX" + NN_ARM_SYSTEM_CALL = "LINUX" + NN_ARM_TAGGED_ADDR_CTRL = "LINUX" + NN_ARM_TLS = "LINUX" + NN_ARM_VFP = "LINUX" + NN_ARM_ZA = "LINUX" + NN_ARM_ZT = "LINUX" + NN_AUXV = "CORE" + NN_FILE = "CORE" + NN_GNU_PROPERTY_TYPE_0 = "GNU" + NN_LOONGARCH_CPUCFG = "LINUX" + NN_LOONGARCH_CSR = "LINUX" + NN_LOONGARCH_HW_BREAK = "LINUX" + NN_LOONGARCH_HW_WATCH = "LINUX" + NN_LOONGARCH_LASX = "LINUX" + NN_LOONGARCH_LBT = "LINUX" + NN_LOONGARCH_LSX = "LINUX" + NN_MIPS_DSP = "LINUX" + NN_MIPS_FP_MODE = "LINUX" + NN_MIPS_MSA = "LINUX" + NN_PPC_DEXCR = "LINUX" + NN_PPC_DSCR = "LINUX" + NN_PPC_EBB = "LINUX" + NN_PPC_HASHKEYR = "LINUX" + NN_PPC_PKEY = "LINUX" + NN_PPC_PMU = "LINUX" + NN_PPC_PPR = "LINUX" + NN_PPC_SPE = "LINUX" + NN_PPC_TAR = "LINUX" + NN_PPC_TM_CDSCR = "LINUX" + NN_PPC_TM_CFPR = "LINUX" + NN_PPC_TM_CGPR = "LINUX" + NN_PPC_TM_CPPR = "LINUX" + NN_PPC_TM_CTAR = "LINUX" + NN_PPC_TM_CVMX = "LINUX" + NN_PPC_TM_CVSX = "LINUX" + NN_PPC_TM_SPR = "LINUX" + NN_PPC_VMX = "LINUX" + NN_PPC_VSX = "LINUX" + NN_PRFPREG = "CORE" + NN_PRPSINFO = "CORE" + NN_PRSTATUS = "CORE" + NN_PRXFPREG = "LINUX" + NN_RISCV_CSR = "LINUX" + NN_RISCV_TAGGED_ADDR_CTRL = "LINUX" + NN_RISCV_VECTOR = "LINUX" + NN_S390_CTRS = "LINUX" + NN_S390_GS_BC = "LINUX" + NN_S390_GS_CB = "LINUX" + NN_S390_HIGH_GPRS = "LINUX" + NN_S390_LAST_BREAK = "LINUX" + NN_S390_PREFIX = "LINUX" + NN_S390_PV_CPU_DATA = "LINUX" + NN_S390_RI_CB = "LINUX" + NN_S390_SYSTEM_CALL = "LINUX" + NN_S390_TDB = "LINUX" + NN_S390_TIMER = "LINUX" + NN_S390_TODCMP = "LINUX" + NN_S390_TODPREG = "LINUX" + NN_S390_VXRS_HIGH = "LINUX" + NN_S390_VXRS_LOW = "LINUX" + NN_SIGINFO = "CORE" + NN_TASKSTRUCT = "CORE" + NN_VMCOREDD = "LINUX" + NN_X86_SHSTK = "LINUX" + NN_X86_XSAVE_LAYOUT = "LINUX" + NN_X86_XSTATE = "LINUX" NSFS_MAGIC = 0x6e736673 + NT_386_IOPERM = 0x201 + NT_386_TLS = 0x200 + NT_ARC_V2 = 0x600 + NT_ARM_FPMR = 0x40e + NT_ARM_GCS = 0x410 + NT_ARM_HW_BREAK = 0x402 + NT_ARM_HW_WATCH = 0x403 + NT_ARM_PACA_KEYS = 0x407 + NT_ARM_PACG_KEYS = 0x408 + NT_ARM_PAC_ENABLED_KEYS = 0x40a + NT_ARM_PAC_MASK = 0x406 + NT_ARM_POE = 0x40f + NT_ARM_SSVE = 0x40b + NT_ARM_SVE = 0x405 + NT_ARM_SYSTEM_CALL = 0x404 + NT_ARM_TAGGED_ADDR_CTRL = 0x409 + NT_ARM_TLS = 0x401 + NT_ARM_VFP = 0x400 + NT_ARM_ZA = 0x40c + NT_ARM_ZT = 0x40d + NT_AUXV = 0x6 + NT_FILE = 0x46494c45 + NT_GNU_PROPERTY_TYPE_0 = 0x5 + NT_LOONGARCH_CPUCFG = 0xa00 + NT_LOONGARCH_CSR = 0xa01 + NT_LOONGARCH_HW_BREAK = 0xa05 + NT_LOONGARCH_HW_WATCH = 0xa06 + NT_LOONGARCH_LASX = 0xa03 + NT_LOONGARCH_LBT = 0xa04 + NT_LOONGARCH_LSX = 0xa02 + NT_MIPS_DSP = 0x800 + NT_MIPS_FP_MODE = 0x801 + NT_MIPS_MSA = 0x802 + NT_PPC_DEXCR = 0x111 + NT_PPC_DSCR = 0x105 + NT_PPC_EBB = 0x106 + NT_PPC_HASHKEYR = 0x112 + NT_PPC_PKEY = 0x110 + NT_PPC_PMU = 0x107 + NT_PPC_PPR = 0x104 + NT_PPC_SPE = 0x101 + NT_PPC_TAR = 0x103 + NT_PPC_TM_CDSCR = 0x10f + NT_PPC_TM_CFPR = 0x109 + NT_PPC_TM_CGPR = 0x108 + NT_PPC_TM_CPPR = 0x10e + NT_PPC_TM_CTAR = 0x10d + NT_PPC_TM_CVMX = 0x10a + NT_PPC_TM_CVSX = 0x10b + NT_PPC_TM_SPR = 0x10c + NT_PPC_VMX = 0x100 + NT_PPC_VSX = 0x102 + NT_PRFPREG = 0x2 + NT_PRPSINFO = 0x3 + NT_PRSTATUS = 0x1 + NT_PRXFPREG = 0x46e62b7f + NT_RISCV_CSR = 0x900 + NT_RISCV_TAGGED_ADDR_CTRL = 0x902 + NT_RISCV_VECTOR = 0x901 + NT_S390_CTRS = 0x304 + NT_S390_GS_BC = 0x30c + NT_S390_GS_CB = 0x30b + NT_S390_HIGH_GPRS = 0x300 + NT_S390_LAST_BREAK = 0x306 + NT_S390_PREFIX = 0x305 + NT_S390_PV_CPU_DATA = 0x30e + NT_S390_RI_CB = 0x30d + NT_S390_SYSTEM_CALL = 0x307 + NT_S390_TDB = 0x308 + NT_S390_TIMER = 0x301 + NT_S390_TODCMP = 0x302 + NT_S390_TODPREG = 0x303 + NT_S390_VXRS_HIGH = 0x30a + NT_S390_VXRS_LOW = 0x309 + NT_SIGINFO = 0x53494749 + NT_TASKSTRUCT = 0x4 + NT_VMCOREDD = 0x700 + NT_X86_SHSTK = 0x204 + NT_X86_XSAVE_LAYOUT = 0x205 + NT_X86_XSTATE = 0x202 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -1395,6 +2539,7 @@ const ( PACKET_FANOUT_DATA = 0x16 PACKET_FANOUT_EBPF = 0x7 PACKET_FANOUT_FLAG_DEFRAG = 0x8000 + PACKET_FANOUT_FLAG_IGNORE_OUTGOING = 0x4000 PACKET_FANOUT_FLAG_ROLLOVER = 0x1000 PACKET_FANOUT_FLAG_UNIQUEID = 0x2000 PACKET_FANOUT_HASH = 0x0 @@ -1430,6 +2575,7 @@ const ( PACKET_USER = 0x6 PACKET_VERSION = 0xa PACKET_VNET_HDR = 0xf + PACKET_VNET_HDR_SZ = 0x18 PARITY_CRC16_PR0 = 0x2 PARITY_CRC16_PR0_CCITT = 0x4 PARITY_CRC16_PR1 = 0x3 @@ -1439,13 +2585,183 @@ const ( PARITY_DEFAULT = 0x0 PARITY_NONE = 0x1 PARMRK = 0x8 + PERF_ATTR_SIZE_VER0 = 0x40 + PERF_ATTR_SIZE_VER1 = 0x48 + PERF_ATTR_SIZE_VER2 = 0x50 + PERF_ATTR_SIZE_VER3 = 0x60 + PERF_ATTR_SIZE_VER4 = 0x68 + PERF_ATTR_SIZE_VER5 = 0x70 + PERF_ATTR_SIZE_VER6 = 0x78 + PERF_ATTR_SIZE_VER7 = 0x80 + PERF_ATTR_SIZE_VER8 = 0x88 + PERF_AUX_FLAG_COLLISION = 0x8 + PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT = 0x0 + PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW = 0x100 + PERF_AUX_FLAG_OVERWRITE = 0x2 + 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 + PERF_BR_ARM64_DEBUG_INST = 0x6 + PERF_BR_ARM64_FIQ = 0x3 + PERF_FLAG_FD_CLOEXEC = 0x8 + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 + PERF_HW_EVENT_MASK = 0xffffffff + PERF_MAX_CONTEXTS_PER_STACK = 0x8 + PERF_MAX_STACK_DEPTH = 0x7f + PERF_MEM_BLK_ADDR = 0x4 + PERF_MEM_BLK_DATA = 0x2 + PERF_MEM_BLK_NA = 0x1 + PERF_MEM_BLK_SHIFT = 0x28 + PERF_MEM_HOPS_0 = 0x1 + PERF_MEM_HOPS_1 = 0x2 + PERF_MEM_HOPS_2 = 0x3 + PERF_MEM_HOPS_3 = 0x4 + PERF_MEM_HOPS_SHIFT = 0x2b + PERF_MEM_LOCK_LOCKED = 0x2 + PERF_MEM_LOCK_NA = 0x1 + PERF_MEM_LOCK_SHIFT = 0x18 + PERF_MEM_LVLNUM_ANY_CACHE = 0xb + PERF_MEM_LVLNUM_CXL = 0x9 + 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 + PERF_MEM_LVLNUM_SHIFT = 0x21 + PERF_MEM_LVLNUM_UNC = 0x8 + PERF_MEM_LVL_HIT = 0x2 + PERF_MEM_LVL_IO = 0x1000 + PERF_MEM_LVL_L1 = 0x8 + PERF_MEM_LVL_L2 = 0x20 + PERF_MEM_LVL_L3 = 0x40 + PERF_MEM_LVL_LFB = 0x10 + PERF_MEM_LVL_LOC_RAM = 0x80 + PERF_MEM_LVL_MISS = 0x4 + PERF_MEM_LVL_NA = 0x1 + PERF_MEM_LVL_REM_CCE1 = 0x400 + PERF_MEM_LVL_REM_CCE2 = 0x800 + PERF_MEM_LVL_REM_RAM1 = 0x100 + PERF_MEM_LVL_REM_RAM2 = 0x200 + PERF_MEM_LVL_SHIFT = 0x5 + PERF_MEM_LVL_UNC = 0x2000 + PERF_MEM_OP_EXEC = 0x10 + PERF_MEM_OP_LOAD = 0x2 + PERF_MEM_OP_NA = 0x1 + PERF_MEM_OP_PFETCH = 0x8 + PERF_MEM_OP_SHIFT = 0x0 + PERF_MEM_OP_STORE = 0x4 + PERF_MEM_REMOTE_REMOTE = 0x1 + PERF_MEM_REMOTE_SHIFT = 0x25 + PERF_MEM_SNOOPX_FWD = 0x1 + PERF_MEM_SNOOPX_PEER = 0x2 + PERF_MEM_SNOOPX_SHIFT = 0x26 + PERF_MEM_SNOOP_HIT = 0x4 + PERF_MEM_SNOOP_HITM = 0x10 + PERF_MEM_SNOOP_MISS = 0x8 + PERF_MEM_SNOOP_NA = 0x1 + PERF_MEM_SNOOP_NONE = 0x2 + PERF_MEM_SNOOP_SHIFT = 0x13 + PERF_MEM_TLB_HIT = 0x2 + PERF_MEM_TLB_L1 = 0x8 + PERF_MEM_TLB_L2 = 0x10 + PERF_MEM_TLB_MISS = 0x4 + PERF_MEM_TLB_NA = 0x1 + PERF_MEM_TLB_OS = 0x40 + PERF_MEM_TLB_SHIFT = 0x1a + PERF_MEM_TLB_WK = 0x20 + PERF_PMU_TYPE_SHIFT = 0x20 + PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER = 0x1 + PERF_RECORD_MISC_COMM_EXEC = 0x2000 + PERF_RECORD_MISC_CPUMODE_MASK = 0x7 + PERF_RECORD_MISC_CPUMODE_UNKNOWN = 0x0 + PERF_RECORD_MISC_EXACT_IP = 0x4000 + PERF_RECORD_MISC_EXT_RESERVED = 0x8000 + PERF_RECORD_MISC_FORK_EXEC = 0x2000 + PERF_RECORD_MISC_GUEST_KERNEL = 0x4 + PERF_RECORD_MISC_GUEST_USER = 0x5 + PERF_RECORD_MISC_HYPERVISOR = 0x3 + PERF_RECORD_MISC_KERNEL = 0x1 + PERF_RECORD_MISC_MMAP_BUILD_ID = 0x4000 + PERF_RECORD_MISC_MMAP_DATA = 0x2000 + PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT = 0x1000 + PERF_RECORD_MISC_SWITCH_OUT = 0x2000 + PERF_RECORD_MISC_SWITCH_OUT_PREEMPT = 0x4000 + PERF_RECORD_MISC_USER = 0x2 + PERF_SAMPLE_BRANCH_PLM_ALL = 0x7 + PERF_SAMPLE_WEIGHT_TYPE = 0x1004000 + PF_ALG = 0x26 + PF_APPLETALK = 0x5 + PF_ASH = 0x12 + PF_ATMPVC = 0x8 + PF_ATMSVC = 0x14 + PF_AX25 = 0x3 + PF_BLUETOOTH = 0x1f + PF_BRIDGE = 0x7 + PF_CAIF = 0x25 + PF_CAN = 0x1d + PF_DECnet = 0xc + PF_ECONET = 0x13 + PF_FILE = 0x1 + PF_IB = 0x1b + PF_IEEE802154 = 0x24 + PF_INET = 0x2 + PF_INET6 = 0xa + PF_IPX = 0x4 + PF_IRDA = 0x17 + PF_ISDN = 0x22 + PF_IUCV = 0x20 + PF_KCM = 0x29 + PF_KEY = 0xf + PF_LLC = 0x1a + PF_LOCAL = 0x1 + PF_MAX = 0x2e + PF_MCTP = 0x2d + PF_MPLS = 0x1c + PF_NETBEUI = 0xd + PF_NETLINK = 0x10 + PF_NETROM = 0x6 + PF_NFC = 0x27 + PF_PACKET = 0x11 + PF_PHONET = 0x23 + PF_PPPOX = 0x18 + PF_QIPCRTR = 0x2a + PF_R = 0x4 + PF_RDS = 0x15 + PF_ROSE = 0xb + PF_ROUTE = 0x10 + PF_RXRPC = 0x21 + PF_SECURITY = 0xe + PF_SMC = 0x2b + PF_SNA = 0x16 + PF_TIPC = 0x1e + PF_UNIX = 0x1 + PF_UNSPEC = 0x0 + PF_VSOCK = 0x28 + PF_W = 0x2 + PF_WANPIPE = 0x19 + PF_X = 0x1 + PF_X25 = 0x9 + PF_XDP = 0x2c + PID_FS_MAGIC = 0x50494446 PIPEFS_MAGIC = 0x50495045 - PPC_CMM_MAGIC = 0xc7571590 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 @@ -1477,18 +2793,27 @@ const ( PR_FP_EXC_UND = 0x40000 PR_FP_MODE_FR = 0x1 PR_FP_MODE_FRE = 0x2 + PR_FUTEX_HASH = 0x4e + PR_FUTEX_HASH_GET_IMMUTABLE = 0x3 + PR_FUTEX_HASH_GET_SLOTS = 0x2 + PR_FUTEX_HASH_SET_SLOTS = 0x1 + PR_GET_AUXV = 0x41555856 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 PR_GET_ENDIAN = 0x13 PR_GET_FPEMU = 0x9 PR_GET_FPEXC = 0xb PR_GET_FP_MODE = 0x2e + PR_GET_IO_FLUSHER = 0x3a PR_GET_KEEPCAPS = 0x7 + PR_GET_MDWE = 0x42 + PR_GET_MEMORY_MERGE = 0x44 PR_GET_NAME = 0x10 PR_GET_NO_NEW_PRIVS = 0x27 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 @@ -1497,6 +2822,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 @@ -1504,21 +2830,72 @@ const ( PR_MCE_KILL_GET = 0x22 PR_MCE_KILL_LATE = 0x0 PR_MCE_KILL_SET = 0x1 + PR_MDWE_NO_INHERIT = 0x2 + PR_MDWE_REFUSE_EXEC_GAIN = 0x1 PR_MPX_DISABLE_MANAGEMENT = 0x2c PR_MPX_ENABLE_MANAGEMENT = 0x2b + PR_MTE_TAG_MASK = 0x7fff8 + PR_MTE_TAG_SHIFT = 0x3 + PR_MTE_TCF_ASYNC = 0x4 + PR_MTE_TCF_MASK = 0x6 + PR_MTE_TCF_NONE = 0x0 + PR_MTE_TCF_SHIFT = 0x1 + PR_MTE_TCF_SYNC = 0x2 PR_PAC_APDAKEY = 0x4 PR_PAC_APDBKEY = 0x8 PR_PAC_APGAKEY = 0x10 PR_PAC_APIAKEY = 0x1 PR_PAC_APIBKEY = 0x2 + 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 + PR_RISCV_V_VSTATE_CTRL_DEFAULT = 0x0 + PR_RISCV_V_VSTATE_CTRL_INHERIT = 0x10 + PR_RISCV_V_VSTATE_CTRL_MASK = 0x1f + PR_RISCV_V_VSTATE_CTRL_NEXT_MASK = 0xc + PR_RISCV_V_VSTATE_CTRL_OFF = 0x1 + PR_RISCV_V_VSTATE_CTRL_ON = 0x2 + PR_SCHED_CORE = 0x3e + PR_SCHED_CORE_CREATE = 0x1 + PR_SCHED_CORE_GET = 0x0 + PR_SCHED_CORE_MAX = 0x4 + PR_SCHED_CORE_SCOPE_PROCESS_GROUP = 0x2 + PR_SCHED_CORE_SCOPE_THREAD = 0x0 + PR_SCHED_CORE_SCOPE_THREAD_GROUP = 0x1 + PR_SCHED_CORE_SHARE_FROM = 0x3 + PR_SCHED_CORE_SHARE_TO = 0x2 PR_SET_CHILD_SUBREAPER = 0x24 PR_SET_DUMPABLE = 0x4 PR_SET_ENDIAN = 0x14 PR_SET_FPEMU = 0xa PR_SET_FPEXC = 0xc PR_SET_FP_MODE = 0x2d + PR_SET_IO_FLUSHER = 0x39 PR_SET_KEEPCAPS = 0x8 + PR_SET_MDWE = 0x41 + PR_SET_MEMORY_MERGE = 0x43 PR_SET_MM = 0x23 PR_SET_MM_ARG_END = 0x9 PR_SET_MM_ARG_START = 0x8 @@ -1541,18 +2918,31 @@ 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 PR_SET_THP_DISABLE = 0x29 PR_SET_TIMERSLACK = 0x1d PR_SET_TIMING = 0xe PR_SET_TSC = 0x1a 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 + PR_SME_VL_INHERIT = 0x20000 + PR_SME_VL_LEN_MASK = 0xffff PR_SPEC_DISABLE = 0x4 PR_SPEC_DISABLE_NOEXEC = 0x10 PR_SPEC_ENABLE = 0x2 PR_SPEC_FORCE_DISABLE = 0x8 PR_SPEC_INDIRECT_BRANCH = 0x1 + PR_SPEC_L1D_FLUSH = 0x2 PR_SPEC_NOT_AFFECTED = 0x0 PR_SPEC_PRCTL = 0x1 PR_SPEC_STORE_BYPASS = 0x0 @@ -1561,9 +2951,15 @@ const ( PR_SVE_SET_VL_ONEXEC = 0x40000 PR_SVE_VL_INHERIT = 0x20000 PR_SVE_VL_LEN_MASK = 0xffff + PR_SYS_DISPATCH_OFF = 0x0 + PR_SYS_DISPATCH_ON = 0x1 PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 + PR_TIMER_CREATE_RESTORE_IDS = 0x4d + PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 + PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 + PR_TIMER_CREATE_RESTORE_IDS_ON = 0x1 PR_TIMING_STATISTICAL = 0x0 PR_TIMING_TIMESTAMP = 0x1 PR_TSC_ENABLE = 0x1 @@ -1571,6 +2967,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 @@ -1589,7 +3007,9 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_RSEQ_CONFIGURATION = 0x420f PTRACE_GET_SYSCALL_INFO = 0x420e + PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG = 0x4211 PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 PTRACE_LISTEN = 0x4208 @@ -1620,6 +3040,8 @@ const ( PTRACE_SETREGSET = 0x4205 PTRACE_SETSIGINFO = 0x4203 PTRACE_SETSIGMASK = 0x420b + PTRACE_SET_SYSCALL_INFO = 0x4212 + PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210 PTRACE_SINGLESTEP = 0x9 PTRACE_SYSCALL = 0x18 PTRACE_SYSCALL_INFO_ENTRY = 0x1 @@ -1627,9 +3049,35 @@ const ( PTRACE_SYSCALL_INFO_NONE = 0x0 PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 + PT_AARCH64_MEMTAG_MTE = 0x70000002 + PT_DYNAMIC = 0x2 + PT_GNU_EH_FRAME = 0x6474e550 + PT_GNU_PROPERTY = 0x6474e553 + PT_GNU_RELRO = 0x6474e552 + PT_GNU_STACK = 0x6474e551 + PT_HIOS = 0x6fffffff + PT_HIPROC = 0x7fffffff + PT_INTERP = 0x3 + PT_LOAD = 0x1 + PT_LOOS = 0x60000000 + PT_LOPROC = 0x70000000 + PT_NOTE = 0x4 + PT_NULL = 0x0 + PT_PHDR = 0x6 + PT_SHLIB = 0x5 + PT_TLS = 0x7 + P_ALL = 0x0 + P_PGID = 0x2 + P_PID = 0x1 + P_PIDFD = 0x3 QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 RAMFS_MAGIC = 0x858458f6 + RAW_PAYLOAD_DIGITAL = 0x3 + RAW_PAYLOAD_HCI = 0x2 + RAW_PAYLOAD_LLCP = 0x0 + RAW_PAYLOAD_NCI = 0x1 + RAW_PAYLOAD_PROPRIETARY = 0x4 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 RENAME_EXCHANGE = 0x2 @@ -1654,8 +3102,9 @@ const ( RTAX_FEATURES = 0xc RTAX_FEATURE_ALLFRAG = 0x8 RTAX_FEATURE_ECN = 0x1 - RTAX_FEATURE_MASK = 0xf + RTAX_FEATURE_MASK = 0x1f RTAX_FEATURE_SACK = 0x2 + RTAX_FEATURE_TCP_USEC_TS = 0x10 RTAX_FEATURE_TIMESTAMP = 0x4 RTAX_HOPLIMIT = 0xa RTAX_INITCWND = 0xb @@ -1672,7 +3121,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 @@ -1680,8 +3129,24 @@ const ( RTCF_NAT = 0x800000 RTCF_VALVE = 0x200000 RTC_AF = 0x20 + RTC_BSM_DIRECT = 0x1 + RTC_BSM_DISABLED = 0x0 + RTC_BSM_LEVEL = 0x2 + RTC_BSM_STANDBY = 0x3 + RTC_FEATURE_ALARM = 0x0 + RTC_FEATURE_ALARM_RES_2S = 0x3 + RTC_FEATURE_ALARM_RES_MINUTE = 0x1 + RTC_FEATURE_ALARM_WAKEUP_ONLY = 0x7 + RTC_FEATURE_BACKUP_SWITCH_MODE = 0x6 + RTC_FEATURE_CNT = 0x8 + RTC_FEATURE_CORRECTION = 0x5 + RTC_FEATURE_NEED_WEEK_DAY = 0x2 + RTC_FEATURE_UPDATE_INTERRUPT = 0x4 RTC_IRQF = 0x80 RTC_MAX_FREQ = 0x2000 + RTC_PARAM_BACKUP_SWITCH_MODE = 0x2 + RTC_PARAM_CORRECTION = 0x1 + RTC_PARAM_FEATURES = 0x0 RTC_PF = 0x40 RTC_UF = 0x10 RTF_ADDRCLASSMASK = 0xf8000000 @@ -1733,25 +3198,33 @@ 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 + RTM_DELNEXTHOPBUCKET = 0x75 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 RTM_DELRULE = 0x21 RTM_DELTCLASS = 0x29 RTM_DELTFILTER = 0x2d + RTM_DELTUNNEL = 0x79 + RTM_DELVLAN = 0x71 RTM_F_CLONED = 0x200 RTM_F_EQUALIZE = 0x400 RTM_F_FIB_MATCH = 0x2000 RTM_F_LOOKUP_TABLE = 0x1000 RTM_F_NOTIFY = 0x100 + RTM_F_OFFLOAD = 0x4000 + RTM_F_OFFLOAD_FAILED = 0x20000000 RTM_F_PREFIX = 0x800 + RTM_F_TRAP = 0x8000 RTM_GETACTION = 0x32 RTM_GETADDR = 0x16 RTM_GETADDRLABEL = 0x4a @@ -1766,6 +3239,7 @@ const ( RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 RTM_GETNEXTHOP = 0x6a + RTM_GETNEXTHOPBUCKET = 0x76 RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -1773,20 +3247,25 @@ const ( RTM_GETSTATS = 0x5e RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e - RTM_MAX = 0x6f + RTM_GETTUNNEL = 0x7a + RTM_GETVLAN = 0x72 + RTM_MAX = 0x7b 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 RTM_NEWNETCONF = 0x50 RTM_NEWNEXTHOP = 0x68 + RTM_NEWNEXTHOPBUCKET = 0x74 RTM_NEWNSID = 0x58 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 @@ -1795,18 +3274,22 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x18 - RTM_NR_MSGTYPES = 0x60 + RTM_NEWTUNNEL = 0x78 + RTM_NEWVLAN = 0x70 + RTM_NR_FAMILIES = 0x1b + RTM_NR_MSGTYPES = 0x6c RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 + RTM_SETSTATS = 0x5f RTNH_ALIGNTO = 0x4 - RTNH_COMPARE_MASK = 0x19 + RTNH_COMPARE_MASK = 0x59 RTNH_F_DEAD = 0x1 RTNH_F_LINKDOWN = 0x10 RTNH_F_OFFLOAD = 0x8 RTNH_F_ONLINK = 0x4 RTNH_F_PERVASIVE = 0x2 + RTNH_F_TRAP = 0x40 RTNH_F_UNRESOLVED = 0x20 RTN_MAX = 0xb RTPROT_BABEL = 0x2a @@ -1818,11 +3301,14 @@ const ( RTPROT_EIGRP = 0xc0 RTPROT_GATED = 0x8 RTPROT_ISIS = 0xbb + RTPROT_KEEPALIVED = 0x12 RTPROT_KERNEL = 0x2 RTPROT_MROUTED = 0x11 RTPROT_MRT = 0xa RTPROT_NTK = 0xf + RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc + RTPROT_OVN = 0x54 RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 RTPROT_RIP = 0xbd @@ -1839,21 +3325,121 @@ 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 + SCHED_FLAG_KEEP_ALL = 0x18 + SCHED_FLAG_KEEP_PARAMS = 0x10 + SCHED_FLAG_KEEP_POLICY = 0x8 + SCHED_FLAG_RECLAIM = 0x2 + SCHED_FLAG_RESET_ON_FORK = 0x1 + SCHED_FLAG_UTIL_CLAMP = 0x60 + SCHED_FLAG_UTIL_CLAMP_MAX = 0x40 + SCHED_FLAG_UTIL_CLAMP_MIN = 0x20 + SCHED_IDLE = 0x5 + SCHED_NORMAL = 0x0 + 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 + SECCOMP_ADDFD_FLAG_SETFD = 0x1 + SECCOMP_FILTER_FLAG_LOG = 0x2 + SECCOMP_FILTER_FLAG_NEW_LISTENER = 0x8 + SECCOMP_FILTER_FLAG_SPEC_ALLOW = 0x4 + SECCOMP_FILTER_FLAG_TSYNC = 0x1 + SECCOMP_FILTER_FLAG_TSYNC_ESRCH = 0x10 + SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV = 0x20 + SECCOMP_GET_ACTION_AVAIL = 0x2 + SECCOMP_GET_NOTIF_SIZES = 0x3 + SECCOMP_IOCTL_NOTIF_RECV = 0xc0502100 + SECCOMP_IOCTL_NOTIF_SEND = 0xc0182101 + SECCOMP_IOC_MAGIC = '!' SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 SECCOMP_MODE_STRICT = 0x1 + SECCOMP_RET_ACTION = 0x7fff0000 + SECCOMP_RET_ACTION_FULL = 0xffff0000 + SECCOMP_RET_ALLOW = 0x7fff0000 + SECCOMP_RET_DATA = 0xffff + SECCOMP_RET_ERRNO = 0x50000 + SECCOMP_RET_KILL = 0x0 + SECCOMP_RET_KILL_PROCESS = 0x80000000 + SECCOMP_RET_KILL_THREAD = 0x0 + SECCOMP_RET_LOG = 0x7ffc0000 + SECCOMP_RET_TRACE = 0x7ff00000 + SECCOMP_RET_TRAP = 0x30000 + SECCOMP_RET_USER_NOTIF = 0x7fc00000 + SECCOMP_SET_MODE_FILTER = 0x1 + SECCOMP_SET_MODE_STRICT = 0x0 + SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP = 0x1 + SECCOMP_USER_NOTIF_FLAG_CONTINUE = 0x1 + SECRETMEM_MAGIC = 0x5345434d SECURITYFS_MAGIC = 0x73636673 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_MAX = 0x4 + SEEK_SET = 0x0 SELINUX_MAGIC = 0xf97cff8c + SHF_ALLOC = 0x2 + SHF_EXCLUDE = 0x8000000 + SHF_EXECINSTR = 0x4 + SHF_GROUP = 0x200 + SHF_INFO_LINK = 0x40 + SHF_LINK_ORDER = 0x80 + SHF_MASKOS = 0xff00000 + SHF_MASKPROC = 0xf0000000 + SHF_MERGE = 0x10 + SHF_ORDERED = 0x4000000 + SHF_OS_NONCONFORMING = 0x100 + SHF_RELA_LIVEPATCH = 0x100000 + SHF_RO_AFTER_INIT = 0x200000 + SHF_STRINGS = 0x20 + SHF_TLS = 0x400 + SHF_WRITE = 0x1 + SHN_ABS = 0xfff1 + SHN_COMMON = 0xfff2 + SHN_HIPROC = 0xff1f + SHN_HIRESERVE = 0xffff + SHN_LIVEPATCH = 0xff20 + SHN_LOPROC = 0xff00 + SHN_LORESERVE = 0xff00 + SHN_UNDEF = 0x0 + SHT_DYNAMIC = 0x6 + SHT_DYNSYM = 0xb + SHT_HASH = 0x5 + SHT_HIPROC = 0x7fffffff + SHT_HIUSER = 0xffffffff + SHT_LOPROC = 0x70000000 + SHT_LOUSER = 0x80000000 + SHT_NOBITS = 0x8 + SHT_NOTE = 0x7 + SHT_NULL = 0x0 + SHT_NUM = 0xc + SHT_PROGBITS = 0x1 + SHT_REL = 0x9 + SHT_RELA = 0x4 + SHT_SHLIB = 0xa + SHT_STRTAB = 0x3 + SHT_SYMTAB = 0x2 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1913,6 +3499,9 @@ const ( SIOCGSTAMPNS = 0x8907 SIOCGSTAMPNS_OLD = 0x8907 SIOCGSTAMP_OLD = 0x8906 + SIOCKCMATTACH = 0x89e0 + SIOCKCMCLONE = 0x89e2 + SIOCKCMUNATTACH = 0x89e1 SIOCOUTQNSD = 0x894b SIOCPROTOPRIVATE = 0x89e0 SIOCRTMSG = 0x890d @@ -1940,6 +3529,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 @@ -1955,19 +3546,29 @@ const ( SMART_STATUS = 0xda SMART_WRITE_LOG_SECTOR = 0xd6 SMART_WRITE_THRESHOLDS = 0xd7 + SMB2_SUPER_MAGIC = 0xfe534d42 SMB_SUPER_MAGIC = 0x517b 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 + SOCK_RCVBUF_LOCK = 0x2 SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 + SOCK_SNDBUF_LOCK = 0x1 + SOCK_TXREHASH_DEFAULT = 0xff + SOCK_TXREHASH_DISABLED = 0x0 + SOCK_TXREHASH_ENABLED = 0x1 SOL_AAL = 0x109 SOL_ALG = 0x117 SOL_ATM = 0x108 SOL_CAIF = 0x116 SOL_CAN_BASE = 0x64 + SOL_CAN_RAW = 0x65 SOL_DCCP = 0x10d SOL_DECNET = 0x105 SOL_ICMPV6 = 0x3a @@ -1977,6 +3578,8 @@ const ( SOL_IUCV = 0x115 SOL_KCM = 0x119 SOL_LLC = 0x10c + SOL_MCTP = 0x11d + SOL_MPTCP = 0x11c SOL_NETBEUI = 0x10b SOL_NETLINK = 0x10e SOL_NFC = 0x118 @@ -1986,9 +3589,12 @@ const ( SOL_RAW = 0xff SOL_RDS = 0x114 SOL_RXRPC = 0x110 + SOL_SMC = 0x11e SOL_TCP = 0x6 SOL_TIPC = 0x10f SOL_TLS = 0x11a + SOL_UDP = 0x11 + SOL_VSOCK = 0x11f SOL_X25 = 0x106 SOL_XDP = 0x11b SOMAXCONN = 0x1000 @@ -2007,6 +3613,7 @@ const ( SO_EE_ORIGIN_TXSTATUS = 0x4 SO_EE_ORIGIN_TXTIME = 0x6 SO_EE_ORIGIN_ZEROCOPY = 0x5 + SO_EE_RFC4884_FLAG_INVALID = 0x1 SO_GET_FILTER = 0x1a SO_NO_CHECK = 0xb SO_PEERNAME = 0x1c @@ -2017,6 +3624,8 @@ const ( SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 SO_VM_SOCKETS_BUFFER_SIZE = 0x0 SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6 + SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW = 0x8 + SO_VM_SOCKETS_CONNECT_TIMEOUT_OLD = 0x6 SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7 SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3 SO_VM_SOCKETS_TRUSTED = 0x5 @@ -2031,23 +3640,42 @@ const ( STATX_ATTR_APPEND = 0x20 STATX_ATTR_AUTOMOUNT = 0x1000 STATX_ATTR_COMPRESSED = 0x4 + STATX_ATTR_DAX = 0x200000 STATX_ATTR_ENCRYPTED = 0x800 STATX_ATTR_IMMUTABLE = 0x10 + 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 + STB_GLOBAL = 0x1 + STB_LOCAL = 0x0 + STB_WEAK = 0x2 + STT_COMMON = 0x5 + STT_FILE = 0x4 + STT_FUNC = 0x2 + STT_NOTYPE = 0x0 + STT_OBJECT = 0x1 + STT_SECTION = 0x3 + STT_TLS = 0x6 SYNC_FILE_RANGE_WAIT_AFTER = 0x4 SYNC_FILE_RANGE_WAIT_BEFORE = 0x1 SYNC_FILE_RANGE_WRITE = 0x2 @@ -2086,7 +3714,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0x9 + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -2094,8 +3722,14 @@ const ( TCOFLUSH = 0x1 TCOOFF = 0x0 TCOON = 0x1 - TCP_BPF_IW = 0x3e9 - TCP_BPF_SNDCWND_CLAMP = 0x3ea + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 TCP_CC_INFO = 0x1a TCP_CM_INQ = 0x24 TCP_CONGESTION = 0xd @@ -2122,6 +3756,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 @@ -2151,6 +3786,8 @@ const ( TCP_USER_TIMEOUT = 0x12 TCP_WINDOW_CLAMP = 0xa TCP_ZEROCOPY_RECEIVE = 0x23 + TFD_TIMER_ABSTIME = 0x1 + TFD_TIMER_CANCEL_ON_SET = 0x2 TIMER_ABSTIME = 0x1 TIOCM_DTR = 0x2 TIOCM_LE = 0x1 @@ -2212,6 +3849,7 @@ const ( TIPC_NODE_STATE = 0x0 TIPC_OK = 0x0 TIPC_PUBLISHED = 0x1 + TIPC_REKEYING_NOW = 0xffffffff TIPC_RESERVED_TYPES = 0x40 TIPC_RETDATA = 0x2 TIPC_SERVICE_ADDR = 0x2 @@ -2241,6 +3879,7 @@ const ( TP_STATUS_COPY = 0x2 TP_STATUS_CSUMNOTREADY = 0x8 TP_STATUS_CSUM_VALID = 0x80 + TP_STATUS_GSO_TCP = 0x100 TP_STATUS_KERNEL = 0x0 TP_STATUS_LOSING = 0x4 TP_STATUS_SENDING = 0x2 @@ -2254,30 +3893,70 @@ 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 + UDP_ENCAP_ESPINUDP = 0x2 + UDP_ENCAP_ESPINUDP_NON_IKE = 0x1 + UDP_ENCAP_GTP0 = 0x4 + UDP_ENCAP_GTP1U = 0x5 + UDP_ENCAP_L2TPINUDP = 0x3 + UDP_GRO = 0x68 + UDP_NO_CHECK6_RX = 0x66 + UDP_NO_CHECK6_TX = 0x65 + UDP_SEGMENT = 0x67 UMOUNT_NOFOLLOW = 0x8 USBDEVICE_SUPER_MAGIC = 0x9fa2 UTIME_NOW = 0x3fffffff UTIME_OMIT = 0x3ffffffe V9FS_MAGIC = 0x1021997 VERASE = 0x2 + VER_FLG_BASE = 0x1 + VER_FLG_WEAK = 0x2 VINTR = 0x0 VKILL = 0x3 VLNEXT = 0xf VMADDR_CID_ANY = 0xffffffff VMADDR_CID_HOST = 0x2 VMADDR_CID_HYPERVISOR = 0x0 - VMADDR_CID_RESERVED = 0x1 + VMADDR_CID_LOCAL = 0x1 + VMADDR_FLAG_TO_HOST = 0x1 VMADDR_PORT_ANY = 0xffffffff VM_SOCKETS_INVALID_VERSION = 0xffffffff VQUIT = 0x1 VT0 = 0x0 + WAKE_MAGIC = 0x20 WALL = 0x40000000 WCLONE = 0x80000000 WCONTINUED = 0x8 WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 + WDIOF_ALARMONLY = 0x400 + WDIOF_CARDRESET = 0x20 + WDIOF_EXTERN1 = 0x4 + WDIOF_EXTERN2 = 0x8 + WDIOF_FANFAULT = 0x2 + WDIOF_KEEPALIVEPING = 0x8000 + WDIOF_MAGICCLOSE = 0x100 + WDIOF_OVERHEAT = 0x1 + WDIOF_POWEROVER = 0x40 + WDIOF_POWERUNDER = 0x10 + WDIOF_PRETIMEOUT = 0x200 + WDIOF_SETTIMEOUT = 0x80 + WDIOF_UNKNOWN = -0x1 + WDIOS_DISABLECARD = 0x1 + WDIOS_ENABLECARD = 0x2 + WDIOS_TEMPPANIC = 0x4 + WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 + WGALLOWEDIP_A_MAX = 0x4 + WGDEVICE_A_MAX = 0x8 + WGPEER_A_MAX = 0xa + WG_CMD_MAX = 0x1 + WG_GENL_NAME = "wireguard" + WG_GENL_VERSION = 0x1 + WG_KEY_LEN = 0x20 WIN_ACKMEDIACHANGE = 0xdb WIN_CHECKPOWERMODE1 = 0xe5 WIN_CHECKPOWERMODE2 = 0x98 @@ -2368,8 +4047,9 @@ const ( XDP_COPY = 0x2 XDP_FLAGS_DRV_MODE = 0x4 XDP_FLAGS_HW_MODE = 0x8 - XDP_FLAGS_MASK = 0xf + XDP_FLAGS_MASK = 0x1f XDP_FLAGS_MODES = 0xe + XDP_FLAGS_REPLACE = 0x10 XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 XDP_MMAP_OFFSETS = 0x1 @@ -2378,23 +4058,33 @@ const ( XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 + XDP_PKT_CONTD = 0x1 XDP_RING_NEED_WAKEUP = 0x1 XDP_RX_RING = 0x2 XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 + XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_LAUNCH_TIME = 0x4 + 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 XDP_ZEROCOPY = 0x4 XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 - Z3FOLD_MAGIC = 0x33 - ZSMALLOC_MAGIC = 0x58295829 + ZONEFS_MAGIC = 0x5a4f4653 + _HIDIOCGRAWNAME_LEN = 0x80 + _HIDIOCGRAWPHYS_LEN = 0x40 + _HIDIOCGRAWUNIQ_LEN = 0x40 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 0876cf9..97a61fc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include -m32 +// mkerrors.sh -Wall -Werror -static -I/tmp/386/include -m32 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,linux +//go:build 386 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/386/include -m32 _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x127a BLKBSZGET = 0x80041270 BLKBSZSET = 0x40041271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c BLKFLSBUF = 0x1261 BLKFRAGET = 0x1265 BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 BLKGETSIZE = 0x1260 BLKGETSIZE64 = 0x80041272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 BLKPBSZGET = 0x127b BLKRAGET = 0x1263 BLKRASET = 0x1262 BLKROGET = 0x125e BLKROSET = 0x125d + BLKROTATIONAL = 0x127e BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d BLKSECTGET = 0x1267 BLKSECTSET = 0x1266 BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,14 +79,22 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d FLUSHO = 0x1000 FP_XSTATE_MAGIC2 = 0x46505845 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80046601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40046602 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 F_GETLK = 0xc F_GETLK64 = 0xc @@ -87,17 +107,26 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 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 @@ -113,15 +142,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc03c4d1a + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x4d13 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -159,6 +212,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x2405 PPPIOCATTACH = 0x4004743d PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 PPPIOCCONNECT = 0x4004743a PPPIOCDETACH = 0x4004743c PPPIOCDISCONN = 0x7439 @@ -186,8 +240,23 @@ const ( PPPIOCSPASS = 0x40087447 PPPIOCSRASYNCMAP = 0x40047454 PPPIOCSXASYNCMAP = 0x4020744f + 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 @@ -218,6 +287,8 @@ const ( RTC_EPOCH_SET = 0x4004700e RTC_IRQP_READ = 0x8004700b RTC_IRQP_SET = 0x4004700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x801c7011 @@ -232,12 +303,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -261,10 +338,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -276,21 +358,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -311,6 +401,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -340,6 +431,8 @@ const ( TCSETXF = 0x5434 TCSETXW = 0x5435 TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -473,6 +566,9 @@ const ( X86_FXSR_MAGIC = 0x0 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index d5be2e8..a0d6d49 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include -m64 +// mkerrors.sh -Wall -Werror -static -I/tmp/amd64/include -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,linux +//go:build amd64 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/amd64/include -m64 _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x127a BLKBSZGET = 0x80081270 BLKBSZSET = 0x40081271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c BLKFLSBUF = 0x1261 BLKFRAGET = 0x1265 BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 BLKGETSIZE = 0x1260 BLKGETSIZE64 = 0x80081272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 BLKPBSZGET = 0x127b BLKRAGET = 0x1263 BLKRASET = 0x1262 BLKROGET = 0x125e BLKROSET = 0x125d + BLKROTATIONAL = 0x127e BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d BLKSECTGET = 0x1267 BLKSECTSET = 0x1266 BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,14 +79,22 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d FLUSHO = 0x1000 FP_XSTATE_MAGIC2 = 0x46505845 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 F_GETLK = 0x5 F_GETLK64 = 0x5 @@ -87,17 +107,26 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 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 @@ -113,15 +142,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -159,6 +212,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x2405 PPPIOCATTACH = 0x4004743d PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 PPPIOCCONNECT = 0x4004743a PPPIOCDETACH = 0x4004743c PPPIOCDISCONN = 0x7439 @@ -186,8 +240,23 @@ const ( PPPIOCSPASS = 0x40107447 PPPIOCSRASYNCMAP = 0x40047454 PPPIOCSXASYNCMAP = 0x4020744f + 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 @@ -219,6 +288,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -233,12 +304,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -262,10 +339,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -277,21 +359,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -312,6 +402,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -341,6 +432,8 @@ const ( TCSETXF = 0x5434 TCSETXW = 0x5435 TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -473,6 +566,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index fbeef83..dd9c903 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/arm/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,linux +//go:build arm && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/arm/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x127a BLKBSZGET = 0x80041270 BLKBSZSET = 0x40041271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c BLKFLSBUF = 0x1261 BLKFRAGET = 0x1265 BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 BLKGETSIZE = 0x1260 BLKGETSIZE64 = 0x80041272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 BLKPBSZGET = 0x127b BLKRAGET = 0x1263 BLKRASET = 0x1262 BLKROGET = 0x125e BLKROSET = 0x125d + BLKROTATIONAL = 0x127e BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d BLKSECTGET = 0x1267 BLKSECTSET = 0x1266 BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d FLUSHO = 0x1000 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80046601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40046602 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 F_GETLK = 0xc F_GETLK64 = 0xc @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x4d13 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x2405 PPPIOCATTACH = 0x4004743d PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 PPPIOCCONNECT = 0x4004743a PPPIOCDETACH = 0x4004743c PPPIOCDISCONN = 0x7439 @@ -184,8 +237,23 @@ const ( PPPIOCSPASS = 0x40087447 PPPIOCSRASYNCMAP = 0x40047454 PPPIOCSXASYNCMAP = 0x4020744f + 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 @@ -225,6 +293,8 @@ const ( RTC_EPOCH_SET = 0x4004700e RTC_IRQP_READ = 0x8004700b RTC_IRQP_SET = 0x4004700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x801c7011 @@ -239,12 +309,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -268,10 +344,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -283,21 +364,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -318,6 +407,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -347,6 +437,8 @@ const ( TCSETXF = 0x5434 TCSETXW = 0x5435 TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -479,6 +571,9 @@ const ( WORDSIZE = 0x20 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 06daa50..384c61c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include -fsigned-char +// mkerrors.sh -Wall -Werror -static -I/tmp/arm64/include -fsigned-char // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,linux +//go:build arm64 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/arm64/include -fsigned-char _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x127a BLKBSZGET = 0x80081270 BLKBSZSET = 0x40081271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c BLKFLSBUF = 0x1261 BLKFRAGET = 0x1265 BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 BLKGETSIZE = 0x1260 BLKGETSIZE64 = 0x80081272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 BLKPBSZGET = 0x127b BLKRAGET = 0x1263 BLKRASET = 0x1262 BLKROGET = 0x125e BLKROSET = 0x125d + BLKROTATIONAL = 0x127e BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d BLKSECTGET = 0x1267 BLKSECTSET = 0x1266 BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,16 +79,25 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 ESR_MAGIC = 0x45535201 EXTPROC = 0x10000 EXTRA_MAGIC = 0x45585401 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d FLUSHO = 0x1000 + FPMR_MAGIC = 0x46504d52 FPSIMD_MAGIC = 0x46508001 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 F_GETLK = 0x5 F_GETLK64 = 0x5 @@ -89,12 +110,21 @@ 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_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -114,15 +144,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -158,8 +212,10 @@ 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 PPPIOCCONNECT = 0x4004743a PPPIOCDETACH = 0x4004743c PPPIOCDISCONN = 0x7439 @@ -187,8 +243,27 @@ const ( PPPIOCSPASS = 0x40107447 PPPIOCSRASYNCMAP = 0x40047454 PPPIOCSXASYNCMAP = 0x4020744f + PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e + 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 PTRACE_SYSEMU_SINGLESTEP = 0x20 RLIMIT_AS = 0x9 @@ -211,6 +286,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -225,12 +302,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -254,10 +337,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -269,21 +357,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -304,6 +400,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -334,6 +431,8 @@ const ( TCSETXF = 0x5434 TCSETXW = 0x5435 TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -395,6 +494,7 @@ const ( TIOCSWINSZ = 0x5414 TIOCVHANGUP = 0x5437 TOSTOP = 0x100 + TPIDR2_MAGIC = 0x54504902 TUNATTACHFILTER = 0x401054d5 TUNDETACHFILTER = 0x401054d6 TUNGETDEVNETNS = 0x54e3 @@ -466,6 +566,11 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + ZA_MAGIC = 0x54366345 + ZT_MAGIC = 0x5a544e01 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go new file mode 100644 index 0000000..6384c98 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -0,0 +1,870 @@ +// mkerrors.sh -Wall -Werror -static -I/tmp/loong64/include +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build loong64 && linux + +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs -- -Wall -Werror -static -I/tmp/loong64/include _const.go + +package unix + +import "syscall" + +const ( + B1000000 = 0x1008 + B115200 = 0x1002 + B1152000 = 0x1009 + B1500000 = 0x100a + B2000000 = 0x100b + B230400 = 0x1003 + B2500000 = 0x100c + B3000000 = 0x100d + B3500000 = 0x100e + B4000000 = 0x100f + B460800 = 0x1004 + B500000 = 0x1005 + B57600 = 0x1001 + B576000 = 0x1006 + B921600 = 0x1007 + BLKALIGNOFF = 0x127a + BLKBSZGET = 0x80081270 + BLKBSZSET = 0x40081271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c + BLKFLSBUF = 0x1261 + BLKFRAGET = 0x1265 + BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 + BLKGETSIZE = 0x1260 + BLKGETSIZE64 = 0x80081272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 + BLKPBSZGET = 0x127b + BLKRAGET = 0x1263 + BLKRASET = 0x1262 + BLKROGET = 0x125e + BLKROSET = 0x125d + BLKROTATIONAL = 0x127e + BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d + BLKSECTGET = 0x1267 + BLKSECTSET = 0x1266 + BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f + BOTHER = 0x1000 + BS1 = 0x2000 + BSDLY = 0x2000 + CBAUD = 0x100f + CBAUDEX = 0x1000 + CIBAUD = 0x100f0000 + CLOCAL = 0x800 + CR1 = 0x200 + CR2 = 0x400 + CR3 = 0x600 + CRDLY = 0x600 + CREAD = 0x80 + CS6 = 0x10 + CS7 = 0x20 + CS8 = 0x30 + CSIZE = 0x30 + CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 + ECHOCTL = 0x200 + ECHOE = 0x10 + ECHOK = 0x20 + ECHOKE = 0x800 + ECHONL = 0x40 + ECHOPRT = 0x400 + EFD_CLOEXEC = 0x80000 + EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 + EPOLL_CLOEXEC = 0x80000 + EXTPROC = 0x10000 + FF1 = 0x8000 + FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d + FLUSHO = 0x1000 + FPU_CTX_MAGIC = 0x46505501 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b + FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 + FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40086602 + FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 + F_GETLK = 0x5 + F_GETLK64 = 0x5 + F_GETOWN = 0x9 + F_RDLCK = 0x0 + F_SETLK = 0x6 + F_SETLK64 = 0x6 + F_SETLKW = 0x7 + F_SETLKW64 = 0x7 + F_SETOWN = 0x8 + F_UNLCK = 0x2 + F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d + HUPCL = 0x400 + ICANON = 0x2 + IEXTEN = 0x8000 + IN_CLOEXEC = 0x80000 + IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + ISIG = 0x1 + IUCLC = 0x200 + IXOFF = 0x1000 + IXON = 0x400 + LASX_CTX_MAGIC = 0x41535801 + LBT_CTX_MAGIC = 0x42540001 + LSX_CTX_MAGIC = 0x53580001 + MAP_ANON = 0x20 + MAP_ANONYMOUS = 0x20 + MAP_DENYWRITE = 0x800 + MAP_EXECUTABLE = 0x1000 + MAP_GROWSDOWN = 0x100 + MAP_HUGETLB = 0x40000 + MAP_LOCKED = 0x2000 + MAP_NONBLOCK = 0x10000 + MAP_NORESERVE = 0x4000 + MAP_POPULATE = 0x8000 + MAP_STACK = 0x20000 + MAP_SYNC = 0x80000 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 + 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d + O_APPEND = 0x400 + O_ASYNC = 0x2000 + O_CLOEXEC = 0x80000 + O_CREAT = 0x40 + O_DIRECT = 0x4000 + O_DIRECTORY = 0x10000 + O_DSYNC = 0x1000 + O_EXCL = 0x80 + O_FSYNC = 0x101000 + O_LARGEFILE = 0x0 + O_NDELAY = 0x800 + O_NOATIME = 0x40000 + O_NOCTTY = 0x100 + O_NOFOLLOW = 0x20000 + O_NONBLOCK = 0x800 + O_PATH = 0x200000 + O_RSYNC = 0x101000 + O_SYNC = 0x101000 + O_TMPFILE = 0x410000 + O_TRUNC = 0x200 + PARENB = 0x100 + PARODD = 0x200 + PENDIN = 0x4000 + PERF_EVENT_IOC_DISABLE = 0x2401 + PERF_EVENT_IOC_ENABLE = 0x2400 + PERF_EVENT_IOC_ID = 0x80082407 + PERF_EVENT_IOC_MODIFY_ATTRIBUTES = 0x4008240b + PERF_EVENT_IOC_PAUSE_OUTPUT = 0x40042409 + PERF_EVENT_IOC_PERIOD = 0x40082404 + PERF_EVENT_IOC_QUERY_BPF = 0xc008240a + PERF_EVENT_IOC_REFRESH = 0x2402 + PERF_EVENT_IOC_RESET = 0x2403 + PERF_EVENT_IOC_SET_BPF = 0x40042408 + PERF_EVENT_IOC_SET_FILTER = 0x40082406 + PERF_EVENT_IOC_SET_OUTPUT = 0x2405 + PPPIOCATTACH = 0x4004743d + PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 + PPPIOCCONNECT = 0x4004743a + PPPIOCDETACH = 0x4004743c + PPPIOCDISCONN = 0x7439 + PPPIOCGASYNCMAP = 0x80047458 + PPPIOCGCHAN = 0x80047437 + PPPIOCGDEBUG = 0x80047441 + PPPIOCGFLAGS = 0x8004745a + PPPIOCGIDLE = 0x8010743f + PPPIOCGIDLE32 = 0x8008743f + PPPIOCGIDLE64 = 0x8010743f + PPPIOCGL2TPSTATS = 0x80487436 + PPPIOCGMRU = 0x80047453 + PPPIOCGRASYNCMAP = 0x80047455 + PPPIOCGUNIT = 0x80047456 + PPPIOCGXASYNCMAP = 0x80207450 + PPPIOCSACTIVE = 0x40107446 + PPPIOCSASYNCMAP = 0x40047457 + PPPIOCSCOMPRESS = 0x4010744d + PPPIOCSDEBUG = 0x40047440 + PPPIOCSFLAGS = 0x40047459 + PPPIOCSMAXCID = 0x40047451 + PPPIOCSMRRU = 0x4004743b + PPPIOCSMRU = 0x40047452 + PPPIOCSNPMODE = 0x4008744b + PPPIOCSPASS = 0x40107447 + PPPIOCSRASYNCMAP = 0x40047454 + PPPIOCSXASYNCMAP = 0x4020744f + 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 + RLIMIT_MEMLOCK = 0x8 + RLIMIT_NOFILE = 0x7 + RLIMIT_NPROC = 0x6 + RLIMIT_RSS = 0x5 + RNDADDENTROPY = 0x40085203 + RNDADDTOENTCNT = 0x40045201 + RNDCLEARPOOL = 0x5206 + RNDGETENTCNT = 0x80045200 + RNDGETPOOL = 0x80085202 + RNDRESEEDCRNG = 0x5207 + RNDZAPENTCNT = 0x5204 + RTC_AIE_OFF = 0x7002 + RTC_AIE_ON = 0x7001 + RTC_ALM_READ = 0x80247008 + RTC_ALM_SET = 0x40247007 + RTC_EPOCH_READ = 0x8008700d + RTC_EPOCH_SET = 0x4008700e + RTC_IRQP_READ = 0x8008700b + RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 + RTC_PIE_OFF = 0x7006 + RTC_PIE_ON = 0x7005 + RTC_PLL_GET = 0x80207011 + RTC_PLL_SET = 0x40207012 + RTC_RD_TIME = 0x80247009 + RTC_SET_TIME = 0x4024700a + RTC_UIE_OFF = 0x7004 + RTC_UIE_ON = 0x7003 + RTC_VL_CLR = 0x7014 + RTC_VL_READ = 0x80047013 + RTC_WIE_OFF = 0x7010 + 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 + SFD_CLOEXEC = 0x80000 + SFD_NONBLOCK = 0x800 + SIOCATMARK = 0x8905 + SIOCGPGRP = 0x8904 + SIOCGSTAMPNS_NEW = 0x80108907 + SIOCGSTAMP_NEW = 0x80108906 + SIOCINQ = 0x541b + SIOCOUTQ = 0x5411 + SIOCSPGRP = 0x8902 + SOCK_CLOEXEC = 0x80000 + SOCK_DGRAM = 0x2 + SOCK_NONBLOCK = 0x800 + SOCK_STREAM = 0x1 + SOL_SOCKET = 0x1 + SO_ACCEPTCONN = 0x1e + SO_ATTACH_BPF = 0x32 + SO_ATTACH_REUSEPORT_CBPF = 0x33 + SO_ATTACH_REUSEPORT_EBPF = 0x34 + SO_BINDTODEVICE = 0x19 + SO_BINDTOIFINDEX = 0x3e + SO_BPF_EXTENSIONS = 0x30 + SO_BROADCAST = 0x6 + SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 + SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 + 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 + SO_INCOMING_CPU = 0x31 + SO_INCOMING_NAPI_ID = 0x38 + SO_KEEPALIVE = 0x9 + SO_LINGER = 0xd + SO_LOCK_FILTER = 0x2c + SO_MARK = 0x24 + SO_MAX_PACING_RATE = 0x2f + SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 + SO_NOFCS = 0x2b + SO_OOBINLINE = 0xa + SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 + SO_PASSSEC = 0x22 + SO_PEEK_OFF = 0x2a + SO_PEERCRED = 0x11 + SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d + SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 + SO_PROTOCOL = 0x26 + SO_RCVBUF = 0x8 + SO_RCVBUFFORCE = 0x21 + SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 + SO_RCVTIMEO = 0x14 + SO_RCVTIMEO_NEW = 0x42 + SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 + SO_REUSEADDR = 0x2 + SO_REUSEPORT = 0xf + SO_RXQ_OVFL = 0x28 + SO_SECURITY_AUTHENTICATION = 0x16 + SO_SECURITY_ENCRYPTION_NETWORK = 0x18 + SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17 + SO_SELECT_ERR_QUEUE = 0x2d + SO_SNDBUF = 0x7 + SO_SNDBUFFORCE = 0x20 + SO_SNDLOWAT = 0x13 + SO_SNDTIMEO = 0x15 + SO_SNDTIMEO_NEW = 0x43 + SO_SNDTIMEO_OLD = 0x15 + SO_TIMESTAMPING = 0x25 + SO_TIMESTAMPING_NEW = 0x41 + SO_TIMESTAMPING_OLD = 0x25 + SO_TIMESTAMPNS = 0x23 + SO_TIMESTAMPNS_NEW = 0x40 + SO_TIMESTAMPNS_OLD = 0x23 + SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a + SO_TXTIME = 0x3d + SO_TYPE = 0x3 + SO_WIFI_STATUS = 0x29 + SO_ZEROCOPY = 0x3c + TAB1 = 0x800 + TAB2 = 0x1000 + TAB3 = 0x1800 + TABDLY = 0x1800 + TCFLSH = 0x540b + TCGETA = 0x5405 + TCGETS = 0x5401 + TCGETS2 = 0x802c542a + TCGETX = 0x5432 + TCSAFLUSH = 0x2 + TCSBRK = 0x5409 + TCSBRKP = 0x5425 + TCSETA = 0x5406 + TCSETAF = 0x5408 + TCSETAW = 0x5407 + TCSETS = 0x5402 + TCSETS2 = 0x402c542b + TCSETSF = 0x5404 + TCSETSF2 = 0x402c542d + TCSETSW = 0x5403 + TCSETSW2 = 0x402c542c + TCSETX = 0x5433 + TCSETXF = 0x5434 + TCSETXW = 0x5435 + TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 + TIOCCBRK = 0x5428 + TIOCCONS = 0x541d + TIOCEXCL = 0x540c + TIOCGDEV = 0x80045432 + TIOCGETD = 0x5424 + TIOCGEXCL = 0x80045440 + TIOCGICOUNT = 0x545d + TIOCGISO7816 = 0x80285442 + TIOCGLCKTRMIOS = 0x5456 + TIOCGPGRP = 0x540f + TIOCGPKT = 0x80045438 + TIOCGPTLCK = 0x80045439 + TIOCGPTN = 0x80045430 + TIOCGPTPEER = 0x5441 + TIOCGRS485 = 0x542e + TIOCGSERIAL = 0x541e + TIOCGSID = 0x5429 + TIOCGSOFTCAR = 0x5419 + TIOCGWINSZ = 0x5413 + TIOCINQ = 0x541b + TIOCLINUX = 0x541c + TIOCMBIC = 0x5417 + TIOCMBIS = 0x5416 + TIOCMGET = 0x5415 + TIOCMIWAIT = 0x545c + TIOCMSET = 0x5418 + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x5422 + TIOCNXCL = 0x540d + TIOCOUTQ = 0x5411 + TIOCPKT = 0x5420 + TIOCSBRK = 0x5427 + TIOCSCTTY = 0x540e + TIOCSERCONFIG = 0x5453 + TIOCSERGETLSR = 0x5459 + TIOCSERGETMULTI = 0x545a + TIOCSERGSTRUCT = 0x5458 + TIOCSERGWILD = 0x5454 + TIOCSERSETMULTI = 0x545b + TIOCSERSWILD = 0x5455 + TIOCSER_TEMT = 0x1 + TIOCSETD = 0x5423 + TIOCSIG = 0x40045436 + TIOCSISO7816 = 0xc0285443 + TIOCSLCKTRMIOS = 0x5457 + TIOCSPGRP = 0x5410 + TIOCSPTLCK = 0x40045431 + TIOCSRS485 = 0x542f + TIOCSSERIAL = 0x541f + TIOCSSOFTCAR = 0x541a + TIOCSTI = 0x5412 + TIOCSWINSZ = 0x5414 + TIOCVHANGUP = 0x5437 + TOSTOP = 0x100 + TUNATTACHFILTER = 0x401054d5 + TUNDETACHFILTER = 0x401054d6 + TUNGETDEVNETNS = 0x54e3 + TUNGETFEATURES = 0x800454cf + TUNGETFILTER = 0x801054db + TUNGETIFF = 0x800454d2 + TUNGETSNDBUF = 0x800454d3 + TUNGETVNETBE = 0x800454df + TUNGETVNETHDRSZ = 0x800454d7 + TUNGETVNETLE = 0x800454dd + TUNSETCARRIER = 0x400454e2 + TUNSETDEBUG = 0x400454c9 + TUNSETFILTEREBPF = 0x800454e1 + TUNSETGROUP = 0x400454ce + TUNSETIFF = 0x400454ca + TUNSETIFINDEX = 0x400454da + TUNSETLINK = 0x400454cd + TUNSETNOCSUM = 0x400454c8 + TUNSETOFFLOAD = 0x400454d0 + TUNSETOWNER = 0x400454cc + TUNSETPERSIST = 0x400454cb + TUNSETQUEUE = 0x400454d9 + TUNSETSNDBUF = 0x400454d4 + TUNSETSTEERINGEBPF = 0x800454e0 + TUNSETTXFILTER = 0x400454d1 + TUNSETVNETBE = 0x400454de + TUNSETVNETHDRSZ = 0x400454d8 + TUNSETVNETLE = 0x400454dc + UBI_IOCATT = 0x40186f40 + UBI_IOCDET = 0x40046f41 + UBI_IOCEBCH = 0x40044f02 + UBI_IOCEBER = 0x40044f01 + UBI_IOCEBISMAP = 0x80044f05 + UBI_IOCEBMAP = 0x40084f03 + UBI_IOCEBUNMAP = 0x40044f04 + UBI_IOCMKVOL = 0x40986f00 + UBI_IOCRMVOL = 0x40046f01 + UBI_IOCRNVOL = 0x51106f03 + UBI_IOCRPEB = 0x40046f04 + UBI_IOCRSVOL = 0x400c6f02 + UBI_IOCSETVOLPROP = 0x40104f06 + UBI_IOCSPEB = 0x40046f05 + UBI_IOCVOLCRBLK = 0x40804f07 + UBI_IOCVOLRMBLK = 0x4f08 + UBI_IOCVOLUP = 0x40084f00 + VDISCARD = 0xd + VEOF = 0x4 + VEOL = 0xb + VEOL2 = 0x10 + VMIN = 0x6 + VREPRINT = 0xc + VSTART = 0x8 + VSTOP = 0x9 + VSUSP = 0xa + VSWTC = 0x7 + VT1 = 0x4000 + VTDLY = 0x4000 + VTIME = 0x5 + VWERASE = 0xe + WDIOC_GETBOOTSTATUS = 0x80045702 + WDIOC_GETPRETIMEOUT = 0x80045709 + WDIOC_GETSTATUS = 0x80045701 + WDIOC_GETSUPPORT = 0x80285700 + WDIOC_GETTEMP = 0x80045703 + WDIOC_GETTIMELEFT = 0x8004570a + WDIOC_GETTIMEOUT = 0x80045707 + WDIOC_KEEPALIVE = 0x80045705 + WDIOC_SETOPTIONS = 0x80045704 + WORDSIZE = 0x40 + XCASE = 0x4 + XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 +) + +// Errors +const ( + EADDRINUSE = syscall.Errno(0x62) + EADDRNOTAVAIL = syscall.Errno(0x63) + EADV = syscall.Errno(0x44) + EAFNOSUPPORT = syscall.Errno(0x61) + EALREADY = syscall.Errno(0x72) + EBADE = syscall.Errno(0x34) + EBADFD = syscall.Errno(0x4d) + EBADMSG = syscall.Errno(0x4a) + EBADR = syscall.Errno(0x35) + EBADRQC = syscall.Errno(0x38) + EBADSLT = syscall.Errno(0x39) + EBFONT = syscall.Errno(0x3b) + ECANCELED = syscall.Errno(0x7d) + ECHRNG = syscall.Errno(0x2c) + ECOMM = syscall.Errno(0x46) + ECONNABORTED = syscall.Errno(0x67) + ECONNREFUSED = syscall.Errno(0x6f) + ECONNRESET = syscall.Errno(0x68) + EDEADLK = syscall.Errno(0x23) + EDEADLOCK = syscall.Errno(0x23) + EDESTADDRREQ = syscall.Errno(0x59) + EDOTDOT = syscall.Errno(0x49) + EDQUOT = syscall.Errno(0x7a) + EHOSTDOWN = syscall.Errno(0x70) + EHOSTUNREACH = syscall.Errno(0x71) + EHWPOISON = syscall.Errno(0x85) + EIDRM = syscall.Errno(0x2b) + EILSEQ = syscall.Errno(0x54) + EINPROGRESS = syscall.Errno(0x73) + EISCONN = syscall.Errno(0x6a) + EISNAM = syscall.Errno(0x78) + EKEYEXPIRED = syscall.Errno(0x7f) + EKEYREJECTED = syscall.Errno(0x81) + EKEYREVOKED = syscall.Errno(0x80) + EL2HLT = syscall.Errno(0x33) + EL2NSYNC = syscall.Errno(0x2d) + EL3HLT = syscall.Errno(0x2e) + EL3RST = syscall.Errno(0x2f) + ELIBACC = syscall.Errno(0x4f) + ELIBBAD = syscall.Errno(0x50) + ELIBEXEC = syscall.Errno(0x53) + ELIBMAX = syscall.Errno(0x52) + ELIBSCN = syscall.Errno(0x51) + ELNRNG = syscall.Errno(0x30) + ELOOP = syscall.Errno(0x28) + EMEDIUMTYPE = syscall.Errno(0x7c) + EMSGSIZE = syscall.Errno(0x5a) + EMULTIHOP = syscall.Errno(0x48) + ENAMETOOLONG = syscall.Errno(0x24) + ENAVAIL = syscall.Errno(0x77) + ENETDOWN = syscall.Errno(0x64) + ENETRESET = syscall.Errno(0x66) + ENETUNREACH = syscall.Errno(0x65) + ENOANO = syscall.Errno(0x37) + ENOBUFS = syscall.Errno(0x69) + ENOCSI = syscall.Errno(0x32) + ENODATA = syscall.Errno(0x3d) + ENOKEY = syscall.Errno(0x7e) + ENOLCK = syscall.Errno(0x25) + ENOLINK = syscall.Errno(0x43) + ENOMEDIUM = syscall.Errno(0x7b) + ENOMSG = syscall.Errno(0x2a) + ENONET = syscall.Errno(0x40) + ENOPKG = syscall.Errno(0x41) + ENOPROTOOPT = syscall.Errno(0x5c) + ENOSR = syscall.Errno(0x3f) + ENOSTR = syscall.Errno(0x3c) + ENOSYS = syscall.Errno(0x26) + ENOTCONN = syscall.Errno(0x6b) + ENOTEMPTY = syscall.Errno(0x27) + ENOTNAM = syscall.Errno(0x76) + ENOTRECOVERABLE = syscall.Errno(0x83) + ENOTSOCK = syscall.Errno(0x58) + ENOTSUP = syscall.Errno(0x5f) + ENOTUNIQ = syscall.Errno(0x4c) + EOPNOTSUPP = syscall.Errno(0x5f) + EOVERFLOW = syscall.Errno(0x4b) + EOWNERDEAD = syscall.Errno(0x82) + EPFNOSUPPORT = syscall.Errno(0x60) + EPROTO = syscall.Errno(0x47) + EPROTONOSUPPORT = syscall.Errno(0x5d) + EPROTOTYPE = syscall.Errno(0x5b) + EREMCHG = syscall.Errno(0x4e) + EREMOTE = syscall.Errno(0x42) + EREMOTEIO = syscall.Errno(0x79) + ERESTART = syscall.Errno(0x55) + ERFKILL = syscall.Errno(0x84) + ESHUTDOWN = syscall.Errno(0x6c) + ESOCKTNOSUPPORT = syscall.Errno(0x5e) + ESRMNT = syscall.Errno(0x45) + ESTALE = syscall.Errno(0x74) + ESTRPIPE = syscall.Errno(0x56) + ETIME = syscall.Errno(0x3e) + ETIMEDOUT = syscall.Errno(0x6e) + ETOOMANYREFS = syscall.Errno(0x6d) + EUCLEAN = syscall.Errno(0x75) + EUNATCH = syscall.Errno(0x31) + EUSERS = syscall.Errno(0x57) + EXFULL = syscall.Errno(0x36) +) + +// Signals +const ( + SIGBUS = syscall.Signal(0x7) + SIGCHLD = syscall.Signal(0x11) + SIGCLD = syscall.Signal(0x11) + SIGCONT = syscall.Signal(0x12) + SIGIO = syscall.Signal(0x1d) + SIGPOLL = syscall.Signal(0x1d) + SIGPROF = syscall.Signal(0x1b) + SIGPWR = syscall.Signal(0x1e) + SIGSTKFLT = syscall.Signal(0x10) + SIGSTOP = syscall.Signal(0x13) + SIGSYS = syscall.Signal(0x1f) + SIGTSTP = syscall.Signal(0x14) + SIGTTIN = syscall.Signal(0x15) + SIGTTOU = syscall.Signal(0x16) + SIGURG = syscall.Signal(0x17) + SIGUSR1 = syscall.Signal(0xa) + SIGUSR2 = syscall.Signal(0xc) + SIGVTALRM = syscall.Signal(0x1a) + SIGWINCH = syscall.Signal(0x1c) + SIGXCPU = syscall.Signal(0x18) + SIGXFSZ = syscall.Signal(0x19) +) + +// Error table +var errorList = [...]struct { + num syscall.Errno + name string + desc string +}{ + {1, "EPERM", "operation not permitted"}, + {2, "ENOENT", "no such file or directory"}, + {3, "ESRCH", "no such process"}, + {4, "EINTR", "interrupted system call"}, + {5, "EIO", "input/output error"}, + {6, "ENXIO", "no such device or address"}, + {7, "E2BIG", "argument list too long"}, + {8, "ENOEXEC", "exec format error"}, + {9, "EBADF", "bad file descriptor"}, + {10, "ECHILD", "no child processes"}, + {11, "EAGAIN", "resource temporarily unavailable"}, + {12, "ENOMEM", "cannot allocate memory"}, + {13, "EACCES", "permission denied"}, + {14, "EFAULT", "bad address"}, + {15, "ENOTBLK", "block device required"}, + {16, "EBUSY", "device or resource busy"}, + {17, "EEXIST", "file exists"}, + {18, "EXDEV", "invalid cross-device link"}, + {19, "ENODEV", "no such device"}, + {20, "ENOTDIR", "not a directory"}, + {21, "EISDIR", "is a directory"}, + {22, "EINVAL", "invalid argument"}, + {23, "ENFILE", "too many open files in system"}, + {24, "EMFILE", "too many open files"}, + {25, "ENOTTY", "inappropriate ioctl for device"}, + {26, "ETXTBSY", "text file busy"}, + {27, "EFBIG", "file too large"}, + {28, "ENOSPC", "no space left on device"}, + {29, "ESPIPE", "illegal seek"}, + {30, "EROFS", "read-only file system"}, + {31, "EMLINK", "too many links"}, + {32, "EPIPE", "broken pipe"}, + {33, "EDOM", "numerical argument out of domain"}, + {34, "ERANGE", "numerical result out of range"}, + {35, "EDEADLK", "resource deadlock avoided"}, + {36, "ENAMETOOLONG", "file name too long"}, + {37, "ENOLCK", "no locks available"}, + {38, "ENOSYS", "function not implemented"}, + {39, "ENOTEMPTY", "directory not empty"}, + {40, "ELOOP", "too many levels of symbolic links"}, + {42, "ENOMSG", "no message of desired type"}, + {43, "EIDRM", "identifier removed"}, + {44, "ECHRNG", "channel number out of range"}, + {45, "EL2NSYNC", "level 2 not synchronized"}, + {46, "EL3HLT", "level 3 halted"}, + {47, "EL3RST", "level 3 reset"}, + {48, "ELNRNG", "link number out of range"}, + {49, "EUNATCH", "protocol driver not attached"}, + {50, "ENOCSI", "no CSI structure available"}, + {51, "EL2HLT", "level 2 halted"}, + {52, "EBADE", "invalid exchange"}, + {53, "EBADR", "invalid request descriptor"}, + {54, "EXFULL", "exchange full"}, + {55, "ENOANO", "no anode"}, + {56, "EBADRQC", "invalid request code"}, + {57, "EBADSLT", "invalid slot"}, + {59, "EBFONT", "bad font file format"}, + {60, "ENOSTR", "device not a stream"}, + {61, "ENODATA", "no data available"}, + {62, "ETIME", "timer expired"}, + {63, "ENOSR", "out of streams resources"}, + {64, "ENONET", "machine is not on the network"}, + {65, "ENOPKG", "package not installed"}, + {66, "EREMOTE", "object is remote"}, + {67, "ENOLINK", "link has been severed"}, + {68, "EADV", "advertise error"}, + {69, "ESRMNT", "srmount error"}, + {70, "ECOMM", "communication error on send"}, + {71, "EPROTO", "protocol error"}, + {72, "EMULTIHOP", "multihop attempted"}, + {73, "EDOTDOT", "RFS specific error"}, + {74, "EBADMSG", "bad message"}, + {75, "EOVERFLOW", "value too large for defined data type"}, + {76, "ENOTUNIQ", "name not unique on network"}, + {77, "EBADFD", "file descriptor in bad state"}, + {78, "EREMCHG", "remote address changed"}, + {79, "ELIBACC", "can not access a needed shared library"}, + {80, "ELIBBAD", "accessing a corrupted shared library"}, + {81, "ELIBSCN", ".lib section in a.out corrupted"}, + {82, "ELIBMAX", "attempting to link in too many shared libraries"}, + {83, "ELIBEXEC", "cannot exec a shared library directly"}, + {84, "EILSEQ", "invalid or incomplete multibyte or wide character"}, + {85, "ERESTART", "interrupted system call should be restarted"}, + {86, "ESTRPIPE", "streams pipe error"}, + {87, "EUSERS", "too many users"}, + {88, "ENOTSOCK", "socket operation on non-socket"}, + {89, "EDESTADDRREQ", "destination address required"}, + {90, "EMSGSIZE", "message too long"}, + {91, "EPROTOTYPE", "protocol wrong type for socket"}, + {92, "ENOPROTOOPT", "protocol not available"}, + {93, "EPROTONOSUPPORT", "protocol not supported"}, + {94, "ESOCKTNOSUPPORT", "socket type not supported"}, + {95, "ENOTSUP", "operation not supported"}, + {96, "EPFNOSUPPORT", "protocol family not supported"}, + {97, "EAFNOSUPPORT", "address family not supported by protocol"}, + {98, "EADDRINUSE", "address already in use"}, + {99, "EADDRNOTAVAIL", "cannot assign requested address"}, + {100, "ENETDOWN", "network is down"}, + {101, "ENETUNREACH", "network is unreachable"}, + {102, "ENETRESET", "network dropped connection on reset"}, + {103, "ECONNABORTED", "software caused connection abort"}, + {104, "ECONNRESET", "connection reset by peer"}, + {105, "ENOBUFS", "no buffer space available"}, + {106, "EISCONN", "transport endpoint is already connected"}, + {107, "ENOTCONN", "transport endpoint is not connected"}, + {108, "ESHUTDOWN", "cannot send after transport endpoint shutdown"}, + {109, "ETOOMANYREFS", "too many references: cannot splice"}, + {110, "ETIMEDOUT", "connection timed out"}, + {111, "ECONNREFUSED", "connection refused"}, + {112, "EHOSTDOWN", "host is down"}, + {113, "EHOSTUNREACH", "no route to host"}, + {114, "EALREADY", "operation already in progress"}, + {115, "EINPROGRESS", "operation now in progress"}, + {116, "ESTALE", "stale file handle"}, + {117, "EUCLEAN", "structure needs cleaning"}, + {118, "ENOTNAM", "not a XENIX named type file"}, + {119, "ENAVAIL", "no XENIX semaphores available"}, + {120, "EISNAM", "is a named type file"}, + {121, "EREMOTEIO", "remote I/O error"}, + {122, "EDQUOT", "disk quota exceeded"}, + {123, "ENOMEDIUM", "no medium found"}, + {124, "EMEDIUMTYPE", "wrong medium type"}, + {125, "ECANCELED", "operation canceled"}, + {126, "ENOKEY", "required key not available"}, + {127, "EKEYEXPIRED", "key has expired"}, + {128, "EKEYREVOKED", "key has been revoked"}, + {129, "EKEYREJECTED", "key was rejected by service"}, + {130, "EOWNERDEAD", "owner died"}, + {131, "ENOTRECOVERABLE", "state not recoverable"}, + {132, "ERFKILL", "operation not possible due to RF-kill"}, + {133, "EHWPOISON", "memory page has hardware error"}, +} + +// Signal table +var signalList = [...]struct { + num syscall.Signal + name string + desc string +}{ + {1, "SIGHUP", "hangup"}, + {2, "SIGINT", "interrupt"}, + {3, "SIGQUIT", "quit"}, + {4, "SIGILL", "illegal instruction"}, + {5, "SIGTRAP", "trace/breakpoint trap"}, + {6, "SIGABRT", "aborted"}, + {7, "SIGBUS", "bus error"}, + {8, "SIGFPE", "floating point exception"}, + {9, "SIGKILL", "killed"}, + {10, "SIGUSR1", "user defined signal 1"}, + {11, "SIGSEGV", "segmentation fault"}, + {12, "SIGUSR2", "user defined signal 2"}, + {13, "SIGPIPE", "broken pipe"}, + {14, "SIGALRM", "alarm clock"}, + {15, "SIGTERM", "terminated"}, + {16, "SIGSTKFLT", "stack fault"}, + {17, "SIGCHLD", "child exited"}, + {18, "SIGCONT", "continued"}, + {19, "SIGSTOP", "stopped (signal)"}, + {20, "SIGTSTP", "stopped"}, + {21, "SIGTTIN", "stopped (tty input)"}, + {22, "SIGTTOU", "stopped (tty output)"}, + {23, "SIGURG", "urgent I/O condition"}, + {24, "SIGXCPU", "CPU time limit exceeded"}, + {25, "SIGXFSZ", "file size limit exceeded"}, + {26, "SIGVTALRM", "virtual timer expired"}, + {27, "SIGPROF", "profiling timer expired"}, + {28, "SIGWINCH", "window changed"}, + {29, "SIGIO", "I/O possible"}, + {30, "SIGPWR", "power failure"}, + {31, "SIGSYS", "bad system call"}, +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 7c866b8..553c1c6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/mips/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips,linux +//go:build mips && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/mips/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40041270 BLKBSZSET = 0x80041271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40041272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x2000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40046601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80046602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0x21 F_GETLK64 = 0x21 @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x18 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 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 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -184,8 +237,23 @@ const ( PPPIOCSPASS = 0x80087447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + 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 @@ -218,6 +286,8 @@ const ( RTC_EPOCH_SET = 0x8004700e RTC_IRQP_READ = 0x4004700b RTC_IRQP_SET = 0x8004700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x401c7011 @@ -232,12 +302,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 @@ -261,10 +337,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -276,21 +357,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1e + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x1028 SO_RCVBUF = 0x1002 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 @@ -312,6 +401,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_WIFI_STATUS = 0x29 @@ -337,6 +427,8 @@ const ( TCSETSW = 0x540f TCSETSW2 = 0x8030542c TCXONC = 0x5406 + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x80 TIOCCBRK = 0x5428 TIOCCONS = 0x80047478 TIOCEXCL = 0x740d @@ -475,6 +567,9 @@ const ( WORDSIZE = 0x20 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index c42966d..b3339f2 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/mips64/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips64,linux +//go:build mips64 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/mips64/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40081270 BLKBSZSET = 0x80081271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40081272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x2000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0xe F_GETLK64 = 0xe @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x18 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 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 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -184,8 +237,23 @@ const ( PPPIOCSPASS = 0x80107447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + 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 @@ -218,6 +286,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -232,12 +302,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 @@ -261,10 +337,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -276,21 +357,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1e + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x1028 SO_RCVBUF = 0x1002 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 @@ -312,6 +401,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_WIFI_STATUS = 0x29 @@ -337,6 +427,8 @@ const ( TCSETSW = 0x540f TCSETSW2 = 0x8030542c TCXONC = 0x5406 + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x80 TIOCCBRK = 0x5428 TIOCCONS = 0x80047478 TIOCEXCL = 0x740d @@ -475,6 +567,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index a5b2b42..177091d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/mips64le/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips64le,linux +//go:build mips64le && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/mips64le/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40081270 BLKBSZSET = 0x80081271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40081272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x2000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0xe F_GETLK64 = 0xe @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x18 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 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 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -184,8 +237,23 @@ const ( PPPIOCSPASS = 0x80107447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + 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 @@ -218,6 +286,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -232,12 +302,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 @@ -261,10 +337,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -276,21 +357,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1e + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x1028 SO_RCVBUF = 0x1002 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 @@ -312,6 +401,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_WIFI_STATUS = 0x29 @@ -337,6 +427,8 @@ const ( TCSETSW = 0x540f TCSETSW2 = 0x8030542c TCXONC = 0x5406 + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x80 TIOCCBRK = 0x5428 TIOCCONS = 0x80047478 TIOCEXCL = 0x740d @@ -475,6 +567,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 7f91881..c5abf15 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/mipsle/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mipsle,linux +//go:build mipsle && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/mipsle/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40041270 BLKBSZSET = 0x80041271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40041272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x2000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40046601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80046602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0x21 F_GETLK64 = 0x21 @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x18 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 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 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -184,8 +237,23 @@ const ( PPPIOCSPASS = 0x80087447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + 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 @@ -218,6 +286,8 @@ const ( RTC_EPOCH_SET = 0x8004700e RTC_IRQP_READ = 0x4004700b RTC_IRQP_SET = 0x8004700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x401c7011 @@ -232,12 +302,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 @@ -261,10 +337,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -276,21 +357,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x12 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1e + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x1028 SO_RCVBUF = 0x1002 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x1004 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 @@ -312,6 +401,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x1008 SO_WIFI_STATUS = 0x29 @@ -337,6 +427,8 @@ const ( TCSETSW = 0x540f TCSETSW2 = 0x8030542c TCXONC = 0x5406 + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x80 TIOCCBRK = 0x5428 TIOCCONS = 0x80047478 TIOCEXCL = 0x740d @@ -475,6 +567,9 @@ const ( WORDSIZE = 0x20 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go new file mode 100644 index 0000000..f1f3fad --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -0,0 +1,936 @@ +// mkerrors.sh -Wall -Werror -static -I/tmp/ppc/include +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build ppc && linux + +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs -- -Wall -Werror -static -I/tmp/ppc/include _const.go + +package unix + +import "syscall" + +const ( + B1000000 = 0x17 + B115200 = 0x11 + B1152000 = 0x18 + B1500000 = 0x19 + B2000000 = 0x1a + B230400 = 0x12 + B2500000 = 0x1b + B3000000 = 0x1c + B3500000 = 0x1d + B4000000 = 0x1e + B460800 = 0x13 + B500000 = 0x14 + B57600 = 0x10 + B576000 = 0x15 + B921600 = 0x16 + BLKALIGNOFF = 0x2000127a + BLKBSZGET = 0x40041270 + BLKBSZSET = 0x80041271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c + BLKFLSBUF = 0x20001261 + BLKFRAGET = 0x20001265 + BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 + BLKGETSIZE = 0x20001260 + BLKGETSIZE64 = 0x40041272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 + BLKPBSZGET = 0x2000127b + BLKRAGET = 0x20001263 + BLKRASET = 0x20001262 + BLKROGET = 0x2000125e + BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e + BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d + BLKSECTGET = 0x20001267 + BLKSECTSET = 0x20001266 + BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f + BOTHER = 0x1f + BS1 = 0x8000 + BSDLY = 0x8000 + CBAUD = 0xff + CBAUDEX = 0x0 + CIBAUD = 0xff0000 + CLOCAL = 0x8000 + CR1 = 0x1000 + CR2 = 0x2000 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EFD_CLOEXEC = 0x80000 + EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 + EPOLL_CLOEXEC = 0x80000 + EXTPROC = 0x10000000 + FF1 = 0x4000 + FFDLY = 0x4000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d + FLUSHO = 0x800000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40046601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b + FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 + FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80046602 + FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 + F_GETLK = 0xc + F_GETLK64 = 0xc + F_GETOWN = 0x9 + F_RDLCK = 0x0 + F_SETLK = 0xd + F_SETLK64 = 0xd + F_SETLKW = 0xe + F_SETLKW64 = 0xe + F_SETOWN = 0x8 + F_UNLCK = 0x2 + F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d + HUPCL = 0x4000 + ICANON = 0x100 + IEXTEN = 0x400 + IN_CLOEXEC = 0x80000 + IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff + ISIG = 0x80 + IUCLC = 0x1000 + IXOFF = 0x400 + IXON = 0x200 + MAP_ANON = 0x20 + MAP_ANONYMOUS = 0x20 + MAP_DENYWRITE = 0x800 + MAP_EXECUTABLE = 0x1000 + MAP_GROWSDOWN = 0x100 + MAP_HUGETLB = 0x40000 + MAP_LOCKED = 0x80 + MAP_NONBLOCK = 0x10000 + MAP_NORESERVE = 0x40 + MAP_POPULATE = 0x8000 + MAP_STACK = 0x20000 + MAP_SYNC = 0x80000 + MCL_CURRENT = 0x2000 + MCL_FUTURE = 0x4000 + MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 + NFDBITS = 0x20 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + 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 = 0x4 + ONLCR = 0x2 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d + O_APPEND = 0x400 + O_ASYNC = 0x2000 + O_CLOEXEC = 0x80000 + O_CREAT = 0x40 + O_DIRECT = 0x20000 + O_DIRECTORY = 0x4000 + O_DSYNC = 0x1000 + O_EXCL = 0x80 + O_FSYNC = 0x101000 + O_LARGEFILE = 0x10000 + O_NDELAY = 0x800 + O_NOATIME = 0x40000 + O_NOCTTY = 0x100 + O_NOFOLLOW = 0x8000 + O_NONBLOCK = 0x800 + O_PATH = 0x200000 + O_RSYNC = 0x101000 + O_SYNC = 0x101000 + O_TMPFILE = 0x404000 + O_TRUNC = 0x200 + PARENB = 0x1000 + PARODD = 0x2000 + PENDIN = 0x20000000 + PERF_EVENT_IOC_DISABLE = 0x20002401 + PERF_EVENT_IOC_ENABLE = 0x20002400 + PERF_EVENT_IOC_ID = 0x40042407 + PERF_EVENT_IOC_MODIFY_ATTRIBUTES = 0x8004240b + PERF_EVENT_IOC_PAUSE_OUTPUT = 0x80042409 + PERF_EVENT_IOC_PERIOD = 0x80082404 + PERF_EVENT_IOC_QUERY_BPF = 0xc004240a + PERF_EVENT_IOC_REFRESH = 0x20002402 + PERF_EVENT_IOC_RESET = 0x20002403 + PERF_EVENT_IOC_SET_BPF = 0x80042408 + PERF_EVENT_IOC_SET_FILTER = 0x80042406 + PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 + PPPIOCATTACH = 0x8004743d + PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 + PPPIOCCONNECT = 0x8004743a + PPPIOCDETACH = 0x8004743c + PPPIOCDISCONN = 0x20007439 + PPPIOCGASYNCMAP = 0x40047458 + PPPIOCGCHAN = 0x40047437 + PPPIOCGDEBUG = 0x40047441 + PPPIOCGFLAGS = 0x4004745a + PPPIOCGIDLE = 0x4008743f + PPPIOCGIDLE32 = 0x4008743f + PPPIOCGIDLE64 = 0x4010743f + PPPIOCGL2TPSTATS = 0x40487436 + PPPIOCGMRU = 0x40047453 + PPPIOCGRASYNCMAP = 0x40047455 + PPPIOCGUNIT = 0x40047456 + PPPIOCGXASYNCMAP = 0x40207450 + PPPIOCSACTIVE = 0x80087446 + PPPIOCSASYNCMAP = 0x80047457 + PPPIOCSCOMPRESS = 0x800c744d + PPPIOCSDEBUG = 0x80047440 + PPPIOCSFLAGS = 0x80047459 + PPPIOCSMAXCID = 0x80047451 + PPPIOCSMRRU = 0x8004743b + PPPIOCSMRU = 0x80047452 + PPPIOCSNPMODE = 0x8008744b + PPPIOCSPASS = 0x80087447 + PPPIOCSRASYNCMAP = 0x80047454 + PPPIOCSXASYNCMAP = 0x8020744f + PPPIOCUNBRIDGECHAN = 0x20007434 + PPPIOCXFERUNIT = 0x2000744e + PROT_SAO = 0x10 + 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_GETEVRREGS = 0x14 + PTRACE_GETFPREGS = 0xe + PTRACE_GETREGS64 = 0x16 + PTRACE_GETVRREGS = 0x12 + PTRACE_GETVSRREGS = 0x1b + PTRACE_GET_DEBUGREG = 0x19 + PTRACE_SETEVRREGS = 0x15 + PTRACE_SETFPREGS = 0xf + PTRACE_SETREGS64 = 0x17 + PTRACE_SETVRREGS = 0x13 + PTRACE_SETVSRREGS = 0x1c + PTRACE_SET_DEBUGREG = 0x1a + PTRACE_SINGLEBLOCK = 0x100 + PTRACE_SYSEMU = 0x1d + PTRACE_SYSEMU_SINGLESTEP = 0x1e + PT_CCR = 0x26 + PT_CTR = 0x23 + PT_DAR = 0x29 + PT_DSCR = 0x2c + PT_DSISR = 0x2a + PT_FPR0 = 0x30 + PT_FPR31 = 0x6e + PT_FPSCR = 0x71 + PT_LNK = 0x24 + PT_MQ = 0x27 + PT_MSR = 0x21 + PT_NIP = 0x20 + PT_ORIG_R3 = 0x22 + PT_R0 = 0x0 + PT_R1 = 0x1 + PT_R10 = 0xa + PT_R11 = 0xb + PT_R12 = 0xc + PT_R13 = 0xd + PT_R14 = 0xe + PT_R15 = 0xf + PT_R16 = 0x10 + PT_R17 = 0x11 + PT_R18 = 0x12 + PT_R19 = 0x13 + PT_R2 = 0x2 + PT_R20 = 0x14 + PT_R21 = 0x15 + PT_R22 = 0x16 + PT_R23 = 0x17 + PT_R24 = 0x18 + PT_R25 = 0x19 + PT_R26 = 0x1a + PT_R27 = 0x1b + PT_R28 = 0x1c + PT_R29 = 0x1d + PT_R3 = 0x3 + PT_R30 = 0x1e + PT_R31 = 0x1f + PT_R4 = 0x4 + PT_R5 = 0x5 + PT_R6 = 0x6 + PT_R7 = 0x7 + PT_R8 = 0x8 + PT_R9 = 0x9 + PT_REGS_COUNT = 0x2c + PT_RESULT = 0x2b + PT_TRAP = 0x28 + PT_XER = 0x25 + RLIMIT_AS = 0x9 + RLIMIT_MEMLOCK = 0x8 + RLIMIT_NOFILE = 0x7 + RLIMIT_NPROC = 0x6 + RLIMIT_RSS = 0x5 + RNDADDENTROPY = 0x80085203 + RNDADDTOENTCNT = 0x80045201 + RNDCLEARPOOL = 0x20005206 + RNDGETENTCNT = 0x40045200 + RNDGETPOOL = 0x40085202 + RNDRESEEDCRNG = 0x20005207 + RNDZAPENTCNT = 0x20005204 + RTC_AIE_OFF = 0x20007002 + RTC_AIE_ON = 0x20007001 + RTC_ALM_READ = 0x40247008 + RTC_ALM_SET = 0x80247007 + RTC_EPOCH_READ = 0x4004700d + RTC_EPOCH_SET = 0x8004700e + RTC_IRQP_READ = 0x4004700b + RTC_IRQP_SET = 0x8004700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 + RTC_PIE_OFF = 0x20007006 + RTC_PIE_ON = 0x20007005 + RTC_PLL_GET = 0x401c7011 + RTC_PLL_SET = 0x801c7012 + RTC_RD_TIME = 0x40247009 + RTC_SET_TIME = 0x8024700a + RTC_UIE_OFF = 0x20007004 + RTC_UIE_ON = 0x20007003 + RTC_VL_CLR = 0x20007014 + RTC_VL_READ = 0x40047013 + RTC_WIE_OFF = 0x20007010 + 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 + SFD_CLOEXEC = 0x80000 + SFD_NONBLOCK = 0x800 + SIOCATMARK = 0x8905 + SIOCGPGRP = 0x8904 + SIOCGSTAMPNS_NEW = 0x40108907 + SIOCGSTAMP_NEW = 0x40108906 + SIOCINQ = 0x4004667f + SIOCOUTQ = 0x40047473 + SIOCSPGRP = 0x8902 + SOCK_CLOEXEC = 0x80000 + SOCK_DGRAM = 0x2 + SOCK_NONBLOCK = 0x800 + SOCK_STREAM = 0x1 + SOL_SOCKET = 0x1 + SO_ACCEPTCONN = 0x1e + SO_ATTACH_BPF = 0x32 + SO_ATTACH_REUSEPORT_CBPF = 0x33 + SO_ATTACH_REUSEPORT_EBPF = 0x34 + SO_BINDTODEVICE = 0x19 + SO_BINDTOIFINDEX = 0x3e + SO_BPF_EXTENSIONS = 0x30 + SO_BROADCAST = 0x6 + SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 + SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 + 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 + SO_INCOMING_CPU = 0x31 + SO_INCOMING_NAPI_ID = 0x38 + SO_KEEPALIVE = 0x9 + SO_LINGER = 0xd + SO_LOCK_FILTER = 0x2c + SO_MARK = 0x24 + SO_MAX_PACING_RATE = 0x2f + SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 + SO_NOFCS = 0x2b + SO_OOBINLINE = 0xa + SO_PASSCRED = 0x14 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 + SO_PASSSEC = 0x22 + SO_PEEK_OFF = 0x2a + SO_PEERCRED = 0x15 + SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d + SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 + SO_PROTOCOL = 0x26 + SO_RCVBUF = 0x8 + SO_RCVBUFFORCE = 0x21 + SO_RCVLOWAT = 0x10 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 + SO_RCVTIMEO = 0x12 + SO_RCVTIMEO_NEW = 0x42 + SO_RCVTIMEO_OLD = 0x12 + SO_RESERVE_MEM = 0x49 + SO_REUSEADDR = 0x2 + SO_REUSEPORT = 0xf + SO_RXQ_OVFL = 0x28 + SO_SECURITY_AUTHENTICATION = 0x16 + SO_SECURITY_ENCRYPTION_NETWORK = 0x18 + SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17 + SO_SELECT_ERR_QUEUE = 0x2d + SO_SNDBUF = 0x7 + SO_SNDBUFFORCE = 0x20 + SO_SNDLOWAT = 0x11 + SO_SNDTIMEO = 0x13 + SO_SNDTIMEO_NEW = 0x43 + SO_SNDTIMEO_OLD = 0x13 + SO_TIMESTAMPING = 0x25 + SO_TIMESTAMPING_NEW = 0x41 + SO_TIMESTAMPING_OLD = 0x25 + SO_TIMESTAMPNS = 0x23 + SO_TIMESTAMPNS_NEW = 0x40 + SO_TIMESTAMPNS_OLD = 0x23 + SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a + SO_TXTIME = 0x3d + SO_TYPE = 0x3 + SO_WIFI_STATUS = 0x29 + SO_ZEROCOPY = 0x3c + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0xc00 + TABDLY = 0xc00 + TCFLSH = 0x2000741f + TCGETA = 0x40147417 + TCGETS = 0x402c7413 + TCSAFLUSH = 0x2 + TCSBRK = 0x2000741d + TCSBRKP = 0x5425 + TCSETA = 0x80147418 + TCSETAF = 0x8014741c + TCSETAW = 0x80147419 + TCSETS = 0x802c7414 + TCSETSF = 0x802c7416 + TCSETSW = 0x802c7415 + TCXONC = 0x2000741e + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 + TIOCCBRK = 0x5428 + TIOCCONS = 0x541d + TIOCEXCL = 0x540c + TIOCGDEV = 0x40045432 + TIOCGETC = 0x40067412 + TIOCGETD = 0x5424 + TIOCGETP = 0x40067408 + TIOCGEXCL = 0x40045440 + TIOCGICOUNT = 0x545d + TIOCGISO7816 = 0x40285442 + TIOCGLCKTRMIOS = 0x5456 + TIOCGLTC = 0x40067474 + TIOCGPGRP = 0x40047477 + TIOCGPKT = 0x40045438 + TIOCGPTLCK = 0x40045439 + TIOCGPTN = 0x40045430 + TIOCGPTPEER = 0x20005441 + TIOCGRS485 = 0x542e + TIOCGSERIAL = 0x541e + TIOCGSID = 0x5429 + TIOCGSOFTCAR = 0x5419 + TIOCGWINSZ = 0x40087468 + TIOCINQ = 0x4004667f + TIOCLINUX = 0x541c + TIOCMBIC = 0x5417 + TIOCMBIS = 0x5416 + TIOCMGET = 0x5415 + TIOCMIWAIT = 0x545c + TIOCMSET = 0x5418 + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_LOOP = 0x8000 + TIOCM_OUT1 = 0x2000 + TIOCM_OUT2 = 0x4000 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x5422 + TIOCNXCL = 0x540d + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x5420 + TIOCSBRK = 0x5427 + TIOCSCTTY = 0x540e + TIOCSERCONFIG = 0x5453 + TIOCSERGETLSR = 0x5459 + TIOCSERGETMULTI = 0x545a + TIOCSERGSTRUCT = 0x5458 + TIOCSERGWILD = 0x5454 + TIOCSERSETMULTI = 0x545b + TIOCSERSWILD = 0x5455 + TIOCSER_TEMT = 0x1 + TIOCSETC = 0x80067411 + TIOCSETD = 0x5423 + TIOCSETN = 0x8006740a + TIOCSETP = 0x80067409 + TIOCSIG = 0x80045436 + TIOCSISO7816 = 0xc0285443 + TIOCSLCKTRMIOS = 0x5457 + TIOCSLTC = 0x80067475 + TIOCSPGRP = 0x80047476 + TIOCSPTLCK = 0x80045431 + TIOCSRS485 = 0x542f + TIOCSSERIAL = 0x541f + TIOCSSOFTCAR = 0x541a + TIOCSTART = 0x2000746e + TIOCSTI = 0x5412 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCVHANGUP = 0x5437 + TOSTOP = 0x400000 + TUNATTACHFILTER = 0x800854d5 + TUNDETACHFILTER = 0x800854d6 + TUNGETDEVNETNS = 0x200054e3 + TUNGETFEATURES = 0x400454cf + TUNGETFILTER = 0x400854db + TUNGETIFF = 0x400454d2 + TUNGETSNDBUF = 0x400454d3 + TUNGETVNETBE = 0x400454df + TUNGETVNETHDRSZ = 0x400454d7 + TUNGETVNETLE = 0x400454dd + TUNSETCARRIER = 0x800454e2 + TUNSETDEBUG = 0x800454c9 + TUNSETFILTEREBPF = 0x400454e1 + TUNSETGROUP = 0x800454ce + TUNSETIFF = 0x800454ca + TUNSETIFINDEX = 0x800454da + TUNSETLINK = 0x800454cd + TUNSETNOCSUM = 0x800454c8 + TUNSETOFFLOAD = 0x800454d0 + TUNSETOWNER = 0x800454cc + TUNSETPERSIST = 0x800454cb + TUNSETQUEUE = 0x800454d9 + TUNSETSNDBUF = 0x800454d4 + TUNSETSTEERINGEBPF = 0x400454e0 + TUNSETTXFILTER = 0x800454d1 + TUNSETVNETBE = 0x800454de + TUNSETVNETHDRSZ = 0x800454d8 + TUNSETVNETLE = 0x800454dc + UBI_IOCATT = 0x80186f40 + UBI_IOCDET = 0x80046f41 + UBI_IOCEBCH = 0x80044f02 + UBI_IOCEBER = 0x80044f01 + UBI_IOCEBISMAP = 0x40044f05 + UBI_IOCEBMAP = 0x80084f03 + UBI_IOCEBUNMAP = 0x80044f04 + UBI_IOCMKVOL = 0x80986f00 + UBI_IOCRMVOL = 0x80046f01 + UBI_IOCRNVOL = 0x91106f03 + UBI_IOCRPEB = 0x80046f04 + UBI_IOCRSVOL = 0x800c6f02 + UBI_IOCSETVOLPROP = 0x80104f06 + UBI_IOCSPEB = 0x80046f05 + UBI_IOCVOLCRBLK = 0x80804f07 + UBI_IOCVOLRMBLK = 0x20004f08 + UBI_IOCVOLUP = 0x80084f00 + VDISCARD = 0x10 + VEOF = 0x4 + VEOL = 0x6 + VEOL2 = 0x8 + VMIN = 0x5 + VREPRINT = 0xb + VSTART = 0xd + VSTOP = 0xe + VSUSP = 0xc + VSWTC = 0x9 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x7 + VWERASE = 0xa + WDIOC_GETBOOTSTATUS = 0x40045702 + WDIOC_GETPRETIMEOUT = 0x40045709 + WDIOC_GETSTATUS = 0x40045701 + WDIOC_GETSUPPORT = 0x40285700 + WDIOC_GETTEMP = 0x40045703 + WDIOC_GETTIMELEFT = 0x4004570a + WDIOC_GETTIMEOUT = 0x40045707 + WDIOC_KEEPALIVE = 0x40045705 + WDIOC_SETOPTIONS = 0x40045704 + WORDSIZE = 0x20 + XCASE = 0x4000 + XTABS = 0xc00 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 +) + +// Errors +const ( + EADDRINUSE = syscall.Errno(0x62) + EADDRNOTAVAIL = syscall.Errno(0x63) + EADV = syscall.Errno(0x44) + EAFNOSUPPORT = syscall.Errno(0x61) + EALREADY = syscall.Errno(0x72) + EBADE = syscall.Errno(0x34) + EBADFD = syscall.Errno(0x4d) + EBADMSG = syscall.Errno(0x4a) + EBADR = syscall.Errno(0x35) + EBADRQC = syscall.Errno(0x38) + EBADSLT = syscall.Errno(0x39) + EBFONT = syscall.Errno(0x3b) + ECANCELED = syscall.Errno(0x7d) + ECHRNG = syscall.Errno(0x2c) + ECOMM = syscall.Errno(0x46) + ECONNABORTED = syscall.Errno(0x67) + ECONNREFUSED = syscall.Errno(0x6f) + ECONNRESET = syscall.Errno(0x68) + EDEADLK = syscall.Errno(0x23) + EDEADLOCK = syscall.Errno(0x3a) + EDESTADDRREQ = syscall.Errno(0x59) + EDOTDOT = syscall.Errno(0x49) + EDQUOT = syscall.Errno(0x7a) + EHOSTDOWN = syscall.Errno(0x70) + EHOSTUNREACH = syscall.Errno(0x71) + EHWPOISON = syscall.Errno(0x85) + EIDRM = syscall.Errno(0x2b) + EILSEQ = syscall.Errno(0x54) + EINPROGRESS = syscall.Errno(0x73) + EISCONN = syscall.Errno(0x6a) + EISNAM = syscall.Errno(0x78) + EKEYEXPIRED = syscall.Errno(0x7f) + EKEYREJECTED = syscall.Errno(0x81) + EKEYREVOKED = syscall.Errno(0x80) + EL2HLT = syscall.Errno(0x33) + EL2NSYNC = syscall.Errno(0x2d) + EL3HLT = syscall.Errno(0x2e) + EL3RST = syscall.Errno(0x2f) + ELIBACC = syscall.Errno(0x4f) + ELIBBAD = syscall.Errno(0x50) + ELIBEXEC = syscall.Errno(0x53) + ELIBMAX = syscall.Errno(0x52) + ELIBSCN = syscall.Errno(0x51) + ELNRNG = syscall.Errno(0x30) + ELOOP = syscall.Errno(0x28) + EMEDIUMTYPE = syscall.Errno(0x7c) + EMSGSIZE = syscall.Errno(0x5a) + EMULTIHOP = syscall.Errno(0x48) + ENAMETOOLONG = syscall.Errno(0x24) + ENAVAIL = syscall.Errno(0x77) + ENETDOWN = syscall.Errno(0x64) + ENETRESET = syscall.Errno(0x66) + ENETUNREACH = syscall.Errno(0x65) + ENOANO = syscall.Errno(0x37) + ENOBUFS = syscall.Errno(0x69) + ENOCSI = syscall.Errno(0x32) + ENODATA = syscall.Errno(0x3d) + ENOKEY = syscall.Errno(0x7e) + ENOLCK = syscall.Errno(0x25) + ENOLINK = syscall.Errno(0x43) + ENOMEDIUM = syscall.Errno(0x7b) + ENOMSG = syscall.Errno(0x2a) + ENONET = syscall.Errno(0x40) + ENOPKG = syscall.Errno(0x41) + ENOPROTOOPT = syscall.Errno(0x5c) + ENOSR = syscall.Errno(0x3f) + ENOSTR = syscall.Errno(0x3c) + ENOSYS = syscall.Errno(0x26) + ENOTCONN = syscall.Errno(0x6b) + ENOTEMPTY = syscall.Errno(0x27) + ENOTNAM = syscall.Errno(0x76) + ENOTRECOVERABLE = syscall.Errno(0x83) + ENOTSOCK = syscall.Errno(0x58) + ENOTSUP = syscall.Errno(0x5f) + ENOTUNIQ = syscall.Errno(0x4c) + EOPNOTSUPP = syscall.Errno(0x5f) + EOVERFLOW = syscall.Errno(0x4b) + EOWNERDEAD = syscall.Errno(0x82) + EPFNOSUPPORT = syscall.Errno(0x60) + EPROTO = syscall.Errno(0x47) + EPROTONOSUPPORT = syscall.Errno(0x5d) + EPROTOTYPE = syscall.Errno(0x5b) + EREMCHG = syscall.Errno(0x4e) + EREMOTE = syscall.Errno(0x42) + EREMOTEIO = syscall.Errno(0x79) + ERESTART = syscall.Errno(0x55) + ERFKILL = syscall.Errno(0x84) + ESHUTDOWN = syscall.Errno(0x6c) + ESOCKTNOSUPPORT = syscall.Errno(0x5e) + ESRMNT = syscall.Errno(0x45) + ESTALE = syscall.Errno(0x74) + ESTRPIPE = syscall.Errno(0x56) + ETIME = syscall.Errno(0x3e) + ETIMEDOUT = syscall.Errno(0x6e) + ETOOMANYREFS = syscall.Errno(0x6d) + EUCLEAN = syscall.Errno(0x75) + EUNATCH = syscall.Errno(0x31) + EUSERS = syscall.Errno(0x57) + EXFULL = syscall.Errno(0x36) +) + +// Signals +const ( + SIGBUS = syscall.Signal(0x7) + SIGCHLD = syscall.Signal(0x11) + SIGCLD = syscall.Signal(0x11) + SIGCONT = syscall.Signal(0x12) + SIGIO = syscall.Signal(0x1d) + SIGPOLL = syscall.Signal(0x1d) + SIGPROF = syscall.Signal(0x1b) + SIGPWR = syscall.Signal(0x1e) + SIGSTKFLT = syscall.Signal(0x10) + SIGSTOP = syscall.Signal(0x13) + SIGSYS = syscall.Signal(0x1f) + SIGTSTP = syscall.Signal(0x14) + SIGTTIN = syscall.Signal(0x15) + SIGTTOU = syscall.Signal(0x16) + SIGURG = syscall.Signal(0x17) + SIGUSR1 = syscall.Signal(0xa) + SIGUSR2 = syscall.Signal(0xc) + SIGVTALRM = syscall.Signal(0x1a) + SIGWINCH = syscall.Signal(0x1c) + SIGXCPU = syscall.Signal(0x18) + SIGXFSZ = syscall.Signal(0x19) +) + +// Error table +var errorList = [...]struct { + num syscall.Errno + name string + desc string +}{ + {1, "EPERM", "operation not permitted"}, + {2, "ENOENT", "no such file or directory"}, + {3, "ESRCH", "no such process"}, + {4, "EINTR", "interrupted system call"}, + {5, "EIO", "input/output error"}, + {6, "ENXIO", "no such device or address"}, + {7, "E2BIG", "argument list too long"}, + {8, "ENOEXEC", "exec format error"}, + {9, "EBADF", "bad file descriptor"}, + {10, "ECHILD", "no child processes"}, + {11, "EAGAIN", "resource temporarily unavailable"}, + {12, "ENOMEM", "cannot allocate memory"}, + {13, "EACCES", "permission denied"}, + {14, "EFAULT", "bad address"}, + {15, "ENOTBLK", "block device required"}, + {16, "EBUSY", "device or resource busy"}, + {17, "EEXIST", "file exists"}, + {18, "EXDEV", "invalid cross-device link"}, + {19, "ENODEV", "no such device"}, + {20, "ENOTDIR", "not a directory"}, + {21, "EISDIR", "is a directory"}, + {22, "EINVAL", "invalid argument"}, + {23, "ENFILE", "too many open files in system"}, + {24, "EMFILE", "too many open files"}, + {25, "ENOTTY", "inappropriate ioctl for device"}, + {26, "ETXTBSY", "text file busy"}, + {27, "EFBIG", "file too large"}, + {28, "ENOSPC", "no space left on device"}, + {29, "ESPIPE", "illegal seek"}, + {30, "EROFS", "read-only file system"}, + {31, "EMLINK", "too many links"}, + {32, "EPIPE", "broken pipe"}, + {33, "EDOM", "numerical argument out of domain"}, + {34, "ERANGE", "numerical result out of range"}, + {35, "EDEADLK", "resource deadlock avoided"}, + {36, "ENAMETOOLONG", "file name too long"}, + {37, "ENOLCK", "no locks available"}, + {38, "ENOSYS", "function not implemented"}, + {39, "ENOTEMPTY", "directory not empty"}, + {40, "ELOOP", "too many levels of symbolic links"}, + {42, "ENOMSG", "no message of desired type"}, + {43, "EIDRM", "identifier removed"}, + {44, "ECHRNG", "channel number out of range"}, + {45, "EL2NSYNC", "level 2 not synchronized"}, + {46, "EL3HLT", "level 3 halted"}, + {47, "EL3RST", "level 3 reset"}, + {48, "ELNRNG", "link number out of range"}, + {49, "EUNATCH", "protocol driver not attached"}, + {50, "ENOCSI", "no CSI structure available"}, + {51, "EL2HLT", "level 2 halted"}, + {52, "EBADE", "invalid exchange"}, + {53, "EBADR", "invalid request descriptor"}, + {54, "EXFULL", "exchange full"}, + {55, "ENOANO", "no anode"}, + {56, "EBADRQC", "invalid request code"}, + {57, "EBADSLT", "invalid slot"}, + {58, "EDEADLOCK", "file locking deadlock error"}, + {59, "EBFONT", "bad font file format"}, + {60, "ENOSTR", "device not a stream"}, + {61, "ENODATA", "no data available"}, + {62, "ETIME", "timer expired"}, + {63, "ENOSR", "out of streams resources"}, + {64, "ENONET", "machine is not on the network"}, + {65, "ENOPKG", "package not installed"}, + {66, "EREMOTE", "object is remote"}, + {67, "ENOLINK", "link has been severed"}, + {68, "EADV", "advertise error"}, + {69, "ESRMNT", "srmount error"}, + {70, "ECOMM", "communication error on send"}, + {71, "EPROTO", "protocol error"}, + {72, "EMULTIHOP", "multihop attempted"}, + {73, "EDOTDOT", "RFS specific error"}, + {74, "EBADMSG", "bad message"}, + {75, "EOVERFLOW", "value too large for defined data type"}, + {76, "ENOTUNIQ", "name not unique on network"}, + {77, "EBADFD", "file descriptor in bad state"}, + {78, "EREMCHG", "remote address changed"}, + {79, "ELIBACC", "can not access a needed shared library"}, + {80, "ELIBBAD", "accessing a corrupted shared library"}, + {81, "ELIBSCN", ".lib section in a.out corrupted"}, + {82, "ELIBMAX", "attempting to link in too many shared libraries"}, + {83, "ELIBEXEC", "cannot exec a shared library directly"}, + {84, "EILSEQ", "invalid or incomplete multibyte or wide character"}, + {85, "ERESTART", "interrupted system call should be restarted"}, + {86, "ESTRPIPE", "streams pipe error"}, + {87, "EUSERS", "too many users"}, + {88, "ENOTSOCK", "socket operation on non-socket"}, + {89, "EDESTADDRREQ", "destination address required"}, + {90, "EMSGSIZE", "message too long"}, + {91, "EPROTOTYPE", "protocol wrong type for socket"}, + {92, "ENOPROTOOPT", "protocol not available"}, + {93, "EPROTONOSUPPORT", "protocol not supported"}, + {94, "ESOCKTNOSUPPORT", "socket type not supported"}, + {95, "ENOTSUP", "operation not supported"}, + {96, "EPFNOSUPPORT", "protocol family not supported"}, + {97, "EAFNOSUPPORT", "address family not supported by protocol"}, + {98, "EADDRINUSE", "address already in use"}, + {99, "EADDRNOTAVAIL", "cannot assign requested address"}, + {100, "ENETDOWN", "network is down"}, + {101, "ENETUNREACH", "network is unreachable"}, + {102, "ENETRESET", "network dropped connection on reset"}, + {103, "ECONNABORTED", "software caused connection abort"}, + {104, "ECONNRESET", "connection reset by peer"}, + {105, "ENOBUFS", "no buffer space available"}, + {106, "EISCONN", "transport endpoint is already connected"}, + {107, "ENOTCONN", "transport endpoint is not connected"}, + {108, "ESHUTDOWN", "cannot send after transport endpoint shutdown"}, + {109, "ETOOMANYREFS", "too many references: cannot splice"}, + {110, "ETIMEDOUT", "connection timed out"}, + {111, "ECONNREFUSED", "connection refused"}, + {112, "EHOSTDOWN", "host is down"}, + {113, "EHOSTUNREACH", "no route to host"}, + {114, "EALREADY", "operation already in progress"}, + {115, "EINPROGRESS", "operation now in progress"}, + {116, "ESTALE", "stale file handle"}, + {117, "EUCLEAN", "structure needs cleaning"}, + {118, "ENOTNAM", "not a XENIX named type file"}, + {119, "ENAVAIL", "no XENIX semaphores available"}, + {120, "EISNAM", "is a named type file"}, + {121, "EREMOTEIO", "remote I/O error"}, + {122, "EDQUOT", "disk quota exceeded"}, + {123, "ENOMEDIUM", "no medium found"}, + {124, "EMEDIUMTYPE", "wrong medium type"}, + {125, "ECANCELED", "operation canceled"}, + {126, "ENOKEY", "required key not available"}, + {127, "EKEYEXPIRED", "key has expired"}, + {128, "EKEYREVOKED", "key has been revoked"}, + {129, "EKEYREJECTED", "key was rejected by service"}, + {130, "EOWNERDEAD", "owner died"}, + {131, "ENOTRECOVERABLE", "state not recoverable"}, + {132, "ERFKILL", "operation not possible due to RF-kill"}, + {133, "EHWPOISON", "memory page has hardware error"}, +} + +// Signal table +var signalList = [...]struct { + num syscall.Signal + name string + desc string +}{ + {1, "SIGHUP", "hangup"}, + {2, "SIGINT", "interrupt"}, + {3, "SIGQUIT", "quit"}, + {4, "SIGILL", "illegal instruction"}, + {5, "SIGTRAP", "trace/breakpoint trap"}, + {6, "SIGABRT", "aborted"}, + {7, "SIGBUS", "bus error"}, + {8, "SIGFPE", "floating point exception"}, + {9, "SIGKILL", "killed"}, + {10, "SIGUSR1", "user defined signal 1"}, + {11, "SIGSEGV", "segmentation fault"}, + {12, "SIGUSR2", "user defined signal 2"}, + {13, "SIGPIPE", "broken pipe"}, + {14, "SIGALRM", "alarm clock"}, + {15, "SIGTERM", "terminated"}, + {16, "SIGSTKFLT", "stack fault"}, + {17, "SIGCHLD", "child exited"}, + {18, "SIGCONT", "continued"}, + {19, "SIGSTOP", "stopped (signal)"}, + {20, "SIGTSTP", "stopped"}, + {21, "SIGTTIN", "stopped (tty input)"}, + {22, "SIGTTOU", "stopped (tty output)"}, + {23, "SIGURG", "urgent I/O condition"}, + {24, "SIGXCPU", "CPU time limit exceeded"}, + {25, "SIGXFSZ", "file size limit exceeded"}, + {26, "SIGVTALRM", "virtual timer expired"}, + {27, "SIGPROF", "profiling timer expired"}, + {28, "SIGWINCH", "window changed"}, + {29, "SIGIO", "I/O possible"}, + {30, "SIGPWR", "power failure"}, + {31, "SIGSYS", "bad system call"}, +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 63df355..203ad9c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/ppc64/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64,linux +//go:build ppc64 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/ppc64/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x10 B576000 = 0x15 B921600 = 0x16 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40081270 BLKBSZSET = 0x80081271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40081272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1f BS1 = 0x8000 BSDLY = 0x8000 @@ -59,6 +68,9 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 FFDLY = 0x4000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x800000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0x5 F_GETLK64 = 0xc @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x4000 ICANON = 0x100 IEXTEN = 0x400 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -111,17 +139,41 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NL2 = 0x200 NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + 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 = 0x4 ONLCR = 0x2 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -159,6 +211,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -186,9 +239,24 @@ const ( PPPIOCSPASS = 0x80107447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 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_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 @@ -277,6 +345,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -291,12 +361,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -320,10 +396,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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,21 +416,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -370,6 +459,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -391,6 +481,8 @@ const ( TCSETSF = 0x802c7416 TCSETSW = 0x802c7415 TCXONC = 0x2000741e + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -535,6 +627,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4000 XTABS = 0xc00 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 7ab68f7..4b9abcb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/ppc64le/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64le,linux +//go:build ppc64le && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/ppc64le/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x10 B576000 = 0x15 B921600 = 0x16 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40081270 BLKBSZSET = 0x80081271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40081272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1f BS1 = 0x8000 BSDLY = 0x8000 @@ -59,6 +68,9 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 FFDLY = 0x4000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x800000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0x5 F_GETLK64 = 0xc @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x4000 ICANON = 0x100 IEXTEN = 0x400 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -111,17 +139,41 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NL2 = 0x200 NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + 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 = 0x4 ONLCR = 0x2 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -159,6 +211,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -186,9 +239,24 @@ const ( PPPIOCSPASS = 0x80107447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 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_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 @@ -277,6 +345,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -291,12 +361,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -320,10 +396,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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,21 +416,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x15 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x10 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -370,6 +459,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -391,6 +481,8 @@ const ( TCSETSF = 0x802c7416 TCSETSW = 0x802c7415 TCXONC = 0x2000741e + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -535,6 +627,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4000 XTABS = 0xc00 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index f99cf1b..f879830 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/riscv64/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build riscv64,linux +//go:build riscv64 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/riscv64/include _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x127a BLKBSZGET = 0x80081270 BLKBSZSET = 0x40081271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c BLKFLSBUF = 0x1261 BLKFRAGET = 0x1265 BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 BLKGETSIZE = 0x1260 BLKGETSIZE64 = 0x80081272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 BLKPBSZGET = 0x127b BLKRAGET = 0x1263 BLKRASET = 0x1262 BLKROGET = 0x125e BLKROSET = 0x125d + BLKROTATIONAL = 0x127e BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d BLKSECTGET = 0x1267 BLKSECTSET = 0x1266 BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d FLUSHO = 0x1000 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 F_GETLK = 0x5 F_GETLK64 = 0x5 @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x2405 PPPIOCATTACH = 0x4004743d PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 PPPIOCCONNECT = 0x4004743a PPPIOCDETACH = 0x4004743c PPPIOCDISCONN = 0x7439 @@ -184,8 +237,26 @@ const ( PPPIOCSPASS = 0x40107447 PPPIOCSRASYNCMAP = 0x40047454 PPPIOCSXASYNCMAP = 0x4020744f + 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_GETFDPIC = 0x21 + PTRACE_GETFDPIC_EXEC = 0x0 + PTRACE_GETFDPIC_INTERP = 0x1 RLIMIT_AS = 0x9 RLIMIT_MEMLOCK = 0x8 RLIMIT_NOFILE = 0x7 @@ -206,6 +277,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -220,12 +293,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -249,10 +328,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -264,21 +348,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -299,6 +391,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -328,6 +421,8 @@ const ( TCSETXF = 0x5434 TCSETXW = 0x5435 TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -460,6 +555,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 613ee23..64347eb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include -fsigned-char +// mkerrors.sh -Wall -Werror -static -I/tmp/s390x/include -fsigned-char // Code generated by the command above; see README.md. DO NOT EDIT. -// +build s390x,linux +//go:build s390x && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/s390x/include -fsigned-char _const.go package unix @@ -26,22 +26,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x127a BLKBSZGET = 0x80081270 BLKBSZSET = 0x40081271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c BLKFLSBUF = 0x1261 BLKFRAGET = 0x1265 BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 BLKGETSIZE = 0x1260 BLKGETSIZE64 = 0x80081272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 BLKPBSZGET = 0x127b BLKRAGET = 0x1263 BLKRASET = 0x1262 BLKROGET = 0x125e BLKROSET = 0x125d + BLKROTATIONAL = 0x127e BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d BLKSECTGET = 0x1267 BLKSECTSET = 0x1266 BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -59,6 +68,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -67,13 +79,21 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d FLUSHO = 0x1000 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 F_GETLK = 0x5 F_GETLK64 = 0x5 @@ -86,12 +106,20 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -111,15 +139,39 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 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 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -157,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x2405 PPPIOCATTACH = 0x4004743d PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 PPPIOCCONNECT = 0x4004743a PPPIOCDETACH = 0x4004743c PPPIOCDISCONN = 0x7439 @@ -184,8 +237,23 @@ const ( PPPIOCSPASS = 0x40107447 PPPIOCSRASYNCMAP = 0x40047454 PPPIOCSXASYNCMAP = 0x4020744f + 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_DISABLE_TE = 0x5010 PTRACE_ENABLE_TE = 0x5009 PTRACE_GET_LAST_BREAK = 0x5006 @@ -200,6 +268,8 @@ const ( PTRACE_POKE_SYSTEM_CALL = 0x5008 PTRACE_PROT = 0x15 PTRACE_SINGLEBLOCK = 0xc + PTRACE_SYSEMU = 0x1f + PTRACE_SYSEMU_SINGLESTEP = 0x20 PTRACE_TE_ABORT_RAND = 0x5011 PT_ACR0 = 0x90 PT_ACR1 = 0x94 @@ -279,6 +349,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -293,12 +365,18 @@ 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 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 @@ -322,10 +400,15 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 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 @@ -337,21 +420,29 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 SO_PASSSEC = 0x22 SO_PEEK_OFF = 0x2a SO_PEERCRED = 0x11 SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 SO_PROTOCOL = 0x26 SO_RCVBUF = 0x8 SO_RCVBUFFORCE = 0x21 SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 @@ -372,6 +463,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x40 SO_TIMESTAMPNS_OLD = 0x23 SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a SO_TXTIME = 0x3d SO_TYPE = 0x3 SO_WIFI_STATUS = 0x29 @@ -401,6 +493,8 @@ const ( TCSETXF = 0x5434 TCSETXW = 0x5435 TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 TIOCCBRK = 0x5428 TIOCCONS = 0x541d TIOCEXCL = 0x540c @@ -533,6 +627,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 1f7a68d..7d71911 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -Wall -Werror -static -I/tmp/include +// mkerrors.sh -Wall -Werror -static -I/tmp/sparc64/include // Code generated by the command above; see README.md. DO NOT EDIT. -// +build sparc64,linux +//go:build sparc64 && linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/sparc64/include _const.go package unix @@ -29,22 +29,31 @@ const ( B57600 = 0x1001 B576000 = 0x1006 B921600 = 0x1007 + BLKALIGNOFF = 0x2000127a BLKBSZGET = 0x40081270 BLKBSZSET = 0x80081271 + BLKDISCARD = 0x20001277 + BLKDISCARDZEROES = 0x2000127c BLKFLSBUF = 0x20001261 BLKFRAGET = 0x20001265 BLKFRASET = 0x20001264 + BLKGETDISKSEQ = 0x40081280 BLKGETSIZE = 0x20001260 BLKGETSIZE64 = 0x40081272 + BLKIOMIN = 0x20001278 + BLKIOOPT = 0x20001279 BLKPBSZGET = 0x2000127b BLKRAGET = 0x20001263 BLKRASET = 0x20001262 BLKROGET = 0x2000125e BLKROSET = 0x2000125d + BLKROTATIONAL = 0x2000127e BLKRRPART = 0x2000125f + BLKSECDISCARD = 0x2000127d BLKSECTGET = 0x20001267 BLKSECTSET = 0x20001266 BLKSSZGET = 0x20001268 + BLKZEROOUT = 0x2000127f BOTHER = 0x1000 BS1 = 0x2000 BSDLY = 0x2000 @@ -62,6 +71,9 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0x2000fd12 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -71,13 +83,21 @@ const ( EFD_CLOEXEC = 0x400000 EFD_NONBLOCK = 0x4000 EMT_TAGOVF = 0x1 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x400000 EXTPROC = 0x10000 FF1 = 0x8000 FFDLY = 0x8000 + FICLONE = 0x80049409 + FICLONERANGE = 0x8020940d FLUSHO = 0x1000 + FS_IOC_ENABLE_VERITY = 0x80806685 + FS_IOC_GETFLAGS = 0x40086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615 FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614 + FS_IOC_SETFLAGS = 0x80086602 FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613 F_GETLK = 0x7 F_GETLK64 = 0x7 @@ -90,12 +110,20 @@ const ( F_SETOWN = 0x6 F_UNLCK = 0x3 F_WRLCK = 0x2 + HIDIOCGRAWINFO = 0x40084803 + HIDIOCGRDESC = 0x50044802 + HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x400000 IN_NONBLOCK = 0x4000 + IOCTL_MEI_NOTIFY_GET = 0x40044803 + IOCTL_MEI_NOTIFY_SET = 0x80044802 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -116,15 +144,39 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 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 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x40 O_CLOEXEC = 0x400000 @@ -162,6 +214,7 @@ const ( PERF_EVENT_IOC_SET_OUTPUT = 0x20002405 PPPIOCATTACH = 0x8004743d PPPIOCATTCHAN = 0x80047438 + PPPIOCBRIDGECHAN = 0x80047435 PPPIOCCONNECT = 0x8004743a PPPIOCDETACH = 0x8004743c PPPIOCDISCONN = 0x20007439 @@ -189,8 +242,23 @@ const ( PPPIOCSPASS = 0x80107447 PPPIOCSRASYNCMAP = 0x80047454 PPPIOCSXASYNCMAP = 0x8020744f + 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_GETFPAREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETFPREGS64 = 0x19 @@ -272,6 +340,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -286,14 +356,68 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x58 + SCM_DEVMEM_LINEAR = 0x57 SCM_TIMESTAMPING = 0x23 SCM_TIMESTAMPING_OPT_STATS = 0x38 SCM_TIMESTAMPING_PKTINFO = 0x3c SCM_TIMESTAMPNS = 0x21 + SCM_TS_OPT_ID = 0x5a SCM_TXTIME = 0x3f SCM_WIFI_STATUS = 0x25 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x400000 SFD_NONBLOCK = 0x4000 + SF_FP = 0x38 + SF_I0 = 0x20 + SF_I1 = 0x24 + SF_I2 = 0x28 + SF_I3 = 0x2c + SF_I4 = 0x30 + SF_I5 = 0x34 + SF_L0 = 0x0 + SF_L1 = 0x4 + SF_L2 = 0x8 + SF_L3 = 0xc + SF_L4 = 0x10 + SF_L5 = 0x14 + SF_L6 = 0x18 + SF_L7 = 0x1c + SF_PC = 0x3c + SF_RETP = 0x40 + SF_V9_FP = 0x70 + SF_V9_I0 = 0x40 + SF_V9_I1 = 0x48 + SF_V9_I2 = 0x50 + SF_V9_I3 = 0x58 + SF_V9_I4 = 0x60 + SF_V9_I5 = 0x68 + SF_V9_L0 = 0x0 + SF_V9_L1 = 0x8 + SF_V9_L2 = 0x10 + SF_V9_L3 = 0x18 + SF_V9_L4 = 0x20 + SF_V9_L5 = 0x28 + SF_V9_L6 = 0x30 + SF_V9_L7 = 0x38 + SF_V9_PC = 0x78 + SF_V9_RETP = 0x80 + SF_V9_XARG0 = 0x88 + SF_V9_XARG1 = 0x90 + SF_V9_XARG2 = 0x98 + SF_V9_XARG3 = 0xa0 + SF_V9_XARG4 = 0xa8 + SF_V9_XARG5 = 0xb0 + SF_V9_XXARG = 0xb8 + SF_XARG0 = 0x44 + SF_XARG1 = 0x48 + SF_XARG2 = 0x4c + SF_XARG3 = 0x50 + SF_XARG4 = 0x54 + SF_XARG5 = 0x58 + SF_XXARG = 0x5c SIOCATMARK = 0x8905 SIOCGPGRP = 0x8904 SIOCGSTAMPNS_NEW = 0x40108907 @@ -315,10 +439,15 @@ const ( SO_BPF_EXTENSIONS = 0x32 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0x400 + SO_BUF_LOCK = 0x51 SO_BUSY_POLL = 0x30 + SO_BUSY_POLL_BUDGET = 0x49 SO_CNX_ADVICE = 0x37 SO_COOKIE = 0x3b SO_DETACH_REUSEPORT_BPF = 0x47 + SO_DEVMEM_DMABUF = 0x58 + SO_DEVMEM_DONTNEED = 0x59 + SO_DEVMEM_LINEAR = 0x57 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 @@ -330,21 +459,29 @@ const ( SO_MARK = 0x22 SO_MAX_PACING_RATE = 0x31 SO_MEMINFO = 0x39 + SO_NETNS_COOKIE = 0x50 SO_NOFCS = 0x27 SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 + SO_PASSPIDFD = 0x55 + SO_PASSRIGHTS = 0x5c SO_PASSSEC = 0x1f SO_PEEK_OFF = 0x26 SO_PEERCRED = 0x40 SO_PEERGROUPS = 0x3d + SO_PEERPIDFD = 0x56 SO_PEERSEC = 0x1e + SO_PREFER_BUSY_POLL = 0x48 SO_PROTOCOL = 0x1028 SO_RCVBUF = 0x1002 SO_RCVBUFFORCE = 0x100b SO_RCVLOWAT = 0x800 + SO_RCVMARK = 0x54 + SO_RCVPRIORITY = 0x5b SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 + SO_RESERVE_MEM = 0x52 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x24 @@ -365,6 +502,7 @@ const ( SO_TIMESTAMPNS_NEW = 0x42 SO_TIMESTAMPNS_OLD = 0x21 SO_TIMESTAMP_NEW = 0x46 + SO_TXREHASH = 0x53 SO_TXTIME = 0x3f SO_TYPE = 0x1008 SO_WIFI_STATUS = 0x25 @@ -390,6 +528,8 @@ const ( TCSETSW = 0x8024540a TCSETSW2 = 0x802c540e TCXONC = 0x20005406 + TFD_CLOEXEC = 0x400000 + TFD_NONBLOCK = 0x4000 TIOCCBRK = 0x2000747a TIOCCONS = 0x20007424 TIOCEXCL = 0x2000740d @@ -523,6 +663,9 @@ const ( WORDSIZE = 0x40 XCASE = 0x4 XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x40804804 + _HIDIOCGRAWPHYS = 0x40404805 + _HIDIOCGRAWUNIQ = 0x40404808 __TIOCFLUSH = 0x80047410 ) diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go index 96b9b8a..130085d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go @@ -1,7 +1,7 @@ // mkerrors.sh -m32 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,netbsd +//go:build 386 && netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go @@ -158,6 +158,12 @@ const ( CLONE_SIGHAND = 0x800 CLONE_VFORK = 0x4000 CLONE_VM = 0x100 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go index ed522a8..84769a1 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,netbsd +//go:build amd64 && netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -158,6 +158,12 @@ const ( CLONE_SIGHAND = 0x800 CLONE_VFORK = 0x4000 CLONE_VM = 0x100 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go index c8d36fe..602ded0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go @@ -1,7 +1,7 @@ // mkerrors.sh -marm // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,netbsd +//go:build arm && netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -marm _const.go @@ -150,6 +150,12 @@ const ( BRKINT = 0x2 CFLUSH = 0xf CLOCAL = 0x8000 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go index f1c146a..efc0406 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,netbsd +//go:build arm64 && netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -158,6 +158,12 @@ const ( CLONE_SIGHAND = 0x800 CLONE_VFORK = 0x4000 CLONE_VM = 0x100 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go index 5402bd5..5a6500f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -1,7 +1,7 @@ // mkerrors.sh -m32 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,openbsd +//go:build 386 && openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go @@ -45,6 +45,7 @@ const ( AF_SNA = 0xb AF_UNIX = 0x1 AF_UNSPEC = 0x0 + ALTWERASE = 0x200 ARPHRD_ETHER = 0x1 ARPHRD_FRELAY = 0xf ARPHRD_IEEE1394 = 0x18 @@ -107,6 +108,15 @@ const ( BPF_DIRECTION_IN = 0x1 BPF_DIRECTION_OUT = 0x2 BPF_DIV = 0x30 + BPF_FILDROP_CAPTURE = 0x1 + BPF_FILDROP_DROP = 0x2 + BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 @@ -135,6 +145,7 @@ const ( BPF_OR = 0x40 BPF_RELEASE = 0x30bb6 BPF_RET = 0x6 + BPF_RND = 0xc0 BPF_RSH = 0x70 BPF_ST = 0x2 BPF_STX = 0x3 @@ -146,6 +157,19 @@ const ( BRKINT = 0x2 CFLUSH = 0xf CLOCAL = 0x8000 + CLOCK_BOOTTIME = 0x6 + CLOCK_MONOTONIC = 0x3 + CLOCK_PROCESS_CPUTIME_ID = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x4 + CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 @@ -162,7 +186,65 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0xc CTL_NET = 0x4 + DIOCADDQUEUE = 0xc100445d + DIOCADDRULE = 0xccc84404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xccc8441a + DIOCCLRIFFLAG = 0xc024445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0d04412 + DIOCCLRSTATUS = 0xc0244416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1084460 + DIOCGETQUEUE = 0xc100445f + DIOCGETQUEUES = 0xc100445e + DIOCGETRULE = 0xccc84407 + DIOCGETRULES = 0xccc84406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0084454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0084419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0244457 + DIOCKILLSRCNODES = 0xc068445b + DIOCKILLSTATES = 0xc0d04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc084444f DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0844450 + DIOCRADDADDRS = 0xc44c4443 + DIOCRADDTABLES = 0xc44c443d + DIOCRCLRADDRS = 0xc44c4442 + DIOCRCLRASTATS = 0xc44c4448 + DIOCRCLRTABLES = 0xc44c443c + DIOCRCLRTSTATS = 0xc44c4441 + DIOCRDELADDRS = 0xc44c4444 + DIOCRDELTABLES = 0xc44c443e + DIOCRGETADDRS = 0xc44c4446 + DIOCRGETASTATS = 0xc44c4447 + DIOCRGETTABLES = 0xc44c443f + DIOCRGETTSTATS = 0xc44c4440 + DIOCRINADEFINE = 0xc44c444d + DIOCRSETADDRS = 0xc44c4445 + DIOCRSETTFLAGS = 0xc44c444a + DIOCRTSTADDRS = 0xc44c4449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0244459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0244414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc00c4451 + DIOCXCOMMIT = 0xc00c4452 + DIOCXROLLBACK = 0xc00c4453 DLT_ARCNET = 0x7 DLT_ATM_RFC1483 = 0xb DLT_AX25 = 0x3 @@ -178,6 +260,7 @@ const ( DLT_LOOP = 0xc DLT_MPLS = 0xdb DLT_NULL = 0x0 + DLT_OPENFLOW = 0x10b DLT_PFLOG = 0x75 DLT_PFSYNC = 0x12 DLT_PPP = 0x9 @@ -188,6 +271,23 @@ const ( DLT_RAW = 0xe DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xf + DLT_USBPCAP = 0xf9 + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -207,6 +307,8 @@ const ( EMUL_ENABLED = 0x1 EMUL_NATIVE = 0x2 ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 ETHERMIN = 0x2e ETHERMTU = 0x5dc ETHERTYPE_8023 = 0x4 @@ -259,6 +361,7 @@ const ( ETHERTYPE_DN = 0x6003 ETHERTYPE_DOGFIGHT = 0x1989 ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e ETHERTYPE_ECMA = 0x803 ETHERTYPE_ENCRYPT = 0x803d ETHERTYPE_ES = 0x805d @@ -290,6 +393,7 @@ const ( ETHERTYPE_LLDP = 0x88cc ETHERTYPE_LOGICRAFT = 0x8148 ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 ETHERTYPE_MATRA = 0x807a ETHERTYPE_MAX = 0xffff ETHERTYPE_MERIT = 0x807c @@ -318,15 +422,17 @@ const ( ETHERTYPE_NCD = 0x8149 ETHERTYPE_NESTAR = 0x8006 ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 ETHERTYPE_NOVELL = 0x8138 ETHERTYPE_NS = 0x600 ETHERTYPE_NSAT = 0x601 ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f ETHERTYPE_NTRAILER = 0x10 ETHERTYPE_OS9 = 0x7007 ETHERTYPE_OS9NET = 0x7009 ETHERTYPE_PACER = 0x80c6 - ETHERTYPE_PAE = 0x888e + ETHERTYPE_PBB = 0x88e7 ETHERTYPE_PCS = 0x4242 ETHERTYPE_PLANNING = 0x8044 ETHERTYPE_PPP = 0x880b @@ -401,28 +507,40 @@ const ( ETHER_CRC_POLY_LE = 0xedb88320 ETHER_HDR_LEN = 0xe ETHER_MAX_DIX_LEN = 0x600 + ETHER_MAX_HARDMTU_LEN = 0xff9b ETHER_MAX_LEN = 0x5ee ETHER_MIN_LEN = 0x40 ETHER_TYPE_LEN = 0x2 ETHER_VLAN_ENCAP_LEN = 0x4 EVFILT_AIO = -0x3 + EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 EVFILT_PROC = -0x5 EVFILT_READ = -0x1 EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x7 + EVFILT_SYSCOUNT = 0x9 EVFILT_TIMER = -0x7 EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 + EVL_ENCAPLEN = 0x4 + EVL_PRIO_BITS = 0xd + EVL_PRIO_MAX = 0x7 + EVL_VLID_MASK = 0xfff + EVL_VLID_MAX = 0xffe + EVL_VLID_MIN = 0x1 + EVL_VLID_NULL = 0x0 EV_ADD = 0x1 EV_CLEAR = 0x20 EV_DELETE = 0x2 EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 EV_ENABLE = 0x4 EV_EOF = 0x8000 EV_ERROR = 0x4000 EV_FLAG1 = 0x2000 EV_ONESHOT = 0x10 - EV_SYSFLAGS = 0xf000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTPROC = 0x800 @@ -435,6 +553,7 @@ const ( F_GETFL = 0x3 F_GETLK = 0x7 F_GETOWN = 0x5 + F_ISATTY = 0xb F_OK = 0x0 F_RDLCK = 0x1 F_SETFD = 0x2 @@ -452,7 +571,6 @@ const ( IEXTEN = 0x400 IFAN_ARRIVAL = 0x0 IFAN_DEPARTURE = 0x1 - IFA_ROUTE = 0x1 IFF_ALLMULTI = 0x200 IFF_BROADCAST = 0x2 IFF_CANTCHANGE = 0x8e52 @@ -463,12 +581,12 @@ const ( IFF_LOOPBACK = 0x8 IFF_MULTICAST = 0x8000 IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 IFF_OACTIVE = 0x400 IFF_POINTOPOINT = 0x10 IFF_PROMISC = 0x100 IFF_RUNNING = 0x40 IFF_SIMPLEX = 0x800 + IFF_STATICARP = 0x20 IFF_UP = 0x1 IFNAMSIZ = 0x10 IFT_1822 = 0x2 @@ -597,6 +715,7 @@ const ( IFT_LINEGROUP = 0xd2 IFT_LOCALTALK = 0x2a IFT_LOOP = 0x18 + IFT_MBIM = 0xfa IFT_MEDIAMAILOVERIP = 0x8b IFT_MFSIGLINK = 0xa7 IFT_MIOX25 = 0x26 @@ -687,6 +806,7 @@ const ( IFT_VOICEOVERCABLE = 0xc6 IFT_VOICEOVERFRAMERELAY = 0x99 IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb IFT_X213 = 0x5d IFT_X25 = 0x5 IFT_X25DDN = 0x4 @@ -721,8 +841,6 @@ const ( IPPROTO_AH = 0x33 IPPROTO_CARP = 0x70 IPPROTO_DIVERT = 0x102 - IPPROTO_DIVERT_INIT = 0x2 - IPPROTO_DIVERT_RESP = 0x1 IPPROTO_DONE = 0x101 IPPROTO_DSTOPTS = 0x3c IPPROTO_EGP = 0x8 @@ -754,9 +872,11 @@ const ( IPPROTO_RAW = 0xff IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e + IPPROTO_SCTP = 0x84 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 + IPPROTO_UDPLITE = 0x88 IPV6_AUTH_LEVEL = 0x35 IPV6_AUTOFLOWLABEL = 0x3b IPV6_CHECKSUM = 0x1a @@ -779,6 +899,7 @@ const ( IPV6_LEAVE_GROUP = 0xd IPV6_MAXHLIM = 0xff IPV6_MAXPACKET = 0xffff + IPV6_MINHOPCOUNT = 0x41 IPV6_MMTU = 0x500 IPV6_MULTICAST_HOPS = 0xa IPV6_MULTICAST_IF = 0x9 @@ -818,12 +939,12 @@ const ( IP_DEFAULT_MULTICAST_LOOP = 0x1 IP_DEFAULT_MULTICAST_TTL = 0x1 IP_DF = 0x4000 - IP_DIVERTFL = 0x1022 IP_DROP_MEMBERSHIP = 0xd IP_ESP_NETWORK_LEVEL = 0x16 IP_ESP_TRANS_LEVEL = 0x15 IP_HDRINCL = 0x2 IP_IPCOMP_LEVEL = 0x1d + IP_IPDEFTTL = 0x25 IP_IPSECFLOWINFO = 0x24 IP_IPSEC_LOCAL_AUTH = 0x1b IP_IPSEC_LOCAL_CRED = 0x19 @@ -857,10 +978,15 @@ const ( IP_RETOPTS = 0x8 IP_RF = 0x8000 IP_RTABLE = 0x1021 + IP_SENDSRCADDR = 0x7 IP_TOS = 0x3 IP_TTL = 0x4 ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 + IUCLC = 0x1000 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -892,10 +1018,11 @@ const ( MAP_INHERIT_COPY = 0x1 MAP_INHERIT_NONE = 0x2 MAP_INHERIT_SHARE = 0x0 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 + MAP_INHERIT_ZERO = 0x3 + MAP_NOEXTEND = 0x0 + MAP_NORESERVE = 0x0 MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 + MAP_RENAME = 0x0 MAP_SHARED = 0x1 MAP_STACK = 0x4000 MAP_TRYFIXED = 0x0 @@ -914,6 +1041,7 @@ const ( MNT_NOATIME = 0x8000 MNT_NODEV = 0x10 MNT_NOEXEC = 0x4 + MNT_NOPERM = 0x20 MNT_NOSUID = 0x8 MNT_NOWAIT = 0x2 MNT_QUOTA = 0x2000 @@ -921,13 +1049,29 @@ const ( MNT_RELOAD = 0x40000 MNT_ROOTFS = 0x4000 MNT_SOFTDEP = 0x4000000 + MNT_STALLED = 0x100000 + MNT_SWAPPABLE = 0x200000 MNT_SYNCHRONOUS = 0x2 MNT_UPDATE = 0x10000 MNT_VISFLAGMASK = 0x400ffff MNT_WAIT = 0x1 MNT_WANTRDWR = 0x2000000 MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" MSG_BCAST = 0x100 + MSG_CMSG_CLOEXEC = 0x800 MSG_CTRUNC = 0x20 MSG_DONTROUTE = 0x4 MSG_DONTWAIT = 0x80 @@ -938,6 +1082,7 @@ const ( MSG_PEEK = 0x2 MSG_TRUNC = 0x10 MSG_WAITALL = 0x40 + MSG_WAITFORONE = 0x1000 MS_ASYNC = 0x1 MS_INVALIDATE = 0x4 MS_SYNC = 0x2 @@ -945,12 +1090,16 @@ const ( NET_RT_DUMP = 0x1 NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 - NET_RT_MAXID = 0x6 + NET_RT_IFNAMES = 0x6 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 NFDBITS = 0x20 NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 + NOTE_CHANGE = 0x1 NOTE_CHILD = 0x4 NOTE_DELETE = 0x1 NOTE_EOF = 0x2 @@ -960,6 +1109,7 @@ const ( NOTE_FORK = 0x40000000 NOTE_LINK = 0x10 NOTE_LOWAT = 0x1 + NOTE_OOB = 0x4 NOTE_PCTRLMASK = 0xf0000000 NOTE_PDATAMASK = 0xfffff NOTE_RENAME = 0x20 @@ -969,11 +1119,13 @@ const ( NOTE_TRUNCATE = 0x80 NOTE_WRITE = 0x2 OCRNL = 0x10 + OLCUC = 0x20 ONLCR = 0x2 ONLRET = 0x80 ONOCR = 0x40 ONOEOT = 0x8 OPOST = 0x1 + OXTABS = 0x4 O_ACCMODE = 0x3 O_APPEND = 0x8 O_ASYNC = 0x40 @@ -1007,28 +1159,36 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 - PT_MASK = 0x3ff000 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 + RTAX_BFD = 0xb RTAX_BRD = 0x7 + RTAX_DNS = 0xc RTAX_DST = 0x0 RTAX_GATEWAY = 0x1 RTAX_GENMASK = 0x3 RTAX_IFA = 0x5 RTAX_IFP = 0x4 RTAX_LABEL = 0xa - RTAX_MAX = 0xb + RTAX_MAX = 0xf RTAX_NETMASK = 0x2 + RTAX_SEARCH = 0xe RTAX_SRC = 0x8 RTAX_SRCMASK = 0x9 + RTAX_STATIC = 0xd RTA_AUTHOR = 0x40 + RTA_BFD = 0x800 RTA_BRD = 0x80 + RTA_DNS = 0x1000 RTA_DST = 0x1 RTA_GATEWAY = 0x2 RTA_GENMASK = 0x8 @@ -1036,49 +1196,57 @@ const ( RTA_IFP = 0x10 RTA_LABEL = 0x400 RTA_NETMASK = 0x4 + RTA_SEARCH = 0x4000 RTA_SRC = 0x100 RTA_SRCMASK = 0x200 + RTA_STATIC = 0x2000 RTF_ANNOUNCE = 0x4000 + RTF_BFD = 0x1000000 RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CACHED = 0x20000 RTF_CLONED = 0x10000 RTF_CLONING = 0x100 + RTF_CONNECTED = 0x800000 RTF_DONE = 0x40 RTF_DYNAMIC = 0x10 - RTF_FMASK = 0x10f808 + RTF_FMASK = 0x110fc08 RTF_GATEWAY = 0x2 RTF_HOST = 0x4 RTF_LLINFO = 0x400 - RTF_MASK = 0x80 + RTF_LOCAL = 0x200000 RTF_MODIFIED = 0x20 RTF_MPATH = 0x40000 RTF_MPLS = 0x100000 + RTF_MULTICAST = 0x200 RTF_PERMANENT_ARP = 0x2000 RTF_PROTO1 = 0x8000 RTF_PROTO2 = 0x4000 RTF_PROTO3 = 0x2000 RTF_REJECT = 0x8 - RTF_SOURCE = 0x20000 RTF_STATIC = 0x800 - RTF_TUNNEL = 0x100000 RTF_UP = 0x1 RTF_USETRAILERS = 0x8000 - RTF_XRESOLVE = 0x200 + RTM_80211INFO = 0x15 RTM_ADD = 0x1 + RTM_BFD = 0x12 RTM_CHANGE = 0x3 + RTM_CHGADDRATTR = 0x14 RTM_DELADDR = 0xd RTM_DELETE = 0x2 RTM_DESYNC = 0x10 RTM_GET = 0x4 RTM_IFANNOUNCE = 0xf RTM_IFINFO = 0xe - RTM_LOCK = 0x8 + RTM_INVALIDATE = 0x11 RTM_LOSING = 0x5 RTM_MAXSIZE = 0x800 RTM_MISS = 0x7 RTM_NEWADDR = 0xc + RTM_PROPOSAL = 0x13 RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 + RTM_SOURCE = 0x16 RTM_VERSION = 0x5 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 @@ -1088,67 +1256,74 @@ const ( RTV_RTTVAR = 0x80 RTV_SPIPE = 0x10 RTV_SSTHRESH = 0x20 + RT_TABLEID_BITS = 0x8 + RT_TABLEID_MASK = 0xff RT_TABLEID_MAX = 0xff RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 RUSAGE_THREAD = 0x1 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 SIOCADDMULTI = 0x80206931 SIOCAIFADDR = 0x8040691a SIOCAIFGROUP = 0x80246987 - SIOCALIFADDR = 0x8218691c SIOCATMARK = 0x40047307 - SIOCBRDGADD = 0x8054693c - SIOCBRDGADDS = 0x80546941 - SIOCBRDGARL = 0x806e694d + SIOCBRDGADD = 0x805c693c + SIOCBRDGADDL = 0x805c6949 + SIOCBRDGADDS = 0x805c6941 + SIOCBRDGARL = 0x808c694d SIOCBRDGDADDR = 0x81286947 - SIOCBRDGDEL = 0x8054693d - SIOCBRDGDELS = 0x80546942 - SIOCBRDGFLUSH = 0x80546948 - SIOCBRDGFRL = 0x806e694e + SIOCBRDGDEL = 0x805c693d + SIOCBRDGDELS = 0x805c6942 + SIOCBRDGFLUSH = 0x805c6948 + SIOCBRDGFRL = 0x808c694e SIOCBRDGGCACHE = 0xc0146941 SIOCBRDGGFD = 0xc0146952 SIOCBRDGGHT = 0xc0146951 - SIOCBRDGGIFFLGS = 0xc054693e + SIOCBRDGGIFFLGS = 0xc05c693e SIOCBRDGGMA = 0xc0146953 SIOCBRDGGPARAM = 0xc03c6958 SIOCBRDGGPRI = 0xc0146950 SIOCBRDGGRL = 0xc028694f - SIOCBRDGGSIFS = 0xc054693c SIOCBRDGGTO = 0xc0146946 - SIOCBRDGIFS = 0xc0546942 + SIOCBRDGIFS = 0xc05c6942 SIOCBRDGRTS = 0xc0186943 SIOCBRDGSADDR = 0xc1286944 SIOCBRDGSCACHE = 0x80146940 SIOCBRDGSFD = 0x80146952 SIOCBRDGSHT = 0x80146951 - SIOCBRDGSIFCOST = 0x80546955 - SIOCBRDGSIFFLGS = 0x8054693f - SIOCBRDGSIFPRIO = 0x80546954 + SIOCBRDGSIFCOST = 0x805c6955 + SIOCBRDGSIFFLGS = 0x805c693f + SIOCBRDGSIFPRIO = 0x805c6954 + SIOCBRDGSIFPROT = 0x805c694a SIOCBRDGSMA = 0x80146953 SIOCBRDGSPRI = 0x80146950 SIOCBRDGSPROTO = 0x8014695a SIOCBRDGSTO = 0x80146945 SIOCBRDGSTXHC = 0x80146959 + SIOCDELLABEL = 0x80206997 SIOCDELMULTI = 0x80206932 SIOCDIFADDR = 0x80206919 SIOCDIFGROUP = 0x80246989 + SIOCDIFPARENT = 0x802069b4 SIOCDIFPHYADDR = 0x80206949 - SIOCDLIFADDR = 0x8218691e + SIOCDPWE3NEIGHBOR = 0x802069de + SIOCDVNETID = 0x802069af SIOCGETKALIVE = 0xc01869a4 SIOCGETLABEL = 0x8020699a + SIOCGETMPWCFG = 0xc02069ae SIOCGETPFLOW = 0xc02069fe SIOCGETPFSYNC = 0xc02069f8 SIOCGETSGCNT = 0xc0147534 SIOCGETVIFCNT = 0xc0147533 SIOCGETVLAN = 0xc0206990 - SIOCGHIWAT = 0x40047301 SIOCGIFADDR = 0xc0206921 - SIOCGIFASYNCMAP = 0xc020697c SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCONF = 0xc0086924 SIOCGIFDATA = 0xc020691b @@ -1157,40 +1332,53 @@ const ( SIOCGIFFLAGS = 0xc0206911 SIOCGIFGATTR = 0xc024698b SIOCGIFGENERIC = 0xc020693a + SIOCGIFGLIST = 0xc024698d SIOCGIFGMEMB = 0xc024698a SIOCGIFGROUP = 0xc0246988 SIOCGIFHARDMTU = 0xc02069a5 - SIOCGIFMEDIA = 0xc0286936 + SIOCGIFLLPRIO = 0xc02069b6 + SIOCGIFMEDIA = 0xc0386938 SIOCGIFMETRIC = 0xc0206917 SIOCGIFMTU = 0xc020697e SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206948 + SIOCGIFPAIR = 0xc02069b1 + SIOCGIFPARENT = 0xc02069b3 SIOCGIFPRIORITY = 0xc020699c - SIOCGIFPSRCADDR = 0xc0206947 SIOCGIFRDOMAIN = 0xc02069a0 SIOCGIFRTLABEL = 0xc0206983 - SIOCGIFTIMESLOT = 0xc0206986 + SIOCGIFRXR = 0x802069aa + SIOCGIFSFFPAGE = 0xc1126939 SIOCGIFXFLAGS = 0xc020699e - SIOCGLIFADDR = 0xc218691d SIOCGLIFPHYADDR = 0xc218694b + SIOCGLIFPHYDF = 0xc02069c2 + SIOCGLIFPHYECN = 0xc02069c8 SIOCGLIFPHYRTABLE = 0xc02069a2 SIOCGLIFPHYTTL = 0xc02069a9 - SIOCGLOWAT = 0x40047303 SIOCGPGRP = 0x40047309 + SIOCGPWE3 = 0xc0206998 + SIOCGPWE3CTRLWORD = 0xc02069dc + SIOCGPWE3FAT = 0xc02069dd + SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db SIOCGSPPPPARAMS = 0xc0206994 + SIOCGTXHPRIO = 0xc02069c6 + SIOCGUMBINFO = 0xc02069be + SIOCGUMBPARAM = 0xc02069c0 SIOCGVH = 0xc02069f6 + SIOCGVNETFLOWID = 0xc02069c4 SIOCGVNETID = 0xc02069a7 + SIOCIFAFATTACH = 0x801169ab + SIOCIFAFDETACH = 0x801169ac SIOCIFCREATE = 0x8020697a SIOCIFDESTROY = 0x80206979 SIOCIFGCLONERS = 0xc00c6978 SIOCSETKALIVE = 0x801869a3 SIOCSETLABEL = 0x80206999 + SIOCSETMPWCFG = 0x802069ad SIOCSETPFLOW = 0x802069fd SIOCSETPFSYNC = 0x802069f7 SIOCSETVLAN = 0x8020698f - SIOCSHIWAT = 0x80047300 SIOCSIFADDR = 0x8020690c - SIOCSIFASYNCMAP = 0x8020697d SIOCSIFBRDADDR = 0x80206913 SIOCSIFDESCR = 0x80206980 SIOCSIFDSTADDR = 0x8020690e @@ -1198,25 +1386,37 @@ const ( SIOCSIFGATTR = 0x8024698c SIOCSIFGENERIC = 0x80206939 SIOCSIFLLADDR = 0x8020691f - SIOCSIFMEDIA = 0xc0206935 + SIOCSIFLLPRIO = 0x802069b5 + SIOCSIFMEDIA = 0xc0206937 SIOCSIFMETRIC = 0x80206918 SIOCSIFMTU = 0x8020697f SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x80406946 + SIOCSIFPAIR = 0x802069b0 + SIOCSIFPARENT = 0x802069b2 SIOCSIFPRIORITY = 0x8020699b SIOCSIFRDOMAIN = 0x8020699f SIOCSIFRTLABEL = 0x80206982 - SIOCSIFTIMESLOT = 0x80206985 SIOCSIFXFLAGS = 0x8020699d SIOCSLIFPHYADDR = 0x8218694a + SIOCSLIFPHYDF = 0x802069c1 + SIOCSLIFPHYECN = 0x802069c7 SIOCSLIFPHYRTABLE = 0x802069a1 SIOCSLIFPHYTTL = 0x802069a8 - SIOCSLOWAT = 0x80047302 SIOCSPGRP = 0x80047308 + SIOCSPWE3CTRLWORD = 0x802069dc + SIOCSPWE3FAT = 0x802069dd + SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db SIOCSSPPPPARAMS = 0x80206993 + SIOCSTXHPRIO = 0x802069c5 + SIOCSUMBPARAM = 0x802069bf SIOCSVH = 0xc02069f5 + SIOCSVNETFLOWID = 0x802069c3 SIOCSVNETID = 0x802069a6 + SOCK_CLOEXEC = 0x8000 SOCK_DGRAM = 0x2 + SOCK_DNS = 0x1000 + SOCK_NONBLOCK = 0x4000 SOCK_RAW = 0x3 SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 @@ -1227,6 +1427,7 @@ const ( SO_BINDANY = 0x1000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 @@ -1234,6 +1435,7 @@ const ( SO_NETPROC = 0x1020 SO_OOBINLINE = 0x100 SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 @@ -1247,6 +1449,7 @@ const ( SO_TIMESTAMP = 0x800 SO_TYPE = 0x1008 SO_USELOOPBACK = 0x40 + SO_ZEROIZE = 0x2000 S_BLKSIZE = 0x200 S_IEXEC = 0x40 S_IFBLK = 0x6000 @@ -1276,9 +1479,24 @@ const ( S_IXOTH = 0x1 S_IXUSR = 0x40 TCIFLUSH = 0x1 + TCIOFF = 0x3 TCIOFLUSH = 0x3 + TCION = 0x4 TCOFLUSH = 0x2 - TCP_MAXBURST = 0x4 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 TCP_MAXSEG = 0x2 TCP_MAXWIN = 0xffff TCP_MAX_SACK = 0x3 @@ -1287,11 +1505,15 @@ const ( TCP_MSS = 0x200 TCP_NODELAY = 0x1 TCP_NOPUSH = 0x10 - TCP_NSTATES = 0xb + TCP_SACKHOLE_LIMIT = 0x80 TCP_SACK_ENABLE = 0x8 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 + TIOCCHKVERAUTH = 0x2000741e + TIOCCLRVERAUTH = 0x2000741d TIOCCONS = 0x80047462 TIOCDRAIN = 0x2000745e TIOCEXCL = 0x2000740d @@ -1346,17 +1568,21 @@ const ( TIOCSETAF = 0x802c7416 TIOCSETAW = 0x802c7415 TIOCSETD = 0x8004741b + TIOCSETVERAUTH = 0x8004741c TIOCSFLAGS = 0x8004745c TIOCSIG = 0x8004745f TIOCSPGRP = 0x80047476 TIOCSTART = 0x2000746e - TIOCSTAT = 0x80047465 - TIOCSTI = 0x80017472 + TIOCSTAT = 0x20007465 TIOCSTOP = 0x2000746f TIOCSTSTAMP = 0x8008745a TIOCSWINSZ = 0x80087467 TIOCUCNTL = 0x80047466 + TIOCUCNTL_CBRK = 0x7a + TIOCUCNTL_SBRK = 0x7b TOSTOP = 0x400000 + UTIME_NOW = -0x2 + UTIME_OMIT = -0x1 VDISCARD = 0xf VDSUSP = 0xb VEOF = 0x0 @@ -1367,6 +1593,19 @@ const ( VKILL = 0x5 VLNEXT = 0xe VMIN = 0x10 + VM_ANONMIN = 0x7 + VM_LOADAVG = 0x2 + VM_MALLOC_CONF = 0xc + VM_MAXID = 0xd + VM_MAXSLP = 0xa + VM_METER = 0x1 + VM_NKMEMPAGES = 0x6 + VM_PSSTRINGS = 0x3 + VM_SWAPENCRYPT = 0x5 + VM_USPACE = 0xb + VM_UVMEXP = 0x4 + VM_VNODEMIN = 0x9 + VM_VTEXTMIN = 0x8 VQUIT = 0x9 VREPRINT = 0x6 VSTART = 0xc @@ -1379,8 +1618,8 @@ const ( WCONTINUED = 0x8 WCOREFLAG = 0x80 WNOHANG = 0x1 - WSTOPPED = 0x7f WUNTRACED = 0x2 + XCASE = 0x1000000 ) // Errors @@ -1394,6 +1633,7 @@ const ( EALREADY = syscall.Errno(0x25) EAUTH = syscall.Errno(0x50) EBADF = syscall.Errno(0x9) + EBADMSG = syscall.Errno(0x5c) EBADRPC = syscall.Errno(0x48) EBUSY = syscall.Errno(0x10) ECANCELED = syscall.Errno(0x58) @@ -1420,7 +1660,7 @@ const ( EIPSEC = syscall.Errno(0x52) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x5b) + ELAST = syscall.Errno(0x5f) ELOOP = syscall.Errno(0x3e) EMEDIUMTYPE = syscall.Errno(0x56) EMFILE = syscall.Errno(0x18) @@ -1448,12 +1688,14 @@ const ( ENOTCONN = syscall.Errno(0x39) ENOTDIR = syscall.Errno(0x14) ENOTEMPTY = syscall.Errno(0x42) + ENOTRECOVERABLE = syscall.Errno(0x5d) ENOTSOCK = syscall.Errno(0x26) ENOTSUP = syscall.Errno(0x5b) ENOTTY = syscall.Errno(0x19) ENXIO = syscall.Errno(0x6) EOPNOTSUPP = syscall.Errno(0x2d) EOVERFLOW = syscall.Errno(0x57) + EOWNERDEAD = syscall.Errno(0x5e) EPERM = syscall.Errno(0x1) EPFNOSUPPORT = syscall.Errno(0x2e) EPIPE = syscall.Errno(0x20) @@ -1461,6 +1703,7 @@ const ( EPROCUNAVAIL = syscall.Errno(0x4c) EPROGMISMATCH = syscall.Errno(0x4b) EPROGUNAVAIL = syscall.Errno(0x4a) + EPROTO = syscall.Errno(0x5f) EPROTONOSUPPORT = syscall.Errno(0x2b) EPROTOTYPE = syscall.Errno(0x29) ERANGE = syscall.Errno(0x22) @@ -1557,7 +1800,7 @@ var errorList = [...]struct { {32, "EPIPE", "broken pipe"}, {33, "EDOM", "numerical argument out of domain"}, {34, "ERANGE", "result too large"}, - {35, "EWOULDBLOCK", "resource temporarily unavailable"}, + {35, "EAGAIN", "resource temporarily unavailable"}, {36, "EINPROGRESS", "operation now in progress"}, {37, "EALREADY", "operation already in progress"}, {38, "ENOTSOCK", "socket operation on non-socket"}, @@ -1613,7 +1856,11 @@ var errorList = [...]struct { {88, "ECANCELED", "operation canceled"}, {89, "EIDRM", "identifier removed"}, {90, "ENOMSG", "no message of desired type"}, - {91, "ELAST", "not supported"}, + {91, "ENOTSUP", "not supported"}, + {92, "EBADMSG", "bad message"}, + {93, "ENOTRECOVERABLE", "state not recoverable"}, + {94, "EOWNERDEAD", "previous owner died"}, + {95, "ELAST", "protocol error"}, } // Signal table @@ -1627,7 +1874,7 @@ var signalList = [...]struct { {3, "SIGQUIT", "quit"}, {4, "SIGILL", "illegal instruction"}, {5, "SIGTRAP", "trace/BPT trap"}, - {6, "SIGABRT", "abort trap"}, + {6, "SIGIOT", "abort trap"}, {7, "SIGEMT", "EMT trap"}, {8, "SIGFPE", "floating point exception"}, {9, "SIGKILL", "killed"}, @@ -1654,4 +1901,5 @@ var signalList = [...]struct { {30, "SIGUSR1", "user defined signal 1"}, {31, "SIGUSR2", "user defined signal 2"}, {32, "SIGTHR", "thread AST"}, + {28672, "SIGSTKSZ", "unknown signal"}, } diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index ffaf2d2..a5aeeb9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,openbsd +//go:build amd64 && openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -108,6 +108,15 @@ const ( BPF_DIRECTION_IN = 0x1 BPF_DIRECTION_OUT = 0x2 BPF_DIV = 0x30 + BPF_FILDROP_CAPTURE = 0x1 + BPF_FILDROP_DROP = 0x2 + BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 @@ -136,6 +145,7 @@ const ( BPF_OR = 0x40 BPF_RELEASE = 0x30bb6 BPF_RET = 0x6 + BPF_RND = 0xc0 BPF_RSH = 0x70 BPF_ST = 0x2 BPF_STX = 0x3 @@ -153,6 +163,13 @@ const ( CLOCK_REALTIME = 0x0 CLOCK_THREAD_CPUTIME_ID = 0x4 CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 @@ -169,7 +186,65 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0xc CTL_NET = 0x4 + DIOCADDQUEUE = 0xc110445d + DIOCADDRULE = 0xcd604404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xcd60441a + DIOCCLRIFFLAG = 0xc028445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0e04412 + DIOCCLRSTATUS = 0xc0284416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1204460 + DIOCGETQUEUE = 0xc110445f + DIOCGETQUEUES = 0xc110445e + DIOCGETRULE = 0xcd604407 + DIOCGETRULES = 0xcd604406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0104454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0104419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0284457 + DIOCKILLSRCNODES = 0xc080445b + DIOCKILLSTATES = 0xc0e04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc088444f DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0884450 + DIOCRADDADDRS = 0xc4504443 + DIOCRADDTABLES = 0xc450443d + DIOCRCLRADDRS = 0xc4504442 + DIOCRCLRASTATS = 0xc4504448 + DIOCRCLRTABLES = 0xc450443c + DIOCRCLRTSTATS = 0xc4504441 + DIOCRDELADDRS = 0xc4504444 + DIOCRDELTABLES = 0xc450443e + DIOCRGETADDRS = 0xc4504446 + DIOCRGETASTATS = 0xc4504447 + DIOCRGETTABLES = 0xc450443f + DIOCRGETTSTATS = 0xc4504440 + DIOCRINADEFINE = 0xc450444d + DIOCRSETADDRS = 0xc4504445 + DIOCRSETTFLAGS = 0xc450444a + DIOCRTSTADDRS = 0xc4504449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0284459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0284414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc0104451 + DIOCXCOMMIT = 0xc0104452 + DIOCXROLLBACK = 0xc0104453 DLT_ARCNET = 0x7 DLT_ATM_RFC1483 = 0xb DLT_AX25 = 0x3 @@ -232,6 +307,8 @@ const ( EMUL_ENABLED = 0x1 EMUL_NATIVE = 0x2 ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 ETHERMIN = 0x2e ETHERMTU = 0x5dc ETHERTYPE_8023 = 0x4 @@ -284,6 +361,7 @@ const ( ETHERTYPE_DN = 0x6003 ETHERTYPE_DOGFIGHT = 0x1989 ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e ETHERTYPE_ECMA = 0x803 ETHERTYPE_ENCRYPT = 0x803d ETHERTYPE_ES = 0x805d @@ -315,6 +393,7 @@ const ( ETHERTYPE_LLDP = 0x88cc ETHERTYPE_LOGICRAFT = 0x8148 ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 ETHERTYPE_MATRA = 0x807a ETHERTYPE_MAX = 0xffff ETHERTYPE_MERIT = 0x807c @@ -343,15 +422,17 @@ const ( ETHERTYPE_NCD = 0x8149 ETHERTYPE_NESTAR = 0x8006 ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 ETHERTYPE_NOVELL = 0x8138 ETHERTYPE_NS = 0x600 ETHERTYPE_NSAT = 0x601 ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f ETHERTYPE_NTRAILER = 0x10 ETHERTYPE_OS9 = 0x7007 ETHERTYPE_OS9NET = 0x7009 ETHERTYPE_PACER = 0x80c6 - ETHERTYPE_PAE = 0x888e + ETHERTYPE_PBB = 0x88e7 ETHERTYPE_PCS = 0x4242 ETHERTYPE_PLANNING = 0x8044 ETHERTYPE_PPP = 0x880b @@ -433,10 +514,11 @@ const ( ETHER_VLAN_ENCAP_LEN = 0x4 EVFILT_AIO = -0x3 EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 EVFILT_PROC = -0x5 EVFILT_READ = -0x1 EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x8 + EVFILT_SYSCOUNT = 0x9 EVFILT_TIMER = -0x7 EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 @@ -458,7 +540,7 @@ const ( EV_FLAG1 = 0x2000 EV_ONESHOT = 0x10 EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTPROC = 0x800 @@ -724,6 +806,7 @@ const ( IFT_VOICEOVERCABLE = 0xc6 IFT_VOICEOVERFRAMERELAY = 0x99 IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb IFT_X213 = 0x5d IFT_X25 = 0x5 IFT_X25DDN = 0x4 @@ -789,9 +872,11 @@ const ( IPPROTO_RAW = 0xff IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e + IPPROTO_SCTP = 0x84 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 + IPPROTO_UDPLITE = 0x88 IPV6_AUTH_LEVEL = 0x35 IPV6_AUTOFLOWLABEL = 0x3b IPV6_CHECKSUM = 0x1a @@ -898,6 +983,9 @@ const ( IP_TTL = 0x4 ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IUCLC = 0x1000 IXANY = 0x800 IXOFF = 0x400 @@ -962,12 +1050,26 @@ const ( MNT_ROOTFS = 0x4000 MNT_SOFTDEP = 0x4000000 MNT_STALLED = 0x100000 + MNT_SWAPPABLE = 0x200000 MNT_SYNCHRONOUS = 0x2 MNT_UPDATE = 0x10000 MNT_VISFLAGMASK = 0x400ffff MNT_WAIT = 0x1 MNT_WANTRDWR = 0x2000000 MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" MSG_BCAST = 0x100 MSG_CMSG_CLOEXEC = 0x800 MSG_CTRUNC = 0x20 @@ -980,6 +1082,7 @@ const ( MSG_PEEK = 0x2 MSG_TRUNC = 0x10 MSG_WAITALL = 0x40 + MSG_WAITFORONE = 0x1000 MS_ASYNC = 0x1 MS_INVALIDATE = 0x4 MS_SYNC = 0x2 @@ -988,7 +1091,8 @@ const ( NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 NET_RT_IFNAMES = 0x6 - NET_RT_MAXID = 0x7 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 NFDBITS = 0x20 @@ -1005,6 +1109,7 @@ const ( NOTE_FORK = 0x40000000 NOTE_LINK = 0x10 NOTE_LOWAT = 0x1 + NOTE_OOB = 0x4 NOTE_PCTRLMASK = 0xf0000000 NOTE_PDATAMASK = 0xfffff NOTE_RENAME = 0x20 @@ -1122,9 +1227,11 @@ const ( RTF_STATIC = 0x800 RTF_UP = 0x1 RTF_USETRAILERS = 0x8000 + RTM_80211INFO = 0x15 RTM_ADD = 0x1 RTM_BFD = 0x12 RTM_CHANGE = 0x3 + RTM_CHGADDRATTR = 0x14 RTM_DELADDR = 0xd RTM_DELETE = 0x2 RTM_DESYNC = 0x10 @@ -1132,7 +1239,6 @@ const ( RTM_IFANNOUNCE = 0xf RTM_IFINFO = 0xe RTM_INVALIDATE = 0x11 - RTM_LOCK = 0x8 RTM_LOSING = 0x5 RTM_MAXSIZE = 0x800 RTM_MISS = 0x7 @@ -1140,7 +1246,7 @@ const ( RTM_PROPOSAL = 0x13 RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 + RTM_SOURCE = 0x16 RTM_VERSION = 0x5 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 @@ -1158,6 +1264,9 @@ const ( RUSAGE_THREAD = 0x1 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1174,35 +1283,37 @@ const ( SIOCBRDGDELS = 0x80606942 SIOCBRDGFLUSH = 0x80606948 SIOCBRDGFRL = 0x808c694e - SIOCBRDGGCACHE = 0xc0186941 - SIOCBRDGGFD = 0xc0186952 - SIOCBRDGGHT = 0xc0186951 + SIOCBRDGGCACHE = 0xc0146941 + SIOCBRDGGFD = 0xc0146952 + SIOCBRDGGHT = 0xc0146951 SIOCBRDGGIFFLGS = 0xc060693e - SIOCBRDGGMA = 0xc0186953 + SIOCBRDGGMA = 0xc0146953 SIOCBRDGGPARAM = 0xc0406958 - SIOCBRDGGPRI = 0xc0186950 + SIOCBRDGGPRI = 0xc0146950 SIOCBRDGGRL = 0xc030694f - SIOCBRDGGTO = 0xc0186946 + SIOCBRDGGTO = 0xc0146946 SIOCBRDGIFS = 0xc0606942 SIOCBRDGRTS = 0xc0206943 SIOCBRDGSADDR = 0xc1286944 - SIOCBRDGSCACHE = 0x80186940 - SIOCBRDGSFD = 0x80186952 - SIOCBRDGSHT = 0x80186951 + SIOCBRDGSCACHE = 0x80146940 + SIOCBRDGSFD = 0x80146952 + SIOCBRDGSHT = 0x80146951 SIOCBRDGSIFCOST = 0x80606955 SIOCBRDGSIFFLGS = 0x8060693f SIOCBRDGSIFPRIO = 0x80606954 SIOCBRDGSIFPROT = 0x8060694a - SIOCBRDGSMA = 0x80186953 - SIOCBRDGSPRI = 0x80186950 - SIOCBRDGSPROTO = 0x8018695a - SIOCBRDGSTO = 0x80186945 - SIOCBRDGSTXHC = 0x80186959 + SIOCBRDGSMA = 0x80146953 + SIOCBRDGSPRI = 0x80146950 + SIOCBRDGSPROTO = 0x8014695a + SIOCBRDGSTO = 0x80146945 + SIOCBRDGSTXHC = 0x80146959 + SIOCDELLABEL = 0x80206997 SIOCDELMULTI = 0x80206932 SIOCDIFADDR = 0x80206919 SIOCDIFGROUP = 0x80286989 SIOCDIFPARENT = 0x802069b4 SIOCDIFPHYADDR = 0x80206949 + SIOCDPWE3NEIGHBOR = 0x802069de SIOCDVNETID = 0x802069af SIOCGETKALIVE = 0xc01869a4 SIOCGETLABEL = 0x8020699a @@ -1221,6 +1332,7 @@ const ( SIOCGIFFLAGS = 0xc0206911 SIOCGIFGATTR = 0xc028698b SIOCGIFGENERIC = 0xc020693a + SIOCGIFGLIST = 0xc028698d SIOCGIFGMEMB = 0xc028698a SIOCGIFGROUP = 0xc0286988 SIOCGIFHARDMTU = 0xc02069a5 @@ -1235,13 +1347,21 @@ const ( SIOCGIFRDOMAIN = 0xc02069a0 SIOCGIFRTLABEL = 0xc0206983 SIOCGIFRXR = 0x802069aa + SIOCGIFSFFPAGE = 0xc1126939 SIOCGIFXFLAGS = 0xc020699e SIOCGLIFPHYADDR = 0xc218694b SIOCGLIFPHYDF = 0xc02069c2 + SIOCGLIFPHYECN = 0xc02069c8 SIOCGLIFPHYRTABLE = 0xc02069a2 SIOCGLIFPHYTTL = 0xc02069a9 SIOCGPGRP = 0x40047309 + SIOCGPWE3 = 0xc0206998 + SIOCGPWE3CTRLWORD = 0xc02069dc + SIOCGPWE3FAT = 0xc02069dd + SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db SIOCGSPPPPARAMS = 0xc0206994 + SIOCGTXHPRIO = 0xc02069c6 SIOCGUMBINFO = 0xc02069be SIOCGUMBPARAM = 0xc02069c0 SIOCGVH = 0xc02069f6 @@ -1279,19 +1399,20 @@ const ( SIOCSIFXFLAGS = 0x8020699d SIOCSLIFPHYADDR = 0x8218694a SIOCSLIFPHYDF = 0x802069c1 + SIOCSLIFPHYECN = 0x802069c7 SIOCSLIFPHYRTABLE = 0x802069a1 SIOCSLIFPHYTTL = 0x802069a8 SIOCSPGRP = 0x80047308 + SIOCSPWE3CTRLWORD = 0x802069dc + SIOCSPWE3FAT = 0x802069dd + SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db SIOCSSPPPPARAMS = 0x80206993 + SIOCSTXHPRIO = 0x802069c5 SIOCSUMBPARAM = 0x802069bf SIOCSVH = 0xc02069f5 SIOCSVNETFLOWID = 0x802069c3 SIOCSVNETID = 0x802069a6 - SIOCSWGDPID = 0xc018695b - SIOCSWGMAXFLOW = 0xc0186960 - SIOCSWGMAXGROUP = 0xc018695d - SIOCSWSDPID = 0x8018695c - SIOCSWSPORTNO = 0xc060695f SOCK_CLOEXEC = 0x8000 SOCK_DGRAM = 0x2 SOCK_DNS = 0x1000 @@ -1306,6 +1427,7 @@ const ( SO_BINDANY = 0x1000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 @@ -1313,6 +1435,7 @@ const ( SO_NETPROC = 0x1020 SO_OOBINLINE = 0x100 SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 @@ -1362,7 +1485,18 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 - TCP_MAXBURST = 0x4 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 TCP_MAXSEG = 0x2 TCP_MAXWIN = 0xffff TCP_MAX_SACK = 0x3 @@ -1371,8 +1505,11 @@ const ( TCP_MSS = 0x200 TCP_NODELAY = 0x1 TCP_NOPUSH = 0x10 + TCP_SACKHOLE_LIMIT = 0x80 TCP_SACK_ENABLE = 0x8 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 TIOCCHKVERAUTH = 0x2000741e @@ -1437,7 +1574,6 @@ const ( TIOCSPGRP = 0x80047476 TIOCSTART = 0x2000746e TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 TIOCSTOP = 0x2000746f TIOCSTSTAMP = 0x8008745a TIOCSWINSZ = 0x80087467 @@ -1459,7 +1595,8 @@ const ( VMIN = 0x10 VM_ANONMIN = 0x7 VM_LOADAVG = 0x2 - VM_MAXID = 0xc + VM_MALLOC_CONF = 0xc + VM_MAXID = 0xd VM_MAXSLP = 0xa VM_METER = 0x1 VM_NKMEMPAGES = 0x6 @@ -1737,7 +1874,7 @@ var signalList = [...]struct { {3, "SIGQUIT", "quit"}, {4, "SIGILL", "illegal instruction"}, {5, "SIGTRAP", "trace/BPT trap"}, - {6, "SIGABRT", "abort trap"}, + {6, "SIGIOT", "abort trap"}, {7, "SIGEMT", "EMT trap"}, {8, "SIGFPE", "floating point exception"}, {9, "SIGKILL", "killed"}, @@ -1764,4 +1901,5 @@ var signalList = [...]struct { {30, "SIGUSR1", "user defined signal 1"}, {31, "SIGUSR2", "user defined signal 2"}, {32, "SIGTHR", "thread AST"}, + {28672, "SIGSTKSZ", "unknown signal"}, } diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go index 7aa796a..0e9748a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -1,7 +1,7 @@ // mkerrors.sh // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,openbsd +//go:build arm && openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go @@ -45,6 +45,7 @@ const ( AF_SNA = 0xb AF_UNIX = 0x1 AF_UNSPEC = 0x0 + ALTWERASE = 0x200 ARPHRD_ETHER = 0x1 ARPHRD_FRELAY = 0xf ARPHRD_IEEE1394 = 0x18 @@ -81,7 +82,7 @@ const ( BIOCGFILDROP = 0x40044278 BIOCGHDRCMPLT = 0x40044274 BIOCGRSIG = 0x40044273 - BIOCGRTIMEOUT = 0x400c426e + BIOCGRTIMEOUT = 0x4010426e BIOCGSTATS = 0x4008426f BIOCIMMEDIATE = 0x80044270 BIOCLOCK = 0x20004276 @@ -95,7 +96,7 @@ const ( BIOCSFILDROP = 0x80044279 BIOCSHDRCMPLT = 0x80044275 BIOCSRSIG = 0x80044272 - BIOCSRTIMEOUT = 0x800c426d + BIOCSRTIMEOUT = 0x8010426d BIOCVERSION = 0x40044271 BPF_A = 0x10 BPF_ABS = 0x20 @@ -107,6 +108,15 @@ const ( BPF_DIRECTION_IN = 0x1 BPF_DIRECTION_OUT = 0x2 BPF_DIV = 0x30 + BPF_FILDROP_CAPTURE = 0x1 + BPF_FILDROP_DROP = 0x2 + BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 @@ -135,6 +145,7 @@ const ( BPF_OR = 0x40 BPF_RELEASE = 0x30bb6 BPF_RET = 0x6 + BPF_RND = 0xc0 BPF_RSH = 0x70 BPF_ST = 0x2 BPF_STX = 0x3 @@ -146,6 +157,19 @@ const ( BRKINT = 0x2 CFLUSH = 0xf CLOCAL = 0x8000 + CLOCK_BOOTTIME = 0x6 + CLOCK_MONOTONIC = 0x3 + CLOCK_PROCESS_CPUTIME_ID = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x4 + CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 @@ -162,7 +186,65 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0xc CTL_NET = 0x4 + DIOCADDQUEUE = 0xc100445d + DIOCADDRULE = 0xcce04404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xcce0441a + DIOCCLRIFFLAG = 0xc024445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0d04412 + DIOCCLRSTATUS = 0xc0244416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1084460 + DIOCGETQUEUE = 0xc100445f + DIOCGETQUEUES = 0xc100445e + DIOCGETRULE = 0xcce04407 + DIOCGETRULES = 0xcce04406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0084454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0084419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0244457 + DIOCKILLSRCNODES = 0xc068445b + DIOCKILLSTATES = 0xc0d04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc088444f DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0884450 + DIOCRADDADDRS = 0xc44c4443 + DIOCRADDTABLES = 0xc44c443d + DIOCRCLRADDRS = 0xc44c4442 + DIOCRCLRASTATS = 0xc44c4448 + DIOCRCLRTABLES = 0xc44c443c + DIOCRCLRTSTATS = 0xc44c4441 + DIOCRDELADDRS = 0xc44c4444 + DIOCRDELTABLES = 0xc44c443e + DIOCRGETADDRS = 0xc44c4446 + DIOCRGETASTATS = 0xc44c4447 + DIOCRGETTABLES = 0xc44c443f + DIOCRGETTSTATS = 0xc44c4440 + DIOCRINADEFINE = 0xc44c444d + DIOCRSETADDRS = 0xc44c4445 + DIOCRSETTFLAGS = 0xc44c444a + DIOCRTSTADDRS = 0xc44c4449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0244459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0244414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc00c4451 + DIOCXCOMMIT = 0xc00c4452 + DIOCXROLLBACK = 0xc00c4453 DLT_ARCNET = 0x7 DLT_ATM_RFC1483 = 0xb DLT_AX25 = 0x3 @@ -178,6 +260,7 @@ const ( DLT_LOOP = 0xc DLT_MPLS = 0xdb DLT_NULL = 0x0 + DLT_OPENFLOW = 0x10b DLT_PFLOG = 0x75 DLT_PFSYNC = 0x12 DLT_PPP = 0x9 @@ -188,6 +271,23 @@ const ( DLT_RAW = 0xe DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xf + DLT_USBPCAP = 0xf9 + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -207,6 +307,8 @@ const ( EMUL_ENABLED = 0x1 EMUL_NATIVE = 0x2 ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 ETHERMIN = 0x2e ETHERMTU = 0x5dc ETHERTYPE_8023 = 0x4 @@ -259,6 +361,7 @@ const ( ETHERTYPE_DN = 0x6003 ETHERTYPE_DOGFIGHT = 0x1989 ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e ETHERTYPE_ECMA = 0x803 ETHERTYPE_ENCRYPT = 0x803d ETHERTYPE_ES = 0x805d @@ -290,6 +393,7 @@ const ( ETHERTYPE_LLDP = 0x88cc ETHERTYPE_LOGICRAFT = 0x8148 ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 ETHERTYPE_MATRA = 0x807a ETHERTYPE_MAX = 0xffff ETHERTYPE_MERIT = 0x807c @@ -318,15 +422,17 @@ const ( ETHERTYPE_NCD = 0x8149 ETHERTYPE_NESTAR = 0x8006 ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 ETHERTYPE_NOVELL = 0x8138 ETHERTYPE_NS = 0x600 ETHERTYPE_NSAT = 0x601 ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f ETHERTYPE_NTRAILER = 0x10 ETHERTYPE_OS9 = 0x7007 ETHERTYPE_OS9NET = 0x7009 ETHERTYPE_PACER = 0x80c6 - ETHERTYPE_PAE = 0x888e + ETHERTYPE_PBB = 0x88e7 ETHERTYPE_PCS = 0x4242 ETHERTYPE_PLANNING = 0x8044 ETHERTYPE_PPP = 0x880b @@ -401,28 +507,40 @@ const ( ETHER_CRC_POLY_LE = 0xedb88320 ETHER_HDR_LEN = 0xe ETHER_MAX_DIX_LEN = 0x600 + ETHER_MAX_HARDMTU_LEN = 0xff9b ETHER_MAX_LEN = 0x5ee ETHER_MIN_LEN = 0x40 ETHER_TYPE_LEN = 0x2 ETHER_VLAN_ENCAP_LEN = 0x4 EVFILT_AIO = -0x3 + EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 EVFILT_PROC = -0x5 EVFILT_READ = -0x1 EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x7 + EVFILT_SYSCOUNT = 0x9 EVFILT_TIMER = -0x7 EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 + EVL_ENCAPLEN = 0x4 + EVL_PRIO_BITS = 0xd + EVL_PRIO_MAX = 0x7 + EVL_VLID_MASK = 0xfff + EVL_VLID_MAX = 0xffe + EVL_VLID_MIN = 0x1 + EVL_VLID_NULL = 0x0 EV_ADD = 0x1 EV_CLEAR = 0x20 EV_DELETE = 0x2 EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 EV_ENABLE = 0x4 EV_EOF = 0x8000 EV_ERROR = 0x4000 EV_FLAG1 = 0x2000 EV_ONESHOT = 0x10 - EV_SYSFLAGS = 0xf000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTPROC = 0x800 @@ -435,6 +553,8 @@ const ( F_GETFL = 0x3 F_GETLK = 0x7 F_GETOWN = 0x5 + F_ISATTY = 0xb + F_OK = 0x0 F_RDLCK = 0x1 F_SETFD = 0x2 F_SETFL = 0x4 @@ -451,7 +571,6 @@ const ( IEXTEN = 0x400 IFAN_ARRIVAL = 0x0 IFAN_DEPARTURE = 0x1 - IFA_ROUTE = 0x1 IFF_ALLMULTI = 0x200 IFF_BROADCAST = 0x2 IFF_CANTCHANGE = 0x8e52 @@ -462,12 +581,12 @@ const ( IFF_LOOPBACK = 0x8 IFF_MULTICAST = 0x8000 IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 IFF_OACTIVE = 0x400 IFF_POINTOPOINT = 0x10 IFF_PROMISC = 0x100 IFF_RUNNING = 0x40 IFF_SIMPLEX = 0x800 + IFF_STATICARP = 0x20 IFF_UP = 0x1 IFNAMSIZ = 0x10 IFT_1822 = 0x2 @@ -596,6 +715,7 @@ const ( IFT_LINEGROUP = 0xd2 IFT_LOCALTALK = 0x2a IFT_LOOP = 0x18 + IFT_MBIM = 0xfa IFT_MEDIAMAILOVERIP = 0x8b IFT_MFSIGLINK = 0xa7 IFT_MIOX25 = 0x26 @@ -686,6 +806,7 @@ const ( IFT_VOICEOVERCABLE = 0xc6 IFT_VOICEOVERFRAMERELAY = 0x99 IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb IFT_X213 = 0x5d IFT_X25 = 0x5 IFT_X25DDN = 0x4 @@ -720,8 +841,6 @@ const ( IPPROTO_AH = 0x33 IPPROTO_CARP = 0x70 IPPROTO_DIVERT = 0x102 - IPPROTO_DIVERT_INIT = 0x2 - IPPROTO_DIVERT_RESP = 0x1 IPPROTO_DONE = 0x101 IPPROTO_DSTOPTS = 0x3c IPPROTO_EGP = 0x8 @@ -753,9 +872,11 @@ const ( IPPROTO_RAW = 0xff IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e + IPPROTO_SCTP = 0x84 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 + IPPROTO_UDPLITE = 0x88 IPV6_AUTH_LEVEL = 0x35 IPV6_AUTOFLOWLABEL = 0x3b IPV6_CHECKSUM = 0x1a @@ -778,6 +899,7 @@ const ( IPV6_LEAVE_GROUP = 0xd IPV6_MAXHLIM = 0xff IPV6_MAXPACKET = 0xffff + IPV6_MINHOPCOUNT = 0x41 IPV6_MMTU = 0x500 IPV6_MULTICAST_HOPS = 0xa IPV6_MULTICAST_IF = 0x9 @@ -817,12 +939,12 @@ const ( IP_DEFAULT_MULTICAST_LOOP = 0x1 IP_DEFAULT_MULTICAST_TTL = 0x1 IP_DF = 0x4000 - IP_DIVERTFL = 0x1022 IP_DROP_MEMBERSHIP = 0xd IP_ESP_NETWORK_LEVEL = 0x16 IP_ESP_TRANS_LEVEL = 0x15 IP_HDRINCL = 0x2 IP_IPCOMP_LEVEL = 0x1d + IP_IPDEFTTL = 0x25 IP_IPSECFLOWINFO = 0x24 IP_IPSEC_LOCAL_AUTH = 0x1b IP_IPSEC_LOCAL_CRED = 0x19 @@ -856,10 +978,15 @@ const ( IP_RETOPTS = 0x8 IP_RF = 0x8000 IP_RTABLE = 0x1021 + IP_SENDSRCADDR = 0x7 IP_TOS = 0x3 IP_TTL = 0x4 ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 + IUCLC = 0x1000 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -914,6 +1041,7 @@ const ( MNT_NOATIME = 0x8000 MNT_NODEV = 0x10 MNT_NOEXEC = 0x4 + MNT_NOPERM = 0x20 MNT_NOSUID = 0x8 MNT_NOWAIT = 0x2 MNT_QUOTA = 0x2000 @@ -921,12 +1049,27 @@ const ( MNT_RELOAD = 0x40000 MNT_ROOTFS = 0x4000 MNT_SOFTDEP = 0x4000000 + MNT_STALLED = 0x100000 + MNT_SWAPPABLE = 0x200000 MNT_SYNCHRONOUS = 0x2 MNT_UPDATE = 0x10000 MNT_VISFLAGMASK = 0x400ffff MNT_WAIT = 0x1 MNT_WANTRDWR = 0x2000000 MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" MSG_BCAST = 0x100 MSG_CMSG_CLOEXEC = 0x800 MSG_CTRUNC = 0x20 @@ -939,6 +1082,7 @@ const ( MSG_PEEK = 0x2 MSG_TRUNC = 0x10 MSG_WAITALL = 0x40 + MSG_WAITFORONE = 0x1000 MS_ASYNC = 0x1 MS_INVALIDATE = 0x4 MS_SYNC = 0x2 @@ -946,12 +1090,16 @@ const ( NET_RT_DUMP = 0x1 NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 - NET_RT_MAXID = 0x6 + NET_RT_IFNAMES = 0x6 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 NFDBITS = 0x20 NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 NOTE_ATTRIB = 0x8 + NOTE_CHANGE = 0x1 NOTE_CHILD = 0x4 NOTE_DELETE = 0x1 NOTE_EOF = 0x2 @@ -961,6 +1109,7 @@ const ( NOTE_FORK = 0x40000000 NOTE_LINK = 0x10 NOTE_LOWAT = 0x1 + NOTE_OOB = 0x4 NOTE_PCTRLMASK = 0xf0000000 NOTE_PDATAMASK = 0xfffff NOTE_RENAME = 0x20 @@ -970,11 +1119,13 @@ const ( NOTE_TRUNCATE = 0x80 NOTE_WRITE = 0x2 OCRNL = 0x10 + OLCUC = 0x20 ONLCR = 0x2 ONLRET = 0x80 ONOCR = 0x40 ONOEOT = 0x8 OPOST = 0x1 + OXTABS = 0x4 O_ACCMODE = 0x3 O_APPEND = 0x8 O_ASYNC = 0x40 @@ -1012,23 +1163,32 @@ const ( RLIMIT_CPU = 0x0 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 + RTAX_BFD = 0xb RTAX_BRD = 0x7 + RTAX_DNS = 0xc RTAX_DST = 0x0 RTAX_GATEWAY = 0x1 RTAX_GENMASK = 0x3 RTAX_IFA = 0x5 RTAX_IFP = 0x4 RTAX_LABEL = 0xa - RTAX_MAX = 0xb + RTAX_MAX = 0xf RTAX_NETMASK = 0x2 + RTAX_SEARCH = 0xe RTAX_SRC = 0x8 RTAX_SRCMASK = 0x9 + RTAX_STATIC = 0xd RTA_AUTHOR = 0x40 + RTA_BFD = 0x800 RTA_BRD = 0x80 + RTA_DNS = 0x1000 RTA_DST = 0x1 RTA_GATEWAY = 0x2 RTA_GENMASK = 0x8 @@ -1036,24 +1196,29 @@ const ( RTA_IFP = 0x10 RTA_LABEL = 0x400 RTA_NETMASK = 0x4 + RTA_SEARCH = 0x4000 RTA_SRC = 0x100 RTA_SRCMASK = 0x200 + RTA_STATIC = 0x2000 RTF_ANNOUNCE = 0x4000 + RTF_BFD = 0x1000000 RTF_BLACKHOLE = 0x1000 RTF_BROADCAST = 0x400000 + RTF_CACHED = 0x20000 RTF_CLONED = 0x10000 RTF_CLONING = 0x100 + RTF_CONNECTED = 0x800000 RTF_DONE = 0x40 RTF_DYNAMIC = 0x10 - RTF_FMASK = 0x70f808 + RTF_FMASK = 0x110fc08 RTF_GATEWAY = 0x2 RTF_HOST = 0x4 RTF_LLINFO = 0x400 RTF_LOCAL = 0x200000 - RTF_MASK = 0x80 RTF_MODIFIED = 0x20 RTF_MPATH = 0x40000 RTF_MPLS = 0x100000 + RTF_MULTICAST = 0x200 RTF_PERMANENT_ARP = 0x2000 RTF_PROTO1 = 0x8000 RTF_PROTO2 = 0x4000 @@ -1062,23 +1227,26 @@ const ( RTF_STATIC = 0x800 RTF_UP = 0x1 RTF_USETRAILERS = 0x8000 - RTF_XRESOLVE = 0x200 + RTM_80211INFO = 0x15 RTM_ADD = 0x1 + RTM_BFD = 0x12 RTM_CHANGE = 0x3 + RTM_CHGADDRATTR = 0x14 RTM_DELADDR = 0xd RTM_DELETE = 0x2 RTM_DESYNC = 0x10 RTM_GET = 0x4 RTM_IFANNOUNCE = 0xf RTM_IFINFO = 0xe - RTM_LOCK = 0x8 + RTM_INVALIDATE = 0x11 RTM_LOSING = 0x5 RTM_MAXSIZE = 0x800 RTM_MISS = 0x7 RTM_NEWADDR = 0xc + RTM_PROPOSAL = 0x13 RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 + RTM_SOURCE = 0x16 RTM_VERSION = 0x5 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 @@ -1088,67 +1256,74 @@ const ( RTV_RTTVAR = 0x80 RTV_SPIPE = 0x10 RTV_SSTHRESH = 0x20 + RT_TABLEID_BITS = 0x8 + RT_TABLEID_MASK = 0xff RT_TABLEID_MAX = 0xff RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 RUSAGE_THREAD = 0x1 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 SIOCADDMULTI = 0x80206931 SIOCAIFADDR = 0x8040691a SIOCAIFGROUP = 0x80246987 - SIOCALIFADDR = 0x8218691c SIOCATMARK = 0x40047307 - SIOCBRDGADD = 0x8054693c - SIOCBRDGADDS = 0x80546941 - SIOCBRDGARL = 0x806e694d + SIOCBRDGADD = 0x8060693c + SIOCBRDGADDL = 0x80606949 + SIOCBRDGADDS = 0x80606941 + SIOCBRDGARL = 0x808c694d SIOCBRDGDADDR = 0x81286947 - SIOCBRDGDEL = 0x8054693d - SIOCBRDGDELS = 0x80546942 - SIOCBRDGFLUSH = 0x80546948 - SIOCBRDGFRL = 0x806e694e + SIOCBRDGDEL = 0x8060693d + SIOCBRDGDELS = 0x80606942 + SIOCBRDGFLUSH = 0x80606948 + SIOCBRDGFRL = 0x808c694e SIOCBRDGGCACHE = 0xc0146941 SIOCBRDGGFD = 0xc0146952 SIOCBRDGGHT = 0xc0146951 - SIOCBRDGGIFFLGS = 0xc054693e + SIOCBRDGGIFFLGS = 0xc060693e SIOCBRDGGMA = 0xc0146953 - SIOCBRDGGPARAM = 0xc03c6958 + SIOCBRDGGPARAM = 0xc0406958 SIOCBRDGGPRI = 0xc0146950 SIOCBRDGGRL = 0xc028694f - SIOCBRDGGSIFS = 0xc054693c SIOCBRDGGTO = 0xc0146946 - SIOCBRDGIFS = 0xc0546942 + SIOCBRDGIFS = 0xc0606942 SIOCBRDGRTS = 0xc0186943 SIOCBRDGSADDR = 0xc1286944 SIOCBRDGSCACHE = 0x80146940 SIOCBRDGSFD = 0x80146952 SIOCBRDGSHT = 0x80146951 - SIOCBRDGSIFCOST = 0x80546955 - SIOCBRDGSIFFLGS = 0x8054693f - SIOCBRDGSIFPRIO = 0x80546954 + SIOCBRDGSIFCOST = 0x80606955 + SIOCBRDGSIFFLGS = 0x8060693f + SIOCBRDGSIFPRIO = 0x80606954 + SIOCBRDGSIFPROT = 0x8060694a SIOCBRDGSMA = 0x80146953 SIOCBRDGSPRI = 0x80146950 SIOCBRDGSPROTO = 0x8014695a SIOCBRDGSTO = 0x80146945 SIOCBRDGSTXHC = 0x80146959 + SIOCDELLABEL = 0x80206997 SIOCDELMULTI = 0x80206932 SIOCDIFADDR = 0x80206919 SIOCDIFGROUP = 0x80246989 + SIOCDIFPARENT = 0x802069b4 SIOCDIFPHYADDR = 0x80206949 - SIOCDLIFADDR = 0x8218691e + SIOCDPWE3NEIGHBOR = 0x802069de + SIOCDVNETID = 0x802069af SIOCGETKALIVE = 0xc01869a4 SIOCGETLABEL = 0x8020699a + SIOCGETMPWCFG = 0xc02069ae SIOCGETPFLOW = 0xc02069fe SIOCGETPFSYNC = 0xc02069f8 SIOCGETSGCNT = 0xc0147534 SIOCGETVIFCNT = 0xc0147533 SIOCGETVLAN = 0xc0206990 - SIOCGHIWAT = 0x40047301 SIOCGIFADDR = 0xc0206921 - SIOCGIFASYNCMAP = 0xc020697c SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCONF = 0xc0086924 SIOCGIFDATA = 0xc020691b @@ -1157,41 +1332,53 @@ const ( SIOCGIFFLAGS = 0xc0206911 SIOCGIFGATTR = 0xc024698b SIOCGIFGENERIC = 0xc020693a + SIOCGIFGLIST = 0xc024698d SIOCGIFGMEMB = 0xc024698a SIOCGIFGROUP = 0xc0246988 SIOCGIFHARDMTU = 0xc02069a5 - SIOCGIFMEDIA = 0xc0286936 + SIOCGIFLLPRIO = 0xc02069b6 + SIOCGIFMEDIA = 0xc0386938 SIOCGIFMETRIC = 0xc0206917 SIOCGIFMTU = 0xc020697e SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206948 + SIOCGIFPAIR = 0xc02069b1 + SIOCGIFPARENT = 0xc02069b3 SIOCGIFPRIORITY = 0xc020699c - SIOCGIFPSRCADDR = 0xc0206947 SIOCGIFRDOMAIN = 0xc02069a0 SIOCGIFRTLABEL = 0xc0206983 SIOCGIFRXR = 0x802069aa - SIOCGIFTIMESLOT = 0xc0206986 + SIOCGIFSFFPAGE = 0xc1126939 SIOCGIFXFLAGS = 0xc020699e - SIOCGLIFADDR = 0xc218691d SIOCGLIFPHYADDR = 0xc218694b + SIOCGLIFPHYDF = 0xc02069c2 + SIOCGLIFPHYECN = 0xc02069c8 SIOCGLIFPHYRTABLE = 0xc02069a2 SIOCGLIFPHYTTL = 0xc02069a9 - SIOCGLOWAT = 0x40047303 SIOCGPGRP = 0x40047309 + SIOCGPWE3 = 0xc0206998 + SIOCGPWE3CTRLWORD = 0xc02069dc + SIOCGPWE3FAT = 0xc02069dd + SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db SIOCGSPPPPARAMS = 0xc0206994 + SIOCGTXHPRIO = 0xc02069c6 + SIOCGUMBINFO = 0xc02069be + SIOCGUMBPARAM = 0xc02069c0 SIOCGVH = 0xc02069f6 + SIOCGVNETFLOWID = 0xc02069c4 SIOCGVNETID = 0xc02069a7 + SIOCIFAFATTACH = 0x801169ab + SIOCIFAFDETACH = 0x801169ac SIOCIFCREATE = 0x8020697a SIOCIFDESTROY = 0x80206979 SIOCIFGCLONERS = 0xc00c6978 SIOCSETKALIVE = 0x801869a3 SIOCSETLABEL = 0x80206999 + SIOCSETMPWCFG = 0x802069ad SIOCSETPFLOW = 0x802069fd SIOCSETPFSYNC = 0x802069f7 SIOCSETVLAN = 0x8020698f - SIOCSHIWAT = 0x80047300 SIOCSIFADDR = 0x8020690c - SIOCSIFASYNCMAP = 0x8020697d SIOCSIFBRDADDR = 0x80206913 SIOCSIFDESCR = 0x80206980 SIOCSIFDSTADDR = 0x8020690e @@ -1199,26 +1386,36 @@ const ( SIOCSIFGATTR = 0x8024698c SIOCSIFGENERIC = 0x80206939 SIOCSIFLLADDR = 0x8020691f - SIOCSIFMEDIA = 0xc0206935 + SIOCSIFLLPRIO = 0x802069b5 + SIOCSIFMEDIA = 0xc0206937 SIOCSIFMETRIC = 0x80206918 SIOCSIFMTU = 0x8020697f SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x80406946 + SIOCSIFPAIR = 0x802069b0 + SIOCSIFPARENT = 0x802069b2 SIOCSIFPRIORITY = 0x8020699b SIOCSIFRDOMAIN = 0x8020699f SIOCSIFRTLABEL = 0x80206982 - SIOCSIFTIMESLOT = 0x80206985 SIOCSIFXFLAGS = 0x8020699d SIOCSLIFPHYADDR = 0x8218694a + SIOCSLIFPHYDF = 0x802069c1 + SIOCSLIFPHYECN = 0x802069c7 SIOCSLIFPHYRTABLE = 0x802069a1 SIOCSLIFPHYTTL = 0x802069a8 - SIOCSLOWAT = 0x80047302 SIOCSPGRP = 0x80047308 + SIOCSPWE3CTRLWORD = 0x802069dc + SIOCSPWE3FAT = 0x802069dd + SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db SIOCSSPPPPARAMS = 0x80206993 + SIOCSTXHPRIO = 0x802069c5 + SIOCSUMBPARAM = 0x802069bf SIOCSVH = 0xc02069f5 + SIOCSVNETFLOWID = 0x802069c3 SIOCSVNETID = 0x802069a6 SOCK_CLOEXEC = 0x8000 SOCK_DGRAM = 0x2 + SOCK_DNS = 0x1000 SOCK_NONBLOCK = 0x4000 SOCK_RAW = 0x3 SOCK_RDM = 0x4 @@ -1230,6 +1427,7 @@ const ( SO_BINDANY = 0x1000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 @@ -1237,6 +1435,7 @@ const ( SO_NETPROC = 0x1020 SO_OOBINLINE = 0x100 SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 @@ -1250,6 +1449,7 @@ const ( SO_TIMESTAMP = 0x800 SO_TYPE = 0x1008 SO_USELOOPBACK = 0x40 + SO_ZEROIZE = 0x2000 S_BLKSIZE = 0x200 S_IEXEC = 0x40 S_IFBLK = 0x6000 @@ -1279,9 +1479,24 @@ const ( S_IXOTH = 0x1 S_IXUSR = 0x40 TCIFLUSH = 0x1 + TCIOFF = 0x3 TCIOFLUSH = 0x3 + TCION = 0x4 TCOFLUSH = 0x2 - TCP_MAXBURST = 0x4 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 TCP_MAXSEG = 0x2 TCP_MAXWIN = 0xffff TCP_MAX_SACK = 0x3 @@ -1290,11 +1505,15 @@ const ( TCP_MSS = 0x200 TCP_NODELAY = 0x1 TCP_NOPUSH = 0x10 - TCP_NSTATES = 0xb + TCP_SACKHOLE_LIMIT = 0x80 TCP_SACK_ENABLE = 0x8 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 + TIOCCHKVERAUTH = 0x2000741e + TIOCCLRVERAUTH = 0x2000741d TIOCCONS = 0x80047462 TIOCDRAIN = 0x2000745e TIOCEXCL = 0x2000740d @@ -1310,7 +1529,7 @@ const ( TIOCGFLAGS = 0x4004745d TIOCGPGRP = 0x40047477 TIOCGSID = 0x40047463 - TIOCGTSTAMP = 0x400c745b + TIOCGTSTAMP = 0x4010745b TIOCGWINSZ = 0x40087468 TIOCMBIC = 0x8004746b TIOCMBIS = 0x8004746c @@ -1349,17 +1568,21 @@ const ( TIOCSETAF = 0x802c7416 TIOCSETAW = 0x802c7415 TIOCSETD = 0x8004741b + TIOCSETVERAUTH = 0x8004741c TIOCSFLAGS = 0x8004745c TIOCSIG = 0x8004745f TIOCSPGRP = 0x80047476 TIOCSTART = 0x2000746e - TIOCSTAT = 0x80047465 - TIOCSTI = 0x80017472 + TIOCSTAT = 0x20007465 TIOCSTOP = 0x2000746f TIOCSTSTAMP = 0x8008745a TIOCSWINSZ = 0x80087467 TIOCUCNTL = 0x80047466 + TIOCUCNTL_CBRK = 0x7a + TIOCUCNTL_SBRK = 0x7b TOSTOP = 0x400000 + UTIME_NOW = -0x2 + UTIME_OMIT = -0x1 VDISCARD = 0xf VDSUSP = 0xb VEOF = 0x0 @@ -1370,6 +1593,19 @@ const ( VKILL = 0x5 VLNEXT = 0xe VMIN = 0x10 + VM_ANONMIN = 0x7 + VM_LOADAVG = 0x2 + VM_MALLOC_CONF = 0xc + VM_MAXID = 0xd + VM_MAXSLP = 0xa + VM_METER = 0x1 + VM_NKMEMPAGES = 0x6 + VM_PSSTRINGS = 0x3 + VM_SWAPENCRYPT = 0x5 + VM_USPACE = 0xb + VM_UVMEXP = 0x4 + VM_VNODEMIN = 0x9 + VM_VTEXTMIN = 0x8 VQUIT = 0x9 VREPRINT = 0x6 VSTART = 0xc @@ -1383,6 +1619,7 @@ const ( WCOREFLAG = 0x80 WNOHANG = 0x1 WUNTRACED = 0x2 + XCASE = 0x1000000 ) // Errors @@ -1396,6 +1633,7 @@ const ( EALREADY = syscall.Errno(0x25) EAUTH = syscall.Errno(0x50) EBADF = syscall.Errno(0x9) + EBADMSG = syscall.Errno(0x5c) EBADRPC = syscall.Errno(0x48) EBUSY = syscall.Errno(0x10) ECANCELED = syscall.Errno(0x58) @@ -1422,7 +1660,7 @@ const ( EIPSEC = syscall.Errno(0x52) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x5b) + ELAST = syscall.Errno(0x5f) ELOOP = syscall.Errno(0x3e) EMEDIUMTYPE = syscall.Errno(0x56) EMFILE = syscall.Errno(0x18) @@ -1450,12 +1688,14 @@ const ( ENOTCONN = syscall.Errno(0x39) ENOTDIR = syscall.Errno(0x14) ENOTEMPTY = syscall.Errno(0x42) + ENOTRECOVERABLE = syscall.Errno(0x5d) ENOTSOCK = syscall.Errno(0x26) ENOTSUP = syscall.Errno(0x5b) ENOTTY = syscall.Errno(0x19) ENXIO = syscall.Errno(0x6) EOPNOTSUPP = syscall.Errno(0x2d) EOVERFLOW = syscall.Errno(0x57) + EOWNERDEAD = syscall.Errno(0x5e) EPERM = syscall.Errno(0x1) EPFNOSUPPORT = syscall.Errno(0x2e) EPIPE = syscall.Errno(0x20) @@ -1463,6 +1703,7 @@ const ( EPROCUNAVAIL = syscall.Errno(0x4c) EPROGMISMATCH = syscall.Errno(0x4b) EPROGUNAVAIL = syscall.Errno(0x4a) + EPROTO = syscall.Errno(0x5f) EPROTONOSUPPORT = syscall.Errno(0x2b) EPROTOTYPE = syscall.Errno(0x29) ERANGE = syscall.Errno(0x22) @@ -1559,7 +1800,7 @@ var errorList = [...]struct { {32, "EPIPE", "broken pipe"}, {33, "EDOM", "numerical argument out of domain"}, {34, "ERANGE", "result too large"}, - {35, "EWOULDBLOCK", "resource temporarily unavailable"}, + {35, "EAGAIN", "resource temporarily unavailable"}, {36, "EINPROGRESS", "operation now in progress"}, {37, "EALREADY", "operation already in progress"}, {38, "ENOTSOCK", "socket operation on non-socket"}, @@ -1615,7 +1856,11 @@ var errorList = [...]struct { {88, "ECANCELED", "operation canceled"}, {89, "EIDRM", "identifier removed"}, {90, "ENOMSG", "no message of desired type"}, - {91, "ELAST", "not supported"}, + {91, "ENOTSUP", "not supported"}, + {92, "EBADMSG", "bad message"}, + {93, "ENOTRECOVERABLE", "state not recoverable"}, + {94, "EOWNERDEAD", "previous owner died"}, + {95, "ELAST", "protocol error"}, } // Signal table @@ -1629,7 +1874,7 @@ var signalList = [...]struct { {3, "SIGQUIT", "quit"}, {4, "SIGILL", "illegal instruction"}, {5, "SIGTRAP", "trace/BPT trap"}, - {6, "SIGABRT", "abort trap"}, + {6, "SIGIOT", "abort trap"}, {7, "SIGEMT", "EMT trap"}, {8, "SIGFPE", "floating point exception"}, {9, "SIGKILL", "killed"}, @@ -1656,4 +1901,5 @@ var signalList = [...]struct { {30, "SIGUSR1", "user defined signal 1"}, {31, "SIGUSR2", "user defined signal 2"}, {32, "SIGTHR", "thread AST"}, + {28672, "SIGSTKSZ", "unknown signal"}, } diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go index 1792d3f..4f4449a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,openbsd +//go:build arm64 && openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -111,6 +111,12 @@ const ( BPF_FILDROP_CAPTURE = 0x1 BPF_FILDROP_DROP = 0x2 BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 @@ -139,6 +145,7 @@ const ( BPF_OR = 0x40 BPF_RELEASE = 0x30bb6 BPF_RET = 0x6 + BPF_RND = 0xc0 BPF_RSH = 0x70 BPF_ST = 0x2 BPF_STX = 0x3 @@ -156,6 +163,13 @@ const ( CLOCK_REALTIME = 0x0 CLOCK_THREAD_CPUTIME_ID = 0x4 CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x10000 CS5 = 0x0 @@ -172,7 +186,65 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0xc CTL_NET = 0x4 + DIOCADDQUEUE = 0xc110445d + DIOCADDRULE = 0xcd604404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xcd60441a + DIOCCLRIFFLAG = 0xc028445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0e04412 + DIOCCLRSTATUS = 0xc0284416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1204460 + DIOCGETQUEUE = 0xc110445f + DIOCGETQUEUES = 0xc110445e + DIOCGETRULE = 0xcd604407 + DIOCGETRULES = 0xcd604406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0104454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0104419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0284457 + DIOCKILLSRCNODES = 0xc080445b + DIOCKILLSTATES = 0xc0e04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc088444f DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0884450 + DIOCRADDADDRS = 0xc4504443 + DIOCRADDTABLES = 0xc450443d + DIOCRCLRADDRS = 0xc4504442 + DIOCRCLRASTATS = 0xc4504448 + DIOCRCLRTABLES = 0xc450443c + DIOCRCLRTSTATS = 0xc4504441 + DIOCRDELADDRS = 0xc4504444 + DIOCRDELTABLES = 0xc450443e + DIOCRGETADDRS = 0xc4504446 + DIOCRGETASTATS = 0xc4504447 + DIOCRGETTABLES = 0xc450443f + DIOCRGETTSTATS = 0xc4504440 + DIOCRINADEFINE = 0xc450444d + DIOCRSETADDRS = 0xc4504445 + DIOCRSETTFLAGS = 0xc450444a + DIOCRTSTADDRS = 0xc4504449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0284459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0284414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc0104451 + DIOCXCOMMIT = 0xc0104452 + DIOCXROLLBACK = 0xc0104453 DLT_ARCNET = 0x7 DLT_ATM_RFC1483 = 0xb DLT_AX25 = 0x3 @@ -235,6 +307,8 @@ const ( EMUL_ENABLED = 0x1 EMUL_NATIVE = 0x2 ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 ETHERMIN = 0x2e ETHERMTU = 0x5dc ETHERTYPE_8023 = 0x4 @@ -287,6 +361,7 @@ const ( ETHERTYPE_DN = 0x6003 ETHERTYPE_DOGFIGHT = 0x1989 ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e ETHERTYPE_ECMA = 0x803 ETHERTYPE_ENCRYPT = 0x803d ETHERTYPE_ES = 0x805d @@ -318,6 +393,7 @@ const ( ETHERTYPE_LLDP = 0x88cc ETHERTYPE_LOGICRAFT = 0x8148 ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 ETHERTYPE_MATRA = 0x807a ETHERTYPE_MAX = 0xffff ETHERTYPE_MERIT = 0x807c @@ -346,15 +422,16 @@ const ( ETHERTYPE_NCD = 0x8149 ETHERTYPE_NESTAR = 0x8006 ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 ETHERTYPE_NOVELL = 0x8138 ETHERTYPE_NS = 0x600 ETHERTYPE_NSAT = 0x601 ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f ETHERTYPE_NTRAILER = 0x10 ETHERTYPE_OS9 = 0x7007 ETHERTYPE_OS9NET = 0x7009 ETHERTYPE_PACER = 0x80c6 - ETHERTYPE_PAE = 0x888e ETHERTYPE_PBB = 0x88e7 ETHERTYPE_PCS = 0x4242 ETHERTYPE_PLANNING = 0x8044 @@ -437,10 +514,11 @@ const ( ETHER_VLAN_ENCAP_LEN = 0x4 EVFILT_AIO = -0x3 EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 EVFILT_PROC = -0x5 EVFILT_READ = -0x1 EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x8 + EVFILT_SYSCOUNT = 0x9 EVFILT_TIMER = -0x7 EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 @@ -462,7 +540,7 @@ const ( EV_FLAG1 = 0x2000 EV_ONESHOT = 0x10 EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTPROC = 0x800 @@ -728,6 +806,7 @@ const ( IFT_VOICEOVERCABLE = 0xc6 IFT_VOICEOVERFRAMERELAY = 0x99 IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb IFT_X213 = 0x5d IFT_X25 = 0x5 IFT_X25DDN = 0x4 @@ -793,9 +872,11 @@ const ( IPPROTO_RAW = 0xff IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e + IPPROTO_SCTP = 0x84 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 + IPPROTO_UDPLITE = 0x88 IPV6_AUTH_LEVEL = 0x35 IPV6_AUTOFLOWLABEL = 0x3b IPV6_CHECKSUM = 0x1a @@ -902,6 +983,9 @@ const ( IP_TTL = 0x4 ISIG = 0x80 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IUCLC = 0x1000 IXANY = 0x800 IXOFF = 0x400 @@ -973,6 +1057,19 @@ const ( MNT_WAIT = 0x1 MNT_WANTRDWR = 0x2000000 MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" MSG_BCAST = 0x100 MSG_CMSG_CLOEXEC = 0x800 MSG_CTRUNC = 0x20 @@ -985,6 +1082,7 @@ const ( MSG_PEEK = 0x2 MSG_TRUNC = 0x10 MSG_WAITALL = 0x40 + MSG_WAITFORONE = 0x1000 MS_ASYNC = 0x1 MS_INVALIDATE = 0x4 MS_SYNC = 0x2 @@ -993,7 +1091,8 @@ const ( NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 NET_RT_IFNAMES = 0x6 - NET_RT_MAXID = 0x7 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 NET_RT_STATS = 0x4 NET_RT_TABLE = 0x5 NFDBITS = 0x20 @@ -1010,6 +1109,7 @@ const ( NOTE_FORK = 0x40000000 NOTE_LINK = 0x10 NOTE_LOWAT = 0x1 + NOTE_OOB = 0x4 NOTE_PCTRLMASK = 0xf0000000 NOTE_PDATAMASK = 0xfffff NOTE_RENAME = 0x20 @@ -1146,7 +1246,7 @@ const ( RTM_PROPOSAL = 0x13 RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 + RTM_SOURCE = 0x16 RTM_VERSION = 0x5 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 @@ -1164,6 +1264,9 @@ const ( RUSAGE_THREAD = 0x1 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -1180,30 +1283,30 @@ const ( SIOCBRDGDELS = 0x80606942 SIOCBRDGFLUSH = 0x80606948 SIOCBRDGFRL = 0x808c694e - SIOCBRDGGCACHE = 0xc0186941 - SIOCBRDGGFD = 0xc0186952 - SIOCBRDGGHT = 0xc0186951 + SIOCBRDGGCACHE = 0xc0146941 + SIOCBRDGGFD = 0xc0146952 + SIOCBRDGGHT = 0xc0146951 SIOCBRDGGIFFLGS = 0xc060693e - SIOCBRDGGMA = 0xc0186953 + SIOCBRDGGMA = 0xc0146953 SIOCBRDGGPARAM = 0xc0406958 - SIOCBRDGGPRI = 0xc0186950 + SIOCBRDGGPRI = 0xc0146950 SIOCBRDGGRL = 0xc030694f - SIOCBRDGGTO = 0xc0186946 + SIOCBRDGGTO = 0xc0146946 SIOCBRDGIFS = 0xc0606942 SIOCBRDGRTS = 0xc0206943 SIOCBRDGSADDR = 0xc1286944 - SIOCBRDGSCACHE = 0x80186940 - SIOCBRDGSFD = 0x80186952 - SIOCBRDGSHT = 0x80186951 + SIOCBRDGSCACHE = 0x80146940 + SIOCBRDGSFD = 0x80146952 + SIOCBRDGSHT = 0x80146951 SIOCBRDGSIFCOST = 0x80606955 SIOCBRDGSIFFLGS = 0x8060693f SIOCBRDGSIFPRIO = 0x80606954 SIOCBRDGSIFPROT = 0x8060694a - SIOCBRDGSMA = 0x80186953 - SIOCBRDGSPRI = 0x80186950 - SIOCBRDGSPROTO = 0x8018695a - SIOCBRDGSTO = 0x80186945 - SIOCBRDGSTXHC = 0x80186959 + SIOCBRDGSMA = 0x80146953 + SIOCBRDGSPRI = 0x80146950 + SIOCBRDGSPROTO = 0x8014695a + SIOCBRDGSTO = 0x80146945 + SIOCBRDGSTXHC = 0x80146959 SIOCDELLABEL = 0x80206997 SIOCDELMULTI = 0x80206932 SIOCDIFADDR = 0x80206919 @@ -1256,6 +1359,7 @@ const ( SIOCGPWE3CTRLWORD = 0xc02069dc SIOCGPWE3FAT = 0xc02069dd SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db SIOCGSPPPPARAMS = 0xc0206994 SIOCGTXHPRIO = 0xc02069c6 SIOCGUMBINFO = 0xc02069be @@ -1302,17 +1406,13 @@ const ( SIOCSPWE3CTRLWORD = 0x802069dc SIOCSPWE3FAT = 0x802069dd SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db SIOCSSPPPPARAMS = 0x80206993 SIOCSTXHPRIO = 0x802069c5 SIOCSUMBPARAM = 0x802069bf SIOCSVH = 0xc02069f5 SIOCSVNETFLOWID = 0x802069c3 SIOCSVNETID = 0x802069a6 - SIOCSWGDPID = 0xc018695b - SIOCSWGMAXFLOW = 0xc0186960 - SIOCSWGMAXGROUP = 0xc018695d - SIOCSWSDPID = 0x8018695c - SIOCSWSPORTNO = 0xc060695f SOCK_CLOEXEC = 0x8000 SOCK_DGRAM = 0x2 SOCK_DNS = 0x1000 @@ -1327,6 +1427,7 @@ const ( SO_BINDANY = 0x1000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 @@ -1334,6 +1435,7 @@ const ( SO_NETPROC = 0x1020 SO_OOBINLINE = 0x100 SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 @@ -1383,7 +1485,18 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 - TCP_MAXBURST = 0x4 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 TCP_MAXSEG = 0x2 TCP_MAXWIN = 0xffff TCP_MAX_SACK = 0x3 @@ -1392,6 +1505,7 @@ const ( TCP_MSS = 0x200 TCP_NODELAY = 0x1 TCP_NOPUSH = 0x10 + TCP_SACKHOLE_LIMIT = 0x80 TCP_SACK_ENABLE = 0x8 TCSAFLUSH = 0x2 TIMER_ABSTIME = 0x1 @@ -1760,7 +1874,7 @@ var signalList = [...]struct { {3, "SIGQUIT", "quit"}, {4, "SIGILL", "illegal instruction"}, {5, "SIGTRAP", "trace/BPT trap"}, - {6, "SIGABRT", "abort trap"}, + {6, "SIGIOT", "abort trap"}, {7, "SIGEMT", "EMT trap"}, {8, "SIGFPE", "floating point exception"}, {9, "SIGKILL", "killed"}, @@ -1787,4 +1901,5 @@ var signalList = [...]struct { {30, "SIGUSR1", "user defined signal 1"}, {31, "SIGUSR2", "user defined signal 2"}, {32, "SIGTHR", "thread AST"}, + {28672, "SIGSTKSZ", "unknown signal"}, } diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go new file mode 100644 index 0000000..76a363f --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go @@ -0,0 +1,1905 @@ +// mkerrors.sh -m64 +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build mips64 && openbsd + +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs -- -m64 _const.go + +package unix + +import "syscall" + +const ( + AF_APPLETALK = 0x10 + AF_BLUETOOTH = 0x20 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1a + AF_ECMA = 0x8 + AF_ENCAP = 0x1c + AF_HYLINK = 0xf + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x18 + AF_IPX = 0x17 + AF_ISDN = 0x1a + AF_ISO = 0x7 + AF_KEY = 0x1e + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x24 + AF_MPLS = 0x21 + AF_NATM = 0x1b + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PUP = 0x4 + AF_ROUTE = 0x11 + AF_SIP = 0x1d + AF_SNA = 0xb + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + ALTWERASE = 0x200 + ARPHRD_ETHER = 0x1 + ARPHRD_FRELAY = 0xf + ARPHRD_IEEE1394 = 0x18 + ARPHRD_IEEE802 = 0x6 + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDIRFILT = 0x4004427c + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc010427b + BIOCGETIF = 0x4020426b + BIOCGFILDROP = 0x40044278 + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044273 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCLOCK = 0x20004276 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDIRFILT = 0x8004427d + BIOCSDLT = 0x8004427a + BIOCSETF = 0x80104267 + BIOCSETIF = 0x8020426c + BIOCSETWF = 0x80104277 + BIOCSFILDROP = 0x80044279 + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044272 + BIOCSRTIMEOUT = 0x8010426d + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIRECTION_IN = 0x1 + BPF_DIRECTION_OUT = 0x2 + BPF_DIV = 0x30 + BPF_FILDROP_CAPTURE = 0x1 + BPF_FILDROP_DROP = 0x2 + BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x200000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RND = 0xc0 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_BOOTTIME = 0x6 + CLOCK_MONOTONIC = 0x3 + CLOCK_PROCESS_CPUTIME_ID = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x4 + CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 + CREAD = 0x800 + CRTSCTS = 0x10000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0xff + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DIOCADDQUEUE = 0xc110445d + DIOCADDRULE = 0xcd604404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xcd60441a + DIOCCLRIFFLAG = 0xc028445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0e04412 + DIOCCLRSTATUS = 0xc0284416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1204460 + DIOCGETQUEUE = 0xc110445f + DIOCGETQUEUES = 0xc110445e + DIOCGETRULE = 0xcd604407 + DIOCGETRULES = 0xcd604406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0104454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0104419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0284457 + DIOCKILLSRCNODES = 0xc080445b + DIOCKILLSTATES = 0xc0e04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc088444f + DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0884450 + DIOCRADDADDRS = 0xc4504443 + DIOCRADDTABLES = 0xc450443d + DIOCRCLRADDRS = 0xc4504442 + DIOCRCLRASTATS = 0xc4504448 + DIOCRCLRTABLES = 0xc450443c + DIOCRCLRTSTATS = 0xc4504441 + DIOCRDELADDRS = 0xc4504444 + DIOCRDELTABLES = 0xc450443e + DIOCRGETADDRS = 0xc4504446 + DIOCRGETASTATS = 0xc4504447 + DIOCRGETTABLES = 0xc450443f + DIOCRGETTSTATS = 0xc4504440 + DIOCRINADEFINE = 0xc450444d + DIOCRSETADDRS = 0xc4504445 + DIOCRSETTFLAGS = 0xc450444a + DIOCRTSTADDRS = 0xc4504449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0284459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0284414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc0104451 + DIOCXCOMMIT = 0xc0104452 + DIOCXROLLBACK = 0xc0104453 + DLT_ARCNET = 0x7 + DLT_ATM_RFC1483 = 0xb + DLT_AX25 = 0x3 + DLT_CHAOS = 0x5 + DLT_C_HDLC = 0x68 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0xd + DLT_FDDI = 0xa + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_LOOP = 0xc + DLT_MPLS = 0xdb + DLT_NULL = 0x0 + DLT_OPENFLOW = 0x10b + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_SERIAL = 0x32 + DLT_PRONET = 0x4 + DLT_RAW = 0xe + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_USBPCAP = 0xf9 + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EMT_TAGOVF = 0x1 + EMUL_ENABLED = 0x1 + EMUL_NATIVE = 0x2 + ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 + ETHERMIN = 0x2e + ETHERMTU = 0x5dc + ETHERTYPE_8023 = 0x4 + ETHERTYPE_AARP = 0x80f3 + ETHERTYPE_ACCTON = 0x8390 + ETHERTYPE_AEONIC = 0x8036 + ETHERTYPE_ALPHA = 0x814a + ETHERTYPE_AMBER = 0x6008 + ETHERTYPE_AMOEBA = 0x8145 + ETHERTYPE_AOE = 0x88a2 + ETHERTYPE_APOLLO = 0x80f7 + ETHERTYPE_APOLLODOMAIN = 0x8019 + ETHERTYPE_APPLETALK = 0x809b + ETHERTYPE_APPLITEK = 0x80c7 + ETHERTYPE_ARGONAUT = 0x803a + ETHERTYPE_ARP = 0x806 + ETHERTYPE_AT = 0x809b + ETHERTYPE_ATALK = 0x809b + ETHERTYPE_ATOMIC = 0x86df + ETHERTYPE_ATT = 0x8069 + ETHERTYPE_ATTSTANFORD = 0x8008 + ETHERTYPE_AUTOPHON = 0x806a + ETHERTYPE_AXIS = 0x8856 + ETHERTYPE_BCLOOP = 0x9003 + ETHERTYPE_BOFL = 0x8102 + ETHERTYPE_CABLETRON = 0x7034 + ETHERTYPE_CHAOS = 0x804 + ETHERTYPE_COMDESIGN = 0x806c + ETHERTYPE_COMPUGRAPHIC = 0x806d + ETHERTYPE_COUNTERPOINT = 0x8062 + ETHERTYPE_CRONUS = 0x8004 + ETHERTYPE_CRONUSVLN = 0x8003 + ETHERTYPE_DCA = 0x1234 + ETHERTYPE_DDE = 0x807b + ETHERTYPE_DEBNI = 0xaaaa + ETHERTYPE_DECAM = 0x8048 + ETHERTYPE_DECCUST = 0x6006 + ETHERTYPE_DECDIAG = 0x6005 + ETHERTYPE_DECDNS = 0x803c + ETHERTYPE_DECDTS = 0x803e + ETHERTYPE_DECEXPER = 0x6000 + ETHERTYPE_DECLAST = 0x8041 + ETHERTYPE_DECLTM = 0x803f + ETHERTYPE_DECMUMPS = 0x6009 + ETHERTYPE_DECNETBIOS = 0x8040 + ETHERTYPE_DELTACON = 0x86de + ETHERTYPE_DIDDLE = 0x4321 + ETHERTYPE_DLOG1 = 0x660 + ETHERTYPE_DLOG2 = 0x661 + ETHERTYPE_DN = 0x6003 + ETHERTYPE_DOGFIGHT = 0x1989 + ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e + ETHERTYPE_ECMA = 0x803 + ETHERTYPE_ENCRYPT = 0x803d + ETHERTYPE_ES = 0x805d + ETHERTYPE_EXCELAN = 0x8010 + ETHERTYPE_EXPERDATA = 0x8049 + ETHERTYPE_FLIP = 0x8146 + ETHERTYPE_FLOWCONTROL = 0x8808 + ETHERTYPE_FRARP = 0x808 + ETHERTYPE_GENDYN = 0x8068 + ETHERTYPE_HAYES = 0x8130 + ETHERTYPE_HIPPI_FP = 0x8180 + ETHERTYPE_HITACHI = 0x8820 + ETHERTYPE_HP = 0x8005 + ETHERTYPE_IEEEPUP = 0xa00 + ETHERTYPE_IEEEPUPAT = 0xa01 + ETHERTYPE_IMLBL = 0x4c42 + ETHERTYPE_IMLBLDIAG = 0x424c + ETHERTYPE_IP = 0x800 + ETHERTYPE_IPAS = 0x876c + ETHERTYPE_IPV6 = 0x86dd + ETHERTYPE_IPX = 0x8137 + ETHERTYPE_IPXNEW = 0x8037 + ETHERTYPE_KALPANA = 0x8582 + ETHERTYPE_LANBRIDGE = 0x8038 + ETHERTYPE_LANPROBE = 0x8888 + ETHERTYPE_LAT = 0x6004 + ETHERTYPE_LBACK = 0x9000 + ETHERTYPE_LITTLE = 0x8060 + ETHERTYPE_LLDP = 0x88cc + ETHERTYPE_LOGICRAFT = 0x8148 + ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 + ETHERTYPE_MATRA = 0x807a + ETHERTYPE_MAX = 0xffff + ETHERTYPE_MERIT = 0x807c + ETHERTYPE_MICP = 0x873a + ETHERTYPE_MOPDL = 0x6001 + ETHERTYPE_MOPRC = 0x6002 + ETHERTYPE_MOTOROLA = 0x818d + ETHERTYPE_MPLS = 0x8847 + ETHERTYPE_MPLS_MCAST = 0x8848 + ETHERTYPE_MUMPS = 0x813f + ETHERTYPE_NBPCC = 0x3c04 + ETHERTYPE_NBPCLAIM = 0x3c09 + ETHERTYPE_NBPCLREQ = 0x3c05 + ETHERTYPE_NBPCLRSP = 0x3c06 + ETHERTYPE_NBPCREQ = 0x3c02 + ETHERTYPE_NBPCRSP = 0x3c03 + ETHERTYPE_NBPDG = 0x3c07 + ETHERTYPE_NBPDGB = 0x3c08 + ETHERTYPE_NBPDLTE = 0x3c0a + ETHERTYPE_NBPRAR = 0x3c0c + ETHERTYPE_NBPRAS = 0x3c0b + ETHERTYPE_NBPRST = 0x3c0d + ETHERTYPE_NBPSCD = 0x3c01 + ETHERTYPE_NBPVCD = 0x3c00 + ETHERTYPE_NBS = 0x802 + ETHERTYPE_NCD = 0x8149 + ETHERTYPE_NESTAR = 0x8006 + ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 + ETHERTYPE_NOVELL = 0x8138 + ETHERTYPE_NS = 0x600 + ETHERTYPE_NSAT = 0x601 + ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f + ETHERTYPE_NTRAILER = 0x10 + ETHERTYPE_OS9 = 0x7007 + ETHERTYPE_OS9NET = 0x7009 + ETHERTYPE_PACER = 0x80c6 + ETHERTYPE_PBB = 0x88e7 + ETHERTYPE_PCS = 0x4242 + ETHERTYPE_PLANNING = 0x8044 + ETHERTYPE_PPP = 0x880b + ETHERTYPE_PPPOE = 0x8864 + ETHERTYPE_PPPOEDISC = 0x8863 + ETHERTYPE_PRIMENTS = 0x7031 + ETHERTYPE_PUP = 0x200 + ETHERTYPE_PUPAT = 0x200 + ETHERTYPE_QINQ = 0x88a8 + ETHERTYPE_RACAL = 0x7030 + ETHERTYPE_RATIONAL = 0x8150 + ETHERTYPE_RAWFR = 0x6559 + ETHERTYPE_RCL = 0x1995 + ETHERTYPE_RDP = 0x8739 + ETHERTYPE_RETIX = 0x80f2 + ETHERTYPE_REVARP = 0x8035 + ETHERTYPE_SCA = 0x6007 + ETHERTYPE_SECTRA = 0x86db + ETHERTYPE_SECUREDATA = 0x876d + ETHERTYPE_SGITW = 0x817e + ETHERTYPE_SG_BOUNCE = 0x8016 + ETHERTYPE_SG_DIAG = 0x8013 + ETHERTYPE_SG_NETGAMES = 0x8014 + ETHERTYPE_SG_RESV = 0x8015 + ETHERTYPE_SIMNET = 0x5208 + ETHERTYPE_SLOW = 0x8809 + ETHERTYPE_SNA = 0x80d5 + ETHERTYPE_SNMP = 0x814c + ETHERTYPE_SONIX = 0xfaf5 + ETHERTYPE_SPIDER = 0x809f + ETHERTYPE_SPRITE = 0x500 + ETHERTYPE_STP = 0x8181 + ETHERTYPE_TALARIS = 0x812b + ETHERTYPE_TALARISMC = 0x852b + ETHERTYPE_TCPCOMP = 0x876b + ETHERTYPE_TCPSM = 0x9002 + ETHERTYPE_TEC = 0x814f + ETHERTYPE_TIGAN = 0x802f + ETHERTYPE_TRAIL = 0x1000 + ETHERTYPE_TRANSETHER = 0x6558 + ETHERTYPE_TYMSHARE = 0x802e + ETHERTYPE_UBBST = 0x7005 + ETHERTYPE_UBDEBUG = 0x900 + ETHERTYPE_UBDIAGLOOP = 0x7002 + ETHERTYPE_UBDL = 0x7000 + ETHERTYPE_UBNIU = 0x7001 + ETHERTYPE_UBNMC = 0x7003 + ETHERTYPE_VALID = 0x1600 + ETHERTYPE_VARIAN = 0x80dd + ETHERTYPE_VAXELN = 0x803b + ETHERTYPE_VEECO = 0x8067 + ETHERTYPE_VEXP = 0x805b + ETHERTYPE_VGLAB = 0x8131 + ETHERTYPE_VINES = 0xbad + ETHERTYPE_VINESECHO = 0xbaf + ETHERTYPE_VINESLOOP = 0xbae + ETHERTYPE_VITAL = 0xff00 + ETHERTYPE_VLAN = 0x8100 + ETHERTYPE_VLTLMAN = 0x8080 + ETHERTYPE_VPROD = 0x805c + ETHERTYPE_VURESERVED = 0x8147 + ETHERTYPE_WATERLOO = 0x8130 + ETHERTYPE_WELLFLEET = 0x8103 + ETHERTYPE_X25 = 0x805 + ETHERTYPE_X75 = 0x801 + ETHERTYPE_XNSSM = 0x9001 + ETHERTYPE_XTP = 0x817d + ETHER_ADDR_LEN = 0x6 + ETHER_ALIGN = 0x2 + ETHER_CRC_LEN = 0x4 + ETHER_CRC_POLY_BE = 0x4c11db6 + ETHER_CRC_POLY_LE = 0xedb88320 + ETHER_HDR_LEN = 0xe + ETHER_MAX_DIX_LEN = 0x600 + ETHER_MAX_HARDMTU_LEN = 0xff9b + ETHER_MAX_LEN = 0x5ee + ETHER_MIN_LEN = 0x40 + ETHER_TYPE_LEN = 0x2 + ETHER_VLAN_ENCAP_LEN = 0x4 + EVFILT_AIO = -0x3 + EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x9 + EVFILT_TIMER = -0x7 + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EVL_ENCAPLEN = 0x4 + EVL_PRIO_BITS = 0xd + EVL_PRIO_MAX = 0x7 + EVL_VLID_MASK = 0xfff + EVL_VLID_MAX = 0xffe + EVL_VLID_MIN = 0x1 + EVL_VLID_NULL = 0x0 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf800 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FLUSHO = 0x800000 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0xa + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETOWN = 0x5 + F_ISATTY = 0xb + F_OK = 0x0 + F_RDLCK = 0x1 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETOWN = 0x6 + F_UNLCK = 0x2 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFAN_ARRIVAL = 0x0 + IFAN_DEPARTURE = 0x1 + IFF_ALLMULTI = 0x200 + IFF_BROADCAST = 0x2 + IFF_CANTCHANGE = 0x8e52 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_STATICARP = 0x20 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_A12MPPSWITCH = 0x82 + IFT_AAL2 = 0xbb + IFT_AAL5 = 0x31 + IFT_ADSL = 0x5e + IFT_AFLANE8023 = 0x3b + IFT_AFLANE8025 = 0x3c + IFT_ARAP = 0x58 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ASYNC = 0x54 + IFT_ATM = 0x25 + IFT_ATMDXI = 0x69 + IFT_ATMFUNI = 0x6a + IFT_ATMIMA = 0x6b + IFT_ATMLOGICAL = 0x50 + IFT_ATMRADIO = 0xbd + IFT_ATMSUBINTERFACE = 0x86 + IFT_ATMVCIENDPT = 0xc2 + IFT_ATMVIRTUAL = 0x95 + IFT_BGPPOLICYACCOUNTING = 0xa2 + IFT_BLUETOOTH = 0xf8 + IFT_BRIDGE = 0xd1 + IFT_BSC = 0x53 + IFT_CARP = 0xf7 + IFT_CCTEMUL = 0x3d + IFT_CEPT = 0x13 + IFT_CES = 0x85 + IFT_CHANNEL = 0x46 + IFT_CNR = 0x55 + IFT_COFFEE = 0x84 + IFT_COMPOSITELINK = 0x9b + IFT_DCN = 0x8d + IFT_DIGITALPOWERLINE = 0x8a + IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba + IFT_DLSW = 0x4a + IFT_DOCSCABLEDOWNSTREAM = 0x80 + IFT_DOCSCABLEMACLAYER = 0x7f + IFT_DOCSCABLEUPSTREAM = 0x81 + IFT_DOCSCABLEUPSTREAMCHANNEL = 0xcd + IFT_DS0 = 0x51 + IFT_DS0BUNDLE = 0x52 + IFT_DS1FDL = 0xaa + IFT_DS3 = 0x1e + IFT_DTM = 0x8c + IFT_DUMMY = 0xf1 + IFT_DVBASILN = 0xac + IFT_DVBASIOUT = 0xad + IFT_DVBRCCDOWNSTREAM = 0x93 + IFT_DVBRCCMACLAYER = 0x92 + IFT_DVBRCCUPSTREAM = 0x94 + IFT_ECONET = 0xce + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_EPLRS = 0x57 + IFT_ESCON = 0x49 + IFT_ETHER = 0x6 + IFT_FAITH = 0xf3 + IFT_FAST = 0x7d + IFT_FASTETHER = 0x3e + IFT_FASTETHERFX = 0x45 + IFT_FDDI = 0xf + IFT_FIBRECHANNEL = 0x38 + IFT_FRAMERELAYINTERCONNECT = 0x3a + IFT_FRAMERELAYMPI = 0x5c + IFT_FRDLCIENDPT = 0xc1 + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_FRF16MFRBUNDLE = 0xa3 + IFT_FRFORWARD = 0x9e + IFT_G703AT2MB = 0x43 + IFT_G703AT64K = 0x42 + IFT_GIF = 0xf0 + IFT_GIGABITETHERNET = 0x75 + IFT_GR303IDT = 0xb2 + IFT_GR303RDT = 0xb1 + IFT_H323GATEKEEPER = 0xa4 + IFT_H323PROXY = 0xa5 + IFT_HDH1822 = 0x3 + IFT_HDLC = 0x76 + IFT_HDSL2 = 0xa8 + IFT_HIPERLAN2 = 0xb7 + IFT_HIPPI = 0x2f + IFT_HIPPIINTERFACE = 0x39 + IFT_HOSTPAD = 0x5a + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IBM370PARCHAN = 0x48 + IFT_IDSL = 0x9a + IFT_IEEE1394 = 0x90 + IFT_IEEE80211 = 0x47 + IFT_IEEE80212 = 0x37 + IFT_IEEE8023ADLAG = 0xa1 + IFT_IFGSN = 0x91 + IFT_IMT = 0xbe + IFT_INFINIBAND = 0xc7 + IFT_INTERLEAVE = 0x7c + IFT_IP = 0x7e + IFT_IPFORWARD = 0x8e + IFT_IPOVERATM = 0x72 + IFT_IPOVERCDLC = 0x6d + IFT_IPOVERCLAW = 0x6e + IFT_IPSWITCH = 0x4e + IFT_ISDN = 0x3f + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISDNS = 0x4b + IFT_ISDNU = 0x4c + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88025CRFPINT = 0x62 + IFT_ISO88025DTR = 0x56 + IFT_ISO88025FIBER = 0x73 + IFT_ISO88026 = 0xa + IFT_ISUP = 0xb3 + IFT_L2VLAN = 0x87 + IFT_L3IPVLAN = 0x88 + IFT_L3IPXVLAN = 0x89 + IFT_LAPB = 0x10 + IFT_LAPD = 0x4d + IFT_LAPF = 0x77 + IFT_LINEGROUP = 0xd2 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MBIM = 0xfa + IFT_MEDIAMAILOVERIP = 0x8b + IFT_MFSIGLINK = 0xa7 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_MPC = 0x71 + IFT_MPLS = 0xa6 + IFT_MPLSTUNNEL = 0x96 + IFT_MSDSL = 0x8f + IFT_MVL = 0xbf + IFT_MYRINET = 0x63 + IFT_NFAS = 0xaf + IFT_NSIP = 0x1b + IFT_OPTICALCHANNEL = 0xc3 + IFT_OPTICALTRANSPORT = 0xc4 + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PFLOG = 0xf5 + IFT_PFLOW = 0xf9 + IFT_PFSYNC = 0xf6 + IFT_PLC = 0xae + IFT_PON155 = 0xcf + IFT_PON622 = 0xd0 + IFT_POS = 0xab + IFT_PPP = 0x17 + IFT_PPPMULTILINKBUNDLE = 0x6c + IFT_PROPATM = 0xc5 + IFT_PROPBWAP2MP = 0xb8 + IFT_PROPCNLS = 0x59 + IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 + IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 + IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PROPWIRELESSP2P = 0x9d + IFT_PTPSERIAL = 0x16 + IFT_PVC = 0xf2 + IFT_Q2931 = 0xc9 + IFT_QLLC = 0x44 + IFT_RADIOMAC = 0xbc + IFT_RADSL = 0x5f + IFT_REACHDSL = 0xc0 + IFT_RFC1483 = 0x9f + IFT_RS232 = 0x21 + IFT_RSRB = 0x4f + IFT_SDLC = 0x11 + IFT_SDSL = 0x60 + IFT_SHDSL = 0xa9 + IFT_SIP = 0x1f + IFT_SIPSIG = 0xcc + IFT_SIPTG = 0xcb + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETOVERHEADCHANNEL = 0xb9 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_SRP = 0x97 + IFT_SS7SIGLINK = 0x9c + IFT_STACKTOSTACK = 0x6f + IFT_STARLAN = 0xb + IFT_T1 = 0x12 + IFT_TDLC = 0x74 + IFT_TELINK = 0xc8 + IFT_TERMPAD = 0x5b + IFT_TR008 = 0xb0 + IFT_TRANSPHDLC = 0x7b + IFT_TUNNEL = 0x83 + IFT_ULTRA = 0x1d + IFT_USB = 0xa0 + IFT_V11 = 0x40 + IFT_V35 = 0x2d + IFT_V36 = 0x41 + IFT_V37 = 0x78 + IFT_VDSL = 0x61 + IFT_VIRTUALIPADDRESS = 0x70 + IFT_VIRTUALTG = 0xca + IFT_VOICEDID = 0xd5 + IFT_VOICEEM = 0x64 + IFT_VOICEEMFGD = 0xd3 + IFT_VOICEENCAP = 0x67 + IFT_VOICEFGDEANA = 0xd4 + IFT_VOICEFXO = 0x65 + IFT_VOICEFXS = 0x66 + IFT_VOICEOVERATM = 0x98 + IFT_VOICEOVERCABLE = 0xc6 + IFT_VOICEOVERFRAMERELAY = 0x99 + IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb + IFT_X213 = 0x5d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25HUNTGROUP = 0x7a + IFT_X25MLP = 0x79 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LOOPBACKNET = 0x7f + IN_RFC3021_HOST = 0x1 + IN_RFC3021_NET = 0xfffffffe + IN_RFC3021_NSHIFT = 0x1f + IPPROTO_AH = 0x33 + IPPROTO_CARP = 0x70 + IPPROTO_DIVERT = 0x102 + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GRE = 0x2f + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IGMP = 0x2 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPIP = 0x4 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x103 + IPPROTO_MOBILE = 0x37 + IPPROTO_MPLS = 0x89 + IPPROTO_NONE = 0x3b + IPPROTO_PFSYNC = 0xf0 + IPPROTO_PIM = 0x67 + IPPROTO_PUP = 0xc + IPPROTO_RAW = 0xff + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_SCTP = 0x84 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_UDP = 0x11 + IPPROTO_UDPLITE = 0x88 + IPV6_AUTH_LEVEL = 0x35 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_ESP_NETWORK_LEVEL = 0x37 + IPV6_ESP_TRANS_LEVEL = 0x36 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff + IPV6_FRAGTTL = 0x78 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPCOMP_LEVEL = 0x3c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXPACKET = 0xffff + IPV6_MINHOPCOUNT = 0x41 + IPV6_MMTU = 0x500 + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_OPTIONS = 0x1 + IPV6_PATHMTU = 0x2c + IPV6_PIPEX = 0x3f + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVDSTPORT = 0x40 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x24 + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x39 + IPV6_RTABLE = 0x1021 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x23 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x3d + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_AUTH_LEVEL = 0x14 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DROP_MEMBERSHIP = 0xd + IP_ESP_NETWORK_LEVEL = 0x16 + IP_ESP_TRANS_LEVEL = 0x15 + IP_HDRINCL = 0x2 + IP_IPCOMP_LEVEL = 0x1d + IP_IPDEFTTL = 0x25 + IP_IPSECFLOWINFO = 0x24 + IP_IPSEC_LOCAL_AUTH = 0x1b + IP_IPSEC_LOCAL_CRED = 0x19 + IP_IPSEC_LOCAL_ID = 0x17 + IP_IPSEC_REMOTE_AUTH = 0x1c + IP_IPSEC_REMOTE_CRED = 0x1a + IP_IPSEC_REMOTE_ID = 0x18 + IP_MAXPACKET = 0xffff + IP_MAX_MEMBERSHIPS = 0xfff + IP_MF = 0x2000 + IP_MINTTL = 0x20 + IP_MIN_MEMBERSHIPS = 0xf + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_OFFMASK = 0x1fff + IP_OPTIONS = 0x1 + IP_PIPEX = 0x22 + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVDSTPORT = 0x21 + IP_RECVIF = 0x1e + IP_RECVOPTS = 0x5 + IP_RECVRETOPTS = 0x6 + IP_RECVRTABLE = 0x23 + IP_RECVTTL = 0x1f + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RTABLE = 0x1021 + IP_SENDSRCADDR = 0x7 + IP_TOS = 0x3 + IP_TTL = 0x4 + ISIG = 0x80 + ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 + IUCLC = 0x1000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LCNT_OVERLOAD_FLUSH = 0x6 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x6 + MADV_NORMAL = 0x0 + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_SPACEAVAIL = 0x5 + MADV_WILLNEED = 0x3 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_CONCEAL = 0x8000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_FLAGMASK = 0xfff7 + MAP_HASSEMAPHORE = 0x0 + MAP_INHERIT = 0x0 + MAP_INHERIT_COPY = 0x1 + MAP_INHERIT_NONE = 0x2 + MAP_INHERIT_SHARE = 0x0 + MAP_INHERIT_ZERO = 0x3 + MAP_NOEXTEND = 0x0 + MAP_NORESERVE = 0x0 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x0 + MAP_SHARED = 0x1 + MAP_STACK = 0x4000 + MAP_TRYFIXED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_DEFEXPORTED = 0x200 + MNT_DELEXPORT = 0x20000 + MNT_DOOMED = 0x8000000 + MNT_EXPORTANON = 0x400 + MNT_EXPORTED = 0x100 + MNT_EXRDONLY = 0x80 + MNT_FORCE = 0x80000 + MNT_LAZY = 0x3 + MNT_LOCAL = 0x1000 + MNT_NOATIME = 0x8000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOPERM = 0x20 + MNT_NOSUID = 0x8 + MNT_NOWAIT = 0x2 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_ROOTFS = 0x4000 + MNT_SOFTDEP = 0x4000000 + MNT_STALLED = 0x100000 + MNT_SWAPPABLE = 0x200000 + MNT_SYNCHRONOUS = 0x2 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0x400ffff + MNT_WAIT = 0x1 + MNT_WANTRDWR = 0x2000000 + MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" + MSG_BCAST = 0x100 + MSG_CMSG_CLOEXEC = 0x800 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOR = 0x8 + MSG_MCAST = 0x200 + MSG_NOSIGNAL = 0x400 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITFORONE = 0x1000 + MS_ASYNC = 0x1 + MS_INVALIDATE = 0x4 + MS_SYNC = 0x2 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_FLAGS = 0x2 + NET_RT_IFLIST = 0x3 + NET_RT_IFNAMES = 0x6 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 + NET_RT_STATS = 0x4 + NET_RT_TABLE = 0x5 + NFDBITS = 0x20 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ATTRIB = 0x8 + NOTE_CHANGE = 0x1 + NOTE_CHILD = 0x4 + NOTE_DELETE = 0x1 + NOTE_EOF = 0x2 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXTEND = 0x4 + NOTE_FORK = 0x40000000 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_OOB = 0x4 + NOTE_PCTRLMASK = 0xf0000000 + NOTE_PDATAMASK = 0xfffff + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRUNCATE = 0x80 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OLCUC = 0x20 + ONLCR = 0x2 + ONLRET = 0x80 + ONOCR = 0x40 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x10000 + O_CREAT = 0x200 + O_DIRECTORY = 0x20000 + O_DSYNC = 0x80 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x8000 + O_NOFOLLOW = 0x100 + O_NONBLOCK = 0x4 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_RSYNC = 0x80 + O_SHLOCK = 0x10 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PF_FLUSH = 0x1 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + RLIMIT_CORE = 0x4 + RLIMIT_CPU = 0x0 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BFD = 0xb + RTAX_BRD = 0x7 + RTAX_DNS = 0xc + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_LABEL = 0xa + RTAX_MAX = 0xf + RTAX_NETMASK = 0x2 + RTAX_SEARCH = 0xe + RTAX_SRC = 0x8 + RTAX_SRCMASK = 0x9 + RTAX_STATIC = 0xd + RTA_AUTHOR = 0x40 + RTA_BFD = 0x800 + RTA_BRD = 0x80 + RTA_DNS = 0x1000 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_LABEL = 0x400 + RTA_NETMASK = 0x4 + RTA_SEARCH = 0x4000 + RTA_SRC = 0x100 + RTA_SRCMASK = 0x200 + RTA_STATIC = 0x2000 + RTF_ANNOUNCE = 0x4000 + RTF_BFD = 0x1000000 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CACHED = 0x20000 + RTF_CLONED = 0x10000 + RTF_CLONING = 0x100 + RTF_CONNECTED = 0x800000 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_FMASK = 0x110fc08 + RTF_GATEWAY = 0x2 + RTF_HOST = 0x4 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MPATH = 0x40000 + RTF_MPLS = 0x100000 + RTF_MULTICAST = 0x200 + RTF_PERMANENT_ARP = 0x2000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x2000 + RTF_REJECT = 0x8 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_USETRAILERS = 0x8000 + RTM_80211INFO = 0x15 + RTM_ADD = 0x1 + RTM_BFD = 0x12 + RTM_CHANGE = 0x3 + RTM_CHGADDRATTR = 0x14 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DESYNC = 0x10 + RTM_GET = 0x4 + RTM_IFANNOUNCE = 0xf + RTM_IFINFO = 0xe + RTM_INVALIDATE = 0x11 + RTM_LOSING = 0x5 + RTM_MAXSIZE = 0x800 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_PROPOSAL = 0x13 + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_SOURCE = 0x16 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RT_TABLEID_BITS = 0x8 + RT_TABLEID_MASK = 0xff + RT_TABLEID_MAX = 0xff + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 + RUSAGE_THREAD = 0x1 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCAIFGROUP = 0x80286987 + SIOCATMARK = 0x40047307 + SIOCBRDGADD = 0x8060693c + SIOCBRDGADDL = 0x80606949 + SIOCBRDGADDS = 0x80606941 + SIOCBRDGARL = 0x808c694d + SIOCBRDGDADDR = 0x81286947 + SIOCBRDGDEL = 0x8060693d + SIOCBRDGDELS = 0x80606942 + SIOCBRDGFLUSH = 0x80606948 + SIOCBRDGFRL = 0x808c694e + SIOCBRDGGCACHE = 0xc0146941 + SIOCBRDGGFD = 0xc0146952 + SIOCBRDGGHT = 0xc0146951 + SIOCBRDGGIFFLGS = 0xc060693e + SIOCBRDGGMA = 0xc0146953 + SIOCBRDGGPARAM = 0xc0406958 + SIOCBRDGGPRI = 0xc0146950 + SIOCBRDGGRL = 0xc030694f + SIOCBRDGGTO = 0xc0146946 + SIOCBRDGIFS = 0xc0606942 + SIOCBRDGRTS = 0xc0206943 + SIOCBRDGSADDR = 0xc1286944 + SIOCBRDGSCACHE = 0x80146940 + SIOCBRDGSFD = 0x80146952 + SIOCBRDGSHT = 0x80146951 + SIOCBRDGSIFCOST = 0x80606955 + SIOCBRDGSIFFLGS = 0x8060693f + SIOCBRDGSIFPRIO = 0x80606954 + SIOCBRDGSIFPROT = 0x8060694a + SIOCBRDGSMA = 0x80146953 + SIOCBRDGSPRI = 0x80146950 + SIOCBRDGSPROTO = 0x8014695a + SIOCBRDGSTO = 0x80146945 + SIOCBRDGSTXHC = 0x80146959 + SIOCDELLABEL = 0x80206997 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFGROUP = 0x80286989 + SIOCDIFPARENT = 0x802069b4 + SIOCDIFPHYADDR = 0x80206949 + SIOCDPWE3NEIGHBOR = 0x802069de + SIOCDVNETID = 0x802069af + SIOCGETKALIVE = 0xc01869a4 + SIOCGETLABEL = 0x8020699a + SIOCGETMPWCFG = 0xc02069ae + SIOCGETPFLOW = 0xc02069fe + SIOCGETPFSYNC = 0xc02069f8 + SIOCGETSGCNT = 0xc0207534 + SIOCGETVIFCNT = 0xc0287533 + SIOCGETVLAN = 0xc0206990 + SIOCGIFADDR = 0xc0206921 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCONF = 0xc0106924 + SIOCGIFDATA = 0xc020691b + SIOCGIFDESCR = 0xc0206981 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFGATTR = 0xc028698b + SIOCGIFGENERIC = 0xc020693a + SIOCGIFGLIST = 0xc028698d + SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 + SIOCGIFHARDMTU = 0xc02069a5 + SIOCGIFLLPRIO = 0xc02069b6 + SIOCGIFMEDIA = 0xc0406938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc020697e + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPAIR = 0xc02069b1 + SIOCGIFPARENT = 0xc02069b3 + SIOCGIFPRIORITY = 0xc020699c + SIOCGIFRDOMAIN = 0xc02069a0 + SIOCGIFRTLABEL = 0xc0206983 + SIOCGIFRXR = 0x802069aa + SIOCGIFSFFPAGE = 0xc1126939 + SIOCGIFXFLAGS = 0xc020699e + SIOCGLIFPHYADDR = 0xc218694b + SIOCGLIFPHYDF = 0xc02069c2 + SIOCGLIFPHYECN = 0xc02069c8 + SIOCGLIFPHYRTABLE = 0xc02069a2 + SIOCGLIFPHYTTL = 0xc02069a9 + SIOCGPGRP = 0x40047309 + SIOCGPWE3 = 0xc0206998 + SIOCGPWE3CTRLWORD = 0xc02069dc + SIOCGPWE3FAT = 0xc02069dd + SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db + SIOCGSPPPPARAMS = 0xc0206994 + SIOCGTXHPRIO = 0xc02069c6 + SIOCGUMBINFO = 0xc02069be + SIOCGUMBPARAM = 0xc02069c0 + SIOCGVH = 0xc02069f6 + SIOCGVNETFLOWID = 0xc02069c4 + SIOCGVNETID = 0xc02069a7 + SIOCIFAFATTACH = 0x801169ab + SIOCIFAFDETACH = 0x801169ac + SIOCIFCREATE = 0x8020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106978 + SIOCSETKALIVE = 0x801869a3 + SIOCSETLABEL = 0x80206999 + SIOCSETMPWCFG = 0x802069ad + SIOCSETPFLOW = 0x802069fd + SIOCSETPFSYNC = 0x802069f7 + SIOCSETVLAN = 0x8020698f + SIOCSIFADDR = 0x8020690c + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFDESCR = 0x80206980 + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGATTR = 0x8028698c + SIOCSIFGENERIC = 0x80206939 + SIOCSIFLLADDR = 0x8020691f + SIOCSIFLLPRIO = 0x802069b5 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x8020697f + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPAIR = 0x802069b0 + SIOCSIFPARENT = 0x802069b2 + SIOCSIFPRIORITY = 0x8020699b + SIOCSIFRDOMAIN = 0x8020699f + SIOCSIFRTLABEL = 0x80206982 + SIOCSIFXFLAGS = 0x8020699d + SIOCSLIFPHYADDR = 0x8218694a + SIOCSLIFPHYDF = 0x802069c1 + SIOCSLIFPHYECN = 0x802069c7 + SIOCSLIFPHYRTABLE = 0x802069a1 + SIOCSLIFPHYTTL = 0x802069a8 + SIOCSPGRP = 0x80047308 + SIOCSPWE3CTRLWORD = 0x802069dc + SIOCSPWE3FAT = 0x802069dd + SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db + SIOCSSPPPPARAMS = 0x80206993 + SIOCSTXHPRIO = 0x802069c5 + SIOCSUMBPARAM = 0x802069bf + SIOCSVH = 0xc02069f5 + SIOCSVNETFLOWID = 0x802069c3 + SIOCSVNETID = 0x802069a6 + SOCK_CLOEXEC = 0x8000 + SOCK_DGRAM = 0x2 + SOCK_DNS = 0x1000 + SOCK_NONBLOCK = 0x4000 + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BINDANY = 0x1000 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 + SO_DONTROUTE = 0x10 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LINGER = 0x80 + SO_NETPROC = 0x1020 + SO_OOBINLINE = 0x100 + SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_RTABLE = 0x1021 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_SPLICE = 0x1023 + SO_TIMESTAMP = 0x800 + SO_TYPE = 0x1008 + SO_USELOOPBACK = 0x40 + SO_ZEROIZE = 0x2000 + S_BLKSIZE = 0x200 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x3 + TCP_MAX_WINSHIFT = 0xe + TCP_MD5SIG = 0x4 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOPUSH = 0x10 + TCP_SACKHOLE_LIMIT = 0x80 + TCP_SACK_ENABLE = 0x8 + TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCHKVERAUTH = 0x2000741e + TIOCCLRVERAUTH = 0x2000741d + TIOCCONS = 0x80047462 + TIOCDRAIN = 0x2000745e + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLAG_CLOCAL = 0x2 + TIOCFLAG_CRTSCTS = 0x4 + TIOCFLAG_MDMBUF = 0x8 + TIOCFLAG_PPS = 0x10 + TIOCFLAG_SOFTCAR = 0x1 + TIOCFLUSH = 0x80047410 + TIOCGETA = 0x402c7413 + TIOCGETD = 0x4004741a + TIOCGFLAGS = 0x4004745d + TIOCGPGRP = 0x40047477 + TIOCGSID = 0x40047463 + TIOCGTSTAMP = 0x4010745b + TIOCGWINSZ = 0x40087468 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGET = 0x4004746a + TIOCMODG = 0x4004746a + TIOCMODS = 0x8004746d + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCTTY = 0x20007461 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x802c7414 + TIOCSETAF = 0x802c7416 + TIOCSETAW = 0x802c7415 + TIOCSETD = 0x8004741b + TIOCSETVERAUTH = 0x8004741c + TIOCSFLAGS = 0x8004745c + TIOCSIG = 0x8004745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTOP = 0x2000746f + TIOCSTSTAMP = 0x8008745a + TIOCSWINSZ = 0x80087467 + TIOCUCNTL = 0x80047466 + TIOCUCNTL_CBRK = 0x7a + TIOCUCNTL_SBRK = 0x7b + TOSTOP = 0x400000 + UTIME_NOW = -0x2 + UTIME_OMIT = -0x1 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMIN = 0x10 + VM_ANONMIN = 0x7 + VM_LOADAVG = 0x2 + VM_MALLOC_CONF = 0xc + VM_MAXID = 0xd + VM_MAXSLP = 0xa + VM_METER = 0x1 + VM_NKMEMPAGES = 0x6 + VM_PSSTRINGS = 0x3 + VM_SWAPENCRYPT = 0x5 + VM_USPACE = 0xb + VM_UVMEXP = 0x4 + VM_VNODEMIN = 0x9 + VM_VTEXTMIN = 0x8 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VTIME = 0x11 + VWERASE = 0x4 + WALTSIG = 0x4 + WCONTINUED = 0x8 + WCOREFLAG = 0x80 + WNOHANG = 0x1 + WUNTRACED = 0x2 + XCASE = 0x1000000 +) + +// Errors +const ( + E2BIG = syscall.Errno(0x7) + EACCES = syscall.Errno(0xd) + EADDRINUSE = syscall.Errno(0x30) + EADDRNOTAVAIL = syscall.Errno(0x31) + EAFNOSUPPORT = syscall.Errno(0x2f) + EAGAIN = syscall.Errno(0x23) + EALREADY = syscall.Errno(0x25) + EAUTH = syscall.Errno(0x50) + EBADF = syscall.Errno(0x9) + EBADMSG = syscall.Errno(0x5c) + EBADRPC = syscall.Errno(0x48) + EBUSY = syscall.Errno(0x10) + ECANCELED = syscall.Errno(0x58) + ECHILD = syscall.Errno(0xa) + ECONNABORTED = syscall.Errno(0x35) + ECONNREFUSED = syscall.Errno(0x3d) + ECONNRESET = syscall.Errno(0x36) + EDEADLK = syscall.Errno(0xb) + EDESTADDRREQ = syscall.Errno(0x27) + EDOM = syscall.Errno(0x21) + EDQUOT = syscall.Errno(0x45) + EEXIST = syscall.Errno(0x11) + EFAULT = syscall.Errno(0xe) + EFBIG = syscall.Errno(0x1b) + EFTYPE = syscall.Errno(0x4f) + EHOSTDOWN = syscall.Errno(0x40) + EHOSTUNREACH = syscall.Errno(0x41) + EIDRM = syscall.Errno(0x59) + EILSEQ = syscall.Errno(0x54) + EINPROGRESS = syscall.Errno(0x24) + EINTR = syscall.Errno(0x4) + EINVAL = syscall.Errno(0x16) + EIO = syscall.Errno(0x5) + EIPSEC = syscall.Errno(0x52) + EISCONN = syscall.Errno(0x38) + EISDIR = syscall.Errno(0x15) + ELAST = syscall.Errno(0x5f) + ELOOP = syscall.Errno(0x3e) + EMEDIUMTYPE = syscall.Errno(0x56) + EMFILE = syscall.Errno(0x18) + EMLINK = syscall.Errno(0x1f) + EMSGSIZE = syscall.Errno(0x28) + ENAMETOOLONG = syscall.Errno(0x3f) + ENEEDAUTH = syscall.Errno(0x51) + ENETDOWN = syscall.Errno(0x32) + ENETRESET = syscall.Errno(0x34) + ENETUNREACH = syscall.Errno(0x33) + ENFILE = syscall.Errno(0x17) + ENOATTR = syscall.Errno(0x53) + ENOBUFS = syscall.Errno(0x37) + ENODEV = syscall.Errno(0x13) + ENOENT = syscall.Errno(0x2) + ENOEXEC = syscall.Errno(0x8) + ENOLCK = syscall.Errno(0x4d) + ENOMEDIUM = syscall.Errno(0x55) + ENOMEM = syscall.Errno(0xc) + ENOMSG = syscall.Errno(0x5a) + ENOPROTOOPT = syscall.Errno(0x2a) + ENOSPC = syscall.Errno(0x1c) + ENOSYS = syscall.Errno(0x4e) + ENOTBLK = syscall.Errno(0xf) + ENOTCONN = syscall.Errno(0x39) + ENOTDIR = syscall.Errno(0x14) + ENOTEMPTY = syscall.Errno(0x42) + ENOTRECOVERABLE = syscall.Errno(0x5d) + ENOTSOCK = syscall.Errno(0x26) + ENOTSUP = syscall.Errno(0x5b) + ENOTTY = syscall.Errno(0x19) + ENXIO = syscall.Errno(0x6) + EOPNOTSUPP = syscall.Errno(0x2d) + EOVERFLOW = syscall.Errno(0x57) + EOWNERDEAD = syscall.Errno(0x5e) + EPERM = syscall.Errno(0x1) + EPFNOSUPPORT = syscall.Errno(0x2e) + EPIPE = syscall.Errno(0x20) + EPROCLIM = syscall.Errno(0x43) + EPROCUNAVAIL = syscall.Errno(0x4c) + EPROGMISMATCH = syscall.Errno(0x4b) + EPROGUNAVAIL = syscall.Errno(0x4a) + EPROTO = syscall.Errno(0x5f) + EPROTONOSUPPORT = syscall.Errno(0x2b) + EPROTOTYPE = syscall.Errno(0x29) + ERANGE = syscall.Errno(0x22) + EREMOTE = syscall.Errno(0x47) + EROFS = syscall.Errno(0x1e) + ERPCMISMATCH = syscall.Errno(0x49) + ESHUTDOWN = syscall.Errno(0x3a) + ESOCKTNOSUPPORT = syscall.Errno(0x2c) + ESPIPE = syscall.Errno(0x1d) + ESRCH = syscall.Errno(0x3) + ESTALE = syscall.Errno(0x46) + ETIMEDOUT = syscall.Errno(0x3c) + ETOOMANYREFS = syscall.Errno(0x3b) + ETXTBSY = syscall.Errno(0x1a) + EUSERS = syscall.Errno(0x44) + EWOULDBLOCK = syscall.Errno(0x23) + EXDEV = syscall.Errno(0x12) +) + +// Signals +const ( + SIGABRT = syscall.Signal(0x6) + SIGALRM = syscall.Signal(0xe) + SIGBUS = syscall.Signal(0xa) + SIGCHLD = syscall.Signal(0x14) + SIGCONT = syscall.Signal(0x13) + SIGEMT = syscall.Signal(0x7) + SIGFPE = syscall.Signal(0x8) + SIGHUP = syscall.Signal(0x1) + SIGILL = syscall.Signal(0x4) + SIGINFO = syscall.Signal(0x1d) + SIGINT = syscall.Signal(0x2) + SIGIO = syscall.Signal(0x17) + SIGIOT = syscall.Signal(0x6) + SIGKILL = syscall.Signal(0x9) + SIGPIPE = syscall.Signal(0xd) + SIGPROF = syscall.Signal(0x1b) + SIGQUIT = syscall.Signal(0x3) + SIGSEGV = syscall.Signal(0xb) + SIGSTOP = syscall.Signal(0x11) + SIGSYS = syscall.Signal(0xc) + SIGTERM = syscall.Signal(0xf) + SIGTHR = syscall.Signal(0x20) + SIGTRAP = syscall.Signal(0x5) + SIGTSTP = syscall.Signal(0x12) + SIGTTIN = syscall.Signal(0x15) + SIGTTOU = syscall.Signal(0x16) + SIGURG = syscall.Signal(0x10) + SIGUSR1 = syscall.Signal(0x1e) + SIGUSR2 = syscall.Signal(0x1f) + SIGVTALRM = syscall.Signal(0x1a) + SIGWINCH = syscall.Signal(0x1c) + SIGXCPU = syscall.Signal(0x18) + SIGXFSZ = syscall.Signal(0x19) +) + +// Error table +var errorList = [...]struct { + num syscall.Errno + name string + desc string +}{ + {1, "EPERM", "operation not permitted"}, + {2, "ENOENT", "no such file or directory"}, + {3, "ESRCH", "no such process"}, + {4, "EINTR", "interrupted system call"}, + {5, "EIO", "input/output error"}, + {6, "ENXIO", "device not configured"}, + {7, "E2BIG", "argument list too long"}, + {8, "ENOEXEC", "exec format error"}, + {9, "EBADF", "bad file descriptor"}, + {10, "ECHILD", "no child processes"}, + {11, "EDEADLK", "resource deadlock avoided"}, + {12, "ENOMEM", "cannot allocate memory"}, + {13, "EACCES", "permission denied"}, + {14, "EFAULT", "bad address"}, + {15, "ENOTBLK", "block device required"}, + {16, "EBUSY", "device busy"}, + {17, "EEXIST", "file exists"}, + {18, "EXDEV", "cross-device link"}, + {19, "ENODEV", "operation not supported by device"}, + {20, "ENOTDIR", "not a directory"}, + {21, "EISDIR", "is a directory"}, + {22, "EINVAL", "invalid argument"}, + {23, "ENFILE", "too many open files in system"}, + {24, "EMFILE", "too many open files"}, + {25, "ENOTTY", "inappropriate ioctl for device"}, + {26, "ETXTBSY", "text file busy"}, + {27, "EFBIG", "file too large"}, + {28, "ENOSPC", "no space left on device"}, + {29, "ESPIPE", "illegal seek"}, + {30, "EROFS", "read-only file system"}, + {31, "EMLINK", "too many links"}, + {32, "EPIPE", "broken pipe"}, + {33, "EDOM", "numerical argument out of domain"}, + {34, "ERANGE", "result too large"}, + {35, "EAGAIN", "resource temporarily unavailable"}, + {36, "EINPROGRESS", "operation now in progress"}, + {37, "EALREADY", "operation already in progress"}, + {38, "ENOTSOCK", "socket operation on non-socket"}, + {39, "EDESTADDRREQ", "destination address required"}, + {40, "EMSGSIZE", "message too long"}, + {41, "EPROTOTYPE", "protocol wrong type for socket"}, + {42, "ENOPROTOOPT", "protocol not available"}, + {43, "EPROTONOSUPPORT", "protocol not supported"}, + {44, "ESOCKTNOSUPPORT", "socket type not supported"}, + {45, "EOPNOTSUPP", "operation not supported"}, + {46, "EPFNOSUPPORT", "protocol family not supported"}, + {47, "EAFNOSUPPORT", "address family not supported by protocol family"}, + {48, "EADDRINUSE", "address already in use"}, + {49, "EADDRNOTAVAIL", "can't assign requested address"}, + {50, "ENETDOWN", "network is down"}, + {51, "ENETUNREACH", "network is unreachable"}, + {52, "ENETRESET", "network dropped connection on reset"}, + {53, "ECONNABORTED", "software caused connection abort"}, + {54, "ECONNRESET", "connection reset by peer"}, + {55, "ENOBUFS", "no buffer space available"}, + {56, "EISCONN", "socket is already connected"}, + {57, "ENOTCONN", "socket is not connected"}, + {58, "ESHUTDOWN", "can't send after socket shutdown"}, + {59, "ETOOMANYREFS", "too many references: can't splice"}, + {60, "ETIMEDOUT", "operation timed out"}, + {61, "ECONNREFUSED", "connection refused"}, + {62, "ELOOP", "too many levels of symbolic links"}, + {63, "ENAMETOOLONG", "file name too long"}, + {64, "EHOSTDOWN", "host is down"}, + {65, "EHOSTUNREACH", "no route to host"}, + {66, "ENOTEMPTY", "directory not empty"}, + {67, "EPROCLIM", "too many processes"}, + {68, "EUSERS", "too many users"}, + {69, "EDQUOT", "disk quota exceeded"}, + {70, "ESTALE", "stale NFS file handle"}, + {71, "EREMOTE", "too many levels of remote in path"}, + {72, "EBADRPC", "RPC struct is bad"}, + {73, "ERPCMISMATCH", "RPC version wrong"}, + {74, "EPROGUNAVAIL", "RPC program not available"}, + {75, "EPROGMISMATCH", "program version wrong"}, + {76, "EPROCUNAVAIL", "bad procedure for program"}, + {77, "ENOLCK", "no locks available"}, + {78, "ENOSYS", "function not implemented"}, + {79, "EFTYPE", "inappropriate file type or format"}, + {80, "EAUTH", "authentication error"}, + {81, "ENEEDAUTH", "need authenticator"}, + {82, "EIPSEC", "IPsec processing failure"}, + {83, "ENOATTR", "attribute not found"}, + {84, "EILSEQ", "illegal byte sequence"}, + {85, "ENOMEDIUM", "no medium found"}, + {86, "EMEDIUMTYPE", "wrong medium type"}, + {87, "EOVERFLOW", "value too large to be stored in data type"}, + {88, "ECANCELED", "operation canceled"}, + {89, "EIDRM", "identifier removed"}, + {90, "ENOMSG", "no message of desired type"}, + {91, "ENOTSUP", "not supported"}, + {92, "EBADMSG", "bad message"}, + {93, "ENOTRECOVERABLE", "state not recoverable"}, + {94, "EOWNERDEAD", "previous owner died"}, + {95, "ELAST", "protocol error"}, +} + +// Signal table +var signalList = [...]struct { + num syscall.Signal + name string + desc string +}{ + {1, "SIGHUP", "hangup"}, + {2, "SIGINT", "interrupt"}, + {3, "SIGQUIT", "quit"}, + {4, "SIGILL", "illegal instruction"}, + {5, "SIGTRAP", "trace/BPT trap"}, + {6, "SIGIOT", "abort trap"}, + {7, "SIGEMT", "EMT trap"}, + {8, "SIGFPE", "floating point exception"}, + {9, "SIGKILL", "killed"}, + {10, "SIGBUS", "bus error"}, + {11, "SIGSEGV", "segmentation fault"}, + {12, "SIGSYS", "bad system call"}, + {13, "SIGPIPE", "broken pipe"}, + {14, "SIGALRM", "alarm clock"}, + {15, "SIGTERM", "terminated"}, + {16, "SIGURG", "urgent I/O condition"}, + {17, "SIGSTOP", "suspended (signal)"}, + {18, "SIGTSTP", "suspended"}, + {19, "SIGCONT", "continued"}, + {20, "SIGCHLD", "child exited"}, + {21, "SIGTTIN", "stopped (tty input)"}, + {22, "SIGTTOU", "stopped (tty output)"}, + {23, "SIGIO", "I/O possible"}, + {24, "SIGXCPU", "cputime limit exceeded"}, + {25, "SIGXFSZ", "filesize limit exceeded"}, + {26, "SIGVTALRM", "virtual timer expired"}, + {27, "SIGPROF", "profiling timer expired"}, + {28, "SIGWINCH", "window size changes"}, + {29, "SIGINFO", "information request"}, + {30, "SIGUSR1", "user defined signal 1"}, + {31, "SIGUSR2", "user defined signal 2"}, + {32, "SIGTHR", "thread AST"}, + {81920, "SIGSTKSZ", "unknown signal"}, +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go similarity index 50% rename from vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go rename to vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go index 3e41757..43ca0cd 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go @@ -1,10 +1,10 @@ -// mkerrors.sh +// mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,darwin +//go:build ppc64 && openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- _const.go +// cgo -godefs -- -m64 _const.go package unix @@ -12,6 +12,7 @@ import "syscall" const ( AF_APPLETALK = 0x10 + AF_BLUETOOTH = 0x20 AF_CCITT = 0xa AF_CHAOS = 0x5 AF_CNT = 0x15 @@ -19,116 +20,36 @@ const ( AF_DATAKIT = 0x9 AF_DECnet = 0xc AF_DLI = 0xd - AF_E164 = 0x1c + AF_E164 = 0x1a AF_ECMA = 0x8 + AF_ENCAP = 0x1c AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 AF_IMPLINK = 0x3 AF_INET = 0x2 - AF_INET6 = 0x1e + AF_INET6 = 0x18 AF_IPX = 0x17 - AF_ISDN = 0x1c + AF_ISDN = 0x1a AF_ISO = 0x7 + AF_KEY = 0x1e AF_LAT = 0xe AF_LINK = 0x12 AF_LOCAL = 0x1 - AF_MAX = 0x28 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 + AF_MAX = 0x24 + AF_MPLS = 0x21 + AF_NATM = 0x1b AF_NS = 0x6 AF_OSI = 0x7 - AF_PPP = 0x22 AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 AF_ROUTE = 0x11 - AF_SIP = 0x18 + AF_SIP = 0x1d AF_SNA = 0xb - AF_SYSTEM = 0x20 AF_UNIX = 0x1 AF_UNSPEC = 0x0 - AF_UTUN = 0x26 ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x41c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff + ARPHRD_ETHER = 0x1 + ARPHRD_FRELAY = 0xf + ARPHRD_IEEE1394 = 0x18 + ARPHRD_IEEE802 = 0x6 B0 = 0x0 B110 = 0x6e B115200 = 0x1c200 @@ -154,25 +75,28 @@ const ( B9600 = 0x2580 BIOCFLUSH = 0x20004268 BIOCGBLEN = 0x40044266 + BIOCGDIRFILT = 0x4004427c BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 + BIOCGDLTLIST = 0xc010427b BIOCGETIF = 0x4020426b + BIOCGFILDROP = 0x40044278 BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 + BIOCGRSIG = 0x40044273 BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 BIOCGSTATS = 0x4008426f BIOCIMMEDIATE = 0x80044270 + BIOCLOCK = 0x20004276 BIOCPROMISC = 0x20004269 BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 + BIOCSDIRFILT = 0x8004427d + BIOCSDLT = 0x8004427a BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e BIOCSETIF = 0x8020426c + BIOCSETWF = 0x80104277 + BIOCSFILDROP = 0x80044279 BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 + BIOCSRSIG = 0x80044272 BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 BIOCVERSION = 0x40044271 BPF_A = 0x10 BPF_ABS = 0x20 @@ -181,7 +105,18 @@ const ( BPF_ALU = 0x4 BPF_AND = 0x50 BPF_B = 0x10 + BPF_DIRECTION_IN = 0x1 + BPF_DIRECTION_OUT = 0x2 BPF_DIV = 0x30 + BPF_FILDROP_CAPTURE = 0x1 + BPF_FILDROP_DROP = 0x2 + BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 @@ -197,7 +132,7 @@ const ( BPF_LEN = 0x80 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 + BPF_MAXBUFSIZE = 0x200000 BPF_MAXINSNS = 0x200 BPF_MEM = 0x60 BPF_MEMWORDS = 0x10 @@ -210,6 +145,7 @@ const ( BPF_OR = 0x40 BPF_RELEASE = 0x30bb6 BPF_RET = 0x6 + BPF_RND = 0xc0 BPF_RSH = 0x70 BPF_ST = 0x2 BPF_STX = 0x3 @@ -219,33 +155,30 @@ const ( BPF_W = 0x0 BPF_X = 0x8 BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 CFLUSH = 0xf CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_BOOTTIME = 0x6 + CLOCK_MONOTONIC = 0x3 + CLOCK_PROCESS_CPUTIME_ID = 0x2 CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 + CLOCK_THREAD_CPUTIME_ID = 0x4 + CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 - CRTSCTS = 0x30000 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 CS8 = 0x300 CSIZE = 0x300 CSTART = 0x11 - CSTATUS = 0x14 + CSTATUS = 0xff CSTOP = 0x13 CSTOPB = 0x400 CSUSP = 0x1a @@ -253,149 +186,92 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0xc CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DIOCADDQUEUE = 0xc110445d + DIOCADDRULE = 0xcd604404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xcd60441a + DIOCCLRIFFLAG = 0xc028445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0e04412 + DIOCCLRSTATUS = 0xc0284416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1204460 + DIOCGETQUEUE = 0xc110445f + DIOCGETQUEUES = 0xc110445e + DIOCGETRULE = 0xcd604407 + DIOCGETRULES = 0xcd604406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0104454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0104419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0284457 + DIOCKILLSRCNODES = 0xc080445b + DIOCKILLSTATES = 0xc0e04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc088444f + DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0884450 + DIOCRADDADDRS = 0xc4504443 + DIOCRADDTABLES = 0xc450443d + DIOCRCLRADDRS = 0xc4504442 + DIOCRCLRASTATS = 0xc4504448 + DIOCRCLRTABLES = 0xc450443c + DIOCRCLRTSTATS = 0xc4504441 + DIOCRDELADDRS = 0xc4504444 + DIOCRDELTABLES = 0xc450443e + DIOCRGETADDRS = 0xc4504446 + DIOCRGETASTATS = 0xc4504447 + DIOCRGETTABLES = 0xc450443f + DIOCRGETTSTATS = 0xc4504440 + DIOCRINADEFINE = 0xc450444d + DIOCRSETADDRS = 0xc4504445 + DIOCRSETTFLAGS = 0xc450444a + DIOCRTSTADDRS = 0xc4504449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0284459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0284414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc0104451 + DIOCXCOMMIT = 0xc0104452 + DIOCXROLLBACK = 0xc0104453 DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 DLT_EN10MB = 0x1 DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_ENC = 0xd DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 DLT_IEEE802 = 0x6 DLT_IEEE802_11 = 0x69 DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0xf5 - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 + DLT_LOOP = 0xc DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d + DLT_OPENFLOW = 0x10b DLT_PFLOG = 0x75 DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 DLT_PPP = 0x9 DLT_PPP_BSDOS = 0x10 DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 + DLT_RAW = 0xe DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USBPCAP = 0xf9 DLT_USER0 = 0x93 DLT_USER1 = 0x94 DLT_USER10 = 0x9d @@ -412,9 +288,6 @@ const ( DLT_USER7 = 0x9a DLT_USER8 = 0x9b DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -423,7 +296,6 @@ const ( DT_REG = 0x8 DT_SOCK = 0xc DT_UNKNOWN = 0x0 - DT_WHT = 0xe ECHO = 0x8 ECHOCTL = 0x40 ECHOE = 0x2 @@ -431,107 +303,265 @@ const ( ECHOKE = 0x1 ECHONL = 0x10 ECHOPRT = 0x20 + EMT_TAGOVF = 0x1 + EMUL_ENABLED = 0x1 + EMUL_NATIVE = 0x2 + ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 + ETHERMIN = 0x2e + ETHERMTU = 0x5dc + ETHERTYPE_8023 = 0x4 + ETHERTYPE_AARP = 0x80f3 + ETHERTYPE_ACCTON = 0x8390 + ETHERTYPE_AEONIC = 0x8036 + ETHERTYPE_ALPHA = 0x814a + ETHERTYPE_AMBER = 0x6008 + ETHERTYPE_AMOEBA = 0x8145 + ETHERTYPE_AOE = 0x88a2 + ETHERTYPE_APOLLO = 0x80f7 + ETHERTYPE_APOLLODOMAIN = 0x8019 + ETHERTYPE_APPLETALK = 0x809b + ETHERTYPE_APPLITEK = 0x80c7 + ETHERTYPE_ARGONAUT = 0x803a + ETHERTYPE_ARP = 0x806 + ETHERTYPE_AT = 0x809b + ETHERTYPE_ATALK = 0x809b + ETHERTYPE_ATOMIC = 0x86df + ETHERTYPE_ATT = 0x8069 + ETHERTYPE_ATTSTANFORD = 0x8008 + ETHERTYPE_AUTOPHON = 0x806a + ETHERTYPE_AXIS = 0x8856 + ETHERTYPE_BCLOOP = 0x9003 + ETHERTYPE_BOFL = 0x8102 + ETHERTYPE_CABLETRON = 0x7034 + ETHERTYPE_CHAOS = 0x804 + ETHERTYPE_COMDESIGN = 0x806c + ETHERTYPE_COMPUGRAPHIC = 0x806d + ETHERTYPE_COUNTERPOINT = 0x8062 + ETHERTYPE_CRONUS = 0x8004 + ETHERTYPE_CRONUSVLN = 0x8003 + ETHERTYPE_DCA = 0x1234 + ETHERTYPE_DDE = 0x807b + ETHERTYPE_DEBNI = 0xaaaa + ETHERTYPE_DECAM = 0x8048 + ETHERTYPE_DECCUST = 0x6006 + ETHERTYPE_DECDIAG = 0x6005 + ETHERTYPE_DECDNS = 0x803c + ETHERTYPE_DECDTS = 0x803e + ETHERTYPE_DECEXPER = 0x6000 + ETHERTYPE_DECLAST = 0x8041 + ETHERTYPE_DECLTM = 0x803f + ETHERTYPE_DECMUMPS = 0x6009 + ETHERTYPE_DECNETBIOS = 0x8040 + ETHERTYPE_DELTACON = 0x86de + ETHERTYPE_DIDDLE = 0x4321 + ETHERTYPE_DLOG1 = 0x660 + ETHERTYPE_DLOG2 = 0x661 + ETHERTYPE_DN = 0x6003 + ETHERTYPE_DOGFIGHT = 0x1989 + ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e + ETHERTYPE_ECMA = 0x803 + ETHERTYPE_ENCRYPT = 0x803d + ETHERTYPE_ES = 0x805d + ETHERTYPE_EXCELAN = 0x8010 + ETHERTYPE_EXPERDATA = 0x8049 + ETHERTYPE_FLIP = 0x8146 + ETHERTYPE_FLOWCONTROL = 0x8808 + ETHERTYPE_FRARP = 0x808 + ETHERTYPE_GENDYN = 0x8068 + ETHERTYPE_HAYES = 0x8130 + ETHERTYPE_HIPPI_FP = 0x8180 + ETHERTYPE_HITACHI = 0x8820 + ETHERTYPE_HP = 0x8005 + ETHERTYPE_IEEEPUP = 0xa00 + ETHERTYPE_IEEEPUPAT = 0xa01 + ETHERTYPE_IMLBL = 0x4c42 + ETHERTYPE_IMLBLDIAG = 0x424c + ETHERTYPE_IP = 0x800 + ETHERTYPE_IPAS = 0x876c + ETHERTYPE_IPV6 = 0x86dd + ETHERTYPE_IPX = 0x8137 + ETHERTYPE_IPXNEW = 0x8037 + ETHERTYPE_KALPANA = 0x8582 + ETHERTYPE_LANBRIDGE = 0x8038 + ETHERTYPE_LANPROBE = 0x8888 + ETHERTYPE_LAT = 0x6004 + ETHERTYPE_LBACK = 0x9000 + ETHERTYPE_LITTLE = 0x8060 + ETHERTYPE_LLDP = 0x88cc + ETHERTYPE_LOGICRAFT = 0x8148 + ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 + ETHERTYPE_MATRA = 0x807a + ETHERTYPE_MAX = 0xffff + ETHERTYPE_MERIT = 0x807c + ETHERTYPE_MICP = 0x873a + ETHERTYPE_MOPDL = 0x6001 + ETHERTYPE_MOPRC = 0x6002 + ETHERTYPE_MOTOROLA = 0x818d + ETHERTYPE_MPLS = 0x8847 + ETHERTYPE_MPLS_MCAST = 0x8848 + ETHERTYPE_MUMPS = 0x813f + ETHERTYPE_NBPCC = 0x3c04 + ETHERTYPE_NBPCLAIM = 0x3c09 + ETHERTYPE_NBPCLREQ = 0x3c05 + ETHERTYPE_NBPCLRSP = 0x3c06 + ETHERTYPE_NBPCREQ = 0x3c02 + ETHERTYPE_NBPCRSP = 0x3c03 + ETHERTYPE_NBPDG = 0x3c07 + ETHERTYPE_NBPDGB = 0x3c08 + ETHERTYPE_NBPDLTE = 0x3c0a + ETHERTYPE_NBPRAR = 0x3c0c + ETHERTYPE_NBPRAS = 0x3c0b + ETHERTYPE_NBPRST = 0x3c0d + ETHERTYPE_NBPSCD = 0x3c01 + ETHERTYPE_NBPVCD = 0x3c00 + ETHERTYPE_NBS = 0x802 + ETHERTYPE_NCD = 0x8149 + ETHERTYPE_NESTAR = 0x8006 + ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 + ETHERTYPE_NOVELL = 0x8138 + ETHERTYPE_NS = 0x600 + ETHERTYPE_NSAT = 0x601 + ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f + ETHERTYPE_NTRAILER = 0x10 + ETHERTYPE_OS9 = 0x7007 + ETHERTYPE_OS9NET = 0x7009 + ETHERTYPE_PACER = 0x80c6 + ETHERTYPE_PBB = 0x88e7 + ETHERTYPE_PCS = 0x4242 + ETHERTYPE_PLANNING = 0x8044 + ETHERTYPE_PPP = 0x880b + ETHERTYPE_PPPOE = 0x8864 + ETHERTYPE_PPPOEDISC = 0x8863 + ETHERTYPE_PRIMENTS = 0x7031 + ETHERTYPE_PUP = 0x200 + ETHERTYPE_PUPAT = 0x200 + ETHERTYPE_QINQ = 0x88a8 + ETHERTYPE_RACAL = 0x7030 + ETHERTYPE_RATIONAL = 0x8150 + ETHERTYPE_RAWFR = 0x6559 + ETHERTYPE_RCL = 0x1995 + ETHERTYPE_RDP = 0x8739 + ETHERTYPE_RETIX = 0x80f2 + ETHERTYPE_REVARP = 0x8035 + ETHERTYPE_SCA = 0x6007 + ETHERTYPE_SECTRA = 0x86db + ETHERTYPE_SECUREDATA = 0x876d + ETHERTYPE_SGITW = 0x817e + ETHERTYPE_SG_BOUNCE = 0x8016 + ETHERTYPE_SG_DIAG = 0x8013 + ETHERTYPE_SG_NETGAMES = 0x8014 + ETHERTYPE_SG_RESV = 0x8015 + ETHERTYPE_SIMNET = 0x5208 + ETHERTYPE_SLOW = 0x8809 + ETHERTYPE_SNA = 0x80d5 + ETHERTYPE_SNMP = 0x814c + ETHERTYPE_SONIX = 0xfaf5 + ETHERTYPE_SPIDER = 0x809f + ETHERTYPE_SPRITE = 0x500 + ETHERTYPE_STP = 0x8181 + ETHERTYPE_TALARIS = 0x812b + ETHERTYPE_TALARISMC = 0x852b + ETHERTYPE_TCPCOMP = 0x876b + ETHERTYPE_TCPSM = 0x9002 + ETHERTYPE_TEC = 0x814f + ETHERTYPE_TIGAN = 0x802f + ETHERTYPE_TRAIL = 0x1000 + ETHERTYPE_TRANSETHER = 0x6558 + ETHERTYPE_TYMSHARE = 0x802e + ETHERTYPE_UBBST = 0x7005 + ETHERTYPE_UBDEBUG = 0x900 + ETHERTYPE_UBDIAGLOOP = 0x7002 + ETHERTYPE_UBDL = 0x7000 + ETHERTYPE_UBNIU = 0x7001 + ETHERTYPE_UBNMC = 0x7003 + ETHERTYPE_VALID = 0x1600 + ETHERTYPE_VARIAN = 0x80dd + ETHERTYPE_VAXELN = 0x803b + ETHERTYPE_VEECO = 0x8067 + ETHERTYPE_VEXP = 0x805b + ETHERTYPE_VGLAB = 0x8131 + ETHERTYPE_VINES = 0xbad + ETHERTYPE_VINESECHO = 0xbaf + ETHERTYPE_VINESLOOP = 0xbae + ETHERTYPE_VITAL = 0xff00 + ETHERTYPE_VLAN = 0x8100 + ETHERTYPE_VLTLMAN = 0x8080 + ETHERTYPE_VPROD = 0x805c + ETHERTYPE_VURESERVED = 0x8147 + ETHERTYPE_WATERLOO = 0x8130 + ETHERTYPE_WELLFLEET = 0x8103 + ETHERTYPE_X25 = 0x805 + ETHERTYPE_X75 = 0x801 + ETHERTYPE_XNSSM = 0x9001 + ETHERTYPE_XTP = 0x817d + ETHER_ADDR_LEN = 0x6 + ETHER_ALIGN = 0x2 + ETHER_CRC_LEN = 0x4 + ETHER_CRC_POLY_BE = 0x4c11db6 + ETHER_CRC_POLY_LE = 0xedb88320 + ETHER_HDR_LEN = 0xe + ETHER_MAX_DIX_LEN = 0x600 + ETHER_MAX_HARDMTU_LEN = 0xff9b + ETHER_MAX_LEN = 0x5ee + ETHER_MIN_LEN = 0x40 + ETHER_TYPE_LEN = 0x2 + ETHER_VLAN_ENCAP_LEN = 0x4 EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 + EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 EVFILT_PROC = -0x5 EVFILT_READ = -0x1 EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xf - EVFILT_THREADMARKER = 0xf + EVFILT_SYSCOUNT = 0x9 EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 + EVL_ENCAPLEN = 0x4 + EVL_PRIO_BITS = 0xd + EVL_PRIO_MAX = 0x7 + EVL_VLID_MASK = 0xfff + EVL_VLID_MAX = 0xffe + EVL_VLID_MIN = 0x1 + EVL_VLID_NULL = 0x0 EV_ADD = 0x1 EV_CLEAR = 0x20 EV_DELETE = 0x2 EV_DISABLE = 0x8 EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 EV_ENABLE = 0x4 EV_EOF = 0x8000 EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 EV_FLAG1 = 0x2000 EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTPROC = 0x800 FD_CLOEXEC = 0x1 FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 + F_DUPFD_CLOEXEC = 0xa F_GETFD = 0x1 F_GETFL = 0x3 F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e + F_ISATTY = 0xb F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 F_SETFD = 0x2 F_SETFL = 0x4 F_SETLK = 0x8 F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 F_WRLCK = 0x3 HUPCL = 0x4000 HW_MACHINE = 0x1 @@ -539,9 +569,11 @@ const ( ICMP6_FILTER = 0x12 ICRNL = 0x100 IEXTEN = 0x400 + IFAN_ARRIVAL = 0x0 + IFAN_DEPARTURE = 0x1 IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 IFF_BROADCAST = 0x2 + IFF_CANTCHANGE = 0x8e52 IFF_DEBUG = 0x4 IFF_LINK0 = 0x1000 IFF_LINK1 = 0x2000 @@ -549,80 +581,237 @@ const ( IFF_LOOPBACK = 0x8 IFF_MULTICAST = 0x8000 IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 IFF_OACTIVE = 0x400 IFF_POINTOPOINT = 0x10 IFF_PROMISC = 0x100 IFF_RUNNING = 0x40 IFF_SIMPLEX = 0x800 + IFF_STATICARP = 0x20 IFF_UP = 0x1 IFNAMSIZ = 0x10 IFT_1822 = 0x2 + IFT_A12MPPSWITCH = 0x82 + IFT_AAL2 = 0xbb IFT_AAL5 = 0x31 + IFT_ADSL = 0x5e + IFT_AFLANE8023 = 0x3b + IFT_AFLANE8025 = 0x3c + IFT_ARAP = 0x58 IFT_ARCNET = 0x23 IFT_ARCNETPLUS = 0x24 + IFT_ASYNC = 0x54 IFT_ATM = 0x25 + IFT_ATMDXI = 0x69 + IFT_ATMFUNI = 0x6a + IFT_ATMIMA = 0x6b + IFT_ATMLOGICAL = 0x50 + IFT_ATMRADIO = 0xbd + IFT_ATMSUBINTERFACE = 0x86 + IFT_ATMVCIENDPT = 0xc2 + IFT_ATMVIRTUAL = 0x95 + IFT_BGPPOLICYACCOUNTING = 0xa2 + IFT_BLUETOOTH = 0xf8 IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff + IFT_BSC = 0x53 + IFT_CARP = 0xf7 + IFT_CCTEMUL = 0x3d IFT_CEPT = 0x13 + IFT_CES = 0x85 + IFT_CHANNEL = 0x46 + IFT_CNR = 0x55 + IFT_COFFEE = 0x84 + IFT_COMPOSITELINK = 0x9b + IFT_DCN = 0x8d + IFT_DIGITALPOWERLINE = 0x8a + IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba + IFT_DLSW = 0x4a + IFT_DOCSCABLEDOWNSTREAM = 0x80 + IFT_DOCSCABLEMACLAYER = 0x7f + IFT_DOCSCABLEUPSTREAM = 0x81 + IFT_DOCSCABLEUPSTREAMCHANNEL = 0xcd + IFT_DS0 = 0x51 + IFT_DS0BUNDLE = 0x52 + IFT_DS1FDL = 0xaa IFT_DS3 = 0x1e + IFT_DTM = 0x8c + IFT_DUMMY = 0xf1 + IFT_DVBASILN = 0xac + IFT_DVBASIOUT = 0xad + IFT_DVBRCCDOWNSTREAM = 0x93 + IFT_DVBRCCMACLAYER = 0x92 + IFT_DVBRCCUPSTREAM = 0x94 + IFT_ECONET = 0xce IFT_ENC = 0xf4 IFT_EON = 0x19 + IFT_EPLRS = 0x57 + IFT_ESCON = 0x49 IFT_ETHER = 0x6 - IFT_FAITH = 0x38 + IFT_FAITH = 0xf3 + IFT_FAST = 0x7d + IFT_FASTETHER = 0x3e + IFT_FASTETHERFX = 0x45 IFT_FDDI = 0xf + IFT_FIBRECHANNEL = 0x38 + IFT_FRAMERELAYINTERCONNECT = 0x3a + IFT_FRAMERELAYMPI = 0x5c + IFT_FRDLCIENDPT = 0xc1 IFT_FRELAY = 0x20 IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 + IFT_FRF16MFRBUNDLE = 0xa3 + IFT_FRFORWARD = 0x9e + IFT_G703AT2MB = 0x43 + IFT_G703AT64K = 0x42 + IFT_GIF = 0xf0 + IFT_GIGABITETHERNET = 0x75 + IFT_GR303IDT = 0xb2 + IFT_GR303RDT = 0xb1 + IFT_H323GATEKEEPER = 0xa4 + IFT_H323PROXY = 0xa5 IFT_HDH1822 = 0x3 + IFT_HDLC = 0x76 + IFT_HDSL2 = 0xa8 + IFT_HIPERLAN2 = 0xb7 IFT_HIPPI = 0x2f + IFT_HIPPIINTERFACE = 0x39 + IFT_HOSTPAD = 0x5a IFT_HSSI = 0x2e IFT_HY = 0xe + IFT_IBM370PARCHAN = 0x48 + IFT_IDSL = 0x9a IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 + IFT_IEEE80211 = 0x47 + IFT_IEEE80212 = 0x37 + IFT_IEEE8023ADLAG = 0xa1 + IFT_IFGSN = 0x91 + IFT_IMT = 0xbe + IFT_INFINIBAND = 0xc7 + IFT_INTERLEAVE = 0x7c + IFT_IP = 0x7e + IFT_IPFORWARD = 0x8e + IFT_IPOVERATM = 0x72 + IFT_IPOVERCDLC = 0x6d + IFT_IPOVERCLAW = 0x6e + IFT_IPSWITCH = 0x4e + IFT_ISDN = 0x3f IFT_ISDNBASIC = 0x14 IFT_ISDNPRIMARY = 0x15 + IFT_ISDNS = 0x4b + IFT_ISDNU = 0x4c IFT_ISO88022LLC = 0x29 IFT_ISO88023 = 0x7 IFT_ISO88024 = 0x8 IFT_ISO88025 = 0x9 + IFT_ISO88025CRFPINT = 0x62 + IFT_ISO88025DTR = 0x56 + IFT_ISO88025FIBER = 0x73 IFT_ISO88026 = 0xa + IFT_ISUP = 0xb3 IFT_L2VLAN = 0x87 + IFT_L3IPVLAN = 0x88 + IFT_L3IPXVLAN = 0x89 IFT_LAPB = 0x10 + IFT_LAPD = 0x4d + IFT_LAPF = 0x77 + IFT_LINEGROUP = 0xd2 IFT_LOCALTALK = 0x2a IFT_LOOP = 0x18 + IFT_MBIM = 0xfa + IFT_MEDIAMAILOVERIP = 0x8b + IFT_MFSIGLINK = 0xa7 IFT_MIOX25 = 0x26 IFT_MODEM = 0x30 + IFT_MPC = 0x71 + IFT_MPLS = 0xa6 + IFT_MPLSTUNNEL = 0x96 + IFT_MSDSL = 0x8f + IFT_MVL = 0xbf + IFT_MYRINET = 0x63 + IFT_NFAS = 0xaf IFT_NSIP = 0x1b + IFT_OPTICALCHANNEL = 0xc3 + IFT_OPTICALTRANSPORT = 0xc4 IFT_OTHER = 0x1 IFT_P10 = 0xc IFT_P80 = 0xd IFT_PARA = 0x22 - IFT_PDP = 0xff IFT_PFLOG = 0xf5 + IFT_PFLOW = 0xf9 IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe + IFT_PLC = 0xae + IFT_PON155 = 0xcf + IFT_PON622 = 0xd0 + IFT_POS = 0xab IFT_PPP = 0x17 + IFT_PPPMULTILINKBUNDLE = 0x6c + IFT_PROPATM = 0xc5 + IFT_PROPBWAP2MP = 0xb8 + IFT_PROPCNLS = 0x59 + IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 + IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 + IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 IFT_PROPMUX = 0x36 IFT_PROPVIRTUAL = 0x35 + IFT_PROPWIRELESSP2P = 0x9d IFT_PTPSERIAL = 0x16 + IFT_PVC = 0xf2 + IFT_Q2931 = 0xc9 + IFT_QLLC = 0x44 + IFT_RADIOMAC = 0xbc + IFT_RADSL = 0x5f + IFT_REACHDSL = 0xc0 + IFT_RFC1483 = 0x9f IFT_RS232 = 0x21 + IFT_RSRB = 0x4f IFT_SDLC = 0x11 + IFT_SDSL = 0x60 + IFT_SHDSL = 0xa9 IFT_SIP = 0x1f + IFT_SIPSIG = 0xcc + IFT_SIPTG = 0xcb IFT_SLIP = 0x1c IFT_SMDSDXI = 0x2b IFT_SMDSICIP = 0x34 IFT_SONET = 0x27 + IFT_SONETOVERHEADCHANNEL = 0xb9 IFT_SONETPATH = 0x32 IFT_SONETVT = 0x33 + IFT_SRP = 0x97 + IFT_SS7SIGLINK = 0x9c + IFT_STACKTOSTACK = 0x6f IFT_STARLAN = 0xb - IFT_STF = 0x39 IFT_T1 = 0x12 + IFT_TDLC = 0x74 + IFT_TELINK = 0xc8 + IFT_TERMPAD = 0x5b + IFT_TR008 = 0xb0 + IFT_TRANSPHDLC = 0x7b + IFT_TUNNEL = 0x83 IFT_ULTRA = 0x1d + IFT_USB = 0xa0 + IFT_V11 = 0x40 IFT_V35 = 0x2d + IFT_V36 = 0x41 + IFT_V37 = 0x78 + IFT_VDSL = 0x61 + IFT_VIRTUALIPADDRESS = 0x70 + IFT_VIRTUALTG = 0xca + IFT_VOICEDID = 0xd5 + IFT_VOICEEM = 0x64 + IFT_VOICEEMFGD = 0xd3 + IFT_VOICEENCAP = 0x67 + IFT_VOICEFGDEANA = 0xd4 + IFT_VOICEFXO = 0x65 + IFT_VOICEFXS = 0x66 + IFT_VOICEOVERATM = 0x98 + IFT_VOICEOVERCABLE = 0xc6 + IFT_VOICEOVERFRAMERELAY = 0x99 + IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb + IFT_X213 = 0x5d IFT_X25 = 0x5 IFT_X25DDN = 0x4 + IFT_X25HUNTGROUP = 0x7a + IFT_X25MLP = 0x79 IFT_X25PLE = 0x28 IFT_XETHER = 0x1a IGNBRK = 0x1 @@ -645,239 +834,159 @@ const ( IN_CLASSD_HOST = 0xfffffff IN_CLASSD_NET = 0xf0000000 IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 + IN_RFC3021_HOST = 0x1 + IN_RFC3021_NET = 0xfffffffe + IN_RFC3021_NSHIFT = 0x1f IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe + IPPROTO_CARP = 0x70 + IPPROTO_DIVERT = 0x102 IPPROTO_DONE = 0x101 IPPROTO_DSTOPTS = 0x3c IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe IPPROTO_ENCAP = 0x62 IPPROTO_EON = 0x50 IPPROTO_ESP = 0x32 IPPROTO_ETHERIP = 0x61 IPPROTO_FRAGMENT = 0x2c IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 IPPROTO_HOPOPTS = 0x0 IPPROTO_ICMP = 0x1 IPPROTO_ICMPV6 = 0x3a IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 IPPROTO_IP = 0x0 IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 IPPROTO_IPV4 = 0x4 IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 + IPPROTO_MAXID = 0x103 + IPPROTO_MOBILE = 0x37 + IPPROTO_MPLS = 0x89 IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 + IPPROTO_PFSYNC = 0xf0 IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d + IPPROTO_UDPLITE = 0x88 + IPV6_AUTH_LEVEL = 0x35 + IPV6_AUTOFLOWLABEL = 0x3b IPV6_CHECKSUM = 0x1a IPV6_DEFAULT_MULTICAST_HOPS = 0x1 IPV6_DEFAULT_MULTICAST_LOOP = 0x1 IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_ESP_NETWORK_LEVEL = 0x37 + IPV6_ESP_TRANS_LEVEL = 0x36 IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x300 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff + IPV6_FRAGTTL = 0x78 IPV6_HLIMDEC = 0x1 - IPV6_IPSEC_POLICY = 0x1c + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPCOMP_LEVEL = 0x3c IPV6_JOIN_GROUP = 0xc IPV6_LEAVE_GROUP = 0xd IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MINHOPCOUNT = 0x41 IPV6_MMTU = 0x500 IPV6_MULTICAST_HOPS = 0xa IPV6_MULTICAST_IF = 0x9 IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_OPTIONS = 0x1 + IPV6_PATHMTU = 0x2c + IPV6_PIPEX = 0x3f + IPV6_PKTINFO = 0x2e IPV6_PORTRANGE = 0xe IPV6_PORTRANGE_DEFAULT = 0x0 IPV6_PORTRANGE_HIGH = 0x1 IPV6_PORTRANGE_LOW = 0x2 - IPV6_RECVTCLASS = 0x23 + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVDSTPORT = 0x40 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x24 + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x39 + IPV6_RTABLE = 0x1021 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x23 IPV6_RTHDR_LOOSE = 0x0 IPV6_RTHDR_STRICT = 0x1 IPV6_RTHDR_TYPE_0 = 0x0 IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 + IPV6_TCLASS = 0x3d IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a IPV6_V6ONLY = 0x1b IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 + IP_AUTH_LEVEL = 0x14 IP_DEFAULT_MULTICAST_LOOP = 0x1 IP_DEFAULT_MULTICAST_TTL = 0x1 IP_DF = 0x4000 IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b + IP_ESP_NETWORK_LEVEL = 0x16 + IP_ESP_TRANS_LEVEL = 0x15 IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 + IP_IPCOMP_LEVEL = 0x1d + IP_IPDEFTTL = 0x25 + IP_IPSECFLOWINFO = 0x24 + IP_IPSEC_LOCAL_AUTH = 0x1b + IP_IPSEC_LOCAL_CRED = 0x19 + IP_IPSEC_LOCAL_ID = 0x17 + IP_IPSEC_REMOTE_AUTH = 0x1c + IP_IPSEC_REMOTE_CRED = 0x1a + IP_IPSEC_REMOTE_ID = 0x18 IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a + IP_MINTTL = 0x20 + IP_MIN_MEMBERSHIPS = 0xf IP_MSS = 0x240 IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 IP_MULTICAST_LOOP = 0xb IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a + IP_PIPEX = 0x22 IP_PORTRANGE = 0x13 IP_PORTRANGE_DEFAULT = 0x0 IP_PORTRANGE_HIGH = 0x1 IP_PORTRANGE_LOW = 0x2 IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 + IP_RECVDSTPORT = 0x21 + IP_RECVIF = 0x1e IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 + IP_RECVRTABLE = 0x23 + IP_RECVTTL = 0x1f IP_RETOPTS = 0x8 IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 + IP_RTABLE = 0x1021 + IP_SENDSRCADDR = 0x7 IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 ISIG = 0x80 ISTRIP = 0x20 - IUTF8 = 0x4000 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 + IUCLC = 0x1000 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -885,188 +994,156 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LCNT_OVERLOAD_FLUSH = 0x6 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 + MADV_FREE = 0x6 MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa MADV_RANDOM = 0x1 MADV_SEQUENTIAL = 0x2 + MADV_SPACEAVAIL = 0x5 MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 MAP_ANON = 0x1000 MAP_ANONYMOUS = 0x1000 + MAP_CONCEAL = 0x8000 MAP_COPY = 0x2 MAP_FILE = 0x0 MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 + MAP_FLAGMASK = 0xfff7 + MAP_HASSEMAPHORE = 0x0 + MAP_INHERIT = 0x0 + MAP_INHERIT_COPY = 0x1 + MAP_INHERIT_NONE = 0x2 + MAP_INHERIT_SHARE = 0x0 + MAP_INHERIT_ZERO = 0x3 + MAP_NOEXTEND = 0x0 + MAP_NORESERVE = 0x0 MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 + MAP_RENAME = 0x0 MAP_SHARED = 0x1 + MAP_STACK = 0x4000 + MAP_TRYFIXED = 0x0 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 + MNT_DEFEXPORTED = 0x200 + MNT_DELEXPORT = 0x20000 + MNT_DOOMED = 0x8000000 + MNT_EXPORTANON = 0x400 MNT_EXPORTED = 0x100 + MNT_EXRDONLY = 0x80 MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 + MNT_LAZY = 0x3 MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 + MNT_NOATIME = 0x8000 MNT_NODEV = 0x10 MNT_NOEXEC = 0x4 + MNT_NOPERM = 0x20 MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 MNT_QUOTA = 0x2000 MNT_RDONLY = 0x1 MNT_RELOAD = 0x40000 MNT_ROOTFS = 0x4000 + MNT_SOFTDEP = 0x4000000 + MNT_STALLED = 0x100000 + MNT_SWAPPABLE = 0x200000 MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0x17f0f5ff + MNT_VISFLAGMASK = 0x400ffff MNT_WAIT = 0x1 + MNT_WANTRDWR = 0x2000000 + MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" + MSG_BCAST = 0x100 + MSG_CMSG_CLOEXEC = 0x800 MSG_CTRUNC = 0x20 MSG_DONTROUTE = 0x4 MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 + MSG_MCAST = 0x200 + MSG_NOSIGNAL = 0x400 MSG_OOB = 0x1 MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 MSG_TRUNC = 0x10 MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 + MSG_WAITFORONE = 0x1000 MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 + MS_INVALIDATE = 0x4 + MS_SYNC = 0x2 NAME_MAX = 0xff NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xa - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 + NET_RT_IFNAMES = 0x6 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 + NET_RT_STATS = 0x4 + NET_RT_TABLE = 0x5 NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 + NOTE_CHANGE = 0x1 NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 NOTE_DELETE = 0x1 + NOTE_EOF = 0x2 NOTE_EXEC = 0x20000000 NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 NOTE_LINK = 0x10 NOTE_LOWAT = 0x1 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 + NOTE_OOB = 0x4 + NOTE_PCTRLMASK = 0xf0000000 NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 NOTE_RENAME = 0x20 NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 NOTE_TRACK = 0x1 NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_TRUNCATE = 0x80 NOTE_WRITE = 0x2 OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 + OLCUC = 0x20 ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 + ONLRET = 0x80 + ONOCR = 0x40 ONOEOT = 0x8 OPOST = 0x1 OXTABS = 0x4 O_ACCMODE = 0x3 - O_ALERT = 0x20000000 O_APPEND = 0x8 O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 + O_CLOEXEC = 0x10000 O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 + O_DIRECTORY = 0x20000 + O_DSYNC = 0x80 O_EXCL = 0x800 O_EXLOCK = 0x20 O_FSYNC = 0x80 O_NDELAY = 0x4 - O_NOCTTY = 0x20000 + O_NOCTTY = 0x8000 O_NOFOLLOW = 0x100 O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 O_RDONLY = 0x0 O_RDWR = 0x2 + O_RSYNC = 0x80 O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 O_SYNC = 0x80 O_TRUNC = 0x400 O_WRONLY = 0x1 @@ -1074,6 +1151,7 @@ const ( PARMRK = 0x8 PARODD = 0x2000 PENDIN = 0x20000000 + PF_FLUSH = 0x1 PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 @@ -1081,28 +1159,8 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 RLIMIT_MEMLOCK = 0x6 @@ -1112,70 +1170,83 @@ const ( RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 + RTAX_BFD = 0xb RTAX_BRD = 0x7 + RTAX_DNS = 0xc RTAX_DST = 0x0 RTAX_GATEWAY = 0x1 RTAX_GENMASK = 0x3 RTAX_IFA = 0x5 RTAX_IFP = 0x4 - RTAX_MAX = 0x8 + RTAX_LABEL = 0xa + RTAX_MAX = 0xf RTAX_NETMASK = 0x2 + RTAX_SEARCH = 0xe + RTAX_SRC = 0x8 + RTAX_SRCMASK = 0x9 + RTAX_STATIC = 0xd RTA_AUTHOR = 0x40 + RTA_BFD = 0x800 RTA_BRD = 0x80 + RTA_DNS = 0x1000 RTA_DST = 0x1 RTA_GATEWAY = 0x2 RTA_GENMASK = 0x8 RTA_IFA = 0x20 RTA_IFP = 0x10 + RTA_LABEL = 0x400 RTA_NETMASK = 0x4 + RTA_SEARCH = 0x4000 + RTA_SRC = 0x100 + RTA_SRCMASK = 0x200 + RTA_STATIC = 0x2000 + RTF_ANNOUNCE = 0x4000 + RTF_BFD = 0x1000000 RTF_BLACKHOLE = 0x1000 RTF_BROADCAST = 0x400000 + RTF_CACHED = 0x20000 + RTF_CLONED = 0x10000 RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DELCLONE = 0x80 + RTF_CONNECTED = 0x800000 RTF_DONE = 0x40 RTF_DYNAMIC = 0x10 + RTF_FMASK = 0x110fc08 RTF_GATEWAY = 0x2 RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 RTF_LLINFO = 0x400 RTF_LOCAL = 0x200000 RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 + RTF_MPATH = 0x40000 + RTF_MPLS = 0x100000 + RTF_MULTICAST = 0x200 + RTF_PERMANENT_ARP = 0x2000 RTF_PROTO1 = 0x8000 RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 + RTF_PROTO3 = 0x2000 RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 RTF_STATIC = 0x800 RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 + RTF_USETRAILERS = 0x8000 + RTM_80211INFO = 0x15 RTM_ADD = 0x1 + RTM_BFD = 0x12 RTM_CHANGE = 0x3 + RTM_CHGADDRATTR = 0x14 RTM_DELADDR = 0xd RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 + RTM_DESYNC = 0x10 RTM_GET = 0x4 - RTM_GET2 = 0x14 + RTM_IFANNOUNCE = 0xf RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 + RTM_INVALIDATE = 0x11 RTM_LOSING = 0x5 + RTM_MAXSIZE = 0x800 RTM_MISS = 0x7 RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa + RTM_PROPOSAL = 0x13 RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 + RTM_SOURCE = 0x16 RTM_VERSION = 0x5 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 @@ -1185,83 +1256,167 @@ const ( RTV_RTTVAR = 0x80 RTV_SPIPE = 0x10 RTV_SSTHRESH = 0x20 + RT_TABLEID_BITS = 0x8 + RT_TABLEID_MASK = 0xff + RT_TABLEID_MAX = 0xff RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 + RUSAGE_THREAD = 0x1 SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 + SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 SIOCADDMULTI = 0x80206931 SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 + SIOCAIFGROUP = 0x80286987 SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 + SIOCBRDGADD = 0x8060693c + SIOCBRDGADDL = 0x80606949 + SIOCBRDGADDS = 0x80606941 + SIOCBRDGARL = 0x808c694d + SIOCBRDGDADDR = 0x81286947 + SIOCBRDGDEL = 0x8060693d + SIOCBRDGDELS = 0x80606942 + SIOCBRDGFLUSH = 0x80606948 + SIOCBRDGFRL = 0x808c694e + SIOCBRDGGCACHE = 0xc0146941 + SIOCBRDGGFD = 0xc0146952 + SIOCBRDGGHT = 0xc0146951 + SIOCBRDGGIFFLGS = 0xc060693e + SIOCBRDGGMA = 0xc0146953 + SIOCBRDGGPARAM = 0xc0406958 + SIOCBRDGGPRI = 0xc0146950 + SIOCBRDGGRL = 0xc030694f + SIOCBRDGGTO = 0xc0146946 + SIOCBRDGIFS = 0xc0606942 + SIOCBRDGRTS = 0xc0206943 + SIOCBRDGSADDR = 0xc1286944 + SIOCBRDGSCACHE = 0x80146940 + SIOCBRDGSFD = 0x80146952 + SIOCBRDGSHT = 0x80146951 + SIOCBRDGSIFCOST = 0x80606955 + SIOCBRDGSIFFLGS = 0x8060693f + SIOCBRDGSIFPRIO = 0x80606954 + SIOCBRDGSIFPROT = 0x8060694a + SIOCBRDGSMA = 0x80146953 + SIOCBRDGSPRI = 0x80146950 + SIOCBRDGSPROTO = 0x8014695a + SIOCBRDGSTO = 0x80146945 + SIOCBRDGSTXHC = 0x80146959 + SIOCDELLABEL = 0x80206997 SIOCDELMULTI = 0x80206932 SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 + SIOCDIFGROUP = 0x80286989 + SIOCDIFPARENT = 0x802069b4 + SIOCDIFPHYADDR = 0x80206949 + SIOCDPWE3NEIGHBOR = 0x802069de + SIOCDVNETID = 0x802069af + SIOCGETKALIVE = 0xc01869a4 + SIOCGETLABEL = 0x8020699a + SIOCGETMPWCFG = 0xc02069ae + SIOCGETPFLOW = 0xc02069fe + SIOCGETPFSYNC = 0xc02069f8 + SIOCGETSGCNT = 0xc0207534 + SIOCGETVIFCNT = 0xc0287533 + SIOCGETVLAN = 0xc0206990 SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFCONF = 0xc0106924 + SIOCGIFDATA = 0xc020691b + SIOCGIFDESCR = 0xc0206981 SIOCGIFDSTADDR = 0xc0206922 SIOCGIFFLAGS = 0xc0206911 + SIOCGIFGATTR = 0xc028698b SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFGLIST = 0xc028698d + SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 + SIOCGIFHARDMTU = 0xc02069a5 + SIOCGIFLLPRIO = 0xc02069b6 + SIOCGIFMEDIA = 0xc0406938 SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 + SIOCGIFMTU = 0xc020697e SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGLOWAT = 0x40047303 + SIOCGIFPAIR = 0xc02069b1 + SIOCGIFPARENT = 0xc02069b3 + SIOCGIFPRIORITY = 0xc020699c + SIOCGIFRDOMAIN = 0xc02069a0 + SIOCGIFRTLABEL = 0xc0206983 + SIOCGIFRXR = 0x802069aa + SIOCGIFSFFPAGE = 0xc1126939 + SIOCGIFXFLAGS = 0xc020699e + SIOCGLIFPHYADDR = 0xc218694b + SIOCGLIFPHYDF = 0xc02069c2 + SIOCGLIFPHYECN = 0xc02069c8 + SIOCGLIFPHYRTABLE = 0xc02069a2 + SIOCGLIFPHYTTL = 0xc02069a9 SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a + SIOCGPWE3 = 0xc0206998 + SIOCGPWE3CTRLWORD = 0xc02069dc + SIOCGPWE3FAT = 0xc02069dd + SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db + SIOCGSPPPPARAMS = 0xc0206994 + SIOCGTXHPRIO = 0xc02069c6 + SIOCGUMBINFO = 0xc02069be + SIOCGUMBPARAM = 0xc02069c0 + SIOCGVH = 0xc02069f6 + SIOCGVNETFLOWID = 0xc02069c4 + SIOCGVNETID = 0xc02069a7 + SIOCIFAFATTACH = 0x801169ab + SIOCIFAFDETACH = 0x801169ac + SIOCIFCREATE = 0x8020697a SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 + SIOCIFGCLONERS = 0xc0106978 + SIOCSETKALIVE = 0x801869a3 + SIOCSETLABEL = 0x80206999 + SIOCSETMPWCFG = 0x802069ad + SIOCSETPFLOW = 0x802069fd + SIOCSETPFSYNC = 0x802069f7 + SIOCSETVLAN = 0x8020698f SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a + SIOCSIFDESCR = 0x80206980 SIOCSIFDSTADDR = 0x8020690e SIOCSIFFLAGS = 0x80206910 + SIOCSIFGATTR = 0x8028698c SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 + SIOCSIFLLADDR = 0x8020691f + SIOCSIFLLPRIO = 0x802069b5 SIOCSIFMEDIA = 0xc0206937 SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 + SIOCSIFMTU = 0x8020697f SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 + SIOCSIFPAIR = 0x802069b0 + SIOCSIFPARENT = 0x802069b2 + SIOCSIFPRIORITY = 0x8020699b + SIOCSIFRDOMAIN = 0x8020699f + SIOCSIFRTLABEL = 0x80206982 + SIOCSIFXFLAGS = 0x8020699d + SIOCSLIFPHYADDR = 0x8218694a + SIOCSLIFPHYDF = 0x802069c1 + SIOCSLIFPHYECN = 0x802069c7 + SIOCSLIFPHYRTABLE = 0x802069a1 + SIOCSLIFPHYTTL = 0x802069a8 SIOCSPGRP = 0x80047308 + SIOCSPWE3CTRLWORD = 0x802069dc + SIOCSPWE3FAT = 0x802069dd + SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db + SIOCSSPPPPARAMS = 0x80206993 + SIOCSTXHPRIO = 0x802069c5 + SIOCSUMBPARAM = 0x802069bf + SIOCSVH = 0xc02069f5 + SIOCSVNETFLOWID = 0x802069c3 + SIOCSVNETID = 0x802069a6 + SOCK_CLOEXEC = 0x8000 SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff + SOCK_DNS = 0x1000 + SOCK_NONBLOCK = 0x4000 SOCK_RAW = 0x3 SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 @@ -1269,44 +1424,33 @@ const ( SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 + SO_BINDANY = 0x1000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 + SO_NETPROC = 0x1020 SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 + SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 + SO_RTABLE = 0x1021 SO_SNDBUF = 0x1001 SO_SNDLOWAT = 0x1003 SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 + SO_SPLICE = 0x1023 + SO_TIMESTAMP = 0x800 SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 + SO_ZEROIZE = 0x2000 + S_BLKSIZE = 0x200 S_IEXEC = 0x40 S_IFBLK = 0x6000 S_IFCHR = 0x2000 @@ -1316,7 +1460,6 @@ const ( S_IFMT = 0xf000 S_IFREG = 0x8000 S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 S_IREAD = 0x100 S_IRGRP = 0x20 S_IROTH = 0x4 @@ -1335,11 +1478,6 @@ const ( S_IXGRP = 0x8 S_IXOTH = 0x1 S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 TCIFLUSH = 0x1 TCIOFF = 0x3 TCIOFLUSH = 0x3 @@ -1347,52 +1485,57 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 TCP_MAXSEG = 0x2 TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 + TCP_MAX_SACK = 0x3 TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 + TCP_MD5SIG = 0x4 TCP_MSS = 0x200 TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 + TCP_NOPUSH = 0x10 + TCP_SACKHOLE_LIMIT = 0x80 + TCP_SACK_ENABLE = 0x8 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 + TIOCCHKVERAUTH = 0x2000741e + TIOCCLRVERAUTH = 0x2000741d TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 TIOCEXCL = 0x2000740d TIOCEXT = 0x80047460 + TIOCFLAG_CLOCAL = 0x2 + TIOCFLAG_CRTSCTS = 0x4 + TIOCFLAG_MDMBUF = 0x8 + TIOCFLAG_PPS = 0x10 + TIOCFLAG_SOFTCAR = 0x1 TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 + TIOCGETA = 0x402c7413 TIOCGETD = 0x4004741a + TIOCGFLAGS = 0x4004745d TIOCGPGRP = 0x40047477 + TIOCGSID = 0x40047463 + TIOCGTSTAMP = 0x4010745b TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 TIOCMBIC = 0x8004746b TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b + TIOCMODG = 0x4004746a + TIOCMODS = 0x8004746d TIOCMSET = 0x8004746d TIOCM_CAR = 0x40 TIOCM_CD = 0x40 @@ -1417,29 +1560,29 @@ const ( TIOCPKT_NOSTOP = 0x10 TIOCPKT_START = 0x8 TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 TIOCREMOTE = 0x80047469 TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 + TIOCSETA = 0x802c7414 + TIOCSETAF = 0x802c7416 + TIOCSETAW = 0x802c7415 TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f + TIOCSETVERAUTH = 0x8004741c + TIOCSFLAGS = 0x8004745c + TIOCSIG = 0x8004745f TIOCSPGRP = 0x80047476 TIOCSTART = 0x2000746e TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 TIOCSTOP = 0x2000746f + TIOCSTSTAMP = 0x8008745a TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 TIOCUCNTL = 0x80047466 + TIOCUCNTL_CBRK = 0x7a + TIOCUCNTL_SBRK = 0x7b TOSTOP = 0x400000 + UTIME_NOW = -0x2 + UTIME_OMIT = -0x1 VDISCARD = 0xf VDSUSP = 0xb VEOF = 0x0 @@ -1450,36 +1593,33 @@ const ( VKILL = 0x5 VLNEXT = 0xe VMIN = 0x10 + VM_ANONMIN = 0x7 VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 + VM_MALLOC_CONF = 0xc + VM_MAXID = 0xd + VM_MAXSLP = 0xa VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 + VM_NKMEMPAGES = 0x6 + VM_PSSTRINGS = 0x3 + VM_SWAPENCRYPT = 0x5 + VM_USPACE = 0xb + VM_UVMEXP = 0x4 + VM_VNODEMIN = 0x9 + VM_VTEXTMIN = 0x8 VQUIT = 0x9 VREPRINT = 0x6 VSTART = 0xc VSTATUS = 0x12 VSTOP = 0xd VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 VTIME = 0x11 VWERASE = 0x4 - WCONTINUED = 0x10 + WALTSIG = 0x4 + WCONTINUED = 0x8 WCOREFLAG = 0x80 - WEXITED = 0x4 WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + XCASE = 0x1000000 ) // Errors @@ -1492,21 +1632,17 @@ const ( EAGAIN = syscall.Errno(0x23) EALREADY = syscall.Errno(0x25) EAUTH = syscall.Errno(0x50) - EBADARCH = syscall.Errno(0x56) - EBADEXEC = syscall.Errno(0x55) EBADF = syscall.Errno(0x9) - EBADMACHO = syscall.Errno(0x58) - EBADMSG = syscall.Errno(0x5e) + EBADMSG = syscall.Errno(0x5c) EBADRPC = syscall.Errno(0x48) EBUSY = syscall.Errno(0x10) - ECANCELED = syscall.Errno(0x59) + ECANCELED = syscall.Errno(0x58) ECHILD = syscall.Errno(0xa) ECONNABORTED = syscall.Errno(0x35) ECONNREFUSED = syscall.Errno(0x3d) ECONNRESET = syscall.Errno(0x36) EDEADLK = syscall.Errno(0xb) EDESTADDRREQ = syscall.Errno(0x27) - EDEVERR = syscall.Errno(0x53) EDOM = syscall.Errno(0x21) EDQUOT = syscall.Errno(0x45) EEXIST = syscall.Errno(0x11) @@ -1515,54 +1651,51 @@ const ( EFTYPE = syscall.Errno(0x4f) EHOSTDOWN = syscall.Errno(0x40) EHOSTUNREACH = syscall.Errno(0x41) - EIDRM = syscall.Errno(0x5a) - EILSEQ = syscall.Errno(0x5c) + EIDRM = syscall.Errno(0x59) + EILSEQ = syscall.Errno(0x54) EINPROGRESS = syscall.Errno(0x24) EINTR = syscall.Errno(0x4) EINVAL = syscall.Errno(0x16) EIO = syscall.Errno(0x5) + EIPSEC = syscall.Errno(0x52) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x6a) + ELAST = syscall.Errno(0x5f) ELOOP = syscall.Errno(0x3e) + EMEDIUMTYPE = syscall.Errno(0x56) EMFILE = syscall.Errno(0x18) EMLINK = syscall.Errno(0x1f) EMSGSIZE = syscall.Errno(0x28) - EMULTIHOP = syscall.Errno(0x5f) ENAMETOOLONG = syscall.Errno(0x3f) ENEEDAUTH = syscall.Errno(0x51) ENETDOWN = syscall.Errno(0x32) ENETRESET = syscall.Errno(0x34) ENETUNREACH = syscall.Errno(0x33) ENFILE = syscall.Errno(0x17) - ENOATTR = syscall.Errno(0x5d) + ENOATTR = syscall.Errno(0x53) ENOBUFS = syscall.Errno(0x37) - ENODATA = syscall.Errno(0x60) ENODEV = syscall.Errno(0x13) ENOENT = syscall.Errno(0x2) ENOEXEC = syscall.Errno(0x8) ENOLCK = syscall.Errno(0x4d) - ENOLINK = syscall.Errno(0x61) + ENOMEDIUM = syscall.Errno(0x55) ENOMEM = syscall.Errno(0xc) - ENOMSG = syscall.Errno(0x5b) - ENOPOLICY = syscall.Errno(0x67) + ENOMSG = syscall.Errno(0x5a) ENOPROTOOPT = syscall.Errno(0x2a) ENOSPC = syscall.Errno(0x1c) - ENOSR = syscall.Errno(0x62) - ENOSTR = syscall.Errno(0x63) ENOSYS = syscall.Errno(0x4e) ENOTBLK = syscall.Errno(0xf) ENOTCONN = syscall.Errno(0x39) ENOTDIR = syscall.Errno(0x14) ENOTEMPTY = syscall.Errno(0x42) - ENOTRECOVERABLE = syscall.Errno(0x68) + ENOTRECOVERABLE = syscall.Errno(0x5d) ENOTSOCK = syscall.Errno(0x26) - ENOTSUP = syscall.Errno(0x2d) + ENOTSUP = syscall.Errno(0x5b) ENOTTY = syscall.Errno(0x19) ENXIO = syscall.Errno(0x6) - EOPNOTSUPP = syscall.Errno(0x66) - EOVERFLOW = syscall.Errno(0x54) - EOWNERDEAD = syscall.Errno(0x69) + EOPNOTSUPP = syscall.Errno(0x2d) + EOVERFLOW = syscall.Errno(0x57) + EOWNERDEAD = syscall.Errno(0x5e) EPERM = syscall.Errno(0x1) EPFNOSUPPORT = syscall.Errno(0x2e) EPIPE = syscall.Errno(0x20) @@ -1570,22 +1703,18 @@ const ( EPROCUNAVAIL = syscall.Errno(0x4c) EPROGMISMATCH = syscall.Errno(0x4b) EPROGUNAVAIL = syscall.Errno(0x4a) - EPROTO = syscall.Errno(0x64) + EPROTO = syscall.Errno(0x5f) EPROTONOSUPPORT = syscall.Errno(0x2b) EPROTOTYPE = syscall.Errno(0x29) - EPWROFF = syscall.Errno(0x52) - EQFULL = syscall.Errno(0x6a) ERANGE = syscall.Errno(0x22) EREMOTE = syscall.Errno(0x47) EROFS = syscall.Errno(0x1e) ERPCMISMATCH = syscall.Errno(0x49) - ESHLIBVERS = syscall.Errno(0x57) ESHUTDOWN = syscall.Errno(0x3a) ESOCKTNOSUPPORT = syscall.Errno(0x2c) ESPIPE = syscall.Errno(0x1d) ESRCH = syscall.Errno(0x3) ESTALE = syscall.Errno(0x46) - ETIME = syscall.Errno(0x65) ETIMEDOUT = syscall.Errno(0x3c) ETOOMANYREFS = syscall.Errno(0x3b) ETXTBSY = syscall.Errno(0x1a) @@ -1617,6 +1746,7 @@ const ( SIGSTOP = syscall.Signal(0x11) SIGSYS = syscall.Signal(0xc) SIGTERM = syscall.Signal(0xf) + SIGTHR = syscall.Signal(0x20) SIGTRAP = syscall.Signal(0x5) SIGTSTP = syscall.Signal(0x12) SIGTTIN = syscall.Signal(0x15) @@ -1651,7 +1781,7 @@ var errorList = [...]struct { {13, "EACCES", "permission denied"}, {14, "EFAULT", "bad address"}, {15, "ENOTBLK", "block device required"}, - {16, "EBUSY", "resource busy"}, + {16, "EBUSY", "device busy"}, {17, "EEXIST", "file exists"}, {18, "EXDEV", "cross-device link"}, {19, "ENODEV", "operation not supported by device"}, @@ -1680,7 +1810,7 @@ var errorList = [...]struct { {42, "ENOPROTOOPT", "protocol not available"}, {43, "EPROTONOSUPPORT", "protocol not supported"}, {44, "ESOCKTNOSUPPORT", "socket type not supported"}, - {45, "ENOTSUP", "operation not supported"}, + {45, "EOPNOTSUPP", "operation not supported"}, {46, "EPFNOSUPPORT", "protocol family not supported"}, {47, "EAFNOSUPPORT", "address family not supported by protocol family"}, {48, "EADDRINUSE", "address already in use"}, @@ -1704,12 +1834,12 @@ var errorList = [...]struct { {66, "ENOTEMPTY", "directory not empty"}, {67, "EPROCLIM", "too many processes"}, {68, "EUSERS", "too many users"}, - {69, "EDQUOT", "disc quota exceeded"}, + {69, "EDQUOT", "disk quota exceeded"}, {70, "ESTALE", "stale NFS file handle"}, {71, "EREMOTE", "too many levels of remote in path"}, {72, "EBADRPC", "RPC struct is bad"}, {73, "ERPCMISMATCH", "RPC version wrong"}, - {74, "EPROGUNAVAIL", "RPC prog. not avail"}, + {74, "EPROGUNAVAIL", "RPC program not available"}, {75, "EPROGMISMATCH", "program version wrong"}, {76, "EPROCUNAVAIL", "bad procedure for program"}, {77, "ENOLCK", "no locks available"}, @@ -1717,31 +1847,20 @@ var errorList = [...]struct { {79, "EFTYPE", "inappropriate file type or format"}, {80, "EAUTH", "authentication error"}, {81, "ENEEDAUTH", "need authenticator"}, - {82, "EPWROFF", "device power is off"}, - {83, "EDEVERR", "device error"}, - {84, "EOVERFLOW", "value too large to be stored in data type"}, - {85, "EBADEXEC", "bad executable (or shared library)"}, - {86, "EBADARCH", "bad CPU type in executable"}, - {87, "ESHLIBVERS", "shared library version mismatch"}, - {88, "EBADMACHO", "malformed Mach-o file"}, - {89, "ECANCELED", "operation canceled"}, - {90, "EIDRM", "identifier removed"}, - {91, "ENOMSG", "no message of desired type"}, - {92, "EILSEQ", "illegal byte sequence"}, - {93, "ENOATTR", "attribute not found"}, - {94, "EBADMSG", "bad message"}, - {95, "EMULTIHOP", "EMULTIHOP (Reserved)"}, - {96, "ENODATA", "no message available on STREAM"}, - {97, "ENOLINK", "ENOLINK (Reserved)"}, - {98, "ENOSR", "no STREAM resources"}, - {99, "ENOSTR", "not a STREAM"}, - {100, "EPROTO", "protocol error"}, - {101, "ETIME", "STREAM ioctl timeout"}, - {102, "EOPNOTSUPP", "operation not supported on socket"}, - {103, "ENOPOLICY", "policy not found"}, - {104, "ENOTRECOVERABLE", "state not recoverable"}, - {105, "EOWNERDEAD", "previous owner died"}, - {106, "EQFULL", "interface output queue is full"}, + {82, "EIPSEC", "IPsec processing failure"}, + {83, "ENOATTR", "attribute not found"}, + {84, "EILSEQ", "illegal byte sequence"}, + {85, "ENOMEDIUM", "no medium found"}, + {86, "EMEDIUMTYPE", "wrong medium type"}, + {87, "EOVERFLOW", "value too large to be stored in data type"}, + {88, "ECANCELED", "operation canceled"}, + {89, "EIDRM", "identifier removed"}, + {90, "ENOMSG", "no message of desired type"}, + {91, "ENOTSUP", "not supported"}, + {92, "EBADMSG", "bad message"}, + {93, "ENOTRECOVERABLE", "state not recoverable"}, + {94, "EOWNERDEAD", "previous owner died"}, + {95, "ELAST", "protocol error"}, } // Signal table @@ -1781,4 +1900,5 @@ var signalList = [...]struct { {29, "SIGINFO", "information request"}, {30, "SIGUSR1", "user defined signal 1"}, {31, "SIGUSR2", "user defined signal 2"}, + {32, "SIGTHR", "thread AST"}, } diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go similarity index 50% rename from vendor/golang.org/x/sys/unix/zerrors_darwin_386.go rename to vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go index 6217cdb..b1b8bb2 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go @@ -1,10 +1,10 @@ -// mkerrors.sh -m32 +// mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,darwin +//go:build riscv64 && openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -m32 _const.go +// cgo -godefs -- -m64 _const.go package unix @@ -12,6 +12,7 @@ import "syscall" const ( AF_APPLETALK = 0x10 + AF_BLUETOOTH = 0x20 AF_CCITT = 0xa AF_CHAOS = 0x5 AF_CNT = 0x15 @@ -19,116 +20,36 @@ const ( AF_DATAKIT = 0x9 AF_DECnet = 0xc AF_DLI = 0xd - AF_E164 = 0x1c + AF_E164 = 0x1a AF_ECMA = 0x8 + AF_ENCAP = 0x1c AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 AF_IMPLINK = 0x3 AF_INET = 0x2 - AF_INET6 = 0x1e + AF_INET6 = 0x18 AF_IPX = 0x17 - AF_ISDN = 0x1c + AF_ISDN = 0x1a AF_ISO = 0x7 + AF_KEY = 0x1e AF_LAT = 0xe AF_LINK = 0x12 AF_LOCAL = 0x1 - AF_MAX = 0x28 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 + AF_MAX = 0x24 + AF_MPLS = 0x21 + AF_NATM = 0x1b AF_NS = 0x6 AF_OSI = 0x7 - AF_PPP = 0x22 AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 AF_ROUTE = 0x11 - AF_SIP = 0x18 + AF_SIP = 0x1d AF_SNA = 0xb - AF_SYSTEM = 0x20 AF_UNIX = 0x1 AF_UNSPEC = 0x0 - AF_UTUN = 0x26 ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x41c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff + ARPHRD_ETHER = 0x1 + ARPHRD_FRELAY = 0xf + ARPHRD_IEEE1394 = 0x18 + ARPHRD_IEEE802 = 0x6 B0 = 0x0 B110 = 0x6e B115200 = 0x1c200 @@ -154,25 +75,28 @@ const ( B9600 = 0x2580 BIOCFLUSH = 0x20004268 BIOCGBLEN = 0x40044266 + BIOCGDIRFILT = 0x4004427c BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 + BIOCGDLTLIST = 0xc010427b BIOCGETIF = 0x4020426b + BIOCGFILDROP = 0x40044278 BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4008426e - BIOCGSEESENT = 0x40044276 + BIOCGRSIG = 0x40044273 + BIOCGRTIMEOUT = 0x4010426e BIOCGSTATS = 0x4008426f BIOCIMMEDIATE = 0x80044270 + BIOCLOCK = 0x20004276 BIOCPROMISC = 0x20004269 BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80084267 - BIOCSETFNR = 0x8008427e + BIOCSDIRFILT = 0x8004427d + BIOCSDLT = 0x8004427a + BIOCSETF = 0x80104267 BIOCSETIF = 0x8020426c + BIOCSETWF = 0x80104277 + BIOCSFILDROP = 0x80044279 BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8008426d - BIOCSSEESENT = 0x80044277 + BIOCSRSIG = 0x80044272 + BIOCSRTIMEOUT = 0x8010426d BIOCVERSION = 0x40044271 BPF_A = 0x10 BPF_ABS = 0x20 @@ -181,7 +105,18 @@ const ( BPF_ALU = 0x4 BPF_AND = 0x50 BPF_B = 0x10 + BPF_DIRECTION_IN = 0x1 + BPF_DIRECTION_OUT = 0x2 BPF_DIV = 0x30 + BPF_FILDROP_CAPTURE = 0x1 + BPF_FILDROP_DROP = 0x2 + BPF_FILDROP_PASS = 0x0 + BPF_F_DIR_IN = 0x10 + BPF_F_DIR_MASK = 0x30 + BPF_F_DIR_OUT = 0x20 + BPF_F_DIR_SHIFT = 0x4 + BPF_F_FLOWID = 0x8 + BPF_F_PRI_MASK = 0x7 BPF_H = 0x8 BPF_IMM = 0x0 BPF_IND = 0x40 @@ -197,7 +132,7 @@ const ( BPF_LEN = 0x80 BPF_LSH = 0x60 BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 + BPF_MAXBUFSIZE = 0x200000 BPF_MAXINSNS = 0x200 BPF_MEM = 0x60 BPF_MEMWORDS = 0x10 @@ -210,6 +145,7 @@ const ( BPF_OR = 0x40 BPF_RELEASE = 0x30bb6 BPF_RET = 0x6 + BPF_RND = 0xc0 BPF_RSH = 0x70 BPF_ST = 0x2 BPF_STX = 0x3 @@ -219,33 +155,30 @@ const ( BPF_W = 0x0 BPF_X = 0x8 BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 CFLUSH = 0xf CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_BOOTTIME = 0x6 + CLOCK_MONOTONIC = 0x3 + CLOCK_PROCESS_CPUTIME_ID = 0x2 CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 + CLOCK_THREAD_CPUTIME_ID = 0x4 + CLOCK_UPTIME = 0x5 + CPUSTATES = 0x6 + CP_IDLE = 0x5 + CP_INTR = 0x4 + CP_NICE = 0x1 + CP_SPIN = 0x3 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 - CRTSCTS = 0x30000 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 CS8 = 0x300 CSIZE = 0x300 CSTART = 0x11 - CSTATUS = 0x14 + CSTATUS = 0xff CSTOP = 0x13 CSTOPB = 0x400 CSUSP = 0x1a @@ -253,149 +186,92 @@ const ( CTL_KERN = 0x1 CTL_MAXNAME = 0xc CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DIOCADDQUEUE = 0xc110445d + DIOCADDRULE = 0xcd604404 + DIOCADDSTATE = 0xc1084425 + DIOCCHANGERULE = 0xcd60441a + DIOCCLRIFFLAG = 0xc028445a + DIOCCLRSRCNODES = 0x20004455 + DIOCCLRSTATES = 0xc0e04412 + DIOCCLRSTATUS = 0xc0284416 + DIOCGETLIMIT = 0xc0084427 + DIOCGETQSTATS = 0xc1204460 + DIOCGETQUEUE = 0xc110445f + DIOCGETQUEUES = 0xc110445e + DIOCGETRULE = 0xcd604407 + DIOCGETRULES = 0xcd604406 + DIOCGETRULESET = 0xc444443b + DIOCGETRULESETS = 0xc444443a + DIOCGETSRCNODES = 0xc0104454 + DIOCGETSTATE = 0xc1084413 + DIOCGETSTATES = 0xc0104419 + DIOCGETSTATUS = 0xc1e84415 + DIOCGETSYNFLWATS = 0xc0084463 + DIOCGETTIMEOUT = 0xc008441e + DIOCIGETIFACES = 0xc0284457 + DIOCKILLSRCNODES = 0xc080445b + DIOCKILLSTATES = 0xc0e04429 + DIOCNATLOOK = 0xc0504417 + DIOCOSFPADD = 0xc088444f + DIOCOSFPFLUSH = 0x2000444e + DIOCOSFPGET = 0xc0884450 + DIOCRADDADDRS = 0xc4504443 + DIOCRADDTABLES = 0xc450443d + DIOCRCLRADDRS = 0xc4504442 + DIOCRCLRASTATS = 0xc4504448 + DIOCRCLRTABLES = 0xc450443c + DIOCRCLRTSTATS = 0xc4504441 + DIOCRDELADDRS = 0xc4504444 + DIOCRDELTABLES = 0xc450443e + DIOCRGETADDRS = 0xc4504446 + DIOCRGETASTATS = 0xc4504447 + DIOCRGETTABLES = 0xc450443f + DIOCRGETTSTATS = 0xc4504440 + DIOCRINADEFINE = 0xc450444d + DIOCRSETADDRS = 0xc4504445 + DIOCRSETTFLAGS = 0xc450444a + DIOCRTSTADDRS = 0xc4504449 + DIOCSETDEBUG = 0xc0044418 + DIOCSETHOSTID = 0xc0044456 + DIOCSETIFFLAG = 0xc0284459 + DIOCSETLIMIT = 0xc0084428 + DIOCSETREASS = 0xc004445c + DIOCSETSTATUSIF = 0xc0284414 + DIOCSETSYNCOOKIES = 0xc0014462 + DIOCSETSYNFLWATS = 0xc0084461 + DIOCSETTIMEOUT = 0xc008441d + DIOCSTART = 0x20004401 + DIOCSTOP = 0x20004402 + DIOCXBEGIN = 0xc0104451 + DIOCXCOMMIT = 0xc0104452 + DIOCXROLLBACK = 0xc0104453 DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 DLT_EN10MB = 0x1 DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_ENC = 0xd DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 DLT_IEEE802 = 0x6 DLT_IEEE802_11 = 0x69 DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0xf5 - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 + DLT_LOOP = 0xc DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d + DLT_OPENFLOW = 0x10b DLT_PFLOG = 0x75 DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 DLT_PPP = 0x9 DLT_PPP_BSDOS = 0x10 DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 + DLT_RAW = 0xe DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USBPCAP = 0xf9 DLT_USER0 = 0x93 DLT_USER1 = 0x94 DLT_USER10 = 0x9d @@ -412,9 +288,6 @@ const ( DLT_USER7 = 0x9a DLT_USER8 = 0x9b DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -423,7 +296,6 @@ const ( DT_REG = 0x8 DT_SOCK = 0xc DT_UNKNOWN = 0x0 - DT_WHT = 0xe ECHO = 0x8 ECHOCTL = 0x40 ECHOE = 0x2 @@ -431,107 +303,265 @@ const ( ECHOKE = 0x1 ECHONL = 0x10 ECHOPRT = 0x20 + EMT_TAGOVF = 0x1 + EMUL_ENABLED = 0x1 + EMUL_NATIVE = 0x2 + ENDRUNDISC = 0x9 + ETH64_8021_RSVD_MASK = 0xfffffffffff0 + ETH64_8021_RSVD_PREFIX = 0x180c2000000 + ETHERMIN = 0x2e + ETHERMTU = 0x5dc + ETHERTYPE_8023 = 0x4 + ETHERTYPE_AARP = 0x80f3 + ETHERTYPE_ACCTON = 0x8390 + ETHERTYPE_AEONIC = 0x8036 + ETHERTYPE_ALPHA = 0x814a + ETHERTYPE_AMBER = 0x6008 + ETHERTYPE_AMOEBA = 0x8145 + ETHERTYPE_AOE = 0x88a2 + ETHERTYPE_APOLLO = 0x80f7 + ETHERTYPE_APOLLODOMAIN = 0x8019 + ETHERTYPE_APPLETALK = 0x809b + ETHERTYPE_APPLITEK = 0x80c7 + ETHERTYPE_ARGONAUT = 0x803a + ETHERTYPE_ARP = 0x806 + ETHERTYPE_AT = 0x809b + ETHERTYPE_ATALK = 0x809b + ETHERTYPE_ATOMIC = 0x86df + ETHERTYPE_ATT = 0x8069 + ETHERTYPE_ATTSTANFORD = 0x8008 + ETHERTYPE_AUTOPHON = 0x806a + ETHERTYPE_AXIS = 0x8856 + ETHERTYPE_BCLOOP = 0x9003 + ETHERTYPE_BOFL = 0x8102 + ETHERTYPE_CABLETRON = 0x7034 + ETHERTYPE_CHAOS = 0x804 + ETHERTYPE_COMDESIGN = 0x806c + ETHERTYPE_COMPUGRAPHIC = 0x806d + ETHERTYPE_COUNTERPOINT = 0x8062 + ETHERTYPE_CRONUS = 0x8004 + ETHERTYPE_CRONUSVLN = 0x8003 + ETHERTYPE_DCA = 0x1234 + ETHERTYPE_DDE = 0x807b + ETHERTYPE_DEBNI = 0xaaaa + ETHERTYPE_DECAM = 0x8048 + ETHERTYPE_DECCUST = 0x6006 + ETHERTYPE_DECDIAG = 0x6005 + ETHERTYPE_DECDNS = 0x803c + ETHERTYPE_DECDTS = 0x803e + ETHERTYPE_DECEXPER = 0x6000 + ETHERTYPE_DECLAST = 0x8041 + ETHERTYPE_DECLTM = 0x803f + ETHERTYPE_DECMUMPS = 0x6009 + ETHERTYPE_DECNETBIOS = 0x8040 + ETHERTYPE_DELTACON = 0x86de + ETHERTYPE_DIDDLE = 0x4321 + ETHERTYPE_DLOG1 = 0x660 + ETHERTYPE_DLOG2 = 0x661 + ETHERTYPE_DN = 0x6003 + ETHERTYPE_DOGFIGHT = 0x1989 + ETHERTYPE_DSMD = 0x8039 + ETHERTYPE_EAPOL = 0x888e + ETHERTYPE_ECMA = 0x803 + ETHERTYPE_ENCRYPT = 0x803d + ETHERTYPE_ES = 0x805d + ETHERTYPE_EXCELAN = 0x8010 + ETHERTYPE_EXPERDATA = 0x8049 + ETHERTYPE_FLIP = 0x8146 + ETHERTYPE_FLOWCONTROL = 0x8808 + ETHERTYPE_FRARP = 0x808 + ETHERTYPE_GENDYN = 0x8068 + ETHERTYPE_HAYES = 0x8130 + ETHERTYPE_HIPPI_FP = 0x8180 + ETHERTYPE_HITACHI = 0x8820 + ETHERTYPE_HP = 0x8005 + ETHERTYPE_IEEEPUP = 0xa00 + ETHERTYPE_IEEEPUPAT = 0xa01 + ETHERTYPE_IMLBL = 0x4c42 + ETHERTYPE_IMLBLDIAG = 0x424c + ETHERTYPE_IP = 0x800 + ETHERTYPE_IPAS = 0x876c + ETHERTYPE_IPV6 = 0x86dd + ETHERTYPE_IPX = 0x8137 + ETHERTYPE_IPXNEW = 0x8037 + ETHERTYPE_KALPANA = 0x8582 + ETHERTYPE_LANBRIDGE = 0x8038 + ETHERTYPE_LANPROBE = 0x8888 + ETHERTYPE_LAT = 0x6004 + ETHERTYPE_LBACK = 0x9000 + ETHERTYPE_LITTLE = 0x8060 + ETHERTYPE_LLDP = 0x88cc + ETHERTYPE_LOGICRAFT = 0x8148 + ETHERTYPE_LOOPBACK = 0x9000 + ETHERTYPE_MACSEC = 0x88e5 + ETHERTYPE_MATRA = 0x807a + ETHERTYPE_MAX = 0xffff + ETHERTYPE_MERIT = 0x807c + ETHERTYPE_MICP = 0x873a + ETHERTYPE_MOPDL = 0x6001 + ETHERTYPE_MOPRC = 0x6002 + ETHERTYPE_MOTOROLA = 0x818d + ETHERTYPE_MPLS = 0x8847 + ETHERTYPE_MPLS_MCAST = 0x8848 + ETHERTYPE_MUMPS = 0x813f + ETHERTYPE_NBPCC = 0x3c04 + ETHERTYPE_NBPCLAIM = 0x3c09 + ETHERTYPE_NBPCLREQ = 0x3c05 + ETHERTYPE_NBPCLRSP = 0x3c06 + ETHERTYPE_NBPCREQ = 0x3c02 + ETHERTYPE_NBPCRSP = 0x3c03 + ETHERTYPE_NBPDG = 0x3c07 + ETHERTYPE_NBPDGB = 0x3c08 + ETHERTYPE_NBPDLTE = 0x3c0a + ETHERTYPE_NBPRAR = 0x3c0c + ETHERTYPE_NBPRAS = 0x3c0b + ETHERTYPE_NBPRST = 0x3c0d + ETHERTYPE_NBPSCD = 0x3c01 + ETHERTYPE_NBPVCD = 0x3c00 + ETHERTYPE_NBS = 0x802 + ETHERTYPE_NCD = 0x8149 + ETHERTYPE_NESTAR = 0x8006 + ETHERTYPE_NETBEUI = 0x8191 + ETHERTYPE_NHRP = 0x2001 + ETHERTYPE_NOVELL = 0x8138 + ETHERTYPE_NS = 0x600 + ETHERTYPE_NSAT = 0x601 + ETHERTYPE_NSCOMPAT = 0x807 + ETHERTYPE_NSH = 0x984f + ETHERTYPE_NTRAILER = 0x10 + ETHERTYPE_OS9 = 0x7007 + ETHERTYPE_OS9NET = 0x7009 + ETHERTYPE_PACER = 0x80c6 + ETHERTYPE_PBB = 0x88e7 + ETHERTYPE_PCS = 0x4242 + ETHERTYPE_PLANNING = 0x8044 + ETHERTYPE_PPP = 0x880b + ETHERTYPE_PPPOE = 0x8864 + ETHERTYPE_PPPOEDISC = 0x8863 + ETHERTYPE_PRIMENTS = 0x7031 + ETHERTYPE_PUP = 0x200 + ETHERTYPE_PUPAT = 0x200 + ETHERTYPE_QINQ = 0x88a8 + ETHERTYPE_RACAL = 0x7030 + ETHERTYPE_RATIONAL = 0x8150 + ETHERTYPE_RAWFR = 0x6559 + ETHERTYPE_RCL = 0x1995 + ETHERTYPE_RDP = 0x8739 + ETHERTYPE_RETIX = 0x80f2 + ETHERTYPE_REVARP = 0x8035 + ETHERTYPE_SCA = 0x6007 + ETHERTYPE_SECTRA = 0x86db + ETHERTYPE_SECUREDATA = 0x876d + ETHERTYPE_SGITW = 0x817e + ETHERTYPE_SG_BOUNCE = 0x8016 + ETHERTYPE_SG_DIAG = 0x8013 + ETHERTYPE_SG_NETGAMES = 0x8014 + ETHERTYPE_SG_RESV = 0x8015 + ETHERTYPE_SIMNET = 0x5208 + ETHERTYPE_SLOW = 0x8809 + ETHERTYPE_SNA = 0x80d5 + ETHERTYPE_SNMP = 0x814c + ETHERTYPE_SONIX = 0xfaf5 + ETHERTYPE_SPIDER = 0x809f + ETHERTYPE_SPRITE = 0x500 + ETHERTYPE_STP = 0x8181 + ETHERTYPE_TALARIS = 0x812b + ETHERTYPE_TALARISMC = 0x852b + ETHERTYPE_TCPCOMP = 0x876b + ETHERTYPE_TCPSM = 0x9002 + ETHERTYPE_TEC = 0x814f + ETHERTYPE_TIGAN = 0x802f + ETHERTYPE_TRAIL = 0x1000 + ETHERTYPE_TRANSETHER = 0x6558 + ETHERTYPE_TYMSHARE = 0x802e + ETHERTYPE_UBBST = 0x7005 + ETHERTYPE_UBDEBUG = 0x900 + ETHERTYPE_UBDIAGLOOP = 0x7002 + ETHERTYPE_UBDL = 0x7000 + ETHERTYPE_UBNIU = 0x7001 + ETHERTYPE_UBNMC = 0x7003 + ETHERTYPE_VALID = 0x1600 + ETHERTYPE_VARIAN = 0x80dd + ETHERTYPE_VAXELN = 0x803b + ETHERTYPE_VEECO = 0x8067 + ETHERTYPE_VEXP = 0x805b + ETHERTYPE_VGLAB = 0x8131 + ETHERTYPE_VINES = 0xbad + ETHERTYPE_VINESECHO = 0xbaf + ETHERTYPE_VINESLOOP = 0xbae + ETHERTYPE_VITAL = 0xff00 + ETHERTYPE_VLAN = 0x8100 + ETHERTYPE_VLTLMAN = 0x8080 + ETHERTYPE_VPROD = 0x805c + ETHERTYPE_VURESERVED = 0x8147 + ETHERTYPE_WATERLOO = 0x8130 + ETHERTYPE_WELLFLEET = 0x8103 + ETHERTYPE_X25 = 0x805 + ETHERTYPE_X75 = 0x801 + ETHERTYPE_XNSSM = 0x9001 + ETHERTYPE_XTP = 0x817d + ETHER_ADDR_LEN = 0x6 + ETHER_ALIGN = 0x2 + ETHER_CRC_LEN = 0x4 + ETHER_CRC_POLY_BE = 0x4c11db6 + ETHER_CRC_POLY_LE = 0xedb88320 + ETHER_HDR_LEN = 0xe + ETHER_MAX_DIX_LEN = 0x600 + ETHER_MAX_HARDMTU_LEN = 0xff9b + ETHER_MAX_LEN = 0x5ee + ETHER_MIN_LEN = 0x40 + ETHER_TYPE_LEN = 0x2 + ETHER_VLAN_ENCAP_LEN = 0x4 EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 + EVFILT_DEVICE = -0x8 + EVFILT_EXCEPT = -0x9 EVFILT_PROC = -0x5 EVFILT_READ = -0x1 EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xf - EVFILT_THREADMARKER = 0xf + EVFILT_SYSCOUNT = 0x9 EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc EVFILT_VNODE = -0x4 EVFILT_WRITE = -0x2 + EVL_ENCAPLEN = 0x4 + EVL_PRIO_BITS = 0xd + EVL_PRIO_MAX = 0x7 + EVL_VLID_MASK = 0xfff + EVL_VLID_MAX = 0xffe + EVL_VLID_MIN = 0x1 + EVL_VLID_NULL = 0x0 EV_ADD = 0x1 EV_CLEAR = 0x20 EV_DELETE = 0x2 EV_DISABLE = 0x8 EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 EV_ENABLE = 0x4 EV_EOF = 0x8000 EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 EV_FLAG1 = 0x2000 EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTPROC = 0x800 FD_CLOEXEC = 0x1 FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 + F_DUPFD_CLOEXEC = 0xa F_GETFD = 0x1 F_GETFL = 0x3 F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e + F_ISATTY = 0xb F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 F_SETFD = 0x2 F_SETFL = 0x4 F_SETLK = 0x8 F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 F_WRLCK = 0x3 HUPCL = 0x4000 HW_MACHINE = 0x1 @@ -539,9 +569,11 @@ const ( ICMP6_FILTER = 0x12 ICRNL = 0x100 IEXTEN = 0x400 + IFAN_ARRIVAL = 0x0 + IFAN_DEPARTURE = 0x1 IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 IFF_BROADCAST = 0x2 + IFF_CANTCHANGE = 0x8e52 IFF_DEBUG = 0x4 IFF_LINK0 = 0x1000 IFF_LINK1 = 0x2000 @@ -549,80 +581,237 @@ const ( IFF_LOOPBACK = 0x8 IFF_MULTICAST = 0x8000 IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 IFF_OACTIVE = 0x400 IFF_POINTOPOINT = 0x10 IFF_PROMISC = 0x100 IFF_RUNNING = 0x40 IFF_SIMPLEX = 0x800 + IFF_STATICARP = 0x20 IFF_UP = 0x1 IFNAMSIZ = 0x10 IFT_1822 = 0x2 + IFT_A12MPPSWITCH = 0x82 + IFT_AAL2 = 0xbb IFT_AAL5 = 0x31 + IFT_ADSL = 0x5e + IFT_AFLANE8023 = 0x3b + IFT_AFLANE8025 = 0x3c + IFT_ARAP = 0x58 IFT_ARCNET = 0x23 IFT_ARCNETPLUS = 0x24 + IFT_ASYNC = 0x54 IFT_ATM = 0x25 + IFT_ATMDXI = 0x69 + IFT_ATMFUNI = 0x6a + IFT_ATMIMA = 0x6b + IFT_ATMLOGICAL = 0x50 + IFT_ATMRADIO = 0xbd + IFT_ATMSUBINTERFACE = 0x86 + IFT_ATMVCIENDPT = 0xc2 + IFT_ATMVIRTUAL = 0x95 + IFT_BGPPOLICYACCOUNTING = 0xa2 + IFT_BLUETOOTH = 0xf8 IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff + IFT_BSC = 0x53 + IFT_CARP = 0xf7 + IFT_CCTEMUL = 0x3d IFT_CEPT = 0x13 + IFT_CES = 0x85 + IFT_CHANNEL = 0x46 + IFT_CNR = 0x55 + IFT_COFFEE = 0x84 + IFT_COMPOSITELINK = 0x9b + IFT_DCN = 0x8d + IFT_DIGITALPOWERLINE = 0x8a + IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba + IFT_DLSW = 0x4a + IFT_DOCSCABLEDOWNSTREAM = 0x80 + IFT_DOCSCABLEMACLAYER = 0x7f + IFT_DOCSCABLEUPSTREAM = 0x81 + IFT_DOCSCABLEUPSTREAMCHANNEL = 0xcd + IFT_DS0 = 0x51 + IFT_DS0BUNDLE = 0x52 + IFT_DS1FDL = 0xaa IFT_DS3 = 0x1e + IFT_DTM = 0x8c + IFT_DUMMY = 0xf1 + IFT_DVBASILN = 0xac + IFT_DVBASIOUT = 0xad + IFT_DVBRCCDOWNSTREAM = 0x93 + IFT_DVBRCCMACLAYER = 0x92 + IFT_DVBRCCUPSTREAM = 0x94 + IFT_ECONET = 0xce IFT_ENC = 0xf4 IFT_EON = 0x19 + IFT_EPLRS = 0x57 + IFT_ESCON = 0x49 IFT_ETHER = 0x6 - IFT_FAITH = 0x38 + IFT_FAITH = 0xf3 + IFT_FAST = 0x7d + IFT_FASTETHER = 0x3e + IFT_FASTETHERFX = 0x45 IFT_FDDI = 0xf + IFT_FIBRECHANNEL = 0x38 + IFT_FRAMERELAYINTERCONNECT = 0x3a + IFT_FRAMERELAYMPI = 0x5c + IFT_FRDLCIENDPT = 0xc1 IFT_FRELAY = 0x20 IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 + IFT_FRF16MFRBUNDLE = 0xa3 + IFT_FRFORWARD = 0x9e + IFT_G703AT2MB = 0x43 + IFT_G703AT64K = 0x42 + IFT_GIF = 0xf0 + IFT_GIGABITETHERNET = 0x75 + IFT_GR303IDT = 0xb2 + IFT_GR303RDT = 0xb1 + IFT_H323GATEKEEPER = 0xa4 + IFT_H323PROXY = 0xa5 IFT_HDH1822 = 0x3 + IFT_HDLC = 0x76 + IFT_HDSL2 = 0xa8 + IFT_HIPERLAN2 = 0xb7 IFT_HIPPI = 0x2f + IFT_HIPPIINTERFACE = 0x39 + IFT_HOSTPAD = 0x5a IFT_HSSI = 0x2e IFT_HY = 0xe + IFT_IBM370PARCHAN = 0x48 + IFT_IDSL = 0x9a IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 + IFT_IEEE80211 = 0x47 + IFT_IEEE80212 = 0x37 + IFT_IEEE8023ADLAG = 0xa1 + IFT_IFGSN = 0x91 + IFT_IMT = 0xbe + IFT_INFINIBAND = 0xc7 + IFT_INTERLEAVE = 0x7c + IFT_IP = 0x7e + IFT_IPFORWARD = 0x8e + IFT_IPOVERATM = 0x72 + IFT_IPOVERCDLC = 0x6d + IFT_IPOVERCLAW = 0x6e + IFT_IPSWITCH = 0x4e + IFT_ISDN = 0x3f IFT_ISDNBASIC = 0x14 IFT_ISDNPRIMARY = 0x15 + IFT_ISDNS = 0x4b + IFT_ISDNU = 0x4c IFT_ISO88022LLC = 0x29 IFT_ISO88023 = 0x7 IFT_ISO88024 = 0x8 IFT_ISO88025 = 0x9 + IFT_ISO88025CRFPINT = 0x62 + IFT_ISO88025DTR = 0x56 + IFT_ISO88025FIBER = 0x73 IFT_ISO88026 = 0xa + IFT_ISUP = 0xb3 IFT_L2VLAN = 0x87 + IFT_L3IPVLAN = 0x88 + IFT_L3IPXVLAN = 0x89 IFT_LAPB = 0x10 + IFT_LAPD = 0x4d + IFT_LAPF = 0x77 + IFT_LINEGROUP = 0xd2 IFT_LOCALTALK = 0x2a IFT_LOOP = 0x18 + IFT_MBIM = 0xfa + IFT_MEDIAMAILOVERIP = 0x8b + IFT_MFSIGLINK = 0xa7 IFT_MIOX25 = 0x26 IFT_MODEM = 0x30 + IFT_MPC = 0x71 + IFT_MPLS = 0xa6 + IFT_MPLSTUNNEL = 0x96 + IFT_MSDSL = 0x8f + IFT_MVL = 0xbf + IFT_MYRINET = 0x63 + IFT_NFAS = 0xaf IFT_NSIP = 0x1b + IFT_OPTICALCHANNEL = 0xc3 + IFT_OPTICALTRANSPORT = 0xc4 IFT_OTHER = 0x1 IFT_P10 = 0xc IFT_P80 = 0xd IFT_PARA = 0x22 - IFT_PDP = 0xff IFT_PFLOG = 0xf5 + IFT_PFLOW = 0xf9 IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe + IFT_PLC = 0xae + IFT_PON155 = 0xcf + IFT_PON622 = 0xd0 + IFT_POS = 0xab IFT_PPP = 0x17 + IFT_PPPMULTILINKBUNDLE = 0x6c + IFT_PROPATM = 0xc5 + IFT_PROPBWAP2MP = 0xb8 + IFT_PROPCNLS = 0x59 + IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 + IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 + IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 IFT_PROPMUX = 0x36 IFT_PROPVIRTUAL = 0x35 + IFT_PROPWIRELESSP2P = 0x9d IFT_PTPSERIAL = 0x16 + IFT_PVC = 0xf2 + IFT_Q2931 = 0xc9 + IFT_QLLC = 0x44 + IFT_RADIOMAC = 0xbc + IFT_RADSL = 0x5f + IFT_REACHDSL = 0xc0 + IFT_RFC1483 = 0x9f IFT_RS232 = 0x21 + IFT_RSRB = 0x4f IFT_SDLC = 0x11 + IFT_SDSL = 0x60 + IFT_SHDSL = 0xa9 IFT_SIP = 0x1f + IFT_SIPSIG = 0xcc + IFT_SIPTG = 0xcb IFT_SLIP = 0x1c IFT_SMDSDXI = 0x2b IFT_SMDSICIP = 0x34 IFT_SONET = 0x27 + IFT_SONETOVERHEADCHANNEL = 0xb9 IFT_SONETPATH = 0x32 IFT_SONETVT = 0x33 + IFT_SRP = 0x97 + IFT_SS7SIGLINK = 0x9c + IFT_STACKTOSTACK = 0x6f IFT_STARLAN = 0xb - IFT_STF = 0x39 IFT_T1 = 0x12 + IFT_TDLC = 0x74 + IFT_TELINK = 0xc8 + IFT_TERMPAD = 0x5b + IFT_TR008 = 0xb0 + IFT_TRANSPHDLC = 0x7b + IFT_TUNNEL = 0x83 IFT_ULTRA = 0x1d + IFT_USB = 0xa0 + IFT_V11 = 0x40 IFT_V35 = 0x2d + IFT_V36 = 0x41 + IFT_V37 = 0x78 + IFT_VDSL = 0x61 + IFT_VIRTUALIPADDRESS = 0x70 + IFT_VIRTUALTG = 0xca + IFT_VOICEDID = 0xd5 + IFT_VOICEEM = 0x64 + IFT_VOICEEMFGD = 0xd3 + IFT_VOICEENCAP = 0x67 + IFT_VOICEFGDEANA = 0xd4 + IFT_VOICEFXO = 0x65 + IFT_VOICEFXS = 0x66 + IFT_VOICEOVERATM = 0x98 + IFT_VOICEOVERCABLE = 0xc6 + IFT_VOICEOVERFRAMERELAY = 0x99 + IFT_VOICEOVERIP = 0x68 + IFT_WIREGUARD = 0xfb + IFT_X213 = 0x5d IFT_X25 = 0x5 IFT_X25DDN = 0x4 + IFT_X25HUNTGROUP = 0x7a + IFT_X25MLP = 0x79 IFT_X25PLE = 0x28 IFT_XETHER = 0x1a IGNBRK = 0x1 @@ -645,239 +834,159 @@ const ( IN_CLASSD_HOST = 0xfffffff IN_CLASSD_NET = 0xf0000000 IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 + IN_RFC3021_HOST = 0x1 + IN_RFC3021_NET = 0xfffffffe + IN_RFC3021_NSHIFT = 0x1f IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe + IPPROTO_CARP = 0x70 + IPPROTO_DIVERT = 0x102 IPPROTO_DONE = 0x101 IPPROTO_DSTOPTS = 0x3c IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe IPPROTO_ENCAP = 0x62 IPPROTO_EON = 0x50 IPPROTO_ESP = 0x32 IPPROTO_ETHERIP = 0x61 IPPROTO_FRAGMENT = 0x2c IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 IPPROTO_HOPOPTS = 0x0 IPPROTO_ICMP = 0x1 IPPROTO_ICMPV6 = 0x3a IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 IPPROTO_IP = 0x0 IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 IPPROTO_IPV4 = 0x4 IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 + IPPROTO_MAXID = 0x103 + IPPROTO_MOBILE = 0x37 + IPPROTO_MPLS = 0x89 IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 + IPPROTO_PFSYNC = 0xf0 IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d + IPPROTO_UDPLITE = 0x88 + IPV6_AUTH_LEVEL = 0x35 + IPV6_AUTOFLOWLABEL = 0x3b IPV6_CHECKSUM = 0x1a IPV6_DEFAULT_MULTICAST_HOPS = 0x1 IPV6_DEFAULT_MULTICAST_LOOP = 0x1 IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_ESP_NETWORK_LEVEL = 0x37 + IPV6_ESP_TRANS_LEVEL = 0x36 IPV6_FAITH = 0x1d IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x300 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 + IPV6_FRAGTTL = 0x78 IPV6_HLIMDEC = 0x1 - IPV6_IPSEC_POLICY = 0x1c + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPCOMP_LEVEL = 0x3c IPV6_JOIN_GROUP = 0xc IPV6_LEAVE_GROUP = 0xd IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MINHOPCOUNT = 0x41 IPV6_MMTU = 0x500 IPV6_MULTICAST_HOPS = 0xa IPV6_MULTICAST_IF = 0x9 IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_OPTIONS = 0x1 + IPV6_PATHMTU = 0x2c + IPV6_PIPEX = 0x3f + IPV6_PKTINFO = 0x2e IPV6_PORTRANGE = 0xe IPV6_PORTRANGE_DEFAULT = 0x0 IPV6_PORTRANGE_HIGH = 0x1 IPV6_PORTRANGE_LOW = 0x2 - IPV6_RECVTCLASS = 0x23 + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVDSTPORT = 0x40 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x24 + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x39 + IPV6_RTABLE = 0x1021 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x23 IPV6_RTHDR_LOOSE = 0x0 IPV6_RTHDR_STRICT = 0x1 IPV6_RTHDR_TYPE_0 = 0x0 IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 + IPV6_TCLASS = 0x3d IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a IPV6_V6ONLY = 0x1b IPV6_VERSION = 0x60 IPV6_VERSION_MASK = 0xf0 IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 + IP_AUTH_LEVEL = 0x14 IP_DEFAULT_MULTICAST_LOOP = 0x1 IP_DEFAULT_MULTICAST_TTL = 0x1 IP_DF = 0x4000 IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b + IP_ESP_NETWORK_LEVEL = 0x16 + IP_ESP_TRANS_LEVEL = 0x15 IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 + IP_IPCOMP_LEVEL = 0x1d + IP_IPDEFTTL = 0x25 + IP_IPSECFLOWINFO = 0x24 + IP_IPSEC_LOCAL_AUTH = 0x1b + IP_IPSEC_LOCAL_CRED = 0x19 + IP_IPSEC_LOCAL_ID = 0x17 + IP_IPSEC_REMOTE_AUTH = 0x1c + IP_IPSEC_REMOTE_CRED = 0x1a + IP_IPSEC_REMOTE_ID = 0x18 IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a + IP_MINTTL = 0x20 + IP_MIN_MEMBERSHIPS = 0xf IP_MSS = 0x240 IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 IP_MULTICAST_LOOP = 0xb IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a + IP_PIPEX = 0x22 IP_PORTRANGE = 0x13 IP_PORTRANGE_DEFAULT = 0x0 IP_PORTRANGE_HIGH = 0x1 IP_PORTRANGE_LOW = 0x2 IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 + IP_RECVDSTPORT = 0x21 + IP_RECVIF = 0x1e IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 + IP_RECVRTABLE = 0x23 + IP_RECVTTL = 0x1f IP_RETOPTS = 0x8 IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 + IP_RTABLE = 0x1021 + IP_SENDSRCADDR = 0x7 IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 ISIG = 0x80 ISTRIP = 0x20 - IUTF8 = 0x4000 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 + IUCLC = 0x1000 IXANY = 0x800 IXOFF = 0x400 IXON = 0x200 @@ -885,188 +994,155 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LCNT_OVERLOAD_FLUSH = 0x6 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 + MADV_FREE = 0x6 MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa MADV_RANDOM = 0x1 MADV_SEQUENTIAL = 0x2 + MADV_SPACEAVAIL = 0x5 MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 MAP_ANON = 0x1000 MAP_ANONYMOUS = 0x1000 + MAP_CONCEAL = 0x8000 MAP_COPY = 0x2 MAP_FILE = 0x0 MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 + MAP_FLAGMASK = 0xfff7 + MAP_HASSEMAPHORE = 0x0 + MAP_INHERIT = 0x0 + MAP_INHERIT_COPY = 0x1 + MAP_INHERIT_NONE = 0x2 + MAP_INHERIT_SHARE = 0x0 + MAP_INHERIT_ZERO = 0x3 + MAP_NOEXTEND = 0x0 + MAP_NORESERVE = 0x0 MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 + MAP_RENAME = 0x0 MAP_SHARED = 0x1 + MAP_STACK = 0x4000 + MAP_TRYFIXED = 0x0 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 + MNT_DEFEXPORTED = 0x200 + MNT_DELEXPORT = 0x20000 + MNT_DOOMED = 0x8000000 + MNT_EXPORTANON = 0x400 MNT_EXPORTED = 0x100 + MNT_EXRDONLY = 0x80 MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 + MNT_LAZY = 0x3 MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 + MNT_NOATIME = 0x8000 MNT_NODEV = 0x10 MNT_NOEXEC = 0x4 + MNT_NOPERM = 0x20 MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 MNT_QUOTA = 0x2000 MNT_RDONLY = 0x1 MNT_RELOAD = 0x40000 MNT_ROOTFS = 0x4000 + MNT_SOFTDEP = 0x4000000 + MNT_STALLED = 0x100000 + MNT_SWAPPABLE = 0x200000 MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0x17f0f5ff + MNT_VISFLAGMASK = 0x400ffff MNT_WAIT = 0x1 + MNT_WANTRDWR = 0x2000000 + MNT_WXALLOWED = 0x800 + MOUNT_AFS = "afs" + MOUNT_CD9660 = "cd9660" + MOUNT_EXT2FS = "ext2fs" + MOUNT_FFS = "ffs" + MOUNT_FUSEFS = "fuse" + MOUNT_MFS = "mfs" + MOUNT_MSDOS = "msdos" + MOUNT_NCPFS = "ncpfs" + MOUNT_NFS = "nfs" + MOUNT_NTFS = "ntfs" + MOUNT_TMPFS = "tmpfs" + MOUNT_UDF = "udf" + MOUNT_UFS = "ffs" + MSG_BCAST = 0x100 + MSG_CMSG_CLOEXEC = 0x800 MSG_CTRUNC = 0x20 MSG_DONTROUTE = 0x4 MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 + MSG_MCAST = 0x200 + MSG_NOSIGNAL = 0x400 MSG_OOB = 0x1 MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 MSG_TRUNC = 0x10 MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 + MS_INVALIDATE = 0x4 + MS_SYNC = 0x2 NAME_MAX = 0xff NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 NET_RT_FLAGS = 0x2 NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xa - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 + NET_RT_IFNAMES = 0x6 + NET_RT_MAXID = 0x8 + NET_RT_SOURCE = 0x7 + NET_RT_STATS = 0x4 + NET_RT_TABLE = 0x5 NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 NOFLSH = 0x80000000 NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 + NOTE_CHANGE = 0x1 NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 NOTE_DELETE = 0x1 + NOTE_EOF = 0x2 NOTE_EXEC = 0x20000000 NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 NOTE_LINK = 0x10 NOTE_LOWAT = 0x1 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 + NOTE_OOB = 0x4 + NOTE_PCTRLMASK = 0xf0000000 NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 NOTE_RENAME = 0x20 NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 NOTE_TRACK = 0x1 NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_TRUNCATE = 0x80 NOTE_WRITE = 0x2 OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 + OLCUC = 0x20 ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 + ONLRET = 0x80 + ONOCR = 0x40 ONOEOT = 0x8 OPOST = 0x1 OXTABS = 0x4 O_ACCMODE = 0x3 - O_ALERT = 0x20000000 O_APPEND = 0x8 O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 + O_CLOEXEC = 0x10000 O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 + O_DIRECTORY = 0x20000 + O_DSYNC = 0x80 O_EXCL = 0x800 O_EXLOCK = 0x20 O_FSYNC = 0x80 O_NDELAY = 0x4 - O_NOCTTY = 0x20000 + O_NOCTTY = 0x8000 O_NOFOLLOW = 0x100 O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 O_RDONLY = 0x0 O_RDWR = 0x2 + O_RSYNC = 0x80 O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 O_SYNC = 0x80 O_TRUNC = 0x400 O_WRONLY = 0x1 @@ -1074,6 +1150,7 @@ const ( PARMRK = 0x8 PARODD = 0x2000 PENDIN = 0x20000000 + PF_FLUSH = 0x1 PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 @@ -1081,28 +1158,8 @@ const ( PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 RLIMIT_MEMLOCK = 0x6 @@ -1112,70 +1169,83 @@ const ( RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 + RTAX_BFD = 0xb RTAX_BRD = 0x7 + RTAX_DNS = 0xc RTAX_DST = 0x0 RTAX_GATEWAY = 0x1 RTAX_GENMASK = 0x3 RTAX_IFA = 0x5 RTAX_IFP = 0x4 - RTAX_MAX = 0x8 + RTAX_LABEL = 0xa + RTAX_MAX = 0xf RTAX_NETMASK = 0x2 + RTAX_SEARCH = 0xe + RTAX_SRC = 0x8 + RTAX_SRCMASK = 0x9 + RTAX_STATIC = 0xd RTA_AUTHOR = 0x40 + RTA_BFD = 0x800 RTA_BRD = 0x80 + RTA_DNS = 0x1000 RTA_DST = 0x1 RTA_GATEWAY = 0x2 RTA_GENMASK = 0x8 RTA_IFA = 0x20 RTA_IFP = 0x10 + RTA_LABEL = 0x400 RTA_NETMASK = 0x4 + RTA_SEARCH = 0x4000 + RTA_SRC = 0x100 + RTA_SRCMASK = 0x200 + RTA_STATIC = 0x2000 + RTF_ANNOUNCE = 0x4000 + RTF_BFD = 0x1000000 RTF_BLACKHOLE = 0x1000 RTF_BROADCAST = 0x400000 + RTF_CACHED = 0x20000 + RTF_CLONED = 0x10000 RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DELCLONE = 0x80 + RTF_CONNECTED = 0x800000 RTF_DONE = 0x40 RTF_DYNAMIC = 0x10 + RTF_FMASK = 0x110fc08 RTF_GATEWAY = 0x2 RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 RTF_LLINFO = 0x400 RTF_LOCAL = 0x200000 RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 + RTF_MPATH = 0x40000 + RTF_MPLS = 0x100000 + RTF_MULTICAST = 0x200 + RTF_PERMANENT_ARP = 0x2000 RTF_PROTO1 = 0x8000 RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 + RTF_PROTO3 = 0x2000 RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 RTF_STATIC = 0x800 RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 + RTF_USETRAILERS = 0x8000 + RTM_80211INFO = 0x15 RTM_ADD = 0x1 + RTM_BFD = 0x12 RTM_CHANGE = 0x3 + RTM_CHGADDRATTR = 0x14 RTM_DELADDR = 0xd RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 + RTM_DESYNC = 0x10 RTM_GET = 0x4 - RTM_GET2 = 0x14 + RTM_IFANNOUNCE = 0xf RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 + RTM_INVALIDATE = 0x11 RTM_LOSING = 0x5 + RTM_MAXSIZE = 0x800 RTM_MISS = 0x7 RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa + RTM_PROPOSAL = 0x13 RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 + RTM_SOURCE = 0x16 RTM_VERSION = 0x5 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 @@ -1185,83 +1255,167 @@ const ( RTV_RTTVAR = 0x80 RTV_SPIPE = 0x10 RTV_SSTHRESH = 0x20 + RT_TABLEID_BITS = 0x8 + RT_TABLEID_MASK = 0xff + RT_TABLEID_MAX = 0xff RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 + RUSAGE_THREAD = 0x1 SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 + SCM_TIMESTAMP = 0x4 + SEEK_CUR = 0x1 + SEEK_END = 0x2 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 SIOCADDMULTI = 0x80206931 SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 + SIOCAIFGROUP = 0x80286987 SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 + SIOCBRDGADD = 0x8060693c + SIOCBRDGADDL = 0x80606949 + SIOCBRDGADDS = 0x80606941 + SIOCBRDGARL = 0x808c694d + SIOCBRDGDADDR = 0x81286947 + SIOCBRDGDEL = 0x8060693d + SIOCBRDGDELS = 0x80606942 + SIOCBRDGFLUSH = 0x80606948 + SIOCBRDGFRL = 0x808c694e + SIOCBRDGGCACHE = 0xc0146941 + SIOCBRDGGFD = 0xc0146952 + SIOCBRDGGHT = 0xc0146951 + SIOCBRDGGIFFLGS = 0xc060693e + SIOCBRDGGMA = 0xc0146953 + SIOCBRDGGPARAM = 0xc0406958 + SIOCBRDGGPRI = 0xc0146950 + SIOCBRDGGRL = 0xc030694f + SIOCBRDGGTO = 0xc0146946 + SIOCBRDGIFS = 0xc0606942 + SIOCBRDGRTS = 0xc0206943 + SIOCBRDGSADDR = 0xc1286944 + SIOCBRDGSCACHE = 0x80146940 + SIOCBRDGSFD = 0x80146952 + SIOCBRDGSHT = 0x80146951 + SIOCBRDGSIFCOST = 0x80606955 + SIOCBRDGSIFFLGS = 0x8060693f + SIOCBRDGSIFPRIO = 0x80606954 + SIOCBRDGSIFPROT = 0x8060694a + SIOCBRDGSMA = 0x80146953 + SIOCBRDGSPRI = 0x80146950 + SIOCBRDGSPROTO = 0x8014695a + SIOCBRDGSTO = 0x80146945 + SIOCBRDGSTXHC = 0x80146959 + SIOCDELLABEL = 0x80206997 SIOCDELMULTI = 0x80206932 SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc01c697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 + SIOCDIFGROUP = 0x80286989 + SIOCDIFPARENT = 0x802069b4 + SIOCDIFPHYADDR = 0x80206949 + SIOCDPWE3NEIGHBOR = 0x802069de + SIOCDVNETID = 0x802069af + SIOCGETKALIVE = 0xc01869a4 + SIOCGETLABEL = 0x8020699a + SIOCGETMPWCFG = 0xc02069ae + SIOCGETPFLOW = 0xc02069fe + SIOCGETPFSYNC = 0xc02069f8 + SIOCGETSGCNT = 0xc0207534 + SIOCGETVIFCNT = 0xc0287533 + SIOCGETVLAN = 0xc0206990 SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc0086924 - SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFCONF = 0xc0106924 + SIOCGIFDATA = 0xc020691b + SIOCGIFDESCR = 0xc0206981 SIOCGIFDSTADDR = 0xc0206922 SIOCGIFFLAGS = 0xc0206911 + SIOCGIFGATTR = 0xc028698b SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc0286938 + SIOCGIFGLIST = 0xc028698d + SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 + SIOCGIFHARDMTU = 0xc02069a5 + SIOCGIFLLPRIO = 0xc02069b6 + SIOCGIFMEDIA = 0xc0406938 SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 + SIOCGIFMTU = 0xc020697e SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGLOWAT = 0x40047303 + SIOCGIFPAIR = 0xc02069b1 + SIOCGIFPARENT = 0xc02069b3 + SIOCGIFPRIORITY = 0xc020699c + SIOCGIFRDOMAIN = 0xc02069a0 + SIOCGIFRTLABEL = 0xc0206983 + SIOCGIFRXR = 0x802069aa + SIOCGIFSFFPAGE = 0xc1126939 + SIOCGIFXFLAGS = 0xc020699e + SIOCGLIFPHYADDR = 0xc218694b + SIOCGLIFPHYDF = 0xc02069c2 + SIOCGLIFPHYECN = 0xc02069c8 + SIOCGLIFPHYRTABLE = 0xc02069a2 + SIOCGLIFPHYTTL = 0xc02069a9 SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a + SIOCGPWE3 = 0xc0206998 + SIOCGPWE3CTRLWORD = 0xc02069dc + SIOCGPWE3FAT = 0xc02069dd + SIOCGPWE3NEIGHBOR = 0xc21869de + SIOCGRXHPRIO = 0xc02069db + SIOCGSPPPPARAMS = 0xc0206994 + SIOCGTXHPRIO = 0xc02069c6 + SIOCGUMBINFO = 0xc02069be + SIOCGUMBPARAM = 0xc02069c0 + SIOCGVH = 0xc02069f6 + SIOCGVNETFLOWID = 0xc02069c4 + SIOCGVNETID = 0xc02069a7 + SIOCIFAFATTACH = 0x801169ab + SIOCIFAFDETACH = 0x801169ac + SIOCIFCREATE = 0x8020697a SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc00c6981 - SIOCRSLVMULTI = 0xc008693b - SIOCSDRVSPEC = 0x801c697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 + SIOCIFGCLONERS = 0xc0106978 + SIOCSETKALIVE = 0x801869a3 + SIOCSETLABEL = 0x80206999 + SIOCSETMPWCFG = 0x802069ad + SIOCSETPFLOW = 0x802069fd + SIOCSETPFSYNC = 0x802069f7 + SIOCSETVLAN = 0x8020698f SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a + SIOCSIFDESCR = 0x80206980 SIOCSIFDSTADDR = 0x8020690e SIOCSIFFLAGS = 0x80206910 + SIOCSIFGATTR = 0x8028698c SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 + SIOCSIFLLADDR = 0x8020691f + SIOCSIFLLPRIO = 0x802069b5 SIOCSIFMEDIA = 0xc0206937 SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 + SIOCSIFMTU = 0x8020697f SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 + SIOCSIFPAIR = 0x802069b0 + SIOCSIFPARENT = 0x802069b2 + SIOCSIFPRIORITY = 0x8020699b + SIOCSIFRDOMAIN = 0x8020699f + SIOCSIFRTLABEL = 0x80206982 + SIOCSIFXFLAGS = 0x8020699d + SIOCSLIFPHYADDR = 0x8218694a + SIOCSLIFPHYDF = 0x802069c1 + SIOCSLIFPHYECN = 0x802069c7 + SIOCSLIFPHYRTABLE = 0x802069a1 + SIOCSLIFPHYTTL = 0x802069a8 SIOCSPGRP = 0x80047308 + SIOCSPWE3CTRLWORD = 0x802069dc + SIOCSPWE3FAT = 0x802069dd + SIOCSPWE3NEIGHBOR = 0x821869de + SIOCSRXHPRIO = 0x802069db + SIOCSSPPPPARAMS = 0x80206993 + SIOCSTXHPRIO = 0x802069c5 + SIOCSUMBPARAM = 0x802069bf + SIOCSVH = 0xc02069f5 + SIOCSVNETFLOWID = 0x802069c3 + SIOCSVNETID = 0x802069a6 + SOCK_CLOEXEC = 0x8000 SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff + SOCK_DNS = 0x1000 + SOCK_NONBLOCK = 0x4000 SOCK_RAW = 0x3 SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 @@ -1269,44 +1423,33 @@ const ( SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 + SO_BINDANY = 0x1000 SO_BROADCAST = 0x20 SO_DEBUG = 0x1 + SO_DOMAIN = 0x1024 SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 SO_ERROR = 0x1007 SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 + SO_NETPROC = 0x1020 SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 + SO_PEERCRED = 0x1022 + SO_PROTOCOL = 0x1025 SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 + SO_RTABLE = 0x1021 SO_SNDBUF = 0x1001 SO_SNDLOWAT = 0x1003 SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 + SO_SPLICE = 0x1023 + SO_TIMESTAMP = 0x800 SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 + SO_ZEROIZE = 0x2000 + S_BLKSIZE = 0x200 S_IEXEC = 0x40 S_IFBLK = 0x6000 S_IFCHR = 0x2000 @@ -1316,7 +1459,6 @@ const ( S_IFMT = 0xf000 S_IFREG = 0x8000 S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 S_IREAD = 0x100 S_IRGRP = 0x20 S_IROTH = 0x4 @@ -1335,11 +1477,6 @@ const ( S_IXGRP = 0x8 S_IXOTH = 0x1 S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 TCIFLUSH = 0x1 TCIOFF = 0x3 TCIOFLUSH = 0x3 @@ -1347,52 +1484,57 @@ const ( TCOFLUSH = 0x2 TCOOFF = 0x1 TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_INFO = 0x9 TCP_MAXSEG = 0x2 TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 + TCP_MAX_SACK = 0x3 TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 + TCP_MD5SIG = 0x4 TCP_MSS = 0x200 TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 + TCP_NOPUSH = 0x10 + TCP_SACKHOLE_LIMIT = 0x80 + TCP_SACK_ENABLE = 0x8 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 + TIOCCHKVERAUTH = 0x2000741e + TIOCCLRVERAUTH = 0x2000741d TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40087458 TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 TIOCEXCL = 0x2000740d TIOCEXT = 0x80047460 + TIOCFLAG_CLOCAL = 0x2 + TIOCFLAG_CRTSCTS = 0x4 + TIOCFLAG_MDMBUF = 0x8 + TIOCFLAG_PPS = 0x10 + TIOCFLAG_SOFTCAR = 0x1 TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 TIOCGETA = 0x402c7413 TIOCGETD = 0x4004741a + TIOCGFLAGS = 0x4004745d TIOCGPGRP = 0x40047477 + TIOCGSID = 0x40047463 + TIOCGTSTAMP = 0x4010745b TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 TIOCMBIC = 0x8004746b TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b + TIOCMODG = 0x4004746a + TIOCMODS = 0x8004746d TIOCMSET = 0x8004746d TIOCM_CAR = 0x40 TIOCM_CD = 0x40 @@ -1417,29 +1559,29 @@ const ( TIOCPKT_NOSTOP = 0x10 TIOCPKT_START = 0x8 TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 TIOCREMOTE = 0x80047469 TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 TIOCSDTR = 0x20007479 TIOCSETA = 0x802c7414 TIOCSETAF = 0x802c7416 TIOCSETAW = 0x802c7415 TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f + TIOCSETVERAUTH = 0x8004741c + TIOCSFLAGS = 0x8004745c + TIOCSIG = 0x8004745f TIOCSPGRP = 0x80047476 TIOCSTART = 0x2000746e TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 TIOCSTOP = 0x2000746f + TIOCSTSTAMP = 0x8008745a TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40087459 TIOCUCNTL = 0x80047466 + TIOCUCNTL_CBRK = 0x7a + TIOCUCNTL_SBRK = 0x7b TOSTOP = 0x400000 + UTIME_NOW = -0x2 + UTIME_OMIT = -0x1 VDISCARD = 0xf VDSUSP = 0xb VEOF = 0x0 @@ -1450,36 +1592,33 @@ const ( VKILL = 0x5 VLNEXT = 0xe VMIN = 0x10 + VM_ANONMIN = 0x7 VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 + VM_MALLOC_CONF = 0xc + VM_MAXID = 0xd + VM_MAXSLP = 0xa VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 + VM_NKMEMPAGES = 0x6 + VM_PSSTRINGS = 0x3 + VM_SWAPENCRYPT = 0x5 + VM_USPACE = 0xb + VM_UVMEXP = 0x4 + VM_VNODEMIN = 0x9 + VM_VTEXTMIN = 0x8 VQUIT = 0x9 VREPRINT = 0x6 VSTART = 0xc VSTATUS = 0x12 VSTOP = 0xd VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 VTIME = 0x11 VWERASE = 0x4 - WCONTINUED = 0x10 + WALTSIG = 0x4 + WCONTINUED = 0x8 WCOREFLAG = 0x80 - WEXITED = 0x4 WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x20 - WSTOPPED = 0x8 WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + XCASE = 0x1000000 ) // Errors @@ -1492,21 +1631,17 @@ const ( EAGAIN = syscall.Errno(0x23) EALREADY = syscall.Errno(0x25) EAUTH = syscall.Errno(0x50) - EBADARCH = syscall.Errno(0x56) - EBADEXEC = syscall.Errno(0x55) EBADF = syscall.Errno(0x9) - EBADMACHO = syscall.Errno(0x58) - EBADMSG = syscall.Errno(0x5e) + EBADMSG = syscall.Errno(0x5c) EBADRPC = syscall.Errno(0x48) EBUSY = syscall.Errno(0x10) - ECANCELED = syscall.Errno(0x59) + ECANCELED = syscall.Errno(0x58) ECHILD = syscall.Errno(0xa) ECONNABORTED = syscall.Errno(0x35) ECONNREFUSED = syscall.Errno(0x3d) ECONNRESET = syscall.Errno(0x36) EDEADLK = syscall.Errno(0xb) EDESTADDRREQ = syscall.Errno(0x27) - EDEVERR = syscall.Errno(0x53) EDOM = syscall.Errno(0x21) EDQUOT = syscall.Errno(0x45) EEXIST = syscall.Errno(0x11) @@ -1515,54 +1650,51 @@ const ( EFTYPE = syscall.Errno(0x4f) EHOSTDOWN = syscall.Errno(0x40) EHOSTUNREACH = syscall.Errno(0x41) - EIDRM = syscall.Errno(0x5a) - EILSEQ = syscall.Errno(0x5c) + EIDRM = syscall.Errno(0x59) + EILSEQ = syscall.Errno(0x54) EINPROGRESS = syscall.Errno(0x24) EINTR = syscall.Errno(0x4) EINVAL = syscall.Errno(0x16) EIO = syscall.Errno(0x5) + EIPSEC = syscall.Errno(0x52) EISCONN = syscall.Errno(0x38) EISDIR = syscall.Errno(0x15) - ELAST = syscall.Errno(0x6a) + ELAST = syscall.Errno(0x5f) ELOOP = syscall.Errno(0x3e) + EMEDIUMTYPE = syscall.Errno(0x56) EMFILE = syscall.Errno(0x18) EMLINK = syscall.Errno(0x1f) EMSGSIZE = syscall.Errno(0x28) - EMULTIHOP = syscall.Errno(0x5f) ENAMETOOLONG = syscall.Errno(0x3f) ENEEDAUTH = syscall.Errno(0x51) ENETDOWN = syscall.Errno(0x32) ENETRESET = syscall.Errno(0x34) ENETUNREACH = syscall.Errno(0x33) ENFILE = syscall.Errno(0x17) - ENOATTR = syscall.Errno(0x5d) + ENOATTR = syscall.Errno(0x53) ENOBUFS = syscall.Errno(0x37) - ENODATA = syscall.Errno(0x60) ENODEV = syscall.Errno(0x13) ENOENT = syscall.Errno(0x2) ENOEXEC = syscall.Errno(0x8) ENOLCK = syscall.Errno(0x4d) - ENOLINK = syscall.Errno(0x61) + ENOMEDIUM = syscall.Errno(0x55) ENOMEM = syscall.Errno(0xc) - ENOMSG = syscall.Errno(0x5b) - ENOPOLICY = syscall.Errno(0x67) + ENOMSG = syscall.Errno(0x5a) ENOPROTOOPT = syscall.Errno(0x2a) ENOSPC = syscall.Errno(0x1c) - ENOSR = syscall.Errno(0x62) - ENOSTR = syscall.Errno(0x63) ENOSYS = syscall.Errno(0x4e) ENOTBLK = syscall.Errno(0xf) ENOTCONN = syscall.Errno(0x39) ENOTDIR = syscall.Errno(0x14) ENOTEMPTY = syscall.Errno(0x42) - ENOTRECOVERABLE = syscall.Errno(0x68) + ENOTRECOVERABLE = syscall.Errno(0x5d) ENOTSOCK = syscall.Errno(0x26) - ENOTSUP = syscall.Errno(0x2d) + ENOTSUP = syscall.Errno(0x5b) ENOTTY = syscall.Errno(0x19) ENXIO = syscall.Errno(0x6) - EOPNOTSUPP = syscall.Errno(0x66) - EOVERFLOW = syscall.Errno(0x54) - EOWNERDEAD = syscall.Errno(0x69) + EOPNOTSUPP = syscall.Errno(0x2d) + EOVERFLOW = syscall.Errno(0x57) + EOWNERDEAD = syscall.Errno(0x5e) EPERM = syscall.Errno(0x1) EPFNOSUPPORT = syscall.Errno(0x2e) EPIPE = syscall.Errno(0x20) @@ -1570,22 +1702,18 @@ const ( EPROCUNAVAIL = syscall.Errno(0x4c) EPROGMISMATCH = syscall.Errno(0x4b) EPROGUNAVAIL = syscall.Errno(0x4a) - EPROTO = syscall.Errno(0x64) + EPROTO = syscall.Errno(0x5f) EPROTONOSUPPORT = syscall.Errno(0x2b) EPROTOTYPE = syscall.Errno(0x29) - EPWROFF = syscall.Errno(0x52) - EQFULL = syscall.Errno(0x6a) ERANGE = syscall.Errno(0x22) EREMOTE = syscall.Errno(0x47) EROFS = syscall.Errno(0x1e) ERPCMISMATCH = syscall.Errno(0x49) - ESHLIBVERS = syscall.Errno(0x57) ESHUTDOWN = syscall.Errno(0x3a) ESOCKTNOSUPPORT = syscall.Errno(0x2c) ESPIPE = syscall.Errno(0x1d) ESRCH = syscall.Errno(0x3) ESTALE = syscall.Errno(0x46) - ETIME = syscall.Errno(0x65) ETIMEDOUT = syscall.Errno(0x3c) ETOOMANYREFS = syscall.Errno(0x3b) ETXTBSY = syscall.Errno(0x1a) @@ -1617,6 +1745,7 @@ const ( SIGSTOP = syscall.Signal(0x11) SIGSYS = syscall.Signal(0xc) SIGTERM = syscall.Signal(0xf) + SIGTHR = syscall.Signal(0x20) SIGTRAP = syscall.Signal(0x5) SIGTSTP = syscall.Signal(0x12) SIGTTIN = syscall.Signal(0x15) @@ -1651,7 +1780,7 @@ var errorList = [...]struct { {13, "EACCES", "permission denied"}, {14, "EFAULT", "bad address"}, {15, "ENOTBLK", "block device required"}, - {16, "EBUSY", "resource busy"}, + {16, "EBUSY", "device busy"}, {17, "EEXIST", "file exists"}, {18, "EXDEV", "cross-device link"}, {19, "ENODEV", "operation not supported by device"}, @@ -1680,7 +1809,7 @@ var errorList = [...]struct { {42, "ENOPROTOOPT", "protocol not available"}, {43, "EPROTONOSUPPORT", "protocol not supported"}, {44, "ESOCKTNOSUPPORT", "socket type not supported"}, - {45, "ENOTSUP", "operation not supported"}, + {45, "EOPNOTSUPP", "operation not supported"}, {46, "EPFNOSUPPORT", "protocol family not supported"}, {47, "EAFNOSUPPORT", "address family not supported by protocol family"}, {48, "EADDRINUSE", "address already in use"}, @@ -1704,12 +1833,12 @@ var errorList = [...]struct { {66, "ENOTEMPTY", "directory not empty"}, {67, "EPROCLIM", "too many processes"}, {68, "EUSERS", "too many users"}, - {69, "EDQUOT", "disc quota exceeded"}, + {69, "EDQUOT", "disk quota exceeded"}, {70, "ESTALE", "stale NFS file handle"}, {71, "EREMOTE", "too many levels of remote in path"}, {72, "EBADRPC", "RPC struct is bad"}, {73, "ERPCMISMATCH", "RPC version wrong"}, - {74, "EPROGUNAVAIL", "RPC prog. not avail"}, + {74, "EPROGUNAVAIL", "RPC program not available"}, {75, "EPROGMISMATCH", "program version wrong"}, {76, "EPROCUNAVAIL", "bad procedure for program"}, {77, "ENOLCK", "no locks available"}, @@ -1717,31 +1846,20 @@ var errorList = [...]struct { {79, "EFTYPE", "inappropriate file type or format"}, {80, "EAUTH", "authentication error"}, {81, "ENEEDAUTH", "need authenticator"}, - {82, "EPWROFF", "device power is off"}, - {83, "EDEVERR", "device error"}, - {84, "EOVERFLOW", "value too large to be stored in data type"}, - {85, "EBADEXEC", "bad executable (or shared library)"}, - {86, "EBADARCH", "bad CPU type in executable"}, - {87, "ESHLIBVERS", "shared library version mismatch"}, - {88, "EBADMACHO", "malformed Mach-o file"}, - {89, "ECANCELED", "operation canceled"}, - {90, "EIDRM", "identifier removed"}, - {91, "ENOMSG", "no message of desired type"}, - {92, "EILSEQ", "illegal byte sequence"}, - {93, "ENOATTR", "attribute not found"}, - {94, "EBADMSG", "bad message"}, - {95, "EMULTIHOP", "EMULTIHOP (Reserved)"}, - {96, "ENODATA", "no message available on STREAM"}, - {97, "ENOLINK", "ENOLINK (Reserved)"}, - {98, "ENOSR", "no STREAM resources"}, - {99, "ENOSTR", "not a STREAM"}, - {100, "EPROTO", "protocol error"}, - {101, "ETIME", "STREAM ioctl timeout"}, - {102, "EOPNOTSUPP", "operation not supported on socket"}, - {103, "ENOPOLICY", "policy not found"}, - {104, "ENOTRECOVERABLE", "state not recoverable"}, - {105, "EOWNERDEAD", "previous owner died"}, - {106, "EQFULL", "interface output queue is full"}, + {82, "EIPSEC", "IPsec processing failure"}, + {83, "ENOATTR", "attribute not found"}, + {84, "EILSEQ", "illegal byte sequence"}, + {85, "ENOMEDIUM", "no medium found"}, + {86, "EMEDIUMTYPE", "wrong medium type"}, + {87, "EOVERFLOW", "value too large to be stored in data type"}, + {88, "ECANCELED", "operation canceled"}, + {89, "EIDRM", "identifier removed"}, + {90, "ENOMSG", "no message of desired type"}, + {91, "ENOTSUP", "not supported"}, + {92, "EBADMSG", "bad message"}, + {93, "ENOTRECOVERABLE", "state not recoverable"}, + {94, "EOWNERDEAD", "previous owner died"}, + {95, "ELAST", "protocol error"}, } // Signal table @@ -1781,4 +1899,5 @@ var signalList = [...]struct { {29, "SIGINFO", "information request"}, {30, "SIGUSR1", "user defined signal 1"}, {31, "SIGUSR2", "user defined signal 2"}, + {32, "SIGTHR", "thread AST"}, } diff --git a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go index 46e054c..d2ddd31 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go @@ -1,7 +1,7 @@ // mkerrors.sh -m64 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,solaris +//go:build amd64 && solaris // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go @@ -192,6 +192,12 @@ const ( CSTOPB = 0x40 CSUSP = 0x1a CSWTCH = 0x1a + DIOC = 0x6400 + DIOCGETB = 0x6402 + DIOCGETC = 0x6401 + DIOCGETP = 0x6408 + DIOCSETE = 0x6403 + DIOCSETP = 0x6409 DLT_AIRONET_HEADER = 0x78 DLT_APPLE_IP_OVER_IEEE1394 = 0x8a DLT_ARCNET = 0x7 @@ -290,6 +296,7 @@ const ( FF0 = 0x0 FF1 = 0x8000 FFDLY = 0x8000 + FIORDCHK = 0x6603 FLUSHALL = 0x1 FLUSHDATA = 0x0 FLUSHO = 0x2000 @@ -358,6 +365,7 @@ const ( HUPCL = 0x400 IBSHIFT = 0x10 ICANON = 0x2 + ICMP6_FILTER = 0x1 ICRNL = 0x100 IEXTEN = 0x8000 IFF_ADDRCONF = 0x80000 @@ -604,6 +612,7 @@ const ( IP_RECVPKTINFO = 0x1a IP_RECVRETOPTS = 0x6 IP_RECVSLLA = 0xa + IP_RECVTOS = 0xc IP_RECVTTL = 0xb IP_RETOPTS = 0x8 IP_REUSEADDR = 0x104 @@ -645,6 +654,14 @@ const ( MAP_SHARED = 0x1 MAP_TEXT = 0x400 MAP_TYPE = 0xf + MCAST_BLOCK_SOURCE = 0x2b + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x29 + MCAST_JOIN_SOURCE_GROUP = 0x2d + MCAST_LEAVE_GROUP = 0x2a + MCAST_LEAVE_SOURCE_GROUP = 0x2e + MCAST_UNBLOCK_SOURCE = 0x2c MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MSG_CTRUNC = 0x10 @@ -653,6 +670,7 @@ const ( MSG_DUPCTRL = 0x800 MSG_EOR = 0x8 MSG_MAXIOVLEN = 0x10 + MSG_NOSIGNAL = 0x200 MSG_NOTIFICATION = 0x100 MSG_OOB = 0x1 MSG_PEEK = 0x2 @@ -687,6 +705,8 @@ const ( O_APPEND = 0x8 O_CLOEXEC = 0x800000 O_CREAT = 0x100 + O_DIRECT = 0x2000000 + O_DIRECTORY = 0x1000000 O_DSYNC = 0x40 O_EXCL = 0x400 O_EXEC = 0x400000 @@ -725,7 +745,7 @@ const ( RLIMIT_FSIZE = 0x1 RLIMIT_NOFILE = 0x5 RLIMIT_STACK = 0x3 - RLIM_INFINITY = -0x3 + RLIM_INFINITY = 0xfffffffffffffffd RTAX_AUTHOR = 0x6 RTAX_BRD = 0x7 RTAX_DST = 0x0 @@ -1047,6 +1067,7 @@ const ( TCOON = 0x1 TCP_ABORT_THRESHOLD = 0x11 TCP_ANONPRIVBIND = 0x20 + TCP_CONGESTION = 0x25 TCP_CONN_ABORT_THRESHOLD = 0x13 TCP_CONN_NOTIFY_THRESHOLD = 0x12 TCP_CORK = 0x18 @@ -1076,6 +1097,8 @@ const ( TCSETSF = 0x5410 TCSETSW = 0x540f TCXONC = 0x5406 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOC = 0x5400 TIOCCBRK = 0x747a TIOCCDTR = 0x7478 diff --git a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go new file mode 100644 index 0000000..1ec2b14 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go @@ -0,0 +1,990 @@ +// 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 + +// Hand edited based on zerrors_linux_s390x.go +// TODO: auto-generate. + +package unix + +const ( + BRKINT = 0x0001 + CLOCAL = 0x1 + CLOCK_MONOTONIC = 0x1 + CLOCK_PROCESS_CPUTIME_ID = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x3 + CLONE_NEWIPC = 0x08000000 + CLONE_NEWNET = 0x40000000 + CLONE_NEWNS = 0x00020000 + CLONE_NEWPID = 0x20000000 + CLONE_NEWUTS = 0x04000000 + CLONE_PARENT = 0x00008000 + CS8 = 0x0030 + CSIZE = 0x0030 + ECHO = 0x00000008 + ECHONL = 0x00000001 + EFD_SEMAPHORE = 0x00002000 + EFD_CLOEXEC = 0x00001000 + EFD_NONBLOCK = 0x00000004 + EPOLL_CLOEXEC = 0x00001000 + EPOLL_CTL_ADD = 0 + EPOLL_CTL_MOD = 1 + EPOLL_CTL_DEL = 2 + EPOLLRDNORM = 0x0001 + EPOLLRDBAND = 0x0002 + EPOLLIN = 0x0003 + EPOLLOUT = 0x0004 + EPOLLWRBAND = 0x0008 + EPOLLPRI = 0x0010 + EPOLLERR = 0x0020 + EPOLLHUP = 0x0040 + EPOLLEXCLUSIVE = 0x20000000 + EPOLLONESHOT = 0x40000000 + FD_CLOEXEC = 0x01 + FD_CLOFORK = 0x02 + FD_SETSIZE = 0x800 + FNDELAY = 0x04 + F_CLOSFD = 9 + F_CONTROL_CVT = 13 + F_DUPFD = 0 + F_DUPFD2 = 8 + F_GETFD = 1 + F_GETFL = 259 + F_GETLK = 5 + F_GETOWN = 10 + F_OK = 0x0 + F_RDLCK = 1 + F_SETFD = 2 + F_SETFL = 4 + F_SETLK = 6 + F_SETLKW = 7 + F_SETOWN = 11 + F_SETTAG = 12 + F_UNLCK = 3 + F_WRLCK = 2 + FSTYPE_ZFS = 0xe9 //"Z" + FSTYPE_HFS = 0xc8 //"H" + FSTYPE_NFS = 0xd5 //"N" + FSTYPE_TFS = 0xe3 //"T" + FSTYPE_AUTOMOUNT = 0xc1 //"A" + GRND_NONBLOCK = 1 + GRND_RANDOM = 2 + HUPCL = 0x0100 // Hang up on last close + IN_CLOEXEC = 0x00001000 + IN_NONBLOCK = 0x00000004 + IN_ACCESS = 0x00000001 + IN_MODIFY = 0x00000002 + IN_ATTRIB = 0x00000004 + IN_CLOSE_WRITE = 0x00000008 + IN_CLOSE_NOWRITE = 0x00000010 + IN_OPEN = 0x00000020 + IN_MOVED_FROM = 0x00000040 + IN_MOVED_TO = 0x00000080 + IN_CREATE = 0x00000100 + IN_DELETE = 0x00000200 + IN_DELETE_SELF = 0x00000400 + IN_MOVE_SELF = 0x00000800 + IN_UNMOUNT = 0x00002000 + IN_Q_OVERFLOW = 0x00004000 + IN_IGNORED = 0x00008000 + IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) + IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO) + IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | + IN_CLOSE | IN_OPEN | IN_MOVE | + IN_CREATE | IN_DELETE | IN_DELETE_SELF | + IN_MOVE_SELF) + IN_ONLYDIR = 0x01000000 + IN_DONT_FOLLOW = 0x02000000 + IN_EXCL_UNLINK = 0x04000000 + IN_MASK_CREATE = 0x10000000 + IN_MASK_ADD = 0x20000000 + IN_ISDIR = 0x40000000 + IN_ONESHOT = 0x80000000 + IP6F_MORE_FRAG = 0x0001 + IP6F_OFF_MASK = 0xfff8 + IP6F_RESERVED_MASK = 0x0006 + IP6OPT_JUMBO = 0xc2 + IP6OPT_JUMBO_LEN = 6 + IP6OPT_MUTABLE = 0x20 + IP6OPT_NSAP_ADDR = 0xc3 + IP6OPT_PAD1 = 0x00 + IP6OPT_PADN = 0x01 + IP6OPT_ROUTER_ALERT = 0x05 + IP6OPT_TUNNEL_LIMIT = 0x04 + IP6OPT_TYPE_DISCARD = 0x40 + IP6OPT_TYPE_FORCEICMP = 0x80 + IP6OPT_TYPE_ICMP = 0xc0 + IP6OPT_TYPE_SKIP = 0x00 + IP6_ALERT_AN = 0x0002 + IP6_ALERT_MLD = 0x0000 + IP6_ALERT_RSVP = 0x0001 + IPPORT_RESERVED = 1024 + IPPORT_USERRESERVED = 5000 + IPPROTO_AH = 51 + SOL_AH = 51 + IPPROTO_DSTOPTS = 60 + SOL_DSTOPTS = 60 + IPPROTO_EGP = 8 + SOL_EGP = 8 + IPPROTO_ESP = 50 + SOL_ESP = 50 + IPPROTO_FRAGMENT = 44 + SOL_FRAGMENT = 44 + IPPROTO_GGP = 2 + SOL_GGP = 2 + IPPROTO_HOPOPTS = 0 + SOL_HOPOPTS = 0 + IPPROTO_ICMP = 1 + SOL_ICMP = 1 + IPPROTO_ICMPV6 = 58 + SOL_ICMPV6 = 58 + IPPROTO_IDP = 22 + SOL_IDP = 22 + IPPROTO_IP = 0 + SOL_IP = 0 + IPPROTO_IPV6 = 41 + SOL_IPV6 = 41 + IPPROTO_MAX = 256 + SOL_MAX = 256 + IPPROTO_NONE = 59 + SOL_NONE = 59 + IPPROTO_PUP = 12 + SOL_PUP = 12 + IPPROTO_RAW = 255 + SOL_RAW = 255 + IPPROTO_ROUTING = 43 + SOL_ROUTING = 43 + IPPROTO_TCP = 6 + SOL_TCP = 6 + IPPROTO_UDP = 17 + SOL_UDP = 17 + IPV6_ADDR_PREFERENCES = 32 + IPV6_CHECKSUM = 19 + IPV6_DONTFRAG = 29 + IPV6_DSTOPTS = 23 + IPV6_HOPLIMIT = 11 + IPV6_HOPOPTS = 22 + IPV6_JOIN_GROUP = 5 + IPV6_LEAVE_GROUP = 6 + IPV6_MULTICAST_HOPS = 9 + IPV6_MULTICAST_IF = 7 + IPV6_MULTICAST_LOOP = 4 + IPV6_NEXTHOP = 20 + IPV6_PATHMTU = 12 + IPV6_PKTINFO = 13 + IPV6_PREFER_SRC_CGA = 0x10 + IPV6_PREFER_SRC_COA = 0x02 + IPV6_PREFER_SRC_HOME = 0x01 + IPV6_PREFER_SRC_NONCGA = 0x20 + IPV6_PREFER_SRC_PUBLIC = 0x08 + IPV6_PREFER_SRC_TMP = 0x04 + IPV6_RECVDSTOPTS = 28 + IPV6_RECVHOPLIMIT = 14 + IPV6_RECVHOPOPTS = 26 + IPV6_RECVPATHMTU = 16 + IPV6_RECVPKTINFO = 15 + IPV6_RECVRTHDR = 25 + IPV6_RECVTCLASS = 31 + IPV6_RTHDR = 21 + IPV6_RTHDRDSTOPTS = 24 + IPV6_RTHDR_TYPE_0 = 0 + IPV6_TCLASS = 30 + IPV6_UNICAST_HOPS = 3 + IPV6_USE_MIN_MTU = 18 + IPV6_V6ONLY = 10 + IP_ADD_MEMBERSHIP = 5 + IP_ADD_SOURCE_MEMBERSHIP = 12 + IP_BLOCK_SOURCE = 10 + IP_DEFAULT_MULTICAST_LOOP = 1 + IP_DEFAULT_MULTICAST_TTL = 1 + IP_DROP_MEMBERSHIP = 6 + IP_DROP_SOURCE_MEMBERSHIP = 13 + IP_MAX_MEMBERSHIPS = 20 + IP_MULTICAST_IF = 7 + IP_MULTICAST_LOOP = 4 + IP_MULTICAST_TTL = 3 + IP_OPTIONS = 1 + IP_PKTINFO = 101 + IP_RECVPKTINFO = 102 + IP_TOS = 2 + IP_TTL = 14 + IP_UNBLOCK_SOURCE = 11 + ICMP6_FILTER = 1 + MCAST_INCLUDE = 0 + MCAST_EXCLUDE = 1 + MCAST_JOIN_GROUP = 40 + MCAST_LEAVE_GROUP = 41 + MCAST_JOIN_SOURCE_GROUP = 42 + MCAST_LEAVE_SOURCE_GROUP = 43 + MCAST_BLOCK_SOURCE = 44 + MCAST_UNBLOCK_SOURCE = 46 + ICANON = 0x0010 + ICRNL = 0x0002 + IEXTEN = 0x0020 + IGNBRK = 0x0004 + IGNCR = 0x0008 + INLCR = 0x0020 + ISIG = 0x0040 + ISTRIP = 0x0080 + IXON = 0x0200 + IXOFF = 0x0100 + LOCK_SH = 0x1 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_UN = 0x8 + POLLIN = 0x0003 + POLLOUT = 0x0004 + POLLPRI = 0x0010 + POLLERR = 0x0020 + POLLHUP = 0x0040 + POLLNVAL = 0x0080 + PROT_READ = 0x1 // mmap - page can be read + PROT_WRITE = 0x2 // page can be written + PROT_NONE = 0x4 // can't be accessed + PROT_EXEC = 0x8 // can be executed + MAP_PRIVATE = 0x1 // changes are private + MAP_SHARED = 0x2 // changes are shared + MAP_FIXED = 0x4 // place exactly + __MAP_MEGA = 0x8 + __MAP_64 = 0x10 + MAP_ANON = 0x20 + MAP_ANONYMOUS = 0x20 + MS_SYNC = 0x1 // msync - synchronous writes + MS_ASYNC = 0x2 // asynchronous writes + MS_INVALIDATE = 0x4 // invalidate mappings + MS_BIND = 0x00001000 + MS_MOVE = 0x00002000 + MS_NOSUID = 0x00000002 + MS_PRIVATE = 0x00040000 + MS_REC = 0x00004000 + MS_REMOUNT = 0x00008000 + MS_RDONLY = 0x00000001 + MS_UNBINDABLE = 0x00020000 + MNT_DETACH = 0x00000004 + ZOSDSFS_SUPER_MAGIC = 0x44534653 // zOS DSFS + NFS_SUPER_MAGIC = 0x6969 // NFS + NSFS_MAGIC = 0x6e736673 // PROCNS + PROC_SUPER_MAGIC = 0x9fa0 // proc FS + ZOSTFS_SUPER_MAGIC = 0x544653 // zOS TFS + ZOSUFS_SUPER_MAGIC = 0x554653 // zOS UFS + ZOSZFS_SUPER_MAGIC = 0x5A4653 // zOS ZFS + MTM_RDONLY = 0x80000000 + MTM_RDWR = 0x40000000 + MTM_UMOUNT = 0x10000000 + MTM_IMMED = 0x08000000 + MTM_FORCE = 0x04000000 + MTM_DRAIN = 0x02000000 + MTM_RESET = 0x01000000 + MTM_SAMEMODE = 0x00100000 + MTM_UNQSEFORCE = 0x00040000 + MTM_NOSUID = 0x00000400 + MTM_SYNCHONLY = 0x00000200 + MTM_REMOUNT = 0x00000100 + MTM_NOSECURITY = 0x00000080 + NFDBITS = 0x20 + ONLRET = 0x0020 // NL performs CR function + O_ACCMODE = 0x03 + O_APPEND = 0x08 + O_ASYNCSIG = 0x0200 + O_CREAT = 0x80 + O_DIRECT = 0x00002000 + O_NOFOLLOW = 0x00004000 + O_DIRECTORY = 0x00008000 + O_PATH = 0x00080000 + O_CLOEXEC = 0x00001000 + O_EXCL = 0x40 + O_GETFL = 0x0F + O_LARGEFILE = 0x0400 + O_NDELAY = 0x4 + O_NONBLOCK = 0x04 + O_RDONLY = 0x02 + O_RDWR = 0x03 + O_SYNC = 0x0100 + O_TRUNC = 0x10 + O_WRONLY = 0x01 + O_NOCTTY = 0x20 + OPOST = 0x0001 + ONLCR = 0x0004 + PARENB = 0x0200 + PARMRK = 0x0400 + QUERYCVT = 3 + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 // RUSAGE_THREAD unsupported on z/OS + SEEK_CUR = 1 + SEEK_END = 2 + SEEK_SET = 0 + SETAUTOCVTALL = 5 + SETAUTOCVTON = 2 + SETCVTALL = 4 + SETCVTOFF = 0 + SETCVTON = 1 + AF_APPLETALK = 16 + AF_CCITT = 10 + AF_CHAOS = 5 + AF_DATAKIT = 9 + AF_DLI = 13 + AF_ECMA = 8 + AF_HYLINK = 15 + AF_IMPLINK = 3 + AF_INET = 2 + AF_INET6 = 19 + AF_INTF = 20 + AF_IUCV = 17 + AF_LAT = 14 + AF_LINK = 18 + AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX + AF_MAX = 30 + AF_NBS = 7 + AF_NDD = 23 + AF_NETWARE = 22 + AF_NS = 6 + AF_PUP = 4 + AF_RIF = 21 + AF_ROUTE = 20 + AF_SNA = 11 + AF_UNIX = 1 + AF_UNSPEC = 0 + IBMTCP_IMAGE = 1 + MSG_ACK_EXPECTED = 0x10 + MSG_ACK_GEN = 0x40 + MSG_ACK_TIMEOUT = 0x20 + MSG_CONNTERM = 0x80 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_EOF = 0x8000 + MSG_EOR = 0x8 + MSG_MAXIOVLEN = 16 + MSG_NONBLOCK = 0x4000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + PRIO_PROCESS = 1 + PRIO_PGRP = 2 + PRIO_USER = 3 + RLIMIT_CPU = 0 + RLIMIT_FSIZE = 1 + RLIMIT_DATA = 2 + RLIMIT_STACK = 3 + RLIMIT_CORE = 4 + RLIMIT_AS = 5 + RLIMIT_NOFILE = 6 + RLIMIT_MEMLIMIT = 7 + RLIMIT_MEMLOCK = 0x8 + RLIM_INFINITY = 2147483647 + SCHED_FIFO = 0x2 + SCM_CREDENTIALS = 0x2 + SCM_RIGHTS = 0x01 + SF_CLOSE = 0x00000002 + SF_REUSE = 0x00000001 + SHM_RND = 0x2 + SHM_RDONLY = 0x1 + SHMLBA = 0x1000 + IPC_STAT = 0x3 + IPC_SET = 0x2 + IPC_RMID = 0x1 + IPC_PRIVATE = 0x0 + IPC_CREAT = 0x1000000 + __IPC_MEGA = 0x4000000 + __IPC_SHAREAS = 0x20000000 + __IPC_BELOWBAR = 0x10000000 + IPC_EXCL = 0x2000000 + __IPC_GIGA = 0x8000000 + SHUT_RD = 0 + SHUT_RDWR = 2 + SHUT_WR = 1 + SOCK_CLOEXEC = 0x00001000 + SOCK_CONN_DGRAM = 6 + SOCK_DGRAM = 2 + SOCK_NONBLOCK = 0x800 + SOCK_RAW = 3 + SOCK_RDM = 4 + SOCK_SEQPACKET = 5 + SOCK_STREAM = 1 + SOL_SOCKET = 0xffff + SOMAXCONN = 10 + SO_ACCEPTCONN = 0x0002 + SO_ACCEPTECONNABORTED = 0x0006 + SO_ACKNOW = 0x7700 + SO_BROADCAST = 0x0020 + SO_BULKMODE = 0x8000 + SO_CKSUMRECV = 0x0800 + SO_CLOSE = 0x01 + SO_CLUSTERCONNTYPE = 0x00004001 + SO_CLUSTERCONNTYPE_INTERNAL = 8 + SO_CLUSTERCONNTYPE_NOCONN = 0 + SO_CLUSTERCONNTYPE_NONE = 1 + SO_CLUSTERCONNTYPE_SAME_CLUSTER = 2 + SO_CLUSTERCONNTYPE_SAME_IMAGE = 4 + SO_DEBUG = 0x0001 + SO_DONTROUTE = 0x0010 + SO_ERROR = 0x1007 + SO_IGNOREINCOMINGPUSH = 0x1 + SO_IGNORESOURCEVIPA = 0x0002 + SO_KEEPALIVE = 0x0008 + SO_LINGER = 0x0080 + SO_NONBLOCKLOCAL = 0x8001 + SO_NOREUSEADDR = 0x1000 + SO_OOBINLINE = 0x0100 + SO_OPTACK = 0x8004 + SO_OPTMSS = 0x8003 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x0004 + SO_REUSEPORT = 0x0200 + SO_SECINFO = 0x00004002 + SO_SET = 0x0200 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TYPE = 0x1008 + SO_UNSET = 0x0400 + SO_USELOOPBACK = 0x0040 + SO_USE_IFBUFS = 0x0400 + S_ISUID = 0x0800 + S_ISGID = 0x0400 + S_ISVTX = 0x0200 + S_IRUSR = 0x0100 + S_IWUSR = 0x0080 + S_IXUSR = 0x0040 + S_IRWXU = 0x01C0 + S_IRGRP = 0x0020 + S_IWGRP = 0x0010 + S_IXGRP = 0x0008 + S_IRWXG = 0x0038 + S_IROTH = 0x0004 + S_IWOTH = 0x0002 + S_IXOTH = 0x0001 + S_IRWXO = 0x0007 + S_IREAD = S_IRUSR + S_IWRITE = S_IWUSR + S_IEXEC = S_IXUSR + S_IFDIR = 0x01000000 + S_IFCHR = 0x02000000 + S_IFREG = 0x03000000 + S_IFFIFO = 0x04000000 + S_IFIFO = 0x04000000 + S_IFLNK = 0x05000000 + S_IFBLK = 0x06000000 + S_IFSOCK = 0x07000000 + S_IFVMEXTL = 0xFE000000 + S_IFVMEXTL_EXEC = 0x00010000 + S_IFVMEXTL_DATA = 0x00020000 + S_IFVMEXTL_MEL = 0x00030000 + S_IFEXTL = 0x00000001 + S_IFPROGCTL = 0x00000002 + S_IFAPFCTL = 0x00000004 + S_IFNOSHARE = 0x00000008 + S_IFSHARELIB = 0x00000010 + S_IFMT = 0xFF000000 + S_IFMST = 0x00FF0000 + TCP_KEEPALIVE = 0x8 + TCP_NODELAY = 0x1 + TIOCGWINSZ = 0x4008a368 + TIOCSWINSZ = 0x8008a367 + TIOCSBRK = 0x2000a77b + TIOCCBRK = 0x2000a77a + TIOCSTI = 0x8001a772 + TIOCGPGRP = 0x4004a777 // _IOR(167, 119, int) + TCSANOW = 0 + TCSETS = 0 // equivalent to TCSANOW for tcsetattr + TCSADRAIN = 1 + TCSETSW = 1 // equivalent to TCSADRAIN for tcsetattr + TCSAFLUSH = 2 + TCSETSF = 2 // equivalent to TCSAFLUSH for tcsetattr + TCGETS = 3 // not defined in ioctl.h -- zos golang only + TCIFLUSH = 0 + TCOFLUSH = 1 + TCIOFLUSH = 2 + TCOOFF = 0 + TCOON = 1 + TCIOFF = 2 + TCION = 3 + TIOCSPGRP = 0x8004a776 + TIOCNOTTY = 0x2000a771 + TIOCEXCL = 0x2000a70d + TIOCNXCL = 0x2000a70e + TIOCGETD = 0x4004a700 + TIOCSETD = 0x8004a701 + TIOCPKT = 0x8004a770 + TIOCSTOP = 0x2000a76f + TIOCSTART = 0x2000a76e + TIOCUCNTL = 0x8004a766 + TIOCREMOTE = 0x8004a769 + TIOCMGET = 0x4004a76a + TIOCMSET = 0x8004a76d + TIOCMBIC = 0x8004a76b + TIOCMBIS = 0x8004a76c + VINTR = 0 + VQUIT = 1 + VERASE = 2 + VKILL = 3 + VEOF = 4 + VEOL = 5 + VMIN = 6 + VSTART = 7 + VSTOP = 8 + VSUSP = 9 + VTIME = 10 + WCONTINUED = 0x4 + WEXITED = 0x8 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WSTOPPED = 0x10 + WUNTRACED = 0x2 + _BPX_SWAP = 1 + _BPX_NONSWAP = 2 + MCL_CURRENT = 1 // for Linux compatibility -- no zos semantics + MCL_FUTURE = 2 // for Linux compatibility -- no zos semantics + MCL_ONFAULT = 3 // for Linux compatibility -- no zos semantics + MADV_NORMAL = 0 // for Linux compatibility -- no zos semantics + MADV_RANDOM = 1 // for Linux compatibility -- no zos semantics + MADV_SEQUENTIAL = 2 // for Linux compatibility -- no zos semantics + MADV_WILLNEED = 3 // for Linux compatibility -- no zos semantics + MADV_REMOVE = 4 // for Linux compatibility -- no zos semantics + MADV_DONTFORK = 5 // for Linux compatibility -- no zos semantics + MADV_DOFORK = 6 // for Linux compatibility -- no zos semantics + MADV_HWPOISON = 7 // for Linux compatibility -- no zos semantics + MADV_MERGEABLE = 8 // for Linux compatibility -- no zos semantics + MADV_UNMERGEABLE = 9 // for Linux compatibility -- no zos semantics + MADV_SOFT_OFFLINE = 10 // for Linux compatibility -- no zos semantics + MADV_HUGEPAGE = 11 // for Linux compatibility -- no zos semantics + MADV_NOHUGEPAGE = 12 // for Linux compatibility -- no zos semantics + MADV_DONTDUMP = 13 // for Linux compatibility -- no zos semantics + MADV_DODUMP = 14 // for Linux compatibility -- no zos semantics + MADV_FREE = 15 // for Linux compatibility -- no zos semantics + MADV_WIPEONFORK = 16 // for Linux compatibility -- no zos semantics + MADV_KEEPONFORK = 17 // for Linux compatibility -- no zos semantics + AT_SYMLINK_FOLLOW = 0x400 + AT_SYMLINK_NOFOLLOW = 0x100 + XATTR_CREATE = 0x1 + XATTR_REPLACE = 0x2 + P_PID = 0 + P_PGID = 1 + P_ALL = 2 + PR_SET_NAME = 15 + PR_GET_NAME = 16 + PR_SET_NO_NEW_PRIVS = 38 + PR_GET_NO_NEW_PRIVS = 39 + PR_SET_DUMPABLE = 4 + PR_GET_DUMPABLE = 3 + PR_SET_PDEATHSIG = 1 + PR_GET_PDEATHSIG = 2 + PR_SET_CHILD_SUBREAPER = 36 + PR_GET_CHILD_SUBREAPER = 37 + AT_FDCWD = -100 + AT_EACCESS = 0x200 + AT_EMPTY_PATH = 0x1000 + AT_REMOVEDIR = 0x200 + RENAME_NOREPLACE = 1 << 0 + ST_RDONLY = 1 + ST_NOSUID = 2 +) + +const ( + EDOM = Errno(1) + ERANGE = Errno(2) + EACCES = Errno(111) + EAGAIN = Errno(112) + EBADF = Errno(113) + EBUSY = Errno(114) + ECHILD = Errno(115) + EDEADLK = Errno(116) + EEXIST = Errno(117) + EFAULT = Errno(118) + EFBIG = Errno(119) + EINTR = Errno(120) + EINVAL = Errno(121) + EIO = Errno(122) + EISDIR = Errno(123) + EMFILE = Errno(124) + EMLINK = Errno(125) + ENAMETOOLONG = Errno(126) + ENFILE = Errno(127) + ENOATTR = Errno(265) + ENODEV = Errno(128) + ENOENT = Errno(129) + ENOEXEC = Errno(130) + ENOLCK = Errno(131) + ENOMEM = Errno(132) + ENOSPC = Errno(133) + ENOSYS = Errno(134) + ENOTDIR = Errno(135) + ENOTEMPTY = Errno(136) + ENOTTY = Errno(137) + ENXIO = Errno(138) + EPERM = Errno(139) + EPIPE = Errno(140) + EROFS = Errno(141) + ESPIPE = Errno(142) + ESRCH = Errno(143) + EXDEV = Errno(144) + E2BIG = Errno(145) + ELOOP = Errno(146) + EILSEQ = Errno(147) + ENODATA = Errno(148) + EOVERFLOW = Errno(149) + EMVSNOTUP = Errno(150) + ECMSSTORAGE = Errno(151) + EMVSDYNALC = Errno(151) + EMVSCVAF = Errno(152) + EMVSCATLG = Errno(153) + ECMSINITIAL = Errno(156) + EMVSINITIAL = Errno(156) + ECMSERR = Errno(157) + EMVSERR = Errno(157) + EMVSPARM = Errno(158) + ECMSPFSFILE = Errno(159) + EMVSPFSFILE = Errno(159) + EMVSBADCHAR = Errno(160) + ECMSPFSPERM = Errno(162) + EMVSPFSPERM = Errno(162) + EMVSSAFEXTRERR = Errno(163) + EMVSSAF2ERR = Errno(164) + EMVSTODNOTSET = Errno(165) + EMVSPATHOPTS = Errno(166) + EMVSNORTL = Errno(167) + EMVSEXPIRE = Errno(168) + EMVSPASSWORD = Errno(169) + EMVSWLMERROR = Errno(170) + EMVSCPLERROR = Errno(171) + EMVSARMERROR = Errno(172) + ELENOFORK = Errno(200) + ELEMSGERR = Errno(201) + EFPMASKINV = Errno(202) + EFPMODEINV = Errno(203) + EBUFLEN = Errno(227) + EEXTLINK = Errno(228) + ENODD = Errno(229) + ECMSESMERR = Errno(230) + ECPERR = Errno(231) + ELEMULTITHREAD = Errno(232) + ELEFENCE = Errno(244) + EBADDATA = Errno(245) + EUNKNOWN = Errno(246) + ENOTSUP = Errno(247) + EBADNAME = Errno(248) + ENOTSAFE = Errno(249) + ELEMULTITHREADFORK = Errno(257) + ECUNNOENV = Errno(258) + ECUNNOCONV = Errno(259) + ECUNNOTALIGNED = Errno(260) + ECUNERR = Errno(262) + EIBMBADCALL = Errno(1000) + EIBMBADPARM = Errno(1001) + EIBMSOCKOUTOFRANGE = Errno(1002) + EIBMSOCKINUSE = Errno(1003) + EIBMIUCVERR = Errno(1004) + EOFFLOADboxERROR = Errno(1005) + EOFFLOADboxRESTART = Errno(1006) + EOFFLOADboxDOWN = Errno(1007) + EIBMCONFLICT = Errno(1008) + EIBMCANCELLED = Errno(1009) + EIBMBADTCPNAME = Errno(1011) + ENOTBLK = Errno(1100) + ETXTBSY = Errno(1101) + EWOULDBLOCK = Errno(1102) + EINPROGRESS = Errno(1103) + EALREADY = Errno(1104) + ENOTSOCK = Errno(1105) + EDESTADDRREQ = Errno(1106) + EMSGSIZE = Errno(1107) + EPROTOTYPE = Errno(1108) + ENOPROTOOPT = Errno(1109) + EPROTONOSUPPORT = Errno(1110) + ESOCKTNOSUPPORT = Errno(1111) + EOPNOTSUPP = Errno(1112) + EPFNOSUPPORT = Errno(1113) + EAFNOSUPPORT = Errno(1114) + EADDRINUSE = Errno(1115) + EADDRNOTAVAIL = Errno(1116) + ENETDOWN = Errno(1117) + ENETUNREACH = Errno(1118) + ENETRESET = Errno(1119) + ECONNABORTED = Errno(1120) + ECONNRESET = Errno(1121) + ENOBUFS = Errno(1122) + EISCONN = Errno(1123) + ENOTCONN = Errno(1124) + ESHUTDOWN = Errno(1125) + ETOOMANYREFS = Errno(1126) + ETIMEDOUT = Errno(1127) + ECONNREFUSED = Errno(1128) + EHOSTDOWN = Errno(1129) + EHOSTUNREACH = Errno(1130) + EPROCLIM = Errno(1131) + EUSERS = Errno(1132) + EDQUOT = Errno(1133) + ESTALE = Errno(1134) + EREMOTE = Errno(1135) + ENOSTR = Errno(1136) + ETIME = Errno(1137) + ENOSR = Errno(1138) + ENOMSG = Errno(1139) + EBADMSG = Errno(1140) + EIDRM = Errno(1141) + ENONET = Errno(1142) + ERREMOTE = Errno(1143) + ENOLINK = Errno(1144) + EADV = Errno(1145) + ESRMNT = Errno(1146) + ECOMM = Errno(1147) + EPROTO = Errno(1148) + EMULTIHOP = Errno(1149) + EDOTDOT = Errno(1150) + EREMCHG = Errno(1151) + ECANCELED = Errno(1152) + EINTRNODATA = Errno(1159) + ENOREUSE = Errno(1160) + ENOMOVE = Errno(1161) +) + +// Signals +const ( + SIGHUP = Signal(1) + SIGINT = Signal(2) + SIGABRT = Signal(3) + SIGILL = Signal(4) + SIGPOLL = Signal(5) + SIGURG = Signal(6) + SIGSTOP = Signal(7) + SIGFPE = Signal(8) + SIGKILL = Signal(9) + SIGBUS = Signal(10) + SIGSEGV = Signal(11) + SIGSYS = Signal(12) + SIGPIPE = Signal(13) + SIGALRM = Signal(14) + SIGTERM = Signal(15) + SIGUSR1 = Signal(16) + SIGUSR2 = Signal(17) + SIGABND = Signal(18) + SIGCONT = Signal(19) + SIGCHLD = Signal(20) + SIGTTIN = Signal(21) + SIGTTOU = Signal(22) + SIGIO = Signal(23) + SIGQUIT = Signal(24) + SIGTSTP = Signal(25) + SIGTRAP = Signal(26) + SIGIOERR = Signal(27) + SIGWINCH = Signal(28) + SIGXCPU = Signal(29) + SIGXFSZ = Signal(30) + SIGVTALRM = Signal(31) + SIGPROF = Signal(32) + SIGDANGER = Signal(33) + SIGTHSTOP = Signal(34) + SIGTHCONT = Signal(35) + SIGTRACE = Signal(37) + SIGDCE = Signal(38) + SIGDUMP = Signal(39) +) + +// Error table +var errorList = [...]struct { + num Errno + name string + desc string +}{ + {1, "EDC5001I", "A domain error occurred."}, + {2, "EDC5002I", "A range error occurred."}, + {111, "EDC5111I", "Permission denied."}, + {112, "EDC5112I", "Resource temporarily unavailable."}, + {113, "EDC5113I", "Bad file descriptor."}, + {114, "EDC5114I", "Resource busy."}, + {115, "EDC5115I", "No child processes."}, + {116, "EDC5116I", "Resource deadlock avoided."}, + {117, "EDC5117I", "File exists."}, + {118, "EDC5118I", "Incorrect address."}, + {119, "EDC5119I", "File too large."}, + {120, "EDC5120I", "Interrupted function call."}, + {121, "EDC5121I", "Invalid argument."}, + {122, "EDC5122I", "Input/output error."}, + {123, "EDC5123I", "Is a directory."}, + {124, "EDC5124I", "Too many open files."}, + {125, "EDC5125I", "Too many links."}, + {126, "EDC5126I", "Filename too long."}, + {127, "EDC5127I", "Too many open files in system."}, + {128, "EDC5128I", "No such device."}, + {129, "EDC5129I", "No such file or directory."}, + {130, "EDC5130I", "Exec format error."}, + {131, "EDC5131I", "No locks available."}, + {132, "EDC5132I", "Not enough memory."}, + {133, "EDC5133I", "No space left on device."}, + {134, "EDC5134I", "Function not implemented."}, + {135, "EDC5135I", "Not a directory."}, + {136, "EDC5136I", "Directory not empty."}, + {137, "EDC5137I", "Inappropriate I/O control operation."}, + {138, "EDC5138I", "No such device or address."}, + {139, "EDC5139I", "Operation not permitted."}, + {140, "EDC5140I", "Broken pipe."}, + {141, "EDC5141I", "Read-only file system."}, + {142, "EDC5142I", "Invalid seek."}, + {143, "EDC5143I", "No such process."}, + {144, "EDC5144I", "Improper link."}, + {145, "EDC5145I", "The parameter list is too long, or the message to receive was too large for the buffer."}, + {146, "EDC5146I", "Too many levels of symbolic links."}, + {147, "EDC5147I", "Illegal byte sequence."}, + {148, "EDC5148I", "The named attribute or data not available."}, + {149, "EDC5149I", "Value Overflow Error."}, + {150, "EDC5150I", "UNIX System Services is not active."}, + {151, "EDC5151I", "Dynamic allocation error."}, + {152, "EDC5152I", "Common VTOC access facility (CVAF) error."}, + {153, "EDC5153I", "Catalog obtain error."}, + {156, "EDC5156I", "Process initialization error."}, + {157, "EDC5157I", "An internal error has occurred."}, + {158, "EDC5158I", "Bad parameters were passed to the service."}, + {159, "EDC5159I", "The Physical File System encountered a permanent file error."}, + {160, "EDC5160I", "Bad character in environment variable name."}, + {162, "EDC5162I", "The Physical File System encountered a system error."}, + {163, "EDC5163I", "SAF/RACF extract error."}, + {164, "EDC5164I", "SAF/RACF error."}, + {165, "EDC5165I", "System TOD clock not set."}, + {166, "EDC5166I", "Access mode argument on function call conflicts with PATHOPTS parameter on JCL DD statement."}, + {167, "EDC5167I", "Access to the UNIX System Services version of the C RTL is denied."}, + {168, "EDC5168I", "Password has expired."}, + {169, "EDC5169I", "Password is invalid."}, + {170, "EDC5170I", "An error was encountered with WLM."}, + {171, "EDC5171I", "An error was encountered with CPL."}, + {172, "EDC5172I", "An error was encountered with Application Response Measurement (ARM) component."}, + {200, "EDC5200I", "The application contains a Language Environment member language that cannot tolerate a fork()."}, + {201, "EDC5201I", "The Language Environment message file was not found in the hierarchical file system."}, + {202, "EDC5202E", "DLL facilities are not supported under SPC environment."}, + {203, "EDC5203E", "DLL facilities are not supported under POSIX environment."}, + {227, "EDC5227I", "Buffer is not long enough to contain a path definition"}, + {228, "EDC5228I", "The file referred to is an external link"}, + {229, "EDC5229I", "No path definition for ddname in effect"}, + {230, "EDC5230I", "ESM error."}, + {231, "EDC5231I", "CP or the external security manager had an error"}, + {232, "EDC5232I", "The function failed because it was invoked from a multithread environment."}, + {244, "EDC5244I", "The program, module or DLL is not supported in this environment."}, + {245, "EDC5245I", "Data is not valid."}, + {246, "EDC5246I", "Unknown system state."}, + {247, "EDC5247I", "Operation not supported."}, + {248, "EDC5248I", "The object name specified is not correct."}, + {249, "EDC5249I", "The function is not allowed."}, + {257, "EDC5257I", "Function cannot be called in the child process of a fork() from a multithreaded process until exec() is called."}, + {258, "EDC5258I", "A CUN_RS_NO_UNI_ENV error was issued by Unicode Services."}, + {259, "EDC5259I", "A CUN_RS_NO_CONVERSION error was issued by Unicode Services."}, + {260, "EDC5260I", "A CUN_RS_TABLE_NOT_ALIGNED error was issued by Unicode Services."}, + {262, "EDC5262I", "An iconv() function encountered an unexpected error while using Unicode Services."}, + {265, "EDC5265I", "The named attribute not available."}, + {1000, "EDC8000I", "A bad socket-call constant was found in the IUCV header."}, + {1001, "EDC8001I", "An error was found in the IUCV header."}, + {1002, "EDC8002I", "A socket descriptor is out of range."}, + {1003, "EDC8003I", "A socket descriptor is in use."}, + {1004, "EDC8004I", "Request failed because of an IUCV error."}, + {1005, "EDC8005I", "Offload box error."}, + {1006, "EDC8006I", "Offload box restarted."}, + {1007, "EDC8007I", "Offload box down."}, + {1008, "EDC8008I", "Already a conflicting call outstanding on socket."}, + {1009, "EDC8009I", "Request cancelled using a SOCKcallCANCEL request."}, + {1011, "EDC8011I", "A name of a PFS was specified that either is not configured or is not a Sockets PFS."}, + {1100, "EDC8100I", "Block device required."}, + {1101, "EDC8101I", "Text file busy."}, + {1102, "EDC8102I", "Operation would block."}, + {1103, "EDC8103I", "Operation now in progress."}, + {1104, "EDC8104I", "Connection already in progress."}, + {1105, "EDC8105I", "Socket operation on non-socket."}, + {1106, "EDC8106I", "Destination address required."}, + {1107, "EDC8107I", "Message too long."}, + {1108, "EDC8108I", "Protocol wrong type for socket."}, + {1109, "EDC8109I", "Protocol not available."}, + {1110, "EDC8110I", "Protocol not supported."}, + {1111, "EDC8111I", "Socket type not supported."}, + {1112, "EDC8112I", "Operation not supported on socket."}, + {1113, "EDC8113I", "Protocol family not supported."}, + {1114, "EDC8114I", "Address family not supported."}, + {1115, "EDC8115I", "Address already in use."}, + {1116, "EDC8116I", "Address not available."}, + {1117, "EDC8117I", "Network is down."}, + {1118, "EDC8118I", "Network is unreachable."}, + {1119, "EDC8119I", "Network dropped connection on reset."}, + {1120, "EDC8120I", "Connection ended abnormally."}, + {1121, "EDC8121I", "Connection reset."}, + {1122, "EDC8122I", "No buffer space available."}, + {1123, "EDC8123I", "Socket already connected."}, + {1124, "EDC8124I", "Socket not connected."}, + {1125, "EDC8125I", "Can't send after socket shutdown."}, + {1126, "EDC8126I", "Too many references; can't splice."}, + {1127, "EDC8127I", "Connection timed out."}, + {1128, "EDC8128I", "Connection refused."}, + {1129, "EDC8129I", "Host is not available."}, + {1130, "EDC8130I", "Host cannot be reached."}, + {1131, "EDC8131I", "Too many processes."}, + {1132, "EDC8132I", "Too many users."}, + {1133, "EDC8133I", "Disk quota exceeded."}, + {1134, "EDC8134I", "Stale file handle."}, + {1135, "", ""}, + {1136, "EDC8136I", "File is not a STREAM."}, + {1137, "EDC8137I", "STREAMS ioctl() timeout."}, + {1138, "EDC8138I", "No STREAMS resources."}, + {1139, "EDC8139I", "The message identified by set_id and msg_id is not in the message catalog."}, + {1140, "EDC8140I", "Bad message."}, + {1141, "EDC8141I", "Identifier removed."}, + {1142, "", ""}, + {1143, "", ""}, + {1144, "EDC8144I", "The link has been severed."}, + {1145, "", ""}, + {1146, "", ""}, + {1147, "", ""}, + {1148, "EDC8148I", "Protocol error."}, + {1149, "EDC8149I", "Multihop not allowed."}, + {1150, "", ""}, + {1151, "", ""}, + {1152, "EDC8152I", "The asynchronous I/O request has been canceled."}, + {1159, "EDC8159I", "Function call was interrupted before any data was received."}, + {1160, "EDC8160I", "Socket reuse is not supported."}, + {1161, "EDC8161I", "The file system cannot currently be moved."}, +} + +// Signal table +var signalList = [...]struct { + num Signal + name string + desc string +}{ + {1, "SIGHUP", "hangup"}, + {2, "SIGINT", "interrupt"}, + {3, "SIGABT", "aborted"}, + {4, "SIGILL", "illegal instruction"}, + {5, "SIGPOLL", "pollable event"}, + {6, "SIGURG", "urgent I/O condition"}, + {7, "SIGSTOP", "stop process"}, + {8, "SIGFPE", "floating point exception"}, + {9, "SIGKILL", "killed"}, + {10, "SIGBUS", "bus error"}, + {11, "SIGSEGV", "segmentation fault"}, + {12, "SIGSYS", "bad argument to routine"}, + {13, "SIGPIPE", "broken pipe"}, + {14, "SIGALRM", "alarm clock"}, + {15, "SIGTERM", "terminated"}, + {16, "SIGUSR1", "user defined signal 1"}, + {17, "SIGUSR2", "user defined signal 2"}, + {18, "SIGABND", "abend"}, + {19, "SIGCONT", "continued"}, + {20, "SIGCHLD", "child exited"}, + {21, "SIGTTIN", "stopped (tty input)"}, + {22, "SIGTTOU", "stopped (tty output)"}, + {23, "SIGIO", "I/O possible"}, + {24, "SIGQUIT", "quit"}, + {25, "SIGTSTP", "stopped"}, + {26, "SIGTRAP", "trace/breakpoint trap"}, + {27, "SIGIOER", "I/O error"}, + {28, "SIGWINCH", "window changed"}, + {29, "SIGXCPU", "CPU time limit exceeded"}, + {30, "SIGXFSZ", "file size limit exceeded"}, + {31, "SIGVTALRM", "virtual timer expired"}, + {32, "SIGPROF", "profiling timer expired"}, + {33, "SIGDANGER", "danger"}, + {34, "SIGTHSTOP", "stop thread"}, + {35, "SIGTHCONT", "continue thread"}, + {37, "SIGTRACE", "trace"}, + {38, "", "DCE"}, + {39, "SIGDUMP", "dump"}, +} diff --git a/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go b/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go index 89c5920..586317c 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go @@ -1,7 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("arm", "arm64"). DO NOT EDIT. -// +build linux -// +build arm arm64 +//go:build linux && (arm || arm64) package unix @@ -14,12 +13,12 @@ type PtraceRegsArm struct { // PtraceGetRegsArm fetches the registers used by arm binaries. func PtraceGetRegsArm(pid int, regsout *PtraceRegsArm) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsArm sets the registers used by arm binaries. func PtraceSetRegsArm(pid int, regs *PtraceRegsArm) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } // PtraceRegsArm64 is the registers used by arm64 binaries. @@ -32,10 +31,10 @@ type PtraceRegsArm64 struct { // PtraceGetRegsArm64 fetches the registers used by arm64 binaries. func PtraceGetRegsArm64(pid int, regsout *PtraceRegsArm64) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsArm64 sets the registers used by arm64 binaries. func PtraceSetRegsArm64(pid int, regs *PtraceRegsArm64) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } diff --git a/vendor/golang.org/x/sys/unix/zptrace_linux_arm64.go b/vendor/golang.org/x/sys/unix/zptrace_linux_arm64.go index 6cb6d68..834d285 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zptrace_linux_arm64.go @@ -7,11 +7,11 @@ import "unsafe" // PtraceGetRegSetArm64 fetches the registers used by arm64 binaries. func PtraceGetRegSetArm64(pid, addr int, regsout *PtraceRegsArm64) error { iovec := Iovec{(*byte)(unsafe.Pointer(regsout)), uint64(unsafe.Sizeof(*regsout))} - return ptrace(PTRACE_GETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec))) + return ptracePtr(PTRACE_GETREGSET, pid, uintptr(addr), unsafe.Pointer(&iovec)) } // PtraceSetRegSetArm64 sets the registers used by arm64 binaries. func PtraceSetRegSetArm64(pid, addr int, regs *PtraceRegsArm64) error { iovec := Iovec{(*byte)(unsafe.Pointer(regs)), uint64(unsafe.Sizeof(*regs))} - return ptrace(PTRACE_SETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec))) + return ptracePtr(PTRACE_SETREGSET, pid, uintptr(addr), unsafe.Pointer(&iovec)) } diff --git a/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go b/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go index 24b841e..d7c881b 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go @@ -1,7 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("mips", "mips64"). DO NOT EDIT. -// +build linux -// +build mips mips64 +//go:build linux && (mips || mips64) package unix @@ -20,12 +19,12 @@ type PtraceRegsMips struct { // PtraceGetRegsMips fetches the registers used by mips binaries. func PtraceGetRegsMips(pid int, regsout *PtraceRegsMips) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsMips sets the registers used by mips binaries. func PtraceSetRegsMips(pid int, regs *PtraceRegsMips) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } // PtraceRegsMips64 is the registers used by mips64 binaries. @@ -41,10 +40,10 @@ type PtraceRegsMips64 struct { // PtraceGetRegsMips64 fetches the registers used by mips64 binaries. func PtraceGetRegsMips64(pid int, regsout *PtraceRegsMips64) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsMips64 sets the registers used by mips64 binaries. func PtraceSetRegsMips64(pid int, regs *PtraceRegsMips64) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } diff --git a/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go b/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go index 47b0489..2d2de5d 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go @@ -1,7 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("mipsle", "mips64le"). DO NOT EDIT. -// +build linux -// +build mipsle mips64le +//go:build linux && (mipsle || mips64le) package unix @@ -20,12 +19,12 @@ type PtraceRegsMipsle struct { // PtraceGetRegsMipsle fetches the registers used by mipsle binaries. func PtraceGetRegsMipsle(pid int, regsout *PtraceRegsMipsle) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsMipsle sets the registers used by mipsle binaries. func PtraceSetRegsMipsle(pid int, regs *PtraceRegsMipsle) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } // PtraceRegsMips64le is the registers used by mips64le binaries. @@ -41,10 +40,10 @@ type PtraceRegsMips64le struct { // PtraceGetRegsMips64le fetches the registers used by mips64le binaries. func PtraceGetRegsMips64le(pid int, regsout *PtraceRegsMips64le) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsMips64le sets the registers used by mips64le binaries. func PtraceSetRegsMips64le(pid int, regs *PtraceRegsMips64le) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } diff --git a/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go b/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go index ea5d9cb..5adc79f 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go @@ -1,7 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("386", "amd64"). DO NOT EDIT. -// +build linux -// +build 386 amd64 +//go:build linux && (386 || amd64) package unix @@ -30,12 +29,12 @@ type PtraceRegs386 struct { // PtraceGetRegs386 fetches the registers used by 386 binaries. func PtraceGetRegs386(pid int, regsout *PtraceRegs386) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegs386 sets the registers used by 386 binaries. func PtraceSetRegs386(pid int, regs *PtraceRegs386) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } // PtraceRegsAmd64 is the registers used by amd64 binaries. @@ -71,10 +70,10 @@ type PtraceRegsAmd64 struct { // PtraceGetRegsAmd64 fetches the registers used by amd64 binaries. func PtraceGetRegsAmd64(pid int, regsout *PtraceRegsAmd64) error { - return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) + return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) } // PtraceSetRegsAmd64 sets the registers used by amd64 binaries. func PtraceSetRegsAmd64(pid int, regs *PtraceRegsAmd64) error { - return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) + return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) } diff --git a/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s b/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s new file mode 100644 index 0000000..b77ff5d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s @@ -0,0 +1,364 @@ +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build zos && s390x +#include "textflag.h" + +// provide the address of function variable to be fixed up. + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Flistxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fremovexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fgetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fsetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_accept4Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·accept4(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_RemovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Removexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_Dup3Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Dup3(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_DirfdAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Dirfd(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCreateAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCreate(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCreate1Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCreate1(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCtlAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCtl(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollPwaitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollPwait(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollWaitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollWait(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EventfdAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Eventfd(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FaccessatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Faccessat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FchmodatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fchmodat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FchownatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fchownat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FdatasyncAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fdatasync(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_fstatatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·fstatat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lgetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lsetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FstatfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fstatfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FutimesAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Futimes(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FutimesatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Futimesat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_GetrandomAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Getrandom(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyInitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyInit(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyInit1Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyInit1(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyAddWatchAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyAddWatch(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyRmWatchAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyRmWatch(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_ListxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Listxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Llistxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lremovexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LutimesAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lutimes(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_StatfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Statfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SyncfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Syncfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_UnshareAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unshare(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Linkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_MkdiratAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mkdirat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_MknodatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mknodat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PivotRootAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·PivotRoot(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PrctlAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Prctl(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PrlimitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Prlimit(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_RenameatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Renameat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_Renameat2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Renameat2(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SethostnameAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Sethostname(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SetnsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Setns(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SymlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Symlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_UnlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_openatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·openat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_openat2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·openat2(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_utimensatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·utimensat(SB), R8 + MOVD R8, ret+0(FP) + RET diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go index ed657ff..6ea64a3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go @@ -1,7 +1,7 @@ // go run mksyscall_aix_ppc.go -aix -tags aix,ppc syscall_aix.go syscall_aix_ppc.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build aix,ppc +//go:build aix && ppc package unix @@ -16,6 +16,7 @@ int getdirent(int, uintptr_t, size_t); int wait4(int, uintptr_t, int, uintptr_t); int ioctl(int, int, uintptr_t); int fcntl(uintptr_t, int, uintptr_t); +int fsync_range(int, int, long long, long long); int acct(uintptr_t); int chdir(uintptr_t); int chroot(uintptr_t); @@ -28,7 +29,6 @@ int fchmod(int, unsigned int); int fchmodat(int, uintptr_t, unsigned int, int); int fchownat(int, uintptr_t, int, int, int); int fdatasync(int); -int fsync(int); int getpgid(int); int getpgrp(); int getpid(); @@ -123,7 +123,6 @@ int utime(uintptr_t, uintptr_t); unsigned long long getsystemcfg(int); int umount(uintptr_t); int getrlimit64(int, uintptr_t); -int setrlimit64(int, uintptr_t); long long lseek64(int, long long, int); uintptr_t mmap(uintptr_t, uintptr_t, int, int, int, long long); @@ -212,7 +211,7 @@ func wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { +func ioctl(fd int, req int, arg uintptr) (err error) { r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(arg)) if r0 == -1 && er != nil { err = er @@ -222,6 +221,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) { + r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(uintptr(arg))) + if r0 == -1 && er != nil { + err = er + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func FcntlInt(fd uintptr, cmd int, arg int) (r int, err error) { r0, er := C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg)) r = int(r0) @@ -254,6 +263,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsyncRange(fd int, how int, start int64, length int64) (err error) { + r0, er := C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length)) + if r0 == -1 && er != nil { + err = er + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { _p0 := uintptr(unsafe.Pointer(C.CString(path))) r0, er := C.acct(C.uintptr_t(_p0)) @@ -378,16 +397,6 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fsync(fd int) (err error) { - r0, er := C.fsync(C.int(fd)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getpgid(pid int) (pgid int, err error) { r0, er := C.getpgid(C.int(pid)) pgid = int(r0) @@ -807,28 +816,6 @@ func write(fd int, p []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, p *byte, np int) (n int, err error) { - r0, er := C.read(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(p))), C.size_t(np)) - n = int(r0) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, p *byte, np int) (n int, err error) { - r0, er := C.write(C.int(fd), C.uintptr_t(uintptr(unsafe.Pointer(p))), C.size_t(np)) - n = int(r0) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Dup2(oldfd int, newfd int) (err error) { r0, er := C.dup2(C.int(oldfd), C.int(newfd)) if r0 == -1 && er != nil { @@ -974,7 +961,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 *byte if len(p) > 0 { _p0 = &p[0] @@ -991,7 +978,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 *byte if len(p) > 0 { _p0 = &p[0] @@ -1453,16 +1440,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(resource int, rlim *Rlimit) (err error) { - r0, er := C.setrlimit64(C.int(resource), C.uintptr_t(uintptr(unsafe.Pointer(rlim)))) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Seek(fd int, offset int64, whence int) (off int64, err error) { r0, er := C.lseek64(C.int(fd), C.longlong(offset), C.int(whence)) off = int64(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go index 664b293..99ee439 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go @@ -1,7 +1,7 @@ // go run mksyscall_aix_ppc64.go -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build aix,ppc64 +//go:build aix && ppc64 package unix @@ -92,8 +92,18 @@ func wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, e1 := callioctl(fd, int(req), arg) +func ioctl(fd int, req int, arg uintptr) (err error) { + _, e1 := callioctl(fd, req, arg) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) { + _, e1 := callioctl_ptr(fd, req, arg) if e1 != 0 { err = errnoErr(e1) } @@ -134,6 +144,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsyncRange(fd int, how int, start int64, length int64) (err error) { + _, e1 := callfsync_range(fd, how, start, length) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -282,16 +302,6 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fsync(fd int) (err error) { - _, e1 := callfsync(fd) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getpgid(pid int) (pgid int, err error) { r0, e1 := callgetpgid(pid) pgid = int(r0) @@ -751,28 +761,6 @@ func write(fd int, p []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, p *byte, np int) (n int, err error) { - r0, e1 := callread(fd, uintptr(unsafe.Pointer(p)), np) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, p *byte, np int) (n int, err error) { - r0, e1 := callwrite(fd, uintptr(unsafe.Pointer(p)), np) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Dup2(oldfd int, newfd int) (err error) { _, e1 := calldup2(oldfd, newfd) if e1 != 0 { @@ -930,7 +918,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 *byte if len(p) > 0 { _p0 = &p[0] @@ -945,7 +933,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 *byte if len(p) > 0 { _p0 = &p[0] @@ -1411,16 +1399,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, e1 := callsetrlimit(resource, uintptr(unsafe.Pointer(rlim))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Seek(fd int, offset int64, whence int) (off int64, err error) { r0, e1 := calllseek(fd, offset, whence) off = int64(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go index 4b3a8ad..b68a783 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go @@ -1,8 +1,7 @@ // go run mksyscall_aix_ppc64.go -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build aix,ppc64 -// +build !gccgo +//go:build aix && ppc64 && gc package unix @@ -18,6 +17,7 @@ import ( //go:cgo_import_dynamic libc_wait4 wait4 "libc.a/shr_64.o" //go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o" //go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fsync_range fsync_range "libc.a/shr_64.o" //go:cgo_import_dynamic libc_acct acct "libc.a/shr_64.o" //go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o" //go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o" @@ -30,7 +30,6 @@ import ( //go:cgo_import_dynamic libc_fchmodat fchmodat "libc.a/shr_64.o" //go:cgo_import_dynamic libc_fchownat fchownat "libc.a/shr_64.o" //go:cgo_import_dynamic libc_fdatasync fdatasync "libc.a/shr_64.o" -//go:cgo_import_dynamic libc_fsync fsync "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getpgid getpgid "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getpgrp getpgrp "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o" @@ -124,7 +123,6 @@ import ( //go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o" //go:cgo_import_dynamic libc_umount umount "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getrlimit getrlimit "libc.a/shr_64.o" -//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.a/shr_64.o" //go:cgo_import_dynamic libc_lseek lseek "libc.a/shr_64.o" //go:cgo_import_dynamic libc_mmap64 mmap64 "libc.a/shr_64.o" @@ -136,6 +134,7 @@ import ( //go:linkname libc_wait4 libc_wait4 //go:linkname libc_ioctl libc_ioctl //go:linkname libc_fcntl libc_fcntl +//go:linkname libc_fsync_range libc_fsync_range //go:linkname libc_acct libc_acct //go:linkname libc_chdir libc_chdir //go:linkname libc_chroot libc_chroot @@ -148,7 +147,6 @@ import ( //go:linkname libc_fchmodat libc_fchmodat //go:linkname libc_fchownat libc_fchownat //go:linkname libc_fdatasync libc_fdatasync -//go:linkname libc_fsync libc_fsync //go:linkname libc_getpgid libc_getpgid //go:linkname libc_getpgrp libc_getpgrp //go:linkname libc_getpid libc_getpid @@ -242,7 +240,6 @@ import ( //go:linkname libc_getsystemcfg libc_getsystemcfg //go:linkname libc_umount libc_umount //go:linkname libc_getrlimit libc_getrlimit -//go:linkname libc_setrlimit libc_setrlimit //go:linkname libc_lseek libc_lseek //go:linkname libc_mmap64 libc_mmap64 @@ -257,6 +254,7 @@ var ( libc_wait4, libc_ioctl, libc_fcntl, + libc_fsync_range, libc_acct, libc_chdir, libc_chroot, @@ -269,7 +267,6 @@ var ( libc_fchmodat, libc_fchownat, libc_fdatasync, - libc_fsync, libc_getpgid, libc_getpgrp, libc_getpid, @@ -363,7 +360,6 @@ var ( libc_getsystemcfg, libc_umount, libc_getrlimit, - libc_setrlimit, libc_lseek, libc_mmap64 syscallFunc ) @@ -423,6 +419,13 @@ func callioctl(fd int, req int, arg uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func callioctl_ptr(fd int, req int, arg unsafe.Pointer) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_ioctl)), 3, uintptr(fd), uintptr(req), uintptr(arg), 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, fd, uintptr(cmd), arg, 0, 0, 0) return @@ -430,6 +433,13 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync_range)), 4, uintptr(fd), uintptr(how), uintptr(start), uintptr(length), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) { r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_acct)), 1, _p0, 0, 0, 0, 0, 0) return @@ -514,13 +524,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func callfsync(fd int) (r1 uintptr, e1 Errno) { - r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync)), 1, uintptr(fd), 0, 0, 0, 0, 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func callgetpgid(pid int) (r1 uintptr, e1 Errno) { r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0) return @@ -1172,13 +1175,6 @@ func callgetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func callsetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { - r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setrlimit)), 2, uintptr(resource), rlim, 0, 0, 0, 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) { r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_lseek)), 3, uintptr(fd), uintptr(offset), uintptr(whence), 0, 0, 0) return diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go index cde4dbc..0a87450 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go @@ -1,8 +1,7 @@ // go run mksyscall_aix_ppc64.go -aix -tags aix,ppc64 syscall_aix.go syscall_aix_ppc64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build aix,ppc64 -// +build gccgo +//go:build aix && ppc64 && gccgo package unix @@ -16,6 +15,7 @@ int getdirent(int, uintptr_t, size_t); int wait4(int, uintptr_t, int, uintptr_t); int ioctl(int, int, uintptr_t); int fcntl(uintptr_t, int, uintptr_t); +int fsync_range(int, int, long long, long long); int acct(uintptr_t); int chdir(uintptr_t); int chroot(uintptr_t); @@ -28,7 +28,6 @@ int fchmod(int, unsigned int); int fchmodat(int, uintptr_t, unsigned int, int); int fchownat(int, uintptr_t, int, int, int); int fdatasync(int); -int fsync(int); int getpgid(int); int getpgrp(); int getpid(); @@ -123,7 +122,6 @@ int utime(uintptr_t, uintptr_t); unsigned long long getsystemcfg(int); int umount(uintptr_t); int getrlimit(int, uintptr_t); -int setrlimit(int, uintptr_t); long long lseek(int, long long, int); uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long); @@ -131,6 +129,7 @@ uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long); import "C" import ( "syscall" + "unsafe" ) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -191,6 +190,14 @@ func callioctl(fd int, req int, arg uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func callioctl_ptr(fd int, req int, arg unsafe.Pointer) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.ioctl(C.int(fd), C.int(req), C.uintptr_t(uintptr(arg)))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { r1 = uintptr(C.fcntl(C.uintptr_t(fd), C.int(cmd), C.uintptr_t(arg))) e1 = syscall.GetErrno() @@ -199,6 +206,14 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) { r1 = uintptr(C.acct(C.uintptr_t(_p0))) e1 = syscall.GetErrno() @@ -295,14 +310,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func callfsync(fd int) (r1 uintptr, e1 Errno) { - r1 = uintptr(C.fsync(C.int(fd))) - e1 = syscall.GetErrno() - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func callgetpgid(pid int) (r1 uintptr, e1 Errno) { r1 = uintptr(C.getpgid(C.int(pid))) e1 = syscall.GetErrno() @@ -1047,14 +1054,6 @@ func callgetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func callsetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) { - r1 = uintptr(C.setrlimit(C.int(resource), C.uintptr_t(rlim))) - e1 = syscall.GetErrno() - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) { r1 = uintptr(C.lseek(C.int(fd), C.longlong(offset), C.int(whence))) e1 = syscall.GetErrno() diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go deleted file mode 100644 index c1cc0a4..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go +++ /dev/null @@ -1,1811 +0,0 @@ -// go run mksyscall.go -l32 -tags darwin,386,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_386.1_11.go syscall_darwin_386.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,386,!go1.12 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) - wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func utimes(path string, timeval *[2]Timeval) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Madvise(b []byte, behav int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mprotect(b []byte, prot int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Msync(b []byte, flags int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (r int, w int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - r = int(r0) - w = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fremovexattr(fd int, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_SETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Access(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chflags(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chmod(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chroot(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) - nfd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exchangedata(path1 string, path2 string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path1) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(path2) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdtablesize() (size int) { - r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) - size = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) - egid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) - gid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) - pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) - pgrp = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) - pid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) - ppid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) - prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) - sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Issetugid() (tainted bool) { - r0, _, _ := RawSyscall(SYS_ISSETUGID, 0, 0, 0) - tainted = bool(r0 != 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lchown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Link(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdir(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdirat(dirfd int, path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkfifo(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Open(path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pathconf(path string, name int) (val int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pread(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func read(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rename(from string, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Renameat(fromfd int, from string, tofd int, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Revoke(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rmdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0) - newoffset = int64(int64(r1)<<32 | int64(r0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setegid(egid int) (err error) { - _, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setlogin(name string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setprivexec(flag int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIVEXEC, uintptr(flag), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) - pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlink(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(oldpath) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(newpath) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Truncate(path string, length int64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) - oldmask = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Undelete(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlink(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlinkat(dirfd int, path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unmount(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func write(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0) - ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { - r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int32(r0) - usec = int32(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(buf), uintptr(size), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lstat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Stat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Statfs(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go deleted file mode 100644 index e263fbd..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go +++ /dev/null @@ -1,41 +0,0 @@ -// go run mksyscall.go -l32 -tags darwin,386,go1.13 syscall_darwin.1_13.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,386,go1.13 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func closedir(dir uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_closedir_trampoline() - -//go:linkname libc_closedir libc_closedir -//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { - r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) - res = Errno(r0) - return -} - -func libc_readdir_r_trampoline() - -//go:linkname libc_readdir_r libc_readdir_r -//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s deleted file mode 100644 index 00da1eb..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s +++ /dev/null @@ -1,12 +0,0 @@ -// go run mkasm_darwin.go 386 -// Code generated by the command above; DO NOT EDIT. - -// +build go1.13 - -#include "textflag.h" -TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fdopendir(SB) -TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_closedir(SB) -TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go deleted file mode 100644 index a3fc490..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ /dev/null @@ -1,2499 +0,0 @@ -// go run mksyscall.go -l32 -tags darwin,386,go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_386.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,386,go1.12 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getgroups_trampoline() - -//go:linkname libc_getgroups libc_getgroups -//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setgroups_trampoline() - -//go:linkname libc_setgroups libc_setgroups -//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_wait4_trampoline), uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) - wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_wait4_trampoline() - -//go:linkname libc_wait4 libc_wait4 -//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_accept_trampoline), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_accept_trampoline() - -//go:linkname libc_accept libc_accept -//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_bind_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_bind_trampoline() - -//go:linkname libc_bind libc_bind -//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_connect_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_connect_trampoline() - -//go:linkname libc_connect libc_connect -//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_socket_trampoline), uintptr(domain), uintptr(typ), uintptr(proto)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_socket_trampoline() - -//go:linkname libc_socket libc_socket -//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getsockopt_trampoline() - -//go:linkname libc_getsockopt libc_getsockopt -//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setsockopt_trampoline() - -//go:linkname libc_setsockopt libc_setsockopt -//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getpeername_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getpeername_trampoline() - -//go:linkname libc_getpeername libc_getpeername -//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getsockname_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getsockname_trampoline() - -//go:linkname libc_getsockname libc_getsockname -//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Shutdown(s int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_shutdown_trampoline), uintptr(s), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_shutdown_trampoline() - -//go:linkname libc_shutdown libc_shutdown -//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := syscall_rawSyscall6(funcPC(libc_socketpair_trampoline), uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_socketpair_trampoline() - -//go:linkname libc_socketpair libc_socketpair -//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_recvfrom_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_recvfrom_trampoline() - -//go:linkname libc_recvfrom libc_recvfrom -//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc_sendto_trampoline), uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sendto_trampoline() - -//go:linkname libc_sendto libc_sendto -//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_recvmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_recvmsg_trampoline() - -//go:linkname libc_recvmsg libc_recvmsg -//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_sendmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sendmsg_trampoline() - -//go:linkname libc_sendmsg libc_sendmsg -//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_kevent_trampoline), uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_kevent_trampoline() - -//go:linkname libc_kevent libc_kevent -//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func utimes(path string, timeval *[2]Timeval) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_utimes_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_utimes_trampoline() - -//go:linkname libc_utimes libc_utimes -//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_futimes_trampoline), uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_futimes_trampoline() - -//go:linkname libc_futimes libc_futimes -//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_poll_trampoline), uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_poll_trampoline() - -//go:linkname libc_poll libc_poll -//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Madvise(b []byte, behav int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_madvise_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(behav)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_madvise_trampoline() - -//go:linkname libc_madvise libc_madvise -//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_mlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mlock_trampoline() - -//go:linkname libc_mlock libc_mlock -//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlockall(flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_mlockall_trampoline), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mlockall_trampoline() - -//go:linkname libc_mlockall libc_mlockall -//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mprotect(b []byte, prot int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_mprotect_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mprotect_trampoline() - -//go:linkname libc_mprotect libc_mprotect -//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Msync(b []byte, flags int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_msync_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_msync_trampoline() - -//go:linkname libc_msync libc_msync -//go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_munlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_munlock_trampoline() - -//go:linkname libc_munlock libc_munlock -//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlockall() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munlockall_trampoline), 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_munlockall_trampoline() - -//go:linkname libc_munlockall libc_munlockall -//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getattrlist_trampoline() - -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (r int, w int, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) - r = int(r0) - w = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pipe_trampoline() - -//go:linkname libc_pipe libc_pipe -//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_getxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getxattr_trampoline() - -//go:linkname libc_getxattr libc_getxattr -//go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_fgetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fgetxattr_trampoline() - -//go:linkname libc_fgetxattr libc_fgetxattr -//go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_setxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setxattr_trampoline() - -//go:linkname libc_setxattr libc_setxattr -//go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fsetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fsetxattr_trampoline() - -//go:linkname libc_fsetxattr libc_fsetxattr -//go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_removexattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_removexattr_trampoline() - -//go:linkname libc_removexattr libc_removexattr -//go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fremovexattr(fd int, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_fremovexattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fremovexattr_trampoline() - -//go:linkname libc_fremovexattr libc_fremovexattr -//go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_listxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_listxattr_trampoline() - -//go:linkname libc_listxattr libc_listxattr -//go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_flistxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_flistxattr_trampoline() - -//go:linkname libc_flistxattr libc_flistxattr -//go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setattrlist_trampoline() - -//go:linkname libc_setattrlist libc_setattrlist -//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg)) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fcntl_trampoline() - -//go:linkname libc_fcntl libc_fcntl -//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_kill_trampoline), uintptr(pid), uintptr(signum), uintptr(posix)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_kill_trampoline() - -//go:linkname libc_kill libc_kill -//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ioctl_trampoline), uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ioctl_trampoline() - -//go:linkname libc_ioctl libc_ioctl -//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sysctl_trampoline() - -//go:linkname libc_sysctl libc_sysctl -//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := syscall_syscall9(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sendfile_trampoline() - -//go:linkname libc_sendfile libc_sendfile -//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Access(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_access_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_access_trampoline() - -//go:linkname libc_access libc_access -//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_adjtime_trampoline), uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_adjtime_trampoline() - -//go:linkname libc_adjtime libc_adjtime -//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chdir_trampoline() - -//go:linkname libc_chdir libc_chdir -//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chflags(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chflags_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chflags_trampoline() - -//go:linkname libc_chflags libc_chflags -//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chmod(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chmod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chmod_trampoline() - -//go:linkname libc_chmod libc_chmod -//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chown_trampoline() - -//go:linkname libc_chown libc_chown -//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chroot(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chroot_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chroot_trampoline() - -//go:linkname libc_chroot libc_chroot -//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ClockGettime(clockid int32, time *Timespec) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_clock_gettime_trampoline() - -//go:linkname libc_clock_gettime libc_clock_gettime -//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Close(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_close_trampoline() - -//go:linkname libc_close libc_close -//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup(fd int) (nfd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0) - nfd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_dup_trampoline() - -//go:linkname libc_dup libc_dup -//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup2(from int, to int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_dup2_trampoline), uintptr(from), uintptr(to), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_dup2_trampoline() - -//go:linkname libc_dup2 libc_dup2 -//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exchangedata(path1 string, path2 string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path1) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(path2) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_exchangedata_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_exchangedata_trampoline() - -//go:linkname libc_exchangedata libc_exchangedata -//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exit(code int) { - syscall_syscall(funcPC(libc_exit_trampoline), uintptr(code), 0, 0) - return -} - -func libc_exit_trampoline() - -//go:linkname libc_exit libc_exit -//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_faccessat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_faccessat_trampoline() - -//go:linkname libc_faccessat libc_faccessat -//go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchdir(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchdir_trampoline), uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchdir_trampoline() - -//go:linkname libc_fchdir libc_fchdir -//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchflags(fd int, flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchflags_trampoline), uintptr(fd), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchflags_trampoline() - -//go:linkname libc_fchflags libc_fchflags -//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchmod_trampoline), uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchmod_trampoline() - -//go:linkname libc_fchmod libc_fchmod -//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fchmodat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchmodat_trampoline() - -//go:linkname libc_fchmodat libc_fchmodat -//go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchown_trampoline), uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchown_trampoline() - -//go:linkname libc_fchown libc_fchown -//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fchownat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchownat_trampoline() - -//go:linkname libc_fchownat libc_fchownat -//go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Flock(fd int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_flock_trampoline() - -//go:linkname libc_flock libc_flock -//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fpathconf_trampoline), uintptr(fd), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fpathconf_trampoline() - -//go:linkname libc_fpathconf libc_fpathconf -//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fsync(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fsync_trampoline), uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fsync_trampoline() - -//go:linkname libc_fsync libc_fsync -//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ftruncate_trampoline), uintptr(fd), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ftruncate_trampoline() - -//go:linkname libc_ftruncate libc_ftruncate -//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdtablesize() (size int) { - r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) - size = int(r0) - return -} - -func libc_getdtablesize_trampoline() - -//go:linkname libc_getdtablesize libc_getdtablesize -//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getegid() (egid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getegid_trampoline), 0, 0, 0) - egid = int(r0) - return -} - -func libc_getegid_trampoline() - -//go:linkname libc_getegid libc_getegid -//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Geteuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_geteuid_trampoline), 0, 0, 0) - uid = int(r0) - return -} - -func libc_geteuid_trampoline() - -//go:linkname libc_geteuid libc_geteuid -//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getgid() (gid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getgid_trampoline), 0, 0, 0) - gid = int(r0) - return -} - -func libc_getgid_trampoline() - -//go:linkname libc_getgid libc_getgid -//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getpgid_trampoline), uintptr(pid), 0, 0) - pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getpgid_trampoline() - -//go:linkname libc_getpgid libc_getpgid -//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgrp() (pgrp int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpgrp_trampoline), 0, 0, 0) - pgrp = int(r0) - return -} - -func libc_getpgrp_trampoline() - -//go:linkname libc_getpgrp libc_getpgrp -//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpid() (pid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpid_trampoline), 0, 0, 0) - pid = int(r0) - return -} - -func libc_getpid_trampoline() - -//go:linkname libc_getpid libc_getpid -//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getppid() (ppid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getppid_trampoline), 0, 0, 0) - ppid = int(r0) - return -} - -func libc_getppid_trampoline() - -//go:linkname libc_getppid libc_getppid -//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getpriority_trampoline), uintptr(which), uintptr(who), 0) - prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getpriority_trampoline() - -//go:linkname libc_getpriority libc_getpriority -//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getrlimit_trampoline() - -//go:linkname libc_getrlimit libc_getrlimit -//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrusage_trampoline), uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getrusage_trampoline() - -//go:linkname libc_getrusage libc_getrusage -//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getsid(pid int) (sid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getsid_trampoline), uintptr(pid), 0, 0) - sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getsid_trampoline() - -//go:linkname libc_getsid libc_getsid -//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0) - uid = int(r0) - return -} - -func libc_getuid_trampoline() - -//go:linkname libc_getuid libc_getuid -//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Issetugid() (tainted bool) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_issetugid_trampoline), 0, 0, 0) - tainted = bool(r0 != 0) - return -} - -func libc_issetugid_trampoline() - -//go:linkname libc_issetugid libc_issetugid -//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Kqueue() (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_kqueue_trampoline), 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_kqueue_trampoline() - -//go:linkname libc_kqueue libc_kqueue -//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lchown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_lchown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_lchown_trampoline() - -//go:linkname libc_lchown libc_lchown -//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Link(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_link_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_link_trampoline() - -//go:linkname libc_link libc_link -//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_linkat_trampoline), uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_linkat_trampoline() - -//go:linkname libc_linkat libc_linkat -//go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Listen(s int, backlog int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_listen_trampoline), uintptr(s), uintptr(backlog), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_listen_trampoline() - -//go:linkname libc_listen libc_listen -//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdir(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mkdir_trampoline() - -//go:linkname libc_mkdir libc_mkdir -//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdirat(dirfd int, path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mkdirat_trampoline() - -//go:linkname libc_mkdirat libc_mkdirat -//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkfifo(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mkfifo_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mkfifo_trampoline() - -//go:linkname libc_mkfifo libc_mkfifo -//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mknod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mknod_trampoline() - -//go:linkname libc_mknod libc_mknod -//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Open(path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall(funcPC(libc_open_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_open_trampoline() - -//go:linkname libc_open libc_open -//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_openat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_openat_trampoline() - -//go:linkname libc_openat libc_openat -//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pathconf(path string, name int) (val int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall(funcPC(libc_pathconf_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pathconf_trampoline() - -//go:linkname libc_pathconf libc_pathconf -//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pread(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_pread_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pread_trampoline() - -//go:linkname libc_pread libc_pread -//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_pwrite_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pwrite_trampoline() - -//go:linkname libc_pwrite libc_pwrite -//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func read(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_read_trampoline() - -//go:linkname libc_read libc_read -//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(funcPC(libc_readlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_readlink_trampoline() - -//go:linkname libc_readlink libc_readlink -//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_readlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_readlinkat_trampoline() - -//go:linkname libc_readlinkat libc_readlinkat -//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rename(from string, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_rename_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_rename_trampoline() - -//go:linkname libc_rename libc_rename -//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Renameat(fromfd int, from string, tofd int, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_renameat_trampoline), uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_renameat_trampoline() - -//go:linkname libc_renameat libc_renameat -//go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Revoke(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_revoke_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_revoke_trampoline() - -//go:linkname libc_revoke libc_revoke -//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rmdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_rmdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_rmdir_trampoline() - -//go:linkname libc_rmdir libc_rmdir -//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, r1, e1 := syscall_syscall6(funcPC(libc_lseek_trampoline), uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0) - newoffset = int64(int64(r1)<<32 | int64(r0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_lseek_trampoline() - -//go:linkname libc_lseek libc_lseek -//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_select_trampoline() - -//go:linkname libc_select libc_select -//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setegid(egid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setegid_trampoline), uintptr(egid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setegid_trampoline() - -//go:linkname libc_setegid libc_setegid -//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seteuid(euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_seteuid_trampoline), uintptr(euid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_seteuid_trampoline() - -//go:linkname libc_seteuid libc_seteuid -//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setgid(gid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgid_trampoline), uintptr(gid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setgid_trampoline() - -//go:linkname libc_setgid libc_setgid -//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setlogin(name string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_setlogin_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setlogin_trampoline() - -//go:linkname libc_setlogin libc_setlogin -//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setpgid_trampoline), uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setpgid_trampoline() - -//go:linkname libc_setpgid libc_setpgid -//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setpriority_trampoline), uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setpriority_trampoline() - -//go:linkname libc_setpriority libc_setpriority -//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setprivexec(flag int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setprivexec_trampoline), uintptr(flag), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setprivexec_trampoline() - -//go:linkname libc_setprivexec libc_setprivexec -//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setregid_trampoline), uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setregid_trampoline() - -//go:linkname libc_setregid libc_setregid -//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setreuid_trampoline), uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setreuid_trampoline() - -//go:linkname libc_setreuid libc_setreuid -//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setrlimit_trampoline() - -//go:linkname libc_setrlimit libc_setrlimit -//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setsid() (pid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_setsid_trampoline), 0, 0, 0) - pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setsid_trampoline() - -//go:linkname libc_setsid libc_setsid -//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_settimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_settimeofday_trampoline() - -//go:linkname libc_settimeofday libc_settimeofday -//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setuid(uid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setuid_trampoline), uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setuid_trampoline() - -//go:linkname libc_setuid libc_setuid -//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlink(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_symlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_symlink_trampoline() - -//go:linkname libc_symlink libc_symlink -//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(oldpath) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(newpath) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_symlinkat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_symlinkat_trampoline() - -//go:linkname libc_symlinkat libc_symlinkat -//go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Sync() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_sync_trampoline), 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sync_trampoline() - -//go:linkname libc_sync libc_sync -//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Truncate(path string, length int64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_truncate_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_truncate_trampoline() - -//go:linkname libc_truncate libc_truncate -//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Umask(newmask int) (oldmask int) { - r0, _, _ := syscall_syscall(funcPC(libc_umask_trampoline), uintptr(newmask), 0, 0) - oldmask = int(r0) - return -} - -func libc_umask_trampoline() - -//go:linkname libc_umask libc_umask -//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Undelete(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_undelete_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_undelete_trampoline() - -//go:linkname libc_undelete libc_undelete -//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlink(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_unlink_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_unlink_trampoline() - -//go:linkname libc_unlink libc_unlink -//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlinkat(dirfd int, path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_unlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_unlinkat_trampoline() - -//go:linkname libc_unlinkat libc_unlinkat -//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unmount(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_unmount_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_unmount_trampoline() - -//go:linkname libc_unmount libc_unmount -//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func write(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_write_trampoline() - -//go:linkname libc_write libc_write -//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := syscall_syscall9(funcPC(libc_mmap_trampoline), uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0) - ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mmap_trampoline() - -//go:linkname libc_mmap libc_mmap -//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munmap_trampoline), uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_munmap_trampoline() - -//go:linkname libc_munmap libc_munmap -//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int32(r0) - usec = int32(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_gettimeofday_trampoline() - -//go:linkname libc_gettimeofday libc_gettimeofday -//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fstat64_trampoline() - -//go:linkname libc_fstat64 libc_fstat64 -//go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fstatat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fstatat64_trampoline() - -//go:linkname libc_fstatat64 libc_fstatat64 -//go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstatfs64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fstatfs64_trampoline() - -//go:linkname libc_fstatfs64 libc_fstatfs64 -//go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getfsstat64_trampoline() - -//go:linkname libc_getfsstat64 libc_getfsstat64 -//go:cgo_import_dynamic libc_getfsstat64 getfsstat64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lstat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_lstat64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_lstat64_trampoline() - -//go:linkname libc_lstat64 libc_lstat64 -//go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Stat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_stat64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_stat64_trampoline() - -//go:linkname libc_stat64 libc_stat64 -//go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Statfs(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_statfs64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_statfs64_trampoline() - -//go:linkname libc_statfs64 libc_statfs64 -//go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s deleted file mode 100644 index 6836a41..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s +++ /dev/null @@ -1,284 +0,0 @@ -// go run mkasm_darwin.go 386 -// Code generated by the command above; DO NOT EDIT. - -// +build go1.12 - -#include "textflag.h" -TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getgroups(SB) -TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setgroups(SB) -TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0 - JMP libc_wait4(SB) -TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0 - JMP libc_accept(SB) -TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0 - JMP libc_bind(SB) -TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0 - JMP libc_connect(SB) -TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0 - JMP libc_socket(SB) -TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getsockopt(SB) -TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setsockopt(SB) -TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpeername(SB) -TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getsockname(SB) -TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_shutdown(SB) -TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0 - JMP libc_socketpair(SB) -TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0 - JMP libc_recvfrom(SB) -TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sendto(SB) -TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0 - JMP libc_recvmsg(SB) -TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sendmsg(SB) -TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 - JMP libc_kevent(SB) -TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 - JMP libc_utimes(SB) -TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 - JMP libc_futimes(SB) -TEXT ·libc_poll_trampoline(SB),NOSPLIT,$0-0 - JMP libc_poll(SB) -TEXT ·libc_madvise_trampoline(SB),NOSPLIT,$0-0 - JMP libc_madvise(SB) -TEXT ·libc_mlock_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mlock(SB) -TEXT ·libc_mlockall_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mlockall(SB) -TEXT ·libc_mprotect_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mprotect(SB) -TEXT ·libc_msync_trampoline(SB),NOSPLIT,$0-0 - JMP libc_msync(SB) -TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 - JMP libc_munlock(SB) -TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 - JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) -TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pipe(SB) -TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getxattr(SB) -TEXT ·libc_fgetxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fgetxattr(SB) -TEXT ·libc_setxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setxattr(SB) -TEXT ·libc_fsetxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fsetxattr(SB) -TEXT ·libc_removexattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_removexattr(SB) -TEXT ·libc_fremovexattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fremovexattr(SB) -TEXT ·libc_listxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_listxattr(SB) -TEXT ·libc_flistxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_flistxattr(SB) -TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setattrlist(SB) -TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fcntl(SB) -TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 - JMP libc_kill(SB) -TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ioctl(SB) -TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sysctl(SB) -TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sendfile(SB) -TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 - JMP libc_access(SB) -TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0 - JMP libc_adjtime(SB) -TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chdir(SB) -TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chflags(SB) -TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chmod(SB) -TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chown(SB) -TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chroot(SB) -TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 - JMP libc_clock_gettime(SB) -TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 - JMP libc_close(SB) -TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 - JMP libc_dup(SB) -TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0 - JMP libc_dup2(SB) -TEXT ·libc_exchangedata_trampoline(SB),NOSPLIT,$0-0 - JMP libc_exchangedata(SB) -TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_exit(SB) -TEXT ·libc_faccessat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_faccessat(SB) -TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchdir(SB) -TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchflags(SB) -TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchmod(SB) -TEXT ·libc_fchmodat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchmodat(SB) -TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchown(SB) -TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchownat(SB) -TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0 - JMP libc_flock(SB) -TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fpathconf(SB) -TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fsync(SB) -TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ftruncate(SB) -TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getdtablesize(SB) -TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getegid(SB) -TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_geteuid(SB) -TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getgid(SB) -TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpgid(SB) -TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpgrp(SB) -TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpid(SB) -TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getppid(SB) -TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpriority(SB) -TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getrlimit(SB) -TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getrusage(SB) -TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getsid(SB) -TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getuid(SB) -TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_issetugid(SB) -TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0 - JMP libc_kqueue(SB) -TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_lchown(SB) -TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0 - JMP libc_link(SB) -TEXT ·libc_linkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_linkat(SB) -TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0 - JMP libc_listen(SB) -TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mkdir(SB) -TEXT ·libc_mkdirat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mkdirat(SB) -TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mkfifo(SB) -TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mknod(SB) -TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0 - JMP libc_open(SB) -TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_openat(SB) -TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pathconf(SB) -TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pread(SB) -TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pwrite(SB) -TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0 - JMP libc_read(SB) -TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readlink(SB) -TEXT ·libc_readlinkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readlinkat(SB) -TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0 - JMP libc_rename(SB) -TEXT ·libc_renameat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_renameat(SB) -TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0 - JMP libc_revoke(SB) -TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_rmdir(SB) -TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0 - JMP libc_lseek(SB) -TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0 - JMP libc_select(SB) -TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setegid(SB) -TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_seteuid(SB) -TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setgid(SB) -TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setlogin(SB) -TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setpgid(SB) -TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setpriority(SB) -TEXT ·libc_setprivexec_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setprivexec(SB) -TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setregid(SB) -TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setreuid(SB) -TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setrlimit(SB) -TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setsid(SB) -TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0 - JMP libc_settimeofday(SB) -TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setuid(SB) -TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0 - JMP libc_symlink(SB) -TEXT ·libc_symlinkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_symlinkat(SB) -TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sync(SB) -TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0 - JMP libc_truncate(SB) -TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0 - JMP libc_umask(SB) -TEXT ·libc_undelete_trampoline(SB),NOSPLIT,$0-0 - JMP libc_undelete(SB) -TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0 - JMP libc_unlink(SB) -TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_unlinkat(SB) -TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0 - JMP libc_unmount(SB) -TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0 - JMP libc_write(SB) -TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mmap(SB) -TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 - JMP libc_munmap(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) -TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 - JMP libc_gettimeofday(SB) -TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fstat64(SB) -TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fstatat64(SB) -TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fstatfs64(SB) -TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getfsstat64(SB) -TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_lstat64(SB) -TEXT ·libc_stat64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_stat64(SB) -TEXT ·libc_statfs64_trampoline(SB),NOSPLIT,$0-0 - JMP libc_statfs64(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go deleted file mode 100644 index 314042a..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go +++ /dev/null @@ -1,41 +0,0 @@ -// go run mksyscall.go -tags darwin,amd64,go1.13 syscall_darwin.1_13.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,amd64,go1.13 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func closedir(dir uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_closedir_trampoline() - -//go:linkname libc_closedir libc_closedir -//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { - r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) - res = Errno(r0) - return -} - -func libc_readdir_r_trampoline() - -//go:linkname libc_readdir_r libc_readdir_r -//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s deleted file mode 100644 index d671e83..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s +++ /dev/null @@ -1,12 +0,0 @@ -// go run mkasm_darwin.go amd64 -// Code generated by the command above; DO NOT EDIT. - -// +build go1.13 - -#include "textflag.h" -TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fdopendir(SB) -TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_closedir(SB) -TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 50d6437..813c05b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags darwin,amd64,go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.go +// go run mksyscall.go -tags darwin,amd64 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build darwin,amd64,go1.12 +//go:build darwin && amd64 package unix @@ -15,7 +15,7 @@ var _ syscall.Errno // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -23,30 +23,28 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { return } -func libc_getgroups_trampoline() +var libc_getgroups_trampoline_addr uintptr -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setgroups_trampoline() +var libc_setgroups_trampoline_addr uintptr -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_wait4_trampoline), uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -54,15 +52,14 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err return } -func libc_wait4_trampoline() +var libc_wait4_trampoline_addr uintptr -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_accept_trampoline), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -70,45 +67,42 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { return } -func libc_accept_trampoline() +var libc_accept_trampoline_addr uintptr -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_bind_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_bind_trampoline() +var libc_bind_trampoline_addr uintptr -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_connect_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_connect_trampoline() +var libc_connect_trampoline_addr uintptr -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_socket_trampoline), uintptr(domain), uintptr(typ), uintptr(proto)) + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -116,99 +110,92 @@ func socket(domain int, typ int, proto int) (fd int, err error) { return } -func libc_socket_trampoline() +var libc_socket_trampoline_addr uintptr -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getsockopt_trampoline() +var libc_getsockopt_trampoline_addr uintptr -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setsockopt_trampoline() +var libc_setsockopt_trampoline_addr uintptr -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getpeername_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getpeername_trampoline() +var libc_getpeername_trampoline_addr uintptr -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getsockname_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getsockname_trampoline() +var libc_getsockname_trampoline_addr uintptr -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(s int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_shutdown_trampoline), uintptr(s), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_shutdown_trampoline() +var libc_shutdown_trampoline_addr uintptr -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := syscall_rawSyscall6(funcPC(libc_socketpair_trampoline), uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_socketpair_trampoline() +var libc_socketpair_trampoline_addr uintptr -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -220,7 +207,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_recvfrom_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -228,9 +215,8 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl return } -func libc_recvfrom_trampoline() +var libc_recvfrom_trampoline_addr uintptr -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -242,22 +228,21 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall6(funcPC(libc_sendto_trampoline), uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sendto_trampoline() +var libc_sendto_trampoline_addr uintptr -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_recvmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -265,15 +250,14 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } -func libc_recvmsg_trampoline() +var libc_recvmsg_trampoline_addr uintptr -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_sendmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -281,15 +265,14 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } -func libc_sendmsg_trampoline() +var libc_sendmsg_trampoline_addr uintptr -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_kevent_trampoline), uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -297,9 +280,8 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne return } -func libc_kevent_trampoline() +var libc_kevent_trampoline_addr uintptr -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -310,37 +292,35 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_utimes_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_utimes_trampoline() +var libc_utimes_trampoline_addr uintptr -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_futimes_trampoline), uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_futimes_trampoline() +var libc_futimes_trampoline_addr uintptr -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_poll_trampoline), uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -348,9 +328,8 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { return } -func libc_poll_trampoline() +var libc_poll_trampoline_addr uintptr -//go:linkname libc_poll libc_poll //go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -362,16 +341,15 @@ func Madvise(b []byte, behav int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_madvise_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(behav)) + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_madvise_trampoline() +var libc_madvise_trampoline_addr uintptr -//go:linkname libc_madvise libc_madvise //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -383,31 +361,29 @@ func Mlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_mlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mlock_trampoline() +var libc_mlock_trampoline_addr uintptr -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_mlockall_trampoline), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mlockall_trampoline() +var libc_mlockall_trampoline_addr uintptr -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -419,16 +395,15 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_mprotect_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(prot)) + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mprotect_trampoline() +var libc_mprotect_trampoline_addr uintptr -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -440,16 +415,15 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_msync_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_msync_trampoline() +var libc_msync_trampoline_addr uintptr -//go:linkname libc_msync libc_msync //go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -461,63 +435,69 @@ func Munlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_munlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_munlock_trampoline() +var libc_munlock_trampoline_addr uintptr -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munlockall_trampoline), 0, 0, 0) + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_munlockall_trampoline() +var libc_munlockall_trampoline_addr uintptr -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) +func closedir(dir uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_closedir_trampoline_addr, uintptr(dir), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getattrlist_trampoline() +var libc_closedir_trampoline_addr uintptr -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (r int, w int, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) - r = int(r0) - w = int(r1) +func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { + r0, _, _ := syscall_syscall(libc_readdir_r_trampoline_addr, uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + res = Errno(r0) + return +} + +var libc_readdir_r_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]int32) (err error) { + _, _, e1 := syscall_rawSyscall(libc_pipe_trampoline_addr, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_pipe_trampoline() +var libc_pipe_trampoline_addr uintptr -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -533,7 +513,7 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_getxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + r0, _, e1 := syscall_syscall6(libc_getxattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -541,9 +521,8 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o return } -func libc_getxattr_trampoline() +var libc_getxattr_trampoline_addr uintptr -//go:linkname libc_getxattr libc_getxattr //go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -554,7 +533,7 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_fgetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + r0, _, e1 := syscall_syscall6(libc_fgetxattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -562,9 +541,8 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio return } -func libc_fgetxattr_trampoline() +var libc_fgetxattr_trampoline_addr uintptr -//go:linkname libc_fgetxattr libc_fgetxattr //go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -580,16 +558,15 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_setxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + _, _, e1 := syscall_syscall6(libc_setxattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setxattr_trampoline() +var libc_setxattr_trampoline_addr uintptr -//go:linkname libc_setxattr libc_setxattr //go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -600,16 +577,15 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fsetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + _, _, e1 := syscall_syscall6(libc_fsetxattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fsetxattr_trampoline() +var libc_fsetxattr_trampoline_addr uintptr -//go:linkname libc_fsetxattr libc_fsetxattr //go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -625,16 +601,15 @@ func removexattr(path string, attr string, options int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_removexattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + _, _, e1 := syscall_syscall(libc_removexattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_removexattr_trampoline() +var libc_removexattr_trampoline_addr uintptr -//go:linkname libc_removexattr libc_removexattr //go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -645,16 +620,15 @@ func fremovexattr(fd int, attr string, options int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_fremovexattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + _, _, e1 := syscall_syscall(libc_fremovexattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fremovexattr_trampoline() +var libc_fremovexattr_trampoline_addr uintptr -//go:linkname libc_fremovexattr libc_fremovexattr //go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -665,7 +639,7 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_listxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + r0, _, e1 := syscall_syscall6(libc_listxattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -673,15 +647,14 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro return } -func libc_listxattr_trampoline() +var libc_listxattr_trampoline_addr uintptr -//go:linkname libc_listxattr libc_listxattr //go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_flistxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + r0, _, e1 := syscall_syscall6(libc_flistxattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -689,30 +662,33 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { return } -func libc_flistxattr_trampoline() +var libc_flistxattr_trampoline_addr uintptr -//go:linkname libc_flistxattr libc_flistxattr //go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setattrlist_trampoline() +var libc_utimensat_trampoline_addr uintptr -//go:linkname libc_setattrlist libc_setattrlist -//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_utimensat utimensat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg)) + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -720,43 +696,98 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { return } -func libc_fcntl_trampoline() +var libc_fcntl_trampoline_addr uintptr -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_kill_trampoline), uintptr(pid), uintptr(signum), uintptr(posix)) + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_kill_trampoline() +var libc_kill_trampoline_addr uintptr -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ioctl_trampoline), uintptr(fd), uintptr(req), uintptr(arg)) + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_ioctl_trampoline() +var libc_ioctl_trampoline_addr uintptr -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renamexNp(from string, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renamex_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameatx_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -764,66 +795,174 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sysctl_trampoline() +var libc_sysctl_trampoline_addr uintptr -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) + _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sendfile_trampoline() +var libc_sendfile_trampoline_addr uintptr -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmdt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmget_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_access_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_access_trampoline() +var libc_access_trampoline_addr uintptr -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_adjtime_trampoline), uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_adjtime_trampoline() +var libc_adjtime_trampoline_addr uintptr -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -834,16 +973,15 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chdir_trampoline() +var libc_chdir_trampoline_addr uintptr -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -854,16 +992,15 @@ func Chflags(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chflags_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chflags_trampoline() +var libc_chflags_trampoline_addr uintptr -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -874,16 +1011,15 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chmod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chmod_trampoline() +var libc_chmod_trampoline_addr uintptr -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -894,16 +1030,15 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chown_trampoline() +var libc_chown_trampoline_addr uintptr -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -914,52 +1049,97 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chroot_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chroot_trampoline() +var libc_chroot_trampoline_addr uintptr -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ClockGettime(clockid int32, time *Timespec) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_clock_gettime_trampoline() +var libc_clock_gettime_trampoline_addr uintptr -//go:linkname libc_clock_gettime libc_clock_gettime //go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Close(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_close_trampoline() +var libc_close_trampoline_addr uintptr -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Clonefile(src string, dst string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(src) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dst) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_clonefile_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clonefile_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(src) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dst) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_clonefileat_trampoline_addr, uintptr(srcDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clonefileat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(fd int) (nfd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0) + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) nfd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -967,24 +1147,22 @@ func Dup(fd int) (nfd int, err error) { return } -func libc_dup_trampoline() +var libc_dup_trampoline_addr uintptr -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(from int, to int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_dup2_trampoline), uintptr(from), uintptr(to), 0) + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_dup2_trampoline() +var libc_dup2_trampoline_addr uintptr -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1000,28 +1178,26 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_exchangedata_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + _, _, e1 := syscall_syscall(libc_exchangedata_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_exchangedata_trampoline() +var libc_exchangedata_trampoline_addr uintptr -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - syscall_syscall(funcPC(libc_exit_trampoline), uintptr(code), 0, 0) + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) return } -func libc_exit_trampoline() +var libc_exit_trampoline_addr uintptr -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1032,61 +1208,57 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_faccessat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_faccessat_trampoline() +var libc_faccessat_trampoline_addr uintptr -//go:linkname libc_faccessat libc_faccessat //go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchdir_trampoline), uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchdir_trampoline() +var libc_fchdir_trampoline_addr uintptr -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchflags(fd int, flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchflags_trampoline), uintptr(fd), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchflags_trampoline() +var libc_fchflags_trampoline_addr uintptr -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchmod_trampoline), uintptr(fd), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchmod_trampoline() +var libc_fchmod_trampoline_addr uintptr -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1097,31 +1269,29 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fchmodat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchmodat_trampoline() +var libc_fchmodat_trampoline_addr uintptr -//go:linkname libc_fchmodat libc_fchmodat //go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchown_trampoline), uintptr(fd), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchown_trampoline() +var libc_fchown_trampoline_addr uintptr -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1132,37 +1302,54 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fchownat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchownat_trampoline() +var libc_fchownat_trampoline_addr uintptr -//go:linkname libc_fchownat libc_fchownat //go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(dst) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fclonefileat_trampoline_addr, uintptr(srcDirfd), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fclonefileat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_flock_trampoline() +var libc_flock_trampoline_addr uintptr -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fpathconf_trampoline), uintptr(fd), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1170,97 +1357,111 @@ func Fpathconf(fd int, name int) (val int, err error) { return } -func libc_fpathconf_trampoline() +var libc_fpathconf_trampoline_addr uintptr -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fsync_trampoline), uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fsync_trampoline() +var libc_fsync_trampoline_addr uintptr -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ftruncate_trampoline), uintptr(fd), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_ftruncate_trampoline() +var libc_ftruncate_trampoline_addr uintptr -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { - r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) + r0, _, _ := syscall_syscall(libc_getdtablesize_trampoline_addr, 0, 0, 0) size = int(r0) return } -func libc_getdtablesize_trampoline() +var libc_getdtablesize_trampoline_addr uintptr -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getegid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) egid = int(r0) return } -func libc_getegid_trampoline() +var libc_getegid_trampoline_addr uintptr -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_geteuid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } -func libc_geteuid_trampoline() +var libc_geteuid_trampoline_addr uintptr -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getgid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) gid = int(r0) return } -func libc_getgid_trampoline() +var libc_getgid_trampoline_addr uintptr -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getpgid_trampoline), uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) pgid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1268,54 +1469,50 @@ func Getpgid(pid int) (pgid int, err error) { return } -func libc_getpgid_trampoline() +var libc_getpgid_trampoline_addr uintptr -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pgrp int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpgrp_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) pgrp = int(r0) return } -func libc_getpgrp_trampoline() +var libc_getpgrp_trampoline_addr uintptr -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) pid = int(r0) return } -func libc_getpid_trampoline() +var libc_getpid_trampoline_addr uintptr -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getppid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) ppid = int(r0) return } -func libc_getppid_trampoline() +var libc_getppid_trampoline_addr uintptr -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getpriority_trampoline), uintptr(which), uintptr(who), 0) + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) prio = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1323,45 +1520,42 @@ func Getpriority(which int, who int) (prio int, err error) { return } -func libc_getpriority_trampoline() +var libc_getpriority_trampoline_addr uintptr -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getrlimit_trampoline() +var libc_getrlimit_trampoline_addr uintptr -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrusage_trampoline), uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getrusage_trampoline() +var libc_getrusage_trampoline_addr uintptr -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getsid_trampoline), uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) sid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1369,41 +1563,52 @@ func Getsid(pid int) (sid int, err error) { return } -func libc_getsid_trampoline() +var libc_getsid_trampoline_addr uintptr -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Gettimeofday(tp *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } -func libc_getuid_trampoline() +var libc_getuid_trampoline_addr uintptr -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_issetugid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_issetugid_trampoline_addr, 0, 0, 0) tainted = bool(r0 != 0) return } -func libc_issetugid_trampoline() +var libc_issetugid_trampoline_addr uintptr -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kqueue() (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_kqueue_trampoline), 0, 0, 0) + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1411,9 +1616,8 @@ func Kqueue() (fd int, err error) { return } -func libc_kqueue_trampoline() +var libc_kqueue_trampoline_addr uintptr -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1424,16 +1628,15 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_lchown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_lchown_trampoline() +var libc_lchown_trampoline_addr uintptr -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1449,16 +1652,15 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_link_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_link_trampoline() +var libc_link_trampoline_addr uintptr -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1474,31 +1676,29 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_linkat_trampoline), uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_linkat_trampoline() +var libc_linkat_trampoline_addr uintptr -//go:linkname libc_linkat libc_linkat //go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_listen_trampoline), uintptr(s), uintptr(backlog), 0) + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_listen_trampoline() +var libc_listen_trampoline_addr uintptr -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1509,16 +1709,15 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mkdir_trampoline() +var libc_mkdir_trampoline_addr uintptr -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1529,16 +1728,15 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mkdirat_trampoline() +var libc_mkdirat_trampoline_addr uintptr -//go:linkname libc_mkdirat libc_mkdirat //go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1549,16 +1747,15 @@ func Mkfifo(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mkfifo_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mkfifo_trampoline() +var libc_mkfifo_trampoline_addr uintptr -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1569,27 +1766,50 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mknod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mknod_trampoline() +var libc_mknod_trampoline_addr uintptr -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Open(path string, mode int, perm uint32) (fd int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - r0, _, e1 := syscall_syscall(funcPC(libc_open_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1597,9 +1817,8 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { return } -func libc_open_trampoline() +var libc_open_trampoline_addr uintptr -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1610,7 +1829,7 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_openat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1618,9 +1837,8 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { return } -func libc_openat_trampoline() +var libc_openat_trampoline_addr uintptr -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1631,7 +1849,7 @@ func Pathconf(path string, name int) (val int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall(funcPC(libc_pathconf_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1639,21 +1857,20 @@ func Pathconf(path string, name int) (val int, err error) { return } -func libc_pathconf_trampoline() +var libc_pathconf_trampoline_addr uintptr -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_pread_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1661,21 +1878,20 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { return } -func libc_pread_trampoline() +var libc_pread_trampoline_addr uintptr -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_pwrite_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1683,9 +1899,8 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { return } -func libc_pwrite_trampoline() +var libc_pwrite_trampoline_addr uintptr -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1697,7 +1912,7 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1705,9 +1920,8 @@ func read(fd int, p []byte) (n int, err error) { return } -func libc_read_trampoline() +var libc_read_trampoline_addr uintptr -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1724,7 +1938,7 @@ func Readlink(path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(funcPC(libc_readlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1732,9 +1946,8 @@ func Readlink(path string, buf []byte) (n int, err error) { return } -func libc_readlink_trampoline() +var libc_readlink_trampoline_addr uintptr -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1751,7 +1964,7 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_readlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1759,9 +1972,8 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { return } -func libc_readlinkat_trampoline() +var libc_readlinkat_trampoline_addr uintptr -//go:linkname libc_readlinkat libc_readlinkat //go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1777,16 +1989,15 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_rename_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_rename_trampoline() +var libc_rename_trampoline_addr uintptr -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1802,16 +2013,15 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_renameat_trampoline), uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_renameat_trampoline() +var libc_renameat_trampoline_addr uintptr -//go:linkname libc_renameat libc_renameat //go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1822,16 +2032,15 @@ func Revoke(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_revoke_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_revoke_trampoline() +var libc_revoke_trampoline_addr uintptr -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1842,22 +2051,21 @@ func Rmdir(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_rmdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_rmdir_trampoline() +var libc_rmdir_trampoline_addr uintptr -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_lseek_trampoline), uintptr(fd), uintptr(offset), uintptr(whence)) + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) newoffset = int64(r0) if e1 != 0 { err = errnoErr(e1) @@ -1865,15 +2073,14 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return } -func libc_lseek_trampoline() +var libc_lseek_trampoline_addr uintptr -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1881,54 +2088,75 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err return } -func libc_select_trampoline() +var libc_select_trampoline_addr uintptr -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(attrBuf) > 0 { + _p1 = unsafe.Pointer(&attrBuf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_setattrlist_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(attrlist)), uintptr(_p1), uintptr(len(attrBuf)), uintptr(options), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setattrlist_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Setegid(egid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setegid_trampoline), uintptr(egid), 0, 0) + _, _, e1 := syscall_syscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setegid_trampoline() +var libc_setegid_trampoline_addr uintptr -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seteuid(euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_seteuid_trampoline), uintptr(euid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_seteuid_trampoline() +var libc_seteuid_trampoline_addr uintptr -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(gid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgid_trampoline), uintptr(gid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setgid_trampoline() +var libc_setgid_trampoline_addr uintptr -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1939,112 +2167,91 @@ func Setlogin(name string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_setlogin_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setlogin_trampoline() +var libc_setlogin_trampoline_addr uintptr -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setpgid_trampoline), uintptr(pid), uintptr(pgid), 0) + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setpgid_trampoline() +var libc_setpgid_trampoline_addr uintptr -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setpriority_trampoline), uintptr(which), uintptr(who), uintptr(prio)) + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setpriority_trampoline() +var libc_setpriority_trampoline_addr uintptr -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setprivexec(flag int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setprivexec_trampoline), uintptr(flag), 0, 0) + _, _, e1 := syscall_syscall(libc_setprivexec_trampoline_addr, uintptr(flag), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setprivexec_trampoline() +var libc_setprivexec_trampoline_addr uintptr -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setregid_trampoline), uintptr(rgid), uintptr(egid), 0) + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setregid_trampoline() +var libc_setregid_trampoline_addr uintptr -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setreuid_trampoline), uintptr(ruid), uintptr(euid), 0) + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setreuid_trampoline() +var libc_setreuid_trampoline_addr uintptr -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setrlimit_trampoline() - -//go:linkname libc_setrlimit libc_setrlimit -//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_setsid_trampoline), 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) pid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2052,39 +2259,36 @@ func Setsid() (pid int, err error) { return } -func libc_setsid_trampoline() +var libc_setsid_trampoline_addr uintptr -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_settimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_settimeofday_trampoline() +var libc_settimeofday_trampoline_addr uintptr -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setuid_trampoline), uintptr(uid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setuid_trampoline() +var libc_setuid_trampoline_addr uintptr -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2100,16 +2304,15 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_symlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_symlink_trampoline() +var libc_symlink_trampoline_addr uintptr -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2125,31 +2328,29 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_symlinkat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } return } -func libc_symlinkat_trampoline() +var libc_symlinkat_trampoline_addr uintptr -//go:linkname libc_symlinkat libc_symlinkat //go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_sync_trampoline), 0, 0, 0) + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sync_trampoline() +var libc_sync_trampoline_addr uintptr -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2160,29 +2361,27 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_truncate_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_truncate_trampoline() +var libc_truncate_trampoline_addr uintptr -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(newmask int) (oldmask int) { - r0, _, _ := syscall_syscall(funcPC(libc_umask_trampoline), uintptr(newmask), 0, 0) + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) oldmask = int(r0) return } -func libc_umask_trampoline() +var libc_umask_trampoline_addr uintptr -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2193,16 +2392,15 @@ func Undelete(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_undelete_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_undelete_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_undelete_trampoline() +var libc_undelete_trampoline_addr uintptr -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2213,16 +2411,15 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_unlink_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_unlink_trampoline() +var libc_unlink_trampoline_addr uintptr -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2233,16 +2430,15 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_unlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_unlinkat_trampoline() +var libc_unlinkat_trampoline_addr uintptr -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2253,16 +2449,15 @@ func Unmount(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_unmount_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_unmount_trampoline() +var libc_unmount_trampoline_addr uintptr -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2274,7 +2469,7 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2282,15 +2477,14 @@ func write(fd int, p []byte) (n int, err error) { return } -func libc_write_trampoline() +var libc_write_trampoline_addr uintptr -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_mmap_trampoline), uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) ret = uintptr(r0) if e1 != 0 { err = errnoErr(e1) @@ -2298,30 +2492,34 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( return } -func libc_mmap_trampoline() +var libc_mmap_trampoline_addr uintptr -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munmap_trampoline), uintptr(addr), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_munmap_trampoline() +var libc_munmap_trampoline_addr uintptr -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func readv(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2329,10 +2527,20 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_readv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readv readv "/usr/lib/libSystem.B.dylib" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2340,51 +2548,64 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_preadv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_preadv preadv "/usr/lib/libSystem.B.dylib" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) +func writev(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_ptrace_trampoline() +var libc_writev_trampoline_addr uintptr -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int64(r0) - usec = int32(r1) +func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_gettimeofday_trampoline() +var libc_pwritev_trampoline_addr uintptr -//go:linkname libc_gettimeofday libc_gettimeofday -//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_pwritev pwritev "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstat64_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fstat64_trampoline() +var libc_fstat64_trampoline_addr uintptr -//go:linkname libc_fstat64 libc_fstat64 //go:cgo_import_dynamic libc_fstat64 fstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2395,37 +2616,35 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fstatat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fstatat64_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fstatat64_trampoline() +var libc_fstatat64_trampoline_addr uintptr -//go:linkname libc_fstatat64 libc_fstatat64 //go:cgo_import_dynamic libc_fstatat64 fstatat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstatfs64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstatfs64_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fstatfs64_trampoline() +var libc_fstatfs64_trampoline_addr uintptr -//go:linkname libc_fstatfs64 libc_fstatfs64 //go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_getfsstat64_trampoline_addr, uintptr(buf), uintptr(size), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2433,9 +2652,8 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { return } -func libc_getfsstat64_trampoline() +var libc_getfsstat64_trampoline_addr uintptr -//go:linkname libc_getfsstat64 libc_getfsstat64 //go:cgo_import_dynamic libc_getfsstat64 getfsstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2446,36 +2664,48 @@ func Lstat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_lstat64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_lstat64_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_lstat64_trampoline() +var libc_lstat64_trampoline_addr uintptr -//go:linkname libc_lstat64 libc_lstat64 //go:cgo_import_dynamic libc_lstat64 lstat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(libc_ptrace_trampoline_addr, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ptrace_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Stat(path string, stat *Stat_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_stat64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_stat64_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_stat64_trampoline() +var libc_stat64_trampoline_addr uintptr -//go:linkname libc_stat64 libc_stat64 //go:cgo_import_dynamic libc_stat64 stat64 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2486,14 +2716,13 @@ func Statfs(path string, stat *Statfs_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_statfs64_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_statfs64_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_statfs64_trampoline() +var libc_statfs64_trampoline_addr uintptr -//go:linkname libc_statfs64 libc_statfs64 //go:cgo_import_dynamic libc_statfs64 statfs64 "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index a3fdf09..fda3285 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -1,284 +1,799 @@ -// go run mkasm_darwin.go amd64 +// go run mkasm.go darwin amd64 // Code generated by the command above; DO NOT EDIT. -// +build go1.12 - #include "textflag.h" -TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0 + +TEXT libc_fdopendir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fdopendir(SB) +GLOBL ·libc_fdopendir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fdopendir_trampoline_addr(SB)/8, $libc_fdopendir_trampoline<>(SB) + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getgroups(SB) -TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setgroups(SB) -TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_wait4(SB) -TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_accept(SB) -TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_bind(SB) -TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_connect(SB) -TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_socket(SB) -TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getsockopt(SB) -TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setsockopt(SB) -TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpeername(SB) -TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getsockname(SB) -TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_shutdown(SB) -TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_socketpair(SB) -TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_recvfrom(SB) -TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendto(SB) -TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_recvmsg(SB) -TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) -TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) -TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_futimes(SB) -TEXT ·libc_poll_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_poll(SB) -TEXT ·libc_madvise_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_madvise(SB) -TEXT ·libc_mlock_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mlock(SB) -TEXT ·libc_mlockall_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mlockall(SB) -TEXT ·libc_mprotect_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mprotect(SB) -TEXT ·libc_msync_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_msync(SB) -TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) -TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) -TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_closedir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_closedir(SB) +GLOBL ·libc_closedir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_closedir_trampoline_addr(SB)/8, $libc_closedir_trampoline<>(SB) + +TEXT libc_readdir_r_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readdir_r(SB) +GLOBL ·libc_readdir_r_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readdir_r_trampoline_addr(SB)/8, $libc_readdir_r_trampoline<>(SB) + +TEXT libc_pipe_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) -TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pipe_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe_trampoline_addr(SB)/8, $libc_pipe_trampoline<>(SB) + +TEXT libc_getxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getxattr(SB) -TEXT ·libc_fgetxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getxattr_trampoline_addr(SB)/8, $libc_getxattr_trampoline<>(SB) + +TEXT libc_fgetxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fgetxattr(SB) -TEXT ·libc_setxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fgetxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fgetxattr_trampoline_addr(SB)/8, $libc_fgetxattr_trampoline<>(SB) + +TEXT libc_setxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setxattr(SB) -TEXT ·libc_fsetxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setxattr_trampoline_addr(SB)/8, $libc_setxattr_trampoline<>(SB) + +TEXT libc_fsetxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fsetxattr(SB) -TEXT ·libc_removexattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fsetxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsetxattr_trampoline_addr(SB)/8, $libc_fsetxattr_trampoline<>(SB) + +TEXT libc_removexattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_removexattr(SB) -TEXT ·libc_fremovexattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_removexattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_removexattr_trampoline_addr(SB)/8, $libc_removexattr_trampoline<>(SB) + +TEXT libc_fremovexattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fremovexattr(SB) -TEXT ·libc_listxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fremovexattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fremovexattr_trampoline_addr(SB)/8, $libc_fremovexattr_trampoline<>(SB) + +TEXT libc_listxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_listxattr(SB) -TEXT ·libc_flistxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_listxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listxattr_trampoline_addr(SB)/8, $libc_listxattr_trampoline<>(SB) + +TEXT libc_flistxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_flistxattr(SB) -TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setattrlist(SB) -TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_flistxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flistxattr_trampoline_addr(SB)/8, $libc_flistxattr_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fcntl(SB) -TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_kill(SB) -TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ioctl(SB) -TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renamex_np(SB) +GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB) + +TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameatx_np(SB) +GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sysctl(SB) -TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + +TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) -TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendfile_trampoline_addr(SB)/8, $libc_sendfile_trampoline<>(SB) + +TEXT libc_shmat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmat(SB) +GLOBL ·libc_shmat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmat_trampoline_addr(SB)/8, $libc_shmat_trampoline<>(SB) + +TEXT libc_shmctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmctl(SB) +GLOBL ·libc_shmctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmctl_trampoline_addr(SB)/8, $libc_shmctl_trampoline<>(SB) + +TEXT libc_shmdt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmdt(SB) +GLOBL ·libc_shmdt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmdt_trampoline_addr(SB)/8, $libc_shmdt_trampoline<>(SB) + +TEXT libc_shmget_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmget(SB) +GLOBL ·libc_shmget_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmget_trampoline_addr(SB)/8, $libc_shmget_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_access(SB) -TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_adjtime(SB) -TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chdir(SB) -TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chflags(SB) -TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chmod(SB) -TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chown(SB) -TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chroot(SB) -TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_clock_gettime(SB) -TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_close(SB) -TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_clonefile_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clonefile(SB) +GLOBL ·libc_clonefile_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clonefile_trampoline_addr(SB)/8, $libc_clonefile_trampoline<>(SB) + +TEXT libc_clonefileat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clonefileat(SB) +GLOBL ·libc_clonefileat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clonefileat_trampoline_addr(SB)/8, $libc_clonefileat_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_dup(SB) -TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_dup2(SB) -TEXT ·libc_exchangedata_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_exchangedata_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_exchangedata(SB) -TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_exchangedata_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exchangedata_trampoline_addr(SB)/8, $libc_exchangedata_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_exit(SB) -TEXT ·libc_faccessat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_faccessat(SB) -TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchdir(SB) -TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchflags(SB) -TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchmod(SB) -TEXT ·libc_fchmodat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchmodat(SB) -TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchown(SB) -TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchownat(SB) -TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_fclonefileat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fclonefileat(SB) +GLOBL ·libc_fclonefileat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fclonefileat_trampoline_addr(SB)/8, $libc_fclonefileat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_flock(SB) -TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fpathconf(SB) -TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fsync(SB) -TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ftruncate(SB) -TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getdtablesize_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getdtablesize(SB) -TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getdtablesize_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdtablesize_trampoline_addr(SB)/8, $libc_getdtablesize_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getegid(SB) -TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_geteuid(SB) -TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getgid(SB) -TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpgid(SB) -TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpgrp(SB) -TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpid(SB) -TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getppid(SB) -TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpriority(SB) -TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getrlimit(SB) -TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getrusage(SB) -TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getsid(SB) -TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getuid(SB) -TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_issetugid(SB) -TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_kqueue(SB) -TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_lchown(SB) -TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_link(SB) -TEXT ·libc_linkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_linkat(SB) -TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_listen(SB) -TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mkdir(SB) -TEXT ·libc_mkdirat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mkdirat(SB) -TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mkfifo(SB) -TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mknod(SB) -TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_open(SB) -TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_openat(SB) -TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pathconf(SB) -TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pread(SB) -TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pwrite(SB) -TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) -TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_readlink(SB) -TEXT ·libc_readlinkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_readlinkat(SB) -TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_rename(SB) -TEXT ·libc_renameat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_renameat(SB) -TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_revoke(SB) -TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_rmdir(SB) -TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_lseek(SB) -TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_select(SB) -TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setattrlist_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setattrlist(SB) +GLOBL ·libc_setattrlist_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setattrlist_trampoline_addr(SB)/8, $libc_setattrlist_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setegid(SB) -TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_seteuid(SB) -TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setgid(SB) -TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setlogin(SB) -TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setpgid(SB) -TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setpriority(SB) -TEXT ·libc_setprivexec_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setprivexec_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setprivexec(SB) -TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setprivexec_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setprivexec_trampoline_addr(SB)/8, $libc_setprivexec_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setregid(SB) -TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setreuid(SB) -TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setrlimit(SB) -TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setsid(SB) -TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_settimeofday(SB) -TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setuid(SB) -TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_symlink(SB) -TEXT ·libc_symlinkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_symlinkat(SB) -TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sync(SB) -TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_truncate(SB) -TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_umask(SB) -TEXT ·libc_undelete_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_undelete_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_undelete(SB) -TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_undelete_trampoline_addr(SB), RODATA, $8 +DATA ·libc_undelete_trampoline_addr(SB)/8, $libc_undelete_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_unlink(SB) -TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_unlinkat(SB) -TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_unmount(SB) -TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_write(SB) -TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) -TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) -TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 - JMP libc_gettimeofday(SB) -TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readv(SB) +GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) + +TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_preadv(SB) +GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) + +TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_writev(SB) +GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) + +TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwritev(SB) +GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) + +TEXT libc_fstat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstat64(SB) -TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fstat64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat64_trampoline_addr(SB)/8, $libc_fstat64_trampoline<>(SB) + +TEXT libc_fstatat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstatat64(SB) -TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fstatat64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat64_trampoline_addr(SB)/8, $libc_fstatat64_trampoline<>(SB) + +TEXT libc_fstatfs64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstatfs64(SB) -TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fstatfs64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs64_trampoline_addr(SB)/8, $libc_fstatfs64_trampoline<>(SB) + +TEXT libc_getfsstat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getfsstat64(SB) -TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getfsstat64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat64_trampoline_addr(SB)/8, $libc_getfsstat64_trampoline<>(SB) + +TEXT libc_lstat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_lstat64(SB) -TEXT ·libc_stat64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_lstat64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat64_trampoline_addr(SB)/8, $libc_lstat64_trampoline<>(SB) + +TEXT libc_ptrace_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) +GLOBL ·libc_ptrace_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ptrace_trampoline_addr(SB)/8, $libc_ptrace_trampoline<>(SB) + +TEXT libc_stat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_stat64(SB) -TEXT ·libc_statfs64_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_stat64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat64_trampoline_addr(SB)/8, $libc_stat64_trampoline<>(SB) + +TEXT libc_statfs64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_statfs64(SB) +GLOBL ·libc_statfs64_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs64_trampoline_addr(SB)/8, $libc_statfs64_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go deleted file mode 100644 index cea04e0..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go +++ /dev/null @@ -1,1784 +0,0 @@ -// go run mksyscall.go -l32 -tags darwin,arm,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm.1_11.go syscall_darwin_arm.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,arm,!go1.12 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) - wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func utimes(path string, timeval *[2]Timeval) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Madvise(b []byte, behav int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mprotect(b []byte, prot int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Msync(b []byte, flags int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (r int, w int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - r = int(r0) - w = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fremovexattr(fd int, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_SETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Access(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chflags(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chmod(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chroot(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) - nfd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exchangedata(path1 string, path2 string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path1) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(path2) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdtablesize() (size int) { - r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) - size = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) - egid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) - gid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) - pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) - pgrp = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) - pid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) - ppid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) - prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) - sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Issetugid() (tainted bool) { - r0, _, _ := RawSyscall(SYS_ISSETUGID, 0, 0, 0) - tainted = bool(r0 != 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lchown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Link(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdir(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdirat(dirfd int, path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkfifo(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Open(path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pathconf(path string, name int) (val int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pread(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func read(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rename(from string, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Renameat(fromfd int, from string, tofd int, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Revoke(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rmdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0) - newoffset = int64(int64(r1)<<32 | int64(r0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setegid(egid int) (err error) { - _, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setlogin(name string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setprivexec(flag int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIVEXEC, uintptr(flag), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) - pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlink(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(oldpath) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(newpath) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Truncate(path string, length int64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) - oldmask = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Undelete(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlink(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlinkat(dirfd int, path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unmount(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func write(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0) - ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { - r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int32(r0) - usec = int32(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(buf), uintptr(size), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lstat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Stat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Statfs(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go deleted file mode 100644 index f519ce9..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go +++ /dev/null @@ -1,41 +0,0 @@ -// go run mksyscall.go -l32 -tags darwin,arm,go1.13 syscall_darwin.1_13.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,arm,go1.13 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func closedir(dir uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_closedir_trampoline() - -//go:linkname libc_closedir libc_closedir -//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { - r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) - res = Errno(r0) - return -} - -func libc_readdir_r_trampoline() - -//go:linkname libc_readdir_r libc_readdir_r -//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s deleted file mode 100644 index 488e557..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s +++ /dev/null @@ -1,12 +0,0 @@ -// go run mkasm_darwin.go arm -// Code generated by the command above; DO NOT EDIT. - -// +build go1.13 - -#include "textflag.h" -TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fdopendir(SB) -TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_closedir(SB) -TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go deleted file mode 100644 index 6310395..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ /dev/null @@ -1,2484 +0,0 @@ -// go run mksyscall.go -l32 -tags darwin,arm,go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,arm,go1.12 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getgroups_trampoline() - -//go:linkname libc_getgroups libc_getgroups -//go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setgroups_trampoline() - -//go:linkname libc_setgroups libc_setgroups -//go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_wait4_trampoline), uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) - wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_wait4_trampoline() - -//go:linkname libc_wait4 libc_wait4 -//go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_accept_trampoline), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_accept_trampoline() - -//go:linkname libc_accept libc_accept -//go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_bind_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_bind_trampoline() - -//go:linkname libc_bind libc_bind -//go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_connect_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_connect_trampoline() - -//go:linkname libc_connect libc_connect -//go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_socket_trampoline), uintptr(domain), uintptr(typ), uintptr(proto)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_socket_trampoline() - -//go:linkname libc_socket libc_socket -//go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getsockopt_trampoline() - -//go:linkname libc_getsockopt libc_getsockopt -//go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setsockopt_trampoline() - -//go:linkname libc_setsockopt libc_setsockopt -//go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getpeername_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getpeername_trampoline() - -//go:linkname libc_getpeername libc_getpeername -//go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getsockname_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getsockname_trampoline() - -//go:linkname libc_getsockname libc_getsockname -//go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Shutdown(s int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_shutdown_trampoline), uintptr(s), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_shutdown_trampoline() - -//go:linkname libc_shutdown libc_shutdown -//go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := syscall_rawSyscall6(funcPC(libc_socketpair_trampoline), uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_socketpair_trampoline() - -//go:linkname libc_socketpair libc_socketpair -//go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_recvfrom_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_recvfrom_trampoline() - -//go:linkname libc_recvfrom libc_recvfrom -//go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc_sendto_trampoline), uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sendto_trampoline() - -//go:linkname libc_sendto libc_sendto -//go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_recvmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_recvmsg_trampoline() - -//go:linkname libc_recvmsg libc_recvmsg -//go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_sendmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sendmsg_trampoline() - -//go:linkname libc_sendmsg libc_sendmsg -//go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_kevent_trampoline), uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_kevent_trampoline() - -//go:linkname libc_kevent libc_kevent -//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func utimes(path string, timeval *[2]Timeval) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_utimes_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_utimes_trampoline() - -//go:linkname libc_utimes libc_utimes -//go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_futimes_trampoline), uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_futimes_trampoline() - -//go:linkname libc_futimes libc_futimes -//go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_poll_trampoline), uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_poll_trampoline() - -//go:linkname libc_poll libc_poll -//go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Madvise(b []byte, behav int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_madvise_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(behav)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_madvise_trampoline() - -//go:linkname libc_madvise libc_madvise -//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_mlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mlock_trampoline() - -//go:linkname libc_mlock libc_mlock -//go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlockall(flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_mlockall_trampoline), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mlockall_trampoline() - -//go:linkname libc_mlockall libc_mlockall -//go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mprotect(b []byte, prot int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_mprotect_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mprotect_trampoline() - -//go:linkname libc_mprotect libc_mprotect -//go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Msync(b []byte, flags int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_msync_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_msync_trampoline() - -//go:linkname libc_msync libc_msync -//go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(funcPC(libc_munlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_munlock_trampoline() - -//go:linkname libc_munlock libc_munlock -//go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlockall() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munlockall_trampoline), 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_munlockall_trampoline() - -//go:linkname libc_munlockall libc_munlockall -//go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getattrlist_trampoline() - -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (r int, w int, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) - r = int(r0) - w = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pipe_trampoline() - -//go:linkname libc_pipe libc_pipe -//go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_getxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getxattr_trampoline() - -//go:linkname libc_getxattr libc_getxattr -//go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_fgetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fgetxattr_trampoline() - -//go:linkname libc_fgetxattr libc_fgetxattr -//go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_setxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setxattr_trampoline() - -//go:linkname libc_setxattr libc_setxattr -//go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fsetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fsetxattr_trampoline() - -//go:linkname libc_fsetxattr libc_fsetxattr -//go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_removexattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_removexattr_trampoline() - -//go:linkname libc_removexattr libc_removexattr -//go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fremovexattr(fd int, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_fremovexattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fremovexattr_trampoline() - -//go:linkname libc_fremovexattr libc_fremovexattr -//go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_listxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_listxattr_trampoline() - -//go:linkname libc_listxattr libc_listxattr -//go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_flistxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_flistxattr_trampoline() - -//go:linkname libc_flistxattr libc_flistxattr -//go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setattrlist_trampoline() - -//go:linkname libc_setattrlist libc_setattrlist -//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg)) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fcntl_trampoline() - -//go:linkname libc_fcntl libc_fcntl -//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_kill_trampoline), uintptr(pid), uintptr(signum), uintptr(posix)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_kill_trampoline() - -//go:linkname libc_kill libc_kill -//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ioctl_trampoline), uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ioctl_trampoline() - -//go:linkname libc_ioctl libc_ioctl -//go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sysctl_trampoline() - -//go:linkname libc_sysctl libc_sysctl -//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := syscall_syscall9(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(offset>>32), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sendfile_trampoline() - -//go:linkname libc_sendfile libc_sendfile -//go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Access(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_access_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_access_trampoline() - -//go:linkname libc_access libc_access -//go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_adjtime_trampoline), uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_adjtime_trampoline() - -//go:linkname libc_adjtime libc_adjtime -//go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chdir_trampoline() - -//go:linkname libc_chdir libc_chdir -//go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chflags(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chflags_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chflags_trampoline() - -//go:linkname libc_chflags libc_chflags -//go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chmod(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chmod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chmod_trampoline() - -//go:linkname libc_chmod libc_chmod -//go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chown_trampoline() - -//go:linkname libc_chown libc_chown -//go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chroot(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_chroot_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_chroot_trampoline() - -//go:linkname libc_chroot libc_chroot -//go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ClockGettime(clockid int32, time *Timespec) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_clock_gettime_trampoline() - -//go:linkname libc_clock_gettime libc_clock_gettime -//go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Close(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_close_trampoline() - -//go:linkname libc_close libc_close -//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup(fd int) (nfd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0) - nfd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_dup_trampoline() - -//go:linkname libc_dup libc_dup -//go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup2(from int, to int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_dup2_trampoline), uintptr(from), uintptr(to), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_dup2_trampoline() - -//go:linkname libc_dup2 libc_dup2 -//go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exchangedata(path1 string, path2 string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path1) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(path2) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_exchangedata_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_exchangedata_trampoline() - -//go:linkname libc_exchangedata libc_exchangedata -//go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exit(code int) { - syscall_syscall(funcPC(libc_exit_trampoline), uintptr(code), 0, 0) - return -} - -func libc_exit_trampoline() - -//go:linkname libc_exit libc_exit -//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_faccessat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_faccessat_trampoline() - -//go:linkname libc_faccessat libc_faccessat -//go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchdir(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchdir_trampoline), uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchdir_trampoline() - -//go:linkname libc_fchdir libc_fchdir -//go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchflags(fd int, flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchflags_trampoline), uintptr(fd), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchflags_trampoline() - -//go:linkname libc_fchflags libc_fchflags -//go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchmod_trampoline), uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchmod_trampoline() - -//go:linkname libc_fchmod libc_fchmod -//go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fchmodat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchmodat_trampoline() - -//go:linkname libc_fchmodat libc_fchmodat -//go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchown_trampoline), uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchown_trampoline() - -//go:linkname libc_fchown libc_fchown -//go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fchownat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fchownat_trampoline() - -//go:linkname libc_fchownat libc_fchownat -//go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Flock(fd int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_flock_trampoline() - -//go:linkname libc_flock libc_flock -//go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fpathconf_trampoline), uintptr(fd), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fpathconf_trampoline() - -//go:linkname libc_fpathconf libc_fpathconf -//go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fsync(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fsync_trampoline), uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fsync_trampoline() - -//go:linkname libc_fsync libc_fsync -//go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ftruncate_trampoline), uintptr(fd), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ftruncate_trampoline() - -//go:linkname libc_ftruncate libc_ftruncate -//go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdtablesize() (size int) { - r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) - size = int(r0) - return -} - -func libc_getdtablesize_trampoline() - -//go:linkname libc_getdtablesize libc_getdtablesize -//go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getegid() (egid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getegid_trampoline), 0, 0, 0) - egid = int(r0) - return -} - -func libc_getegid_trampoline() - -//go:linkname libc_getegid libc_getegid -//go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Geteuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_geteuid_trampoline), 0, 0, 0) - uid = int(r0) - return -} - -func libc_geteuid_trampoline() - -//go:linkname libc_geteuid libc_geteuid -//go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getgid() (gid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getgid_trampoline), 0, 0, 0) - gid = int(r0) - return -} - -func libc_getgid_trampoline() - -//go:linkname libc_getgid libc_getgid -//go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getpgid_trampoline), uintptr(pid), 0, 0) - pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getpgid_trampoline() - -//go:linkname libc_getpgid libc_getpgid -//go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgrp() (pgrp int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpgrp_trampoline), 0, 0, 0) - pgrp = int(r0) - return -} - -func libc_getpgrp_trampoline() - -//go:linkname libc_getpgrp libc_getpgrp -//go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpid() (pid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpid_trampoline), 0, 0, 0) - pid = int(r0) - return -} - -func libc_getpid_trampoline() - -//go:linkname libc_getpid libc_getpid -//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getppid() (ppid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getppid_trampoline), 0, 0, 0) - ppid = int(r0) - return -} - -func libc_getppid_trampoline() - -//go:linkname libc_getppid libc_getppid -//go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getpriority_trampoline), uintptr(which), uintptr(who), 0) - prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getpriority_trampoline() - -//go:linkname libc_getpriority libc_getpriority -//go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getrlimit_trampoline() - -//go:linkname libc_getrlimit libc_getrlimit -//go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrusage_trampoline), uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getrusage_trampoline() - -//go:linkname libc_getrusage libc_getrusage -//go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getsid(pid int) (sid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getsid_trampoline), uintptr(pid), 0, 0) - sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getsid_trampoline() - -//go:linkname libc_getsid libc_getsid -//go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0) - uid = int(r0) - return -} - -func libc_getuid_trampoline() - -//go:linkname libc_getuid libc_getuid -//go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Issetugid() (tainted bool) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_issetugid_trampoline), 0, 0, 0) - tainted = bool(r0 != 0) - return -} - -func libc_issetugid_trampoline() - -//go:linkname libc_issetugid libc_issetugid -//go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Kqueue() (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_kqueue_trampoline), 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_kqueue_trampoline() - -//go:linkname libc_kqueue libc_kqueue -//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lchown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_lchown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_lchown_trampoline() - -//go:linkname libc_lchown libc_lchown -//go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Link(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_link_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_link_trampoline() - -//go:linkname libc_link libc_link -//go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_linkat_trampoline), uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_linkat_trampoline() - -//go:linkname libc_linkat libc_linkat -//go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Listen(s int, backlog int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_listen_trampoline), uintptr(s), uintptr(backlog), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_listen_trampoline() - -//go:linkname libc_listen libc_listen -//go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdir(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mkdir_trampoline() - -//go:linkname libc_mkdir libc_mkdir -//go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdirat(dirfd int, path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mkdirat_trampoline() - -//go:linkname libc_mkdirat libc_mkdirat -//go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkfifo(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mkfifo_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mkfifo_trampoline() - -//go:linkname libc_mkfifo libc_mkfifo -//go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_mknod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mknod_trampoline() - -//go:linkname libc_mknod libc_mknod -//go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Open(path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall(funcPC(libc_open_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_open_trampoline() - -//go:linkname libc_open libc_open -//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall6(funcPC(libc_openat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_openat_trampoline() - -//go:linkname libc_openat libc_openat -//go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pathconf(path string, name int) (val int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := syscall_syscall(funcPC(libc_pathconf_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pathconf_trampoline() - -//go:linkname libc_pathconf libc_pathconf -//go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pread(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_pread_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pread_trampoline() - -//go:linkname libc_pread libc_pread -//go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_pwrite_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_pwrite_trampoline() - -//go:linkname libc_pwrite libc_pwrite -//go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func read(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_read_trampoline() - -//go:linkname libc_read libc_read -//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(funcPC(libc_readlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_readlink_trampoline() - -//go:linkname libc_readlink libc_readlink -//go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(funcPC(libc_readlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_readlinkat_trampoline() - -//go:linkname libc_readlinkat libc_readlinkat -//go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rename(from string, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_rename_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_rename_trampoline() - -//go:linkname libc_rename libc_rename -//go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Renameat(fromfd int, from string, tofd int, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_renameat_trampoline), uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_renameat_trampoline() - -//go:linkname libc_renameat libc_renameat -//go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Revoke(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_revoke_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_revoke_trampoline() - -//go:linkname libc_revoke libc_revoke -//go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rmdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_rmdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_rmdir_trampoline() - -//go:linkname libc_rmdir libc_rmdir -//go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, r1, e1 := syscall_syscall6(funcPC(libc_lseek_trampoline), uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0) - newoffset = int64(int64(r1)<<32 | int64(r0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_lseek_trampoline() - -//go:linkname libc_lseek libc_lseek -//go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_select_trampoline() - -//go:linkname libc_select libc_select -//go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setegid(egid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setegid_trampoline), uintptr(egid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setegid_trampoline() - -//go:linkname libc_setegid libc_setegid -//go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seteuid(euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_seteuid_trampoline), uintptr(euid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_seteuid_trampoline() - -//go:linkname libc_seteuid libc_seteuid -//go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setgid(gid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgid_trampoline), uintptr(gid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setgid_trampoline() - -//go:linkname libc_setgid libc_setgid -//go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setlogin(name string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_setlogin_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setlogin_trampoline() - -//go:linkname libc_setlogin libc_setlogin -//go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setpgid_trampoline), uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setpgid_trampoline() - -//go:linkname libc_setpgid libc_setpgid -//go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setpriority_trampoline), uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setpriority_trampoline() - -//go:linkname libc_setpriority libc_setpriority -//go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setprivexec(flag int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setprivexec_trampoline), uintptr(flag), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setprivexec_trampoline() - -//go:linkname libc_setprivexec libc_setprivexec -//go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setregid_trampoline), uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setregid_trampoline() - -//go:linkname libc_setregid libc_setregid -//go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setreuid_trampoline), uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setreuid_trampoline() - -//go:linkname libc_setreuid libc_setreuid -//go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setrlimit_trampoline() - -//go:linkname libc_setrlimit libc_setrlimit -//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setsid() (pid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_setsid_trampoline), 0, 0, 0) - pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setsid_trampoline() - -//go:linkname libc_setsid libc_setsid -//go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_settimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_settimeofday_trampoline() - -//go:linkname libc_settimeofday libc_settimeofday -//go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setuid(uid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setuid_trampoline), uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setuid_trampoline() - -//go:linkname libc_setuid libc_setuid -//go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlink(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_symlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_symlink_trampoline() - -//go:linkname libc_symlink libc_symlink -//go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(oldpath) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(newpath) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_symlinkat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_symlinkat_trampoline() - -//go:linkname libc_symlinkat libc_symlinkat -//go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Sync() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_sync_trampoline), 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_sync_trampoline() - -//go:linkname libc_sync libc_sync -//go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Truncate(path string, length int64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_truncate_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_truncate_trampoline() - -//go:linkname libc_truncate libc_truncate -//go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Umask(newmask int) (oldmask int) { - r0, _, _ := syscall_syscall(funcPC(libc_umask_trampoline), uintptr(newmask), 0, 0) - oldmask = int(r0) - return -} - -func libc_umask_trampoline() - -//go:linkname libc_umask libc_umask -//go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Undelete(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_undelete_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_undelete_trampoline() - -//go:linkname libc_undelete libc_undelete -//go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlink(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_unlink_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_unlink_trampoline() - -//go:linkname libc_unlink libc_unlink -//go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlinkat(dirfd int, path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_unlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_unlinkat_trampoline() - -//go:linkname libc_unlinkat libc_unlinkat -//go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unmount(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_unmount_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_unmount_trampoline() - -//go:linkname libc_unmount libc_unmount -//go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func write(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_write_trampoline() - -//go:linkname libc_write libc_write -//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := syscall_syscall9(funcPC(libc_mmap_trampoline), uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0) - ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_mmap_trampoline() - -//go:linkname libc_mmap libc_mmap -//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munmap_trampoline), uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_munmap_trampoline() - -//go:linkname libc_munmap libc_munmap -//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int32(r0) - usec = int32(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_gettimeofday_trampoline() - -//go:linkname libc_gettimeofday libc_gettimeofday -//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fstat_trampoline() - -//go:linkname libc_fstat libc_fstat -//go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(funcPC(libc_fstatat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fstatat_trampoline() - -//go:linkname libc_fstatat libc_fstatat -//go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstatfs_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_fstatfs_trampoline() - -//go:linkname libc_fstatfs libc_fstatfs -//go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat_trampoline), uintptr(buf), uintptr(size), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getfsstat_trampoline() - -//go:linkname libc_getfsstat libc_getfsstat -//go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lstat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_lstat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_lstat_trampoline() - -//go:linkname libc_lstat libc_lstat -//go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Stat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_stat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_stat_trampoline() - -//go:linkname libc_stat libc_stat -//go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Statfs(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(funcPC(libc_statfs_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_statfs_trampoline() - -//go:linkname libc_statfs libc_statfs -//go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s deleted file mode 100644 index b67f518..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s +++ /dev/null @@ -1,282 +0,0 @@ -// go run mkasm_darwin.go arm -// Code generated by the command above; DO NOT EDIT. - -// +build go1.12 - -#include "textflag.h" -TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getgroups(SB) -TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setgroups(SB) -TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0 - JMP libc_wait4(SB) -TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0 - JMP libc_accept(SB) -TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0 - JMP libc_bind(SB) -TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0 - JMP libc_connect(SB) -TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0 - JMP libc_socket(SB) -TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getsockopt(SB) -TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setsockopt(SB) -TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpeername(SB) -TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getsockname(SB) -TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_shutdown(SB) -TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0 - JMP libc_socketpair(SB) -TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0 - JMP libc_recvfrom(SB) -TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sendto(SB) -TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0 - JMP libc_recvmsg(SB) -TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sendmsg(SB) -TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 - JMP libc_kevent(SB) -TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 - JMP libc_utimes(SB) -TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 - JMP libc_futimes(SB) -TEXT ·libc_poll_trampoline(SB),NOSPLIT,$0-0 - JMP libc_poll(SB) -TEXT ·libc_madvise_trampoline(SB),NOSPLIT,$0-0 - JMP libc_madvise(SB) -TEXT ·libc_mlock_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mlock(SB) -TEXT ·libc_mlockall_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mlockall(SB) -TEXT ·libc_mprotect_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mprotect(SB) -TEXT ·libc_msync_trampoline(SB),NOSPLIT,$0-0 - JMP libc_msync(SB) -TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 - JMP libc_munlock(SB) -TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 - JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) -TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pipe(SB) -TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getxattr(SB) -TEXT ·libc_fgetxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fgetxattr(SB) -TEXT ·libc_setxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setxattr(SB) -TEXT ·libc_fsetxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fsetxattr(SB) -TEXT ·libc_removexattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_removexattr(SB) -TEXT ·libc_fremovexattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fremovexattr(SB) -TEXT ·libc_listxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_listxattr(SB) -TEXT ·libc_flistxattr_trampoline(SB),NOSPLIT,$0-0 - JMP libc_flistxattr(SB) -TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setattrlist(SB) -TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fcntl(SB) -TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 - JMP libc_kill(SB) -TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ioctl(SB) -TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sysctl(SB) -TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sendfile(SB) -TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 - JMP libc_access(SB) -TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0 - JMP libc_adjtime(SB) -TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chdir(SB) -TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chflags(SB) -TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chmod(SB) -TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chown(SB) -TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 - JMP libc_chroot(SB) -TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 - JMP libc_clock_gettime(SB) -TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 - JMP libc_close(SB) -TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 - JMP libc_dup(SB) -TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0 - JMP libc_dup2(SB) -TEXT ·libc_exchangedata_trampoline(SB),NOSPLIT,$0-0 - JMP libc_exchangedata(SB) -TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_exit(SB) -TEXT ·libc_faccessat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_faccessat(SB) -TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchdir(SB) -TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchflags(SB) -TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchmod(SB) -TEXT ·libc_fchmodat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchmodat(SB) -TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchown(SB) -TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fchownat(SB) -TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0 - JMP libc_flock(SB) -TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fpathconf(SB) -TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fsync(SB) -TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ftruncate(SB) -TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getdtablesize(SB) -TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getegid(SB) -TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_geteuid(SB) -TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getgid(SB) -TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpgid(SB) -TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpgrp(SB) -TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpid(SB) -TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getppid(SB) -TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getpriority(SB) -TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getrlimit(SB) -TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getrusage(SB) -TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getsid(SB) -TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getuid(SB) -TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_issetugid(SB) -TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0 - JMP libc_kqueue(SB) -TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0 - JMP libc_lchown(SB) -TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0 - JMP libc_link(SB) -TEXT ·libc_linkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_linkat(SB) -TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0 - JMP libc_listen(SB) -TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mkdir(SB) -TEXT ·libc_mkdirat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mkdirat(SB) -TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mkfifo(SB) -TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mknod(SB) -TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0 - JMP libc_open(SB) -TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_openat(SB) -TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pathconf(SB) -TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pread(SB) -TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0 - JMP libc_pwrite(SB) -TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0 - JMP libc_read(SB) -TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readlink(SB) -TEXT ·libc_readlinkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readlinkat(SB) -TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0 - JMP libc_rename(SB) -TEXT ·libc_renameat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_renameat(SB) -TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0 - JMP libc_revoke(SB) -TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_rmdir(SB) -TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0 - JMP libc_lseek(SB) -TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0 - JMP libc_select(SB) -TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setegid(SB) -TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_seteuid(SB) -TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setgid(SB) -TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setlogin(SB) -TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setpgid(SB) -TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setpriority(SB) -TEXT ·libc_setprivexec_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setprivexec(SB) -TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setregid(SB) -TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setreuid(SB) -TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setrlimit(SB) -TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setsid(SB) -TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0 - JMP libc_settimeofday(SB) -TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setuid(SB) -TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0 - JMP libc_symlink(SB) -TEXT ·libc_symlinkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_symlinkat(SB) -TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0 - JMP libc_sync(SB) -TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0 - JMP libc_truncate(SB) -TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0 - JMP libc_umask(SB) -TEXT ·libc_undelete_trampoline(SB),NOSPLIT,$0-0 - JMP libc_undelete(SB) -TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0 - JMP libc_unlink(SB) -TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_unlinkat(SB) -TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0 - JMP libc_unmount(SB) -TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0 - JMP libc_write(SB) -TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 - JMP libc_mmap(SB) -TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 - JMP libc_munmap(SB) -TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 - JMP libc_gettimeofday(SB) -TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fstat(SB) -TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fstatat(SB) -TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fstatfs(SB) -TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getfsstat(SB) -TEXT ·libc_lstat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_lstat(SB) -TEXT ·libc_stat_trampoline(SB),NOSPLIT,$0-0 - JMP libc_stat(SB) -TEXT ·libc_statfs_trampoline(SB),NOSPLIT,$0-0 - JMP libc_statfs(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go deleted file mode 100644 index 8c3bb3a..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go +++ /dev/null @@ -1,1784 +0,0 @@ -// go run mksyscall.go -tags darwin,arm64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.1_11.go syscall_darwin_arm64.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,arm64,!go1.12 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) - wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func utimes(path string, timeval *[2]Timeval) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Madvise(b []byte, behav int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mprotect(b []byte, prot int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Msync(b []byte, flags int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlock(b []byte) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (r int, w int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - r = int(r0) - w = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fremovexattr(fd int, attr string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_SETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Access(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chflags(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chmod(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Chroot(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) - nfd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exchangedata(path1 string, path2 string, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path1) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(path2) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdtablesize() (size int) { - r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) - size = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) - egid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) - gid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) - pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) - pgrp = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) - pid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) - ppid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) - prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) - sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Issetugid() (tainted bool) { - r0, _, _ := RawSyscall(SYS_ISSETUGID, 0, 0, 0) - tainted = bool(r0 != 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lchown(path string, uid int, gid int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Link(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdir(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkdirat(dirfd int, path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mkfifo(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Open(path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pathconf(path string, name int) (val int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) - val = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pread(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func read(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rename(from string, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Renameat(fromfd int, from string, tofd int, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Revoke(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rmdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence)) - newoffset = int64(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setegid(egid int) (err error) { - _, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setlogin(name string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setprivexec(flag int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIVEXEC, uintptr(flag), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) - pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlink(path string, link string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(link) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(oldpath) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(newpath) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Truncate(path string, length int64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) - oldmask = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Undelete(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlink(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unlinkat(dirfd int, path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Unmount(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func write(fd int, p []byte) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) - ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { - r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int64(r0) - usec = int32(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(buf), uintptr(size), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lstat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Stat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Statfs(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go deleted file mode 100644 index d64e6c8..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go +++ /dev/null @@ -1,41 +0,0 @@ -// go run mksyscall.go -tags darwin,arm64,go1.13 syscall_darwin.1_13.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build darwin,arm64,go1.13 - -package unix - -import ( - "syscall" - "unsafe" -) - -var _ syscall.Errno - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func closedir(dir uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_closedir_trampoline() - -//go:linkname libc_closedir libc_closedir -//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { - r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) - res = Errno(r0) - return -} - -func libc_readdir_r_trampoline() - -//go:linkname libc_readdir_r libc_readdir_r -//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s deleted file mode 100644 index b29dabb..0000000 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s +++ /dev/null @@ -1,12 +0,0 @@ -// go run mkasm_darwin.go arm64 -// Code generated by the command above; DO NOT EDIT. - -// +build go1.13 - -#include "textflag.h" -TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_fdopendir(SB) -TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0 - JMP libc_closedir(SB) -TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0 - JMP libc_readdir_r(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index a8709f7..e6f58f3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags darwin,arm64,go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.go +// go run mksyscall.go -tags darwin,arm64 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build darwin,arm64,go1.12 +//go:build darwin && arm64 package unix @@ -15,7 +15,7 @@ var _ syscall.Errno // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -23,30 +23,28 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { return } -func libc_getgroups_trampoline() +var libc_getgroups_trampoline_addr uintptr -//go:linkname libc_getgroups libc_getgroups //go:cgo_import_dynamic libc_getgroups getgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgroups_trampoline), uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setgroups_trampoline() +var libc_setgroups_trampoline_addr uintptr -//go:linkname libc_setgroups libc_setgroups //go:cgo_import_dynamic libc_setgroups setgroups "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_wait4_trampoline), uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -54,15 +52,14 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err return } -func libc_wait4_trampoline() +var libc_wait4_trampoline_addr uintptr -//go:linkname libc_wait4 libc_wait4 //go:cgo_import_dynamic libc_wait4 wait4 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_accept_trampoline), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -70,45 +67,42 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { return } -func libc_accept_trampoline() +var libc_accept_trampoline_addr uintptr -//go:linkname libc_accept libc_accept //go:cgo_import_dynamic libc_accept accept "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_bind_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_bind_trampoline() +var libc_bind_trampoline_addr uintptr -//go:linkname libc_bind libc_bind //go:cgo_import_dynamic libc_bind bind "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_connect_trampoline), uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_connect_trampoline() +var libc_connect_trampoline_addr uintptr -//go:linkname libc_connect libc_connect //go:cgo_import_dynamic libc_connect connect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_socket_trampoline), uintptr(domain), uintptr(typ), uintptr(proto)) + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -116,99 +110,92 @@ func socket(domain int, typ int, proto int) (fd int, err error) { return } -func libc_socket_trampoline() +var libc_socket_trampoline_addr uintptr -//go:linkname libc_socket libc_socket //go:cgo_import_dynamic libc_socket socket "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getsockopt_trampoline() +var libc_getsockopt_trampoline_addr uintptr -//go:linkname libc_getsockopt libc_getsockopt //go:cgo_import_dynamic libc_getsockopt getsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setsockopt_trampoline), uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setsockopt_trampoline() +var libc_setsockopt_trampoline_addr uintptr -//go:linkname libc_setsockopt libc_setsockopt //go:cgo_import_dynamic libc_setsockopt setsockopt "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getpeername_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getpeername_trampoline() +var libc_getpeername_trampoline_addr uintptr -//go:linkname libc_getpeername libc_getpeername //go:cgo_import_dynamic libc_getpeername getpeername "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getsockname_trampoline), uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getsockname_trampoline() +var libc_getsockname_trampoline_addr uintptr -//go:linkname libc_getsockname libc_getsockname //go:cgo_import_dynamic libc_getsockname getsockname "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(s int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_shutdown_trampoline), uintptr(s), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_shutdown_trampoline() +var libc_shutdown_trampoline_addr uintptr -//go:linkname libc_shutdown libc_shutdown //go:cgo_import_dynamic libc_shutdown shutdown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := syscall_rawSyscall6(funcPC(libc_socketpair_trampoline), uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_socketpair_trampoline() +var libc_socketpair_trampoline_addr uintptr -//go:linkname libc_socketpair libc_socketpair //go:cgo_import_dynamic libc_socketpair socketpair "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -220,7 +207,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_recvfrom_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -228,9 +215,8 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl return } -func libc_recvfrom_trampoline() +var libc_recvfrom_trampoline_addr uintptr -//go:linkname libc_recvfrom libc_recvfrom //go:cgo_import_dynamic libc_recvfrom recvfrom "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -242,22 +228,21 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall6(funcPC(libc_sendto_trampoline), uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sendto_trampoline() +var libc_sendto_trampoline_addr uintptr -//go:linkname libc_sendto libc_sendto //go:cgo_import_dynamic libc_sendto sendto "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_recvmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -265,15 +250,14 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } -func libc_recvmsg_trampoline() +var libc_recvmsg_trampoline_addr uintptr -//go:linkname libc_recvmsg libc_recvmsg //go:cgo_import_dynamic libc_recvmsg recvmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_sendmsg_trampoline), uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -281,15 +265,14 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } -func libc_sendmsg_trampoline() +var libc_sendmsg_trampoline_addr uintptr -//go:linkname libc_sendmsg libc_sendmsg //go:cgo_import_dynamic libc_sendmsg sendmsg "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_kevent_trampoline), uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -297,9 +280,8 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne return } -func libc_kevent_trampoline() +var libc_kevent_trampoline_addr uintptr -//go:linkname libc_kevent libc_kevent //go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -310,37 +292,35 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_utimes_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_utimes_trampoline() +var libc_utimes_trampoline_addr uintptr -//go:linkname libc_utimes libc_utimes //go:cgo_import_dynamic libc_utimes utimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_futimes_trampoline), uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_futimes_trampoline() +var libc_futimes_trampoline_addr uintptr -//go:linkname libc_futimes libc_futimes //go:cgo_import_dynamic libc_futimes futimes "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_poll_trampoline), uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -348,9 +328,8 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { return } -func libc_poll_trampoline() +var libc_poll_trampoline_addr uintptr -//go:linkname libc_poll libc_poll //go:cgo_import_dynamic libc_poll poll "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -362,16 +341,15 @@ func Madvise(b []byte, behav int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_madvise_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(behav)) + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_madvise_trampoline() +var libc_madvise_trampoline_addr uintptr -//go:linkname libc_madvise libc_madvise //go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -383,31 +361,29 @@ func Mlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_mlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mlock_trampoline() +var libc_mlock_trampoline_addr uintptr -//go:linkname libc_mlock libc_mlock //go:cgo_import_dynamic libc_mlock mlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_mlockall_trampoline), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mlockall_trampoline() +var libc_mlockall_trampoline_addr uintptr -//go:linkname libc_mlockall libc_mlockall //go:cgo_import_dynamic libc_mlockall mlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -419,16 +395,15 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_mprotect_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(prot)) + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mprotect_trampoline() +var libc_mprotect_trampoline_addr uintptr -//go:linkname libc_mprotect libc_mprotect //go:cgo_import_dynamic libc_mprotect mprotect "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -440,16 +415,15 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_msync_trampoline), uintptr(_p0), uintptr(len(b)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_msync_trampoline() +var libc_msync_trampoline_addr uintptr -//go:linkname libc_msync libc_msync //go:cgo_import_dynamic libc_msync msync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -461,63 +435,69 @@ func Munlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(funcPC(libc_munlock_trampoline), uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_munlock_trampoline() +var libc_munlock_trampoline_addr uintptr -//go:linkname libc_munlock libc_munlock //go:cgo_import_dynamic libc_munlock munlock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munlockall_trampoline), 0, 0, 0) + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_munlockall_trampoline() +var libc_munlockall_trampoline_addr uintptr -//go:linkname libc_munlockall libc_munlockall //go:cgo_import_dynamic libc_munlockall munlockall "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) +func closedir(dir uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_closedir_trampoline_addr, uintptr(dir), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getattrlist_trampoline() +var libc_closedir_trampoline_addr uintptr -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (r int, w int, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) - r = int(r0) - w = int(r1) +func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) { + r0, _, _ := syscall_syscall(libc_readdir_r_trampoline_addr, uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + res = Errno(r0) + return +} + +var libc_readdir_r_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]int32) (err error) { + _, _, e1 := syscall_rawSyscall(libc_pipe_trampoline_addr, uintptr(unsafe.Pointer(p)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_pipe_trampoline() +var libc_pipe_trampoline_addr uintptr -//go:linkname libc_pipe libc_pipe //go:cgo_import_dynamic libc_pipe pipe "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -533,7 +513,7 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_getxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + r0, _, e1 := syscall_syscall6(libc_getxattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -541,9 +521,8 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o return } -func libc_getxattr_trampoline() +var libc_getxattr_trampoline_addr uintptr -//go:linkname libc_getxattr libc_getxattr //go:cgo_import_dynamic libc_getxattr getxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -554,7 +533,7 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_fgetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + r0, _, e1 := syscall_syscall6(libc_fgetxattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -562,9 +541,8 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio return } -func libc_fgetxattr_trampoline() +var libc_fgetxattr_trampoline_addr uintptr -//go:linkname libc_fgetxattr libc_fgetxattr //go:cgo_import_dynamic libc_fgetxattr fgetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -580,16 +558,15 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_setxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + _, _, e1 := syscall_syscall6(libc_setxattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setxattr_trampoline() +var libc_setxattr_trampoline_addr uintptr -//go:linkname libc_setxattr libc_setxattr //go:cgo_import_dynamic libc_setxattr setxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -600,16 +577,15 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fsetxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + _, _, e1 := syscall_syscall6(libc_fsetxattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fsetxattr_trampoline() +var libc_fsetxattr_trampoline_addr uintptr -//go:linkname libc_fsetxattr libc_fsetxattr //go:cgo_import_dynamic libc_fsetxattr fsetxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -625,16 +601,15 @@ func removexattr(path string, attr string, options int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_removexattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + _, _, e1 := syscall_syscall(libc_removexattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_removexattr_trampoline() +var libc_removexattr_trampoline_addr uintptr -//go:linkname libc_removexattr libc_removexattr //go:cgo_import_dynamic libc_removexattr removexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -645,16 +620,15 @@ func fremovexattr(fd int, attr string, options int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_fremovexattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + _, _, e1 := syscall_syscall(libc_fremovexattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fremovexattr_trampoline() +var libc_fremovexattr_trampoline_addr uintptr -//go:linkname libc_fremovexattr libc_fremovexattr //go:cgo_import_dynamic libc_fremovexattr fremovexattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -665,7 +639,7 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_listxattr_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + r0, _, e1 := syscall_syscall6(libc_listxattr_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -673,15 +647,14 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro return } -func libc_listxattr_trampoline() +var libc_listxattr_trampoline_addr uintptr -//go:linkname libc_listxattr libc_listxattr //go:cgo_import_dynamic libc_listxattr listxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_flistxattr_trampoline), uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + r0, _, e1 := syscall_syscall6(libc_flistxattr_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) sz = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -689,30 +662,33 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { return } -func libc_flistxattr_trampoline() +var libc_flistxattr_trampoline_addr uintptr -//go:linkname libc_flistxattr libc_flistxattr //go:cgo_import_dynamic libc_flistxattr flistxattr "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_setattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setattrlist_trampoline() +var libc_utimensat_trampoline_addr uintptr -//go:linkname libc_setattrlist libc_setattrlist -//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_utimensat utimensat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg)) + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -720,43 +696,98 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { return } -func libc_fcntl_trampoline() +var libc_fcntl_trampoline_addr uintptr -//go:linkname libc_fcntl libc_fcntl //go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_kill_trampoline), uintptr(pid), uintptr(signum), uintptr(posix)) + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_kill_trampoline() +var libc_kill_trampoline_addr uintptr -//go:linkname libc_kill libc_kill //go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ioctl_trampoline), uintptr(fd), uintptr(req), uintptr(arg)) + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_ioctl_trampoline() +var libc_ioctl_trampoline_addr uintptr -//go:linkname libc_ioctl libc_ioctl //go:cgo_import_dynamic libc_ioctl ioctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renamexNp(from string, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renamex_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameatx_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -764,66 +795,174 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sysctl_trampoline() +var libc_sysctl_trampoline_addr uintptr -//go:linkname libc_sysctl libc_sysctl //go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_sendfile_trampoline), uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) + _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sendfile_trampoline() +var libc_sendfile_trampoline_addr uintptr -//go:linkname libc_sendfile libc_sendfile //go:cgo_import_dynamic libc_sendfile sendfile "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmdt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmget_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_access_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_access_trampoline() +var libc_access_trampoline_addr uintptr -//go:linkname libc_access libc_access //go:cgo_import_dynamic libc_access access "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_adjtime_trampoline), uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_adjtime_trampoline() +var libc_adjtime_trampoline_addr uintptr -//go:linkname libc_adjtime libc_adjtime //go:cgo_import_dynamic libc_adjtime adjtime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -834,16 +973,15 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chdir_trampoline() +var libc_chdir_trampoline_addr uintptr -//go:linkname libc_chdir libc_chdir //go:cgo_import_dynamic libc_chdir chdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -854,16 +992,15 @@ func Chflags(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chflags_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chflags_trampoline() +var libc_chflags_trampoline_addr uintptr -//go:linkname libc_chflags libc_chflags //go:cgo_import_dynamic libc_chflags chflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -874,16 +1011,15 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chmod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chmod_trampoline() +var libc_chmod_trampoline_addr uintptr -//go:linkname libc_chmod libc_chmod //go:cgo_import_dynamic libc_chmod chmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -894,16 +1030,15 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chown_trampoline() +var libc_chown_trampoline_addr uintptr -//go:linkname libc_chown libc_chown //go:cgo_import_dynamic libc_chown chown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -914,52 +1049,97 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_chroot_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_chroot_trampoline() +var libc_chroot_trampoline_addr uintptr -//go:linkname libc_chroot libc_chroot //go:cgo_import_dynamic libc_chroot chroot "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ClockGettime(clockid int32, time *Timespec) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_clock_gettime_trampoline), uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_clock_gettime_trampoline() +var libc_clock_gettime_trampoline_addr uintptr -//go:linkname libc_clock_gettime libc_clock_gettime //go:cgo_import_dynamic libc_clock_gettime clock_gettime "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Close(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_close_trampoline), uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_close_trampoline() +var libc_close_trampoline_addr uintptr -//go:linkname libc_close libc_close //go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Clonefile(src string, dst string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(src) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dst) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_clonefile_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clonefile_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(src) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dst) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_clonefileat_trampoline_addr, uintptr(srcDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clonefileat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup(fd int) (nfd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0) + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) nfd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -967,24 +1147,22 @@ func Dup(fd int) (nfd int, err error) { return } -func libc_dup_trampoline() +var libc_dup_trampoline_addr uintptr -//go:linkname libc_dup libc_dup //go:cgo_import_dynamic libc_dup dup "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(from int, to int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_dup2_trampoline), uintptr(from), uintptr(to), 0) + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_dup2_trampoline() +var libc_dup2_trampoline_addr uintptr -//go:linkname libc_dup2 libc_dup2 //go:cgo_import_dynamic libc_dup2 dup2 "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1000,28 +1178,26 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_exchangedata_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + _, _, e1 := syscall_syscall(libc_exchangedata_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_exchangedata_trampoline() +var libc_exchangedata_trampoline_addr uintptr -//go:linkname libc_exchangedata libc_exchangedata //go:cgo_import_dynamic libc_exchangedata exchangedata "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - syscall_syscall(funcPC(libc_exit_trampoline), uintptr(code), 0, 0) + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) return } -func libc_exit_trampoline() +var libc_exit_trampoline_addr uintptr -//go:linkname libc_exit libc_exit //go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1032,61 +1208,57 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_faccessat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_faccessat_trampoline() +var libc_faccessat_trampoline_addr uintptr -//go:linkname libc_faccessat libc_faccessat //go:cgo_import_dynamic libc_faccessat faccessat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchdir_trampoline), uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchdir_trampoline() +var libc_fchdir_trampoline_addr uintptr -//go:linkname libc_fchdir libc_fchdir //go:cgo_import_dynamic libc_fchdir fchdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchflags(fd int, flags int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchflags_trampoline), uintptr(fd), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchflags_trampoline() +var libc_fchflags_trampoline_addr uintptr -//go:linkname libc_fchflags libc_fchflags //go:cgo_import_dynamic libc_fchflags fchflags "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchmod_trampoline), uintptr(fd), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchmod_trampoline() +var libc_fchmod_trampoline_addr uintptr -//go:linkname libc_fchmod libc_fchmod //go:cgo_import_dynamic libc_fchmod fchmod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1097,31 +1269,29 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fchmodat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchmodat_trampoline() +var libc_fchmodat_trampoline_addr uintptr -//go:linkname libc_fchmodat libc_fchmodat //go:cgo_import_dynamic libc_fchmodat fchmodat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fchown_trampoline), uintptr(fd), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchown_trampoline() +var libc_fchown_trampoline_addr uintptr -//go:linkname libc_fchown libc_fchown //go:cgo_import_dynamic libc_fchown fchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1132,37 +1302,54 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fchownat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fchownat_trampoline() +var libc_fchownat_trampoline_addr uintptr -//go:linkname libc_fchownat libc_fchownat //go:cgo_import_dynamic libc_fchownat fchownat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(dst) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fclonefileat_trampoline_addr, uintptr(srcDirfd), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fclonefileat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_flock_trampoline() +var libc_flock_trampoline_addr uintptr -//go:linkname libc_flock libc_flock //go:cgo_import_dynamic libc_flock flock "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_fpathconf_trampoline), uintptr(fd), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1170,97 +1357,111 @@ func Fpathconf(fd int, name int) (val int, err error) { return } -func libc_fpathconf_trampoline() +var libc_fpathconf_trampoline_addr uintptr -//go:linkname libc_fpathconf libc_fpathconf //go:cgo_import_dynamic libc_fpathconf fpathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fsync_trampoline), uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fsync_trampoline() +var libc_fsync_trampoline_addr uintptr -//go:linkname libc_fsync libc_fsync //go:cgo_import_dynamic libc_fsync fsync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_ftruncate_trampoline), uintptr(fd), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_ftruncate_trampoline() +var libc_ftruncate_trampoline_addr uintptr -//go:linkname libc_ftruncate libc_ftruncate //go:cgo_import_dynamic libc_ftruncate ftruncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { - r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) + r0, _, _ := syscall_syscall(libc_getdtablesize_trampoline_addr, 0, 0, 0) size = int(r0) return } -func libc_getdtablesize_trampoline() +var libc_getdtablesize_trampoline_addr uintptr -//go:linkname libc_getdtablesize libc_getdtablesize //go:cgo_import_dynamic libc_getdtablesize getdtablesize "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getegid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) egid = int(r0) return } -func libc_getegid_trampoline() +var libc_getegid_trampoline_addr uintptr -//go:linkname libc_getegid libc_getegid //go:cgo_import_dynamic libc_getegid getegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_geteuid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } -func libc_geteuid_trampoline() +var libc_geteuid_trampoline_addr uintptr -//go:linkname libc_geteuid libc_geteuid //go:cgo_import_dynamic libc_geteuid geteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getgid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) gid = int(r0) return } -func libc_getgid_trampoline() +var libc_getgid_trampoline_addr uintptr -//go:linkname libc_getgid libc_getgid //go:cgo_import_dynamic libc_getgid getgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getpgid_trampoline), uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) pgid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1268,54 +1469,50 @@ func Getpgid(pid int) (pgid int, err error) { return } -func libc_getpgid_trampoline() +var libc_getpgid_trampoline_addr uintptr -//go:linkname libc_getpgid libc_getpgid //go:cgo_import_dynamic libc_getpgid getpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pgrp int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpgrp_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) pgrp = int(r0) return } -func libc_getpgrp_trampoline() +var libc_getpgrp_trampoline_addr uintptr -//go:linkname libc_getpgrp libc_getpgrp //go:cgo_import_dynamic libc_getpgrp getpgrp "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getpid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) pid = int(r0) return } -func libc_getpid_trampoline() +var libc_getpid_trampoline_addr uintptr -//go:linkname libc_getpid libc_getpid //go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getppid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) ppid = int(r0) return } -func libc_getppid_trampoline() +var libc_getppid_trampoline_addr uintptr -//go:linkname libc_getppid libc_getppid //go:cgo_import_dynamic libc_getppid getppid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getpriority_trampoline), uintptr(which), uintptr(who), 0) + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) prio = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1323,45 +1520,42 @@ func Getpriority(which int, who int) (prio int, err error) { return } -func libc_getpriority_trampoline() +var libc_getpriority_trampoline_addr uintptr -//go:linkname libc_getpriority libc_getpriority //go:cgo_import_dynamic libc_getpriority getpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getrlimit_trampoline() +var libc_getrlimit_trampoline_addr uintptr -//go:linkname libc_getrlimit libc_getrlimit //go:cgo_import_dynamic libc_getrlimit getrlimit "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_getrusage_trampoline), uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_getrusage_trampoline() +var libc_getrusage_trampoline_addr uintptr -//go:linkname libc_getrusage libc_getrusage //go:cgo_import_dynamic libc_getrusage getrusage "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_getsid_trampoline), uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) sid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1369,41 +1563,52 @@ func Getsid(pid int) (sid int, err error) { return } -func libc_getsid_trampoline() +var libc_getsid_trampoline_addr uintptr -//go:linkname libc_getsid libc_getsid //go:cgo_import_dynamic libc_getsid getsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Gettimeofday(tp *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getuid() (uid int) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } -func libc_getuid_trampoline() +var libc_getuid_trampoline_addr uintptr -//go:linkname libc_getuid libc_getuid //go:cgo_import_dynamic libc_getuid getuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := syscall_rawSyscall(funcPC(libc_issetugid_trampoline), 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_issetugid_trampoline_addr, 0, 0, 0) tainted = bool(r0 != 0) return } -func libc_issetugid_trampoline() +var libc_issetugid_trampoline_addr uintptr -//go:linkname libc_issetugid libc_issetugid //go:cgo_import_dynamic libc_issetugid issetugid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kqueue() (fd int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_kqueue_trampoline), 0, 0, 0) + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1411,9 +1616,8 @@ func Kqueue() (fd int, err error) { return } -func libc_kqueue_trampoline() +var libc_kqueue_trampoline_addr uintptr -//go:linkname libc_kqueue libc_kqueue //go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1424,16 +1628,15 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_lchown_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_lchown_trampoline() +var libc_lchown_trampoline_addr uintptr -//go:linkname libc_lchown libc_lchown //go:cgo_import_dynamic libc_lchown lchown "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1449,16 +1652,15 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_link_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_link_trampoline() +var libc_link_trampoline_addr uintptr -//go:linkname libc_link libc_link //go:cgo_import_dynamic libc_link link "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1474,31 +1676,29 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_linkat_trampoline), uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_linkat_trampoline() +var libc_linkat_trampoline_addr uintptr -//go:linkname libc_linkat libc_linkat //go:cgo_import_dynamic libc_linkat linkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_listen_trampoline), uintptr(s), uintptr(backlog), 0) + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_listen_trampoline() +var libc_listen_trampoline_addr uintptr -//go:linkname libc_listen libc_listen //go:cgo_import_dynamic libc_listen listen "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1509,16 +1709,15 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mkdir_trampoline() +var libc_mkdir_trampoline_addr uintptr -//go:linkname libc_mkdir libc_mkdir //go:cgo_import_dynamic libc_mkdir mkdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1529,16 +1728,15 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mkdirat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mkdirat_trampoline() +var libc_mkdirat_trampoline_addr uintptr -//go:linkname libc_mkdirat libc_mkdirat //go:cgo_import_dynamic libc_mkdirat mkdirat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1549,16 +1747,15 @@ func Mkfifo(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mkfifo_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mkfifo_trampoline() +var libc_mkfifo_trampoline_addr uintptr -//go:linkname libc_mkfifo libc_mkfifo //go:cgo_import_dynamic libc_mkfifo mkfifo "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1569,27 +1766,50 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_mknod_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_mknod_trampoline() +var libc_mknod_trampoline_addr uintptr -//go:linkname libc_mknod libc_mknod //go:cgo_import_dynamic libc_mknod mknod "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Open(path string, mode int, perm uint32) (fd int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - r0, _, e1 := syscall_syscall(funcPC(libc_open_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1597,9 +1817,8 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { return } -func libc_open_trampoline() +var libc_open_trampoline_addr uintptr -//go:linkname libc_open libc_open //go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1610,7 +1829,7 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall6(funcPC(libc_openat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1618,9 +1837,8 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { return } -func libc_openat_trampoline() +var libc_openat_trampoline_addr uintptr -//go:linkname libc_openat libc_openat //go:cgo_import_dynamic libc_openat openat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1631,7 +1849,7 @@ func Pathconf(path string, name int) (val int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall(funcPC(libc_pathconf_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1639,21 +1857,20 @@ func Pathconf(path string, name int) (val int, err error) { return } -func libc_pathconf_trampoline() +var libc_pathconf_trampoline_addr uintptr -//go:linkname libc_pathconf libc_pathconf //go:cgo_import_dynamic libc_pathconf pathconf "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_pread_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1661,21 +1878,20 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { return } -func libc_pread_trampoline() +var libc_pread_trampoline_addr uintptr -//go:linkname libc_pread libc_pread //go:cgo_import_dynamic libc_pread pread "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_pwrite_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1683,9 +1899,8 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { return } -func libc_pwrite_trampoline() +var libc_pwrite_trampoline_addr uintptr -//go:linkname libc_pwrite libc_pwrite //go:cgo_import_dynamic libc_pwrite pwrite "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1697,7 +1912,7 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1705,9 +1920,8 @@ func read(fd int, p []byte) (n int, err error) { return } -func libc_read_trampoline() +var libc_read_trampoline_addr uintptr -//go:linkname libc_read libc_read //go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1724,7 +1938,7 @@ func Readlink(path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(funcPC(libc_readlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1732,9 +1946,8 @@ func Readlink(path string, buf []byte) (n int, err error) { return } -func libc_readlink_trampoline() +var libc_readlink_trampoline_addr uintptr -//go:linkname libc_readlink libc_readlink //go:cgo_import_dynamic libc_readlink readlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1751,7 +1964,7 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(funcPC(libc_readlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1759,9 +1972,8 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { return } -func libc_readlinkat_trampoline() +var libc_readlinkat_trampoline_addr uintptr -//go:linkname libc_readlinkat libc_readlinkat //go:cgo_import_dynamic libc_readlinkat readlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1777,16 +1989,15 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_rename_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_rename_trampoline() +var libc_rename_trampoline_addr uintptr -//go:linkname libc_rename libc_rename //go:cgo_import_dynamic libc_rename rename "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1802,16 +2013,15 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_renameat_trampoline), uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_renameat_trampoline() +var libc_renameat_trampoline_addr uintptr -//go:linkname libc_renameat libc_renameat //go:cgo_import_dynamic libc_renameat renameat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1822,16 +2032,15 @@ func Revoke(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_revoke_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_revoke_trampoline() +var libc_revoke_trampoline_addr uintptr -//go:linkname libc_revoke libc_revoke //go:cgo_import_dynamic libc_revoke revoke "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1842,22 +2051,21 @@ func Rmdir(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_rmdir_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_rmdir_trampoline() +var libc_rmdir_trampoline_addr uintptr -//go:linkname libc_rmdir libc_rmdir //go:cgo_import_dynamic libc_rmdir rmdir "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_lseek_trampoline), uintptr(fd), uintptr(offset), uintptr(whence)) + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) newoffset = int64(r0) if e1 != 0 { err = errnoErr(e1) @@ -1865,15 +2073,14 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return } -func libc_lseek_trampoline() +var libc_lseek_trampoline_addr uintptr -//go:linkname libc_lseek libc_lseek //go:cgo_import_dynamic libc_lseek lseek "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_select_trampoline), uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1881,54 +2088,75 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err return } -func libc_select_trampoline() +var libc_select_trampoline_addr uintptr -//go:linkname libc_select libc_select //go:cgo_import_dynamic libc_select select "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(attrBuf) > 0 { + _p1 = unsafe.Pointer(&attrBuf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_setattrlist_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(attrlist)), uintptr(_p1), uintptr(len(attrBuf)), uintptr(options), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setattrlist_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Setegid(egid int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setegid_trampoline), uintptr(egid), 0, 0) + _, _, e1 := syscall_syscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setegid_trampoline() +var libc_setegid_trampoline_addr uintptr -//go:linkname libc_setegid libc_setegid //go:cgo_import_dynamic libc_setegid setegid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seteuid(euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_seteuid_trampoline), uintptr(euid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_seteuid_trampoline() +var libc_seteuid_trampoline_addr uintptr -//go:linkname libc_seteuid libc_seteuid //go:cgo_import_dynamic libc_seteuid seteuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(gid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setgid_trampoline), uintptr(gid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setgid_trampoline() +var libc_setgid_trampoline_addr uintptr -//go:linkname libc_setgid libc_setgid //go:cgo_import_dynamic libc_setgid setgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1939,112 +2167,91 @@ func Setlogin(name string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_setlogin_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setlogin_trampoline() +var libc_setlogin_trampoline_addr uintptr -//go:linkname libc_setlogin libc_setlogin //go:cgo_import_dynamic libc_setlogin setlogin "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setpgid_trampoline), uintptr(pid), uintptr(pgid), 0) + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setpgid_trampoline() +var libc_setpgid_trampoline_addr uintptr -//go:linkname libc_setpgid libc_setpgid //go:cgo_import_dynamic libc_setpgid setpgid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setpriority_trampoline), uintptr(which), uintptr(who), uintptr(prio)) + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setpriority_trampoline() +var libc_setpriority_trampoline_addr uintptr -//go:linkname libc_setpriority libc_setpriority //go:cgo_import_dynamic libc_setpriority setpriority "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setprivexec(flag int) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_setprivexec_trampoline), uintptr(flag), 0, 0) + _, _, e1 := syscall_syscall(libc_setprivexec_trampoline_addr, uintptr(flag), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setprivexec_trampoline() +var libc_setprivexec_trampoline_addr uintptr -//go:linkname libc_setprivexec libc_setprivexec //go:cgo_import_dynamic libc_setprivexec setprivexec "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setregid_trampoline), uintptr(rgid), uintptr(egid), 0) + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setregid_trampoline() +var libc_setregid_trampoline_addr uintptr -//go:linkname libc_setregid libc_setregid //go:cgo_import_dynamic libc_setregid setregid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setreuid_trampoline), uintptr(ruid), uintptr(euid), 0) + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setreuid_trampoline() +var libc_setreuid_trampoline_addr uintptr -//go:linkname libc_setreuid libc_setreuid //go:cgo_import_dynamic libc_setreuid setreuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setrlimit_trampoline), uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_setrlimit_trampoline() - -//go:linkname libc_setrlimit libc_setrlimit -//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { - r0, _, e1 := syscall_rawSyscall(funcPC(libc_setsid_trampoline), 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) pid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2052,39 +2259,36 @@ func Setsid() (pid int, err error) { return } -func libc_setsid_trampoline() +var libc_setsid_trampoline_addr uintptr -//go:linkname libc_setsid libc_setsid //go:cgo_import_dynamic libc_setsid setsid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_settimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_settimeofday_trampoline() +var libc_settimeofday_trampoline_addr uintptr -//go:linkname libc_settimeofday libc_settimeofday //go:cgo_import_dynamic libc_settimeofday settimeofday "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := syscall_rawSyscall(funcPC(libc_setuid_trampoline), uintptr(uid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_setuid_trampoline() +var libc_setuid_trampoline_addr uintptr -//go:linkname libc_setuid libc_setuid //go:cgo_import_dynamic libc_setuid setuid "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2100,16 +2304,15 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_symlink_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_symlink_trampoline() +var libc_symlink_trampoline_addr uintptr -//go:linkname libc_symlink libc_symlink //go:cgo_import_dynamic libc_symlink symlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2125,31 +2328,29 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_symlinkat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } return } -func libc_symlinkat_trampoline() +var libc_symlinkat_trampoline_addr uintptr -//go:linkname libc_symlinkat libc_symlinkat //go:cgo_import_dynamic libc_symlinkat symlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_sync_trampoline), 0, 0, 0) + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_sync_trampoline() +var libc_sync_trampoline_addr uintptr -//go:linkname libc_sync libc_sync //go:cgo_import_dynamic libc_sync sync "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2160,29 +2361,27 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_truncate_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_truncate_trampoline() +var libc_truncate_trampoline_addr uintptr -//go:linkname libc_truncate libc_truncate //go:cgo_import_dynamic libc_truncate truncate "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(newmask int) (oldmask int) { - r0, _, _ := syscall_syscall(funcPC(libc_umask_trampoline), uintptr(newmask), 0, 0) + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) oldmask = int(r0) return } -func libc_umask_trampoline() +var libc_umask_trampoline_addr uintptr -//go:linkname libc_umask libc_umask //go:cgo_import_dynamic libc_umask umask "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2193,16 +2392,15 @@ func Undelete(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_undelete_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_undelete_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_undelete_trampoline() +var libc_undelete_trampoline_addr uintptr -//go:linkname libc_undelete libc_undelete //go:cgo_import_dynamic libc_undelete undelete "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2213,16 +2411,15 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_unlink_trampoline), uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_unlink_trampoline() +var libc_unlink_trampoline_addr uintptr -//go:linkname libc_unlink libc_unlink //go:cgo_import_dynamic libc_unlink unlink "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2233,16 +2430,15 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_unlinkat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } -func libc_unlinkat_trampoline() +var libc_unlinkat_trampoline_addr uintptr -//go:linkname libc_unlinkat libc_unlinkat //go:cgo_import_dynamic libc_unlinkat unlinkat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2253,16 +2449,15 @@ func Unmount(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_unmount_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_unmount_trampoline() +var libc_unmount_trampoline_addr uintptr -//go:linkname libc_unmount libc_unmount //go:cgo_import_dynamic libc_unmount unmount "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2274,7 +2469,7 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2282,15 +2477,14 @@ func write(fd int, p []byte) (n int, err error) { return } -func libc_write_trampoline() +var libc_write_trampoline_addr uintptr -//go:linkname libc_write libc_write //go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := syscall_syscall6(funcPC(libc_mmap_trampoline), uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) ret = uintptr(r0) if e1 != 0 { err = errnoErr(e1) @@ -2298,30 +2492,34 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( return } -func libc_mmap_trampoline() +var libc_mmap_trampoline_addr uintptr -//go:linkname libc_mmap libc_mmap //go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_munmap_trampoline), uintptr(addr), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_munmap_trampoline() +var libc_munmap_trampoline_addr uintptr -//go:linkname libc_munmap libc_munmap //go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_read_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func readv(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2329,10 +2527,20 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_readv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readv readv "/usr/lib/libSystem.B.dylib" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_write_trampoline), uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2340,36 +2548,64 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_preadv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_preadv preadv "/usr/lib/libSystem.B.dylib" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { - r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int64(r0) - usec = int32(r1) +func writev(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_gettimeofday_trampoline() +var libc_writev_trampoline_addr uintptr -//go:linkname libc_gettimeofday libc_gettimeofday -//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwritev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwritev pwritev "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fstat_trampoline() +var libc_fstat_trampoline_addr uintptr -//go:linkname libc_fstat libc_fstat //go:cgo_import_dynamic libc_fstat fstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2380,37 +2616,35 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall6(funcPC(libc_fstatat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fstatat_trampoline() +var libc_fstatat_trampoline_addr uintptr -//go:linkname libc_fstatat libc_fstatat //go:cgo_import_dynamic libc_fstatat fstatat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := syscall_syscall(funcPC(libc_fstatfs_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_fstatfs_trampoline() +var libc_fstatfs_trampoline_addr uintptr -//go:linkname libc_fstatfs libc_fstatfs //go:cgo_import_dynamic libc_fstatfs fstatfs "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat_trampoline), uintptr(buf), uintptr(size), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(buf), uintptr(size), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -2418,9 +2652,8 @@ func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { return } -func libc_getfsstat_trampoline() +var libc_getfsstat_trampoline_addr uintptr -//go:linkname libc_getfsstat libc_getfsstat //go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2431,36 +2664,48 @@ func Lstat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_lstat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_lstat_trampoline() +var libc_lstat_trampoline_addr uintptr -//go:linkname libc_lstat libc_lstat //go:cgo_import_dynamic libc_lstat lstat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(libc_ptrace_trampoline_addr, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ptrace_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Stat(path string, stat *Stat_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_stat_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_stat_trampoline() +var libc_stat_trampoline_addr uintptr -//go:linkname libc_stat libc_stat //go:cgo_import_dynamic libc_stat stat "/usr/lib/libSystem.B.dylib" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -2471,14 +2716,13 @@ func Statfs(path string, stat *Statfs_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(funcPC(libc_statfs_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } -func libc_statfs_trampoline() +var libc_statfs_trampoline_addr uintptr -//go:linkname libc_statfs libc_statfs //go:cgo_import_dynamic libc_statfs statfs "/usr/lib/libSystem.B.dylib" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 40cce1b..7f8998b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -1,282 +1,799 @@ -// go run mkasm_darwin.go arm64 +// go run mkasm.go darwin arm64 // Code generated by the command above; DO NOT EDIT. -// +build go1.12 - #include "textflag.h" -TEXT ·libc_getgroups_trampoline(SB),NOSPLIT,$0-0 + +TEXT libc_fdopendir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fdopendir(SB) +GLOBL ·libc_fdopendir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fdopendir_trampoline_addr(SB)/8, $libc_fdopendir_trampoline<>(SB) + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getgroups(SB) -TEXT ·libc_setgroups_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setgroups(SB) -TEXT ·libc_wait4_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_wait4(SB) -TEXT ·libc_accept_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_accept(SB) -TEXT ·libc_bind_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_bind(SB) -TEXT ·libc_connect_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_connect(SB) -TEXT ·libc_socket_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_socket(SB) -TEXT ·libc_getsockopt_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getsockopt(SB) -TEXT ·libc_setsockopt_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setsockopt(SB) -TEXT ·libc_getpeername_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpeername(SB) -TEXT ·libc_getsockname_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getsockname(SB) -TEXT ·libc_shutdown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_shutdown(SB) -TEXT ·libc_socketpair_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_socketpair(SB) -TEXT ·libc_recvfrom_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_recvfrom(SB) -TEXT ·libc_sendto_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendto(SB) -TEXT ·libc_recvmsg_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_recvmsg(SB) -TEXT ·libc_sendmsg_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendmsg(SB) -TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_kevent(SB) -TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimes(SB) -TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_futimes(SB) -TEXT ·libc_poll_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_poll(SB) -TEXT ·libc_madvise_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_madvise(SB) -TEXT ·libc_mlock_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mlock(SB) -TEXT ·libc_mlockall_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mlockall(SB) -TEXT ·libc_mprotect_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mprotect(SB) -TEXT ·libc_msync_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_msync(SB) -TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) -TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) -TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_closedir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_closedir(SB) +GLOBL ·libc_closedir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_closedir_trampoline_addr(SB)/8, $libc_closedir_trampoline<>(SB) + +TEXT libc_readdir_r_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readdir_r(SB) +GLOBL ·libc_readdir_r_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readdir_r_trampoline_addr(SB)/8, $libc_readdir_r_trampoline<>(SB) + +TEXT libc_pipe_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) -TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pipe_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe_trampoline_addr(SB)/8, $libc_pipe_trampoline<>(SB) + +TEXT libc_getxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getxattr(SB) -TEXT ·libc_fgetxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getxattr_trampoline_addr(SB)/8, $libc_getxattr_trampoline<>(SB) + +TEXT libc_fgetxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fgetxattr(SB) -TEXT ·libc_setxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fgetxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fgetxattr_trampoline_addr(SB)/8, $libc_fgetxattr_trampoline<>(SB) + +TEXT libc_setxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setxattr(SB) -TEXT ·libc_fsetxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setxattr_trampoline_addr(SB)/8, $libc_setxattr_trampoline<>(SB) + +TEXT libc_fsetxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fsetxattr(SB) -TEXT ·libc_removexattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fsetxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsetxattr_trampoline_addr(SB)/8, $libc_fsetxattr_trampoline<>(SB) + +TEXT libc_removexattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_removexattr(SB) -TEXT ·libc_fremovexattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_removexattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_removexattr_trampoline_addr(SB)/8, $libc_removexattr_trampoline<>(SB) + +TEXT libc_fremovexattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fremovexattr(SB) -TEXT ·libc_listxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fremovexattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fremovexattr_trampoline_addr(SB)/8, $libc_fremovexattr_trampoline<>(SB) + +TEXT libc_listxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_listxattr(SB) -TEXT ·libc_flistxattr_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_listxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listxattr_trampoline_addr(SB)/8, $libc_listxattr_trampoline<>(SB) + +TEXT libc_flistxattr_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_flistxattr(SB) -TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setattrlist(SB) -TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_flistxattr_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flistxattr_trampoline_addr(SB)/8, $libc_flistxattr_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fcntl(SB) -TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_kill(SB) -TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ioctl(SB) -TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renamex_np(SB) +GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB) + +TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameatx_np(SB) +GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sysctl(SB) -TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + +TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) -TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendfile_trampoline_addr(SB)/8, $libc_sendfile_trampoline<>(SB) + +TEXT libc_shmat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmat(SB) +GLOBL ·libc_shmat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmat_trampoline_addr(SB)/8, $libc_shmat_trampoline<>(SB) + +TEXT libc_shmctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmctl(SB) +GLOBL ·libc_shmctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmctl_trampoline_addr(SB)/8, $libc_shmctl_trampoline<>(SB) + +TEXT libc_shmdt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmdt(SB) +GLOBL ·libc_shmdt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmdt_trampoline_addr(SB)/8, $libc_shmdt_trampoline<>(SB) + +TEXT libc_shmget_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmget(SB) +GLOBL ·libc_shmget_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmget_trampoline_addr(SB)/8, $libc_shmget_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_access(SB) -TEXT ·libc_adjtime_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_adjtime(SB) -TEXT ·libc_chdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chdir(SB) -TEXT ·libc_chflags_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chflags(SB) -TEXT ·libc_chmod_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chmod(SB) -TEXT ·libc_chown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chown(SB) -TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_chroot(SB) -TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_clock_gettime(SB) -TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_close(SB) -TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_clonefile_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clonefile(SB) +GLOBL ·libc_clonefile_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clonefile_trampoline_addr(SB)/8, $libc_clonefile_trampoline<>(SB) + +TEXT libc_clonefileat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clonefileat(SB) +GLOBL ·libc_clonefileat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clonefileat_trampoline_addr(SB)/8, $libc_clonefileat_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_dup(SB) -TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_dup2(SB) -TEXT ·libc_exchangedata_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_exchangedata_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_exchangedata(SB) -TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_exchangedata_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exchangedata_trampoline_addr(SB)/8, $libc_exchangedata_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_exit(SB) -TEXT ·libc_faccessat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_faccessat(SB) -TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchdir(SB) -TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchflags(SB) -TEXT ·libc_fchmod_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchmod(SB) -TEXT ·libc_fchmodat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchmodat(SB) -TEXT ·libc_fchown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchown(SB) -TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fchownat(SB) -TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_fclonefileat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fclonefileat(SB) +GLOBL ·libc_fclonefileat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fclonefileat_trampoline_addr(SB)/8, $libc_fclonefileat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_flock(SB) -TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fpathconf(SB) -TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fsync(SB) -TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ftruncate(SB) -TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getdtablesize_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getdtablesize(SB) -TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getdtablesize_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdtablesize_trampoline_addr(SB)/8, $libc_getdtablesize_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getegid(SB) -TEXT ·libc_geteuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_geteuid(SB) -TEXT ·libc_getgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getgid(SB) -TEXT ·libc_getpgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpgid(SB) -TEXT ·libc_getpgrp_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpgrp(SB) -TEXT ·libc_getpid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpid(SB) -TEXT ·libc_getppid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getppid(SB) -TEXT ·libc_getpriority_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getpriority(SB) -TEXT ·libc_getrlimit_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getrlimit(SB) -TEXT ·libc_getrusage_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getrusage(SB) -TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getsid(SB) -TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getuid(SB) -TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_issetugid(SB) -TEXT ·libc_kqueue_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_kqueue(SB) -TEXT ·libc_lchown_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_lchown(SB) -TEXT ·libc_link_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_link(SB) -TEXT ·libc_linkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_linkat(SB) -TEXT ·libc_listen_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_listen(SB) -TEXT ·libc_mkdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mkdir(SB) -TEXT ·libc_mkdirat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mkdirat(SB) -TEXT ·libc_mkfifo_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mkfifo(SB) -TEXT ·libc_mknod_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mknod(SB) -TEXT ·libc_open_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_open(SB) -TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_openat(SB) -TEXT ·libc_pathconf_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pathconf(SB) -TEXT ·libc_pread_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pread(SB) -TEXT ·libc_pwrite_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_pwrite(SB) -TEXT ·libc_read_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) -TEXT ·libc_readlink_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_readlink(SB) -TEXT ·libc_readlinkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_readlinkat(SB) -TEXT ·libc_rename_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_rename(SB) -TEXT ·libc_renameat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_renameat(SB) -TEXT ·libc_revoke_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_revoke(SB) -TEXT ·libc_rmdir_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_rmdir(SB) -TEXT ·libc_lseek_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_lseek(SB) -TEXT ·libc_select_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_select(SB) -TEXT ·libc_setegid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setattrlist_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setattrlist(SB) +GLOBL ·libc_setattrlist_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setattrlist_trampoline_addr(SB)/8, $libc_setattrlist_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setegid(SB) -TEXT ·libc_seteuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_seteuid(SB) -TEXT ·libc_setgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setgid(SB) -TEXT ·libc_setlogin_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setlogin(SB) -TEXT ·libc_setpgid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setpgid(SB) -TEXT ·libc_setpriority_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setpriority(SB) -TEXT ·libc_setprivexec_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setprivexec_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setprivexec(SB) -TEXT ·libc_setregid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setprivexec_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setprivexec_trampoline_addr(SB)/8, $libc_setprivexec_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setregid(SB) -TEXT ·libc_setreuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setreuid(SB) -TEXT ·libc_setrlimit_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setrlimit(SB) -TEXT ·libc_setsid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setsid(SB) -TEXT ·libc_settimeofday_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_settimeofday(SB) -TEXT ·libc_setuid_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_setuid(SB) -TEXT ·libc_symlink_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_symlink(SB) -TEXT ·libc_symlinkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_symlinkat(SB) -TEXT ·libc_sync_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sync(SB) -TEXT ·libc_truncate_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_truncate(SB) -TEXT ·libc_umask_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_umask(SB) -TEXT ·libc_undelete_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_undelete_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_undelete(SB) -TEXT ·libc_unlink_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_undelete_trampoline_addr(SB), RODATA, $8 +DATA ·libc_undelete_trampoline_addr(SB)/8, $libc_undelete_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_unlink(SB) -TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_unlinkat(SB) -TEXT ·libc_unmount_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_unmount(SB) -TEXT ·libc_write_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_write(SB) -TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) -TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) -TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0 - JMP libc_gettimeofday(SB) -TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readv(SB) +GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) + +TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_preadv(SB) +GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) + +TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_writev(SB) +GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) + +TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwritev(SB) +GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstat(SB) -TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat_trampoline_addr(SB)/8, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstatat(SB) -TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat_trampoline_addr(SB)/8, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstatfs(SB) -TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs_trampoline_addr(SB)/8, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_getfsstat(SB) -TEXT ·libc_lstat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_lstat(SB) -TEXT ·libc_stat_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat_trampoline_addr(SB)/8, $libc_lstat_trampoline<>(SB) + +TEXT libc_ptrace_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) +GLOBL ·libc_ptrace_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ptrace_trampoline_addr(SB)/8, $libc_ptrace_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_stat(SB) -TEXT ·libc_statfs_trampoline(SB),NOSPLIT,$0-0 +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat_trampoline_addr(SB)/8, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs_trampoline_addr(SB)/8, $libc_statfs_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index fe1fdd7..aad65fc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -dragonfly -tags dragonfly,amd64 syscall_bsd.go syscall_dragonfly.go syscall_dragonfly_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build dragonfly,amd64 +//go:build dragonfly && amd64 package unix @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -378,6 +362,18 @@ func pipe() (r int, w int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (r int, w int, err error) { + r0, r1, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + r = int(r0) + w = int(r1) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func extpread(fd int, p []byte, flags int, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { @@ -439,6 +435,32 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -539,6 +561,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -1377,16 +1409,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1619,28 +1641,6 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) nfd = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go index 600f1d2..c009639 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -1,7 +1,7 @@ // go run mksyscall.go -l32 -tags freebsd,386 syscall_bsd.go syscall_freebsd.go syscall_freebsd_386.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build freebsd,386 +//go:build freebsd && 386 package unix @@ -387,6 +387,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -413,6 +423,16 @@ func ptrace(request int, pid int, addr uintptr, data int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptracePtr(request int, pid int, addr unsafe.Pointer, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -543,6 +563,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -911,7 +941,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat(fd int, stat *stat_freebsd11_t) (err error) { +func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -921,17 +951,7 @@ func fstat(fd int, stat *stat_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat_freebsd12(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -946,22 +966,7 @@ func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { +func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -971,16 +976,6 @@ func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1001,7 +996,7 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) @@ -1018,23 +1013,6 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getdtablesize() (size int) { r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) size = int(r0) @@ -1256,21 +1234,6 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func lstat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Mkdir(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1316,43 +1279,13 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mknodat(fd int, path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { +func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), uintptr(dev>>32), 0) + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), uintptr(dev>>32), 0) if e1 != 0 { err = errnoErr(e1) } @@ -1419,7 +1352,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1436,7 +1369,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1711,16 +1644,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1752,22 +1675,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func stat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func statfs(path string, stat *statfs_freebsd11_t) (err error) { +func Statfs(path string, stat *Statfs_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1782,21 +1690,6 @@ func statfs(path string, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func statfs_freebsd12(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1968,28 +1861,6 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) nfd = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index 064934b..7664df7 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -tags freebsd,amd64 syscall_bsd.go syscall_freebsd.go syscall_freebsd_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build freebsd,amd64 +//go:build freebsd && amd64 package unix @@ -387,6 +387,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -413,6 +423,16 @@ func ptrace(request int, pid int, addr uintptr, data int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptracePtr(request int, pid int, addr unsafe.Pointer, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -543,6 +563,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -911,7 +941,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat(fd int, stat *stat_freebsd11_t) (err error) { +func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -921,17 +951,7 @@ func fstat(fd int, stat *stat_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat_freebsd12(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -946,22 +966,7 @@ func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { +func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -971,16 +976,6 @@ func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1001,7 +996,7 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) @@ -1018,23 +1013,6 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getdtablesize() (size int) { r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) size = int(r0) @@ -1256,21 +1234,6 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func lstat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Mkdir(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1316,22 +1279,7 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mknodat(fd int, path string, mode uint32, dev int) (err error) { +func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1346,21 +1294,6 @@ func mknodat(fd int, path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1419,7 +1352,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1436,7 +1369,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1711,16 +1644,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1752,22 +1675,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func stat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func statfs(path string, stat *statfs_freebsd11_t) (err error) { +func Statfs(path string, stat *Statfs_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1782,21 +1690,6 @@ func statfs(path string, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func statfs_freebsd12(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1968,28 +1861,6 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) nfd = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index 31d2c46..ae09918 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -1,7 +1,7 @@ // go run mksyscall.go -l32 -arm -tags freebsd,arm syscall_bsd.go syscall_freebsd.go syscall_freebsd_arm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build freebsd,arm +//go:build freebsd && arm package unix @@ -350,14 +350,25 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getcwd(buf []byte) (n int, err error) { var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -366,8 +377,8 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -376,15 +387,24 @@ func pipe2(p *[2]_C_int, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getcwd(buf []byte) (n int, err error) { +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) - n = int(r0) + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) if e1 != 0 { err = errnoErr(e1) } @@ -393,8 +413,8 @@ func Getcwd(buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -403,7 +423,7 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data int) (err error) { +func ptracePtr(request int, pid int, addr unsafe.Pointer, data int) (err error) { _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { err = errnoErr(e1) @@ -543,6 +563,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -911,7 +941,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat(fd int, stat *stat_freebsd11_t) (err error) { +func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -921,17 +951,7 @@ func fstat(fd int, stat *stat_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat_freebsd12(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -946,22 +966,7 @@ func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { +func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -971,16 +976,6 @@ func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1001,7 +996,7 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) @@ -1018,23 +1013,6 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getdtablesize() (size int) { r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) size = int(r0) @@ -1256,21 +1234,6 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func lstat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Mkdir(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1316,43 +1279,13 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mknod(path string, mode uint32, dev int) (err error) { +func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mknodat(fd int, path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, uintptr(dev), uintptr(dev>>32)) if e1 != 0 { err = errnoErr(e1) } @@ -1419,7 +1352,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1436,7 +1369,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1711,16 +1644,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1752,22 +1675,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func stat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func statfs(path string, stat *statfs_freebsd11_t) (err error) { +func Statfs(path string, stat *Statfs_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1782,21 +1690,6 @@ func statfs(path string, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func statfs_freebsd12(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1968,28 +1861,6 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) nfd = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go index 4adaaa5..11fd5d4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -tags freebsd,arm64 syscall_bsd.go syscall_freebsd.go syscall_freebsd_arm64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build freebsd,arm64 +//go:build freebsd && arm64 package unix @@ -387,6 +387,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -413,6 +423,16 @@ func ptrace(request int, pid int, addr uintptr, data int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptracePtr(request int, pid int, addr unsafe.Pointer, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -543,6 +563,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -911,7 +941,7 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat(fd int, stat *stat_freebsd11_t) (err error) { +func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -921,17 +951,7 @@ func fstat(fd int, stat *stat_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat_freebsd12(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) { +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -946,22 +966,7 @@ func fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { +func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) @@ -971,16 +976,6 @@ func fstatfs(fd int, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1001,7 +996,7 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) @@ -1018,23 +1013,6 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES_FREEBSD12, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getdtablesize() (size int) { r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) size = int(r0) @@ -1256,21 +1234,6 @@ func Listen(s int, backlog int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func lstat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Mkdir(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1316,22 +1279,7 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func mknodat(fd int, path string, mode uint32, dev int) (err error) { +func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1346,21 +1294,6 @@ func mknodat(fd int, path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_MKNODAT_FREEBSD12, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1419,7 +1352,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1436,7 +1369,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1711,16 +1644,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1752,22 +1675,7 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func stat(path string, stat *stat_freebsd11_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func statfs(path string, stat *statfs_freebsd11_t) (err error) { +func Statfs(path string, stat *Statfs_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { @@ -1782,21 +1690,6 @@ func statfs(path string, stat *statfs_freebsd11_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func statfs_freebsd12(path string, stat *Statfs_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STATFS_FREEBSD12, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1968,28 +1861,6 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) nfd = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go similarity index 81% rename from vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go rename to vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go index f8e5c37..c3d2d65 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags darwin,amd64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.1_11.go syscall_darwin_amd64.go +// go run mksyscall.go -tags freebsd,riscv64 syscall_bsd.go syscall_freebsd.go syscall_freebsd_riscv64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build darwin,amd64,!go1.12 +//go:build freebsd && riscv64 package unix @@ -350,8 +350,8 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -360,10 +360,15 @@ func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (r int, w int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - r = int(r0) - w = int(r1) +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -372,19 +377,34 @@ func pipe() (r int, w int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getxattr(path string, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) } - r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) if e1 != 0 { err = errnoErr(e1) } @@ -393,14 +413,18 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return +func ptrace(request int, pid int, addr uintptr, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) } - r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) - sz = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ptracePtr(request int, pid int, addr unsafe.Pointer, data int) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -409,18 +433,23 @@ func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, optio // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { +func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return + _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) } - _, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { + _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } @@ -429,13 +458,28 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(attr) - if err != nil { - return +func CapEnter() (err error) { + _, _, e1 := Syscall(SYS_CAP_ENTER, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) } - _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func capRightsGet(version int, fd int, rightsp *CapRights) (err error) { + _, _, e1 := Syscall(SYS___CAP_RIGHTS_GET, uintptr(version), uintptr(fd), uintptr(unsafe.Pointer(rightsp))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func capRightsLimit(fd int, rightsp *CapRights) (err error) { + _, _, e1 := Syscall(SYS_CAP_RIGHTS_LIMIT, uintptr(fd), uintptr(unsafe.Pointer(rightsp)), 0) if e1 != 0 { err = errnoErr(e1) } @@ -444,18 +488,13 @@ func fsetxattr(fd int, attr string, data *byte, size int, position uint32, optio // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func removexattr(path string, attr string, options int) (err error) { +func Chdir(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - var _p1 *byte - _p1, err = BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -464,13 +503,13 @@ func removexattr(path string, attr string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fremovexattr(fd int, attr string, options int) (err error) { +func Chflags(path string, flags int) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(attr) + _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -479,14 +518,13 @@ func fremovexattr(fd int, attr string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { +func Chmod(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - r0, _, e1 := Syscall6(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) + _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } @@ -495,9 +533,13 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { - r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) - sz = int(r0) +func Chown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } @@ -506,8 +548,13 @@ func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := Syscall6(SYS_SETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -516,9 +563,8 @@ func setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintp // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) - val = int(r0) +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } @@ -527,8 +573,8 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func kill(pid int, signum int, posix int) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) +func Close(fd int) (err error) { + _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -537,8 +583,9 @@ func kill(pid int, signum int, posix int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) +func Dup(fd int) (nfd int, err error) { + r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) + nfd = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -547,14 +594,8 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS_SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) +func Dup2(from int, to int) (err error) { + _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } @@ -563,23 +604,21 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { - _, _, e1 := Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) - } +func Exit(code int) { + Syscall(SYS_EXIT, uintptr(code), 0, 0) return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Access(path string, mode uint32) (err error) { +func ExtattrGetFd(fd int, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(attrname) if err != nil { return } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + r0, _, e1 := Syscall6(SYS_EXTATTR_GET_FD, uintptr(fd), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p0)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -588,8 +627,14 @@ func Access(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) +func ExtattrSetFd(fd int, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_SET_FD, uintptr(fd), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p0)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -598,13 +643,13 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chdir(path string) (err error) { +func ExtattrDeleteFd(fd int, attrnamespace int, attrname string) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(attrname) if err != nil { return } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := Syscall(SYS_EXTATTR_DELETE_FD, uintptr(fd), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p0))) if e1 != 0 { err = errnoErr(e1) } @@ -613,13 +658,9 @@ func Chdir(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chflags(path string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) +func ExtattrListFd(fd int, attrnamespace int, data uintptr, nbytes int) (ret int, err error) { + r0, _, e1 := Syscall6(SYS_EXTATTR_LIST_FD, uintptr(fd), uintptr(attrnamespace), uintptr(data), uintptr(nbytes), 0, 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -628,13 +669,19 @@ func Chflags(path string, flags int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chmod(path string, mode uint32) (err error) { +func ExtattrGetFile(file string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(file) if err != nil { return } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_GET_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -643,13 +690,19 @@ func Chmod(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chown(path string, uid int, gid int) (err error) { +func ExtattrSetFile(file string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(file) if err != nil { return } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_SET_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -658,13 +711,18 @@ func Chown(path string, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chroot(path string) (err error) { +func ExtattrDeleteFile(file string, attrnamespace int, attrname string) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(file) if err != nil { return } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_EXTATTR_DELETE_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } @@ -673,8 +731,14 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) +func ExtattrListFile(file string, attrnamespace int, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(file) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_LIST_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(data), uintptr(nbytes), 0, 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -683,9 +747,19 @@ func Close(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) - nfd = int(r0) +func ExtattrGetLink(link string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_GET_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -694,8 +768,19 @@ func Dup(fd int) (nfd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) +func ExtattrSetLink(link string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_SET_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -704,18 +789,18 @@ func Dup2(from int, to int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Exchangedata(path1 string, path2 string, options int) (err error) { +func ExtattrDeleteLink(link string, attrnamespace int, attrname string) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(path1) + _p0, err = BytePtrFromString(link) if err != nil { return } var _p1 *byte - _p1, err = BytePtrFromString(path2) + _p1, err = BytePtrFromString(attrname) if err != nil { return } - _, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + _, _, e1 := Syscall(SYS_EXTATTR_DELETE_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } @@ -724,8 +809,27 @@ func Exchangedata(path1 string, path2 string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) +func ExtattrListLink(link string, attrnamespace int, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_LIST_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(data), uintptr(nbytes), 0, 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_POSIX_FADVISE, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } return } @@ -837,6 +941,41 @@ func Fpathconf(fd int, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstat(fd int, stat *Stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatfs(fd int, stat *Statfs_t) (err error) { + _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -857,6 +996,23 @@ func Ftruncate(fd int, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getdirentries(fd int, buf []byte, basep *uint64) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0) size = int(r0) @@ -966,6 +1122,16 @@ func Getsid(pid int) (sid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getuid() (uid int) { r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) uid = int(r0) @@ -975,13 +1141,23 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := RawSyscall(SYS_ISSETUGID, 0, 0, 0) + r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0) tainted = bool(r0 != 0) return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Kill(pid int, signum syscall.Signal) (err error) { + _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Kqueue() (fd int, err error) { r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) fd = int(r0) @@ -1103,13 +1279,23 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mknod(path string, mode uint32, dev int) (err error) { +func Mknodat(fd int, path string, mode uint32, dev uint64) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Nanosleep(time *Timespec, leftover *Timespec) (err error) { + _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { err = errnoErr(e1) } @@ -1134,13 +1320,13 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { +func Openat(fdat int, path string, mode int, perm uint32) (fd int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(fdat), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1166,7 +1352,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1183,7 +1369,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1354,7 +1540,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setegid(egid int) (err error) { - _, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0) + _, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1418,8 +1604,8 @@ func Setpriority(which int, who int, prio int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setprivexec(flag int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIVEXEC, uintptr(flag), 0, 0) +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } @@ -1428,8 +1614,8 @@ func Setprivexec(flag int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } @@ -1438,8 +1624,8 @@ func Setregid(rgid int, egid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) +func Setresgid(rgid int, egid int, sgid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) if e1 != 0 { err = errnoErr(e1) } @@ -1448,8 +1634,8 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) +func Setresuid(ruid int, euid int, suid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) if e1 != 0 { err = errnoErr(e1) } @@ -1489,6 +1675,21 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Statfs(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Symlink(path string, link string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1660,135 +1861,9 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) { - r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) - sec = int64(r0) - usec = int32(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(buf), uintptr(size), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Lstat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Stat(path string, stat *Stat_t) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) +func accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error) { + r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) + nfd = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -1797,13 +1872,13 @@ func Stat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Statfs(path string, stat *Statfs_t) (err error) { +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go index 92efa1d..c698cbc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go @@ -1,7 +1,7 @@ // go run mksyscall_solaris.go -illumos -tags illumos,amd64 syscall_illumos.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build illumos,amd64 +//go:build illumos && amd64 package unix @@ -13,17 +13,20 @@ import ( //go:cgo_import_dynamic libc_preadv preadv "libc.so" //go:cgo_import_dynamic libc_writev writev "libc.so" //go:cgo_import_dynamic libc_pwritev pwritev "libc.so" +//go:cgo_import_dynamic libc_accept4 accept4 "libsocket.so" //go:linkname procreadv libc_readv //go:linkname procpreadv libc_preadv //go:linkname procwritev libc_writev //go:linkname procpwritev libc_pwritev +//go:linkname procaccept4 libc_accept4 var ( procreadv, procpreadv, procwritev, - procpwritev syscallFunc + procpwritev, + procaccept4 syscallFunc ) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -36,7 +39,7 @@ func readv(fd int, iovs []Iovec) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procreadv)), 3, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(iovs)), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -51,7 +54,7 @@ func preadv(fd int, iovs []Iovec, off int64) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procpreadv)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(iovs)), uintptr(off), 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -66,7 +69,7 @@ func writev(fd int, iovs []Iovec) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwritev)), 3, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(iovs)), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -81,7 +84,18 @@ func pwritev(fd int, iovs []Iovec, off int64) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procpwritev)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(iovs)), uintptr(off), 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procaccept4)), 4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) } return } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index fd2dae8..8935d10 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -1,6 +1,6 @@ -// Code generated by mkmerge.go; DO NOT EDIT. +// Code generated by mkmerge; DO NOT EDIT. -// +build linux +//go:build linux package unix @@ -37,6 +37,21 @@ func fchmodat(dirfd int, path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT2, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ioctl(fd int, req uint, arg uintptr) (err error) { _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { @@ -47,6 +62,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(oldpath) @@ -83,6 +108,32 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT2, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(open_how)), uintptr(size), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -194,6 +245,16 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) { + _, _, e1 := Syscall6(SYS_WAITID, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func KeyctlInt(cmd int, arg2 int, arg3 int, arg4 int, arg5 int) (ret int, err error) { r0, _, e1 := Syscall6(SYS_KEYCTL, uintptr(cmd), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5), 0) ret = int(r0) @@ -332,6 +393,16 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptracePtr(request int, pid int, addr uintptr, data unsafe.Pointer) (err error) { + _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(arg) @@ -372,6 +443,21 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(pathname) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MOUNT_SETATTR, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(unsafe.Pointer(attr)), uintptr(size), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -475,6 +561,17 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockAdjtime(clockid int32, buf *Timex) (state int, err error) { + r0, _, e1 := Syscall(SYS_CLOCK_ADJTIME, uintptr(clockid), uintptr(unsafe.Pointer(buf)), 0) + state = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ClockGetres(clockid int32, res *Timespec) (err error) { _, _, e1 := Syscall(SYS_CLOCK_GETRES, uintptr(clockid), uintptr(unsafe.Pointer(res)), 0) if e1 != 0 { @@ -495,6 +592,16 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockSettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_SETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error) { _, _, e1 := Syscall6(SYS_CLOCK_NANOSLEEP, uintptr(clockid), uintptr(flags), uintptr(unsafe.Pointer(request)), uintptr(unsafe.Pointer(remain)), 0, 0) if e1 != 0 { @@ -515,6 +622,16 @@ func Close(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func CloseRange(first uint, last uint, flags uint) (err error) { + _, _, e1 := Syscall(SYS_CLOSE_RANGE, uintptr(first), uintptr(last), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) { r0, _, e1 := Syscall6(SYS_COPY_FILE_RANGE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags)) n = int(r0) @@ -756,6 +873,59 @@ func Fsync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error) { + r0, _, e1 := Syscall(SYS_FSMOUNT, uintptr(fd), uintptr(flags), uintptr(mountAttrs)) + fsfd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsopen(fsName string, flags int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsName) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_FSOPEN, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fspick(dirfd int, pathName string, flags int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(pathName) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_FSPICK, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) { + _, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdents(fd int, buf []byte) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { @@ -811,23 +981,6 @@ func Getpriority(which int, who int) (prio int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getrandom(buf []byte, flags int) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_GETRANDOM, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { @@ -1133,6 +1286,26 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func MoveMount(fromDirfd int, fromPathName string, toDirfd int, toPathName string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fromPathName) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(toPathName) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MOVE_MOUNT, uintptr(fromDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(toDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1143,6 +1316,22 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func OpenTree(dfd int, fileName string, flags uint) (r int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fileName) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_OPEN_TREE, uintptr(dfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + r = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_PERF_EVENT_OPEN, uintptr(unsafe.Pointer(attr)), uintptr(pid), uintptr(cpu), uintptr(groupFd), uintptr(flags), 0) fd = int(r0) @@ -1174,16 +1363,6 @@ func PivotRoot(newroot string, putold string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { - _, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { _, _, e1 := Syscall6(SYS_PRCTL, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5), 0) if e1 != 0 { @@ -1194,7 +1373,7 @@ func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) ( // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { +func pselect6(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *sigset_argpack) (n int, err error) { r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask))) n = int(r0) if e1 != 0 { @@ -1450,6 +1629,37 @@ func Sysinfo(info *Sysinfo_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func TimerfdCreate(clockid int, flags int) (fd int, err error) { + r0, _, e1 := RawSyscall(SYS_TIMERFD_CREATE, uintptr(clockid), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func TimerfdGettime(fd int, currValue *ItimerSpec) (err error) { + _, _, e1 := RawSyscall(SYS_TIMERFD_GETTIME, uintptr(fd), uintptr(unsafe.Pointer(currValue)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error) { + _, _, e1 := RawSyscall6(SYS_TIMERFD_SETTIME, uintptr(fd), uintptr(flags), uintptr(unsafe.Pointer(newValue)), uintptr(unsafe.Pointer(oldValue)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) { _, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig)) if e1 != 0 { @@ -1541,28 +1751,6 @@ func exitThread(code int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, p *byte, np int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, p *byte, np int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func readv(fd int, iovs []Iovec) (n int, err error) { var _p0 unsafe.Pointer if len(iovs) > 0 { @@ -1675,6 +1863,17 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldaddr), uintptr(oldlength), uintptr(newlength), uintptr(flags), uintptr(newaddr), 0) + xaddr = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Madvise(b []byte, advice int) (err error) { var _p0 unsafe.Pointer if len(b) > 0 { @@ -1790,6 +1989,21 @@ func faccessat(dirfd int, path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FACCESSAT2, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(pathname) @@ -1816,8 +2030,219 @@ func openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) { + var _p0 unsafe.Pointer + if len(localIov) > 0 { + _p0 = unsafe.Pointer(&localIov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 unsafe.Pointer + if len(remoteIov) > 0 { + _p1 = unsafe.Pointer(&remoteIov[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PROCESS_VM_READV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) { + var _p0 unsafe.Pointer + if len(localIov) > 0 { + _p0 = unsafe.Pointer(&localIov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + var _p1 unsafe.Pointer + if len(remoteIov) > 0 { + _p1 = unsafe.Pointer(&remoteIov[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PROCESS_VM_WRITEV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func PidfdOpen(pid int, flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_PIDFD_OPEN, uintptr(pid), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_PIDFD_GETFD, uintptr(pidfd), uintptr(targetfd), uintptr(flags)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func PidfdSendSignal(pidfd int, sig Signal, info *Siginfo, flags int) (err error) { + _, _, e1 := Syscall6(SYS_PIDFD_SEND_SIGNAL, uintptr(pidfd), uintptr(sig), uintptr(unsafe.Pointer(info)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := Syscall(SYS_SHMAT, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := Syscall(SYS_SHMCTL, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := Syscall(SYS_SHMDT, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := Syscall(SYS_SHMGET, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getitimer(which int, currValue *Itimerval) (err error) { + _, _, e1 := Syscall(SYS_GETITIMER, uintptr(which), uintptr(unsafe.Pointer(currValue)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error) { + _, _, e1 := Syscall(SYS_SETITIMER, uintptr(which), uintptr(unsafe.Pointer(newValue)), uintptr(unsafe.Pointer(oldValue))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func rtSigprocmask(how int, set *Sigset_t, oldset *Sigset_t, sigsetsize uintptr) (err error) { + _, _, e1 := RawSyscall6(SYS_RT_SIGPROCMASK, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oldset)), uintptr(sigsetsize), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + RawSyscallNoError(SYS_GETRESUID, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + RawSyscallNoError(SYS_GETRESGID, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func schedSetattr(pid int, attr *SchedAttr, flags uint) (err error) { + _, _, e1 := Syscall(SYS_SCHED_SETATTR, uintptr(pid), uintptr(unsafe.Pointer(attr)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func schedGetattr(pid int, attr *SchedAttr, size uint, flags uint) (err error) { + _, _, e1 := Syscall6(SYS_SCHED_GETATTR, uintptr(pid), uintptr(unsafe.Pointer(attr)), uintptr(size), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) { + _, _, e1 := Syscall6(SYS_CACHESTAT, uintptr(fd), uintptr(unsafe.Pointer(crange)), uintptr(unsafe.Pointer(cstat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mseal(b []byte, flags uint) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MSEAL, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setMemPolicy(mode int, mask *CPUSet, size int) (err error) { + _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size)) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index ba63af7..4def3e9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -l32 -tags linux,386 syscall_linux.go syscall_linux_386.go +// go run mksyscall.go -l32 -tags linux,386 syscall_linux.go syscall_linux_386.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,386 +//go:build linux && 386 package unix @@ -45,37 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -180,17 +149,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -241,7 +199,7 @@ func Lstat(path string, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -258,7 +216,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -328,46 +286,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID32, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID32, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID32, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID32, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) { r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags)) n = int(r0) @@ -492,16 +410,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setrlimit(resource int, rlim *rlimit32) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func futimesat(dirfd int, path string, times *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -568,9 +476,9 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index f64adef..fef2bc8 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags linux,amd64 syscall_linux.go syscall_linux_amd64.go +// go run mksyscall.go -tags linux,amd64 syscall_linux.go syscall_linux_amd64.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,amd64 +//go:build linux && amd64 package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -190,17 +169,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func inotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -246,6 +214,17 @@ func Listen(s int, n int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func MemfdSecret(flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_MEMFD_SECRET, uintptr(flags), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pause() (err error) { _, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0) if e1 != 0 { @@ -256,7 +235,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -273,7 +252,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -354,56 +333,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -475,17 +404,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -710,19 +628,13 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) +func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(cmdline) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) + _, _, e1 := Syscall6(SYS_KEXEC_FILE_LOAD, uintptr(kernelFd), uintptr(initrdFd), uintptr(cmdlineLen), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -731,13 +643,9 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(cmdline) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_KEXEC_FILE_LOAD, uintptr(kernelFd), uintptr(initrdFd), uintptr(cmdlineLen), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index ac19523..a9fd76a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -1,7 +1,7 @@ // go run mksyscall.go -l32 -arm -tags linux,arm syscall_linux.go syscall_linux_arm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,arm +//go:build linux && arm package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -234,27 +213,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -339,17 +297,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -464,46 +411,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID32, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID32, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID32, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID32, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -590,7 +497,7 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -607,7 +514,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -670,27 +577,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setrlimit(resource int, rlim *rlimit32) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func armSyncFileRange(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_ARM_SYNC_FILE_RANGE, uintptr(fd), uintptr(flags), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index f0d2890..4600650 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -tags linux,arm64 syscall_linux.go syscall_linux_arm64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,arm64 +//go:build linux && arm64 package unix @@ -151,7 +151,7 @@ func Getgid() (gid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getrlimit(resource int, rlim *Rlimit) (err error) { +func getrlimit(resource int, rlim *Rlimit) (err error) { _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) if e1 != 0 { err = errnoErr(e1) @@ -179,7 +179,18 @@ func Listen(s int, n int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func MemfdSecret(flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_MEMFD_SECRET, uintptr(flags), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -196,7 +207,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -277,56 +288,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -388,17 +349,6 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go new file mode 100644 index 0000000..c8987d2 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go @@ -0,0 +1,486 @@ +// go run mksyscall.go -tags linux,loong64 syscall_linux.go syscall_linux_loong64.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build linux && loong64 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error) { + _, _, e1 := Syscall6(SYS_FANOTIFY_MARK, uintptr(fd), uintptr(flags), uintptr(mask), uintptr(dirFd), uintptr(unsafe.Pointer(pathname)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fallocate(fd int, mode uint32, off int64, len int64) (err error) { + _, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { + r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0) + n = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + var _p0 unsafe.Pointer + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_EPOLL_PWAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatfs(fd int, buf *Statfs_t) (err error) { + _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + r0, _ := RawSyscallNoError(SYS_GETEGID, 0, 0, 0) + egid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (euid int) { + r0, _ := RawSyscallNoError(SYS_GETEUID, 0, 0, 0) + euid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _ := RawSyscallNoError(SYS_GETGID, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _ := RawSyscallNoError(SYS_GETUID, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, n int) (err error) { + _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seek(fd int, offset int64, whence int) (off int64, err error) { + r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence)) + off = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0) + written = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setfsgid(gid int) (prev int, err error) { + r0, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0) + prev = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setfsuid(uid int) (prev int, err error) { + r0, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0) + prev = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Shutdown(fd int, how int) (err error) { + _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { + r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags)) + n = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Statfs(path string, buf *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func SyncFileRange(fd int, off int64, n int64, flags int) (err error) { + _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getgroups(n int, list *_Gid_t) (nn int, err error) { + r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + nn = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setgroups(n int, list *_Gid_t) (err error) { + _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { + _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { + _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socket(domain int, typ int, proto int) (fd int, err error) { + r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { + _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)) + xaddr = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(cmdline) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEXEC_FILE_LOAD, uintptr(kernelFd), uintptr(initrdFd), uintptr(cmdlineLen), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index aecbbca..921f430 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -b32 -arm -tags linux,mips syscall_linux.go syscall_linux_mipsx.go +// go run mksyscall.go -b32 -arm -tags linux,mips syscall_linux.go syscall_linux_mipsx.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,mips +//go:build linux && mips package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -170,7 +149,7 @@ func Listen(s int, n int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -187,7 +166,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -268,46 +247,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -364,17 +303,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -543,17 +471,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -705,18 +622,6 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) @@ -738,19 +643,9 @@ func getrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setrlimit(resource int, rlim *rlimit32) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index 424fb7f..44f0678 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags linux,mips64 syscall_linux.go syscall_linux_mips64x.go +// go run mksyscall.go -tags linux,mips64 syscall_linux.go syscall_linux_mips64x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,mips64 +//go:build linux && mips64 package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -200,7 +179,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -217,7 +196,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -298,56 +277,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -419,17 +348,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -719,9 +637,9 @@ func stat(path string, st *stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 28c7239..e7fa0ab 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -1,7 +1,7 @@ // go run mksyscall.go -tags linux,mips64le syscall_linux.go syscall_linux_mips64x.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,mips64le +//go:build linux && mips64le package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -200,7 +179,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -217,7 +196,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -298,56 +277,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -419,17 +348,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -716,14 +634,3 @@ func stat(path string, st *stat_t) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index 84596b3..8c51256 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -l32 -arm -tags linux,mipsle syscall_linux.go syscall_linux_mipsx.go +// go run mksyscall.go -l32 -arm -tags linux,mipsle syscall_linux.go syscall_linux_mipsx.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,mipsle +//go:build linux && mipsle package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -170,7 +149,7 @@ func Listen(s int, n int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -187,7 +166,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -268,46 +247,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -364,17 +303,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -543,17 +471,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -705,18 +622,6 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) @@ -738,19 +643,9 @@ func getrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func setrlimit(resource int, rlim *rlimit32) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go new file mode 100644 index 0000000..7392fd4 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go @@ -0,0 +1,658 @@ +// go run mksyscall.go -b32 -tags linux,ppc syscall_linux.go syscall_linux_ppc.go syscall_linux_alarm.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build linux && ppc + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error) { + _, _, e1 := Syscall6(SYS_FANOTIFY_MARK, uintptr(fd), uintptr(flags), uintptr(mask>>32), uintptr(mask), uintptr(dirFd), uintptr(unsafe.Pointer(pathname))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fallocate(fd int, mode uint32, off int64, len int64) (err error) { + _, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off>>32), uintptr(off), uintptr(len>>32), uintptr(len)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { + r0, r1, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0) + n = int64(int64(r0)<<32 | int64(r1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + var _p0 unsafe.Pointer + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, stat *Stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := Syscall(SYS_FTRUNCATE64, uintptr(fd), uintptr(length>>32), uintptr(length)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + r0, _ := RawSyscallNoError(SYS_GETEGID, 0, 0, 0) + egid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (euid int) { + r0, _ := RawSyscallNoError(SYS_GETEUID, 0, 0, 0) + euid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _ := RawSyscallNoError(SYS_GETGID, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _ := RawSyscallNoError(SYS_GETUID, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ioperm(from int, num int, on int) (err error) { + _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Iopl(level int) (err error) { + _, _, e1 := Syscall(SYS_IOPL, uintptr(level), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, n int) (err error) { + _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lstat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pause() (err error) { + _, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset>>32), uintptr(offset), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset>>32), uintptr(offset), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := Syscall6(SYS__NEWSELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + r0, _, e1 := Syscall6(SYS_SENDFILE64, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0) + written = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setfsgid(gid int) (prev int, err error) { + r0, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0) + prev = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setfsuid(uid int) (prev int, err error) { + r0, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0) + prev = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Shutdown(fd int, how int) (err error) { + _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) { + r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Stat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_TRUNCATE64, uintptr(unsafe.Pointer(_p0)), uintptr(length>>32), uintptr(length)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ustat(dev int, ubuf *Ustat_t) (err error) { + _, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getgroups(n int, list *_Gid_t) (nn int, err error) { + r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + nn = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setgroups(n int, list *_Gid_t) (err error) { + _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { + _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { + _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socket(domain int, typ int, proto int) (fd int, err error) { + r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { + _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func futimesat(dirfd int, path string, times *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Time(t *Time_t) (tt Time_t, err error) { + r0, _, e1 := RawSyscall(SYS_TIME, uintptr(unsafe.Pointer(t)), 0, 0) + tt = Time_t(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Utime(path string, buf *Utimbuf) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimes(path string, times *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) + xaddr = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getrlimit(resource int, rlim *rlimit32) (err error) { + _, _, e1 := RawSyscall(SYS_UGETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { + _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off>>32), uintptr(off), uintptr(n>>32), uintptr(n)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(cmdline) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEXEC_FILE_LOAD, uintptr(kernelFd), uintptr(initrdFd), uintptr(cmdlineLen), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index de02263..4118043 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags linux,ppc64 syscall_linux.go syscall_linux_ppc64x.go +// go run mksyscall.go -tags linux,ppc64 syscall_linux.go syscall_linux_ppc64x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,ppc64 +//go:build linux && ppc64 package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -190,17 +169,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -271,7 +239,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -288,7 +256,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -380,56 +348,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -506,17 +424,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -762,27 +669,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { @@ -805,3 +691,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 888f21d..40c6ce7 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags linux,ppc64le syscall_linux.go syscall_linux_ppc64x.go +// go run mksyscall.go -tags linux,ppc64le syscall_linux.go syscall_linux_ppc64x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,ppc64le +//go:build linux && ppc64le package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -190,17 +169,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -271,7 +239,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -288,7 +256,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -380,56 +348,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -506,17 +424,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -762,27 +669,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { @@ -805,3 +691,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index b761334..2cfe34a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -tags linux,riscv64 syscall_linux.go syscall_linux_riscv64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,riscv64 +//go:build linux && riscv64 package unix @@ -179,7 +179,18 @@ func Listen(s int, n int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func MemfdSecret(flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_MEMFD_SECRET, uintptr(flags), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -196,7 +207,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -257,56 +268,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -368,17 +329,6 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -580,3 +530,19 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func riscvHWProbe(pairs []RISCVHWProbePairs, cpuCount uintptr, cpus *CPUSet, flags uint) (err error) { + var _p0 unsafe.Pointer + if len(pairs) > 0 { + _p0 = unsafe.Pointer(&pairs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_RISCV_HWPROBE, uintptr(_p0), uintptr(len(pairs)), uintptr(cpuCount), uintptr(unsafe.Pointer(cpus)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 9bc353f..61e6f07 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags linux,s390x syscall_linux.go syscall_linux_s390x.go +// go run mksyscall.go -tags linux,s390x syscall_linux.go syscall_linux_s390x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,s390x +//go:build linux && s390x package unix @@ -45,27 +45,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -190,17 +169,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -241,7 +209,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -258,7 +226,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -350,56 +318,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags)) n = int64(r0) @@ -552,9 +470,13 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) +func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(cmdline) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_KEXEC_FILE_LOAD, uintptr(kernelFd), uintptr(initrdFd), uintptr(cmdlineLen), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -563,13 +485,9 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(cmdline) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_KEXEC_FILE_LOAD, uintptr(kernelFd), uintptr(initrdFd), uintptr(cmdlineLen), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 854e816..834b842 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -tags linux,sparc64 syscall_linux.go syscall_linux_sparc64.go +// go run mksyscall.go -tags linux,sparc64 syscall_linux.go syscall_linux_sparc64.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build linux,sparc64 +//go:build linux && sparc64 package unix @@ -72,16 +72,6 @@ func Fadvise(fd int, offset int64, length int64, advice int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -179,17 +169,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -240,7 +219,7 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -257,7 +236,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -349,56 +328,6 @@ func setfsuid(uid int) (prev int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Shutdown(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -475,17 +404,6 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -720,19 +638,9 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 3bbd9e3..e91ebc1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -1,7 +1,7 @@ // go run mksyscall.go -l32 -netbsd -tags netbsd,386 syscall_bsd.go syscall_netbsd.go syscall_netbsd_386.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build netbsd,386 +//go:build netbsd && 386 package unix @@ -350,10 +350,8 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -406,6 +404,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -522,6 +530,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -1331,7 +1349,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1348,7 +1366,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1588,16 +1606,6 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1815,20 +1823,13 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) + _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1837,13 +1838,9 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) +func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0) + xaddr = uintptr(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index d8cf501..be28bab 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -netbsd -tags netbsd,amd64 syscall_bsd.go syscall_netbsd.go syscall_netbsd_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build netbsd,amd64 +//go:build netbsd && amd64 package unix @@ -350,10 +350,8 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -406,6 +404,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -522,6 +530,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -1331,7 +1349,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1348,7 +1366,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1588,16 +1606,6 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1815,20 +1823,13 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) + _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1837,13 +1838,9 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) +func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0) + xaddr = uintptr(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 1153fe6..fb587e8 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -1,7 +1,7 @@ // go run mksyscall.go -l32 -netbsd -arm -tags netbsd,arm syscall_bsd.go syscall_netbsd.go syscall_netbsd_arm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build netbsd,arm +//go:build netbsd && arm package unix @@ -350,10 +350,8 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -406,6 +404,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -522,6 +530,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -1331,7 +1349,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1348,7 +1366,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1588,16 +1606,6 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1815,20 +1823,13 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) + _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1837,13 +1838,9 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) +func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0) + xaddr = uintptr(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go index 24b4ebb..d576438 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go @@ -1,7 +1,7 @@ // go run mksyscall.go -netbsd -tags netbsd,arm64 syscall_bsd.go syscall_netbsd.go syscall_netbsd_arm64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build netbsd,arm64 +//go:build netbsd && arm64 package unix @@ -350,10 +350,8 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } @@ -406,6 +404,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -522,6 +530,16 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_GETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Close(fd int) (err error) { _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) if e1 != 0 { @@ -1331,7 +1349,7 @@ func Pathconf(path string, name int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1348,7 +1366,7 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) @@ -1588,16 +1606,6 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Setsid() (pid int, err error) { r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) pid = int(r0) @@ -1815,20 +1823,13 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) + _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } @@ -1837,13 +1838,9 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) +func mremapNetBSD(oldp uintptr, oldsize uintptr, newp uintptr, newsize uintptr, flags int) (xaddr uintptr, err error) { + r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldp), uintptr(oldsize), uintptr(newp), uintptr(newsize), uintptr(flags), 0) + xaddr = uintptr(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index b44b31a..1851df1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -l32 -openbsd -tags openbsd,386 syscall_bsd.go syscall_openbsd.go syscall_openbsd_386.go +// go run mksyscall.go -l32 -openbsd -libc -tags openbsd,386 syscall_bsd.go syscall_openbsd.go syscall_openbsd_386.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build openbsd,386 +//go:build openbsd && 386 package unix @@ -15,7 +15,7 @@ var _ syscall.Errno // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -23,20 +23,28 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { return } +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -44,10 +52,14 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err return } +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -55,30 +67,42 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { return } +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -86,66 +110,94 @@ func socket(domain int, typ int, proto int) (fd int, err error) { return } +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { @@ -155,7 +207,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -163,6 +215,10 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl return } +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { @@ -172,17 +228,21 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -190,10 +250,14 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -201,10 +265,14 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -212,6 +280,10 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne return } +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func utimes(path string, timeval *[2]Timeval) (err error) { @@ -220,27 +292,35 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -248,6 +328,10 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { return } +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Madvise(b []byte, behav int) (err error) { @@ -257,13 +341,17 @@ func Madvise(b []byte, behav int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlock(b []byte) (err error) { @@ -273,23 +361,31 @@ func Mlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mprotect(b []byte, prot int) (err error) { @@ -299,13 +395,17 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Msync(b []byte, flags int) (err error) { @@ -315,13 +415,17 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlock(b []byte) (err error) { @@ -331,33 +435,45 @@ func Munlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getdents(fd int, buf []byte) (n int, err error) { @@ -367,7 +483,7 @@ func Getdents(fd int, buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -375,6 +491,10 @@ func Getdents(fd int, buf []byte) (n int, err error) { return } +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getcwd(buf []byte) (n int, err error) { @@ -384,7 +504,7 @@ func Getcwd(buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -392,10 +512,50 @@ func Getcwd(buf []byte) (n int, err error) { return } +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -411,7 +571,37 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -421,7 +611,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { - r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -429,6 +619,10 @@ func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, return } +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Access(path string, mode uint32) (err error) { @@ -437,23 +631,31 @@ func Access(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chdir(path string) (err error) { @@ -462,13 +664,17 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chflags(path string, flags int) (err error) { @@ -477,13 +683,17 @@ func Chflags(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chmod(path string, mode uint32) (err error) { @@ -492,13 +702,17 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chown(path string, uid int, gid int) (err error) { @@ -507,13 +721,17 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chroot(path string) (err error) { @@ -522,27 +740,49 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) nfd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -550,33 +790,49 @@ func Dup(fd int) (nfd int, err error) { return } +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup3(from int, to int, flags int) (err error) { - _, _, e1 := Syscall(SYS_DUP3, uintptr(from), uintptr(to), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) return } +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -585,43 +841,59 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -630,23 +902,31 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { @@ -655,27 +935,35 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -683,16 +971,24 @@ func Fpathconf(fd int, name int) (val int, err error) { return } +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { @@ -701,71 +997,99 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall6(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0) + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), uintptr(length>>32)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) egid = int(r0) return } +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) gid = int(r0) return } +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) pgid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -773,34 +1097,50 @@ func Getpgid(pid int) (pgid int, err error) { return } +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) pgrp = int(r0) return } +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) pid = int(r0) return } +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) ppid = int(r0) return } +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) prio = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -808,20 +1148,28 @@ func Getpriority(which int, who int) (prio int, err error) { return } +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrtable() (rtable int, err error) { - r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) rtable = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -829,20 +1177,28 @@ func Getrtable() (rtable int, err error) { return } +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) sid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -850,46 +1206,66 @@ func Getsid(pid int) (sid int, err error) { return } +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Gettimeofday(tv *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0) + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) tainted = bool(r0 != 0) return } +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kill(pid int, signum syscall.Signal) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0) + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -897,6 +1273,10 @@ func Kqueue() (fd int, err error) { return } +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lchown(path string, uid int, gid int) (err error) { @@ -905,13 +1285,17 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Link(path string, link string) (err error) { @@ -925,13 +1309,17 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { @@ -945,23 +1333,31 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er if err != nil { return } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lstat(path string, stat *Stat_t) (err error) { @@ -970,13 +1366,17 @@ func Lstat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdir(path string, mode uint32) (err error) { @@ -985,13 +1385,17 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdirat(dirfd int, path string, mode uint32) (err error) { @@ -1000,13 +1404,17 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifo(path string, mode uint32) (err error) { @@ -1015,13 +1423,17 @@ func Mkfifo(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifoat(dirfd int, path string, mode uint32) (err error) { @@ -1030,13 +1442,17 @@ func Mkfifoat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknod(path string, mode uint32, dev int) (err error) { @@ -1045,13 +1461,17 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { @@ -1060,23 +1480,55 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Nanosleep(time *Timespec, leftover *Timespec) (err error) { - _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Open(path string, mode int, perm uint32) (fd int, err error) { @@ -1085,7 +1537,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1093,6 +1545,10 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { return } +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { @@ -1101,7 +1557,7 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1109,6 +1565,10 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { return } +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Pathconf(path string, name int) (val int, err error) { @@ -1117,7 +1577,7 @@ func Pathconf(path string, name int) (val int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1125,16 +1585,20 @@ func Pathconf(path string, name int) (val int, err error) { return } +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32)) + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1142,16 +1606,20 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32)) + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1159,6 +1627,10 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func read(fd int, p []byte) (n int, err error) { @@ -1168,7 +1640,7 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1176,6 +1648,10 @@ func read(fd int, p []byte) (n int, err error) { return } +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlink(path string, buf []byte) (n int, err error) { @@ -1190,7 +1666,7 @@ func Readlink(path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1198,6 +1674,10 @@ func Readlink(path string, buf []byte) (n int, err error) { return } +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { @@ -1212,7 +1692,7 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1220,6 +1700,10 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { return } +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rename(from string, to string) (err error) { @@ -1233,13 +1717,17 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Renameat(fromfd int, from string, tofd int, to string) (err error) { @@ -1253,13 +1741,17 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Revoke(path string) (err error) { @@ -1268,13 +1760,17 @@ func Revoke(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rmdir(path string) (err error) { @@ -1283,17 +1779,21 @@ func Rmdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(whence), 0) + r0, r1, e1 := syscall_syscall6(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0) newoffset = int64(int64(r1)<<32 | int64(r0)) if e1 != 0 { err = errnoErr(e1) @@ -1301,10 +1801,14 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return } +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1312,36 +1816,52 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err return } +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setegid(egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setlogin(name string) (err error) { @@ -1350,97 +1870,119 @@ func Setlogin(name string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) if e1 != 0 { err = errnoErr(e1) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +var libc_setresuid_trampoline_addr uintptr -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrtable(rtable int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) pid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1448,26 +1990,38 @@ func Setsid() (pid int, err error) { return } +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Stat(path string, stat *Stat_t) (err error) { @@ -1476,13 +2030,17 @@ func Stat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Statfs(path string, stat *Statfs_t) (err error) { @@ -1491,13 +2049,17 @@ func Statfs(path string, stat *Statfs_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlink(path string, link string) (err error) { @@ -1511,13 +2073,17 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { @@ -1531,23 +2097,31 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Truncate(path string, length int64) (err error) { @@ -1556,21 +2130,29 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0) + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) oldmask = int(r0) return } +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlink(path string) (err error) { @@ -1579,13 +2161,17 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlinkat(dirfd int, path string, flags int) (err error) { @@ -1594,13 +2180,17 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unmount(path string, flags int) (err error) { @@ -1609,13 +2199,17 @@ func Unmount(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func write(fd int, p []byte) (n int, err error) { @@ -1625,7 +2219,7 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1633,10 +2227,14 @@ func write(fd int, p []byte) (n int, err error) { return } +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0) + r0, _, e1 := syscall_syscall9(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0) ret = uintptr(r0) if e1 != 0 { err = errnoErr(e1) @@ -1644,20 +2242,28 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( return } +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1665,28 +2271,53 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) if e1 != 0 { err = errnoErr(e1) } return } + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s new file mode 100644 index 0000000..0b43c69 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s @@ -0,0 +1,699 @@ +// go run mkasm.go openbsd 386 +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgroups(SB) +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getgroups_trampoline_addr(SB)/4, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgroups(SB) +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setgroups_trampoline_addr(SB)/4, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_wait4(SB) +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $4 +DATA ·libc_wait4_trampoline_addr(SB)/4, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_accept(SB) +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $4 +DATA ·libc_accept_trampoline_addr(SB)/4, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_bind(SB) +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $4 +DATA ·libc_bind_trampoline_addr(SB)/4, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connect(SB) +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $4 +DATA ·libc_connect_trampoline_addr(SB)/4, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socket(SB) +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $4 +DATA ·libc_socket_trampoline_addr(SB)/4, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockopt(SB) +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getsockopt_trampoline_addr(SB)/4, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsockopt(SB) +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setsockopt_trampoline_addr(SB)/4, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpeername(SB) +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpeername_trampoline_addr(SB)/4, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockname(SB) +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getsockname_trampoline_addr(SB)/4, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shutdown(SB) +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_shutdown_trampoline_addr(SB)/4, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socketpair(SB) +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $4 +DATA ·libc_socketpair_trampoline_addr(SB)/4, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvfrom(SB) +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $4 +DATA ·libc_recvfrom_trampoline_addr(SB)/4, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendto(SB) +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sendto_trampoline_addr(SB)/4, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvmsg(SB) +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $4 +DATA ·libc_recvmsg_trampoline_addr(SB)/4, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendmsg(SB) +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sendmsg_trampoline_addr(SB)/4, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kevent(SB) +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $4 +DATA ·libc_kevent_trampoline_addr(SB)/4, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimes(SB) +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $4 +DATA ·libc_utimes_trampoline_addr(SB)/4, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_futimes(SB) +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $4 +DATA ·libc_futimes_trampoline_addr(SB)/4, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_poll(SB) +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $4 +DATA ·libc_poll_trampoline_addr(SB)/4, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_madvise(SB) +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $4 +DATA ·libc_madvise_trampoline_addr(SB)/4, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlock(SB) +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mlock_trampoline_addr(SB)/4, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlockall(SB) +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mlockall_trampoline_addr(SB)/4, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mprotect(SB) +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mprotect_trampoline_addr(SB)/4, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_msync(SB) +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $4 +DATA ·libc_msync_trampoline_addr(SB)/4, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlock(SB) +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $4 +DATA ·libc_munlock_trampoline_addr(SB)/4, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlockall(SB) +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $4 +DATA ·libc_munlockall_trampoline_addr(SB)/4, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pipe2(SB) +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pipe2_trampoline_addr(SB)/4, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getdents(SB) +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getdents_trampoline_addr(SB)/4, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getcwd_trampoline_addr(SB)/4, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresuid(SB) +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getresuid_trampoline_addr(SB)/4, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresgid(SB) +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getresgid_trampoline_addr(SB)/4, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ioctl(SB) +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_ioctl_trampoline_addr(SB)/4, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sysctl_trampoline_addr(SB)/4, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fcntl_trampoline_addr(SB)/4, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ppoll(SB) +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $4 +DATA ·libc_ppoll_trampoline_addr(SB)/4, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_access(SB) +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $4 +DATA ·libc_access_trampoline_addr(SB)/4, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_adjtime(SB) +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $4 +DATA ·libc_adjtime_trampoline_addr(SB)/4, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chdir(SB) +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chdir_trampoline_addr(SB)/4, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chflags(SB) +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chflags_trampoline_addr(SB)/4, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chmod(SB) +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chmod_trampoline_addr(SB)/4, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chown(SB) +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chown_trampoline_addr(SB)/4, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chroot(SB) +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chroot_trampoline_addr(SB)/4, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $4 +DATA ·libc_clock_gettime_trampoline_addr(SB)/4, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_close(SB) +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $4 +DATA ·libc_close_trampoline_addr(SB)/4, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup(SB) +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $4 +DATA ·libc_dup_trampoline_addr(SB)/4, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup2(SB) +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $4 +DATA ·libc_dup2_trampoline_addr(SB)/4, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup3(SB) +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $4 +DATA ·libc_dup3_trampoline_addr(SB)/4, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_exit(SB) +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $4 +DATA ·libc_exit_trampoline_addr(SB)/4, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_faccessat(SB) +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_faccessat_trampoline_addr(SB)/4, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchdir(SB) +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchdir_trampoline_addr(SB)/4, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchflags(SB) +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchflags_trampoline_addr(SB)/4, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmod(SB) +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchmod_trampoline_addr(SB)/4, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmodat(SB) +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchmodat_trampoline_addr(SB)/4, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchown(SB) +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchown_trampoline_addr(SB)/4, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchownat(SB) +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchownat_trampoline_addr(SB)/4, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_flock(SB) +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $4 +DATA ·libc_flock_trampoline_addr(SB)/4, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fpathconf(SB) +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fpathconf_trampoline_addr(SB)/4, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstat(SB) +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fstat_trampoline_addr(SB)/4, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatat(SB) +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fstatat_trampoline_addr(SB)/4, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatfs(SB) +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fstatfs_trampoline_addr(SB)/4, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fsync(SB) +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fsync_trampoline_addr(SB)/4, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ftruncate(SB) +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $4 +DATA ·libc_ftruncate_trampoline_addr(SB)/4, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getegid(SB) +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getegid_trampoline_addr(SB)/4, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_geteuid(SB) +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_geteuid_trampoline_addr(SB)/4, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgid(SB) +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getgid_trampoline_addr(SB)/4, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgid(SB) +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpgid_trampoline_addr(SB)/4, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgrp(SB) +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpgrp_trampoline_addr(SB)/4, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpid(SB) +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpid_trampoline_addr(SB)/4, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getppid(SB) +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getppid_trampoline_addr(SB)/4, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpriority(SB) +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpriority_trampoline_addr(SB)/4, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrlimit(SB) +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getrlimit_trampoline_addr(SB)/4, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrtable(SB) +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getrtable_trampoline_addr(SB)/4, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrusage(SB) +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getrusage_trampoline_addr(SB)/4, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsid(SB) +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getsid_trampoline_addr(SB)/4, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $4 +DATA ·libc_gettimeofday_trampoline_addr(SB)/4, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getuid(SB) +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getuid_trampoline_addr(SB)/4, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_issetugid(SB) +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_issetugid_trampoline_addr(SB)/4, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kill(SB) +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $4 +DATA ·libc_kill_trampoline_addr(SB)/4, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kqueue(SB) +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $4 +DATA ·libc_kqueue_trampoline_addr(SB)/4, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lchown(SB) +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_lchown_trampoline_addr(SB)/4, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_link(SB) +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $4 +DATA ·libc_link_trampoline_addr(SB)/4, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_linkat(SB) +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_linkat_trampoline_addr(SB)/4, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_listen(SB) +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $4 +DATA ·libc_listen_trampoline_addr(SB)/4, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lstat(SB) +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_lstat_trampoline_addr(SB)/4, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdir(SB) +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkdir_trampoline_addr(SB)/4, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdirat(SB) +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkdirat_trampoline_addr(SB)/4, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifo(SB) +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkfifo_trampoline_addr(SB)/4, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifoat(SB) +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkfifoat_trampoline_addr(SB)/4, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknod(SB) +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mknod_trampoline_addr(SB)/4, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknodat(SB) +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_nanosleep(SB) +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4 +DATA ·libc_nanosleep_trampoline_addr(SB)/4, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_open(SB) +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $4 +DATA ·libc_open_trampoline_addr(SB)/4, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_openat(SB) +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_openat_trampoline_addr(SB)/4, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pathconf(SB) +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pathconf_trampoline_addr(SB)/4, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pread(SB) +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pread_trampoline_addr(SB)/4, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwrite(SB) +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pwrite_trampoline_addr(SB)/4, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_read(SB) +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $4 +DATA ·libc_read_trampoline_addr(SB)/4, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlink(SB) +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $4 +DATA ·libc_readlink_trampoline_addr(SB)/4, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlinkat(SB) +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_readlinkat_trampoline_addr(SB)/4, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rename(SB) +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $4 +DATA ·libc_rename_trampoline_addr(SB)/4, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameat(SB) +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_renameat_trampoline_addr(SB)/4, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_revoke(SB) +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $4 +DATA ·libc_revoke_trampoline_addr(SB)/4, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rmdir(SB) +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_rmdir_trampoline_addr(SB)/4, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lseek(SB) +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $4 +DATA ·libc_lseek_trampoline_addr(SB)/4, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_select(SB) +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $4 +DATA ·libc_select_trampoline_addr(SB)/4, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setegid(SB) +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setegid_trampoline_addr(SB)/4, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_seteuid(SB) +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_seteuid_trampoline_addr(SB)/4, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgid(SB) +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setgid_trampoline_addr(SB)/4, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setlogin(SB) +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setlogin_trampoline_addr(SB)/4, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpgid(SB) +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setpgid_trampoline_addr(SB)/4, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpriority(SB) +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setpriority_trampoline_addr(SB)/4, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setregid(SB) +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setregid_trampoline_addr(SB)/4, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setreuid(SB) +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setreuid_trampoline_addr(SB)/4, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresgid(SB) +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setresgid_trampoline_addr(SB)/4, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresuid(SB) +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setresuid_trampoline_addr(SB)/4, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setrtable(SB) +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setrtable_trampoline_addr(SB)/4, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsid(SB) +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setsid_trampoline_addr(SB)/4, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_settimeofday(SB) +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $4 +DATA ·libc_settimeofday_trampoline_addr(SB)/4, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setuid(SB) +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setuid_trampoline_addr(SB)/4, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_stat(SB) +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_stat_trampoline_addr(SB)/4, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $4 +DATA ·libc_statfs_trampoline_addr(SB)/4, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlink(SB) +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $4 +DATA ·libc_symlink_trampoline_addr(SB)/4, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlinkat(SB) +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_symlinkat_trampoline_addr(SB)/4, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sync(SB) +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sync_trampoline_addr(SB)/4, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_truncate(SB) +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $4 +DATA ·libc_truncate_trampoline_addr(SB)/4, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_umask(SB) +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $4 +DATA ·libc_umask_trampoline_addr(SB)/4, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlink(SB) +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unlink_trampoline_addr(SB)/4, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlinkat(SB) +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unlinkat_trampoline_addr(SB)/4, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unmount(SB) +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unmount_trampoline_addr(SB)/4, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_write(SB) +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $4 +DATA ·libc_write_trampoline_addr(SB)/4, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mmap(SB) +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mmap_trampoline_addr(SB)/4, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munmap(SB) +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $4 +DATA ·libc_munmap_trampoline_addr(SB)/4, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getfsstat_trampoline_addr(SB)/4, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 67f93ee..e1ec0db 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -openbsd -tags openbsd,amd64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_amd64.go +// go run mksyscall.go -openbsd -libc -tags openbsd,amd64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build openbsd,amd64 +//go:build openbsd && amd64 package unix @@ -15,7 +15,7 @@ var _ syscall.Errno // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -23,20 +23,28 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { return } +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -44,10 +52,14 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err return } +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -55,30 +67,42 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { return } +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -86,66 +110,94 @@ func socket(domain int, typ int, proto int) (fd int, err error) { return } +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { @@ -155,7 +207,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -163,6 +215,10 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl return } +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { @@ -172,17 +228,21 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -190,10 +250,14 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -201,10 +265,14 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -212,6 +280,10 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne return } +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func utimes(path string, timeval *[2]Timeval) (err error) { @@ -220,27 +292,35 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -248,6 +328,10 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { return } +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Madvise(b []byte, behav int) (err error) { @@ -257,13 +341,17 @@ func Madvise(b []byte, behav int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlock(b []byte) (err error) { @@ -273,23 +361,31 @@ func Mlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mprotect(b []byte, prot int) (err error) { @@ -299,13 +395,17 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Msync(b []byte, flags int) (err error) { @@ -315,13 +415,17 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlock(b []byte) (err error) { @@ -331,33 +435,45 @@ func Munlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getdents(fd int, buf []byte) (n int, err error) { @@ -367,7 +483,7 @@ func Getdents(fd int, buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -375,6 +491,10 @@ func Getdents(fd int, buf []byte) (n int, err error) { return } +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getcwd(buf []byte) (n int, err error) { @@ -384,7 +504,7 @@ func Getcwd(buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -392,10 +512,50 @@ func Getcwd(buf []byte) (n int, err error) { return } +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -411,7 +571,37 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -421,7 +611,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { - r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -429,6 +619,10 @@ func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, return } +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Access(path string, mode uint32) (err error) { @@ -437,23 +631,31 @@ func Access(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chdir(path string) (err error) { @@ -462,13 +664,17 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chflags(path string, flags int) (err error) { @@ -477,13 +683,17 @@ func Chflags(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chmod(path string, mode uint32) (err error) { @@ -492,13 +702,17 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chown(path string, uid int, gid int) (err error) { @@ -507,13 +721,17 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chroot(path string) (err error) { @@ -522,27 +740,49 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) nfd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -550,33 +790,49 @@ func Dup(fd int) (nfd int, err error) { return } +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup3(from int, to int, flags int) (err error) { - _, _, e1 := Syscall(SYS_DUP3, uintptr(from), uintptr(to), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) return } +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -585,43 +841,59 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -630,23 +902,31 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { @@ -655,27 +935,35 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -683,16 +971,24 @@ func Fpathconf(fd int, name int) (val int, err error) { return } +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { @@ -701,71 +997,99 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length)) + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) egid = int(r0) return } +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) gid = int(r0) return } +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) pgid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -773,34 +1097,50 @@ func Getpgid(pid int) (pgid int, err error) { return } +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) pgrp = int(r0) return } +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) pid = int(r0) return } +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) ppid = int(r0) return } +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) prio = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -808,20 +1148,28 @@ func Getpriority(which int, who int) (prio int, err error) { return } +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrtable() (rtable int, err error) { - r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) rtable = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -829,20 +1177,28 @@ func Getrtable() (rtable int, err error) { return } +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) sid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -850,46 +1206,66 @@ func Getsid(pid int) (sid int, err error) { return } +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Gettimeofday(tv *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0) + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) tainted = bool(r0 != 0) return } +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kill(pid int, signum syscall.Signal) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0) + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -897,6 +1273,10 @@ func Kqueue() (fd int, err error) { return } +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lchown(path string, uid int, gid int) (err error) { @@ -905,13 +1285,17 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Link(path string, link string) (err error) { @@ -925,13 +1309,17 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { @@ -945,23 +1333,31 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er if err != nil { return } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lstat(path string, stat *Stat_t) (err error) { @@ -970,13 +1366,17 @@ func Lstat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdir(path string, mode uint32) (err error) { @@ -985,13 +1385,17 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdirat(dirfd int, path string, mode uint32) (err error) { @@ -1000,13 +1404,17 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifo(path string, mode uint32) (err error) { @@ -1015,13 +1423,17 @@ func Mkfifo(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifoat(dirfd int, path string, mode uint32) (err error) { @@ -1030,13 +1442,17 @@ func Mkfifoat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknod(path string, mode uint32, dev int) (err error) { @@ -1045,13 +1461,17 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { @@ -1060,23 +1480,55 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Nanosleep(time *Timespec, leftover *Timespec) (err error) { - _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Open(path string, mode int, perm uint32) (fd int, err error) { @@ -1085,7 +1537,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1093,6 +1545,10 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { return } +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { @@ -1101,7 +1557,7 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1109,6 +1565,10 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { return } +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Pathconf(path string, name int) (val int, err error) { @@ -1117,7 +1577,7 @@ func Pathconf(path string, name int) (val int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1125,16 +1585,20 @@ func Pathconf(path string, name int) (val int, err error) { return } +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0) + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1142,16 +1606,20 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0) + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1159,6 +1627,10 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func read(fd int, p []byte) (n int, err error) { @@ -1168,7 +1640,7 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1176,6 +1648,10 @@ func read(fd int, p []byte) (n int, err error) { return } +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlink(path string, buf []byte) (n int, err error) { @@ -1190,7 +1666,7 @@ func Readlink(path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1198,6 +1674,10 @@ func Readlink(path string, buf []byte) (n int, err error) { return } +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { @@ -1212,7 +1692,7 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1220,6 +1700,10 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { return } +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rename(from string, to string) (err error) { @@ -1233,13 +1717,17 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Renameat(fromfd int, from string, tofd int, to string) (err error) { @@ -1253,13 +1741,17 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Revoke(path string) (err error) { @@ -1268,13 +1760,17 @@ func Revoke(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rmdir(path string) (err error) { @@ -1283,17 +1779,21 @@ func Rmdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, _, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(whence), 0, 0) + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) newoffset = int64(r0) if e1 != 0 { err = errnoErr(e1) @@ -1301,10 +1801,14 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return } +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1312,36 +1816,52 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err return } +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setegid(egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setlogin(name string) (err error) { @@ -1350,97 +1870,119 @@ func Setlogin(name string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) if e1 != 0 { err = errnoErr(e1) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +var libc_setresuid_trampoline_addr uintptr -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrtable(rtable int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) pid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1448,26 +1990,38 @@ func Setsid() (pid int, err error) { return } +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Stat(path string, stat *Stat_t) (err error) { @@ -1476,13 +2030,17 @@ func Stat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Statfs(path string, stat *Statfs_t) (err error) { @@ -1491,13 +2049,17 @@ func Statfs(path string, stat *Statfs_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlink(path string, link string) (err error) { @@ -1511,13 +2073,17 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { @@ -1531,23 +2097,31 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Truncate(path string, length int64) (err error) { @@ -1556,21 +2130,29 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length)) + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) oldmask = int(r0) return } +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlink(path string) (err error) { @@ -1579,13 +2161,17 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlinkat(dirfd int, path string, flags int) (err error) { @@ -1594,13 +2180,17 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unmount(path string, flags int) (err error) { @@ -1609,13 +2199,17 @@ func Unmount(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func write(fd int, p []byte) (n int, err error) { @@ -1625,7 +2219,7 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1633,10 +2227,14 @@ func write(fd int, p []byte) (n int, err error) { return } +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), 0, 0) + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) ret = uintptr(r0) if e1 != 0 { err = errnoErr(e1) @@ -1644,20 +2242,28 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( return } +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1665,28 +2271,53 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) if e1 != 0 { err = errnoErr(e1) } return } + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s new file mode 100644 index 0000000..880c6d6 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s @@ -0,0 +1,699 @@ +// go run mkasm.go openbsd amd64 +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgroups(SB) +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgroups(SB) +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_wait4(SB) +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_accept(SB) +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_bind(SB) +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connect(SB) +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socket(SB) +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockopt(SB) +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsockopt(SB) +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpeername(SB) +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockname(SB) +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shutdown(SB) +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socketpair(SB) +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvfrom(SB) +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendto(SB) +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvmsg(SB) +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendmsg(SB) +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kevent(SB) +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimes(SB) +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_futimes(SB) +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_poll(SB) +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_madvise(SB) +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlock(SB) +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlockall(SB) +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mprotect(SB) +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_msync(SB) +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlock(SB) +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlockall(SB) +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pipe2(SB) +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe2_trampoline_addr(SB)/8, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getdents(SB) +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdents_trampoline_addr(SB)/8, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresuid(SB) +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresgid(SB) +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ioctl(SB) +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ppoll(SB) +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ppoll_trampoline_addr(SB)/8, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_access(SB) +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_adjtime(SB) +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chdir(SB) +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chflags(SB) +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chmod(SB) +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chown(SB) +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chroot(SB) +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_close(SB) +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup(SB) +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup2(SB) +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup3(SB) +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup3_trampoline_addr(SB)/8, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_exit(SB) +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_faccessat(SB) +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchdir(SB) +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchflags(SB) +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmod(SB) +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmodat(SB) +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchown(SB) +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchownat(SB) +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_flock(SB) +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fpathconf(SB) +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstat(SB) +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat_trampoline_addr(SB)/8, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatat(SB) +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat_trampoline_addr(SB)/8, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatfs(SB) +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs_trampoline_addr(SB)/8, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fsync(SB) +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ftruncate(SB) +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getegid(SB) +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_geteuid(SB) +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgid(SB) +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgid(SB) +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgrp(SB) +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpid(SB) +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getppid(SB) +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpriority(SB) +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrlimit(SB) +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrtable(SB) +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrtable_trampoline_addr(SB)/8, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrusage(SB) +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsid(SB) +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getuid(SB) +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_issetugid(SB) +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kill(SB) +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kqueue(SB) +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lchown(SB) +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_link(SB) +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_linkat(SB) +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_listen(SB) +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lstat(SB) +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat_trampoline_addr(SB)/8, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdir(SB) +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdirat(SB) +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifo(SB) +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifoat(SB) +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifoat_trampoline_addr(SB)/8, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknod(SB) +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknodat(SB) +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_nanosleep(SB) +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 +DATA ·libc_nanosleep_trampoline_addr(SB)/8, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_open(SB) +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_openat(SB) +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pathconf(SB) +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pread(SB) +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwrite(SB) +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_read(SB) +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlink(SB) +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlinkat(SB) +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rename(SB) +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameat(SB) +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_revoke(SB) +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rmdir(SB) +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lseek(SB) +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_select(SB) +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setegid(SB) +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_seteuid(SB) +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgid(SB) +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setlogin(SB) +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpgid(SB) +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpriority(SB) +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setregid(SB) +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setreuid(SB) +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresgid(SB) +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresgid_trampoline_addr(SB)/8, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresuid(SB) +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setrtable(SB) +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setrtable_trampoline_addr(SB)/8, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsid(SB) +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_settimeofday(SB) +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setuid(SB) +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_stat(SB) +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat_trampoline_addr(SB)/8, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs_trampoline_addr(SB)/8, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlink(SB) +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlinkat(SB) +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sync(SB) +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_truncate(SB) +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_umask(SB) +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlink(SB) +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlinkat(SB) +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unmount(SB) +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_write(SB) +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mmap(SB) +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munmap(SB) +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index d7c878b..7c8452a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -l32 -openbsd -arm -tags openbsd,arm syscall_bsd.go syscall_openbsd.go syscall_openbsd_arm.go +// go run mksyscall.go -l32 -openbsd -arm -libc -tags openbsd,arm syscall_bsd.go syscall_openbsd.go syscall_openbsd_arm.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build openbsd,arm +//go:build openbsd && arm package unix @@ -15,7 +15,7 @@ var _ syscall.Errno // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -23,20 +23,28 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { return } +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -44,10 +52,14 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err return } +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -55,30 +67,42 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { return } +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -86,66 +110,94 @@ func socket(domain int, typ int, proto int) (fd int, err error) { return } +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { @@ -155,7 +207,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -163,6 +215,10 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl return } +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { @@ -172,17 +228,21 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -190,10 +250,14 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -201,10 +265,14 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -212,6 +280,10 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne return } +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func utimes(path string, timeval *[2]Timeval) (err error) { @@ -220,27 +292,35 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -248,6 +328,10 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { return } +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Madvise(b []byte, behav int) (err error) { @@ -257,13 +341,17 @@ func Madvise(b []byte, behav int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlock(b []byte) (err error) { @@ -273,23 +361,31 @@ func Mlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mprotect(b []byte, prot int) (err error) { @@ -299,13 +395,17 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Msync(b []byte, flags int) (err error) { @@ -315,13 +415,17 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlock(b []byte) (err error) { @@ -331,33 +435,45 @@ func Munlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getdents(fd int, buf []byte) (n int, err error) { @@ -367,7 +483,7 @@ func Getdents(fd int, buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -375,6 +491,10 @@ func Getdents(fd int, buf []byte) (n int, err error) { return } +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getcwd(buf []byte) (n int, err error) { @@ -384,7 +504,7 @@ func Getcwd(buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -392,10 +512,50 @@ func Getcwd(buf []byte) (n int, err error) { return } +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -411,7 +571,37 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -421,7 +611,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { - r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -429,6 +619,10 @@ func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, return } +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Access(path string, mode uint32) (err error) { @@ -437,23 +631,31 @@ func Access(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chdir(path string) (err error) { @@ -462,13 +664,17 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chflags(path string, flags int) (err error) { @@ -477,13 +683,17 @@ func Chflags(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chmod(path string, mode uint32) (err error) { @@ -492,13 +702,17 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chown(path string, uid int, gid int) (err error) { @@ -507,13 +721,17 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chroot(path string) (err error) { @@ -522,27 +740,49 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) nfd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -550,33 +790,49 @@ func Dup(fd int) (nfd int, err error) { return } +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup3(from int, to int, flags int) (err error) { - _, _, e1 := Syscall(SYS_DUP3, uintptr(from), uintptr(to), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) return } +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -585,43 +841,59 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -630,23 +902,31 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { @@ -655,27 +935,35 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -683,16 +971,24 @@ func Fpathconf(fd int, name int) (val int, err error) { return } +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { @@ -701,71 +997,99 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall6(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0) + _, _, e1 := syscall_syscall6(libc_ftruncate_trampoline_addr, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) egid = int(r0) return } +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) gid = int(r0) return } +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) pgid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -773,34 +1097,50 @@ func Getpgid(pid int) (pgid int, err error) { return } +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) pgrp = int(r0) return } +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) pid = int(r0) return } +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) ppid = int(r0) return } +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) prio = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -808,20 +1148,28 @@ func Getpriority(which int, who int) (prio int, err error) { return } +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrtable() (rtable int, err error) { - r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) rtable = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -829,20 +1177,28 @@ func Getrtable() (rtable int, err error) { return } +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) sid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -850,46 +1206,66 @@ func Getsid(pid int) (sid int, err error) { return } +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Gettimeofday(tv *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0) + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) tainted = bool(r0 != 0) return } +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kill(pid int, signum syscall.Signal) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0) + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -897,6 +1273,10 @@ func Kqueue() (fd int, err error) { return } +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lchown(path string, uid int, gid int) (err error) { @@ -905,13 +1285,17 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Link(path string, link string) (err error) { @@ -925,13 +1309,17 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { @@ -945,23 +1333,31 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er if err != nil { return } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lstat(path string, stat *Stat_t) (err error) { @@ -970,13 +1366,17 @@ func Lstat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdir(path string, mode uint32) (err error) { @@ -985,13 +1385,17 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdirat(dirfd int, path string, mode uint32) (err error) { @@ -1000,13 +1404,17 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifo(path string, mode uint32) (err error) { @@ -1015,13 +1423,17 @@ func Mkfifo(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifoat(dirfd int, path string, mode uint32) (err error) { @@ -1030,13 +1442,17 @@ func Mkfifoat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknod(path string, mode uint32, dev int) (err error) { @@ -1045,13 +1461,17 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { @@ -1060,23 +1480,55 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Nanosleep(time *Timespec, leftover *Timespec) (err error) { - _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Open(path string, mode int, perm uint32) (fd int, err error) { @@ -1085,7 +1537,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1093,6 +1545,10 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { return } +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { @@ -1101,7 +1557,7 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1109,6 +1565,10 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { return } +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Pathconf(path string, name int) (val int, err error) { @@ -1117,7 +1577,7 @@ func Pathconf(path string, name int) (val int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1125,16 +1585,20 @@ func Pathconf(path string, name int) (val int, err error) { return } +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32)) + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1142,16 +1606,20 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32)) + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1159,6 +1627,10 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func read(fd int, p []byte) (n int, err error) { @@ -1168,7 +1640,7 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1176,6 +1648,10 @@ func read(fd int, p []byte) (n int, err error) { return } +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlink(path string, buf []byte) (n int, err error) { @@ -1190,7 +1666,7 @@ func Readlink(path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1198,6 +1674,10 @@ func Readlink(path string, buf []byte) (n int, err error) { return } +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { @@ -1212,7 +1692,7 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1220,6 +1700,10 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { return } +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rename(from string, to string) (err error) { @@ -1233,13 +1717,17 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Renameat(fromfd int, from string, tofd int, to string) (err error) { @@ -1253,13 +1741,17 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Revoke(path string) (err error) { @@ -1268,13 +1760,17 @@ func Revoke(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rmdir(path string) (err error) { @@ -1283,17 +1779,21 @@ func Rmdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(whence), 0) + r0, r1, e1 := syscall_syscall6(libc_lseek_trampoline_addr, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(whence), 0) newoffset = int64(int64(r1)<<32 | int64(r0)) if e1 != 0 { err = errnoErr(e1) @@ -1301,10 +1801,14 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return } +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1312,36 +1816,52 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err return } +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setegid(egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setlogin(name string) (err error) { @@ -1350,97 +1870,119 @@ func Setlogin(name string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) if e1 != 0 { err = errnoErr(e1) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +var libc_setresuid_trampoline_addr uintptr -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrtable(rtable int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) pid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1448,26 +1990,38 @@ func Setsid() (pid int, err error) { return } +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Stat(path string, stat *Stat_t) (err error) { @@ -1476,13 +2030,17 @@ func Stat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Statfs(path string, stat *Statfs_t) (err error) { @@ -1491,13 +2049,17 @@ func Statfs(path string, stat *Statfs_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlink(path string, link string) (err error) { @@ -1511,13 +2073,17 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { @@ -1531,23 +2097,31 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Truncate(path string, length int64) (err error) { @@ -1556,21 +2130,29 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0) + _, _, e1 := syscall_syscall6(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) oldmask = int(r0) return } +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlink(path string) (err error) { @@ -1579,13 +2161,17 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlinkat(dirfd int, path string, flags int) (err error) { @@ -1594,13 +2180,17 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unmount(path string, flags int) (err error) { @@ -1609,13 +2199,17 @@ func Unmount(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func write(fd int, p []byte) (n int, err error) { @@ -1625,7 +2219,7 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1633,10 +2227,14 @@ func write(fd int, p []byte) (n int, err error) { return } +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0) + r0, _, e1 := syscall_syscall9(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0) ret = uintptr(r0) if e1 != 0 { err = errnoErr(e1) @@ -1644,20 +2242,28 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( return } +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1665,28 +2271,53 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) if e1 != 0 { err = errnoErr(e1) } return } + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s new file mode 100644 index 0000000..b8ef95b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s @@ -0,0 +1,699 @@ +// go run mkasm.go openbsd arm +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgroups(SB) +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getgroups_trampoline_addr(SB)/4, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgroups(SB) +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setgroups_trampoline_addr(SB)/4, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_wait4(SB) +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $4 +DATA ·libc_wait4_trampoline_addr(SB)/4, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_accept(SB) +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $4 +DATA ·libc_accept_trampoline_addr(SB)/4, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_bind(SB) +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $4 +DATA ·libc_bind_trampoline_addr(SB)/4, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connect(SB) +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $4 +DATA ·libc_connect_trampoline_addr(SB)/4, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socket(SB) +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $4 +DATA ·libc_socket_trampoline_addr(SB)/4, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockopt(SB) +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getsockopt_trampoline_addr(SB)/4, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsockopt(SB) +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setsockopt_trampoline_addr(SB)/4, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpeername(SB) +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpeername_trampoline_addr(SB)/4, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockname(SB) +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getsockname_trampoline_addr(SB)/4, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shutdown(SB) +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_shutdown_trampoline_addr(SB)/4, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socketpair(SB) +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $4 +DATA ·libc_socketpair_trampoline_addr(SB)/4, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvfrom(SB) +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $4 +DATA ·libc_recvfrom_trampoline_addr(SB)/4, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendto(SB) +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sendto_trampoline_addr(SB)/4, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvmsg(SB) +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $4 +DATA ·libc_recvmsg_trampoline_addr(SB)/4, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendmsg(SB) +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sendmsg_trampoline_addr(SB)/4, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kevent(SB) +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $4 +DATA ·libc_kevent_trampoline_addr(SB)/4, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimes(SB) +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $4 +DATA ·libc_utimes_trampoline_addr(SB)/4, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_futimes(SB) +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $4 +DATA ·libc_futimes_trampoline_addr(SB)/4, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_poll(SB) +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $4 +DATA ·libc_poll_trampoline_addr(SB)/4, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_madvise(SB) +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $4 +DATA ·libc_madvise_trampoline_addr(SB)/4, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlock(SB) +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mlock_trampoline_addr(SB)/4, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlockall(SB) +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mlockall_trampoline_addr(SB)/4, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mprotect(SB) +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mprotect_trampoline_addr(SB)/4, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_msync(SB) +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $4 +DATA ·libc_msync_trampoline_addr(SB)/4, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlock(SB) +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $4 +DATA ·libc_munlock_trampoline_addr(SB)/4, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlockall(SB) +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $4 +DATA ·libc_munlockall_trampoline_addr(SB)/4, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pipe2(SB) +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pipe2_trampoline_addr(SB)/4, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getdents(SB) +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getdents_trampoline_addr(SB)/4, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getcwd_trampoline_addr(SB)/4, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresuid(SB) +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getresuid_trampoline_addr(SB)/4, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresgid(SB) +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getresgid_trampoline_addr(SB)/4, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ioctl(SB) +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_ioctl_trampoline_addr(SB)/4, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sysctl_trampoline_addr(SB)/4, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fcntl_trampoline_addr(SB)/4, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ppoll(SB) +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $4 +DATA ·libc_ppoll_trampoline_addr(SB)/4, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_access(SB) +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $4 +DATA ·libc_access_trampoline_addr(SB)/4, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_adjtime(SB) +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $4 +DATA ·libc_adjtime_trampoline_addr(SB)/4, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chdir(SB) +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chdir_trampoline_addr(SB)/4, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chflags(SB) +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chflags_trampoline_addr(SB)/4, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chmod(SB) +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chmod_trampoline_addr(SB)/4, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chown(SB) +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chown_trampoline_addr(SB)/4, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chroot(SB) +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $4 +DATA ·libc_chroot_trampoline_addr(SB)/4, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $4 +DATA ·libc_clock_gettime_trampoline_addr(SB)/4, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_close(SB) +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $4 +DATA ·libc_close_trampoline_addr(SB)/4, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup(SB) +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $4 +DATA ·libc_dup_trampoline_addr(SB)/4, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup2(SB) +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $4 +DATA ·libc_dup2_trampoline_addr(SB)/4, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup3(SB) +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $4 +DATA ·libc_dup3_trampoline_addr(SB)/4, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_exit(SB) +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $4 +DATA ·libc_exit_trampoline_addr(SB)/4, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_faccessat(SB) +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_faccessat_trampoline_addr(SB)/4, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchdir(SB) +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchdir_trampoline_addr(SB)/4, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchflags(SB) +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchflags_trampoline_addr(SB)/4, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmod(SB) +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchmod_trampoline_addr(SB)/4, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmodat(SB) +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchmodat_trampoline_addr(SB)/4, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchown(SB) +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchown_trampoline_addr(SB)/4, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchownat(SB) +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fchownat_trampoline_addr(SB)/4, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_flock(SB) +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $4 +DATA ·libc_flock_trampoline_addr(SB)/4, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fpathconf(SB) +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fpathconf_trampoline_addr(SB)/4, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstat(SB) +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fstat_trampoline_addr(SB)/4, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatat(SB) +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fstatat_trampoline_addr(SB)/4, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatfs(SB) +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fstatfs_trampoline_addr(SB)/4, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fsync(SB) +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fsync_trampoline_addr(SB)/4, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ftruncate(SB) +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $4 +DATA ·libc_ftruncate_trampoline_addr(SB)/4, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getegid(SB) +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getegid_trampoline_addr(SB)/4, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_geteuid(SB) +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_geteuid_trampoline_addr(SB)/4, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgid(SB) +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getgid_trampoline_addr(SB)/4, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgid(SB) +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpgid_trampoline_addr(SB)/4, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgrp(SB) +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpgrp_trampoline_addr(SB)/4, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpid(SB) +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpid_trampoline_addr(SB)/4, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getppid(SB) +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getppid_trampoline_addr(SB)/4, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpriority(SB) +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getpriority_trampoline_addr(SB)/4, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrlimit(SB) +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getrlimit_trampoline_addr(SB)/4, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrtable(SB) +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getrtable_trampoline_addr(SB)/4, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrusage(SB) +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getrusage_trampoline_addr(SB)/4, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsid(SB) +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getsid_trampoline_addr(SB)/4, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $4 +DATA ·libc_gettimeofday_trampoline_addr(SB)/4, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getuid(SB) +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getuid_trampoline_addr(SB)/4, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_issetugid(SB) +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_issetugid_trampoline_addr(SB)/4, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kill(SB) +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $4 +DATA ·libc_kill_trampoline_addr(SB)/4, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kqueue(SB) +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $4 +DATA ·libc_kqueue_trampoline_addr(SB)/4, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lchown(SB) +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $4 +DATA ·libc_lchown_trampoline_addr(SB)/4, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_link(SB) +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $4 +DATA ·libc_link_trampoline_addr(SB)/4, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_linkat(SB) +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_linkat_trampoline_addr(SB)/4, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_listen(SB) +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $4 +DATA ·libc_listen_trampoline_addr(SB)/4, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lstat(SB) +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_lstat_trampoline_addr(SB)/4, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdir(SB) +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkdir_trampoline_addr(SB)/4, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdirat(SB) +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkdirat_trampoline_addr(SB)/4, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifo(SB) +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkfifo_trampoline_addr(SB)/4, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifoat(SB) +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mkfifoat_trampoline_addr(SB)/4, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknod(SB) +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mknod_trampoline_addr(SB)/4, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknodat(SB) +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_nanosleep(SB) +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4 +DATA ·libc_nanosleep_trampoline_addr(SB)/4, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_open(SB) +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $4 +DATA ·libc_open_trampoline_addr(SB)/4, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_openat(SB) +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_openat_trampoline_addr(SB)/4, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pathconf(SB) +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pathconf_trampoline_addr(SB)/4, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pread(SB) +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pread_trampoline_addr(SB)/4, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwrite(SB) +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pwrite_trampoline_addr(SB)/4, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_read(SB) +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $4 +DATA ·libc_read_trampoline_addr(SB)/4, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlink(SB) +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $4 +DATA ·libc_readlink_trampoline_addr(SB)/4, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlinkat(SB) +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_readlinkat_trampoline_addr(SB)/4, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rename(SB) +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $4 +DATA ·libc_rename_trampoline_addr(SB)/4, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameat(SB) +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_renameat_trampoline_addr(SB)/4, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_revoke(SB) +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $4 +DATA ·libc_revoke_trampoline_addr(SB)/4, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rmdir(SB) +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $4 +DATA ·libc_rmdir_trampoline_addr(SB)/4, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lseek(SB) +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $4 +DATA ·libc_lseek_trampoline_addr(SB)/4, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_select(SB) +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $4 +DATA ·libc_select_trampoline_addr(SB)/4, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setegid(SB) +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setegid_trampoline_addr(SB)/4, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_seteuid(SB) +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_seteuid_trampoline_addr(SB)/4, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgid(SB) +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setgid_trampoline_addr(SB)/4, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setlogin(SB) +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setlogin_trampoline_addr(SB)/4, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpgid(SB) +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setpgid_trampoline_addr(SB)/4, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpriority(SB) +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setpriority_trampoline_addr(SB)/4, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setregid(SB) +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setregid_trampoline_addr(SB)/4, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setreuid(SB) +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setreuid_trampoline_addr(SB)/4, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresgid(SB) +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setresgid_trampoline_addr(SB)/4, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresuid(SB) +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setresuid_trampoline_addr(SB)/4, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setrtable(SB) +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setrtable_trampoline_addr(SB)/4, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsid(SB) +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setsid_trampoline_addr(SB)/4, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_settimeofday(SB) +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $4 +DATA ·libc_settimeofday_trampoline_addr(SB)/4, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setuid(SB) +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $4 +DATA ·libc_setuid_trampoline_addr(SB)/4, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_stat(SB) +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_stat_trampoline_addr(SB)/4, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $4 +DATA ·libc_statfs_trampoline_addr(SB)/4, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlink(SB) +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $4 +DATA ·libc_symlink_trampoline_addr(SB)/4, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlinkat(SB) +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_symlinkat_trampoline_addr(SB)/4, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sync(SB) +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $4 +DATA ·libc_sync_trampoline_addr(SB)/4, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_truncate(SB) +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $4 +DATA ·libc_truncate_trampoline_addr(SB)/4, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_umask(SB) +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $4 +DATA ·libc_umask_trampoline_addr(SB)/4, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlink(SB) +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unlink_trampoline_addr(SB)/4, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlinkat(SB) +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unlinkat_trampoline_addr(SB)/4, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unmount(SB) +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unmount_trampoline_addr(SB)/4, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_write(SB) +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $4 +DATA ·libc_write_trampoline_addr(SB)/4, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mmap(SB) +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mmap_trampoline_addr(SB)/4, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munmap(SB) +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $4 +DATA ·libc_munmap_trampoline_addr(SB)/4, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getfsstat_trampoline_addr(SB)/4, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index 8facd69..2ffdf86 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -1,7 +1,7 @@ -// go run mksyscall.go -openbsd -tags openbsd,arm64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_arm64.go +// go run mksyscall.go -openbsd -libc -tags openbsd,arm64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_arm64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build openbsd,arm64 +//go:build openbsd && arm64 package unix @@ -15,7 +15,7 @@ var _ syscall.Errno // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(ngid int, gid *_Gid_t) (n int, err error) { - r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -23,20 +23,28 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { return } +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(ngid int, gid *_Gid_t) (err error) { - _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { - r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -44,10 +52,14 @@ func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err return } +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -55,30 +67,42 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { return } +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen)) + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -86,66 +110,94 @@ func socket(domain int, typ int, proto int) (fd int, err error) { return } +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(s int, how int) (err error) { - _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { @@ -155,7 +207,7 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -163,6 +215,10 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl return } +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { @@ -172,17 +228,21 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -190,10 +250,14 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -201,10 +265,14 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { return } +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { - r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -212,6 +280,10 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne return } +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func utimes(path string, timeval *[2]Timeval) (err error) { @@ -220,27 +292,35 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func futimes(fd int, timeval *[2]Timeval) (err error) { - _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -248,6 +328,10 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { return } +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Madvise(b []byte, behav int) (err error) { @@ -257,13 +341,17 @@ func Madvise(b []byte, behav int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlock(b []byte) (err error) { @@ -273,23 +361,31 @@ func Mlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mlockall(flags int) (err error) { - _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mprotect(b []byte, prot int) (err error) { @@ -299,13 +395,17 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Msync(b []byte, flags int) (err error) { @@ -315,13 +415,17 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlock(b []byte) (err error) { @@ -331,33 +435,45 @@ func Munlock(b []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Munlockall() (err error) { - _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getdents(fd int, buf []byte) (n int, err error) { @@ -367,7 +483,7 @@ func Getdents(fd int, buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -375,6 +491,10 @@ func Getdents(fd int, buf []byte) (n int, err error) { return } +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getcwd(buf []byte) (n int, err error) { @@ -384,7 +504,7 @@ func Getcwd(buf []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -392,10 +512,50 @@ func Getcwd(buf []byte) (n int, err error) { return } +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { err = errnoErr(e1) } @@ -411,7 +571,37 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) if e1 != 0 { err = errnoErr(e1) } @@ -421,7 +611,7 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { - r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -429,6 +619,10 @@ func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, return } +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Access(path string, mode uint32) (err error) { @@ -437,23 +631,31 @@ func Access(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { - _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chdir(path string) (err error) { @@ -462,13 +664,17 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chflags(path string, flags int) (err error) { @@ -477,13 +683,17 @@ func Chflags(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chmod(path string, mode uint32) (err error) { @@ -492,13 +702,17 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chown(path string, uid int, gid int) (err error) { @@ -507,13 +721,17 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Chroot(path string) (err error) { @@ -522,27 +740,49 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Close(fd int) (err error) { - _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup(fd int) (nfd int, err error) { - r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) nfd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -550,33 +790,49 @@ func Dup(fd int) (nfd int, err error) { return } +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(from int, to int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup3(from int, to int, flags int) (err error) { - _, _, e1 := Syscall(SYS_DUP3, uintptr(from), uintptr(to), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - Syscall(SYS_EXIT, uintptr(code), 0, 0) + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) return } +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -585,43 +841,59 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchflags(fd int, flags int) (err error) { - _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { @@ -630,23 +902,31 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { @@ -655,27 +935,35 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Flock(fd int, how int) (err error) { - _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fpathconf(fd int, name int) (val int, err error) { - r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -683,16 +971,24 @@ func Fpathconf(fd int, name int) (val int, err error) { return } +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstat(fd int, stat *Stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { @@ -701,71 +997,99 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fstatfs(fd int, stat *Statfs_t) (err error) { - _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length)) + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getegid() (egid int) { - r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) egid = int(r0) return } +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Geteuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getgid() (gid int) { - r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) gid = int(r0) return } +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) pgid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -773,34 +1097,50 @@ func Getpgid(pid int) (pgid int, err error) { return } +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgrp() (pgrp int) { - r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) pgrp = int(r0) return } +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) pid = int(r0) return } +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (ppid int) { - r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) ppid = int(r0) return } +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) prio = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -808,20 +1148,28 @@ func Getpriority(which int, who int) (prio int, err error) { return } +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrtable() (rtable int, err error) { - r0, _, e1 := RawSyscall(SYS_GETRTABLE, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) rtable = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -829,20 +1177,28 @@ func Getrtable() (rtable int, err error) { return } +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrusage(who int, rusage *Rusage) (err error) { - _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getsid(pid int) (sid int, err error) { - r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) sid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -850,46 +1206,66 @@ func Getsid(pid int) (sid int, err error) { return } +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Gettimeofday(tv *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getuid() (uid int) { - r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) uid = int(r0) return } +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Issetugid() (tainted bool) { - r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0) + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) tainted = bool(r0 != 0) return } +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kill(pid int, signum syscall.Signal) (err error) { - _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0) + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kqueue() (fd int, err error) { - r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -897,6 +1273,10 @@ func Kqueue() (fd int, err error) { return } +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lchown(path string, uid int, gid int) (err error) { @@ -905,13 +1285,17 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Link(path string, link string) (err error) { @@ -925,13 +1309,17 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { @@ -945,23 +1333,31 @@ func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err er if err != nil { return } - _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Lstat(path string, stat *Stat_t) (err error) { @@ -970,13 +1366,17 @@ func Lstat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdir(path string, mode uint32) (err error) { @@ -985,13 +1385,17 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkdirat(dirfd int, path string, mode uint32) (err error) { @@ -1000,13 +1404,17 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifo(path string, mode uint32) (err error) { @@ -1015,13 +1423,17 @@ func Mkfifo(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mkfifoat(dirfd int, path string, mode uint32) (err error) { @@ -1030,13 +1442,17 @@ func Mkfifoat(dirfd int, path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknod(path string, mode uint32, dev int) (err error) { @@ -1045,13 +1461,17 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { @@ -1060,23 +1480,55 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Nanosleep(time *Timespec, leftover *Timespec) (err error) { - _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Open(path string, mode int, perm uint32) (fd int, err error) { @@ -1085,7 +1537,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1093,6 +1545,10 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { return } +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { @@ -1101,7 +1557,7 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) fd = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1109,6 +1565,10 @@ func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { return } +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Pathconf(path string, name int) (val int, err error) { @@ -1117,7 +1577,7 @@ func Pathconf(path string, name int) (val int, err error) { if err != nil { return } - r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) val = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1125,16 +1585,20 @@ func Pathconf(path string, name int) (val int, err error) { return } +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0) + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1142,16 +1606,20 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0) + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1159,6 +1627,10 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { return } +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func read(fd int, p []byte) (n int, err error) { @@ -1168,7 +1640,7 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1176,6 +1648,10 @@ func read(fd int, p []byte) (n int, err error) { return } +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlink(path string, buf []byte) (n int, err error) { @@ -1190,7 +1666,7 @@ func Readlink(path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1198,6 +1674,10 @@ func Readlink(path string, buf []byte) (n int, err error) { return } +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { @@ -1212,7 +1692,7 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { } else { _p1 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1220,6 +1700,10 @@ func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { return } +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rename(from string, to string) (err error) { @@ -1233,13 +1717,17 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Renameat(fromfd int, from string, tofd int, to string) (err error) { @@ -1253,13 +1741,17 @@ func Renameat(fromfd int, from string, tofd int, to string) (err error) { if err != nil { return } - _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Revoke(path string) (err error) { @@ -1268,13 +1760,17 @@ func Revoke(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rmdir(path string) (err error) { @@ -1283,17 +1779,21 @@ func Rmdir(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { - r0, _, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(whence), 0, 0) + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) newoffset = int64(r0) if e1 != 0 { err = errnoErr(e1) @@ -1301,10 +1801,14 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return } +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1312,36 +1816,52 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err return } +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setegid(egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seteuid(euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(gid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setlogin(name string) (err error) { @@ -1350,97 +1870,119 @@ func Setlogin(name string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresgid(rgid int, egid int, sgid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)) + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setresuid(ruid int, euid int, suid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)) + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) if e1 != 0 { err = errnoErr(e1) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +var libc_setresuid_trampoline_addr uintptr -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrtable(rtable int) (err error) { - _, _, e1 := RawSyscall(SYS_SETRTABLE, uintptr(rtable), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) pid = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1448,26 +1990,38 @@ func Setsid() (pid int, err error) { return } +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Settimeofday(tp *Timeval) (err error) { - _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Stat(path string, stat *Stat_t) (err error) { @@ -1476,13 +2030,17 @@ func Stat(path string, stat *Stat_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Statfs(path string, stat *Statfs_t) (err error) { @@ -1491,13 +2049,17 @@ func Statfs(path string, stat *Statfs_t) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlink(path string, link string) (err error) { @@ -1511,13 +2073,17 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { @@ -1531,23 +2097,31 @@ func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) if e1 != 0 { err = errnoErr(e1) } return } +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() (err error) { - _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Truncate(path string, length int64) (err error) { @@ -1556,21 +2130,29 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length)) + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(newmask int) (oldmask int) { - r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) oldmask = int(r0) return } +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlink(path string) (err error) { @@ -1579,13 +2161,17 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unlinkat(dirfd int, path string, flags int) (err error) { @@ -1594,13 +2180,17 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Unmount(path string, flags int) (err error) { @@ -1609,13 +2199,17 @@ func Unmount(path string, flags int) (err error) { if err != nil { return } - _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func write(fd int, p []byte) (n int, err error) { @@ -1625,7 +2219,7 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1633,10 +2227,14 @@ func write(fd int, p []byte) (n int, err error) { return } +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), 0, 0) + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) ret = uintptr(r0) if e1 != 0 { err = errnoErr(e1) @@ -1644,20 +2242,28 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( return } +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readlen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) n = int(r0) if e1 != 0 { err = errnoErr(e1) @@ -1665,28 +2271,53 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) { return } +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func writelen(fd int, buf *byte, nbuf int) (n int, err error) { - r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) - n = int(r0) +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) if e1 != 0 { err = errnoErr(e1) } return } +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) } - _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) if e1 != 0 { err = errnoErr(e1) } return } + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s new file mode 100644 index 0000000..2af3b5c --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s @@ -0,0 +1,699 @@ +// go run mkasm.go openbsd arm64 +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgroups(SB) +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgroups(SB) +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_wait4(SB) +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_accept(SB) +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_bind(SB) +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connect(SB) +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socket(SB) +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockopt(SB) +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsockopt(SB) +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpeername(SB) +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockname(SB) +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shutdown(SB) +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socketpair(SB) +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvfrom(SB) +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendto(SB) +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvmsg(SB) +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendmsg(SB) +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kevent(SB) +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimes(SB) +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_futimes(SB) +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_poll(SB) +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_madvise(SB) +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlock(SB) +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlockall(SB) +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mprotect(SB) +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_msync(SB) +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlock(SB) +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlockall(SB) +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pipe2(SB) +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe2_trampoline_addr(SB)/8, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getdents(SB) +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdents_trampoline_addr(SB)/8, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresuid(SB) +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresgid(SB) +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ioctl(SB) +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ppoll(SB) +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ppoll_trampoline_addr(SB)/8, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_access(SB) +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_adjtime(SB) +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chdir(SB) +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chflags(SB) +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chmod(SB) +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chown(SB) +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chroot(SB) +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_close(SB) +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup(SB) +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup2(SB) +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup3(SB) +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup3_trampoline_addr(SB)/8, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_exit(SB) +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_faccessat(SB) +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchdir(SB) +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchflags(SB) +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmod(SB) +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmodat(SB) +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchown(SB) +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchownat(SB) +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_flock(SB) +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fpathconf(SB) +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstat(SB) +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat_trampoline_addr(SB)/8, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatat(SB) +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat_trampoline_addr(SB)/8, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatfs(SB) +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs_trampoline_addr(SB)/8, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fsync(SB) +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ftruncate(SB) +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getegid(SB) +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_geteuid(SB) +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgid(SB) +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgid(SB) +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgrp(SB) +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpid(SB) +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getppid(SB) +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpriority(SB) +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrlimit(SB) +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrtable(SB) +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrtable_trampoline_addr(SB)/8, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrusage(SB) +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsid(SB) +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getuid(SB) +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_issetugid(SB) +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kill(SB) +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kqueue(SB) +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lchown(SB) +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_link(SB) +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_linkat(SB) +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_listen(SB) +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lstat(SB) +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat_trampoline_addr(SB)/8, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdir(SB) +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdirat(SB) +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifo(SB) +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifoat(SB) +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifoat_trampoline_addr(SB)/8, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknod(SB) +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknodat(SB) +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_nanosleep(SB) +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 +DATA ·libc_nanosleep_trampoline_addr(SB)/8, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_open(SB) +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_openat(SB) +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pathconf(SB) +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pread(SB) +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwrite(SB) +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_read(SB) +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlink(SB) +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlinkat(SB) +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rename(SB) +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameat(SB) +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_revoke(SB) +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rmdir(SB) +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lseek(SB) +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_select(SB) +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setegid(SB) +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_seteuid(SB) +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgid(SB) +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setlogin(SB) +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpgid(SB) +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpriority(SB) +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setregid(SB) +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setreuid(SB) +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresgid(SB) +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresgid_trampoline_addr(SB)/8, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresuid(SB) +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setrtable(SB) +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setrtable_trampoline_addr(SB)/8, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsid(SB) +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_settimeofday(SB) +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setuid(SB) +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_stat(SB) +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat_trampoline_addr(SB)/8, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs_trampoline_addr(SB)/8, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlink(SB) +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlinkat(SB) +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sync(SB) +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_truncate(SB) +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_umask(SB) +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlink(SB) +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlinkat(SB) +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unmount(SB) +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_write(SB) +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mmap(SB) +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munmap(SB) +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go new file mode 100644 index 0000000..1da08d5 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go @@ -0,0 +1,2323 @@ +// go run mksyscall.go -openbsd -libc -tags openbsd,mips64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_mips64.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build openbsd && mips64 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getgroups(ngid int, gid *_Gid_t) (n int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setgroups(ngid int, gid *_Gid_t) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + wpid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socket(domain int, typ int, proto int) (fd int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Shutdown(s int, how int) (err error) { + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimes(path string, timeval *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func futimes(fd int, timeval *[2]Timeval) (err error) { + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Madvise(b []byte, behav int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlockall(flags int) (err error) { + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mprotect(b []byte, prot int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Msync(b []byte, flags int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlockall() (err error) { + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getdents(fd int, buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Access(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chflags(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chmod(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(fd int) (nfd int, err error) { + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) + nfd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup2(from int, to int) (err error) { + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup3(from int, to int, flags int) (err error) { + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Exit(code int) { + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) + return +} + +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchdir(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchflags(fd int, flags int) (err error) { + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmod(fd int, mode uint32) (err error) { + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flock(fd int, how int) (err error) { + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fpathconf(fd int, name int) (val int, err error) { + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, stat *Stat_t) (err error) { + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatfs(fd int, stat *Statfs_t) (err error) { + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsync(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) + egid = int(r0) + return +} + +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (uid int) { + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) + uid = int(r0) + return +} + +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) + gid = int(r0) + return +} + +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgid(pid int) (pgid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) + pgid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgrp() (pgrp int) { + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) + pgrp = int(r0) + return +} + +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpid() (pid int) { + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) + pid = int(r0) + return +} + +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getppid() (ppid int) { + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) + ppid = int(r0) + return +} + +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpriority(which int, who int) (prio int, err error) { + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) + prio = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrlimit(which int, lim *Rlimit) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrtable() (rtable int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) + rtable = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrusage(who int, rusage *Rusage) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) + sid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) + uid = int(r0) + return +} + +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Issetugid() (tainted bool) { + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) + tainted = bool(r0 != 0) + return +} + +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kill(pid int, signum syscall.Signal) (err error) { + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kqueue() (fd int, err error) { + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Link(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, backlog int) (err error) { + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lstat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdir(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifo(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknod(path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Nanosleep(time *Timespec, leftover *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Open(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pathconf(path string, name int) (val int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func read(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rename(from string, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Revoke(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rmdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) + newoffset = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setegid(egid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setgid(gid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setlogin(name string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpgid(pid int, pgid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpriority(which int, who int, prio int) (err error) { + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setresgid(rgid int, egid int, sgid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setresuid(ruid int, euid int, suid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setrtable(rtable int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setsid() (pid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) + pid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Settimeofday(tp *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setuid(uid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Stat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Statfs(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlink(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Sync() (err error) { + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Umask(newmask int) (oldmask int) { + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) + oldmask = int(r0) + return +} + +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlink(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unmount(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func write(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func munmap(addr uintptr, length uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s new file mode 100644 index 0000000..b7a2513 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s @@ -0,0 +1,699 @@ +// go run mkasm.go openbsd mips64 +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgroups(SB) +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgroups(SB) +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_wait4(SB) +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_accept(SB) +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_bind(SB) +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connect(SB) +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socket(SB) +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockopt(SB) +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsockopt(SB) +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpeername(SB) +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockname(SB) +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shutdown(SB) +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socketpair(SB) +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvfrom(SB) +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendto(SB) +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvmsg(SB) +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendmsg(SB) +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kevent(SB) +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimes(SB) +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_futimes(SB) +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_poll(SB) +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_madvise(SB) +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlock(SB) +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlockall(SB) +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mprotect(SB) +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_msync(SB) +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlock(SB) +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlockall(SB) +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pipe2(SB) +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe2_trampoline_addr(SB)/8, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getdents(SB) +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdents_trampoline_addr(SB)/8, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresuid(SB) +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresgid(SB) +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ioctl(SB) +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ppoll(SB) +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ppoll_trampoline_addr(SB)/8, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_access(SB) +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_adjtime(SB) +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chdir(SB) +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chflags(SB) +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chmod(SB) +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chown(SB) +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chroot(SB) +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_close(SB) +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup(SB) +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup2(SB) +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup3(SB) +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup3_trampoline_addr(SB)/8, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_exit(SB) +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_faccessat(SB) +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchdir(SB) +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchflags(SB) +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmod(SB) +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmodat(SB) +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchown(SB) +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchownat(SB) +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_flock(SB) +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fpathconf(SB) +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstat(SB) +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat_trampoline_addr(SB)/8, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatat(SB) +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat_trampoline_addr(SB)/8, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatfs(SB) +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs_trampoline_addr(SB)/8, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fsync(SB) +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ftruncate(SB) +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getegid(SB) +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_geteuid(SB) +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgid(SB) +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgid(SB) +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgrp(SB) +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpid(SB) +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getppid(SB) +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpriority(SB) +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrlimit(SB) +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrtable(SB) +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrtable_trampoline_addr(SB)/8, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrusage(SB) +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsid(SB) +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getuid(SB) +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_issetugid(SB) +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kill(SB) +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kqueue(SB) +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lchown(SB) +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_link(SB) +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_linkat(SB) +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_listen(SB) +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lstat(SB) +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat_trampoline_addr(SB)/8, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdir(SB) +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdirat(SB) +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifo(SB) +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifoat(SB) +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifoat_trampoline_addr(SB)/8, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknod(SB) +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknodat(SB) +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_nanosleep(SB) +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 +DATA ·libc_nanosleep_trampoline_addr(SB)/8, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_open(SB) +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_openat(SB) +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pathconf(SB) +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pread(SB) +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwrite(SB) +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_read(SB) +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlink(SB) +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlinkat(SB) +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rename(SB) +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameat(SB) +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_revoke(SB) +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rmdir(SB) +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lseek(SB) +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_select(SB) +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setegid(SB) +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_seteuid(SB) +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgid(SB) +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setlogin(SB) +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpgid(SB) +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpriority(SB) +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setregid(SB) +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setreuid(SB) +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresgid(SB) +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresgid_trampoline_addr(SB)/8, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresuid(SB) +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setrtable(SB) +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setrtable_trampoline_addr(SB)/8, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsid(SB) +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_settimeofday(SB) +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setuid(SB) +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_stat(SB) +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat_trampoline_addr(SB)/8, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs_trampoline_addr(SB)/8, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlink(SB) +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlinkat(SB) +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sync(SB) +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_truncate(SB) +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_umask(SB) +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlink(SB) +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlinkat(SB) +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unmount(SB) +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_write(SB) +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mmap(SB) +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munmap(SB) +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go new file mode 100644 index 0000000..6e85b0a --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go @@ -0,0 +1,2323 @@ +// go run mksyscall.go -openbsd -libc -tags openbsd,ppc64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_ppc64.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build openbsd && ppc64 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getgroups(ngid int, gid *_Gid_t) (n int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setgroups(ngid int, gid *_Gid_t) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + wpid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socket(domain int, typ int, proto int) (fd int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Shutdown(s int, how int) (err error) { + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimes(path string, timeval *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func futimes(fd int, timeval *[2]Timeval) (err error) { + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Madvise(b []byte, behav int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlockall(flags int) (err error) { + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mprotect(b []byte, prot int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Msync(b []byte, flags int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlockall() (err error) { + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getdents(fd int, buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Access(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chflags(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chmod(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(fd int) (nfd int, err error) { + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) + nfd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup2(from int, to int) (err error) { + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup3(from int, to int, flags int) (err error) { + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Exit(code int) { + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) + return +} + +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchdir(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchflags(fd int, flags int) (err error) { + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmod(fd int, mode uint32) (err error) { + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flock(fd int, how int) (err error) { + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fpathconf(fd int, name int) (val int, err error) { + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, stat *Stat_t) (err error) { + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatfs(fd int, stat *Statfs_t) (err error) { + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsync(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) + egid = int(r0) + return +} + +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (uid int) { + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) + uid = int(r0) + return +} + +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) + gid = int(r0) + return +} + +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgid(pid int) (pgid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) + pgid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgrp() (pgrp int) { + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) + pgrp = int(r0) + return +} + +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpid() (pid int) { + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) + pid = int(r0) + return +} + +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getppid() (ppid int) { + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) + ppid = int(r0) + return +} + +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpriority(which int, who int) (prio int, err error) { + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) + prio = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrlimit(which int, lim *Rlimit) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrtable() (rtable int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) + rtable = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrusage(who int, rusage *Rusage) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) + sid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) + uid = int(r0) + return +} + +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Issetugid() (tainted bool) { + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) + tainted = bool(r0 != 0) + return +} + +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kill(pid int, signum syscall.Signal) (err error) { + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kqueue() (fd int, err error) { + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Link(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, backlog int) (err error) { + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lstat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdir(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifo(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknod(path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Nanosleep(time *Timespec, leftover *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Open(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pathconf(path string, name int) (val int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func read(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rename(from string, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Revoke(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rmdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) + newoffset = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setegid(egid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setgid(gid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setlogin(name string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpgid(pid int, pgid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpriority(which int, who int, prio int) (err error) { + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setresgid(rgid int, egid int, sgid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setresuid(ruid int, euid int, suid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setrtable(rtable int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setsid() (pid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) + pid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Settimeofday(tp *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setuid(uid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Stat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Statfs(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlink(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Sync() (err error) { + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Umask(newmask int) (oldmask int) { + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) + oldmask = int(r0) + return +} + +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlink(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unmount(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func write(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func munmap(addr uintptr, length uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s new file mode 100644 index 0000000..f15dadf --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s @@ -0,0 +1,838 @@ +// go run mkasm.go openbsd ppc64 +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getgroups(SB) + RET +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setgroups(SB) + RET +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_wait4(SB) + RET +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_accept(SB) + RET +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_bind(SB) + RET +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_connect(SB) + RET +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_socket(SB) + RET +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getsockopt(SB) + RET +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setsockopt(SB) + RET +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getpeername(SB) + RET +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getsockname(SB) + RET +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_shutdown(SB) + RET +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_socketpair(SB) + RET +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_recvfrom(SB) + RET +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_sendto(SB) + RET +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_recvmsg(SB) + RET +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_sendmsg(SB) + RET +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_kevent(SB) + RET +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_utimes(SB) + RET +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_futimes(SB) + RET +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_poll(SB) + RET +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_madvise(SB) + RET +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mlock(SB) + RET +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mlockall(SB) + RET +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mprotect(SB) + RET +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_msync(SB) + RET +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_munlock(SB) + RET +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_munlockall(SB) + RET +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pipe2(SB) + RET +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe2_trampoline_addr(SB)/8, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getdents(SB) + RET +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdents_trampoline_addr(SB)/8, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getcwd(SB) + RET +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getresuid(SB) + RET +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getresgid(SB) + RET +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_ioctl(SB) + RET +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_sysctl(SB) + RET +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fcntl(SB) + RET +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_ppoll(SB) + RET +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ppoll_trampoline_addr(SB)/8, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_access(SB) + RET +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_adjtime(SB) + RET +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_chdir(SB) + RET +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_chflags(SB) + RET +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_chmod(SB) + RET +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_chown(SB) + RET +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_chroot(SB) + RET +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_clock_gettime(SB) + RET +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_close(SB) + RET +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_dup(SB) + RET +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_dup2(SB) + RET +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_dup3(SB) + RET +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup3_trampoline_addr(SB)/8, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_exit(SB) + RET +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_faccessat(SB) + RET +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fchdir(SB) + RET +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fchflags(SB) + RET +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fchmod(SB) + RET +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fchmodat(SB) + RET +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fchown(SB) + RET +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fchownat(SB) + RET +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_flock(SB) + RET +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fpathconf(SB) + RET +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fstat(SB) + RET +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat_trampoline_addr(SB)/8, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fstatat(SB) + RET +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat_trampoline_addr(SB)/8, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fstatfs(SB) + RET +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs_trampoline_addr(SB)/8, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fsync(SB) + RET +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_ftruncate(SB) + RET +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getegid(SB) + RET +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_geteuid(SB) + RET +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getgid(SB) + RET +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getpgid(SB) + RET +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getpgrp(SB) + RET +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getpid(SB) + RET +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getppid(SB) + RET +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getpriority(SB) + RET +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getrlimit(SB) + RET +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getrtable(SB) + RET +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrtable_trampoline_addr(SB)/8, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getrusage(SB) + RET +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getsid(SB) + RET +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_gettimeofday(SB) + RET +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getuid(SB) + RET +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_issetugid(SB) + RET +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_kill(SB) + RET +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_kqueue(SB) + RET +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_lchown(SB) + RET +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_link(SB) + RET +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_linkat(SB) + RET +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_listen(SB) + RET +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_lstat(SB) + RET +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat_trampoline_addr(SB)/8, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mkdir(SB) + RET +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mkdirat(SB) + RET +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mkfifo(SB) + RET +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mkfifoat(SB) + RET +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifoat_trampoline_addr(SB)/8, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mknod(SB) + RET +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mknodat(SB) + RET +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mount(SB) + RET +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_nanosleep(SB) + RET +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 +DATA ·libc_nanosleep_trampoline_addr(SB)/8, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_open(SB) + RET +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_openat(SB) + RET +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pathconf(SB) + RET +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pread(SB) + RET +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pwrite(SB) + RET +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_read(SB) + RET +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_readlink(SB) + RET +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_readlinkat(SB) + RET +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_rename(SB) + RET +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_renameat(SB) + RET +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_revoke(SB) + RET +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_rmdir(SB) + RET +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_lseek(SB) + RET +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_select(SB) + RET +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setegid(SB) + RET +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_seteuid(SB) + RET +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setgid(SB) + RET +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setlogin(SB) + RET +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setpgid(SB) + RET +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setpriority(SB) + RET +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setregid(SB) + RET +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setreuid(SB) + RET +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setresgid(SB) + RET +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresgid_trampoline_addr(SB)/8, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setresuid(SB) + RET +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setrtable(SB) + RET +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setrtable_trampoline_addr(SB)/8, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setsid(SB) + RET +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_settimeofday(SB) + RET +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_setuid(SB) + RET +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_stat(SB) + RET +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat_trampoline_addr(SB)/8, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_statfs(SB) + RET +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs_trampoline_addr(SB)/8, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_symlink(SB) + RET +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_symlinkat(SB) + RET +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_sync(SB) + RET +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_truncate(SB) + RET +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_umask(SB) + RET +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_unlink(SB) + RET +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_unlinkat(SB) + RET +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_unmount(SB) + RET +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_write(SB) + RET +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mmap(SB) + RET +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_munmap(SB) + RET +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getfsstat(SB) + RET +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_utimensat(SB) + RET +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pledge(SB) + RET +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_unveil(SB) + RET +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go new file mode 100644 index 0000000..28b487d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go @@ -0,0 +1,2323 @@ +// go run mksyscall.go -openbsd -libc -tags openbsd,riscv64 syscall_bsd.go syscall_openbsd.go syscall_openbsd_riscv64.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build openbsd && riscv64 + +package unix + +import ( + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getgroups(ngid int, gid *_Gid_t) (n int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setgroups(ngid int, gid *_Gid_t) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setgroups_trampoline_addr, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setgroups_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) { + r0, _, e1 := syscall_syscall6(libc_wait4_trampoline_addr, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + wpid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_wait4_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { + r0, _, e1 := syscall_syscall(libc_accept_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_accept_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_accept accept "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := syscall_syscall(libc_bind_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_bind_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_bind bind "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + _, _, e1 := syscall_syscall(libc_connect_trampoline_addr, uintptr(s), uintptr(addr), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connect connect "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socket(domain int, typ int, proto int) (fd int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_socket_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_socket_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socket socket "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { + _, _, e1 := syscall_syscall6(libc_getsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockopt getsockopt "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { + _, _, e1 := syscall_syscall6(libc_setsockopt_trampoline_addr, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setsockopt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsockopt setsockopt "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getpeername_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpeername_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpeername getpeername "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getsockname_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsockname_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsockname getsockname "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Shutdown(s int, how int) (err error) { + _, _, e1 := syscall_syscall(libc_shutdown_trampoline_addr, uintptr(s), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shutdown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shutdown shutdown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { + _, _, e1 := syscall_rawSyscall6(libc_socketpair_trampoline_addr, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_socketpair_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_socketpair socketpair "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_recvfrom_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_recvfrom_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvfrom recvfrom "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_sendto_trampoline_addr, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sendto_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendto sendto "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_recvmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_recvmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_recvmsg recvmsg "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_sendmsg_trampoline_addr, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sendmsg_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sendmsg sendmsg "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_kevent_trampoline_addr, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kevent_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kevent kevent "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimes(path string, timeval *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_utimes_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_utimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimes utimes "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func futimes(fd int, timeval *[2]Timeval) (err error) { + _, _, e1 := syscall_syscall(libc_futimes_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_futimes_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_futimes futimes "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_poll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_poll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_poll poll "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Madvise(b []byte, behav int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_madvise_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_madvise_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_madvise madvise "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_mlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlock mlock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlockall(flags int) (err error) { + _, _, e1 := syscall_syscall(libc_mlockall_trampoline_addr, uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mlockall mlockall "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mprotect(b []byte, prot int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_mprotect_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mprotect_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mprotect mprotect "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Msync(b []byte, flags int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_msync_trampoline_addr, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_msync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_msync msync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall(libc_munlock_trampoline_addr, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munlock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlock munlock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlockall() (err error) { + _, _, e1 := syscall_syscall(libc_munlockall_trampoline_addr, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munlockall_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munlockall munlockall "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_pipe2_trampoline_addr, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pipe2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getdents(fd int, buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getdents_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getdents_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getdents getdents "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_getcwd_trampoline_addr, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getcwd_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getcwd getcwd "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) { + syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid))) + return +} + +var libc_getresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresuid getresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) { + syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid))) + return +} + +var libc_getresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getresgid getresgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ioctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sysctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ppoll_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ppoll ppoll "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Access(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_access_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_access_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_access access "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { + _, _, e1 := syscall_syscall(libc_adjtime_trampoline_addr, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_adjtime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_adjtime adjtime "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chdir chdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chflags(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chflags_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chflags chflags "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chmod(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chmod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chmod chmod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chown chown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_chroot_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_chroot_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_chroot chroot "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_clock_gettime_trampoline_addr, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_clock_gettime_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_close_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_close_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_close close "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(fd int) (nfd int, err error) { + r0, _, e1 := syscall_syscall(libc_dup_trampoline_addr, uintptr(fd), 0, 0) + nfd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup dup "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup2(from int, to int) (err error) { + _, _, e1 := syscall_syscall(libc_dup2_trampoline_addr, uintptr(from), uintptr(to), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup2_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup2 dup2 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup3(from int, to int, flags int) (err error) { + _, _, e1 := syscall_syscall(libc_dup3_trampoline_addr, uintptr(from), uintptr(to), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_dup3_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_dup3 dup3 "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Exit(code int) { + syscall_syscall(libc_exit_trampoline_addr, uintptr(code), 0, 0) + return +} + +var libc_exit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_exit exit "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_faccessat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_faccessat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_faccessat faccessat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchdir(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_fchdir_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchdir fchdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchflags(fd int, flags int) (err error) { + _, _, e1 := syscall_syscall(libc_fchflags_trampoline_addr, uintptr(fd), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchflags_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchflags fchflags "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmod(fd int, mode uint32) (err error) { + _, _, e1 := syscall_syscall(libc_fchmod_trampoline_addr, uintptr(fd), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchmod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmod fchmod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fchmodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchmodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + _, _, e1 := syscall_syscall(libc_fchown_trampoline_addr, uintptr(fd), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchown fchown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fchownat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fchownat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fchownat fchownat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flock(fd int, how int) (err error) { + _, _, e1 := syscall_syscall(libc_flock_trampoline_addr, uintptr(fd), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_flock_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_flock flock "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fpathconf(fd int, name int) (val int, err error) { + r0, _, e1 := syscall_syscall(libc_fpathconf_trampoline_addr, uintptr(fd), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fpathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, stat *Stat_t) (err error) { + _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstat fstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_fstatat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstatat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatfs(fd int, stat *Statfs_t) (err error) { + _, _, e1 := syscall_syscall(libc_fstatfs_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fstatfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fstatfs fstatfs "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsync(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_fsync_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fsync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fsync fsync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := syscall_syscall(libc_ftruncate_trampoline_addr, uintptr(fd), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_ftruncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_ftruncate ftruncate "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + r0, _, _ := syscall_rawSyscall(libc_getegid_trampoline_addr, 0, 0, 0) + egid = int(r0) + return +} + +var libc_getegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getegid getegid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (uid int) { + r0, _, _ := syscall_rawSyscall(libc_geteuid_trampoline_addr, 0, 0, 0) + uid = int(r0) + return +} + +var libc_geteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_geteuid geteuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _, _ := syscall_rawSyscall(libc_getgid_trampoline_addr, 0, 0, 0) + gid = int(r0) + return +} + +var libc_getgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getgid getgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgid(pid int) (pgid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getpgid_trampoline_addr, uintptr(pid), 0, 0) + pgid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgid getpgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgrp() (pgrp int) { + r0, _, _ := syscall_rawSyscall(libc_getpgrp_trampoline_addr, 0, 0, 0) + pgrp = int(r0) + return +} + +var libc_getpgrp_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpid() (pid int) { + r0, _, _ := syscall_rawSyscall(libc_getpid_trampoline_addr, 0, 0, 0) + pid = int(r0) + return +} + +var libc_getpid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpid getpid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getppid() (ppid int) { + r0, _, _ := syscall_rawSyscall(libc_getppid_trampoline_addr, 0, 0, 0) + ppid = int(r0) + return +} + +var libc_getppid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getppid getppid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpriority(which int, who int) (prio int, err error) { + r0, _, e1 := syscall_syscall(libc_getpriority_trampoline_addr, uintptr(which), uintptr(who), 0) + prio = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getpriority getpriority "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrlimit(which int, lim *Rlimit) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrlimit_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrtable() (rtable int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getrtable_trampoline_addr, 0, 0, 0) + rtable = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrtable getrtable "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrusage(who int, rusage *Rusage) (err error) { + _, _, e1 := syscall_rawSyscall(libc_getrusage_trampoline_addr, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getrusage_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getrusage getrusage "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_getsid_trampoline_addr, uintptr(pid), 0, 0) + sid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getsid getsid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_gettimeofday_trampoline_addr, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_gettimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := syscall_rawSyscall(libc_getuid_trampoline_addr, 0, 0, 0) + uid = int(r0) + return +} + +var libc_getuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getuid getuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Issetugid() (tainted bool) { + r0, _, _ := syscall_syscall(libc_issetugid_trampoline_addr, 0, 0, 0) + tainted = bool(r0 != 0) + return +} + +var libc_issetugid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_issetugid issetugid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kill(pid int, signum syscall.Signal) (err error) { + _, _, e1 := syscall_syscall(libc_kill_trampoline_addr, uintptr(pid), uintptr(signum), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kill_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kill kill "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kqueue() (fd int, err error) { + r0, _, e1 := syscall_syscall(libc_kqueue_trampoline_addr, 0, 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_kqueue_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_kqueue kqueue "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_lchown_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lchown_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lchown lchown "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Link(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_link_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_link_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_link link "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_linkat_trampoline_addr, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_linkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_linkat linkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, backlog int) (err error) { + _, _, e1 := syscall_syscall(libc_listen_trampoline_addr, uintptr(s), uintptr(backlog), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_listen_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_listen listen "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lstat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_lstat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lstat lstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdir(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdir mkdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkdirat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkdirat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkdirat mkdirat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifo(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkfifo_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkfifo_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifo mkfifo "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mkfifoat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mkfifoat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mkfifoat mkfifoat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknod(path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_mknod_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mknod_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknod mknod "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mknodat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mknodat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mknodat mknodat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Nanosleep(time *Timespec, leftover *Timespec) (err error) { + _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_nanosleep_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_nanosleep nanosleep "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Open(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall(libc_open_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_open_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_open open "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall6(libc_openat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_openat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_openat openat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pathconf(path string, name int) (val int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall_syscall(libc_pathconf_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pathconf_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pathconf pathconf "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pread_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pread_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pread pread "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwrite_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwrite_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwrite pwrite "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func read(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_read_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_read_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_read read "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlink readlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_readlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readlinkat readlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rename(from string, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_rename_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_rename_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rename rename "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameat_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameat renameat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Revoke(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_revoke_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_revoke_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_revoke revoke "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rmdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_rmdir_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_rmdir_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_rmdir rmdir "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { + r0, _, e1 := syscall_syscall(libc_lseek_trampoline_addr, uintptr(fd), uintptr(offset), uintptr(whence)) + newoffset = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_lseek_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_lseek lseek "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { + r0, _, e1 := syscall_syscall6(libc_select_trampoline_addr, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_select_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_select select "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setegid(egid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setegid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setegid setegid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_seteuid_trampoline_addr, uintptr(euid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_seteuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_seteuid seteuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setgid(gid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setgid_trampoline_addr, uintptr(gid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setgid setgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setlogin(name string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_setlogin_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setlogin_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setlogin setlogin "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpgid(pid int, pgid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setpgid_trampoline_addr, uintptr(pid), uintptr(pgid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setpgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpgid setpgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpriority(which int, who int, prio int) (err error) { + _, _, e1 := syscall_syscall(libc_setpriority_trampoline_addr, uintptr(which), uintptr(who), uintptr(prio)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setpriority_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setpriority setpriority "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setregid_trampoline_addr, uintptr(rgid), uintptr(egid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setregid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setregid setregid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setreuid_trampoline_addr, uintptr(ruid), uintptr(euid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setreuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setreuid setreuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setresgid(rgid int, egid int, sgid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setresgid_trampoline_addr, uintptr(rgid), uintptr(egid), uintptr(sgid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setresgid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresgid setresgid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setresuid(ruid int, euid int, suid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setresuid_trampoline_addr, uintptr(ruid), uintptr(euid), uintptr(suid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setresuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setresuid setresuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setrtable(rtable int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setrtable_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setrtable setrtable "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setsid() (pid int, err error) { + r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) + pid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setsid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setsid setsid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Settimeofday(tp *Timeval) (err error) { + _, _, e1 := syscall_rawSyscall(libc_settimeofday_trampoline_addr, uintptr(unsafe.Pointer(tp)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_settimeofday_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_settimeofday settimeofday "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setuid(uid int) (err error) { + _, _, e1 := syscall_rawSyscall(libc_setuid_trampoline_addr, uintptr(uid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_setuid_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_setuid setuid "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Stat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_stat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_stat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_stat stat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Statfs(path string, stat *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_statfs_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_statfs_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_statfs statfs "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlink(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_symlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_symlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlink symlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_symlinkat_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_symlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_symlinkat symlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Sync() (err error) { + _, _, e1 := syscall_syscall(libc_sync_trampoline_addr, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_sync_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_sync sync "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_truncate_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_truncate_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_truncate truncate "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Umask(newmask int) (oldmask int) { + r0, _, _ := syscall_syscall(libc_umask_trampoline_addr, uintptr(newmask), 0, 0) + oldmask = int(r0) + return +} + +var libc_umask_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_umask umask "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlink(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unlink_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlink unlink "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unlinkat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unlinkat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unmount(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_unmount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unmount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unmount unmount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func write(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_write_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_write_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_write write "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall6(libc_mmap_trampoline_addr, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mmap mmap "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func munmap(addr uintptr, length uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_munmap_trampoline_addr, uintptr(addr), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_munmap_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_munmap munmap "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_utimensat_trampoline_addr, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_utimensat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s new file mode 100644 index 0000000..1e7f321 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s @@ -0,0 +1,699 @@ +// go run mkasm.go openbsd riscv64 +// Code generated by the command above; DO NOT EDIT. + +#include "textflag.h" + +TEXT libc_getgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgroups(SB) +GLOBL ·libc_getgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgroups_trampoline_addr(SB)/8, $libc_getgroups_trampoline<>(SB) + +TEXT libc_setgroups_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgroups(SB) +GLOBL ·libc_setgroups_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgroups_trampoline_addr(SB)/8, $libc_setgroups_trampoline<>(SB) + +TEXT libc_wait4_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_wait4(SB) +GLOBL ·libc_wait4_trampoline_addr(SB), RODATA, $8 +DATA ·libc_wait4_trampoline_addr(SB)/8, $libc_wait4_trampoline<>(SB) + +TEXT libc_accept_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_accept(SB) +GLOBL ·libc_accept_trampoline_addr(SB), RODATA, $8 +DATA ·libc_accept_trampoline_addr(SB)/8, $libc_accept_trampoline<>(SB) + +TEXT libc_bind_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_bind(SB) +GLOBL ·libc_bind_trampoline_addr(SB), RODATA, $8 +DATA ·libc_bind_trampoline_addr(SB)/8, $libc_bind_trampoline<>(SB) + +TEXT libc_connect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connect(SB) +GLOBL ·libc_connect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connect_trampoline_addr(SB)/8, $libc_connect_trampoline<>(SB) + +TEXT libc_socket_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socket(SB) +GLOBL ·libc_socket_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socket_trampoline_addr(SB)/8, $libc_socket_trampoline<>(SB) + +TEXT libc_getsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockopt(SB) +GLOBL ·libc_getsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockopt_trampoline_addr(SB)/8, $libc_getsockopt_trampoline<>(SB) + +TEXT libc_setsockopt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsockopt(SB) +GLOBL ·libc_setsockopt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsockopt_trampoline_addr(SB)/8, $libc_setsockopt_trampoline<>(SB) + +TEXT libc_getpeername_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpeername(SB) +GLOBL ·libc_getpeername_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpeername_trampoline_addr(SB)/8, $libc_getpeername_trampoline<>(SB) + +TEXT libc_getsockname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsockname(SB) +GLOBL ·libc_getsockname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsockname_trampoline_addr(SB)/8, $libc_getsockname_trampoline<>(SB) + +TEXT libc_shutdown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shutdown(SB) +GLOBL ·libc_shutdown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shutdown_trampoline_addr(SB)/8, $libc_shutdown_trampoline<>(SB) + +TEXT libc_socketpair_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_socketpair(SB) +GLOBL ·libc_socketpair_trampoline_addr(SB), RODATA, $8 +DATA ·libc_socketpair_trampoline_addr(SB)/8, $libc_socketpair_trampoline<>(SB) + +TEXT libc_recvfrom_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvfrom(SB) +GLOBL ·libc_recvfrom_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvfrom_trampoline_addr(SB)/8, $libc_recvfrom_trampoline<>(SB) + +TEXT libc_sendto_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendto(SB) +GLOBL ·libc_sendto_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendto_trampoline_addr(SB)/8, $libc_sendto_trampoline<>(SB) + +TEXT libc_recvmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_recvmsg(SB) +GLOBL ·libc_recvmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_recvmsg_trampoline_addr(SB)/8, $libc_recvmsg_trampoline<>(SB) + +TEXT libc_sendmsg_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sendmsg(SB) +GLOBL ·libc_sendmsg_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sendmsg_trampoline_addr(SB)/8, $libc_sendmsg_trampoline<>(SB) + +TEXT libc_kevent_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kevent(SB) +GLOBL ·libc_kevent_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kevent_trampoline_addr(SB)/8, $libc_kevent_trampoline<>(SB) + +TEXT libc_utimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimes(SB) +GLOBL ·libc_utimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimes_trampoline_addr(SB)/8, $libc_utimes_trampoline<>(SB) + +TEXT libc_futimes_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_futimes(SB) +GLOBL ·libc_futimes_trampoline_addr(SB), RODATA, $8 +DATA ·libc_futimes_trampoline_addr(SB)/8, $libc_futimes_trampoline<>(SB) + +TEXT libc_poll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_poll(SB) +GLOBL ·libc_poll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_poll_trampoline_addr(SB)/8, $libc_poll_trampoline<>(SB) + +TEXT libc_madvise_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_madvise(SB) +GLOBL ·libc_madvise_trampoline_addr(SB), RODATA, $8 +DATA ·libc_madvise_trampoline_addr(SB)/8, $libc_madvise_trampoline<>(SB) + +TEXT libc_mlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlock(SB) +GLOBL ·libc_mlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlock_trampoline_addr(SB)/8, $libc_mlock_trampoline<>(SB) + +TEXT libc_mlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mlockall(SB) +GLOBL ·libc_mlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mlockall_trampoline_addr(SB)/8, $libc_mlockall_trampoline<>(SB) + +TEXT libc_mprotect_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mprotect(SB) +GLOBL ·libc_mprotect_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mprotect_trampoline_addr(SB)/8, $libc_mprotect_trampoline<>(SB) + +TEXT libc_msync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_msync(SB) +GLOBL ·libc_msync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_msync_trampoline_addr(SB)/8, $libc_msync_trampoline<>(SB) + +TEXT libc_munlock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlock(SB) +GLOBL ·libc_munlock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlock_trampoline_addr(SB)/8, $libc_munlock_trampoline<>(SB) + +TEXT libc_munlockall_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munlockall(SB) +GLOBL ·libc_munlockall_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munlockall_trampoline_addr(SB)/8, $libc_munlockall_trampoline<>(SB) + +TEXT libc_pipe2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pipe2(SB) +GLOBL ·libc_pipe2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pipe2_trampoline_addr(SB)/8, $libc_pipe2_trampoline<>(SB) + +TEXT libc_getdents_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getdents(SB) +GLOBL ·libc_getdents_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getdents_trampoline_addr(SB)/8, $libc_getdents_trampoline<>(SB) + +TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) +GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) + +TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresuid(SB) +GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB) + +TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getresgid(SB) +GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB) + +TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ioctl(SB) +GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + +TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ppoll(SB) +GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ppoll_trampoline_addr(SB)/8, $libc_ppoll_trampoline<>(SB) + +TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_access(SB) +GLOBL ·libc_access_trampoline_addr(SB), RODATA, $8 +DATA ·libc_access_trampoline_addr(SB)/8, $libc_access_trampoline<>(SB) + +TEXT libc_adjtime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_adjtime(SB) +GLOBL ·libc_adjtime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_adjtime_trampoline_addr(SB)/8, $libc_adjtime_trampoline<>(SB) + +TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chdir(SB) +GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB) + +TEXT libc_chflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chflags(SB) +GLOBL ·libc_chflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chflags_trampoline_addr(SB)/8, $libc_chflags_trampoline<>(SB) + +TEXT libc_chmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chmod(SB) +GLOBL ·libc_chmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chmod_trampoline_addr(SB)/8, $libc_chmod_trampoline<>(SB) + +TEXT libc_chown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chown(SB) +GLOBL ·libc_chown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chown_trampoline_addr(SB)/8, $libc_chown_trampoline<>(SB) + +TEXT libc_chroot_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_chroot(SB) +GLOBL ·libc_chroot_trampoline_addr(SB), RODATA, $8 +DATA ·libc_chroot_trampoline_addr(SB)/8, $libc_chroot_trampoline<>(SB) + +TEXT libc_clock_gettime_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_clock_gettime(SB) +GLOBL ·libc_clock_gettime_trampoline_addr(SB), RODATA, $8 +DATA ·libc_clock_gettime_trampoline_addr(SB)/8, $libc_clock_gettime_trampoline<>(SB) + +TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_close(SB) +GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8 +DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB) + +TEXT libc_dup_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup(SB) +GLOBL ·libc_dup_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup_trampoline_addr(SB)/8, $libc_dup_trampoline<>(SB) + +TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup2(SB) +GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB) + +TEXT libc_dup3_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_dup3(SB) +GLOBL ·libc_dup3_trampoline_addr(SB), RODATA, $8 +DATA ·libc_dup3_trampoline_addr(SB)/8, $libc_dup3_trampoline<>(SB) + +TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_exit(SB) +GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB) + +TEXT libc_faccessat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_faccessat(SB) +GLOBL ·libc_faccessat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_faccessat_trampoline_addr(SB)/8, $libc_faccessat_trampoline<>(SB) + +TEXT libc_fchdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchdir(SB) +GLOBL ·libc_fchdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchdir_trampoline_addr(SB)/8, $libc_fchdir_trampoline<>(SB) + +TEXT libc_fchflags_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchflags(SB) +GLOBL ·libc_fchflags_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchflags_trampoline_addr(SB)/8, $libc_fchflags_trampoline<>(SB) + +TEXT libc_fchmod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmod(SB) +GLOBL ·libc_fchmod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmod_trampoline_addr(SB)/8, $libc_fchmod_trampoline<>(SB) + +TEXT libc_fchmodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchmodat(SB) +GLOBL ·libc_fchmodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchmodat_trampoline_addr(SB)/8, $libc_fchmodat_trampoline<>(SB) + +TEXT libc_fchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchown(SB) +GLOBL ·libc_fchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchown_trampoline_addr(SB)/8, $libc_fchown_trampoline<>(SB) + +TEXT libc_fchownat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fchownat(SB) +GLOBL ·libc_fchownat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fchownat_trampoline_addr(SB)/8, $libc_fchownat_trampoline<>(SB) + +TEXT libc_flock_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_flock(SB) +GLOBL ·libc_flock_trampoline_addr(SB), RODATA, $8 +DATA ·libc_flock_trampoline_addr(SB)/8, $libc_flock_trampoline<>(SB) + +TEXT libc_fpathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fpathconf(SB) +GLOBL ·libc_fpathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fpathconf_trampoline_addr(SB)/8, $libc_fpathconf_trampoline<>(SB) + +TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstat(SB) +GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstat_trampoline_addr(SB)/8, $libc_fstat_trampoline<>(SB) + +TEXT libc_fstatat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatat(SB) +GLOBL ·libc_fstatat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatat_trampoline_addr(SB)/8, $libc_fstatat_trampoline<>(SB) + +TEXT libc_fstatfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fstatfs(SB) +GLOBL ·libc_fstatfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fstatfs_trampoline_addr(SB)/8, $libc_fstatfs_trampoline<>(SB) + +TEXT libc_fsync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fsync(SB) +GLOBL ·libc_fsync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fsync_trampoline_addr(SB)/8, $libc_fsync_trampoline<>(SB) + +TEXT libc_ftruncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_ftruncate(SB) +GLOBL ·libc_ftruncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_ftruncate_trampoline_addr(SB)/8, $libc_ftruncate_trampoline<>(SB) + +TEXT libc_getegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getegid(SB) +GLOBL ·libc_getegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getegid_trampoline_addr(SB)/8, $libc_getegid_trampoline<>(SB) + +TEXT libc_geteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_geteuid(SB) +GLOBL ·libc_geteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_geteuid_trampoline_addr(SB)/8, $libc_geteuid_trampoline<>(SB) + +TEXT libc_getgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getgid(SB) +GLOBL ·libc_getgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getgid_trampoline_addr(SB)/8, $libc_getgid_trampoline<>(SB) + +TEXT libc_getpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgid(SB) +GLOBL ·libc_getpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgid_trampoline_addr(SB)/8, $libc_getpgid_trampoline<>(SB) + +TEXT libc_getpgrp_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpgrp(SB) +GLOBL ·libc_getpgrp_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpgrp_trampoline_addr(SB)/8, $libc_getpgrp_trampoline<>(SB) + +TEXT libc_getpid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpid(SB) +GLOBL ·libc_getpid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpid_trampoline_addr(SB)/8, $libc_getpid_trampoline<>(SB) + +TEXT libc_getppid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getppid(SB) +GLOBL ·libc_getppid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getppid_trampoline_addr(SB)/8, $libc_getppid_trampoline<>(SB) + +TEXT libc_getpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getpriority(SB) +GLOBL ·libc_getpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getpriority_trampoline_addr(SB)/8, $libc_getpriority_trampoline<>(SB) + +TEXT libc_getrlimit_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrlimit(SB) +GLOBL ·libc_getrlimit_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrlimit_trampoline_addr(SB)/8, $libc_getrlimit_trampoline<>(SB) + +TEXT libc_getrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrtable(SB) +GLOBL ·libc_getrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrtable_trampoline_addr(SB)/8, $libc_getrtable_trampoline<>(SB) + +TEXT libc_getrusage_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getrusage(SB) +GLOBL ·libc_getrusage_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getrusage_trampoline_addr(SB)/8, $libc_getrusage_trampoline<>(SB) + +TEXT libc_getsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getsid(SB) +GLOBL ·libc_getsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getsid_trampoline_addr(SB)/8, $libc_getsid_trampoline<>(SB) + +TEXT libc_gettimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_gettimeofday(SB) +GLOBL ·libc_gettimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_gettimeofday_trampoline_addr(SB)/8, $libc_gettimeofday_trampoline<>(SB) + +TEXT libc_getuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getuid(SB) +GLOBL ·libc_getuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getuid_trampoline_addr(SB)/8, $libc_getuid_trampoline<>(SB) + +TEXT libc_issetugid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_issetugid(SB) +GLOBL ·libc_issetugid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_issetugid_trampoline_addr(SB)/8, $libc_issetugid_trampoline<>(SB) + +TEXT libc_kill_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kill(SB) +GLOBL ·libc_kill_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kill_trampoline_addr(SB)/8, $libc_kill_trampoline<>(SB) + +TEXT libc_kqueue_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_kqueue(SB) +GLOBL ·libc_kqueue_trampoline_addr(SB), RODATA, $8 +DATA ·libc_kqueue_trampoline_addr(SB)/8, $libc_kqueue_trampoline<>(SB) + +TEXT libc_lchown_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lchown(SB) +GLOBL ·libc_lchown_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lchown_trampoline_addr(SB)/8, $libc_lchown_trampoline<>(SB) + +TEXT libc_link_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_link(SB) +GLOBL ·libc_link_trampoline_addr(SB), RODATA, $8 +DATA ·libc_link_trampoline_addr(SB)/8, $libc_link_trampoline<>(SB) + +TEXT libc_linkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_linkat(SB) +GLOBL ·libc_linkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_linkat_trampoline_addr(SB)/8, $libc_linkat_trampoline<>(SB) + +TEXT libc_listen_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_listen(SB) +GLOBL ·libc_listen_trampoline_addr(SB), RODATA, $8 +DATA ·libc_listen_trampoline_addr(SB)/8, $libc_listen_trampoline<>(SB) + +TEXT libc_lstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lstat(SB) +GLOBL ·libc_lstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lstat_trampoline_addr(SB)/8, $libc_lstat_trampoline<>(SB) + +TEXT libc_mkdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdir(SB) +GLOBL ·libc_mkdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdir_trampoline_addr(SB)/8, $libc_mkdir_trampoline<>(SB) + +TEXT libc_mkdirat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkdirat(SB) +GLOBL ·libc_mkdirat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkdirat_trampoline_addr(SB)/8, $libc_mkdirat_trampoline<>(SB) + +TEXT libc_mkfifo_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifo(SB) +GLOBL ·libc_mkfifo_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifo_trampoline_addr(SB)/8, $libc_mkfifo_trampoline<>(SB) + +TEXT libc_mkfifoat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mkfifoat(SB) +GLOBL ·libc_mkfifoat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mkfifoat_trampoline_addr(SB)/8, $libc_mkfifoat_trampoline<>(SB) + +TEXT libc_mknod_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknod(SB) +GLOBL ·libc_mknod_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknod_trampoline_addr(SB)/8, $libc_mknod_trampoline<>(SB) + +TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mknodat(SB) +GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) + +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + +TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_nanosleep(SB) +GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 +DATA ·libc_nanosleep_trampoline_addr(SB)/8, $libc_nanosleep_trampoline<>(SB) + +TEXT libc_open_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_open(SB) +GLOBL ·libc_open_trampoline_addr(SB), RODATA, $8 +DATA ·libc_open_trampoline_addr(SB)/8, $libc_open_trampoline<>(SB) + +TEXT libc_openat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_openat(SB) +GLOBL ·libc_openat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_openat_trampoline_addr(SB)/8, $libc_openat_trampoline<>(SB) + +TEXT libc_pathconf_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pathconf(SB) +GLOBL ·libc_pathconf_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pathconf_trampoline_addr(SB)/8, $libc_pathconf_trampoline<>(SB) + +TEXT libc_pread_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pread(SB) +GLOBL ·libc_pread_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pread_trampoline_addr(SB)/8, $libc_pread_trampoline<>(SB) + +TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwrite(SB) +GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) + +TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_read(SB) +GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 +DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB) + +TEXT libc_readlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlink(SB) +GLOBL ·libc_readlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlink_trampoline_addr(SB)/8, $libc_readlink_trampoline<>(SB) + +TEXT libc_readlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readlinkat(SB) +GLOBL ·libc_readlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readlinkat_trampoline_addr(SB)/8, $libc_readlinkat_trampoline<>(SB) + +TEXT libc_rename_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rename(SB) +GLOBL ·libc_rename_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rename_trampoline_addr(SB)/8, $libc_rename_trampoline<>(SB) + +TEXT libc_renameat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameat(SB) +GLOBL ·libc_renameat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameat_trampoline_addr(SB)/8, $libc_renameat_trampoline<>(SB) + +TEXT libc_revoke_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_revoke(SB) +GLOBL ·libc_revoke_trampoline_addr(SB), RODATA, $8 +DATA ·libc_revoke_trampoline_addr(SB)/8, $libc_revoke_trampoline<>(SB) + +TEXT libc_rmdir_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_rmdir(SB) +GLOBL ·libc_rmdir_trampoline_addr(SB), RODATA, $8 +DATA ·libc_rmdir_trampoline_addr(SB)/8, $libc_rmdir_trampoline<>(SB) + +TEXT libc_lseek_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_lseek(SB) +GLOBL ·libc_lseek_trampoline_addr(SB), RODATA, $8 +DATA ·libc_lseek_trampoline_addr(SB)/8, $libc_lseek_trampoline<>(SB) + +TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_select(SB) +GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 +DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) + +TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setegid(SB) +GLOBL ·libc_setegid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setegid_trampoline_addr(SB)/8, $libc_setegid_trampoline<>(SB) + +TEXT libc_seteuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_seteuid(SB) +GLOBL ·libc_seteuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_seteuid_trampoline_addr(SB)/8, $libc_seteuid_trampoline<>(SB) + +TEXT libc_setgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setgid(SB) +GLOBL ·libc_setgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setgid_trampoline_addr(SB)/8, $libc_setgid_trampoline<>(SB) + +TEXT libc_setlogin_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setlogin(SB) +GLOBL ·libc_setlogin_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setlogin_trampoline_addr(SB)/8, $libc_setlogin_trampoline<>(SB) + +TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpgid(SB) +GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB) + +TEXT libc_setpriority_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setpriority(SB) +GLOBL ·libc_setpriority_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setpriority_trampoline_addr(SB)/8, $libc_setpriority_trampoline<>(SB) + +TEXT libc_setregid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setregid(SB) +GLOBL ·libc_setregid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setregid_trampoline_addr(SB)/8, $libc_setregid_trampoline<>(SB) + +TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setreuid(SB) +GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) + +TEXT libc_setresgid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresgid(SB) +GLOBL ·libc_setresgid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresgid_trampoline_addr(SB)/8, $libc_setresgid_trampoline<>(SB) + +TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setresuid(SB) +GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) + +TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setrtable(SB) +GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setrtable_trampoline_addr(SB)/8, $libc_setrtable_trampoline<>(SB) + +TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setsid(SB) +GLOBL ·libc_setsid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setsid_trampoline_addr(SB)/8, $libc_setsid_trampoline<>(SB) + +TEXT libc_settimeofday_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_settimeofday(SB) +GLOBL ·libc_settimeofday_trampoline_addr(SB), RODATA, $8 +DATA ·libc_settimeofday_trampoline_addr(SB)/8, $libc_settimeofday_trampoline<>(SB) + +TEXT libc_setuid_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_setuid(SB) +GLOBL ·libc_setuid_trampoline_addr(SB), RODATA, $8 +DATA ·libc_setuid_trampoline_addr(SB)/8, $libc_setuid_trampoline<>(SB) + +TEXT libc_stat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_stat(SB) +GLOBL ·libc_stat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_stat_trampoline_addr(SB)/8, $libc_stat_trampoline<>(SB) + +TEXT libc_statfs_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_statfs(SB) +GLOBL ·libc_statfs_trampoline_addr(SB), RODATA, $8 +DATA ·libc_statfs_trampoline_addr(SB)/8, $libc_statfs_trampoline<>(SB) + +TEXT libc_symlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlink(SB) +GLOBL ·libc_symlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlink_trampoline_addr(SB)/8, $libc_symlink_trampoline<>(SB) + +TEXT libc_symlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_symlinkat(SB) +GLOBL ·libc_symlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_symlinkat_trampoline_addr(SB)/8, $libc_symlinkat_trampoline<>(SB) + +TEXT libc_sync_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sync(SB) +GLOBL ·libc_sync_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sync_trampoline_addr(SB)/8, $libc_sync_trampoline<>(SB) + +TEXT libc_truncate_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_truncate(SB) +GLOBL ·libc_truncate_trampoline_addr(SB), RODATA, $8 +DATA ·libc_truncate_trampoline_addr(SB)/8, $libc_truncate_trampoline<>(SB) + +TEXT libc_umask_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_umask(SB) +GLOBL ·libc_umask_trampoline_addr(SB), RODATA, $8 +DATA ·libc_umask_trampoline_addr(SB)/8, $libc_umask_trampoline<>(SB) + +TEXT libc_unlink_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlink(SB) +GLOBL ·libc_unlink_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlink_trampoline_addr(SB)/8, $libc_unlink_trampoline<>(SB) + +TEXT libc_unlinkat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unlinkat(SB) +GLOBL ·libc_unlinkat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unlinkat_trampoline_addr(SB)/8, $libc_unlinkat_trampoline<>(SB) + +TEXT libc_unmount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unmount(SB) +GLOBL ·libc_unmount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unmount_trampoline_addr(SB)/8, $libc_unmount_trampoline<>(SB) + +TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_write(SB) +GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8 +DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB) + +TEXT libc_mmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mmap(SB) +GLOBL ·libc_mmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mmap_trampoline_addr(SB)/8, $libc_mmap_trampoline<>(SB) + +TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_munmap(SB) +GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 +DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) + +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + +TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) +GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index a96165d..b4609c2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -1,7 +1,7 @@ // go run mksyscall_solaris.go -tags solaris,amd64 syscall_solaris.go syscall_solaris_amd64.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build solaris,amd64 +//go:build solaris && amd64 package unix @@ -11,6 +11,7 @@ import ( ) //go:cgo_import_dynamic libc_pipe pipe "libc.so" +//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so" //go:cgo_import_dynamic libc_getsockname getsockname "libsocket.so" //go:cgo_import_dynamic libc_getcwd getcwd "libc.so" //go:cgo_import_dynamic libc_getgroups getgroups "libc.so" @@ -36,6 +37,7 @@ import ( //go:cgo_import_dynamic libc_chmod chmod "libc.so" //go:cgo_import_dynamic libc_chown chown "libc.so" //go:cgo_import_dynamic libc_chroot chroot "libc.so" +//go:cgo_import_dynamic libc_clockgettime clockgettime "libc.so" //go:cgo_import_dynamic libc_close close "libc.so" //go:cgo_import_dynamic libc_creat creat "libc.so" //go:cgo_import_dynamic libc_dup dup "libc.so" @@ -64,12 +66,13 @@ import ( //go:cgo_import_dynamic libc_getpriority getpriority "libc.so" //go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" //go:cgo_import_dynamic libc_getrusage getrusage "libc.so" +//go:cgo_import_dynamic libc_getsid getsid "libc.so" //go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" //go:cgo_import_dynamic libc_getuid getuid "libc.so" //go:cgo_import_dynamic libc_kill kill "libc.so" //go:cgo_import_dynamic libc_lchown lchown "libc.so" //go:cgo_import_dynamic libc_link link "libc.so" -//go:cgo_import_dynamic libc___xnet_llisten __xnet_llisten "libsocket.so" +//go:cgo_import_dynamic libc___xnet_listen __xnet_listen "libsocket.so" //go:cgo_import_dynamic libc_lstat lstat "libc.so" //go:cgo_import_dynamic libc_madvise madvise "libc.so" //go:cgo_import_dynamic libc_mkdir mkdir "libc.so" @@ -106,7 +109,6 @@ import ( //go:cgo_import_dynamic libc_setpriority setpriority "libc.so" //go:cgo_import_dynamic libc_setregid setregid "libc.so" //go:cgo_import_dynamic libc_setreuid setreuid "libc.so" -//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.so" //go:cgo_import_dynamic libc_setsid setsid "libc.so" //go:cgo_import_dynamic libc_setuid setuid "libc.so" //go:cgo_import_dynamic libc_shutdown shutdown "libsocket.so" @@ -114,6 +116,7 @@ import ( //go:cgo_import_dynamic libc_statvfs statvfs "libc.so" //go:cgo_import_dynamic libc_symlink symlink "libc.so" //go:cgo_import_dynamic libc_sync sync "libc.so" +//go:cgo_import_dynamic libc_sysconf sysconf "libc.so" //go:cgo_import_dynamic libc_times times "libc.so" //go:cgo_import_dynamic libc_truncate truncate "libc.so" //go:cgo_import_dynamic libc_fsync fsync "libc.so" @@ -138,8 +141,26 @@ import ( //go:cgo_import_dynamic libc_getpeername getpeername "libsocket.so" //go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so" //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" +//go:cgo_import_dynamic libc_getpeerucred getpeerucred "libc.so" +//go:cgo_import_dynamic libc_ucred_get ucred_get "libc.so" +//go:cgo_import_dynamic libc_ucred_geteuid ucred_geteuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getegid ucred_getegid "libc.so" +//go:cgo_import_dynamic libc_ucred_getruid ucred_getruid "libc.so" +//go:cgo_import_dynamic libc_ucred_getrgid ucred_getrgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsuid ucred_getsuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsgid ucred_getsgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getpid ucred_getpid "libc.so" +//go:cgo_import_dynamic libc_ucred_free ucred_free "libc.so" +//go:cgo_import_dynamic libc_port_create port_create "libc.so" +//go:cgo_import_dynamic libc_port_associate port_associate "libc.so" +//go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so" +//go:cgo_import_dynamic libc_port_get port_get "libc.so" +//go:cgo_import_dynamic libc_port_getn port_getn "libc.so" +//go:cgo_import_dynamic libc_putmsg putmsg "libc.so" +//go:cgo_import_dynamic libc_getmsg getmsg "libc.so" //go:linkname procpipe libc_pipe +//go:linkname procpipe2 libc_pipe2 //go:linkname procgetsockname libc_getsockname //go:linkname procGetcwd libc_getcwd //go:linkname procgetgroups libc_getgroups @@ -165,6 +186,7 @@ import ( //go:linkname procChmod libc_chmod //go:linkname procChown libc_chown //go:linkname procChroot libc_chroot +//go:linkname procClockGettime libc_clockgettime //go:linkname procClose libc_close //go:linkname procCreat libc_creat //go:linkname procDup libc_dup @@ -193,12 +215,13 @@ import ( //go:linkname procGetpriority libc_getpriority //go:linkname procGetrlimit libc_getrlimit //go:linkname procGetrusage libc_getrusage +//go:linkname procGetsid libc_getsid //go:linkname procGettimeofday libc_gettimeofday //go:linkname procGetuid libc_getuid //go:linkname procKill libc_kill //go:linkname procLchown libc_lchown //go:linkname procLink libc_link -//go:linkname proc__xnet_llisten libc___xnet_llisten +//go:linkname proc__xnet_listen libc___xnet_listen //go:linkname procLstat libc_lstat //go:linkname procMadvise libc_madvise //go:linkname procMkdir libc_mkdir @@ -218,8 +241,8 @@ import ( //go:linkname procOpenat libc_openat //go:linkname procPathconf libc_pathconf //go:linkname procPause libc_pause -//go:linkname procPread libc_pread -//go:linkname procPwrite libc_pwrite +//go:linkname procpread libc_pread +//go:linkname procpwrite libc_pwrite //go:linkname procread libc_read //go:linkname procReadlink libc_readlink //go:linkname procRename libc_rename @@ -235,7 +258,6 @@ import ( //go:linkname procSetpriority libc_setpriority //go:linkname procSetregid libc_setregid //go:linkname procSetreuid libc_setreuid -//go:linkname procSetrlimit libc_setrlimit //go:linkname procSetsid libc_setsid //go:linkname procSetuid libc_setuid //go:linkname procshutdown libc_shutdown @@ -243,6 +265,7 @@ import ( //go:linkname procStatvfs libc_statvfs //go:linkname procSymlink libc_symlink //go:linkname procSync libc_sync +//go:linkname procSysconf libc_sysconf //go:linkname procTimes libc_times //go:linkname procTruncate libc_truncate //go:linkname procFsync libc_fsync @@ -267,9 +290,27 @@ import ( //go:linkname procgetpeername libc_getpeername //go:linkname procsetsockopt libc_setsockopt //go:linkname procrecvfrom libc_recvfrom +//go:linkname procgetpeerucred libc_getpeerucred +//go:linkname procucred_get libc_ucred_get +//go:linkname procucred_geteuid libc_ucred_geteuid +//go:linkname procucred_getegid libc_ucred_getegid +//go:linkname procucred_getruid libc_ucred_getruid +//go:linkname procucred_getrgid libc_ucred_getrgid +//go:linkname procucred_getsuid libc_ucred_getsuid +//go:linkname procucred_getsgid libc_ucred_getsgid +//go:linkname procucred_getpid libc_ucred_getpid +//go:linkname procucred_free libc_ucred_free +//go:linkname procport_create libc_port_create +//go:linkname procport_associate libc_port_associate +//go:linkname procport_dissociate libc_port_dissociate +//go:linkname procport_get libc_port_get +//go:linkname procport_getn libc_port_getn +//go:linkname procputmsg libc_putmsg +//go:linkname procgetmsg libc_getmsg var ( procpipe, + procpipe2, procgetsockname, procGetcwd, procgetgroups, @@ -295,6 +336,7 @@ var ( procChmod, procChown, procChroot, + procClockGettime, procClose, procCreat, procDup, @@ -323,12 +365,13 @@ var ( procGetpriority, procGetrlimit, procGetrusage, + procGetsid, procGettimeofday, procGetuid, procKill, procLchown, procLink, - proc__xnet_llisten, + proc__xnet_listen, procLstat, procMadvise, procMkdir, @@ -348,8 +391,8 @@ var ( procOpenat, procPathconf, procPause, - procPread, - procPwrite, + procpread, + procpwrite, procread, procReadlink, procRename, @@ -365,7 +408,6 @@ var ( procSetpriority, procSetregid, procSetreuid, - procSetrlimit, procSetsid, procSetuid, procshutdown, @@ -373,6 +415,7 @@ var ( procStatvfs, procSymlink, procSync, + procSysconf, procTimes, procTruncate, procFsync, @@ -396,7 +439,24 @@ var ( proc__xnet_getsockopt, procgetpeername, procsetsockopt, - procrecvfrom syscallFunc + procrecvfrom, + procgetpeerucred, + procucred_get, + procucred_geteuid, + procucred_getegid, + procucred_getruid, + procucred_getrgid, + procucred_getsuid, + procucred_getsgid, + procucred_getpid, + procucred_free, + procport_create, + procport_associate, + procport_dissociate, + procport_get, + procport_getn, + procputmsg, + procgetmsg syscallFunc ) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -405,7 +465,17 @@ func pipe(p *[2]_C_int) (n int, err error) { r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procpipe)), 1, uintptr(unsafe.Pointer(p)), 0, 0, 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procpipe2)), 2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -415,7 +485,7 @@ func pipe(p *[2]_C_int) (n int, err error) { func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetsockname)), 3, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -430,7 +500,7 @@ func Getcwd(buf []byte) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procGetcwd)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0, 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -441,7 +511,7 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procgetgroups)), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -451,7 +521,7 @@ func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func setgroups(ngid int, gid *_Gid_t) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procsetgroups)), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -462,7 +532,7 @@ func wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwait4)), 4, uintptr(pid), uintptr(unsafe.Pointer(statusp)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) wpid = int32(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -477,7 +547,7 @@ func gethostname(buf []byte) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgethostname)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0, 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -492,7 +562,7 @@ func utimes(path string, times *[2]Timeval) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procutimes)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -507,7 +577,7 @@ func utimensat(fd int, path string, times *[2]Timespec, flag int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procutimensat)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flag), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -518,7 +588,7 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0) val = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -528,7 +598,7 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { func futimesat(fildes int, path *byte, times *[2]Timeval) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfutimesat)), 3, uintptr(fildes), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -539,7 +609,7 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procaccept)), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) fd = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -550,7 +620,7 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_recvmsg)), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -561,7 +631,7 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_sendmsg)), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -571,7 +641,7 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { func acct(path *byte) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procacct)), 1, uintptr(unsafe.Pointer(path)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -602,10 +672,22 @@ func __minor(version int, dev uint64) (val uint) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ioctl(fd int, req uint, arg uintptr) (err error) { - _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, uintptr(fd), uintptr(req), uintptr(arg), 0, 0, 0) +func ioctlRet(fd int, req int, arg uintptr) (ret int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, uintptr(fd), uintptr(req), uintptr(arg), 0, 0, 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, uintptr(fd), uintptr(req), uintptr(arg), 0, 0, 0) + ret = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -616,7 +698,7 @@ func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procpoll)), 3, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -631,7 +713,7 @@ func Access(path string, mode uint32) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procAccess)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -641,7 +723,7 @@ func Access(path string, mode uint32) (err error) { func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procAdjtime)), 2, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -656,7 +738,7 @@ func Chdir(path string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procChdir)), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -671,7 +753,7 @@ func Chmod(path string, mode uint32) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procChmod)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -686,7 +768,7 @@ func Chown(path string, uid int, gid int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procChown)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -701,7 +783,17 @@ func Chroot(path string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procChroot)), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ClockGettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procClockGettime)), 2, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -711,7 +803,7 @@ func Chroot(path string) (err error) { func Close(fd int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procClose)), 1, uintptr(fd), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -727,7 +819,7 @@ func Creat(path string, mode uint32) (fd int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procCreat)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0) fd = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -738,7 +830,7 @@ func Dup(fd int) (nfd int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procDup)), 1, uintptr(fd), 0, 0, 0, 0, 0) nfd = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -748,7 +840,7 @@ func Dup(fd int) (nfd int, err error) { func Dup2(oldfd int, newfd int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procDup2)), 2, uintptr(oldfd), uintptr(newfd), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -770,7 +862,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFaccessat)), 4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -780,7 +872,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { func Fchdir(fd int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFchdir)), 1, uintptr(fd), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -790,7 +882,7 @@ func Fchdir(fd int) (err error) { func Fchmod(fd int, mode uint32) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFchmod)), 2, uintptr(fd), uintptr(mode), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -805,7 +897,7 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFchmodat)), 4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -815,7 +907,7 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFchown)), 3, uintptr(fd), uintptr(uid), uintptr(gid), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -830,7 +922,7 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFchownat)), 5, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -840,7 +932,7 @@ func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { func Fdatasync(fd int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFdatasync)), 1, uintptr(fd), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -850,7 +942,7 @@ func Fdatasync(fd int) (err error) { func Flock(fd int, how int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFlock)), 2, uintptr(fd), uintptr(how), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -861,7 +953,7 @@ func Fpathconf(fd int, name int) (val int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFpathconf)), 2, uintptr(fd), uintptr(name), 0, 0, 0, 0) val = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -871,7 +963,7 @@ func Fpathconf(fd int, name int) (val int, err error) { func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFstat)), 2, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -886,7 +978,7 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFstatat)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -896,7 +988,7 @@ func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { func Fstatvfs(fd int, vfsstat *Statvfs_t) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFstatvfs)), 2, uintptr(fd), uintptr(unsafe.Pointer(vfsstat)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -911,7 +1003,7 @@ func Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procGetdents)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -938,7 +1030,7 @@ func Getpgid(pid int) (pgid int, err error) { r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0) pgid = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -949,7 +1041,7 @@ func Getpgrp() (pgid int, err error) { r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetpgrp)), 0, 0, 0, 0, 0, 0, 0) pgid = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -984,7 +1076,7 @@ func Getpriority(which int, who int) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procGetpriority)), 2, uintptr(which), uintptr(who), 0, 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -994,7 +1086,7 @@ func Getpriority(which int, who int) (n int, err error) { func Getrlimit(which int, lim *Rlimit) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetrlimit)), 2, uintptr(which), uintptr(unsafe.Pointer(lim)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1004,7 +1096,18 @@ func Getrlimit(which int, lim *Rlimit) (err error) { func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetrusage)), 2, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetsid)), 1, uintptr(pid), 0, 0, 0, 0, 0) + sid = int(r0) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1014,7 +1117,7 @@ func Getrusage(who int, rusage *Rusage) (err error) { func Gettimeofday(tv *Timeval) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGettimeofday)), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1032,7 +1135,7 @@ func Getuid() (uid int) { func Kill(pid int, signum syscall.Signal) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procKill)), 2, uintptr(pid), uintptr(signum), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1047,7 +1150,7 @@ func Lchown(path string, uid int, gid int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procLchown)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1067,7 +1170,7 @@ func Link(path string, link string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procLink)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1075,9 +1178,9 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Listen(s int, backlog int) (err error) { - _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_llisten)), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0) + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_listen)), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1092,7 +1195,7 @@ func Lstat(path string, stat *Stat_t) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procLstat)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1106,7 +1209,7 @@ func Madvise(b []byte, advice int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMadvise)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(advice), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1121,7 +1224,7 @@ func Mkdir(path string, mode uint32) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMkdir)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1136,7 +1239,7 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMkdirat)), 3, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1151,7 +1254,7 @@ func Mkfifo(path string, mode uint32) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMkfifo)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1166,7 +1269,7 @@ func Mkfifoat(dirfd int, path string, mode uint32) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMkfifoat)), 3, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1181,7 +1284,7 @@ func Mknod(path string, mode uint32, dev int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMknod)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1196,7 +1299,7 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMknodat)), 4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1210,7 +1313,7 @@ func Mlock(b []byte) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMlock)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1220,7 +1323,7 @@ func Mlock(b []byte) (err error) { func Mlockall(flags int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMlockall)), 1, uintptr(flags), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1234,7 +1337,7 @@ func Mprotect(b []byte, prot int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMprotect)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(prot), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1248,7 +1351,7 @@ func Msync(b []byte, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMsync)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(flags), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1262,7 +1365,7 @@ func Munlock(b []byte) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMunlock)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1272,7 +1375,7 @@ func Munlock(b []byte) (err error) { func Munlockall() (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procMunlockall)), 0, 0, 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1282,7 +1385,7 @@ func Munlockall() (err error) { func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procNanosleep)), 2, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1298,7 +1401,7 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procOpen)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0, 0) fd = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1314,7 +1417,7 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procOpenat)), 4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0) fd = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1330,7 +1433,7 @@ func Pathconf(path string, name int) (val int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procPathconf)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0, 0, 0, 0) val = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1340,37 +1443,37 @@ func Pathconf(path string, name int) (val int, err error) { func Pause() (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procPause)), 0, 0, 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { +func pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 *byte if len(p) > 0 { _p0 = &p[0] } - r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procPread)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0) + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procpread)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func pwrite(fd int, p []byte, offset int64) (n int, err error) { var _p0 *byte if len(p) > 0 { _p0 = &p[0] } - r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procPwrite)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0) + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procpwrite)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1385,7 +1488,7 @@ func read(fd int, p []byte) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1405,7 +1508,7 @@ func Readlink(path string, buf []byte) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procReadlink)), 3, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(len(buf)), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1425,7 +1528,7 @@ func Rename(from string, to string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procRename)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1445,7 +1548,7 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procRenameat)), 4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1460,7 +1563,7 @@ func Rmdir(path string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procRmdir)), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1471,7 +1574,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proclseek)), 3, uintptr(fd), uintptr(offset), uintptr(whence), 0, 0, 0) newoffset = int64(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1482,7 +1585,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1492,7 +1595,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err func Setegid(egid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetegid)), 1, uintptr(egid), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1502,7 +1605,7 @@ func Setegid(egid int) (err error) { func Seteuid(euid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSeteuid)), 1, uintptr(euid), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1512,7 +1615,7 @@ func Seteuid(euid int) (err error) { func Setgid(gid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetgid)), 1, uintptr(gid), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1526,7 +1629,7 @@ func Sethostname(p []byte) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSethostname)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1536,7 +1639,7 @@ func Sethostname(p []byte) (err error) { func Setpgid(pid int, pgid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetpgid)), 2, uintptr(pid), uintptr(pgid), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1546,7 +1649,7 @@ func Setpgid(pid int, pgid int) (err error) { func Setpriority(which int, who int, prio int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSetpriority)), 3, uintptr(which), uintptr(who), uintptr(prio), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1556,7 +1659,7 @@ func Setpriority(which int, who int, prio int) (err error) { func Setregid(rgid int, egid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetregid)), 2, uintptr(rgid), uintptr(egid), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1566,17 +1669,7 @@ func Setregid(rgid int, egid int) (err error) { func Setreuid(ruid int, euid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetreuid)), 2, uintptr(ruid), uintptr(euid), 0, 0, 0, 0) if e1 != 0 { - err = e1 - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Setrlimit(which int, lim *Rlimit) (err error) { - _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetrlimit)), 2, uintptr(which), uintptr(unsafe.Pointer(lim)), 0, 0, 0, 0) - if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1587,7 +1680,7 @@ func Setsid() (pid int, err error) { r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetsid)), 0, 0, 0, 0, 0, 0, 0) pid = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1597,7 +1690,7 @@ func Setsid() (pid int, err error) { func Setuid(uid int) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procSetuid)), 1, uintptr(uid), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1607,7 +1700,7 @@ func Setuid(uid int) (err error) { func Shutdown(s int, how int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procshutdown)), 2, uintptr(s), uintptr(how), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1622,7 +1715,7 @@ func Stat(path string, stat *Stat_t) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procStat)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1637,7 +1730,7 @@ func Statvfs(path string, vfsstat *Statvfs_t) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procStatvfs)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(vfsstat)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1657,7 +1750,7 @@ func Symlink(path string, link string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSymlink)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1667,7 +1760,18 @@ func Symlink(path string, link string) (err error) { func Sync() (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSync)), 0, 0, 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Sysconf(which int) (n int64, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSysconf)), 1, uintptr(which), 0, 0, 0, 0, 0) + n = int64(r0) + if e1 != 0 { + err = errnoErr(e1) } return } @@ -1678,7 +1782,7 @@ func Times(tms *Tms) (ticks uintptr, err error) { r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procTimes)), 1, uintptr(unsafe.Pointer(tms)), 0, 0, 0, 0, 0) ticks = uintptr(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1693,7 +1797,7 @@ func Truncate(path string, length int64) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procTruncate)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1703,7 +1807,7 @@ func Truncate(path string, length int64) (err error) { func Fsync(fd int) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFsync)), 1, uintptr(fd), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1713,7 +1817,7 @@ func Fsync(fd int) (err error) { func Ftruncate(fd int, length int64) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFtruncate)), 2, uintptr(fd), uintptr(length), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1731,7 +1835,7 @@ func Umask(mask int) (oldmask int) { func Uname(buf *Utsname) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procUname)), 1, uintptr(unsafe.Pointer(buf)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1746,7 +1850,7 @@ func Unmount(target string, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procumount)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1761,7 +1865,7 @@ func Unlink(path string) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procUnlink)), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1776,7 +1880,7 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procUnlinkat)), 3, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1786,7 +1890,7 @@ func Unlinkat(dirfd int, path string, flags int) (err error) { func Ustat(dev int, ubuf *Ustat_t) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procUstat)), 2, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1801,7 +1905,7 @@ func Utime(path string, buf *Utimbuf) (err error) { } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procUtime)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1811,7 +1915,7 @@ func Utime(path string, buf *Utimbuf) (err error) { func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_bind)), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1821,7 +1925,7 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_connect)), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1832,7 +1936,7 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procmmap)), 6, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) ret = uintptr(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1842,7 +1946,7 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( func munmap(addr uintptr, length uintptr) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procmunmap)), 2, uintptr(addr), uintptr(length), 0, 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1853,7 +1957,7 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procsendfile)), 4, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0) written = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1867,7 +1971,7 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_sendto)), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1878,7 +1982,7 @@ func socket(domain int, typ int, proto int) (fd int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_socket)), 3, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0) fd = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1888,7 +1992,7 @@ func socket(domain int, typ int, proto int) (fd int, err error) { func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&proc__xnet_socketpair)), 4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1903,7 +2007,7 @@ func write(fd int, p []byte) (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), 0, 0, 0) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1913,7 +2017,7 @@ func write(fd int, p []byte) (n int, err error) { func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&proc__xnet_getsockopt)), 5, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1923,7 +2027,7 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procgetpeername)), 3, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1933,7 +2037,7 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procsetsockopt)), 5, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) if e1 != 0 { - err = e1 + err = errnoErr(e1) } return } @@ -1948,7 +2052,166 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procrecvfrom)), 6, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) n = int(r0) if e1 != 0 { - err = e1 + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeerucred(fd uintptr, ucred *uintptr) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetpeerucred)), 2, uintptr(fd), uintptr(unsafe.Pointer(ucred)), 0, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGet(pid int) (ucred uintptr, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procucred_get)), 1, uintptr(pid), 0, 0, 0, 0, 0) + ucred = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGeteuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_geteuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetegid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getegid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetruid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getruid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetrgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getrgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetpid(ucred uintptr) (pid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getpid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredFree(ucred uintptr) { + sysvicall6(uintptr(unsafe.Pointer(&procucred_free)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_create() (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_create)), 0, 0, 0, 0, 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_associate)), 5, uintptr(port), uintptr(source), uintptr(object), uintptr(events), uintptr(unsafe.Pointer(user)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_dissociate(port int, source int, object uintptr) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_dissociate)), 3, uintptr(port), uintptr(source), uintptr(object), 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_get)), 3, uintptr(port), uintptr(unsafe.Pointer(pe)), uintptr(unsafe.Pointer(timeout)), 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_getn)), 5, uintptr(port), uintptr(unsafe.Pointer(pe)), uintptr(max), uintptr(unsafe.Pointer(nget)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procputmsg)), 4, uintptr(fd), uintptr(unsafe.Pointer(clptr)), uintptr(unsafe.Pointer(dataptr)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetmsg)), 4, uintptr(fd), uintptr(unsafe.Pointer(clptr)), uintptr(unsafe.Pointer(dataptr)), uintptr(unsafe.Pointer(flags)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) } return } diff --git a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go new file mode 100644 index 0000000..7ccf66b --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go @@ -0,0 +1,3458 @@ +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build zos && s390x + +package unix + +import ( + "runtime" + "syscall" + "unsafe" +) + +var _ syscall.Errno + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (val int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.ExitSyscall() + val = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FLISTXATTR_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FlistxattrAddr() *(func(fd int, dest []byte) (sz int, err error)) + +var Flistxattr = enter_Flistxattr + +func enter_Flistxattr(fd int, dest []byte) (sz int, err error) { + funcref := get_FlistxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FLISTXATTR_A<<4, "") == 0 { + *funcref = impl_Flistxattr + } else { + *funcref = error_Flistxattr + } + return (*funcref)(fd, dest) +} + +func error_Flistxattr(fd int, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FremovexattrAddr() *(func(fd int, attr string) (err error)) + +var Fremovexattr = enter_Fremovexattr + +func enter_Fremovexattr(fd int, attr string) (err error) { + funcref := get_FremovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Fremovexattr + } else { + *funcref = error_Fremovexattr + } + return (*funcref)(fd, attr) +} + +func error_Fremovexattr(fd int, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func read(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_READ<<4, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func write(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FGETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FgetxattrAddr() *(func(fd int, attr string, dest []byte) (sz int, err error)) + +var Fgetxattr = enter_Fgetxattr + +func enter_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + funcref := get_FgetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FGETXATTR_A<<4, "") == 0 { + *funcref = impl_Fgetxattr + } else { + *funcref = error_Fgetxattr + } + return (*funcref)(fd, attr, dest) +} + +func error_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(data) > 0 { + _p1 = unsafe.Pointer(&data[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(data)), uintptr(flag)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FsetxattrAddr() *(func(fd int, attr string, data []byte, flag int) (err error)) + +var Fsetxattr = enter_Fsetxattr + +func enter_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + funcref := get_FsetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FSETXATTR_A<<4, "") == 0 { + *funcref = impl_Fsetxattr + } else { + *funcref = error_Fsetxattr + } + return (*funcref)(fd, attr, data, flag) +} + +func error_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT4_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_accept4Addr() *(func(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)) + +var accept4 = enter_accept4 + +func enter_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + funcref := get_accept4Addr() + if funcptrtest(GetZosLibVec()+SYS___ACCEPT4_A<<4, "") == 0 { + *funcref = impl_accept4 + } else { + *funcref = error_accept4 + } + return (*funcref)(s, rsa, addrlen, flags) +} + +func error_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___BIND_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONNECT_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getgroups(n int, list *_Gid_t) (nn int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list))) + nn = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setgroups(n int, list *_Gid_t) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socket(domain int, typ int, proto int) (fd int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKET<<4, uintptr(domain), uintptr(typ), uintptr(proto)) + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKETPAIR<<4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETPEERNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETSOCKNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Removexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_RemovexattrAddr() *(func(path string, attr string) (err error)) + +var Removexattr = enter_Removexattr + +func enter_Removexattr(path string, attr string) (err error) { + funcref := get_RemovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Removexattr + } else { + *funcref = error_Removexattr + } + return (*funcref)(path, attr) +} + +func error_Removexattr(path string, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVFROM_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDTO_A<<4, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MMAP<<4, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + runtime.ExitSyscall() + ret = uintptr(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func munmap(addr uintptr, length uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MUNMAP<<4, uintptr(addr), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctl(fd int, req int, arg uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMAT<<4, uintptr(id), uintptr(addr), uintptr(flag)) + runtime.ExitSyscall() + ret = uintptr(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMCTL64<<4, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + result = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMDT<<4, uintptr(addr)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMGET<<4, uintptr(key), uintptr(size), uintptr(flag)) + runtime.ExitSyscall() + id = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Access(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCESS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHDIR_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chmod(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHMOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Creat(path string, mode uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CREAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(oldfd int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP<<4, uintptr(oldfd)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup2(oldfd int, newfd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP2<<4, uintptr(oldfd), uintptr(newfd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Dup3(oldfd int, newfd int, flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP3<<4, uintptr(oldfd), uintptr(newfd), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Dup3Addr() *(func(oldfd int, newfd int, flags int) (err error)) + +var Dup3 = enter_Dup3 + +func enter_Dup3(oldfd int, newfd int, flags int) (err error) { + funcref := get_Dup3Addr() + if funcptrtest(GetZosLibVec()+SYS_DUP3<<4, "") == 0 { + *funcref = impl_Dup3 + } else { + *funcref = error_Dup3 + } + return (*funcref)(oldfd, newfd, flags) +} + +func error_Dup3(oldfd int, newfd int, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Dirfd(dirp uintptr) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DIRFD<<4, uintptr(dirp)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_DirfdAddr() *(func(dirp uintptr) (fd int, err error)) + +var Dirfd = enter_Dirfd + +func enter_Dirfd(dirp uintptr) (fd int, err error) { + funcref := get_DirfdAddr() + if funcptrtest(GetZosLibVec()+SYS_DIRFD<<4, "") == 0 { + *funcref = impl_Dirfd + } else { + *funcref = error_Dirfd + } + return (*funcref)(dirp) +} + +func error_Dirfd(dirp uintptr) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollCreate(size int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE<<4, uintptr(size)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollCreateAddr() *(func(size int) (fd int, err error)) + +var EpollCreate = enter_EpollCreate + +func enter_EpollCreate(size int) (fd int, err error) { + funcref := get_EpollCreateAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE<<4, "") == 0 { + *funcref = impl_EpollCreate + } else { + *funcref = error_EpollCreate + } + return (*funcref)(size) +} + +func error_EpollCreate(size int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollCreate1(flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollCreate1Addr() *(func(flags int) (fd int, err error)) + +var EpollCreate1 = enter_EpollCreate1 + +func enter_EpollCreate1(flags int) (fd int, err error) { + funcref := get_EpollCreate1Addr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, "") == 0 { + *funcref = impl_EpollCreate1 + } else { + *funcref = error_EpollCreate1 + } + return (*funcref)(flags) +} + +func error_EpollCreate1(flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CTL<<4, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollCtlAddr() *(func(epfd int, op int, fd int, event *EpollEvent) (err error)) + +var EpollCtl = enter_EpollCtl + +func enter_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + funcref := get_EpollCtlAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CTL<<4, "") == 0 { + *funcref = impl_EpollCtl + } else { + *funcref = error_EpollCtl + } + return (*funcref)(epfd, op, fd, event) +} + +func error_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + var _p0 unsafe.Pointer + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), uintptr(unsafe.Pointer(sigmask))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollPwaitAddr() *(func(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error)) + +var EpollPwait = enter_EpollPwait + +func enter_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + funcref := get_EpollPwaitAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, "") == 0 { + *funcref = impl_EpollPwait + } else { + *funcref = error_EpollPwait + } + return (*funcref)(epfd, events, msec, sigmask) +} + +func error_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + var _p0 unsafe.Pointer + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_WAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollWaitAddr() *(func(epfd int, events []EpollEvent, msec int) (n int, err error)) + +var EpollWait = enter_EpollWait + +func enter_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + funcref := get_EpollWaitAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_WAIT<<4, "") == 0 { + *funcref = impl_EpollWait + } else { + *funcref = error_EpollWait + } + return (*funcref)(epfd, events, msec) +} + +func error_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Errno2() (er2 int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERRNO2<<4) + runtime.ExitSyscall() + er2 = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Eventfd(initval uint, flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EVENTFD<<4, uintptr(initval), uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EventfdAddr() *(func(initval uint, flags int) (fd int, err error)) + +var Eventfd = enter_Eventfd + +func enter_Eventfd(initval uint, flags int) (fd int, err error) { + funcref := get_EventfdAddr() + if funcptrtest(GetZosLibVec()+SYS_EVENTFD<<4, "") == 0 { + *funcref = impl_Eventfd + } else { + *funcref = error_Eventfd + } + return (*funcref)(initval, flags) +} + +func error_Eventfd(initval uint, flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Exit(code int) { + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_EXIT<<4, uintptr(code)) + runtime.ExitSyscall() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FACCESSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FaccessatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error)) + +var Faccessat = enter_Faccessat + +func enter_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + funcref := get_FaccessatAddr() + if funcptrtest(GetZosLibVec()+SYS___FACCESSAT_A<<4, "") == 0 { + *funcref = impl_Faccessat + } else { + *funcref = error_Faccessat + } + return (*funcref)(dirfd, path, mode, flags) +} + +func error_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchdir(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHDIR<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmod(fd int, mode uint32) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHMOD<<4, uintptr(fd), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHMODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FchmodatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error)) + +var Fchmodat = enter_Fchmodat + +func enter_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + funcref := get_FchmodatAddr() + if funcptrtest(GetZosLibVec()+SYS___FCHMODAT_A<<4, "") == 0 { + *funcref = impl_Fchmodat + } else { + *funcref = error_Fchmodat + } + return (*funcref)(dirfd, path, mode, flags) +} + +func error_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHOWN<<4, uintptr(fd), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHOWNAT_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FchownatAddr() *(func(fd int, path string, uid int, gid int, flags int) (err error)) + +var Fchownat = enter_Fchownat + +func enter_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + funcref := get_FchownatAddr() + if funcptrtest(GetZosLibVec()+SYS___FCHOWNAT_A<<4, "") == 0 { + *funcref = impl_Fchownat + } else { + *funcref = error_Fchownat + } + return (*funcref)(fd, path, uid, gid, flags) +} + +func error_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.ExitSyscall() + retval = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fdatasync(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FDATASYNC<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FdatasyncAddr() *(func(fd int) (err error)) + +var Fdatasync = enter_Fdatasync + +func enter_Fdatasync(fd int) (err error) { + funcref := get_FdatasyncAddr() + if funcptrtest(GetZosLibVec()+SYS_FDATASYNC<<4, "") == 0 { + *funcref = impl_Fdatasync + } else { + *funcref = error_Fdatasync + } + return (*funcref)(fd) +} + +func error_Fdatasync(fd int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstat(fd int, stat *Stat_LE_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTAT<<4, uintptr(fd), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSTATAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_fstatatAddr() *(func(dirfd int, path string, stat *Stat_LE_t, flags int) (err error)) + +var fstatat = enter_fstatat + +func enter_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + funcref := get_fstatatAddr() + if funcptrtest(GetZosLibVec()+SYS___FSTATAT_A<<4, "") == 0 { + *funcref = impl_fstatat + } else { + *funcref = error_fstatat + } + return (*funcref)(dirfd, path, stat, flags) +} + +func error_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LGETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LgetxattrAddr() *(func(link string, attr string, dest []byte) (sz int, err error)) + +var Lgetxattr = enter_Lgetxattr + +func enter_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + funcref := get_LgetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LGETXATTR_A<<4, "") == 0 { + *funcref = impl_Lgetxattr + } else { + *funcref = error_Lgetxattr + } + return (*funcref)(link, attr, dest) +} + +func error_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LsetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error)) + +var Lsetxattr = enter_Lsetxattr + +func enter_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + funcref := get_LsetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LSETXATTR_A<<4, "") == 0 { + *funcref = impl_Lsetxattr + } else { + *funcref = error_Lsetxattr + } + return (*funcref)(path, attr, data, flags) +} + +func error_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fstatfs(fd int, buf *Statfs_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATFS<<4, uintptr(fd), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FstatfsAddr() *(func(fd int, buf *Statfs_t) (err error)) + +var Fstatfs = enter_Fstatfs + +func enter_Fstatfs(fd int, buf *Statfs_t) (err error) { + funcref := get_FstatfsAddr() + if funcptrtest(GetZosLibVec()+SYS_FSTATFS<<4, "") == 0 { + *funcref = impl_Fstatfs + } else { + *funcref = error_Fstatfs + } + return (*funcref)(fd, buf) +} + +func error_Fstatfs(fd int, buf *Statfs_t) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatvfs(fd int, stat *Statvfs_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATVFS<<4, uintptr(fd), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsync(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSYNC<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Futimes(fd int, tv []Timeval) (err error) { + var _p0 unsafe.Pointer + if len(tv) > 0 { + _p0 = unsafe.Pointer(&tv[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FUTIMES<<4, uintptr(fd), uintptr(_p0), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FutimesAddr() *(func(fd int, tv []Timeval) (err error)) + +var Futimes = enter_Futimes + +func enter_Futimes(fd int, tv []Timeval) (err error) { + funcref := get_FutimesAddr() + if funcptrtest(GetZosLibVec()+SYS_FUTIMES<<4, "") == 0 { + *funcref = impl_Futimes + } else { + *funcref = error_Futimes + } + return (*funcref)(fd, tv) +} + +func error_Futimes(fd int, tv []Timeval) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(tv) > 0 { + _p1 = unsafe.Pointer(&tv[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FUTIMESAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FutimesatAddr() *(func(dirfd int, path string, tv []Timeval) (err error)) + +var Futimesat = enter_Futimesat + +func enter_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + funcref := get_FutimesatAddr() + if funcptrtest(GetZosLibVec()+SYS___FUTIMESAT_A<<4, "") == 0 { + *funcref = impl_Futimesat + } else { + *funcref = error_Futimesat + } + return (*funcref)(dirfd, path, tv) +} + +func error_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FTRUNCATE<<4, uintptr(fd), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Getrandom(buf []byte, flags int) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRANDOM<<4, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_GetrandomAddr() *(func(buf []byte, flags int) (n int, err error)) + +var Getrandom = enter_Getrandom + +func enter_Getrandom(buf []byte, flags int) (n int, err error) { + funcref := get_GetrandomAddr() + if funcptrtest(GetZosLibVec()+SYS_GETRANDOM<<4, "") == 0 { + *funcref = impl_Getrandom + } else { + *funcref = error_Getrandom + } + return (*funcref)(buf, flags) +} + +func error_Getrandom(buf []byte, flags int) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyInit() (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_INOTIFY_INIT<<4) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyInitAddr() *(func() (fd int, err error)) + +var InotifyInit = enter_InotifyInit + +func enter_InotifyInit() (fd int, err error) { + funcref := get_InotifyInitAddr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT<<4, "") == 0 { + *funcref = impl_InotifyInit + } else { + *funcref = error_InotifyInit + } + return (*funcref)() +} + +func error_InotifyInit() (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyInit1(flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyInit1Addr() *(func(flags int) (fd int, err error)) + +var InotifyInit1 = enter_InotifyInit1 + +func enter_InotifyInit1(flags int) (fd int, err error) { + funcref := get_InotifyInit1Addr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, "") == 0 { + *funcref = impl_InotifyInit1 + } else { + *funcref = error_InotifyInit1 + } + return (*funcref)(flags) +} + +func error_InotifyInit1(flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(pathname) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask)) + runtime.ExitSyscall() + watchdesc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyAddWatchAddr() *(func(fd int, pathname string, mask uint32) (watchdesc int, err error)) + +var InotifyAddWatch = enter_InotifyAddWatch + +func enter_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + funcref := get_InotifyAddWatchAddr() + if funcptrtest(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, "") == 0 { + *funcref = impl_InotifyAddWatch + } else { + *funcref = error_InotifyAddWatch + } + return (*funcref)(fd, pathname, mask) +} + +func error_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + watchdesc = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, uintptr(fd), uintptr(watchdesc)) + runtime.ExitSyscall() + success = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyRmWatchAddr() *(func(fd int, watchdesc uint32) (success int, err error)) + +var InotifyRmWatch = enter_InotifyRmWatch + +func enter_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + funcref := get_InotifyRmWatchAddr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, "") == 0 { + *funcref = impl_InotifyRmWatch + } else { + *funcref = error_InotifyRmWatch + } + return (*funcref)(fd, watchdesc) +} + +func error_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + success = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Listxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_ListxattrAddr() *(func(path string, dest []byte) (sz int, err error)) + +var Listxattr = enter_Listxattr + +func enter_Listxattr(path string, dest []byte) (sz int, err error) { + funcref := get_ListxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LISTXATTR_A<<4, "") == 0 { + *funcref = impl_Listxattr + } else { + *funcref = error_Listxattr + } + return (*funcref)(path, dest) +} + +func error_Listxattr(path string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LLISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LlistxattrAddr() *(func(path string, dest []byte) (sz int, err error)) + +var Llistxattr = enter_Llistxattr + +func enter_Llistxattr(path string, dest []byte) (sz int, err error) { + funcref := get_LlistxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LLISTXATTR_A<<4, "") == 0 { + *funcref = impl_Llistxattr + } else { + *funcref = error_Llistxattr + } + return (*funcref)(path, dest) +} + +func error_Llistxattr(path string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LremovexattrAddr() *(func(path string, attr string) (err error)) + +var Lremovexattr = enter_Lremovexattr + +func enter_Lremovexattr(path string, attr string) (err error) { + funcref := get_LremovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Lremovexattr + } else { + *funcref = error_Lremovexattr + } + return (*funcref)(path, attr) +} + +func error_Lremovexattr(path string, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lutimes(path string, tv []Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(tv) > 0 { + _p1 = unsafe.Pointer(&tv[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LUTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LutimesAddr() *(func(path string, tv []Timeval) (err error)) + +var Lutimes = enter_Lutimes + +func enter_Lutimes(path string, tv []Timeval) (err error) { + funcref := get_LutimesAddr() + if funcptrtest(GetZosLibVec()+SYS___LUTIMES_A<<4, "") == 0 { + *funcref = impl_Lutimes + } else { + *funcref = error_Lutimes + } + return (*funcref)(path, tv) +} + +func error_Lutimes(path string, tv []Timeval) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mprotect(b []byte, prot int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MPROTECT<<4, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Msync(b []byte, flags int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MSYNC<<4, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONSOLE2<<4, uintptr(unsafe.Pointer(cmsg)), uintptr(unsafe.Pointer(modstr)), uintptr(unsafe.Pointer(concmd))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Poll(fds []PollFd, timeout int) (n int, err error) { + var _p0 unsafe.Pointer + if len(fds) > 0 { + _p0 = unsafe.Pointer(&fds[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POLL<<4, uintptr(_p0), uintptr(len(fds)), uintptr(timeout)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_R_A<<4, uintptr(dirp), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Statfs(path string, buf *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STATFS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_StatfsAddr() *(func(path string, buf *Statfs_t) (err error)) + +var Statfs = enter_Statfs + +func enter_Statfs(path string, buf *Statfs_t) (err error) { + funcref := get_StatfsAddr() + if funcptrtest(GetZosLibVec()+SYS___STATFS_A<<4, "") == 0 { + *funcref = impl_Statfs + } else { + *funcref = error_Statfs + } + return (*funcref)(path, buf) +} + +func error_Statfs(path string, buf *Statfs_t) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Syncfs(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SYNCFS<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SyncfsAddr() *(func(fd int) (err error)) + +var Syncfs = enter_Syncfs + +func enter_Syncfs(fd int) (err error) { + funcref := get_SyncfsAddr() + if funcptrtest(GetZosLibVec()+SYS_SYNCFS<<4, "") == 0 { + *funcref = impl_Syncfs + } else { + *funcref = error_Syncfs + } + return (*funcref)(fd) +} + +func error_Syncfs(fd int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Times(tms *Tms) (ticks uintptr, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TIMES<<4, uintptr(unsafe.Pointer(tms))) + runtime.ExitSyscall() + ticks = uintptr(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func W_Getmntent(buff *byte, size int) (lastsys int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_GETMNTENT<<4, uintptr(unsafe.Pointer(buff)), uintptr(size)) + runtime.ExitSyscall() + lastsys = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func W_Getmntent_A(buff *byte, size int) (lastsys int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___W_GETMNTENT_A<<4, uintptr(unsafe.Pointer(buff)), uintptr(size)) + runtime.ExitSyscall() + lastsys = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(filesystem) + if err != nil { + return + } + var _p2 *byte + _p2, err = BytePtrFromString(fstype) + if err != nil { + return + } + var _p3 *byte + _p3, err = BytePtrFromString(parm) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unmount_LE(filesystem string, mtm int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(filesystem) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mtm)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHROOT_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SELECT<<4, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout))) + runtime.ExitSyscall() + ret = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Uname(buf *Utsname) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____OSNAME_A<<4, uintptr(unsafe.Pointer(buf))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Unshare(flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNSHARE<<4, uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnshareAddr() *(func(flags int) (err error)) + +var Unshare = enter_Unshare + +func enter_Unshare(flags int) (err error) { + funcref := get_UnshareAddr() + if funcptrtest(GetZosLibVec()+SYS_UNSHARE<<4, "") == 0 { + *funcref = impl_Unshare + } else { + *funcref = error_Unshare + } + return (*funcref)(flags) +} + +func error_Unshare(flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gethostname(buf []byte) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETGID<<4) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpid() (pid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPID<<4) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgid(pid int) (pgid int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPGID<<4, uintptr(pid)) + pgid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getppid() (pid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPPID<<4) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpriority(which int, who int) (prio int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPRIORITY<<4, uintptr(which), uintptr(who)) + runtime.ExitSyscall() + prio = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrlimit(resource int, rlim *Rlimit) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(rlim))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getrusage(who int, rusage *rusage_zos) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRUSAGE<<4, uintptr(who), uintptr(unsafe.Pointer(rusage))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEGID<<4) + runtime.ExitSyscall() + egid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (euid int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEUID<<4) + runtime.ExitSyscall() + euid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSID<<4, uintptr(pid)) + sid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETUID<<4) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kill(pid int, sig Signal) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_KILL<<4, uintptr(pid), uintptr(sig)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LCHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Link(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldPath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newPath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINKAT_A<<4, uintptr(oldDirFd), uintptr(unsafe.Pointer(_p0)), uintptr(newDirFd), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LinkatAddr() *(func(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error)) + +var Linkat = enter_Linkat + +func enter_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + funcref := get_LinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___LINKAT_A<<4, "") == 0 { + *funcref = impl_Linkat + } else { + *funcref = error_Linkat + } + return (*funcref)(oldDirFd, oldPath, newDirFd, newPath, flags) +} + +func error_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, n int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LISTEN<<4, uintptr(s), uintptr(n)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lstat(path string, stat *Stat_LE_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSTAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdir(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIRAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MkdiratAddr() *(func(dirfd int, path string, mode uint32) (err error)) + +var Mkdirat = enter_Mkdirat + +func enter_Mkdirat(dirfd int, path string, mode uint32) (err error) { + funcref := get_MkdiratAddr() + if funcptrtest(GetZosLibVec()+SYS___MKDIRAT_A<<4, "") == 0 { + *funcref = impl_Mkdirat + } else { + *funcref = error_Mkdirat + } + return (*funcref)(dirfd, path, mode) +} + +func error_Mkdirat(dirfd int, path string, mode uint32) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifo(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFO_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknod(path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MknodatAddr() *(func(dirfd int, path string, mode uint32, dev int) (err error)) + +var Mknodat = enter_Mknodat + +func enter_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + funcref := get_MknodatAddr() + if funcptrtest(GetZosLibVec()+SYS___MKNODAT_A<<4, "") == 0 { + *funcref = impl_Mknodat + } else { + *funcref = error_Mknodat + } + return (*funcref)(dirfd, path, mode, dev) +} + +func error_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_PivotRoot(newroot string, oldroot string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(newroot) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(oldroot) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_PivotRootAddr() *(func(newroot string, oldroot string) (err error)) + +var PivotRoot = enter_PivotRoot + +func enter_PivotRoot(newroot string, oldroot string) (err error) { + funcref := get_PivotRootAddr() + if funcptrtest(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, "") == 0 { + *funcref = impl_PivotRoot + } else { + *funcref = error_PivotRoot + } + return (*funcref)(newroot, oldroot) +} + +func error_PivotRoot(newroot string, oldroot string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PREAD<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PWRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PRCTL_A<<4, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_PrctlAddr() *(func(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)) + +var Prctl = enter_Prctl + +func enter_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + funcref := get_PrctlAddr() + if funcptrtest(GetZosLibVec()+SYS___PRCTL_A<<4, "") == 0 { + *funcref = impl_Prctl + } else { + *funcref = error_Prctl + } + return (*funcref)(option, arg2, arg3, arg4, arg5) +} + +func error_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PRLIMIT<<4, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_PrlimitAddr() *(func(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error)) + +var Prlimit = enter_Prlimit + +func enter_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + funcref := get_PrlimitAddr() + if funcptrtest(GetZosLibVec()+SYS_PRLIMIT<<4, "") == 0 { + *funcref = impl_Prlimit + } else { + *funcref = error_Prlimit + } + return (*funcref)(pid, resource, newlimit, old) +} + +func error_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rename(from string, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_RenameatAddr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)) + +var Renameat = enter_Renameat + +func enter_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + funcref := get_RenameatAddr() + if funcptrtest(GetZosLibVec()+SYS___RENAMEAT_A<<4, "") == 0 { + *funcref = impl_Renameat + } else { + *funcref = error_Renameat + } + return (*funcref)(olddirfd, oldpath, newdirfd, newpath) +} + +func error_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT2_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Renameat2Addr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)) + +var Renameat2 = enter_Renameat2 + +func enter_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + funcref := get_Renameat2Addr() + if funcptrtest(GetZosLibVec()+SYS___RENAMEAT2_A<<4, "") == 0 { + *funcref = impl_Renameat2 + } else { + *funcref = error_Renameat2 + } + return (*funcref)(olddirfd, oldpath, newdirfd, newpath, flags) +} + +func error_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rmdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RMDIR_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seek(fd int, offset int64, whence int) (off int64, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LSEEK<<4, uintptr(fd), uintptr(offset), uintptr(whence)) + runtime.ExitSyscall() + off = int64(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setegid(egid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEGID<<4, uintptr(egid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEUID<<4, uintptr(euid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Sethostname(p []byte) (err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SethostnameAddr() *(func(p []byte) (err error)) + +var Sethostname = enter_Sethostname + +func enter_Sethostname(p []byte) (err error) { + funcref := get_SethostnameAddr() + if funcptrtest(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, "") == 0 { + *funcref = impl_Sethostname + } else { + *funcref = error_Sethostname + } + return (*funcref)(p) +} + +func error_Sethostname(p []byte) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Setns(fd int, nstype int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETNS<<4, uintptr(fd), uintptr(nstype)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SetnsAddr() *(func(fd int, nstype int) (err error)) + +var Setns = enter_Setns + +func enter_Setns(fd int, nstype int) (err error) { + funcref := get_SetnsAddr() + if funcptrtest(GetZosLibVec()+SYS_SETNS<<4, "") == 0 { + *funcref = impl_Setns + } else { + *funcref = error_Setns + } + return (*funcref)(fd, nstype) +} + +func error_Setns(fd int, nstype int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpriority(which int, who int, prio int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPRIORITY<<4, uintptr(which), uintptr(who), uintptr(prio)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpgid(pid int, pgid int) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPGID<<4, uintptr(pid), uintptr(pgid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setrlimit(resource int, lim *Rlimit) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(lim))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setregid(rgid int, egid int) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREGID<<4, uintptr(rgid), uintptr(egid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setreuid(ruid int, euid int) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREUID<<4, uintptr(ruid), uintptr(euid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setsid() (pid int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_SETSID<<4) + pid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setuid(uid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETUID<<4, uintptr(uid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setgid(uid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGID<<4, uintptr(uid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Shutdown(fd int, how int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHUTDOWN<<4, uintptr(fd), uintptr(how)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func stat(path string, statLE *Stat_LE_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlink(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldPath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newPath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINKAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(dirfd), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SymlinkatAddr() *(func(oldPath string, dirfd int, newPath string) (err error)) + +var Symlinkat = enter_Symlinkat + +func enter_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + funcref := get_SymlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___SYMLINKAT_A<<4, "") == 0 { + *funcref = impl_Symlinkat + } else { + *funcref = error_Symlinkat + } + return (*funcref)(oldPath, dirfd, newPath) +} + +func error_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Sync() { + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec() + SYS_SYNC<<4) + runtime.ExitSyscall() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___TRUNCATE_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Tcgetattr(fildes int, termptr *Termios) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCGETATTR<<4, uintptr(fildes), uintptr(unsafe.Pointer(termptr))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Tcsetattr(fildes int, when int, termptr *Termios) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCSETATTR<<4, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Umask(mask int) (oldmask int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec()+SYS_UMASK<<4, uintptr(mask)) + runtime.ExitSyscall() + oldmask = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlink(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINK_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnlinkatAddr() *(func(dirfd int, path string, flags int) (err error)) + +var Unlinkat = enter_Unlinkat + +func enter_Unlinkat(dirfd int, path string, flags int) (err error) { + funcref := get_UnlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___UNLINKAT_A<<4, "") == 0 { + *funcref = impl_Unlinkat + } else { + *funcref = error_Unlinkat + } + return (*funcref)(dirfd, path, flags) +} + +func error_Unlinkat(dirfd int, path string, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Utime(path string, utim *Utimbuf) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func open(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPEN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_openatAddr() *(func(dirfd int, path string, flags int, mode uint32) (fd int, err error)) + +var openat = enter_openat + +func enter_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + funcref := get_openatAddr() + if funcptrtest(GetZosLibVec()+SYS___OPENAT_A<<4, "") == 0 { + *funcref = impl_openat + } else { + *funcref = error_openat + } + return (*funcref)(dirfd, path, flags, mode) +} + +func error_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT2_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(open_how)), uintptr(size)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_openat2Addr() *(func(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error)) + +var openat2 = enter_openat2 + +func enter_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + funcref := get_openat2Addr() + if funcptrtest(GetZosLibVec()+SYS___OPENAT2_A<<4, "") == 0 { + *funcref = impl_openat2 + } else { + *funcref = error_openat2 + } + return (*funcref)(dirfd, path, open_how, size) +} + +func error_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func remove(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_REMOVE<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func waitid(idType int, id int, info *Siginfo, options int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITID<<4, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITPID<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options)) + runtime.ExitSyscall() + wpid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func gettimeofday(tv *timeval_zos) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETTIMEOFDAY<<4, uintptr(unsafe.Pointer(tv))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]_C_int) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE<<4, uintptr(unsafe.Pointer(p))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimes(path string, timeval *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMENSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(ts)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_utimensatAddr() *(func(dirfd int, path string, ts *[2]Timespec, flags int) (err error)) + +var utimensat = enter_utimensat + +func enter_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + funcref := get_utimensatAddr() + if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 { + *funcref = impl_utimensat + } else { + *funcref = error_utimensat + } + return (*funcref)(dirfd, path, ts, flags) +} + +func error_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Posix_openpt(oflag int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POSIX_OPENPT<<4, uintptr(oflag)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Grantpt(fildes int) (rc int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GRANTPT<<4, uintptr(fildes)) + runtime.ExitSyscall() + rc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlockpt(fildes int) (rc int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNLOCKPT<<4, uintptr(fildes)) + runtime.ExitSyscall() + rc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go index 37dcc74..3a58ae8 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go @@ -1,7 +1,7 @@ -// mksysctl_openbsd.pl +// go run mksysctl_openbsd.go // Code generated by the command above; DO NOT EDIT. -// +build 386,openbsd +//go:build 386 && openbsd package unix @@ -16,6 +16,7 @@ var sysctlMib = []mibentry{ {"ddb.max_line", []_C_int{9, 3}}, {"ddb.max_width", []_C_int{9, 2}}, {"ddb.panic", []_C_int{9, 5}}, + {"ddb.profile", []_C_int{9, 9}}, {"ddb.radix", []_C_int{9, 1}}, {"ddb.tab_stop_width", []_C_int{9, 4}}, {"ddb.trigger", []_C_int{9, 8}}, @@ -30,30 +31,39 @@ var sysctlMib = []mibentry{ {"hw.model", []_C_int{6, 2}}, {"hw.ncpu", []_C_int{6, 3}}, {"hw.ncpufound", []_C_int{6, 21}}, + {"hw.ncpuonline", []_C_int{6, 25}}, {"hw.pagesize", []_C_int{6, 7}}, + {"hw.perfpolicy", []_C_int{6, 23}}, {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, {"hw.product", []_C_int{6, 15}}, {"hw.serialno", []_C_int{6, 17}}, {"hw.setperf", []_C_int{6, 13}}, + {"hw.smt", []_C_int{6, 24}}, {"hw.usermem", []_C_int{6, 20}}, {"hw.uuid", []_C_int{6, 18}}, {"hw.vendor", []_C_int{6, 14}}, {"hw.version", []_C_int{6, 16}}, - {"kern.arandom", []_C_int{1, 37}}, + {"kern.allowdt", []_C_int{1, 65}}, + {"kern.allowkmem", []_C_int{1, 52}}, {"kern.argmax", []_C_int{1, 8}}, + {"kern.audio", []_C_int{1, 84}}, {"kern.boottime", []_C_int{1, 21}}, {"kern.bufcachepercent", []_C_int{1, 72}}, {"kern.ccpu", []_C_int{1, 45}}, {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, {"kern.consdev", []_C_int{1, 75}}, {"kern.cp_time", []_C_int{1, 40}}, {"kern.cp_time2", []_C_int{1, 71}}, - {"kern.cryptodevallowsoft", []_C_int{1, 53}}, + {"kern.cpustats", []_C_int{1, 85}}, {"kern.domainname", []_C_int{1, 22}}, {"kern.file", []_C_int{1, 73}}, {"kern.forkstat", []_C_int{1, 42}}, {"kern.fscale", []_C_int{1, 46}}, {"kern.fsync", []_C_int{1, 33}}, + {"kern.global_ptrace", []_C_int{1, 81}}, {"kern.hostid", []_C_int{1, 11}}, {"kern.hostname", []_C_int{1, 10}}, {"kern.intrcnt.nintrcnt", []_C_int{1, 63, 1}}, @@ -76,17 +86,16 @@ var sysctlMib = []mibentry{ {"kern.ngroups", []_C_int{1, 18}}, {"kern.nosuidcoredump", []_C_int{1, 32}}, {"kern.nprocs", []_C_int{1, 47}}, - {"kern.nselcoll", []_C_int{1, 43}}, {"kern.nthreads", []_C_int{1, 26}}, {"kern.numvnodes", []_C_int{1, 58}}, {"kern.osrelease", []_C_int{1, 2}}, {"kern.osrevision", []_C_int{1, 3}}, {"kern.ostype", []_C_int{1, 1}}, {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, {"kern.pool_debug", []_C_int{1, 77}}, {"kern.posix1version", []_C_int{1, 17}}, {"kern.proc", []_C_int{1, 66}}, - {"kern.random", []_C_int{1, 31}}, {"kern.rawpartition", []_C_int{1, 24}}, {"kern.saved_ids", []_C_int{1, 20}}, {"kern.securelevel", []_C_int{1, 9}}, @@ -104,21 +113,20 @@ var sysctlMib = []mibentry{ {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, {"kern.timecounter.tick", []_C_int{1, 69, 1}}, {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, - {"kern.tty.maxptys", []_C_int{1, 44, 6}}, - {"kern.tty.nptys", []_C_int{1, 44, 7}}, + {"kern.timeout_stats", []_C_int{1, 87}}, {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, {"kern.ttycount", []_C_int{1, 57}}, - {"kern.userasymcrypto", []_C_int{1, 60}}, - {"kern.usercrypto", []_C_int{1, 52}}, - {"kern.usermount", []_C_int{1, 30}}, + {"kern.utc_offset", []_C_int{1, 88}}, {"kern.version", []_C_int{1, 4}}, - {"kern.vnode", []_C_int{1, 13}}, + {"kern.video", []_C_int{1, 89}}, {"kern.watchdog.auto", []_C_int{1, 64, 2}}, {"kern.watchdog.period", []_C_int{1, 64, 1}}, + {"kern.witnesswatch", []_C_int{1, 53}}, + {"kern.wxabort", []_C_int{1, 74}}, {"net.bpf.bufsize", []_C_int{4, 31, 1}}, {"net.bpf.maxbufsize", []_C_int{4, 31, 2}}, {"net.inet.ah.enable", []_C_int{4, 2, 51, 1}}, @@ -146,7 +154,9 @@ var sysctlMib = []mibentry{ {"net.inet.icmp.stats", []_C_int{4, 2, 1, 7}}, {"net.inet.icmp.tstamprepl", []_C_int{4, 2, 1, 6}}, {"net.inet.igmp.stats", []_C_int{4, 2, 2, 1}}, + {"net.inet.ip.arpdown", []_C_int{4, 2, 0, 40}}, {"net.inet.ip.arpqueued", []_C_int{4, 2, 0, 36}}, + {"net.inet.ip.arptimeout", []_C_int{4, 2, 0, 39}}, {"net.inet.ip.encdebug", []_C_int{4, 2, 0, 12}}, {"net.inet.ip.forwarding", []_C_int{4, 2, 0, 1}}, {"net.inet.ip.ifq.congestion", []_C_int{4, 2, 0, 30, 4}}, @@ -155,8 +165,10 @@ var sysctlMib = []mibentry{ {"net.inet.ip.ifq.maxlen", []_C_int{4, 2, 0, 30, 2}}, {"net.inet.ip.maxqueue", []_C_int{4, 2, 0, 11}}, {"net.inet.ip.mforwarding", []_C_int{4, 2, 0, 31}}, + {"net.inet.ip.mrtmfc", []_C_int{4, 2, 0, 37}}, {"net.inet.ip.mrtproto", []_C_int{4, 2, 0, 34}}, {"net.inet.ip.mrtstats", []_C_int{4, 2, 0, 35}}, + {"net.inet.ip.mrtvif", []_C_int{4, 2, 0, 38}}, {"net.inet.ip.mtu", []_C_int{4, 2, 0, 4}}, {"net.inet.ip.mtudisc", []_C_int{4, 2, 0, 27}}, {"net.inet.ip.mtudisctimeout", []_C_int{4, 2, 0, 28}}, @@ -173,9 +185,7 @@ var sysctlMib = []mibentry{ {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, - {"net.inet.mobileip.allow", []_C_int{4, 2, 55, 1}}, {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, - {"net.inet.pim.stats", []_C_int{4, 2, 103, 1}}, {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, {"net.inet.tcp.baddynamic", []_C_int{4, 2, 6, 6}}, @@ -189,6 +199,7 @@ var sysctlMib = []mibentry{ {"net.inet.tcp.reasslimit", []_C_int{4, 2, 6, 18}}, {"net.inet.tcp.rfc1323", []_C_int{4, 2, 6, 1}}, {"net.inet.tcp.rfc3390", []_C_int{4, 2, 6, 17}}, + {"net.inet.tcp.rootonly", []_C_int{4, 2, 6, 24}}, {"net.inet.tcp.rstppslimit", []_C_int{4, 2, 6, 12}}, {"net.inet.tcp.sack", []_C_int{4, 2, 6, 10}}, {"net.inet.tcp.sackholelimit", []_C_int{4, 2, 6, 20}}, @@ -196,9 +207,12 @@ var sysctlMib = []mibentry{ {"net.inet.tcp.stats", []_C_int{4, 2, 6, 21}}, {"net.inet.tcp.synbucketlimit", []_C_int{4, 2, 6, 16}}, {"net.inet.tcp.syncachelimit", []_C_int{4, 2, 6, 15}}, + {"net.inet.tcp.synhashsize", []_C_int{4, 2, 6, 25}}, + {"net.inet.tcp.synuselimit", []_C_int{4, 2, 6, 23}}, {"net.inet.udp.baddynamic", []_C_int{4, 2, 17, 2}}, {"net.inet.udp.checksum", []_C_int{4, 2, 17, 1}}, {"net.inet.udp.recvspace", []_C_int{4, 2, 17, 3}}, + {"net.inet.udp.rootonly", []_C_int{4, 2, 17, 6}}, {"net.inet.udp.sendspace", []_C_int{4, 2, 17, 4}}, {"net.inet.udp.stats", []_C_int{4, 2, 17, 5}}, {"net.inet6.divert.recvspace", []_C_int{4, 24, 86, 1}}, @@ -211,13 +225,8 @@ var sysctlMib = []mibentry{ {"net.inet6.icmp6.nd6_delay", []_C_int{4, 24, 30, 8}}, {"net.inet6.icmp6.nd6_maxnudhint", []_C_int{4, 24, 30, 15}}, {"net.inet6.icmp6.nd6_mmaxtries", []_C_int{4, 24, 30, 10}}, - {"net.inet6.icmp6.nd6_prune", []_C_int{4, 24, 30, 6}}, {"net.inet6.icmp6.nd6_umaxtries", []_C_int{4, 24, 30, 9}}, - {"net.inet6.icmp6.nd6_useloopback", []_C_int{4, 24, 30, 11}}, - {"net.inet6.icmp6.nodeinfo", []_C_int{4, 24, 30, 13}}, - {"net.inet6.icmp6.rediraccept", []_C_int{4, 24, 30, 2}}, {"net.inet6.icmp6.redirtimeout", []_C_int{4, 24, 30, 3}}, - {"net.inet6.ip6.accept_rtadv", []_C_int{4, 24, 17, 12}}, {"net.inet6.ip6.auto_flowlabel", []_C_int{4, 24, 17, 17}}, {"net.inet6.ip6.dad_count", []_C_int{4, 24, 17, 16}}, {"net.inet6.ip6.dad_pending", []_C_int{4, 24, 17, 49}}, @@ -230,20 +239,19 @@ var sysctlMib = []mibentry{ {"net.inet6.ip6.maxdynroutes", []_C_int{4, 24, 17, 48}}, {"net.inet6.ip6.maxfragpackets", []_C_int{4, 24, 17, 9}}, {"net.inet6.ip6.maxfrags", []_C_int{4, 24, 17, 41}}, - {"net.inet6.ip6.maxifdefrouters", []_C_int{4, 24, 17, 47}}, - {"net.inet6.ip6.maxifprefixes", []_C_int{4, 24, 17, 46}}, {"net.inet6.ip6.mforwarding", []_C_int{4, 24, 17, 42}}, + {"net.inet6.ip6.mrtmfc", []_C_int{4, 24, 17, 53}}, + {"net.inet6.ip6.mrtmif", []_C_int{4, 24, 17, 52}}, {"net.inet6.ip6.mrtproto", []_C_int{4, 24, 17, 8}}, {"net.inet6.ip6.mtudisctimeout", []_C_int{4, 24, 17, 50}}, {"net.inet6.ip6.multicast_mtudisc", []_C_int{4, 24, 17, 44}}, {"net.inet6.ip6.multipath", []_C_int{4, 24, 17, 43}}, {"net.inet6.ip6.neighborgcthresh", []_C_int{4, 24, 17, 45}}, {"net.inet6.ip6.redirect", []_C_int{4, 24, 17, 2}}, - {"net.inet6.ip6.rr_prune", []_C_int{4, 24, 17, 22}}, + {"net.inet6.ip6.soiikey", []_C_int{4, 24, 17, 54}}, {"net.inet6.ip6.sourcecheck", []_C_int{4, 24, 17, 10}}, {"net.inet6.ip6.sourcecheck_logint", []_C_int{4, 24, 17, 11}}, {"net.inet6.ip6.use_deprecated", []_C_int{4, 24, 17, 21}}, - {"net.inet6.ip6.v6only", []_C_int{4, 24, 17, 24}}, {"net.key.sadb_dump", []_C_int{4, 30, 1}}, {"net.key.spd_dump", []_C_int{4, 30, 2}}, {"net.mpls.ifq.congestion", []_C_int{4, 33, 3, 4}}, @@ -252,12 +260,12 @@ var sysctlMib = []mibentry{ {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, - {"net.mpls.maxloop_inkernel", []_C_int{4, 33, 4}}, {"net.mpls.ttl", []_C_int{4, 33, 2}}, {"net.pflow.stats", []_C_int{4, 34, 1}}, {"net.pipex.enable", []_C_int{4, 35, 1}}, {"vm.anonmin", []_C_int{2, 7}}, {"vm.loadavg", []_C_int{2, 2}}, + {"vm.malloc_conf", []_C_int{2, 12}}, {"vm.maxslp", []_C_int{2, 10}}, {"vm.nkmempages", []_C_int{2, 6}}, {"vm.psstrings", []_C_int{2, 3}}, diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go index fe6caa6..dcb7a0e 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go @@ -1,7 +1,7 @@ // go run mksysctl_openbsd.go // Code generated by the command above; DO NOT EDIT. -// +build amd64,openbsd +//go:build amd64 && openbsd package unix @@ -31,26 +31,33 @@ var sysctlMib = []mibentry{ {"hw.model", []_C_int{6, 2}}, {"hw.ncpu", []_C_int{6, 3}}, {"hw.ncpufound", []_C_int{6, 21}}, + {"hw.ncpuonline", []_C_int{6, 25}}, {"hw.pagesize", []_C_int{6, 7}}, {"hw.perfpolicy", []_C_int{6, 23}}, {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, {"hw.product", []_C_int{6, 15}}, {"hw.serialno", []_C_int{6, 17}}, {"hw.setperf", []_C_int{6, 13}}, + {"hw.smt", []_C_int{6, 24}}, {"hw.usermem", []_C_int{6, 20}}, {"hw.uuid", []_C_int{6, 18}}, {"hw.vendor", []_C_int{6, 14}}, {"hw.version", []_C_int{6, 16}}, + {"kern.allowdt", []_C_int{1, 65}}, {"kern.allowkmem", []_C_int{1, 52}}, {"kern.argmax", []_C_int{1, 8}}, + {"kern.audio", []_C_int{1, 84}}, {"kern.boottime", []_C_int{1, 21}}, {"kern.bufcachepercent", []_C_int{1, 72}}, {"kern.ccpu", []_C_int{1, 45}}, {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, {"kern.consdev", []_C_int{1, 75}}, {"kern.cp_time", []_C_int{1, 40}}, {"kern.cp_time2", []_C_int{1, 71}}, - {"kern.dnsjackport", []_C_int{1, 13}}, + {"kern.cpustats", []_C_int{1, 85}}, {"kern.domainname", []_C_int{1, 22}}, {"kern.file", []_C_int{1, 73}}, {"kern.forkstat", []_C_int{1, 42}}, @@ -79,13 +86,13 @@ var sysctlMib = []mibentry{ {"kern.ngroups", []_C_int{1, 18}}, {"kern.nosuidcoredump", []_C_int{1, 32}}, {"kern.nprocs", []_C_int{1, 47}}, - {"kern.nselcoll", []_C_int{1, 43}}, {"kern.nthreads", []_C_int{1, 26}}, {"kern.numvnodes", []_C_int{1, 58}}, {"kern.osrelease", []_C_int{1, 2}}, {"kern.osrevision", []_C_int{1, 3}}, {"kern.ostype", []_C_int{1, 1}}, {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, {"kern.pool_debug", []_C_int{1, 77}}, {"kern.posix1version", []_C_int{1, 17}}, {"kern.proc", []_C_int{1, 66}}, @@ -106,15 +113,19 @@ var sysctlMib = []mibentry{ {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, {"kern.timecounter.tick", []_C_int{1, 69, 1}}, {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, + {"kern.timeout_stats", []_C_int{1, 87}}, {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, {"kern.ttycount", []_C_int{1, 57}}, + {"kern.utc_offset", []_C_int{1, 88}}, {"kern.version", []_C_int{1, 4}}, + {"kern.video", []_C_int{1, 89}}, {"kern.watchdog.auto", []_C_int{1, 64, 2}}, {"kern.watchdog.period", []_C_int{1, 64, 1}}, + {"kern.witnesswatch", []_C_int{1, 53}}, {"kern.wxabort", []_C_int{1, 74}}, {"net.bpf.bufsize", []_C_int{4, 31, 1}}, {"net.bpf.maxbufsize", []_C_int{4, 31, 2}}, @@ -174,7 +185,6 @@ var sysctlMib = []mibentry{ {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, - {"net.inet.mobileip.allow", []_C_int{4, 2, 55, 1}}, {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, @@ -250,12 +260,12 @@ var sysctlMib = []mibentry{ {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, - {"net.mpls.maxloop_inkernel", []_C_int{4, 33, 4}}, {"net.mpls.ttl", []_C_int{4, 33, 2}}, {"net.pflow.stats", []_C_int{4, 34, 1}}, {"net.pipex.enable", []_C_int{4, 35, 1}}, {"vm.anonmin", []_C_int{2, 7}}, {"vm.loadavg", []_C_int{2, 2}}, + {"vm.malloc_conf", []_C_int{2, 12}}, {"vm.maxslp", []_C_int{2, 10}}, {"vm.nkmempages", []_C_int{2, 6}}, {"vm.psstrings", []_C_int{2, 3}}, diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go index 6eb8c0b..db5a7bf 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go @@ -1,7 +1,7 @@ // go run mksysctl_openbsd.go // Code generated by the command above; DO NOT EDIT. -// +build arm,openbsd +//go:build arm && openbsd package unix @@ -16,6 +16,7 @@ var sysctlMib = []mibentry{ {"ddb.max_line", []_C_int{9, 3}}, {"ddb.max_width", []_C_int{9, 2}}, {"ddb.panic", []_C_int{9, 5}}, + {"ddb.profile", []_C_int{9, 9}}, {"ddb.radix", []_C_int{9, 1}}, {"ddb.tab_stop_width", []_C_int{9, 4}}, {"ddb.trigger", []_C_int{9, 8}}, @@ -30,30 +31,39 @@ var sysctlMib = []mibentry{ {"hw.model", []_C_int{6, 2}}, {"hw.ncpu", []_C_int{6, 3}}, {"hw.ncpufound", []_C_int{6, 21}}, + {"hw.ncpuonline", []_C_int{6, 25}}, {"hw.pagesize", []_C_int{6, 7}}, + {"hw.perfpolicy", []_C_int{6, 23}}, {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, {"hw.product", []_C_int{6, 15}}, {"hw.serialno", []_C_int{6, 17}}, {"hw.setperf", []_C_int{6, 13}}, + {"hw.smt", []_C_int{6, 24}}, {"hw.usermem", []_C_int{6, 20}}, {"hw.uuid", []_C_int{6, 18}}, {"hw.vendor", []_C_int{6, 14}}, {"hw.version", []_C_int{6, 16}}, - {"kern.arandom", []_C_int{1, 37}}, + {"kern.allowdt", []_C_int{1, 65}}, + {"kern.allowkmem", []_C_int{1, 52}}, {"kern.argmax", []_C_int{1, 8}}, + {"kern.audio", []_C_int{1, 84}}, {"kern.boottime", []_C_int{1, 21}}, {"kern.bufcachepercent", []_C_int{1, 72}}, {"kern.ccpu", []_C_int{1, 45}}, {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, {"kern.consdev", []_C_int{1, 75}}, {"kern.cp_time", []_C_int{1, 40}}, {"kern.cp_time2", []_C_int{1, 71}}, - {"kern.cryptodevallowsoft", []_C_int{1, 53}}, + {"kern.cpustats", []_C_int{1, 85}}, {"kern.domainname", []_C_int{1, 22}}, {"kern.file", []_C_int{1, 73}}, {"kern.forkstat", []_C_int{1, 42}}, {"kern.fscale", []_C_int{1, 46}}, {"kern.fsync", []_C_int{1, 33}}, + {"kern.global_ptrace", []_C_int{1, 81}}, {"kern.hostid", []_C_int{1, 11}}, {"kern.hostname", []_C_int{1, 10}}, {"kern.intrcnt.nintrcnt", []_C_int{1, 63, 1}}, @@ -76,17 +86,16 @@ var sysctlMib = []mibentry{ {"kern.ngroups", []_C_int{1, 18}}, {"kern.nosuidcoredump", []_C_int{1, 32}}, {"kern.nprocs", []_C_int{1, 47}}, - {"kern.nselcoll", []_C_int{1, 43}}, {"kern.nthreads", []_C_int{1, 26}}, {"kern.numvnodes", []_C_int{1, 58}}, {"kern.osrelease", []_C_int{1, 2}}, {"kern.osrevision", []_C_int{1, 3}}, {"kern.ostype", []_C_int{1, 1}}, {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, {"kern.pool_debug", []_C_int{1, 77}}, {"kern.posix1version", []_C_int{1, 17}}, {"kern.proc", []_C_int{1, 66}}, - {"kern.random", []_C_int{1, 31}}, {"kern.rawpartition", []_C_int{1, 24}}, {"kern.saved_ids", []_C_int{1, 20}}, {"kern.securelevel", []_C_int{1, 9}}, @@ -104,21 +113,20 @@ var sysctlMib = []mibentry{ {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, {"kern.timecounter.tick", []_C_int{1, 69, 1}}, {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, - {"kern.tty.maxptys", []_C_int{1, 44, 6}}, - {"kern.tty.nptys", []_C_int{1, 44, 7}}, + {"kern.timeout_stats", []_C_int{1, 87}}, {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, {"kern.ttycount", []_C_int{1, 57}}, - {"kern.userasymcrypto", []_C_int{1, 60}}, - {"kern.usercrypto", []_C_int{1, 52}}, - {"kern.usermount", []_C_int{1, 30}}, + {"kern.utc_offset", []_C_int{1, 88}}, {"kern.version", []_C_int{1, 4}}, - {"kern.vnode", []_C_int{1, 13}}, + {"kern.video", []_C_int{1, 89}}, {"kern.watchdog.auto", []_C_int{1, 64, 2}}, {"kern.watchdog.period", []_C_int{1, 64, 1}}, + {"kern.witnesswatch", []_C_int{1, 53}}, + {"kern.wxabort", []_C_int{1, 74}}, {"net.bpf.bufsize", []_C_int{4, 31, 1}}, {"net.bpf.maxbufsize", []_C_int{4, 31, 2}}, {"net.inet.ah.enable", []_C_int{4, 2, 51, 1}}, @@ -146,7 +154,9 @@ var sysctlMib = []mibentry{ {"net.inet.icmp.stats", []_C_int{4, 2, 1, 7}}, {"net.inet.icmp.tstamprepl", []_C_int{4, 2, 1, 6}}, {"net.inet.igmp.stats", []_C_int{4, 2, 2, 1}}, + {"net.inet.ip.arpdown", []_C_int{4, 2, 0, 40}}, {"net.inet.ip.arpqueued", []_C_int{4, 2, 0, 36}}, + {"net.inet.ip.arptimeout", []_C_int{4, 2, 0, 39}}, {"net.inet.ip.encdebug", []_C_int{4, 2, 0, 12}}, {"net.inet.ip.forwarding", []_C_int{4, 2, 0, 1}}, {"net.inet.ip.ifq.congestion", []_C_int{4, 2, 0, 30, 4}}, @@ -155,8 +165,10 @@ var sysctlMib = []mibentry{ {"net.inet.ip.ifq.maxlen", []_C_int{4, 2, 0, 30, 2}}, {"net.inet.ip.maxqueue", []_C_int{4, 2, 0, 11}}, {"net.inet.ip.mforwarding", []_C_int{4, 2, 0, 31}}, + {"net.inet.ip.mrtmfc", []_C_int{4, 2, 0, 37}}, {"net.inet.ip.mrtproto", []_C_int{4, 2, 0, 34}}, {"net.inet.ip.mrtstats", []_C_int{4, 2, 0, 35}}, + {"net.inet.ip.mrtvif", []_C_int{4, 2, 0, 38}}, {"net.inet.ip.mtu", []_C_int{4, 2, 0, 4}}, {"net.inet.ip.mtudisc", []_C_int{4, 2, 0, 27}}, {"net.inet.ip.mtudisctimeout", []_C_int{4, 2, 0, 28}}, @@ -173,9 +185,7 @@ var sysctlMib = []mibentry{ {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, - {"net.inet.mobileip.allow", []_C_int{4, 2, 55, 1}}, {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, - {"net.inet.pim.stats", []_C_int{4, 2, 103, 1}}, {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, {"net.inet.tcp.baddynamic", []_C_int{4, 2, 6, 6}}, @@ -189,6 +199,7 @@ var sysctlMib = []mibentry{ {"net.inet.tcp.reasslimit", []_C_int{4, 2, 6, 18}}, {"net.inet.tcp.rfc1323", []_C_int{4, 2, 6, 1}}, {"net.inet.tcp.rfc3390", []_C_int{4, 2, 6, 17}}, + {"net.inet.tcp.rootonly", []_C_int{4, 2, 6, 24}}, {"net.inet.tcp.rstppslimit", []_C_int{4, 2, 6, 12}}, {"net.inet.tcp.sack", []_C_int{4, 2, 6, 10}}, {"net.inet.tcp.sackholelimit", []_C_int{4, 2, 6, 20}}, @@ -196,9 +207,12 @@ var sysctlMib = []mibentry{ {"net.inet.tcp.stats", []_C_int{4, 2, 6, 21}}, {"net.inet.tcp.synbucketlimit", []_C_int{4, 2, 6, 16}}, {"net.inet.tcp.syncachelimit", []_C_int{4, 2, 6, 15}}, + {"net.inet.tcp.synhashsize", []_C_int{4, 2, 6, 25}}, + {"net.inet.tcp.synuselimit", []_C_int{4, 2, 6, 23}}, {"net.inet.udp.baddynamic", []_C_int{4, 2, 17, 2}}, {"net.inet.udp.checksum", []_C_int{4, 2, 17, 1}}, {"net.inet.udp.recvspace", []_C_int{4, 2, 17, 3}}, + {"net.inet.udp.rootonly", []_C_int{4, 2, 17, 6}}, {"net.inet.udp.sendspace", []_C_int{4, 2, 17, 4}}, {"net.inet.udp.stats", []_C_int{4, 2, 17, 5}}, {"net.inet6.divert.recvspace", []_C_int{4, 24, 86, 1}}, @@ -211,13 +225,8 @@ var sysctlMib = []mibentry{ {"net.inet6.icmp6.nd6_delay", []_C_int{4, 24, 30, 8}}, {"net.inet6.icmp6.nd6_maxnudhint", []_C_int{4, 24, 30, 15}}, {"net.inet6.icmp6.nd6_mmaxtries", []_C_int{4, 24, 30, 10}}, - {"net.inet6.icmp6.nd6_prune", []_C_int{4, 24, 30, 6}}, {"net.inet6.icmp6.nd6_umaxtries", []_C_int{4, 24, 30, 9}}, - {"net.inet6.icmp6.nd6_useloopback", []_C_int{4, 24, 30, 11}}, - {"net.inet6.icmp6.nodeinfo", []_C_int{4, 24, 30, 13}}, - {"net.inet6.icmp6.rediraccept", []_C_int{4, 24, 30, 2}}, {"net.inet6.icmp6.redirtimeout", []_C_int{4, 24, 30, 3}}, - {"net.inet6.ip6.accept_rtadv", []_C_int{4, 24, 17, 12}}, {"net.inet6.ip6.auto_flowlabel", []_C_int{4, 24, 17, 17}}, {"net.inet6.ip6.dad_count", []_C_int{4, 24, 17, 16}}, {"net.inet6.ip6.dad_pending", []_C_int{4, 24, 17, 49}}, @@ -230,20 +239,19 @@ var sysctlMib = []mibentry{ {"net.inet6.ip6.maxdynroutes", []_C_int{4, 24, 17, 48}}, {"net.inet6.ip6.maxfragpackets", []_C_int{4, 24, 17, 9}}, {"net.inet6.ip6.maxfrags", []_C_int{4, 24, 17, 41}}, - {"net.inet6.ip6.maxifdefrouters", []_C_int{4, 24, 17, 47}}, - {"net.inet6.ip6.maxifprefixes", []_C_int{4, 24, 17, 46}}, {"net.inet6.ip6.mforwarding", []_C_int{4, 24, 17, 42}}, + {"net.inet6.ip6.mrtmfc", []_C_int{4, 24, 17, 53}}, + {"net.inet6.ip6.mrtmif", []_C_int{4, 24, 17, 52}}, {"net.inet6.ip6.mrtproto", []_C_int{4, 24, 17, 8}}, {"net.inet6.ip6.mtudisctimeout", []_C_int{4, 24, 17, 50}}, {"net.inet6.ip6.multicast_mtudisc", []_C_int{4, 24, 17, 44}}, {"net.inet6.ip6.multipath", []_C_int{4, 24, 17, 43}}, {"net.inet6.ip6.neighborgcthresh", []_C_int{4, 24, 17, 45}}, {"net.inet6.ip6.redirect", []_C_int{4, 24, 17, 2}}, - {"net.inet6.ip6.rr_prune", []_C_int{4, 24, 17, 22}}, + {"net.inet6.ip6.soiikey", []_C_int{4, 24, 17, 54}}, {"net.inet6.ip6.sourcecheck", []_C_int{4, 24, 17, 10}}, {"net.inet6.ip6.sourcecheck_logint", []_C_int{4, 24, 17, 11}}, {"net.inet6.ip6.use_deprecated", []_C_int{4, 24, 17, 21}}, - {"net.inet6.ip6.v6only", []_C_int{4, 24, 17, 24}}, {"net.key.sadb_dump", []_C_int{4, 30, 1}}, {"net.key.spd_dump", []_C_int{4, 30, 2}}, {"net.mpls.ifq.congestion", []_C_int{4, 33, 3, 4}}, @@ -252,12 +260,12 @@ var sysctlMib = []mibentry{ {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, - {"net.mpls.maxloop_inkernel", []_C_int{4, 33, 4}}, {"net.mpls.ttl", []_C_int{4, 33, 2}}, {"net.pflow.stats", []_C_int{4, 34, 1}}, {"net.pipex.enable", []_C_int{4, 35, 1}}, {"vm.anonmin", []_C_int{2, 7}}, {"vm.loadavg", []_C_int{2, 2}}, + {"vm.malloc_conf", []_C_int{2, 12}}, {"vm.maxslp", []_C_int{2, 10}}, {"vm.nkmempages", []_C_int{2, 6}}, {"vm.psstrings", []_C_int{2, 3}}, diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go index ba4304f..7be575a 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go @@ -1,7 +1,7 @@ // go run mksysctl_openbsd.go // Code generated by the command above; DO NOT EDIT. -// +build arm64,openbsd +//go:build arm64 && openbsd package unix @@ -35,6 +35,7 @@ var sysctlMib = []mibentry{ {"hw.pagesize", []_C_int{6, 7}}, {"hw.perfpolicy", []_C_int{6, 23}}, {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, {"hw.product", []_C_int{6, 15}}, {"hw.serialno", []_C_int{6, 17}}, {"hw.setperf", []_C_int{6, 13}}, @@ -43,6 +44,7 @@ var sysctlMib = []mibentry{ {"hw.uuid", []_C_int{6, 18}}, {"hw.vendor", []_C_int{6, 14}}, {"hw.version", []_C_int{6, 16}}, + {"kern.allowdt", []_C_int{1, 65}}, {"kern.allowkmem", []_C_int{1, 52}}, {"kern.argmax", []_C_int{1, 8}}, {"kern.audio", []_C_int{1, 84}}, @@ -50,6 +52,8 @@ var sysctlMib = []mibentry{ {"kern.bufcachepercent", []_C_int{1, 72}}, {"kern.ccpu", []_C_int{1, 45}}, {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, {"kern.consdev", []_C_int{1, 75}}, {"kern.cp_time", []_C_int{1, 40}}, {"kern.cp_time2", []_C_int{1, 71}}, @@ -82,13 +86,13 @@ var sysctlMib = []mibentry{ {"kern.ngroups", []_C_int{1, 18}}, {"kern.nosuidcoredump", []_C_int{1, 32}}, {"kern.nprocs", []_C_int{1, 47}}, - {"kern.nselcoll", []_C_int{1, 43}}, {"kern.nthreads", []_C_int{1, 26}}, {"kern.numvnodes", []_C_int{1, 58}}, {"kern.osrelease", []_C_int{1, 2}}, {"kern.osrevision", []_C_int{1, 3}}, {"kern.ostype", []_C_int{1, 1}}, {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, {"kern.pool_debug", []_C_int{1, 77}}, {"kern.posix1version", []_C_int{1, 17}}, {"kern.proc", []_C_int{1, 66}}, @@ -109,13 +113,16 @@ var sysctlMib = []mibentry{ {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, {"kern.timecounter.tick", []_C_int{1, 69, 1}}, {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, + {"kern.timeout_stats", []_C_int{1, 87}}, {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, {"kern.ttycount", []_C_int{1, 57}}, + {"kern.utc_offset", []_C_int{1, 88}}, {"kern.version", []_C_int{1, 4}}, + {"kern.video", []_C_int{1, 89}}, {"kern.watchdog.auto", []_C_int{1, 64, 2}}, {"kern.watchdog.period", []_C_int{1, 64, 1}}, {"kern.witnesswatch", []_C_int{1, 53}}, @@ -178,7 +185,6 @@ var sysctlMib = []mibentry{ {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, - {"net.inet.mobileip.allow", []_C_int{4, 2, 55, 1}}, {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, @@ -254,7 +260,6 @@ var sysctlMib = []mibentry{ {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, - {"net.mpls.maxloop_inkernel", []_C_int{4, 33, 4}}, {"net.mpls.ttl", []_C_int{4, 33, 2}}, {"net.pflow.stats", []_C_int{4, 34, 1}}, {"net.pipex.enable", []_C_int{4, 35, 1}}, diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go new file mode 100644 index 0000000..d6e3174 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go @@ -0,0 +1,280 @@ +// go run mksysctl_openbsd.go +// Code generated by the command above; DO NOT EDIT. + +//go:build mips64 && openbsd + +package unix + +type mibentry struct { + ctlname string + ctloid []_C_int +} + +var sysctlMib = []mibentry{ + {"ddb.console", []_C_int{9, 6}}, + {"ddb.log", []_C_int{9, 7}}, + {"ddb.max_line", []_C_int{9, 3}}, + {"ddb.max_width", []_C_int{9, 2}}, + {"ddb.panic", []_C_int{9, 5}}, + {"ddb.profile", []_C_int{9, 9}}, + {"ddb.radix", []_C_int{9, 1}}, + {"ddb.tab_stop_width", []_C_int{9, 4}}, + {"ddb.trigger", []_C_int{9, 8}}, + {"fs.posix.setuid", []_C_int{3, 1, 1}}, + {"hw.allowpowerdown", []_C_int{6, 22}}, + {"hw.byteorder", []_C_int{6, 4}}, + {"hw.cpuspeed", []_C_int{6, 12}}, + {"hw.diskcount", []_C_int{6, 10}}, + {"hw.disknames", []_C_int{6, 8}}, + {"hw.diskstats", []_C_int{6, 9}}, + {"hw.machine", []_C_int{6, 1}}, + {"hw.model", []_C_int{6, 2}}, + {"hw.ncpu", []_C_int{6, 3}}, + {"hw.ncpufound", []_C_int{6, 21}}, + {"hw.ncpuonline", []_C_int{6, 25}}, + {"hw.pagesize", []_C_int{6, 7}}, + {"hw.perfpolicy", []_C_int{6, 23}}, + {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, + {"hw.product", []_C_int{6, 15}}, + {"hw.serialno", []_C_int{6, 17}}, + {"hw.setperf", []_C_int{6, 13}}, + {"hw.smt", []_C_int{6, 24}}, + {"hw.usermem", []_C_int{6, 20}}, + {"hw.uuid", []_C_int{6, 18}}, + {"hw.vendor", []_C_int{6, 14}}, + {"hw.version", []_C_int{6, 16}}, + {"kern.allowdt", []_C_int{1, 65}}, + {"kern.allowkmem", []_C_int{1, 52}}, + {"kern.argmax", []_C_int{1, 8}}, + {"kern.audio", []_C_int{1, 84}}, + {"kern.boottime", []_C_int{1, 21}}, + {"kern.bufcachepercent", []_C_int{1, 72}}, + {"kern.ccpu", []_C_int{1, 45}}, + {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, + {"kern.consdev", []_C_int{1, 75}}, + {"kern.cp_time", []_C_int{1, 40}}, + {"kern.cp_time2", []_C_int{1, 71}}, + {"kern.cpustats", []_C_int{1, 85}}, + {"kern.domainname", []_C_int{1, 22}}, + {"kern.file", []_C_int{1, 73}}, + {"kern.forkstat", []_C_int{1, 42}}, + {"kern.fscale", []_C_int{1, 46}}, + {"kern.fsync", []_C_int{1, 33}}, + {"kern.global_ptrace", []_C_int{1, 81}}, + {"kern.hostid", []_C_int{1, 11}}, + {"kern.hostname", []_C_int{1, 10}}, + {"kern.intrcnt.nintrcnt", []_C_int{1, 63, 1}}, + {"kern.job_control", []_C_int{1, 19}}, + {"kern.malloc.buckets", []_C_int{1, 39, 1}}, + {"kern.malloc.kmemnames", []_C_int{1, 39, 3}}, + {"kern.maxclusters", []_C_int{1, 67}}, + {"kern.maxfiles", []_C_int{1, 7}}, + {"kern.maxlocksperuid", []_C_int{1, 70}}, + {"kern.maxpartitions", []_C_int{1, 23}}, + {"kern.maxproc", []_C_int{1, 6}}, + {"kern.maxthread", []_C_int{1, 25}}, + {"kern.maxvnodes", []_C_int{1, 5}}, + {"kern.mbstat", []_C_int{1, 59}}, + {"kern.msgbuf", []_C_int{1, 48}}, + {"kern.msgbufsize", []_C_int{1, 38}}, + {"kern.nchstats", []_C_int{1, 41}}, + {"kern.netlivelocks", []_C_int{1, 76}}, + {"kern.nfiles", []_C_int{1, 56}}, + {"kern.ngroups", []_C_int{1, 18}}, + {"kern.nosuidcoredump", []_C_int{1, 32}}, + {"kern.nprocs", []_C_int{1, 47}}, + {"kern.nthreads", []_C_int{1, 26}}, + {"kern.numvnodes", []_C_int{1, 58}}, + {"kern.osrelease", []_C_int{1, 2}}, + {"kern.osrevision", []_C_int{1, 3}}, + {"kern.ostype", []_C_int{1, 1}}, + {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, + {"kern.pool_debug", []_C_int{1, 77}}, + {"kern.posix1version", []_C_int{1, 17}}, + {"kern.proc", []_C_int{1, 66}}, + {"kern.rawpartition", []_C_int{1, 24}}, + {"kern.saved_ids", []_C_int{1, 20}}, + {"kern.securelevel", []_C_int{1, 9}}, + {"kern.seminfo", []_C_int{1, 61}}, + {"kern.shminfo", []_C_int{1, 62}}, + {"kern.somaxconn", []_C_int{1, 28}}, + {"kern.sominconn", []_C_int{1, 29}}, + {"kern.splassert", []_C_int{1, 54}}, + {"kern.stackgap_random", []_C_int{1, 50}}, + {"kern.sysvipc_info", []_C_int{1, 51}}, + {"kern.sysvmsg", []_C_int{1, 34}}, + {"kern.sysvsem", []_C_int{1, 35}}, + {"kern.sysvshm", []_C_int{1, 36}}, + {"kern.timecounter.choice", []_C_int{1, 69, 4}}, + {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, + {"kern.timecounter.tick", []_C_int{1, 69, 1}}, + {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, + {"kern.timeout_stats", []_C_int{1, 87}}, + {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, + {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, + {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, + {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, + {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, + {"kern.ttycount", []_C_int{1, 57}}, + {"kern.utc_offset", []_C_int{1, 88}}, + {"kern.version", []_C_int{1, 4}}, + {"kern.video", []_C_int{1, 89}}, + {"kern.watchdog.auto", []_C_int{1, 64, 2}}, + {"kern.watchdog.period", []_C_int{1, 64, 1}}, + {"kern.witnesswatch", []_C_int{1, 53}}, + {"kern.wxabort", []_C_int{1, 74}}, + {"net.bpf.bufsize", []_C_int{4, 31, 1}}, + {"net.bpf.maxbufsize", []_C_int{4, 31, 2}}, + {"net.inet.ah.enable", []_C_int{4, 2, 51, 1}}, + {"net.inet.ah.stats", []_C_int{4, 2, 51, 2}}, + {"net.inet.carp.allow", []_C_int{4, 2, 112, 1}}, + {"net.inet.carp.log", []_C_int{4, 2, 112, 3}}, + {"net.inet.carp.preempt", []_C_int{4, 2, 112, 2}}, + {"net.inet.carp.stats", []_C_int{4, 2, 112, 4}}, + {"net.inet.divert.recvspace", []_C_int{4, 2, 258, 1}}, + {"net.inet.divert.sendspace", []_C_int{4, 2, 258, 2}}, + {"net.inet.divert.stats", []_C_int{4, 2, 258, 3}}, + {"net.inet.esp.enable", []_C_int{4, 2, 50, 1}}, + {"net.inet.esp.stats", []_C_int{4, 2, 50, 4}}, + {"net.inet.esp.udpencap", []_C_int{4, 2, 50, 2}}, + {"net.inet.esp.udpencap_port", []_C_int{4, 2, 50, 3}}, + {"net.inet.etherip.allow", []_C_int{4, 2, 97, 1}}, + {"net.inet.etherip.stats", []_C_int{4, 2, 97, 2}}, + {"net.inet.gre.allow", []_C_int{4, 2, 47, 1}}, + {"net.inet.gre.wccp", []_C_int{4, 2, 47, 2}}, + {"net.inet.icmp.bmcastecho", []_C_int{4, 2, 1, 2}}, + {"net.inet.icmp.errppslimit", []_C_int{4, 2, 1, 3}}, + {"net.inet.icmp.maskrepl", []_C_int{4, 2, 1, 1}}, + {"net.inet.icmp.rediraccept", []_C_int{4, 2, 1, 4}}, + {"net.inet.icmp.redirtimeout", []_C_int{4, 2, 1, 5}}, + {"net.inet.icmp.stats", []_C_int{4, 2, 1, 7}}, + {"net.inet.icmp.tstamprepl", []_C_int{4, 2, 1, 6}}, + {"net.inet.igmp.stats", []_C_int{4, 2, 2, 1}}, + {"net.inet.ip.arpdown", []_C_int{4, 2, 0, 40}}, + {"net.inet.ip.arpqueued", []_C_int{4, 2, 0, 36}}, + {"net.inet.ip.arptimeout", []_C_int{4, 2, 0, 39}}, + {"net.inet.ip.encdebug", []_C_int{4, 2, 0, 12}}, + {"net.inet.ip.forwarding", []_C_int{4, 2, 0, 1}}, + {"net.inet.ip.ifq.congestion", []_C_int{4, 2, 0, 30, 4}}, + {"net.inet.ip.ifq.drops", []_C_int{4, 2, 0, 30, 3}}, + {"net.inet.ip.ifq.len", []_C_int{4, 2, 0, 30, 1}}, + {"net.inet.ip.ifq.maxlen", []_C_int{4, 2, 0, 30, 2}}, + {"net.inet.ip.maxqueue", []_C_int{4, 2, 0, 11}}, + {"net.inet.ip.mforwarding", []_C_int{4, 2, 0, 31}}, + {"net.inet.ip.mrtmfc", []_C_int{4, 2, 0, 37}}, + {"net.inet.ip.mrtproto", []_C_int{4, 2, 0, 34}}, + {"net.inet.ip.mrtstats", []_C_int{4, 2, 0, 35}}, + {"net.inet.ip.mrtvif", []_C_int{4, 2, 0, 38}}, + {"net.inet.ip.mtu", []_C_int{4, 2, 0, 4}}, + {"net.inet.ip.mtudisc", []_C_int{4, 2, 0, 27}}, + {"net.inet.ip.mtudisctimeout", []_C_int{4, 2, 0, 28}}, + {"net.inet.ip.multipath", []_C_int{4, 2, 0, 32}}, + {"net.inet.ip.portfirst", []_C_int{4, 2, 0, 7}}, + {"net.inet.ip.porthifirst", []_C_int{4, 2, 0, 9}}, + {"net.inet.ip.porthilast", []_C_int{4, 2, 0, 10}}, + {"net.inet.ip.portlast", []_C_int{4, 2, 0, 8}}, + {"net.inet.ip.redirect", []_C_int{4, 2, 0, 2}}, + {"net.inet.ip.sourceroute", []_C_int{4, 2, 0, 5}}, + {"net.inet.ip.stats", []_C_int{4, 2, 0, 33}}, + {"net.inet.ip.ttl", []_C_int{4, 2, 0, 3}}, + {"net.inet.ipcomp.enable", []_C_int{4, 2, 108, 1}}, + {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, + {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, + {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, + {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, + {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, + {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, + {"net.inet.tcp.baddynamic", []_C_int{4, 2, 6, 6}}, + {"net.inet.tcp.drop", []_C_int{4, 2, 6, 19}}, + {"net.inet.tcp.ecn", []_C_int{4, 2, 6, 14}}, + {"net.inet.tcp.ident", []_C_int{4, 2, 6, 9}}, + {"net.inet.tcp.keepidle", []_C_int{4, 2, 6, 3}}, + {"net.inet.tcp.keepinittime", []_C_int{4, 2, 6, 2}}, + {"net.inet.tcp.keepintvl", []_C_int{4, 2, 6, 4}}, + {"net.inet.tcp.mssdflt", []_C_int{4, 2, 6, 11}}, + {"net.inet.tcp.reasslimit", []_C_int{4, 2, 6, 18}}, + {"net.inet.tcp.rfc1323", []_C_int{4, 2, 6, 1}}, + {"net.inet.tcp.rfc3390", []_C_int{4, 2, 6, 17}}, + {"net.inet.tcp.rootonly", []_C_int{4, 2, 6, 24}}, + {"net.inet.tcp.rstppslimit", []_C_int{4, 2, 6, 12}}, + {"net.inet.tcp.sack", []_C_int{4, 2, 6, 10}}, + {"net.inet.tcp.sackholelimit", []_C_int{4, 2, 6, 20}}, + {"net.inet.tcp.slowhz", []_C_int{4, 2, 6, 5}}, + {"net.inet.tcp.stats", []_C_int{4, 2, 6, 21}}, + {"net.inet.tcp.synbucketlimit", []_C_int{4, 2, 6, 16}}, + {"net.inet.tcp.syncachelimit", []_C_int{4, 2, 6, 15}}, + {"net.inet.tcp.synhashsize", []_C_int{4, 2, 6, 25}}, + {"net.inet.tcp.synuselimit", []_C_int{4, 2, 6, 23}}, + {"net.inet.udp.baddynamic", []_C_int{4, 2, 17, 2}}, + {"net.inet.udp.checksum", []_C_int{4, 2, 17, 1}}, + {"net.inet.udp.recvspace", []_C_int{4, 2, 17, 3}}, + {"net.inet.udp.rootonly", []_C_int{4, 2, 17, 6}}, + {"net.inet.udp.sendspace", []_C_int{4, 2, 17, 4}}, + {"net.inet.udp.stats", []_C_int{4, 2, 17, 5}}, + {"net.inet6.divert.recvspace", []_C_int{4, 24, 86, 1}}, + {"net.inet6.divert.sendspace", []_C_int{4, 24, 86, 2}}, + {"net.inet6.divert.stats", []_C_int{4, 24, 86, 3}}, + {"net.inet6.icmp6.errppslimit", []_C_int{4, 24, 30, 14}}, + {"net.inet6.icmp6.mtudisc_hiwat", []_C_int{4, 24, 30, 16}}, + {"net.inet6.icmp6.mtudisc_lowat", []_C_int{4, 24, 30, 17}}, + {"net.inet6.icmp6.nd6_debug", []_C_int{4, 24, 30, 18}}, + {"net.inet6.icmp6.nd6_delay", []_C_int{4, 24, 30, 8}}, + {"net.inet6.icmp6.nd6_maxnudhint", []_C_int{4, 24, 30, 15}}, + {"net.inet6.icmp6.nd6_mmaxtries", []_C_int{4, 24, 30, 10}}, + {"net.inet6.icmp6.nd6_umaxtries", []_C_int{4, 24, 30, 9}}, + {"net.inet6.icmp6.redirtimeout", []_C_int{4, 24, 30, 3}}, + {"net.inet6.ip6.auto_flowlabel", []_C_int{4, 24, 17, 17}}, + {"net.inet6.ip6.dad_count", []_C_int{4, 24, 17, 16}}, + {"net.inet6.ip6.dad_pending", []_C_int{4, 24, 17, 49}}, + {"net.inet6.ip6.defmcasthlim", []_C_int{4, 24, 17, 18}}, + {"net.inet6.ip6.forwarding", []_C_int{4, 24, 17, 1}}, + {"net.inet6.ip6.forwsrcrt", []_C_int{4, 24, 17, 5}}, + {"net.inet6.ip6.hdrnestlimit", []_C_int{4, 24, 17, 15}}, + {"net.inet6.ip6.hlim", []_C_int{4, 24, 17, 3}}, + {"net.inet6.ip6.log_interval", []_C_int{4, 24, 17, 14}}, + {"net.inet6.ip6.maxdynroutes", []_C_int{4, 24, 17, 48}}, + {"net.inet6.ip6.maxfragpackets", []_C_int{4, 24, 17, 9}}, + {"net.inet6.ip6.maxfrags", []_C_int{4, 24, 17, 41}}, + {"net.inet6.ip6.mforwarding", []_C_int{4, 24, 17, 42}}, + {"net.inet6.ip6.mrtmfc", []_C_int{4, 24, 17, 53}}, + {"net.inet6.ip6.mrtmif", []_C_int{4, 24, 17, 52}}, + {"net.inet6.ip6.mrtproto", []_C_int{4, 24, 17, 8}}, + {"net.inet6.ip6.mtudisctimeout", []_C_int{4, 24, 17, 50}}, + {"net.inet6.ip6.multicast_mtudisc", []_C_int{4, 24, 17, 44}}, + {"net.inet6.ip6.multipath", []_C_int{4, 24, 17, 43}}, + {"net.inet6.ip6.neighborgcthresh", []_C_int{4, 24, 17, 45}}, + {"net.inet6.ip6.redirect", []_C_int{4, 24, 17, 2}}, + {"net.inet6.ip6.soiikey", []_C_int{4, 24, 17, 54}}, + {"net.inet6.ip6.sourcecheck", []_C_int{4, 24, 17, 10}}, + {"net.inet6.ip6.sourcecheck_logint", []_C_int{4, 24, 17, 11}}, + {"net.inet6.ip6.use_deprecated", []_C_int{4, 24, 17, 21}}, + {"net.key.sadb_dump", []_C_int{4, 30, 1}}, + {"net.key.spd_dump", []_C_int{4, 30, 2}}, + {"net.mpls.ifq.congestion", []_C_int{4, 33, 3, 4}}, + {"net.mpls.ifq.drops", []_C_int{4, 33, 3, 3}}, + {"net.mpls.ifq.len", []_C_int{4, 33, 3, 1}}, + {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, + {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, + {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, + {"net.mpls.ttl", []_C_int{4, 33, 2}}, + {"net.pflow.stats", []_C_int{4, 34, 1}}, + {"net.pipex.enable", []_C_int{4, 35, 1}}, + {"vm.anonmin", []_C_int{2, 7}}, + {"vm.loadavg", []_C_int{2, 2}}, + {"vm.malloc_conf", []_C_int{2, 12}}, + {"vm.maxslp", []_C_int{2, 10}}, + {"vm.nkmempages", []_C_int{2, 6}}, + {"vm.psstrings", []_C_int{2, 3}}, + {"vm.swapencrypt.enable", []_C_int{2, 5, 0}}, + {"vm.swapencrypt.keyscreated", []_C_int{2, 5, 1}}, + {"vm.swapencrypt.keysdeleted", []_C_int{2, 5, 2}}, + {"vm.uspace", []_C_int{2, 11}}, + {"vm.uvmexp", []_C_int{2, 4}}, + {"vm.vmmeter", []_C_int{2, 1}}, + {"vm.vnodemin", []_C_int{2, 9}}, + {"vm.vtextmin", []_C_int{2, 8}}, +} diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go new file mode 100644 index 0000000..ee97157 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go @@ -0,0 +1,280 @@ +// go run mksysctl_openbsd.go +// Code generated by the command above; DO NOT EDIT. + +//go:build ppc64 && openbsd + +package unix + +type mibentry struct { + ctlname string + ctloid []_C_int +} + +var sysctlMib = []mibentry{ + {"ddb.console", []_C_int{9, 6}}, + {"ddb.log", []_C_int{9, 7}}, + {"ddb.max_line", []_C_int{9, 3}}, + {"ddb.max_width", []_C_int{9, 2}}, + {"ddb.panic", []_C_int{9, 5}}, + {"ddb.profile", []_C_int{9, 9}}, + {"ddb.radix", []_C_int{9, 1}}, + {"ddb.tab_stop_width", []_C_int{9, 4}}, + {"ddb.trigger", []_C_int{9, 8}}, + {"fs.posix.setuid", []_C_int{3, 1, 1}}, + {"hw.allowpowerdown", []_C_int{6, 22}}, + {"hw.byteorder", []_C_int{6, 4}}, + {"hw.cpuspeed", []_C_int{6, 12}}, + {"hw.diskcount", []_C_int{6, 10}}, + {"hw.disknames", []_C_int{6, 8}}, + {"hw.diskstats", []_C_int{6, 9}}, + {"hw.machine", []_C_int{6, 1}}, + {"hw.model", []_C_int{6, 2}}, + {"hw.ncpu", []_C_int{6, 3}}, + {"hw.ncpufound", []_C_int{6, 21}}, + {"hw.ncpuonline", []_C_int{6, 25}}, + {"hw.pagesize", []_C_int{6, 7}}, + {"hw.perfpolicy", []_C_int{6, 23}}, + {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, + {"hw.product", []_C_int{6, 15}}, + {"hw.serialno", []_C_int{6, 17}}, + {"hw.setperf", []_C_int{6, 13}}, + {"hw.smt", []_C_int{6, 24}}, + {"hw.usermem", []_C_int{6, 20}}, + {"hw.uuid", []_C_int{6, 18}}, + {"hw.vendor", []_C_int{6, 14}}, + {"hw.version", []_C_int{6, 16}}, + {"kern.allowdt", []_C_int{1, 65}}, + {"kern.allowkmem", []_C_int{1, 52}}, + {"kern.argmax", []_C_int{1, 8}}, + {"kern.audio", []_C_int{1, 84}}, + {"kern.boottime", []_C_int{1, 21}}, + {"kern.bufcachepercent", []_C_int{1, 72}}, + {"kern.ccpu", []_C_int{1, 45}}, + {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, + {"kern.consdev", []_C_int{1, 75}}, + {"kern.cp_time", []_C_int{1, 40}}, + {"kern.cp_time2", []_C_int{1, 71}}, + {"kern.cpustats", []_C_int{1, 85}}, + {"kern.domainname", []_C_int{1, 22}}, + {"kern.file", []_C_int{1, 73}}, + {"kern.forkstat", []_C_int{1, 42}}, + {"kern.fscale", []_C_int{1, 46}}, + {"kern.fsync", []_C_int{1, 33}}, + {"kern.global_ptrace", []_C_int{1, 81}}, + {"kern.hostid", []_C_int{1, 11}}, + {"kern.hostname", []_C_int{1, 10}}, + {"kern.intrcnt.nintrcnt", []_C_int{1, 63, 1}}, + {"kern.job_control", []_C_int{1, 19}}, + {"kern.malloc.buckets", []_C_int{1, 39, 1}}, + {"kern.malloc.kmemnames", []_C_int{1, 39, 3}}, + {"kern.maxclusters", []_C_int{1, 67}}, + {"kern.maxfiles", []_C_int{1, 7}}, + {"kern.maxlocksperuid", []_C_int{1, 70}}, + {"kern.maxpartitions", []_C_int{1, 23}}, + {"kern.maxproc", []_C_int{1, 6}}, + {"kern.maxthread", []_C_int{1, 25}}, + {"kern.maxvnodes", []_C_int{1, 5}}, + {"kern.mbstat", []_C_int{1, 59}}, + {"kern.msgbuf", []_C_int{1, 48}}, + {"kern.msgbufsize", []_C_int{1, 38}}, + {"kern.nchstats", []_C_int{1, 41}}, + {"kern.netlivelocks", []_C_int{1, 76}}, + {"kern.nfiles", []_C_int{1, 56}}, + {"kern.ngroups", []_C_int{1, 18}}, + {"kern.nosuidcoredump", []_C_int{1, 32}}, + {"kern.nprocs", []_C_int{1, 47}}, + {"kern.nthreads", []_C_int{1, 26}}, + {"kern.numvnodes", []_C_int{1, 58}}, + {"kern.osrelease", []_C_int{1, 2}}, + {"kern.osrevision", []_C_int{1, 3}}, + {"kern.ostype", []_C_int{1, 1}}, + {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, + {"kern.pool_debug", []_C_int{1, 77}}, + {"kern.posix1version", []_C_int{1, 17}}, + {"kern.proc", []_C_int{1, 66}}, + {"kern.rawpartition", []_C_int{1, 24}}, + {"kern.saved_ids", []_C_int{1, 20}}, + {"kern.securelevel", []_C_int{1, 9}}, + {"kern.seminfo", []_C_int{1, 61}}, + {"kern.shminfo", []_C_int{1, 62}}, + {"kern.somaxconn", []_C_int{1, 28}}, + {"kern.sominconn", []_C_int{1, 29}}, + {"kern.splassert", []_C_int{1, 54}}, + {"kern.stackgap_random", []_C_int{1, 50}}, + {"kern.sysvipc_info", []_C_int{1, 51}}, + {"kern.sysvmsg", []_C_int{1, 34}}, + {"kern.sysvsem", []_C_int{1, 35}}, + {"kern.sysvshm", []_C_int{1, 36}}, + {"kern.timecounter.choice", []_C_int{1, 69, 4}}, + {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, + {"kern.timecounter.tick", []_C_int{1, 69, 1}}, + {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, + {"kern.timeout_stats", []_C_int{1, 87}}, + {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, + {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, + {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, + {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, + {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, + {"kern.ttycount", []_C_int{1, 57}}, + {"kern.utc_offset", []_C_int{1, 88}}, + {"kern.version", []_C_int{1, 4}}, + {"kern.video", []_C_int{1, 89}}, + {"kern.watchdog.auto", []_C_int{1, 64, 2}}, + {"kern.watchdog.period", []_C_int{1, 64, 1}}, + {"kern.witnesswatch", []_C_int{1, 53}}, + {"kern.wxabort", []_C_int{1, 74}}, + {"net.bpf.bufsize", []_C_int{4, 31, 1}}, + {"net.bpf.maxbufsize", []_C_int{4, 31, 2}}, + {"net.inet.ah.enable", []_C_int{4, 2, 51, 1}}, + {"net.inet.ah.stats", []_C_int{4, 2, 51, 2}}, + {"net.inet.carp.allow", []_C_int{4, 2, 112, 1}}, + {"net.inet.carp.log", []_C_int{4, 2, 112, 3}}, + {"net.inet.carp.preempt", []_C_int{4, 2, 112, 2}}, + {"net.inet.carp.stats", []_C_int{4, 2, 112, 4}}, + {"net.inet.divert.recvspace", []_C_int{4, 2, 258, 1}}, + {"net.inet.divert.sendspace", []_C_int{4, 2, 258, 2}}, + {"net.inet.divert.stats", []_C_int{4, 2, 258, 3}}, + {"net.inet.esp.enable", []_C_int{4, 2, 50, 1}}, + {"net.inet.esp.stats", []_C_int{4, 2, 50, 4}}, + {"net.inet.esp.udpencap", []_C_int{4, 2, 50, 2}}, + {"net.inet.esp.udpencap_port", []_C_int{4, 2, 50, 3}}, + {"net.inet.etherip.allow", []_C_int{4, 2, 97, 1}}, + {"net.inet.etherip.stats", []_C_int{4, 2, 97, 2}}, + {"net.inet.gre.allow", []_C_int{4, 2, 47, 1}}, + {"net.inet.gre.wccp", []_C_int{4, 2, 47, 2}}, + {"net.inet.icmp.bmcastecho", []_C_int{4, 2, 1, 2}}, + {"net.inet.icmp.errppslimit", []_C_int{4, 2, 1, 3}}, + {"net.inet.icmp.maskrepl", []_C_int{4, 2, 1, 1}}, + {"net.inet.icmp.rediraccept", []_C_int{4, 2, 1, 4}}, + {"net.inet.icmp.redirtimeout", []_C_int{4, 2, 1, 5}}, + {"net.inet.icmp.stats", []_C_int{4, 2, 1, 7}}, + {"net.inet.icmp.tstamprepl", []_C_int{4, 2, 1, 6}}, + {"net.inet.igmp.stats", []_C_int{4, 2, 2, 1}}, + {"net.inet.ip.arpdown", []_C_int{4, 2, 0, 40}}, + {"net.inet.ip.arpqueued", []_C_int{4, 2, 0, 36}}, + {"net.inet.ip.arptimeout", []_C_int{4, 2, 0, 39}}, + {"net.inet.ip.encdebug", []_C_int{4, 2, 0, 12}}, + {"net.inet.ip.forwarding", []_C_int{4, 2, 0, 1}}, + {"net.inet.ip.ifq.congestion", []_C_int{4, 2, 0, 30, 4}}, + {"net.inet.ip.ifq.drops", []_C_int{4, 2, 0, 30, 3}}, + {"net.inet.ip.ifq.len", []_C_int{4, 2, 0, 30, 1}}, + {"net.inet.ip.ifq.maxlen", []_C_int{4, 2, 0, 30, 2}}, + {"net.inet.ip.maxqueue", []_C_int{4, 2, 0, 11}}, + {"net.inet.ip.mforwarding", []_C_int{4, 2, 0, 31}}, + {"net.inet.ip.mrtmfc", []_C_int{4, 2, 0, 37}}, + {"net.inet.ip.mrtproto", []_C_int{4, 2, 0, 34}}, + {"net.inet.ip.mrtstats", []_C_int{4, 2, 0, 35}}, + {"net.inet.ip.mrtvif", []_C_int{4, 2, 0, 38}}, + {"net.inet.ip.mtu", []_C_int{4, 2, 0, 4}}, + {"net.inet.ip.mtudisc", []_C_int{4, 2, 0, 27}}, + {"net.inet.ip.mtudisctimeout", []_C_int{4, 2, 0, 28}}, + {"net.inet.ip.multipath", []_C_int{4, 2, 0, 32}}, + {"net.inet.ip.portfirst", []_C_int{4, 2, 0, 7}}, + {"net.inet.ip.porthifirst", []_C_int{4, 2, 0, 9}}, + {"net.inet.ip.porthilast", []_C_int{4, 2, 0, 10}}, + {"net.inet.ip.portlast", []_C_int{4, 2, 0, 8}}, + {"net.inet.ip.redirect", []_C_int{4, 2, 0, 2}}, + {"net.inet.ip.sourceroute", []_C_int{4, 2, 0, 5}}, + {"net.inet.ip.stats", []_C_int{4, 2, 0, 33}}, + {"net.inet.ip.ttl", []_C_int{4, 2, 0, 3}}, + {"net.inet.ipcomp.enable", []_C_int{4, 2, 108, 1}}, + {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, + {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, + {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, + {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, + {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, + {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, + {"net.inet.tcp.baddynamic", []_C_int{4, 2, 6, 6}}, + {"net.inet.tcp.drop", []_C_int{4, 2, 6, 19}}, + {"net.inet.tcp.ecn", []_C_int{4, 2, 6, 14}}, + {"net.inet.tcp.ident", []_C_int{4, 2, 6, 9}}, + {"net.inet.tcp.keepidle", []_C_int{4, 2, 6, 3}}, + {"net.inet.tcp.keepinittime", []_C_int{4, 2, 6, 2}}, + {"net.inet.tcp.keepintvl", []_C_int{4, 2, 6, 4}}, + {"net.inet.tcp.mssdflt", []_C_int{4, 2, 6, 11}}, + {"net.inet.tcp.reasslimit", []_C_int{4, 2, 6, 18}}, + {"net.inet.tcp.rfc1323", []_C_int{4, 2, 6, 1}}, + {"net.inet.tcp.rfc3390", []_C_int{4, 2, 6, 17}}, + {"net.inet.tcp.rootonly", []_C_int{4, 2, 6, 24}}, + {"net.inet.tcp.rstppslimit", []_C_int{4, 2, 6, 12}}, + {"net.inet.tcp.sack", []_C_int{4, 2, 6, 10}}, + {"net.inet.tcp.sackholelimit", []_C_int{4, 2, 6, 20}}, + {"net.inet.tcp.slowhz", []_C_int{4, 2, 6, 5}}, + {"net.inet.tcp.stats", []_C_int{4, 2, 6, 21}}, + {"net.inet.tcp.synbucketlimit", []_C_int{4, 2, 6, 16}}, + {"net.inet.tcp.syncachelimit", []_C_int{4, 2, 6, 15}}, + {"net.inet.tcp.synhashsize", []_C_int{4, 2, 6, 25}}, + {"net.inet.tcp.synuselimit", []_C_int{4, 2, 6, 23}}, + {"net.inet.udp.baddynamic", []_C_int{4, 2, 17, 2}}, + {"net.inet.udp.checksum", []_C_int{4, 2, 17, 1}}, + {"net.inet.udp.recvspace", []_C_int{4, 2, 17, 3}}, + {"net.inet.udp.rootonly", []_C_int{4, 2, 17, 6}}, + {"net.inet.udp.sendspace", []_C_int{4, 2, 17, 4}}, + {"net.inet.udp.stats", []_C_int{4, 2, 17, 5}}, + {"net.inet6.divert.recvspace", []_C_int{4, 24, 86, 1}}, + {"net.inet6.divert.sendspace", []_C_int{4, 24, 86, 2}}, + {"net.inet6.divert.stats", []_C_int{4, 24, 86, 3}}, + {"net.inet6.icmp6.errppslimit", []_C_int{4, 24, 30, 14}}, + {"net.inet6.icmp6.mtudisc_hiwat", []_C_int{4, 24, 30, 16}}, + {"net.inet6.icmp6.mtudisc_lowat", []_C_int{4, 24, 30, 17}}, + {"net.inet6.icmp6.nd6_debug", []_C_int{4, 24, 30, 18}}, + {"net.inet6.icmp6.nd6_delay", []_C_int{4, 24, 30, 8}}, + {"net.inet6.icmp6.nd6_maxnudhint", []_C_int{4, 24, 30, 15}}, + {"net.inet6.icmp6.nd6_mmaxtries", []_C_int{4, 24, 30, 10}}, + {"net.inet6.icmp6.nd6_umaxtries", []_C_int{4, 24, 30, 9}}, + {"net.inet6.icmp6.redirtimeout", []_C_int{4, 24, 30, 3}}, + {"net.inet6.ip6.auto_flowlabel", []_C_int{4, 24, 17, 17}}, + {"net.inet6.ip6.dad_count", []_C_int{4, 24, 17, 16}}, + {"net.inet6.ip6.dad_pending", []_C_int{4, 24, 17, 49}}, + {"net.inet6.ip6.defmcasthlim", []_C_int{4, 24, 17, 18}}, + {"net.inet6.ip6.forwarding", []_C_int{4, 24, 17, 1}}, + {"net.inet6.ip6.forwsrcrt", []_C_int{4, 24, 17, 5}}, + {"net.inet6.ip6.hdrnestlimit", []_C_int{4, 24, 17, 15}}, + {"net.inet6.ip6.hlim", []_C_int{4, 24, 17, 3}}, + {"net.inet6.ip6.log_interval", []_C_int{4, 24, 17, 14}}, + {"net.inet6.ip6.maxdynroutes", []_C_int{4, 24, 17, 48}}, + {"net.inet6.ip6.maxfragpackets", []_C_int{4, 24, 17, 9}}, + {"net.inet6.ip6.maxfrags", []_C_int{4, 24, 17, 41}}, + {"net.inet6.ip6.mforwarding", []_C_int{4, 24, 17, 42}}, + {"net.inet6.ip6.mrtmfc", []_C_int{4, 24, 17, 53}}, + {"net.inet6.ip6.mrtmif", []_C_int{4, 24, 17, 52}}, + {"net.inet6.ip6.mrtproto", []_C_int{4, 24, 17, 8}}, + {"net.inet6.ip6.mtudisctimeout", []_C_int{4, 24, 17, 50}}, + {"net.inet6.ip6.multicast_mtudisc", []_C_int{4, 24, 17, 44}}, + {"net.inet6.ip6.multipath", []_C_int{4, 24, 17, 43}}, + {"net.inet6.ip6.neighborgcthresh", []_C_int{4, 24, 17, 45}}, + {"net.inet6.ip6.redirect", []_C_int{4, 24, 17, 2}}, + {"net.inet6.ip6.soiikey", []_C_int{4, 24, 17, 54}}, + {"net.inet6.ip6.sourcecheck", []_C_int{4, 24, 17, 10}}, + {"net.inet6.ip6.sourcecheck_logint", []_C_int{4, 24, 17, 11}}, + {"net.inet6.ip6.use_deprecated", []_C_int{4, 24, 17, 21}}, + {"net.key.sadb_dump", []_C_int{4, 30, 1}}, + {"net.key.spd_dump", []_C_int{4, 30, 2}}, + {"net.mpls.ifq.congestion", []_C_int{4, 33, 3, 4}}, + {"net.mpls.ifq.drops", []_C_int{4, 33, 3, 3}}, + {"net.mpls.ifq.len", []_C_int{4, 33, 3, 1}}, + {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, + {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, + {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, + {"net.mpls.ttl", []_C_int{4, 33, 2}}, + {"net.pflow.stats", []_C_int{4, 34, 1}}, + {"net.pipex.enable", []_C_int{4, 35, 1}}, + {"vm.anonmin", []_C_int{2, 7}}, + {"vm.loadavg", []_C_int{2, 2}}, + {"vm.malloc_conf", []_C_int{2, 12}}, + {"vm.maxslp", []_C_int{2, 10}}, + {"vm.nkmempages", []_C_int{2, 6}}, + {"vm.psstrings", []_C_int{2, 3}}, + {"vm.swapencrypt.enable", []_C_int{2, 5, 0}}, + {"vm.swapencrypt.keyscreated", []_C_int{2, 5, 1}}, + {"vm.swapencrypt.keysdeleted", []_C_int{2, 5, 2}}, + {"vm.uspace", []_C_int{2, 11}}, + {"vm.uvmexp", []_C_int{2, 4}}, + {"vm.vmmeter", []_C_int{2, 1}}, + {"vm.vnodemin", []_C_int{2, 9}}, + {"vm.vtextmin", []_C_int{2, 8}}, +} diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go new file mode 100644 index 0000000..35c3b91 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go @@ -0,0 +1,281 @@ +// go run mksysctl_openbsd.go +// Code generated by the command above; DO NOT EDIT. + +//go:build riscv64 && openbsd + +package unix + +type mibentry struct { + ctlname string + ctloid []_C_int +} + +var sysctlMib = []mibentry{ + {"ddb.console", []_C_int{9, 6}}, + {"ddb.log", []_C_int{9, 7}}, + {"ddb.max_line", []_C_int{9, 3}}, + {"ddb.max_width", []_C_int{9, 2}}, + {"ddb.panic", []_C_int{9, 5}}, + {"ddb.profile", []_C_int{9, 9}}, + {"ddb.radix", []_C_int{9, 1}}, + {"ddb.tab_stop_width", []_C_int{9, 4}}, + {"ddb.trigger", []_C_int{9, 8}}, + {"fs.posix.setuid", []_C_int{3, 1, 1}}, + {"hw.allowpowerdown", []_C_int{6, 22}}, + {"hw.byteorder", []_C_int{6, 4}}, + {"hw.cpuspeed", []_C_int{6, 12}}, + {"hw.diskcount", []_C_int{6, 10}}, + {"hw.disknames", []_C_int{6, 8}}, + {"hw.diskstats", []_C_int{6, 9}}, + {"hw.machine", []_C_int{6, 1}}, + {"hw.model", []_C_int{6, 2}}, + {"hw.ncpu", []_C_int{6, 3}}, + {"hw.ncpufound", []_C_int{6, 21}}, + {"hw.ncpuonline", []_C_int{6, 25}}, + {"hw.pagesize", []_C_int{6, 7}}, + {"hw.perfpolicy", []_C_int{6, 23}}, + {"hw.physmem", []_C_int{6, 19}}, + {"hw.power", []_C_int{6, 26}}, + {"hw.product", []_C_int{6, 15}}, + {"hw.serialno", []_C_int{6, 17}}, + {"hw.setperf", []_C_int{6, 13}}, + {"hw.smt", []_C_int{6, 24}}, + {"hw.usermem", []_C_int{6, 20}}, + {"hw.uuid", []_C_int{6, 18}}, + {"hw.vendor", []_C_int{6, 14}}, + {"hw.version", []_C_int{6, 16}}, + {"kern.allowdt", []_C_int{1, 65}}, + {"kern.allowkmem", []_C_int{1, 52}}, + {"kern.argmax", []_C_int{1, 8}}, + {"kern.audio", []_C_int{1, 84}}, + {"kern.boottime", []_C_int{1, 21}}, + {"kern.bufcachepercent", []_C_int{1, 72}}, + {"kern.ccpu", []_C_int{1, 45}}, + {"kern.clockrate", []_C_int{1, 12}}, + {"kern.consbuf", []_C_int{1, 83}}, + {"kern.consbufsize", []_C_int{1, 82}}, + {"kern.consdev", []_C_int{1, 75}}, + {"kern.cp_time", []_C_int{1, 40}}, + {"kern.cp_time2", []_C_int{1, 71}}, + {"kern.cpustats", []_C_int{1, 85}}, + {"kern.domainname", []_C_int{1, 22}}, + {"kern.file", []_C_int{1, 73}}, + {"kern.forkstat", []_C_int{1, 42}}, + {"kern.fscale", []_C_int{1, 46}}, + {"kern.fsync", []_C_int{1, 33}}, + {"kern.global_ptrace", []_C_int{1, 81}}, + {"kern.hostid", []_C_int{1, 11}}, + {"kern.hostname", []_C_int{1, 10}}, + {"kern.intrcnt.nintrcnt", []_C_int{1, 63, 1}}, + {"kern.job_control", []_C_int{1, 19}}, + {"kern.malloc.buckets", []_C_int{1, 39, 1}}, + {"kern.malloc.kmemnames", []_C_int{1, 39, 3}}, + {"kern.maxclusters", []_C_int{1, 67}}, + {"kern.maxfiles", []_C_int{1, 7}}, + {"kern.maxlocksperuid", []_C_int{1, 70}}, + {"kern.maxpartitions", []_C_int{1, 23}}, + {"kern.maxproc", []_C_int{1, 6}}, + {"kern.maxthread", []_C_int{1, 25}}, + {"kern.maxvnodes", []_C_int{1, 5}}, + {"kern.mbstat", []_C_int{1, 59}}, + {"kern.msgbuf", []_C_int{1, 48}}, + {"kern.msgbufsize", []_C_int{1, 38}}, + {"kern.nchstats", []_C_int{1, 41}}, + {"kern.netlivelocks", []_C_int{1, 76}}, + {"kern.nfiles", []_C_int{1, 56}}, + {"kern.ngroups", []_C_int{1, 18}}, + {"kern.nosuidcoredump", []_C_int{1, 32}}, + {"kern.nprocs", []_C_int{1, 47}}, + {"kern.nselcoll", []_C_int{1, 43}}, + {"kern.nthreads", []_C_int{1, 26}}, + {"kern.numvnodes", []_C_int{1, 58}}, + {"kern.osrelease", []_C_int{1, 2}}, + {"kern.osrevision", []_C_int{1, 3}}, + {"kern.ostype", []_C_int{1, 1}}, + {"kern.osversion", []_C_int{1, 27}}, + {"kern.pfstatus", []_C_int{1, 86}}, + {"kern.pool_debug", []_C_int{1, 77}}, + {"kern.posix1version", []_C_int{1, 17}}, + {"kern.proc", []_C_int{1, 66}}, + {"kern.rawpartition", []_C_int{1, 24}}, + {"kern.saved_ids", []_C_int{1, 20}}, + {"kern.securelevel", []_C_int{1, 9}}, + {"kern.seminfo", []_C_int{1, 61}}, + {"kern.shminfo", []_C_int{1, 62}}, + {"kern.somaxconn", []_C_int{1, 28}}, + {"kern.sominconn", []_C_int{1, 29}}, + {"kern.splassert", []_C_int{1, 54}}, + {"kern.stackgap_random", []_C_int{1, 50}}, + {"kern.sysvipc_info", []_C_int{1, 51}}, + {"kern.sysvmsg", []_C_int{1, 34}}, + {"kern.sysvsem", []_C_int{1, 35}}, + {"kern.sysvshm", []_C_int{1, 36}}, + {"kern.timecounter.choice", []_C_int{1, 69, 4}}, + {"kern.timecounter.hardware", []_C_int{1, 69, 3}}, + {"kern.timecounter.tick", []_C_int{1, 69, 1}}, + {"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}}, + {"kern.timeout_stats", []_C_int{1, 87}}, + {"kern.tty.tk_cancc", []_C_int{1, 44, 4}}, + {"kern.tty.tk_nin", []_C_int{1, 44, 1}}, + {"kern.tty.tk_nout", []_C_int{1, 44, 2}}, + {"kern.tty.tk_rawcc", []_C_int{1, 44, 3}}, + {"kern.tty.ttyinfo", []_C_int{1, 44, 5}}, + {"kern.ttycount", []_C_int{1, 57}}, + {"kern.utc_offset", []_C_int{1, 88}}, + {"kern.version", []_C_int{1, 4}}, + {"kern.video", []_C_int{1, 89}}, + {"kern.watchdog.auto", []_C_int{1, 64, 2}}, + {"kern.watchdog.period", []_C_int{1, 64, 1}}, + {"kern.witnesswatch", []_C_int{1, 53}}, + {"kern.wxabort", []_C_int{1, 74}}, + {"net.bpf.bufsize", []_C_int{4, 31, 1}}, + {"net.bpf.maxbufsize", []_C_int{4, 31, 2}}, + {"net.inet.ah.enable", []_C_int{4, 2, 51, 1}}, + {"net.inet.ah.stats", []_C_int{4, 2, 51, 2}}, + {"net.inet.carp.allow", []_C_int{4, 2, 112, 1}}, + {"net.inet.carp.log", []_C_int{4, 2, 112, 3}}, + {"net.inet.carp.preempt", []_C_int{4, 2, 112, 2}}, + {"net.inet.carp.stats", []_C_int{4, 2, 112, 4}}, + {"net.inet.divert.recvspace", []_C_int{4, 2, 258, 1}}, + {"net.inet.divert.sendspace", []_C_int{4, 2, 258, 2}}, + {"net.inet.divert.stats", []_C_int{4, 2, 258, 3}}, + {"net.inet.esp.enable", []_C_int{4, 2, 50, 1}}, + {"net.inet.esp.stats", []_C_int{4, 2, 50, 4}}, + {"net.inet.esp.udpencap", []_C_int{4, 2, 50, 2}}, + {"net.inet.esp.udpencap_port", []_C_int{4, 2, 50, 3}}, + {"net.inet.etherip.allow", []_C_int{4, 2, 97, 1}}, + {"net.inet.etherip.stats", []_C_int{4, 2, 97, 2}}, + {"net.inet.gre.allow", []_C_int{4, 2, 47, 1}}, + {"net.inet.gre.wccp", []_C_int{4, 2, 47, 2}}, + {"net.inet.icmp.bmcastecho", []_C_int{4, 2, 1, 2}}, + {"net.inet.icmp.errppslimit", []_C_int{4, 2, 1, 3}}, + {"net.inet.icmp.maskrepl", []_C_int{4, 2, 1, 1}}, + {"net.inet.icmp.rediraccept", []_C_int{4, 2, 1, 4}}, + {"net.inet.icmp.redirtimeout", []_C_int{4, 2, 1, 5}}, + {"net.inet.icmp.stats", []_C_int{4, 2, 1, 7}}, + {"net.inet.icmp.tstamprepl", []_C_int{4, 2, 1, 6}}, + {"net.inet.igmp.stats", []_C_int{4, 2, 2, 1}}, + {"net.inet.ip.arpdown", []_C_int{4, 2, 0, 40}}, + {"net.inet.ip.arpqueued", []_C_int{4, 2, 0, 36}}, + {"net.inet.ip.arptimeout", []_C_int{4, 2, 0, 39}}, + {"net.inet.ip.encdebug", []_C_int{4, 2, 0, 12}}, + {"net.inet.ip.forwarding", []_C_int{4, 2, 0, 1}}, + {"net.inet.ip.ifq.congestion", []_C_int{4, 2, 0, 30, 4}}, + {"net.inet.ip.ifq.drops", []_C_int{4, 2, 0, 30, 3}}, + {"net.inet.ip.ifq.len", []_C_int{4, 2, 0, 30, 1}}, + {"net.inet.ip.ifq.maxlen", []_C_int{4, 2, 0, 30, 2}}, + {"net.inet.ip.maxqueue", []_C_int{4, 2, 0, 11}}, + {"net.inet.ip.mforwarding", []_C_int{4, 2, 0, 31}}, + {"net.inet.ip.mrtmfc", []_C_int{4, 2, 0, 37}}, + {"net.inet.ip.mrtproto", []_C_int{4, 2, 0, 34}}, + {"net.inet.ip.mrtstats", []_C_int{4, 2, 0, 35}}, + {"net.inet.ip.mrtvif", []_C_int{4, 2, 0, 38}}, + {"net.inet.ip.mtu", []_C_int{4, 2, 0, 4}}, + {"net.inet.ip.mtudisc", []_C_int{4, 2, 0, 27}}, + {"net.inet.ip.mtudisctimeout", []_C_int{4, 2, 0, 28}}, + {"net.inet.ip.multipath", []_C_int{4, 2, 0, 32}}, + {"net.inet.ip.portfirst", []_C_int{4, 2, 0, 7}}, + {"net.inet.ip.porthifirst", []_C_int{4, 2, 0, 9}}, + {"net.inet.ip.porthilast", []_C_int{4, 2, 0, 10}}, + {"net.inet.ip.portlast", []_C_int{4, 2, 0, 8}}, + {"net.inet.ip.redirect", []_C_int{4, 2, 0, 2}}, + {"net.inet.ip.sourceroute", []_C_int{4, 2, 0, 5}}, + {"net.inet.ip.stats", []_C_int{4, 2, 0, 33}}, + {"net.inet.ip.ttl", []_C_int{4, 2, 0, 3}}, + {"net.inet.ipcomp.enable", []_C_int{4, 2, 108, 1}}, + {"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}}, + {"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}}, + {"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}}, + {"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}}, + {"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}}, + {"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}}, + {"net.inet.tcp.baddynamic", []_C_int{4, 2, 6, 6}}, + {"net.inet.tcp.drop", []_C_int{4, 2, 6, 19}}, + {"net.inet.tcp.ecn", []_C_int{4, 2, 6, 14}}, + {"net.inet.tcp.ident", []_C_int{4, 2, 6, 9}}, + {"net.inet.tcp.keepidle", []_C_int{4, 2, 6, 3}}, + {"net.inet.tcp.keepinittime", []_C_int{4, 2, 6, 2}}, + {"net.inet.tcp.keepintvl", []_C_int{4, 2, 6, 4}}, + {"net.inet.tcp.mssdflt", []_C_int{4, 2, 6, 11}}, + {"net.inet.tcp.reasslimit", []_C_int{4, 2, 6, 18}}, + {"net.inet.tcp.rfc1323", []_C_int{4, 2, 6, 1}}, + {"net.inet.tcp.rfc3390", []_C_int{4, 2, 6, 17}}, + {"net.inet.tcp.rootonly", []_C_int{4, 2, 6, 24}}, + {"net.inet.tcp.rstppslimit", []_C_int{4, 2, 6, 12}}, + {"net.inet.tcp.sack", []_C_int{4, 2, 6, 10}}, + {"net.inet.tcp.sackholelimit", []_C_int{4, 2, 6, 20}}, + {"net.inet.tcp.slowhz", []_C_int{4, 2, 6, 5}}, + {"net.inet.tcp.stats", []_C_int{4, 2, 6, 21}}, + {"net.inet.tcp.synbucketlimit", []_C_int{4, 2, 6, 16}}, + {"net.inet.tcp.syncachelimit", []_C_int{4, 2, 6, 15}}, + {"net.inet.tcp.synhashsize", []_C_int{4, 2, 6, 25}}, + {"net.inet.tcp.synuselimit", []_C_int{4, 2, 6, 23}}, + {"net.inet.udp.baddynamic", []_C_int{4, 2, 17, 2}}, + {"net.inet.udp.checksum", []_C_int{4, 2, 17, 1}}, + {"net.inet.udp.recvspace", []_C_int{4, 2, 17, 3}}, + {"net.inet.udp.rootonly", []_C_int{4, 2, 17, 6}}, + {"net.inet.udp.sendspace", []_C_int{4, 2, 17, 4}}, + {"net.inet.udp.stats", []_C_int{4, 2, 17, 5}}, + {"net.inet6.divert.recvspace", []_C_int{4, 24, 86, 1}}, + {"net.inet6.divert.sendspace", []_C_int{4, 24, 86, 2}}, + {"net.inet6.divert.stats", []_C_int{4, 24, 86, 3}}, + {"net.inet6.icmp6.errppslimit", []_C_int{4, 24, 30, 14}}, + {"net.inet6.icmp6.mtudisc_hiwat", []_C_int{4, 24, 30, 16}}, + {"net.inet6.icmp6.mtudisc_lowat", []_C_int{4, 24, 30, 17}}, + {"net.inet6.icmp6.nd6_debug", []_C_int{4, 24, 30, 18}}, + {"net.inet6.icmp6.nd6_delay", []_C_int{4, 24, 30, 8}}, + {"net.inet6.icmp6.nd6_maxnudhint", []_C_int{4, 24, 30, 15}}, + {"net.inet6.icmp6.nd6_mmaxtries", []_C_int{4, 24, 30, 10}}, + {"net.inet6.icmp6.nd6_umaxtries", []_C_int{4, 24, 30, 9}}, + {"net.inet6.icmp6.redirtimeout", []_C_int{4, 24, 30, 3}}, + {"net.inet6.ip6.auto_flowlabel", []_C_int{4, 24, 17, 17}}, + {"net.inet6.ip6.dad_count", []_C_int{4, 24, 17, 16}}, + {"net.inet6.ip6.dad_pending", []_C_int{4, 24, 17, 49}}, + {"net.inet6.ip6.defmcasthlim", []_C_int{4, 24, 17, 18}}, + {"net.inet6.ip6.forwarding", []_C_int{4, 24, 17, 1}}, + {"net.inet6.ip6.forwsrcrt", []_C_int{4, 24, 17, 5}}, + {"net.inet6.ip6.hdrnestlimit", []_C_int{4, 24, 17, 15}}, + {"net.inet6.ip6.hlim", []_C_int{4, 24, 17, 3}}, + {"net.inet6.ip6.log_interval", []_C_int{4, 24, 17, 14}}, + {"net.inet6.ip6.maxdynroutes", []_C_int{4, 24, 17, 48}}, + {"net.inet6.ip6.maxfragpackets", []_C_int{4, 24, 17, 9}}, + {"net.inet6.ip6.maxfrags", []_C_int{4, 24, 17, 41}}, + {"net.inet6.ip6.mforwarding", []_C_int{4, 24, 17, 42}}, + {"net.inet6.ip6.mrtmfc", []_C_int{4, 24, 17, 53}}, + {"net.inet6.ip6.mrtmif", []_C_int{4, 24, 17, 52}}, + {"net.inet6.ip6.mrtproto", []_C_int{4, 24, 17, 8}}, + {"net.inet6.ip6.mtudisctimeout", []_C_int{4, 24, 17, 50}}, + {"net.inet6.ip6.multicast_mtudisc", []_C_int{4, 24, 17, 44}}, + {"net.inet6.ip6.multipath", []_C_int{4, 24, 17, 43}}, + {"net.inet6.ip6.neighborgcthresh", []_C_int{4, 24, 17, 45}}, + {"net.inet6.ip6.redirect", []_C_int{4, 24, 17, 2}}, + {"net.inet6.ip6.soiikey", []_C_int{4, 24, 17, 54}}, + {"net.inet6.ip6.sourcecheck", []_C_int{4, 24, 17, 10}}, + {"net.inet6.ip6.sourcecheck_logint", []_C_int{4, 24, 17, 11}}, + {"net.inet6.ip6.use_deprecated", []_C_int{4, 24, 17, 21}}, + {"net.key.sadb_dump", []_C_int{4, 30, 1}}, + {"net.key.spd_dump", []_C_int{4, 30, 2}}, + {"net.mpls.ifq.congestion", []_C_int{4, 33, 3, 4}}, + {"net.mpls.ifq.drops", []_C_int{4, 33, 3, 3}}, + {"net.mpls.ifq.len", []_C_int{4, 33, 3, 1}}, + {"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}}, + {"net.mpls.mapttl_ip", []_C_int{4, 33, 5}}, + {"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}}, + {"net.mpls.ttl", []_C_int{4, 33, 2}}, + {"net.pflow.stats", []_C_int{4, 34, 1}}, + {"net.pipex.enable", []_C_int{4, 35, 1}}, + {"vm.anonmin", []_C_int{2, 7}}, + {"vm.loadavg", []_C_int{2, 2}}, + {"vm.malloc_conf", []_C_int{2, 12}}, + {"vm.maxslp", []_C_int{2, 10}}, + {"vm.nkmempages", []_C_int{2, 6}}, + {"vm.psstrings", []_C_int{2, 3}}, + {"vm.swapencrypt.enable", []_C_int{2, 5, 0}}, + {"vm.swapencrypt.keyscreated", []_C_int{2, 5, 1}}, + {"vm.swapencrypt.keysdeleted", []_C_int{2, 5, 2}}, + {"vm.uspace", []_C_int{2, 11}}, + {"vm.uvmexp", []_C_int{2, 4}}, + {"vm.vmmeter", []_C_int{2, 1}}, + {"vm.vnodemin", []_C_int{2, 9}}, + {"vm.vtextmin", []_C_int{2, 8}}, +} diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go deleted file mode 100644 index f336145..0000000 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go +++ /dev/null @@ -1,436 +0,0 @@ -// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/sys/syscall.h -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build 386,darwin - -package unix - -const ( - SYS_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAIT4 = 7 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_CHDIR = 12 - SYS_FCHDIR = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_CHOWN = 16 - SYS_GETFSSTAT = 18 - SYS_GETPID = 20 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_GETEUID = 25 - SYS_PTRACE = 26 - SYS_RECVMSG = 27 - SYS_SENDMSG = 28 - SYS_RECVFROM = 29 - SYS_ACCEPT = 30 - SYS_GETPEERNAME = 31 - SYS_GETSOCKNAME = 32 - SYS_ACCESS = 33 - SYS_CHFLAGS = 34 - SYS_FCHFLAGS = 35 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_GETPPID = 39 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_GETEGID = 43 - SYS_SIGACTION = 46 - SYS_GETGID = 47 - SYS_SIGPROCMASK = 48 - SYS_GETLOGIN = 49 - SYS_SETLOGIN = 50 - SYS_ACCT = 51 - SYS_SIGPENDING = 52 - SYS_SIGALTSTACK = 53 - SYS_IOCTL = 54 - SYS_REBOOT = 55 - SYS_REVOKE = 56 - SYS_SYMLINK = 57 - SYS_READLINK = 58 - SYS_EXECVE = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_MSYNC = 65 - SYS_VFORK = 66 - SYS_MUNMAP = 73 - SYS_MPROTECT = 74 - SYS_MADVISE = 75 - SYS_MINCORE = 78 - SYS_GETGROUPS = 79 - SYS_SETGROUPS = 80 - SYS_GETPGRP = 81 - SYS_SETPGID = 82 - SYS_SETITIMER = 83 - SYS_SWAPON = 85 - SYS_GETITIMER = 86 - SYS_GETDTABLESIZE = 89 - SYS_DUP2 = 90 - SYS_FCNTL = 92 - SYS_SELECT = 93 - SYS_FSYNC = 95 - SYS_SETPRIORITY = 96 - SYS_SOCKET = 97 - SYS_CONNECT = 98 - SYS_GETPRIORITY = 100 - SYS_BIND = 104 - SYS_SETSOCKOPT = 105 - SYS_LISTEN = 106 - SYS_SIGSUSPEND = 111 - SYS_GETTIMEOFDAY = 116 - SYS_GETRUSAGE = 117 - SYS_GETSOCKOPT = 118 - SYS_READV = 120 - SYS_WRITEV = 121 - SYS_SETTIMEOFDAY = 122 - SYS_FCHOWN = 123 - SYS_FCHMOD = 124 - SYS_SETREUID = 126 - SYS_SETREGID = 127 - SYS_RENAME = 128 - SYS_FLOCK = 131 - SYS_MKFIFO = 132 - SYS_SENDTO = 133 - SYS_SHUTDOWN = 134 - SYS_SOCKETPAIR = 135 - SYS_MKDIR = 136 - SYS_RMDIR = 137 - SYS_UTIMES = 138 - SYS_FUTIMES = 139 - SYS_ADJTIME = 140 - SYS_GETHOSTUUID = 142 - SYS_SETSID = 147 - SYS_GETPGID = 151 - SYS_SETPRIVEXEC = 152 - SYS_PREAD = 153 - SYS_PWRITE = 154 - SYS_NFSSVC = 155 - SYS_STATFS = 157 - SYS_FSTATFS = 158 - SYS_UNMOUNT = 159 - SYS_GETFH = 161 - SYS_QUOTACTL = 165 - SYS_MOUNT = 167 - SYS_CSOPS = 169 - SYS_CSOPS_AUDITTOKEN = 170 - SYS_WAITID = 173 - SYS_KDEBUG_TYPEFILTER = 177 - SYS_KDEBUG_TRACE_STRING = 178 - SYS_KDEBUG_TRACE64 = 179 - SYS_KDEBUG_TRACE = 180 - SYS_SETGID = 181 - SYS_SETEGID = 182 - SYS_SETEUID = 183 - SYS_SIGRETURN = 184 - SYS_THREAD_SELFCOUNTS = 186 - SYS_FDATASYNC = 187 - SYS_STAT = 188 - SYS_FSTAT = 189 - SYS_LSTAT = 190 - SYS_PATHCONF = 191 - SYS_FPATHCONF = 192 - SYS_GETRLIMIT = 194 - SYS_SETRLIMIT = 195 - SYS_GETDIRENTRIES = 196 - SYS_MMAP = 197 - SYS_LSEEK = 199 - SYS_TRUNCATE = 200 - SYS_FTRUNCATE = 201 - SYS_SYSCTL = 202 - SYS_MLOCK = 203 - SYS_MUNLOCK = 204 - SYS_UNDELETE = 205 - SYS_OPEN_DPROTECTED_NP = 216 - SYS_GETATTRLIST = 220 - SYS_SETATTRLIST = 221 - SYS_GETDIRENTRIESATTR = 222 - SYS_EXCHANGEDATA = 223 - SYS_SEARCHFS = 225 - SYS_DELETE = 226 - SYS_COPYFILE = 227 - SYS_FGETATTRLIST = 228 - SYS_FSETATTRLIST = 229 - SYS_POLL = 230 - SYS_WATCHEVENT = 231 - SYS_WAITEVENT = 232 - SYS_MODWATCH = 233 - SYS_GETXATTR = 234 - SYS_FGETXATTR = 235 - SYS_SETXATTR = 236 - SYS_FSETXATTR = 237 - SYS_REMOVEXATTR = 238 - SYS_FREMOVEXATTR = 239 - SYS_LISTXATTR = 240 - SYS_FLISTXATTR = 241 - SYS_FSCTL = 242 - SYS_INITGROUPS = 243 - SYS_POSIX_SPAWN = 244 - SYS_FFSCTL = 245 - SYS_NFSCLNT = 247 - SYS_FHOPEN = 248 - SYS_MINHERIT = 250 - SYS_SEMSYS = 251 - SYS_MSGSYS = 252 - SYS_SHMSYS = 253 - SYS_SEMCTL = 254 - SYS_SEMGET = 255 - SYS_SEMOP = 256 - SYS_MSGCTL = 258 - SYS_MSGGET = 259 - SYS_MSGSND = 260 - SYS_MSGRCV = 261 - SYS_SHMAT = 262 - SYS_SHMCTL = 263 - SYS_SHMDT = 264 - SYS_SHMGET = 265 - SYS_SHM_OPEN = 266 - SYS_SHM_UNLINK = 267 - SYS_SEM_OPEN = 268 - SYS_SEM_CLOSE = 269 - SYS_SEM_UNLINK = 270 - SYS_SEM_WAIT = 271 - SYS_SEM_TRYWAIT = 272 - SYS_SEM_POST = 273 - SYS_SYSCTLBYNAME = 274 - SYS_OPEN_EXTENDED = 277 - SYS_UMASK_EXTENDED = 278 - SYS_STAT_EXTENDED = 279 - SYS_LSTAT_EXTENDED = 280 - SYS_FSTAT_EXTENDED = 281 - SYS_CHMOD_EXTENDED = 282 - SYS_FCHMOD_EXTENDED = 283 - SYS_ACCESS_EXTENDED = 284 - SYS_SETTID = 285 - SYS_GETTID = 286 - SYS_SETSGROUPS = 287 - SYS_GETSGROUPS = 288 - SYS_SETWGROUPS = 289 - SYS_GETWGROUPS = 290 - SYS_MKFIFO_EXTENDED = 291 - SYS_MKDIR_EXTENDED = 292 - SYS_IDENTITYSVC = 293 - SYS_SHARED_REGION_CHECK_NP = 294 - SYS_VM_PRESSURE_MONITOR = 296 - SYS_PSYNCH_RW_LONGRDLOCK = 297 - SYS_PSYNCH_RW_YIELDWRLOCK = 298 - SYS_PSYNCH_RW_DOWNGRADE = 299 - SYS_PSYNCH_RW_UPGRADE = 300 - SYS_PSYNCH_MUTEXWAIT = 301 - SYS_PSYNCH_MUTEXDROP = 302 - SYS_PSYNCH_CVBROAD = 303 - SYS_PSYNCH_CVSIGNAL = 304 - SYS_PSYNCH_CVWAIT = 305 - SYS_PSYNCH_RW_RDLOCK = 306 - SYS_PSYNCH_RW_WRLOCK = 307 - SYS_PSYNCH_RW_UNLOCK = 308 - SYS_PSYNCH_RW_UNLOCK2 = 309 - SYS_GETSID = 310 - SYS_SETTID_WITH_PID = 311 - SYS_PSYNCH_CVCLRPREPOST = 312 - SYS_AIO_FSYNC = 313 - SYS_AIO_RETURN = 314 - SYS_AIO_SUSPEND = 315 - SYS_AIO_CANCEL = 316 - SYS_AIO_ERROR = 317 - SYS_AIO_READ = 318 - SYS_AIO_WRITE = 319 - SYS_LIO_LISTIO = 320 - SYS_IOPOLICYSYS = 322 - SYS_PROCESS_POLICY = 323 - SYS_MLOCKALL = 324 - SYS_MUNLOCKALL = 325 - SYS_ISSETUGID = 327 - SYS___PTHREAD_KILL = 328 - SYS___PTHREAD_SIGMASK = 329 - SYS___SIGWAIT = 330 - SYS___DISABLE_THREADSIGNAL = 331 - SYS___PTHREAD_MARKCANCEL = 332 - SYS___PTHREAD_CANCELED = 333 - SYS___SEMWAIT_SIGNAL = 334 - SYS_PROC_INFO = 336 - SYS_SENDFILE = 337 - SYS_STAT64 = 338 - SYS_FSTAT64 = 339 - SYS_LSTAT64 = 340 - SYS_STAT64_EXTENDED = 341 - SYS_LSTAT64_EXTENDED = 342 - SYS_FSTAT64_EXTENDED = 343 - SYS_GETDIRENTRIES64 = 344 - SYS_STATFS64 = 345 - SYS_FSTATFS64 = 346 - SYS_GETFSSTAT64 = 347 - SYS___PTHREAD_CHDIR = 348 - SYS___PTHREAD_FCHDIR = 349 - SYS_AUDIT = 350 - SYS_AUDITON = 351 - SYS_GETAUID = 353 - SYS_SETAUID = 354 - SYS_GETAUDIT_ADDR = 357 - SYS_SETAUDIT_ADDR = 358 - SYS_AUDITCTL = 359 - SYS_BSDTHREAD_CREATE = 360 - SYS_BSDTHREAD_TERMINATE = 361 - SYS_KQUEUE = 362 - SYS_KEVENT = 363 - SYS_LCHOWN = 364 - SYS_BSDTHREAD_REGISTER = 366 - SYS_WORKQ_OPEN = 367 - SYS_WORKQ_KERNRETURN = 368 - SYS_KEVENT64 = 369 - SYS___OLD_SEMWAIT_SIGNAL = 370 - SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 - SYS_THREAD_SELFID = 372 - SYS_LEDGER = 373 - SYS_KEVENT_QOS = 374 - SYS_KEVENT_ID = 375 - SYS___MAC_EXECVE = 380 - SYS___MAC_SYSCALL = 381 - SYS___MAC_GET_FILE = 382 - SYS___MAC_SET_FILE = 383 - SYS___MAC_GET_LINK = 384 - SYS___MAC_SET_LINK = 385 - SYS___MAC_GET_PROC = 386 - SYS___MAC_SET_PROC = 387 - SYS___MAC_GET_FD = 388 - SYS___MAC_SET_FD = 389 - SYS___MAC_GET_PID = 390 - SYS_PSELECT = 394 - SYS_PSELECT_NOCANCEL = 395 - SYS_READ_NOCANCEL = 396 - SYS_WRITE_NOCANCEL = 397 - SYS_OPEN_NOCANCEL = 398 - SYS_CLOSE_NOCANCEL = 399 - SYS_WAIT4_NOCANCEL = 400 - SYS_RECVMSG_NOCANCEL = 401 - SYS_SENDMSG_NOCANCEL = 402 - SYS_RECVFROM_NOCANCEL = 403 - SYS_ACCEPT_NOCANCEL = 404 - SYS_MSYNC_NOCANCEL = 405 - SYS_FCNTL_NOCANCEL = 406 - SYS_SELECT_NOCANCEL = 407 - SYS_FSYNC_NOCANCEL = 408 - SYS_CONNECT_NOCANCEL = 409 - SYS_SIGSUSPEND_NOCANCEL = 410 - SYS_READV_NOCANCEL = 411 - SYS_WRITEV_NOCANCEL = 412 - SYS_SENDTO_NOCANCEL = 413 - SYS_PREAD_NOCANCEL = 414 - SYS_PWRITE_NOCANCEL = 415 - SYS_WAITID_NOCANCEL = 416 - SYS_POLL_NOCANCEL = 417 - SYS_MSGSND_NOCANCEL = 418 - SYS_MSGRCV_NOCANCEL = 419 - SYS_SEM_WAIT_NOCANCEL = 420 - SYS_AIO_SUSPEND_NOCANCEL = 421 - SYS___SIGWAIT_NOCANCEL = 422 - SYS___SEMWAIT_SIGNAL_NOCANCEL = 423 - SYS___MAC_MOUNT = 424 - SYS___MAC_GET_MOUNT = 425 - SYS___MAC_GETFSSTAT = 426 - SYS_FSGETPATH = 427 - SYS_AUDIT_SESSION_SELF = 428 - SYS_AUDIT_SESSION_JOIN = 429 - SYS_FILEPORT_MAKEPORT = 430 - SYS_FILEPORT_MAKEFD = 431 - SYS_AUDIT_SESSION_PORT = 432 - SYS_PID_SUSPEND = 433 - SYS_PID_RESUME = 434 - SYS_PID_HIBERNATE = 435 - SYS_PID_SHUTDOWN_SOCKETS = 436 - SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438 - SYS_KAS_INFO = 439 - SYS_MEMORYSTATUS_CONTROL = 440 - SYS_GUARDED_OPEN_NP = 441 - SYS_GUARDED_CLOSE_NP = 442 - SYS_GUARDED_KQUEUE_NP = 443 - SYS_CHANGE_FDGUARD_NP = 444 - SYS_USRCTL = 445 - SYS_PROC_RLIMIT_CONTROL = 446 - SYS_CONNECTX = 447 - SYS_DISCONNECTX = 448 - SYS_PEELOFF = 449 - SYS_SOCKET_DELEGATE = 450 - SYS_TELEMETRY = 451 - SYS_PROC_UUID_POLICY = 452 - SYS_MEMORYSTATUS_GET_LEVEL = 453 - SYS_SYSTEM_OVERRIDE = 454 - SYS_VFS_PURGE = 455 - SYS_SFI_CTL = 456 - SYS_SFI_PIDCTL = 457 - SYS_COALITION = 458 - SYS_COALITION_INFO = 459 - SYS_NECP_MATCH_POLICY = 460 - SYS_GETATTRLISTBULK = 461 - SYS_CLONEFILEAT = 462 - SYS_OPENAT = 463 - SYS_OPENAT_NOCANCEL = 464 - SYS_RENAMEAT = 465 - SYS_FACCESSAT = 466 - SYS_FCHMODAT = 467 - SYS_FCHOWNAT = 468 - SYS_FSTATAT = 469 - SYS_FSTATAT64 = 470 - SYS_LINKAT = 471 - SYS_UNLINKAT = 472 - SYS_READLINKAT = 473 - SYS_SYMLINKAT = 474 - SYS_MKDIRAT = 475 - SYS_GETATTRLISTAT = 476 - SYS_PROC_TRACE_LOG = 477 - SYS_BSDTHREAD_CTL = 478 - SYS_OPENBYID_NP = 479 - SYS_RECVMSG_X = 480 - SYS_SENDMSG_X = 481 - SYS_THREAD_SELFUSAGE = 482 - SYS_CSRCTL = 483 - SYS_GUARDED_OPEN_DPROTECTED_NP = 484 - SYS_GUARDED_WRITE_NP = 485 - SYS_GUARDED_PWRITE_NP = 486 - SYS_GUARDED_WRITEV_NP = 487 - SYS_RENAMEATX_NP = 488 - SYS_MREMAP_ENCRYPTED = 489 - SYS_NETAGENT_TRIGGER = 490 - SYS_STACK_SNAPSHOT_WITH_CONFIG = 491 - SYS_MICROSTACKSHOT = 492 - SYS_GRAB_PGO_DATA = 493 - SYS_PERSONA = 494 - SYS_WORK_INTERVAL_CTL = 499 - SYS_GETENTROPY = 500 - SYS_NECP_OPEN = 501 - SYS_NECP_CLIENT_ACTION = 502 - SYS___NEXUS_OPEN = 503 - SYS___NEXUS_REGISTER = 504 - SYS___NEXUS_DEREGISTER = 505 - SYS___NEXUS_CREATE = 506 - SYS___NEXUS_DESTROY = 507 - SYS___NEXUS_GET_OPT = 508 - SYS___NEXUS_SET_OPT = 509 - SYS___CHANNEL_OPEN = 510 - SYS___CHANNEL_GET_INFO = 511 - SYS___CHANNEL_SYNC = 512 - SYS___CHANNEL_GET_OPT = 513 - SYS___CHANNEL_SET_OPT = 514 - SYS_ULOCK_WAIT = 515 - SYS_ULOCK_WAKE = 516 - SYS_FCLONEFILEAT = 517 - SYS_FS_SNAPSHOT = 518 - SYS_TERMINATE_WITH_PAYLOAD = 520 - SYS_ABORT_WITH_PAYLOAD = 521 - SYS_NECP_SESSION_OPEN = 522 - SYS_NECP_SESSION_ACTION = 523 - SYS_SETATTRLISTAT = 524 - SYS_NET_QOS_GUIDELINE = 525 - SYS_FMOUNT = 526 - SYS_NTP_ADJTIME = 527 - SYS_NTP_GETTIME = 528 - SYS_OS_FAULT_WITH_PAYLOAD = 529 - SYS_MAXSYSCALL = 530 - SYS_INVALID = 63 -) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go index 654dd3d..5edda76 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go @@ -1,10 +1,11 @@ // go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/sys/syscall.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,darwin +//go:build amd64 && darwin package unix +// Deprecated: Use libSystem wrappers instead of direct syscalls. const ( SYS_SYSCALL = 0 SYS_EXIT = 1 diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go deleted file mode 100644 index 103a72e..0000000 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go +++ /dev/null @@ -1,436 +0,0 @@ -// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build arm,darwin - -package unix - -const ( - SYS_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAIT4 = 7 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_CHDIR = 12 - SYS_FCHDIR = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_CHOWN = 16 - SYS_GETFSSTAT = 18 - SYS_GETPID = 20 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_GETEUID = 25 - SYS_PTRACE = 26 - SYS_RECVMSG = 27 - SYS_SENDMSG = 28 - SYS_RECVFROM = 29 - SYS_ACCEPT = 30 - SYS_GETPEERNAME = 31 - SYS_GETSOCKNAME = 32 - SYS_ACCESS = 33 - SYS_CHFLAGS = 34 - SYS_FCHFLAGS = 35 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_GETPPID = 39 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_GETEGID = 43 - SYS_SIGACTION = 46 - SYS_GETGID = 47 - SYS_SIGPROCMASK = 48 - SYS_GETLOGIN = 49 - SYS_SETLOGIN = 50 - SYS_ACCT = 51 - SYS_SIGPENDING = 52 - SYS_SIGALTSTACK = 53 - SYS_IOCTL = 54 - SYS_REBOOT = 55 - SYS_REVOKE = 56 - SYS_SYMLINK = 57 - SYS_READLINK = 58 - SYS_EXECVE = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_MSYNC = 65 - SYS_VFORK = 66 - SYS_MUNMAP = 73 - SYS_MPROTECT = 74 - SYS_MADVISE = 75 - SYS_MINCORE = 78 - SYS_GETGROUPS = 79 - SYS_SETGROUPS = 80 - SYS_GETPGRP = 81 - SYS_SETPGID = 82 - SYS_SETITIMER = 83 - SYS_SWAPON = 85 - SYS_GETITIMER = 86 - SYS_GETDTABLESIZE = 89 - SYS_DUP2 = 90 - SYS_FCNTL = 92 - SYS_SELECT = 93 - SYS_FSYNC = 95 - SYS_SETPRIORITY = 96 - SYS_SOCKET = 97 - SYS_CONNECT = 98 - SYS_GETPRIORITY = 100 - SYS_BIND = 104 - SYS_SETSOCKOPT = 105 - SYS_LISTEN = 106 - SYS_SIGSUSPEND = 111 - SYS_GETTIMEOFDAY = 116 - SYS_GETRUSAGE = 117 - SYS_GETSOCKOPT = 118 - SYS_READV = 120 - SYS_WRITEV = 121 - SYS_SETTIMEOFDAY = 122 - SYS_FCHOWN = 123 - SYS_FCHMOD = 124 - SYS_SETREUID = 126 - SYS_SETREGID = 127 - SYS_RENAME = 128 - SYS_FLOCK = 131 - SYS_MKFIFO = 132 - SYS_SENDTO = 133 - SYS_SHUTDOWN = 134 - SYS_SOCKETPAIR = 135 - SYS_MKDIR = 136 - SYS_RMDIR = 137 - SYS_UTIMES = 138 - SYS_FUTIMES = 139 - SYS_ADJTIME = 140 - SYS_GETHOSTUUID = 142 - SYS_SETSID = 147 - SYS_GETPGID = 151 - SYS_SETPRIVEXEC = 152 - SYS_PREAD = 153 - SYS_PWRITE = 154 - SYS_NFSSVC = 155 - SYS_STATFS = 157 - SYS_FSTATFS = 158 - SYS_UNMOUNT = 159 - SYS_GETFH = 161 - SYS_QUOTACTL = 165 - SYS_MOUNT = 167 - SYS_CSOPS = 169 - SYS_CSOPS_AUDITTOKEN = 170 - SYS_WAITID = 173 - SYS_KDEBUG_TYPEFILTER = 177 - SYS_KDEBUG_TRACE_STRING = 178 - SYS_KDEBUG_TRACE64 = 179 - SYS_KDEBUG_TRACE = 180 - SYS_SETGID = 181 - SYS_SETEGID = 182 - SYS_SETEUID = 183 - SYS_SIGRETURN = 184 - SYS_THREAD_SELFCOUNTS = 186 - SYS_FDATASYNC = 187 - SYS_STAT = 188 - SYS_FSTAT = 189 - SYS_LSTAT = 190 - SYS_PATHCONF = 191 - SYS_FPATHCONF = 192 - SYS_GETRLIMIT = 194 - SYS_SETRLIMIT = 195 - SYS_GETDIRENTRIES = 196 - SYS_MMAP = 197 - SYS_LSEEK = 199 - SYS_TRUNCATE = 200 - SYS_FTRUNCATE = 201 - SYS_SYSCTL = 202 - SYS_MLOCK = 203 - SYS_MUNLOCK = 204 - SYS_UNDELETE = 205 - SYS_OPEN_DPROTECTED_NP = 216 - SYS_GETATTRLIST = 220 - SYS_SETATTRLIST = 221 - SYS_GETDIRENTRIESATTR = 222 - SYS_EXCHANGEDATA = 223 - SYS_SEARCHFS = 225 - SYS_DELETE = 226 - SYS_COPYFILE = 227 - SYS_FGETATTRLIST = 228 - SYS_FSETATTRLIST = 229 - SYS_POLL = 230 - SYS_WATCHEVENT = 231 - SYS_WAITEVENT = 232 - SYS_MODWATCH = 233 - SYS_GETXATTR = 234 - SYS_FGETXATTR = 235 - SYS_SETXATTR = 236 - SYS_FSETXATTR = 237 - SYS_REMOVEXATTR = 238 - SYS_FREMOVEXATTR = 239 - SYS_LISTXATTR = 240 - SYS_FLISTXATTR = 241 - SYS_FSCTL = 242 - SYS_INITGROUPS = 243 - SYS_POSIX_SPAWN = 244 - SYS_FFSCTL = 245 - SYS_NFSCLNT = 247 - SYS_FHOPEN = 248 - SYS_MINHERIT = 250 - SYS_SEMSYS = 251 - SYS_MSGSYS = 252 - SYS_SHMSYS = 253 - SYS_SEMCTL = 254 - SYS_SEMGET = 255 - SYS_SEMOP = 256 - SYS_MSGCTL = 258 - SYS_MSGGET = 259 - SYS_MSGSND = 260 - SYS_MSGRCV = 261 - SYS_SHMAT = 262 - SYS_SHMCTL = 263 - SYS_SHMDT = 264 - SYS_SHMGET = 265 - SYS_SHM_OPEN = 266 - SYS_SHM_UNLINK = 267 - SYS_SEM_OPEN = 268 - SYS_SEM_CLOSE = 269 - SYS_SEM_UNLINK = 270 - SYS_SEM_WAIT = 271 - SYS_SEM_TRYWAIT = 272 - SYS_SEM_POST = 273 - SYS_SYSCTLBYNAME = 274 - SYS_OPEN_EXTENDED = 277 - SYS_UMASK_EXTENDED = 278 - SYS_STAT_EXTENDED = 279 - SYS_LSTAT_EXTENDED = 280 - SYS_FSTAT_EXTENDED = 281 - SYS_CHMOD_EXTENDED = 282 - SYS_FCHMOD_EXTENDED = 283 - SYS_ACCESS_EXTENDED = 284 - SYS_SETTID = 285 - SYS_GETTID = 286 - SYS_SETSGROUPS = 287 - SYS_GETSGROUPS = 288 - SYS_SETWGROUPS = 289 - SYS_GETWGROUPS = 290 - SYS_MKFIFO_EXTENDED = 291 - SYS_MKDIR_EXTENDED = 292 - SYS_IDENTITYSVC = 293 - SYS_SHARED_REGION_CHECK_NP = 294 - SYS_VM_PRESSURE_MONITOR = 296 - SYS_PSYNCH_RW_LONGRDLOCK = 297 - SYS_PSYNCH_RW_YIELDWRLOCK = 298 - SYS_PSYNCH_RW_DOWNGRADE = 299 - SYS_PSYNCH_RW_UPGRADE = 300 - SYS_PSYNCH_MUTEXWAIT = 301 - SYS_PSYNCH_MUTEXDROP = 302 - SYS_PSYNCH_CVBROAD = 303 - SYS_PSYNCH_CVSIGNAL = 304 - SYS_PSYNCH_CVWAIT = 305 - SYS_PSYNCH_RW_RDLOCK = 306 - SYS_PSYNCH_RW_WRLOCK = 307 - SYS_PSYNCH_RW_UNLOCK = 308 - SYS_PSYNCH_RW_UNLOCK2 = 309 - SYS_GETSID = 310 - SYS_SETTID_WITH_PID = 311 - SYS_PSYNCH_CVCLRPREPOST = 312 - SYS_AIO_FSYNC = 313 - SYS_AIO_RETURN = 314 - SYS_AIO_SUSPEND = 315 - SYS_AIO_CANCEL = 316 - SYS_AIO_ERROR = 317 - SYS_AIO_READ = 318 - SYS_AIO_WRITE = 319 - SYS_LIO_LISTIO = 320 - SYS_IOPOLICYSYS = 322 - SYS_PROCESS_POLICY = 323 - SYS_MLOCKALL = 324 - SYS_MUNLOCKALL = 325 - SYS_ISSETUGID = 327 - SYS___PTHREAD_KILL = 328 - SYS___PTHREAD_SIGMASK = 329 - SYS___SIGWAIT = 330 - SYS___DISABLE_THREADSIGNAL = 331 - SYS___PTHREAD_MARKCANCEL = 332 - SYS___PTHREAD_CANCELED = 333 - SYS___SEMWAIT_SIGNAL = 334 - SYS_PROC_INFO = 336 - SYS_SENDFILE = 337 - SYS_STAT64 = 338 - SYS_FSTAT64 = 339 - SYS_LSTAT64 = 340 - SYS_STAT64_EXTENDED = 341 - SYS_LSTAT64_EXTENDED = 342 - SYS_FSTAT64_EXTENDED = 343 - SYS_GETDIRENTRIES64 = 344 - SYS_STATFS64 = 345 - SYS_FSTATFS64 = 346 - SYS_GETFSSTAT64 = 347 - SYS___PTHREAD_CHDIR = 348 - SYS___PTHREAD_FCHDIR = 349 - SYS_AUDIT = 350 - SYS_AUDITON = 351 - SYS_GETAUID = 353 - SYS_SETAUID = 354 - SYS_GETAUDIT_ADDR = 357 - SYS_SETAUDIT_ADDR = 358 - SYS_AUDITCTL = 359 - SYS_BSDTHREAD_CREATE = 360 - SYS_BSDTHREAD_TERMINATE = 361 - SYS_KQUEUE = 362 - SYS_KEVENT = 363 - SYS_LCHOWN = 364 - SYS_BSDTHREAD_REGISTER = 366 - SYS_WORKQ_OPEN = 367 - SYS_WORKQ_KERNRETURN = 368 - SYS_KEVENT64 = 369 - SYS___OLD_SEMWAIT_SIGNAL = 370 - SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 - SYS_THREAD_SELFID = 372 - SYS_LEDGER = 373 - SYS_KEVENT_QOS = 374 - SYS_KEVENT_ID = 375 - SYS___MAC_EXECVE = 380 - SYS___MAC_SYSCALL = 381 - SYS___MAC_GET_FILE = 382 - SYS___MAC_SET_FILE = 383 - SYS___MAC_GET_LINK = 384 - SYS___MAC_SET_LINK = 385 - SYS___MAC_GET_PROC = 386 - SYS___MAC_SET_PROC = 387 - SYS___MAC_GET_FD = 388 - SYS___MAC_SET_FD = 389 - SYS___MAC_GET_PID = 390 - SYS_PSELECT = 394 - SYS_PSELECT_NOCANCEL = 395 - SYS_READ_NOCANCEL = 396 - SYS_WRITE_NOCANCEL = 397 - SYS_OPEN_NOCANCEL = 398 - SYS_CLOSE_NOCANCEL = 399 - SYS_WAIT4_NOCANCEL = 400 - SYS_RECVMSG_NOCANCEL = 401 - SYS_SENDMSG_NOCANCEL = 402 - SYS_RECVFROM_NOCANCEL = 403 - SYS_ACCEPT_NOCANCEL = 404 - SYS_MSYNC_NOCANCEL = 405 - SYS_FCNTL_NOCANCEL = 406 - SYS_SELECT_NOCANCEL = 407 - SYS_FSYNC_NOCANCEL = 408 - SYS_CONNECT_NOCANCEL = 409 - SYS_SIGSUSPEND_NOCANCEL = 410 - SYS_READV_NOCANCEL = 411 - SYS_WRITEV_NOCANCEL = 412 - SYS_SENDTO_NOCANCEL = 413 - SYS_PREAD_NOCANCEL = 414 - SYS_PWRITE_NOCANCEL = 415 - SYS_WAITID_NOCANCEL = 416 - SYS_POLL_NOCANCEL = 417 - SYS_MSGSND_NOCANCEL = 418 - SYS_MSGRCV_NOCANCEL = 419 - SYS_SEM_WAIT_NOCANCEL = 420 - SYS_AIO_SUSPEND_NOCANCEL = 421 - SYS___SIGWAIT_NOCANCEL = 422 - SYS___SEMWAIT_SIGNAL_NOCANCEL = 423 - SYS___MAC_MOUNT = 424 - SYS___MAC_GET_MOUNT = 425 - SYS___MAC_GETFSSTAT = 426 - SYS_FSGETPATH = 427 - SYS_AUDIT_SESSION_SELF = 428 - SYS_AUDIT_SESSION_JOIN = 429 - SYS_FILEPORT_MAKEPORT = 430 - SYS_FILEPORT_MAKEFD = 431 - SYS_AUDIT_SESSION_PORT = 432 - SYS_PID_SUSPEND = 433 - SYS_PID_RESUME = 434 - SYS_PID_HIBERNATE = 435 - SYS_PID_SHUTDOWN_SOCKETS = 436 - SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438 - SYS_KAS_INFO = 439 - SYS_MEMORYSTATUS_CONTROL = 440 - SYS_GUARDED_OPEN_NP = 441 - SYS_GUARDED_CLOSE_NP = 442 - SYS_GUARDED_KQUEUE_NP = 443 - SYS_CHANGE_FDGUARD_NP = 444 - SYS_USRCTL = 445 - SYS_PROC_RLIMIT_CONTROL = 446 - SYS_CONNECTX = 447 - SYS_DISCONNECTX = 448 - SYS_PEELOFF = 449 - SYS_SOCKET_DELEGATE = 450 - SYS_TELEMETRY = 451 - SYS_PROC_UUID_POLICY = 452 - SYS_MEMORYSTATUS_GET_LEVEL = 453 - SYS_SYSTEM_OVERRIDE = 454 - SYS_VFS_PURGE = 455 - SYS_SFI_CTL = 456 - SYS_SFI_PIDCTL = 457 - SYS_COALITION = 458 - SYS_COALITION_INFO = 459 - SYS_NECP_MATCH_POLICY = 460 - SYS_GETATTRLISTBULK = 461 - SYS_CLONEFILEAT = 462 - SYS_OPENAT = 463 - SYS_OPENAT_NOCANCEL = 464 - SYS_RENAMEAT = 465 - SYS_FACCESSAT = 466 - SYS_FCHMODAT = 467 - SYS_FCHOWNAT = 468 - SYS_FSTATAT = 469 - SYS_FSTATAT64 = 470 - SYS_LINKAT = 471 - SYS_UNLINKAT = 472 - SYS_READLINKAT = 473 - SYS_SYMLINKAT = 474 - SYS_MKDIRAT = 475 - SYS_GETATTRLISTAT = 476 - SYS_PROC_TRACE_LOG = 477 - SYS_BSDTHREAD_CTL = 478 - SYS_OPENBYID_NP = 479 - SYS_RECVMSG_X = 480 - SYS_SENDMSG_X = 481 - SYS_THREAD_SELFUSAGE = 482 - SYS_CSRCTL = 483 - SYS_GUARDED_OPEN_DPROTECTED_NP = 484 - SYS_GUARDED_WRITE_NP = 485 - SYS_GUARDED_PWRITE_NP = 486 - SYS_GUARDED_WRITEV_NP = 487 - SYS_RENAMEATX_NP = 488 - SYS_MREMAP_ENCRYPTED = 489 - SYS_NETAGENT_TRIGGER = 490 - SYS_STACK_SNAPSHOT_WITH_CONFIG = 491 - SYS_MICROSTACKSHOT = 492 - SYS_GRAB_PGO_DATA = 493 - SYS_PERSONA = 494 - SYS_WORK_INTERVAL_CTL = 499 - SYS_GETENTROPY = 500 - SYS_NECP_OPEN = 501 - SYS_NECP_CLIENT_ACTION = 502 - SYS___NEXUS_OPEN = 503 - SYS___NEXUS_REGISTER = 504 - SYS___NEXUS_DEREGISTER = 505 - SYS___NEXUS_CREATE = 506 - SYS___NEXUS_DESTROY = 507 - SYS___NEXUS_GET_OPT = 508 - SYS___NEXUS_SET_OPT = 509 - SYS___CHANNEL_OPEN = 510 - SYS___CHANNEL_GET_INFO = 511 - SYS___CHANNEL_SYNC = 512 - SYS___CHANNEL_GET_OPT = 513 - SYS___CHANNEL_SET_OPT = 514 - SYS_ULOCK_WAIT = 515 - SYS_ULOCK_WAKE = 516 - SYS_FCLONEFILEAT = 517 - SYS_FS_SNAPSHOT = 518 - SYS_TERMINATE_WITH_PAYLOAD = 520 - SYS_ABORT_WITH_PAYLOAD = 521 - SYS_NECP_SESSION_OPEN = 522 - SYS_NECP_SESSION_ACTION = 523 - SYS_SETATTRLISTAT = 524 - SYS_NET_QOS_GUIDELINE = 525 - SYS_FMOUNT = 526 - SYS_NTP_ADJTIME = 527 - SYS_NTP_GETTIME = 528 - SYS_OS_FAULT_WITH_PAYLOAD = 529 - SYS_MAXSYSCALL = 530 - SYS_INVALID = 63 -) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go index 7ab2130..0dc9e8b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go @@ -1,10 +1,11 @@ // go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,darwin +//go:build arm64 && darwin package unix +// Deprecated: Use libSystem wrappers instead of direct syscalls. const ( SYS_SYSCALL = 0 SYS_EXIT = 1 diff --git a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go index 464c9a9..308ddf3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go @@ -1,134 +1,130 @@ // go run mksysnum.go https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,dragonfly +//go:build amd64 && dragonfly package unix const ( - // SYS_NOSYS = 0; // { int nosys(void); } syscall nosys_args int - SYS_EXIT = 1 // { void exit(int rval); } - SYS_FORK = 2 // { int fork(void); } - SYS_READ = 3 // { ssize_t read(int fd, void *buf, size_t nbyte); } - SYS_WRITE = 4 // { ssize_t write(int fd, const void *buf, size_t nbyte); } - SYS_OPEN = 5 // { int open(char *path, int flags, int mode); } - SYS_CLOSE = 6 // { int close(int fd); } - SYS_WAIT4 = 7 // { int wait4(int pid, int *status, int options, struct rusage *rusage); } wait4 wait_args int - SYS_LINK = 9 // { int link(char *path, char *link); } - SYS_UNLINK = 10 // { int unlink(char *path); } - SYS_CHDIR = 12 // { int chdir(char *path); } - SYS_FCHDIR = 13 // { int fchdir(int fd); } - SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } - SYS_CHMOD = 15 // { int chmod(char *path, int mode); } - SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } - SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int - SYS_GETFSSTAT = 18 // { int getfsstat(struct statfs *buf, long bufsize, int flags); } - SYS_GETPID = 20 // { pid_t getpid(void); } - SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } - SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } - SYS_SETUID = 23 // { int setuid(uid_t uid); } - SYS_GETUID = 24 // { uid_t getuid(void); } - SYS_GETEUID = 25 // { uid_t geteuid(void); } - SYS_PTRACE = 26 // { int ptrace(int req, pid_t pid, caddr_t addr, int data); } - SYS_RECVMSG = 27 // { int recvmsg(int s, struct msghdr *msg, int flags); } - SYS_SENDMSG = 28 // { int sendmsg(int s, caddr_t msg, int flags); } - SYS_RECVFROM = 29 // { int recvfrom(int s, caddr_t buf, size_t len, int flags, caddr_t from, int *fromlenaddr); } - SYS_ACCEPT = 30 // { int accept(int s, caddr_t name, int *anamelen); } - SYS_GETPEERNAME = 31 // { int getpeername(int fdes, caddr_t asa, int *alen); } - SYS_GETSOCKNAME = 32 // { int getsockname(int fdes, caddr_t asa, int *alen); } - SYS_ACCESS = 33 // { int access(char *path, int flags); } - SYS_CHFLAGS = 34 // { int chflags(char *path, int flags); } - SYS_FCHFLAGS = 35 // { int fchflags(int fd, int flags); } - SYS_SYNC = 36 // { int sync(void); } - SYS_KILL = 37 // { int kill(int pid, int signum); } - SYS_GETPPID = 39 // { pid_t getppid(void); } - SYS_DUP = 41 // { int dup(int fd); } - SYS_PIPE = 42 // { int pipe(void); } - SYS_GETEGID = 43 // { gid_t getegid(void); } - SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } - SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } - SYS_GETGID = 47 // { gid_t getgid(void); } - SYS_GETLOGIN = 49 // { int getlogin(char *namebuf, u_int namelen); } - SYS_SETLOGIN = 50 // { int setlogin(char *namebuf); } - SYS_ACCT = 51 // { int acct(char *path); } - SYS_SIGALTSTACK = 53 // { int sigaltstack(stack_t *ss, stack_t *oss); } - SYS_IOCTL = 54 // { int ioctl(int fd, u_long com, caddr_t data); } - SYS_REBOOT = 55 // { int reboot(int opt); } - SYS_REVOKE = 56 // { int revoke(char *path); } - SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } - SYS_READLINK = 58 // { int readlink(char *path, char *buf, int count); } - SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } - SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int - SYS_CHROOT = 61 // { int chroot(char *path); } - SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } - SYS_VFORK = 66 // { pid_t vfork(void); } - SYS_SBRK = 69 // { int sbrk(int incr); } - SYS_SSTK = 70 // { int sstk(int incr); } - SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } - SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } - SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } - SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } - SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } - SYS_SETGROUPS = 80 // { int setgroups(u_int gidsetsize, gid_t *gidset); } - SYS_GETPGRP = 81 // { int getpgrp(void); } - SYS_SETPGID = 82 // { int setpgid(int pid, int pgid); } - SYS_SETITIMER = 83 // { int setitimer(u_int which, struct itimerval *itv, struct itimerval *oitv); } - SYS_SWAPON = 85 // { int swapon(char *name); } - SYS_GETITIMER = 86 // { int getitimer(u_int which, struct itimerval *itv); } - SYS_GETDTABLESIZE = 89 // { int getdtablesize(void); } - SYS_DUP2 = 90 // { int dup2(int from, int to); } - SYS_FCNTL = 92 // { int fcntl(int fd, int cmd, long arg); } - SYS_SELECT = 93 // { int select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } - SYS_FSYNC = 95 // { int fsync(int fd); } - SYS_SETPRIORITY = 96 // { int setpriority(int which, int who, int prio); } - SYS_SOCKET = 97 // { int socket(int domain, int type, int protocol); } - SYS_CONNECT = 98 // { int connect(int s, caddr_t name, int namelen); } - SYS_GETPRIORITY = 100 // { int getpriority(int which, int who); } - SYS_BIND = 104 // { int bind(int s, caddr_t name, int namelen); } - SYS_SETSOCKOPT = 105 // { int setsockopt(int s, int level, int name, caddr_t val, int valsize); } - SYS_LISTEN = 106 // { int listen(int s, int backlog); } - SYS_GETTIMEOFDAY = 116 // { int gettimeofday(struct timeval *tp, struct timezone *tzp); } - SYS_GETRUSAGE = 117 // { int getrusage(int who, struct rusage *rusage); } - SYS_GETSOCKOPT = 118 // { int getsockopt(int s, int level, int name, caddr_t val, int *avalsize); } - SYS_READV = 120 // { int readv(int fd, struct iovec *iovp, u_int iovcnt); } - SYS_WRITEV = 121 // { int writev(int fd, struct iovec *iovp, u_int iovcnt); } - SYS_SETTIMEOFDAY = 122 // { int settimeofday(struct timeval *tv, struct timezone *tzp); } - SYS_FCHOWN = 123 // { int fchown(int fd, int uid, int gid); } - SYS_FCHMOD = 124 // { int fchmod(int fd, int mode); } - SYS_SETREUID = 126 // { int setreuid(int ruid, int euid); } - SYS_SETREGID = 127 // { int setregid(int rgid, int egid); } - SYS_RENAME = 128 // { int rename(char *from, char *to); } - SYS_FLOCK = 131 // { int flock(int fd, int how); } - SYS_MKFIFO = 132 // { int mkfifo(char *path, int mode); } - SYS_SENDTO = 133 // { int sendto(int s, caddr_t buf, size_t len, int flags, caddr_t to, int tolen); } - SYS_SHUTDOWN = 134 // { int shutdown(int s, int how); } - SYS_SOCKETPAIR = 135 // { int socketpair(int domain, int type, int protocol, int *rsv); } - SYS_MKDIR = 136 // { int mkdir(char *path, int mode); } - SYS_RMDIR = 137 // { int rmdir(char *path); } - SYS_UTIMES = 138 // { int utimes(char *path, struct timeval *tptr); } - SYS_ADJTIME = 140 // { int adjtime(struct timeval *delta, struct timeval *olddelta); } - SYS_SETSID = 147 // { int setsid(void); } - SYS_QUOTACTL = 148 // { int quotactl(char *path, int cmd, int uid, caddr_t arg); } - SYS_STATFS = 157 // { int statfs(char *path, struct statfs *buf); } - SYS_FSTATFS = 158 // { int fstatfs(int fd, struct statfs *buf); } - SYS_GETFH = 161 // { int getfh(char *fname, struct fhandle *fhp); } - SYS_GETDOMAINNAME = 162 // { int getdomainname(char *domainname, int len); } - SYS_SETDOMAINNAME = 163 // { int setdomainname(char *domainname, int len); } - SYS_UNAME = 164 // { int uname(struct utsname *name); } - SYS_SYSARCH = 165 // { int sysarch(int op, char *parms); } - SYS_RTPRIO = 166 // { int rtprio(int function, pid_t pid, struct rtprio *rtp); } - SYS_EXTPREAD = 173 // { ssize_t extpread(int fd, void *buf, size_t nbyte, int flags, off_t offset); } - SYS_EXTPWRITE = 174 // { ssize_t extpwrite(int fd, const void *buf, size_t nbyte, int flags, off_t offset); } - SYS_NTP_ADJTIME = 176 // { int ntp_adjtime(struct timex *tp); } - SYS_SETGID = 181 // { int setgid(gid_t gid); } - SYS_SETEGID = 182 // { int setegid(gid_t egid); } - SYS_SETEUID = 183 // { int seteuid(uid_t euid); } - SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } - SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } - SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int - SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int - SYS_MMAP = 197 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); } - // SYS_NOSYS = 198; // { int nosys(void); } __syscall __syscall_args int + SYS_EXIT = 1 // { void exit(int rval); } + SYS_FORK = 2 // { int fork(void); } + SYS_READ = 3 // { ssize_t read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int open(char *path, int flags, int mode); } + SYS_CLOSE = 6 // { int close(int fd); } + SYS_WAIT4 = 7 // { int wait4(int pid, int *status, int options, struct rusage *rusage); } wait4 wait_args int + // SYS_NOSYS = 8; // { int nosys(void); } __nosys nosys_args int + SYS_LINK = 9 // { int link(char *path, char *link); } + SYS_UNLINK = 10 // { int unlink(char *path); } + SYS_CHDIR = 12 // { int chdir(char *path); } + SYS_FCHDIR = 13 // { int fchdir(int fd); } + SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } + SYS_CHMOD = 15 // { int chmod(char *path, int mode); } + SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } + SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int + SYS_GETFSSTAT = 18 // { int getfsstat(struct statfs *buf, long bufsize, int flags); } + SYS_GETPID = 20 // { pid_t getpid(void); } + SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } + SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } + SYS_SETUID = 23 // { int setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t getuid(void); } + SYS_GETEUID = 25 // { uid_t geteuid(void); } + SYS_PTRACE = 26 // { int ptrace(int req, pid_t pid, caddr_t addr, int data); } + SYS_RECVMSG = 27 // { int recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { int sendmsg(int s, caddr_t msg, int flags); } + SYS_RECVFROM = 29 // { int recvfrom(int s, caddr_t buf, size_t len, int flags, caddr_t from, int *fromlenaddr); } + SYS_ACCEPT = 30 // { int accept(int s, caddr_t name, int *anamelen); } + SYS_GETPEERNAME = 31 // { int getpeername(int fdes, caddr_t asa, int *alen); } + SYS_GETSOCKNAME = 32 // { int getsockname(int fdes, caddr_t asa, int *alen); } + SYS_ACCESS = 33 // { int access(char *path, int flags); } + SYS_CHFLAGS = 34 // { int chflags(const char *path, u_long flags); } + SYS_FCHFLAGS = 35 // { int fchflags(int fd, u_long flags); } + SYS_SYNC = 36 // { int sync(void); } + SYS_KILL = 37 // { int kill(int pid, int signum); } + SYS_GETPPID = 39 // { pid_t getppid(void); } + SYS_DUP = 41 // { int dup(int fd); } + SYS_PIPE = 42 // { int pipe(void); } + SYS_GETEGID = 43 // { gid_t getegid(void); } + SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, u_long offset, u_int scale); } + SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } + SYS_GETGID = 47 // { gid_t getgid(void); } + SYS_GETLOGIN = 49 // { int getlogin(char *namebuf, size_t namelen); } + SYS_SETLOGIN = 50 // { int setlogin(char *namebuf); } + SYS_ACCT = 51 // { int acct(char *path); } + SYS_SIGALTSTACK = 53 // { int sigaltstack(stack_t *ss, stack_t *oss); } + SYS_IOCTL = 54 // { int ioctl(int fd, u_long com, caddr_t data); } + SYS_REBOOT = 55 // { int reboot(int opt); } + SYS_REVOKE = 56 // { int revoke(char *path); } + SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } + SYS_READLINK = 58 // { int readlink(char *path, char *buf, int count); } + SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } + SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int + SYS_CHROOT = 61 // { int chroot(char *path); } + SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } + SYS_VFORK = 66 // { pid_t vfork(void); } + SYS_SBRK = 69 // { caddr_t sbrk(size_t incr); } + SYS_SSTK = 70 // { int sstk(size_t incr); } + SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } + SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } + SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int setgroups(u_int gidsetsize, gid_t *gidset); } + SYS_GETPGRP = 81 // { int getpgrp(void); } + SYS_SETPGID = 82 // { int setpgid(int pid, int pgid); } + SYS_SETITIMER = 83 // { int setitimer(u_int which, struct itimerval *itv, struct itimerval *oitv); } + SYS_SWAPON = 85 // { int swapon(char *name); } + SYS_GETITIMER = 86 // { int getitimer(u_int which, struct itimerval *itv); } + SYS_GETDTABLESIZE = 89 // { int getdtablesize(void); } + SYS_DUP2 = 90 // { int dup2(int from, int to); } + SYS_FCNTL = 92 // { int fcntl(int fd, int cmd, long arg); } + SYS_SELECT = 93 // { int select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_FSYNC = 95 // { int fsync(int fd); } + SYS_SETPRIORITY = 96 // { int setpriority(int which, int who, int prio); } + SYS_SOCKET = 97 // { int socket(int domain, int type, int protocol); } + SYS_CONNECT = 98 // { int connect(int s, caddr_t name, int namelen); } + SYS_GETPRIORITY = 100 // { int getpriority(int which, int who); } + SYS_BIND = 104 // { int bind(int s, caddr_t name, int namelen); } + SYS_SETSOCKOPT = 105 // { int setsockopt(int s, int level, int name, caddr_t val, int valsize); } + SYS_LISTEN = 106 // { int listen(int s, int backlog); } + SYS_GETTIMEOFDAY = 116 // { int gettimeofday(struct timeval *tp, struct timezone *tzp); } + SYS_GETRUSAGE = 117 // { int getrusage(int who, struct rusage *rusage); } + SYS_GETSOCKOPT = 118 // { int getsockopt(int s, int level, int name, caddr_t val, int *avalsize); } + SYS_READV = 120 // { int readv(int fd, struct iovec *iovp, u_int iovcnt); } + SYS_WRITEV = 121 // { int writev(int fd, struct iovec *iovp, u_int iovcnt); } + SYS_SETTIMEOFDAY = 122 // { int settimeofday(struct timeval *tv, struct timezone *tzp); } + SYS_FCHOWN = 123 // { int fchown(int fd, int uid, int gid); } + SYS_FCHMOD = 124 // { int fchmod(int fd, int mode); } + SYS_SETREUID = 126 // { int setreuid(int ruid, int euid); } + SYS_SETREGID = 127 // { int setregid(int rgid, int egid); } + SYS_RENAME = 128 // { int rename(char *from, char *to); } + SYS_FLOCK = 131 // { int flock(int fd, int how); } + SYS_MKFIFO = 132 // { int mkfifo(char *path, int mode); } + SYS_SENDTO = 133 // { int sendto(int s, caddr_t buf, size_t len, int flags, caddr_t to, int tolen); } + SYS_SHUTDOWN = 134 // { int shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int mkdir(char *path, int mode); } + SYS_RMDIR = 137 // { int rmdir(char *path); } + SYS_UTIMES = 138 // { int utimes(char *path, struct timeval *tptr); } + SYS_ADJTIME = 140 // { int adjtime(struct timeval *delta, struct timeval *olddelta); } + SYS_SETSID = 147 // { int setsid(void); } + SYS_QUOTACTL = 148 // { int quotactl(char *path, int cmd, int uid, caddr_t arg); } + SYS_STATFS = 157 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 158 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFH = 161 // { int getfh(char *fname, struct fhandle *fhp); } + SYS_SYSARCH = 165 // { int sysarch(int op, char *parms); } + SYS_RTPRIO = 166 // { int rtprio(int function, pid_t pid, struct rtprio *rtp); } + SYS_EXTPREAD = 173 // { ssize_t extpread(int fd, void *buf, size_t nbyte, int flags, off_t offset); } + SYS_EXTPWRITE = 174 // { ssize_t extpwrite(int fd, const void *buf, size_t nbyte, int flags, off_t offset); } + SYS_NTP_ADJTIME = 176 // { int ntp_adjtime(struct timex *tp); } + SYS_SETGID = 181 // { int setgid(gid_t gid); } + SYS_SETEGID = 182 // { int setegid(gid_t egid); } + SYS_SETEUID = 183 // { int seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } + SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } + SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int + SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int + SYS_MMAP = 197 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); } SYS_LSEEK = 199 // { off_t lseek(int fd, int pad, off_t offset, int whence); } SYS_TRUNCATE = 200 // { int truncate(char *path, int pad, off_t length); } SYS_FTRUNCATE = 201 // { int ftruncate(int fd, int pad, off_t length); } @@ -161,8 +157,8 @@ const ( SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } - SYS_EXTPREADV = 289 // { ssize_t extpreadv(int fd, struct iovec *iovp, u_int iovcnt, int flags, off_t offset); } - SYS_EXTPWRITEV = 290 // { ssize_t extpwritev(int fd, struct iovec *iovp,u_int iovcnt, int flags, off_t offset); } + SYS_EXTPREADV = 289 // { ssize_t extpreadv(int fd, const struct iovec *iovp, int iovcnt, int flags, off_t offset); } + SYS_EXTPWRITEV = 290 // { ssize_t extpwritev(int fd, const struct iovec *iovp, int iovcnt, int flags, off_t offset); } SYS_FHSTATFS = 297 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } SYS_MODNEXT = 300 // { int modnext(int modid); } @@ -225,7 +221,7 @@ const ( SYS_KQUEUE = 362 // { int kqueue(void); } SYS_KEVENT = 363 // { int kevent(int fd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } SYS_KENV = 390 // { int kenv(int what, const char *name, char *value, int len); } - SYS_LCHFLAGS = 391 // { int lchflags(char *path, int flags); } + SYS_LCHFLAGS = 391 // { int lchflags(const char *path, u_long flags); } SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } SYS_VARSYM_SET = 450 // { int varsym_set(int level, const char *name, const char *data); } @@ -302,7 +298,7 @@ const ( SYS_VMM_GUEST_CTL = 534 // { int vmm_guest_ctl(int op, struct vmm_guest_options *options); } SYS_VMM_GUEST_SYNC_ADDR = 535 // { int vmm_guest_sync_addr(long *dstaddr, long *srcaddr); } SYS_PROCCTL = 536 // { int procctl(idtype_t idtype, id_t id, int cmd, void *data); } - SYS_CHFLAGSAT = 537 // { int chflagsat(int fd, const char *path, int flags, int atflags);} + SYS_CHFLAGSAT = 537 // { int chflagsat(int fd, const char *path, u_long flags, int atflags);} SYS_PIPE2 = 538 // { int pipe2(int *fildes, int flags); } SYS_UTIMENSAT = 539 // { int utimensat(int fd, const char *path, const struct timespec *ts, int flags); } SYS_FUTIMENS = 540 // { int futimens(int fd, const struct timespec *ts); } @@ -312,4 +308,9 @@ const ( SYS_LWP_SETAFFINITY = 544 // { int lwp_setaffinity(pid_t pid, lwpid_t tid, const cpumask_t *mask); } SYS_LWP_GETAFFINITY = 545 // { int lwp_getaffinity(pid_t pid, lwpid_t tid, cpumask_t *mask); } SYS_LWP_CREATE2 = 546 // { int lwp_create2(struct lwp_params *params, const cpumask_t *mask); } + SYS_GETCPUCLOCKID = 547 // { int getcpuclockid(pid_t pid, lwpid_t lwp_id, clockid_t *clock_id); } + SYS_WAIT6 = 548 // { int wait6(idtype_t idtype, id_t id, int *status, int options, struct __wrusage *wrusage, siginfo_t *info); } + SYS_LWP_GETNAME = 549 // { int lwp_getname(lwpid_t tid, char *name, size_t len); } + SYS_GETRANDOM = 550 // { ssize_t getrandom(void *buf, size_t len, unsigned flags); } + SYS___REALPATH = 551 // { ssize_t __realpath(const char *path, char *buf, size_t len); } ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go index 9474974..418664e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go @@ -1,7 +1,7 @@ -// go run mksysnum.go https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master +// go run mksysnum.go https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,freebsd +//go:build 386 && freebsd package unix @@ -18,10 +18,9 @@ const ( SYS_UNLINK = 10 // { int unlink(char *path); } SYS_CHDIR = 12 // { int chdir(char *path); } SYS_FCHDIR = 13 // { int fchdir(int fd); } - SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } SYS_CHMOD = 15 // { int chmod(char *path, int mode); } SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } - SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int + SYS_BREAK = 17 // { caddr_t break(char *nsize); } SYS_GETPID = 20 // { pid_t getpid(void); } SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } @@ -42,7 +41,6 @@ const ( SYS_KILL = 37 // { int kill(int pid, int signum); } SYS_GETPPID = 39 // { pid_t getppid(void); } SYS_DUP = 41 // { int dup(u_int fd); } - SYS_PIPE = 42 // { int pipe(void); } SYS_GETEGID = 43 // { gid_t getegid(void); } SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } @@ -57,15 +55,14 @@ const ( SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } SYS_READLINK = 58 // { ssize_t readlink(char *path, char *buf, size_t count); } SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } - SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int + SYS_UMASK = 60 // { int umask(int newmask); } SYS_CHROOT = 61 // { int chroot(char *path); } SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } SYS_VFORK = 66 // { int vfork(void); } SYS_SBRK = 69 // { int sbrk(int incr); } SYS_SSTK = 70 // { int sstk(int incr); } - SYS_OVADVISE = 72 // { int ovadvise(int anom); } vadvise ovadvise_args int SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } - SYS_MPROTECT = 74 // { int mprotect(const void *addr, size_t len, int prot); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } @@ -123,14 +120,10 @@ const ( SYS_SETGID = 181 // { int setgid(gid_t gid); } SYS_SETEGID = 182 // { int setegid(gid_t egid); } SYS_SETEUID = 183 // { int seteuid(uid_t euid); } - SYS_STAT = 188 // { int stat(char *path, struct stat *ub); } - SYS_FSTAT = 189 // { int fstat(int fd, struct stat *sb); } - SYS_LSTAT = 190 // { int lstat(char *path, struct stat *ub); } SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int - SYS_GETDIRENTRIES = 196 // { int getdirentries(int fd, char *buf, u_int count, long *basep); } SYS___SYSCTL = 202 // { int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } __sysctl sysctl_args int SYS_MLOCK = 203 // { int mlock(const void *addr, size_t len); } SYS_MUNLOCK = 204 // { int munlock(const void *addr, size_t len); } @@ -142,12 +135,12 @@ const ( SYS_SEMOP = 222 // { int semop(int semid, struct sembuf *sops, size_t nsops); } SYS_MSGGET = 225 // { int msgget(key_t key, int msgflg); } SYS_MSGSND = 226 // { int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } - SYS_MSGRCV = 227 // { int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_MSGRCV = 227 // { ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } SYS_SHMAT = 228 // { int shmat(int shmid, const void *shmaddr, int shmflg); } SYS_SHMDT = 230 // { int shmdt(const void *shmaddr); } SYS_SHMGET = 231 // { int shmget(key_t key, size_t size, int shmflg); } SYS_CLOCK_GETTIME = 232 // { int clock_gettime(clockid_t clock_id, struct timespec *tp); } - SYS_CLOCK_SETTIME = 233 // { int clock_settime( clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_SETTIME = 233 // { int clock_settime(clockid_t clock_id, const struct timespec *tp); } SYS_CLOCK_GETRES = 234 // { int clock_getres(clockid_t clock_id, struct timespec *tp); } SYS_KTIMER_CREATE = 235 // { int ktimer_create(clockid_t clock_id, struct sigevent *evp, int *timerid); } SYS_KTIMER_DELETE = 236 // { int ktimer_delete(int timerid); } @@ -156,50 +149,44 @@ const ( SYS_KTIMER_GETOVERRUN = 239 // { int ktimer_getoverrun(int timerid); } SYS_NANOSLEEP = 240 // { int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); } - SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( struct ffclock_estimate *cest); } - SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( struct ffclock_estimate *cest); } + SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate(struct ffclock_estimate *cest); } + SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate(struct ffclock_estimate *cest); } SYS_CLOCK_NANOSLEEP = 244 // { int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp); } - SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,int which, clockid_t *clock_id); } + SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id, int which, clockid_t *clock_id); } SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); } SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, int inherit); } SYS_RFORK = 251 // { int rfork(int flags); } - SYS_OPENBSD_POLL = 252 // { int openbsd_poll(struct pollfd *fds, u_int nfds, int timeout); } SYS_ISSETUGID = 253 // { int issetugid(void); } SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } SYS_AIO_READ = 255 // { int aio_read(struct aiocb *aiocbp); } SYS_AIO_WRITE = 256 // { int aio_write(struct aiocb *aiocbp); } - SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } - SYS_GETDENTS = 272 // { int getdents(int fd, char *buf, size_t count); } + SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb* const *acb_list, int nent, struct sigevent *sig); } SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } - SYS_NSTAT = 278 // { int nstat(char *path, struct nstat *ub); } - SYS_NFSTAT = 279 // { int nfstat(int fd, struct nstat *sb); } - SYS_NLSTAT = 280 // { int nlstat(char *path, struct nstat *ub); } SYS_PREADV = 289 // { ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_PWRITEV = 290 // { ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } - SYS_FHSTAT = 299 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } SYS_MODNEXT = 300 // { int modnext(int modid); } - SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat *stat); } + SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat* stat); } SYS_MODFNEXT = 302 // { int modfnext(int modid); } SYS_MODFIND = 303 // { int modfind(const char *name); } SYS_KLDLOAD = 304 // { int kldload(const char *file); } SYS_KLDUNLOAD = 305 // { int kldunload(int fileid); } SYS_KLDFIND = 306 // { int kldfind(const char *file); } SYS_KLDNEXT = 307 // { int kldnext(int fileid); } - SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat* stat); } + SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat *stat); } SYS_KLDFIRSTMOD = 309 // { int kldfirstmod(int fileid); } SYS_GETSID = 310 // { int getsid(pid_t pid); } SYS_SETRESUID = 311 // { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } SYS_SETRESGID = 312 // { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } SYS_AIO_RETURN = 314 // { ssize_t aio_return(struct aiocb *aiocbp); } - SYS_AIO_SUSPEND = 315 // { int aio_suspend( struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } + SYS_AIO_SUSPEND = 315 // { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } SYS_AIO_CANCEL = 316 // { int aio_cancel(int fd, struct aiocb *aiocbp); } SYS_AIO_ERROR = 317 // { int aio_error(struct aiocb *aiocbp); } SYS_YIELD = 321 // { int yield(void); } SYS_MLOCKALL = 324 // { int mlockall(int how); } SYS_MUNLOCKALL = 325 // { int munlockall(void); } - SYS___GETCWD = 326 // { int __getcwd(char *buf, u_int buflen); } + SYS___GETCWD = 326 // { int __getcwd(char *buf, size_t buflen); } SYS_SCHED_SETPARAM = 327 // { int sched_setparam (pid_t pid, const struct sched_param *param); } SYS_SCHED_GETPARAM = 328 // { int sched_getparam (pid_t pid, struct sched_param *param); } SYS_SCHED_SETSCHEDULER = 329 // { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } @@ -225,14 +212,13 @@ const ( SYS___ACL_ACLCHECK_FILE = 353 // { int __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); } SYS___ACL_ACLCHECK_FD = 354 // { int __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); } SYS_EXTATTRCTL = 355 // { int extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); } - SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FILE = 358 // { int extattr_delete_file(const char *path, int attrnamespace, const char *attrname); } - SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete( struct aiocb **aiocbp, struct timespec *timeout); } + SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } SYS_GETRESUID = 360 // { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } SYS_GETRESGID = 361 // { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } SYS_KQUEUE = 362 // { int kqueue(void); } - SYS_KEVENT = 363 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } SYS_EXTATTR_SET_FD = 371 // { ssize_t extattr_set_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_GET_FD = 372 // { ssize_t extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FD = 373 // { int extattr_delete_fd(int fd, int attrnamespace, const char *attrname); } @@ -250,10 +236,6 @@ const ( SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } SYS_MAC_SYSCALL = 394 // { int mac_syscall(const char *policy, int call, void *arg); } - SYS_GETFSSTAT = 395 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } - SYS_STATFS = 396 // { int statfs(char *path, struct statfs *buf); } - SYS_FSTATFS = 397 // { int fstatfs(int fd, struct statfs *buf); } - SYS_FHSTATFS = 398 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } SYS_KSEM_CLOSE = 400 // { int ksem_close(semid_t id); } SYS_KSEM_POST = 401 // { int ksem_post(semid_t id); } SYS_KSEM_WAIT = 402 // { int ksem_wait(semid_t id); } @@ -266,14 +248,14 @@ const ( SYS___MAC_GET_PID = 409 // { int __mac_get_pid(pid_t pid, struct mac *mac_p); } SYS___MAC_GET_LINK = 410 // { int __mac_get_link(const char *path_p, struct mac *mac_p); } SYS___MAC_SET_LINK = 411 // { int __mac_set_link(const char *path_p, struct mac *mac_p); } - SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link( const char *path, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link(const char *path, int attrnamespace, const char *attrname); } SYS___MAC_EXECVE = 415 // { int __mac_execve(char *fname, char **argv, char **envv, struct mac *mac_p); } SYS_SIGACTION = 416 // { int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); } - SYS_SIGRETURN = 417 // { int sigreturn( const struct __ucontext *sigcntxp); } + SYS_SIGRETURN = 417 // { int sigreturn(const struct __ucontext *sigcntxp); } SYS_GETCONTEXT = 421 // { int getcontext(struct __ucontext *ucp); } - SYS_SETCONTEXT = 422 // { int setcontext( const struct __ucontext *ucp); } + SYS_SETCONTEXT = 422 // { int setcontext(const struct __ucontext *ucp); } SYS_SWAPCONTEXT = 423 // { int swapcontext(struct __ucontext *oucp, const struct __ucontext *ucp); } SYS_SWAPOFF = 424 // { int swapoff(const char *name); } SYS___ACL_GET_LINK = 425 // { int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); } @@ -287,10 +269,10 @@ const ( SYS_THR_KILL = 433 // { int thr_kill(long id, int sig); } SYS_JAIL_ATTACH = 436 // { int jail_attach(int jid); } SYS_EXTATTR_LIST_FD = 437 // { ssize_t extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file( const char *path, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link( const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); } SYS_KSEM_TIMEDWAIT = 441 // { int ksem_timedwait(semid_t id, const struct timespec *abstime); } - SYS_THR_SUSPEND = 442 // { int thr_suspend( const struct timespec *timeout); } + SYS_THR_SUSPEND = 442 // { int thr_suspend(const struct timespec *timeout); } SYS_THR_WAKE = 443 // { int thr_wake(long id); } SYS_KLDUNLOADF = 444 // { int kldunloadf(int fileid, int flags); } SYS_AUDIT = 445 // { int audit(const void *record, u_int length); } @@ -299,17 +281,17 @@ const ( SYS_SETAUID = 448 // { int setauid(uid_t *auid); } SYS_GETAUDIT = 449 // { int getaudit(struct auditinfo *auditinfo); } SYS_SETAUDIT = 450 // { int setaudit(struct auditinfo *auditinfo); } - SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } - SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } SYS_AUDITCTL = 453 // { int auditctl(char *path); } SYS__UMTX_OP = 454 // { int _umtx_op(void *obj, int op, u_long val, void *uaddr1, void *uaddr2); } SYS_THR_NEW = 455 // { int thr_new(struct thr_param *param, int param_size); } SYS_SIGQUEUE = 456 // { int sigqueue(pid_t pid, int signum, void *value); } SYS_KMQ_OPEN = 457 // { int kmq_open(const char *path, int flags, mode_t mode, const struct mq_attr *attr); } - SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } - SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } - SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len,unsigned msg_prio, const struct timespec *abs_timeout);} - SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } + SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } + SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } SYS_KMQ_UNLINK = 462 // { int kmq_unlink(const char *path); } SYS_ABORT2 = 463 // { int abort2(const char *why, int nargs, void **args); } SYS_THR_SET_NAME = 464 // { int thr_set_name(long id, const char *name); } @@ -318,7 +300,7 @@ const ( SYS_SCTP_PEELOFF = 471 // { int sctp_peeloff(int sd, uint32_t name); } SYS_SCTP_GENERIC_SENDMSG = 472 // { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } SYS_SCTP_GENERIC_SENDMSG_IOV = 473 // { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } - SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr * from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } + SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr *from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } SYS_PREAD = 475 // { ssize_t pread(int fd, void *buf, size_t nbyte, off_t offset); } SYS_PWRITE = 476 // { ssize_t pwrite(int fd, const void *buf, size_t nbyte, off_t offset); } SYS_MMAP = 477 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos); } @@ -337,14 +319,12 @@ const ( SYS_FCHMODAT = 490 // { int fchmodat(int fd, char *path, mode_t mode, int flag); } SYS_FCHOWNAT = 491 // { int fchownat(int fd, char *path, uid_t uid, gid_t gid, int flag); } SYS_FEXECVE = 492 // { int fexecve(int fd, char **argv, char **envv); } - SYS_FSTATAT = 493 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } SYS_FUTIMESAT = 494 // { int futimesat(int fd, char *path, struct timeval *times); } SYS_LINKAT = 495 // { int linkat(int fd1, char *path1, int fd2, char *path2, int flag); } SYS_MKDIRAT = 496 // { int mkdirat(int fd, char *path, mode_t mode); } SYS_MKFIFOAT = 497 // { int mkfifoat(int fd, char *path, mode_t mode); } - SYS_MKNODAT = 498 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } SYS_OPENAT = 499 // { int openat(int fd, char *path, int flag, mode_t mode); } - SYS_READLINKAT = 500 // { int readlinkat(int fd, char *path, char *buf, size_t bufsize); } + SYS_READLINKAT = 500 // { ssize_t readlinkat(int fd, char *path, char *buf, size_t bufsize); } SYS_RENAMEAT = 501 // { int renameat(int oldfd, char *old, int newfd, char *new); } SYS_SYMLINKAT = 502 // { int symlinkat(char *path1, int fd, char *path2); } SYS_UNLINKAT = 503 // { int unlinkat(int fd, char *path, int flag); } @@ -390,7 +370,24 @@ const ( SYS_PPOLL = 545 // { int ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *set); } SYS_FUTIMENS = 546 // { int futimens(int fd, struct timespec *times); } SYS_UTIMENSAT = 547 // { int utimensat(int fd, char *path, struct timespec *times, int flag); } - SYS_NUMA_GETAFFINITY = 548 // { int numa_getaffinity(cpuwhich_t which, id_t id, struct vm_domain_policy_entry *policy); } - SYS_NUMA_SETAFFINITY = 549 // { int numa_setaffinity(cpuwhich_t which, id_t id, const struct vm_domain_policy_entry *policy); } SYS_FDATASYNC = 550 // { int fdatasync(int fd); } + SYS_FSTAT = 551 // { int fstat(int fd, struct stat *sb); } + SYS_FSTATAT = 552 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } + SYS_FHSTAT = 553 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } + SYS_GETDIRENTRIES = 554 // { ssize_t getdirentries(int fd, char *buf, size_t count, off_t *basep); } + SYS_STATFS = 555 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 556 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFSSTAT = 557 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } + SYS_FHSTATFS = 558 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } + SYS_MKNODAT = 559 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } + SYS_KEVENT = 560 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_CPUSET_GETDOMAIN = 561 // { int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int *policy); } + SYS_CPUSET_SETDOMAIN = 562 // { int cpuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int policy); } + SYS_GETRANDOM = 563 // { int getrandom(void *buf, size_t buflen, unsigned int flags); } + SYS_GETFHAT = 564 // { int getfhat(int fd, char *path, struct fhandle *fhp, int flags); } + SYS_FHLINK = 565 // { int fhlink(struct fhandle *fhp, const char *to); } + SYS_FHLINKAT = 566 // { int fhlinkat(struct fhandle *fhp, int tofd, const char *to,); } + SYS_FHREADLINK = 567 // { int fhreadlink(struct fhandle *fhp, char *buf, size_t bufsize); } + SYS___SYSCTLBYNAME = 570 // { int __sysctlbyname(const char *name, size_t namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_CLOSE_RANGE = 575 // { int close_range(u_int lowfd, u_int highfd, int flags); } ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go index 48a7bea..34d0b86 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go @@ -1,7 +1,7 @@ -// go run mksysnum.go https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master +// go run mksysnum.go https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,freebsd +//go:build amd64 && freebsd package unix @@ -18,10 +18,9 @@ const ( SYS_UNLINK = 10 // { int unlink(char *path); } SYS_CHDIR = 12 // { int chdir(char *path); } SYS_FCHDIR = 13 // { int fchdir(int fd); } - SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } SYS_CHMOD = 15 // { int chmod(char *path, int mode); } SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } - SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int + SYS_BREAK = 17 // { caddr_t break(char *nsize); } SYS_GETPID = 20 // { pid_t getpid(void); } SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } @@ -42,7 +41,6 @@ const ( SYS_KILL = 37 // { int kill(int pid, int signum); } SYS_GETPPID = 39 // { pid_t getppid(void); } SYS_DUP = 41 // { int dup(u_int fd); } - SYS_PIPE = 42 // { int pipe(void); } SYS_GETEGID = 43 // { gid_t getegid(void); } SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } @@ -57,15 +55,14 @@ const ( SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } SYS_READLINK = 58 // { ssize_t readlink(char *path, char *buf, size_t count); } SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } - SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int + SYS_UMASK = 60 // { int umask(int newmask); } SYS_CHROOT = 61 // { int chroot(char *path); } SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } SYS_VFORK = 66 // { int vfork(void); } SYS_SBRK = 69 // { int sbrk(int incr); } SYS_SSTK = 70 // { int sstk(int incr); } - SYS_OVADVISE = 72 // { int ovadvise(int anom); } vadvise ovadvise_args int SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } - SYS_MPROTECT = 74 // { int mprotect(const void *addr, size_t len, int prot); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } @@ -123,14 +120,10 @@ const ( SYS_SETGID = 181 // { int setgid(gid_t gid); } SYS_SETEGID = 182 // { int setegid(gid_t egid); } SYS_SETEUID = 183 // { int seteuid(uid_t euid); } - SYS_STAT = 188 // { int stat(char *path, struct stat *ub); } - SYS_FSTAT = 189 // { int fstat(int fd, struct stat *sb); } - SYS_LSTAT = 190 // { int lstat(char *path, struct stat *ub); } SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int - SYS_GETDIRENTRIES = 196 // { int getdirentries(int fd, char *buf, u_int count, long *basep); } SYS___SYSCTL = 202 // { int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } __sysctl sysctl_args int SYS_MLOCK = 203 // { int mlock(const void *addr, size_t len); } SYS_MUNLOCK = 204 // { int munlock(const void *addr, size_t len); } @@ -142,12 +135,12 @@ const ( SYS_SEMOP = 222 // { int semop(int semid, struct sembuf *sops, size_t nsops); } SYS_MSGGET = 225 // { int msgget(key_t key, int msgflg); } SYS_MSGSND = 226 // { int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } - SYS_MSGRCV = 227 // { int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_MSGRCV = 227 // { ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } SYS_SHMAT = 228 // { int shmat(int shmid, const void *shmaddr, int shmflg); } SYS_SHMDT = 230 // { int shmdt(const void *shmaddr); } SYS_SHMGET = 231 // { int shmget(key_t key, size_t size, int shmflg); } SYS_CLOCK_GETTIME = 232 // { int clock_gettime(clockid_t clock_id, struct timespec *tp); } - SYS_CLOCK_SETTIME = 233 // { int clock_settime( clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_SETTIME = 233 // { int clock_settime(clockid_t clock_id, const struct timespec *tp); } SYS_CLOCK_GETRES = 234 // { int clock_getres(clockid_t clock_id, struct timespec *tp); } SYS_KTIMER_CREATE = 235 // { int ktimer_create(clockid_t clock_id, struct sigevent *evp, int *timerid); } SYS_KTIMER_DELETE = 236 // { int ktimer_delete(int timerid); } @@ -156,50 +149,44 @@ const ( SYS_KTIMER_GETOVERRUN = 239 // { int ktimer_getoverrun(int timerid); } SYS_NANOSLEEP = 240 // { int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); } - SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( struct ffclock_estimate *cest); } - SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( struct ffclock_estimate *cest); } + SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate(struct ffclock_estimate *cest); } + SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate(struct ffclock_estimate *cest); } SYS_CLOCK_NANOSLEEP = 244 // { int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp); } - SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,int which, clockid_t *clock_id); } + SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id, int which, clockid_t *clock_id); } SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); } SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, int inherit); } SYS_RFORK = 251 // { int rfork(int flags); } - SYS_OPENBSD_POLL = 252 // { int openbsd_poll(struct pollfd *fds, u_int nfds, int timeout); } SYS_ISSETUGID = 253 // { int issetugid(void); } SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } SYS_AIO_READ = 255 // { int aio_read(struct aiocb *aiocbp); } SYS_AIO_WRITE = 256 // { int aio_write(struct aiocb *aiocbp); } - SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } - SYS_GETDENTS = 272 // { int getdents(int fd, char *buf, size_t count); } + SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb* const *acb_list, int nent, struct sigevent *sig); } SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } - SYS_NSTAT = 278 // { int nstat(char *path, struct nstat *ub); } - SYS_NFSTAT = 279 // { int nfstat(int fd, struct nstat *sb); } - SYS_NLSTAT = 280 // { int nlstat(char *path, struct nstat *ub); } SYS_PREADV = 289 // { ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_PWRITEV = 290 // { ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } - SYS_FHSTAT = 299 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } SYS_MODNEXT = 300 // { int modnext(int modid); } - SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat *stat); } + SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat* stat); } SYS_MODFNEXT = 302 // { int modfnext(int modid); } SYS_MODFIND = 303 // { int modfind(const char *name); } SYS_KLDLOAD = 304 // { int kldload(const char *file); } SYS_KLDUNLOAD = 305 // { int kldunload(int fileid); } SYS_KLDFIND = 306 // { int kldfind(const char *file); } SYS_KLDNEXT = 307 // { int kldnext(int fileid); } - SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat* stat); } + SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat *stat); } SYS_KLDFIRSTMOD = 309 // { int kldfirstmod(int fileid); } SYS_GETSID = 310 // { int getsid(pid_t pid); } SYS_SETRESUID = 311 // { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } SYS_SETRESGID = 312 // { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } SYS_AIO_RETURN = 314 // { ssize_t aio_return(struct aiocb *aiocbp); } - SYS_AIO_SUSPEND = 315 // { int aio_suspend( struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } + SYS_AIO_SUSPEND = 315 // { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } SYS_AIO_CANCEL = 316 // { int aio_cancel(int fd, struct aiocb *aiocbp); } SYS_AIO_ERROR = 317 // { int aio_error(struct aiocb *aiocbp); } SYS_YIELD = 321 // { int yield(void); } SYS_MLOCKALL = 324 // { int mlockall(int how); } SYS_MUNLOCKALL = 325 // { int munlockall(void); } - SYS___GETCWD = 326 // { int __getcwd(char *buf, u_int buflen); } + SYS___GETCWD = 326 // { int __getcwd(char *buf, size_t buflen); } SYS_SCHED_SETPARAM = 327 // { int sched_setparam (pid_t pid, const struct sched_param *param); } SYS_SCHED_GETPARAM = 328 // { int sched_getparam (pid_t pid, struct sched_param *param); } SYS_SCHED_SETSCHEDULER = 329 // { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } @@ -225,14 +212,13 @@ const ( SYS___ACL_ACLCHECK_FILE = 353 // { int __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); } SYS___ACL_ACLCHECK_FD = 354 // { int __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); } SYS_EXTATTRCTL = 355 // { int extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); } - SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FILE = 358 // { int extattr_delete_file(const char *path, int attrnamespace, const char *attrname); } - SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete( struct aiocb **aiocbp, struct timespec *timeout); } + SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } SYS_GETRESUID = 360 // { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } SYS_GETRESGID = 361 // { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } SYS_KQUEUE = 362 // { int kqueue(void); } - SYS_KEVENT = 363 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } SYS_EXTATTR_SET_FD = 371 // { ssize_t extattr_set_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_GET_FD = 372 // { ssize_t extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FD = 373 // { int extattr_delete_fd(int fd, int attrnamespace, const char *attrname); } @@ -250,10 +236,6 @@ const ( SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } SYS_MAC_SYSCALL = 394 // { int mac_syscall(const char *policy, int call, void *arg); } - SYS_GETFSSTAT = 395 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } - SYS_STATFS = 396 // { int statfs(char *path, struct statfs *buf); } - SYS_FSTATFS = 397 // { int fstatfs(int fd, struct statfs *buf); } - SYS_FHSTATFS = 398 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } SYS_KSEM_CLOSE = 400 // { int ksem_close(semid_t id); } SYS_KSEM_POST = 401 // { int ksem_post(semid_t id); } SYS_KSEM_WAIT = 402 // { int ksem_wait(semid_t id); } @@ -266,14 +248,14 @@ const ( SYS___MAC_GET_PID = 409 // { int __mac_get_pid(pid_t pid, struct mac *mac_p); } SYS___MAC_GET_LINK = 410 // { int __mac_get_link(const char *path_p, struct mac *mac_p); } SYS___MAC_SET_LINK = 411 // { int __mac_set_link(const char *path_p, struct mac *mac_p); } - SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link( const char *path, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link(const char *path, int attrnamespace, const char *attrname); } SYS___MAC_EXECVE = 415 // { int __mac_execve(char *fname, char **argv, char **envv, struct mac *mac_p); } SYS_SIGACTION = 416 // { int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); } - SYS_SIGRETURN = 417 // { int sigreturn( const struct __ucontext *sigcntxp); } + SYS_SIGRETURN = 417 // { int sigreturn(const struct __ucontext *sigcntxp); } SYS_GETCONTEXT = 421 // { int getcontext(struct __ucontext *ucp); } - SYS_SETCONTEXT = 422 // { int setcontext( const struct __ucontext *ucp); } + SYS_SETCONTEXT = 422 // { int setcontext(const struct __ucontext *ucp); } SYS_SWAPCONTEXT = 423 // { int swapcontext(struct __ucontext *oucp, const struct __ucontext *ucp); } SYS_SWAPOFF = 424 // { int swapoff(const char *name); } SYS___ACL_GET_LINK = 425 // { int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); } @@ -287,10 +269,10 @@ const ( SYS_THR_KILL = 433 // { int thr_kill(long id, int sig); } SYS_JAIL_ATTACH = 436 // { int jail_attach(int jid); } SYS_EXTATTR_LIST_FD = 437 // { ssize_t extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file( const char *path, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link( const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); } SYS_KSEM_TIMEDWAIT = 441 // { int ksem_timedwait(semid_t id, const struct timespec *abstime); } - SYS_THR_SUSPEND = 442 // { int thr_suspend( const struct timespec *timeout); } + SYS_THR_SUSPEND = 442 // { int thr_suspend(const struct timespec *timeout); } SYS_THR_WAKE = 443 // { int thr_wake(long id); } SYS_KLDUNLOADF = 444 // { int kldunloadf(int fileid, int flags); } SYS_AUDIT = 445 // { int audit(const void *record, u_int length); } @@ -299,17 +281,17 @@ const ( SYS_SETAUID = 448 // { int setauid(uid_t *auid); } SYS_GETAUDIT = 449 // { int getaudit(struct auditinfo *auditinfo); } SYS_SETAUDIT = 450 // { int setaudit(struct auditinfo *auditinfo); } - SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } - SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } SYS_AUDITCTL = 453 // { int auditctl(char *path); } SYS__UMTX_OP = 454 // { int _umtx_op(void *obj, int op, u_long val, void *uaddr1, void *uaddr2); } SYS_THR_NEW = 455 // { int thr_new(struct thr_param *param, int param_size); } SYS_SIGQUEUE = 456 // { int sigqueue(pid_t pid, int signum, void *value); } SYS_KMQ_OPEN = 457 // { int kmq_open(const char *path, int flags, mode_t mode, const struct mq_attr *attr); } - SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } - SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } - SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len,unsigned msg_prio, const struct timespec *abs_timeout);} - SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } + SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } + SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } SYS_KMQ_UNLINK = 462 // { int kmq_unlink(const char *path); } SYS_ABORT2 = 463 // { int abort2(const char *why, int nargs, void **args); } SYS_THR_SET_NAME = 464 // { int thr_set_name(long id, const char *name); } @@ -318,7 +300,7 @@ const ( SYS_SCTP_PEELOFF = 471 // { int sctp_peeloff(int sd, uint32_t name); } SYS_SCTP_GENERIC_SENDMSG = 472 // { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } SYS_SCTP_GENERIC_SENDMSG_IOV = 473 // { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } - SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr * from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } + SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr *from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } SYS_PREAD = 475 // { ssize_t pread(int fd, void *buf, size_t nbyte, off_t offset); } SYS_PWRITE = 476 // { ssize_t pwrite(int fd, const void *buf, size_t nbyte, off_t offset); } SYS_MMAP = 477 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos); } @@ -337,14 +319,12 @@ const ( SYS_FCHMODAT = 490 // { int fchmodat(int fd, char *path, mode_t mode, int flag); } SYS_FCHOWNAT = 491 // { int fchownat(int fd, char *path, uid_t uid, gid_t gid, int flag); } SYS_FEXECVE = 492 // { int fexecve(int fd, char **argv, char **envv); } - SYS_FSTATAT = 493 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } SYS_FUTIMESAT = 494 // { int futimesat(int fd, char *path, struct timeval *times); } SYS_LINKAT = 495 // { int linkat(int fd1, char *path1, int fd2, char *path2, int flag); } SYS_MKDIRAT = 496 // { int mkdirat(int fd, char *path, mode_t mode); } SYS_MKFIFOAT = 497 // { int mkfifoat(int fd, char *path, mode_t mode); } - SYS_MKNODAT = 498 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } SYS_OPENAT = 499 // { int openat(int fd, char *path, int flag, mode_t mode); } - SYS_READLINKAT = 500 // { int readlinkat(int fd, char *path, char *buf, size_t bufsize); } + SYS_READLINKAT = 500 // { ssize_t readlinkat(int fd, char *path, char *buf, size_t bufsize); } SYS_RENAMEAT = 501 // { int renameat(int oldfd, char *old, int newfd, char *new); } SYS_SYMLINKAT = 502 // { int symlinkat(char *path1, int fd, char *path2); } SYS_UNLINKAT = 503 // { int unlinkat(int fd, char *path, int flag); } @@ -390,7 +370,24 @@ const ( SYS_PPOLL = 545 // { int ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *set); } SYS_FUTIMENS = 546 // { int futimens(int fd, struct timespec *times); } SYS_UTIMENSAT = 547 // { int utimensat(int fd, char *path, struct timespec *times, int flag); } - SYS_NUMA_GETAFFINITY = 548 // { int numa_getaffinity(cpuwhich_t which, id_t id, struct vm_domain_policy_entry *policy); } - SYS_NUMA_SETAFFINITY = 549 // { int numa_setaffinity(cpuwhich_t which, id_t id, const struct vm_domain_policy_entry *policy); } SYS_FDATASYNC = 550 // { int fdatasync(int fd); } + SYS_FSTAT = 551 // { int fstat(int fd, struct stat *sb); } + SYS_FSTATAT = 552 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } + SYS_FHSTAT = 553 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } + SYS_GETDIRENTRIES = 554 // { ssize_t getdirentries(int fd, char *buf, size_t count, off_t *basep); } + SYS_STATFS = 555 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 556 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFSSTAT = 557 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } + SYS_FHSTATFS = 558 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } + SYS_MKNODAT = 559 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } + SYS_KEVENT = 560 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_CPUSET_GETDOMAIN = 561 // { int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int *policy); } + SYS_CPUSET_SETDOMAIN = 562 // { int cpuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int policy); } + SYS_GETRANDOM = 563 // { int getrandom(void *buf, size_t buflen, unsigned int flags); } + SYS_GETFHAT = 564 // { int getfhat(int fd, char *path, struct fhandle *fhp, int flags); } + SYS_FHLINK = 565 // { int fhlink(struct fhandle *fhp, const char *to); } + SYS_FHLINKAT = 566 // { int fhlinkat(struct fhandle *fhp, int tofd, const char *to,); } + SYS_FHREADLINK = 567 // { int fhreadlink(struct fhandle *fhp, char *buf, size_t bufsize); } + SYS___SYSCTLBYNAME = 570 // { int __sysctlbyname(const char *name, size_t namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_CLOSE_RANGE = 575 // { int close_range(u_int lowfd, u_int highfd, int flags); } ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go index 4a6dfd4..b71cf45 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go @@ -1,7 +1,7 @@ -// go run mksysnum.go https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master +// go run mksysnum.go https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,freebsd +//go:build arm && freebsd package unix @@ -18,10 +18,9 @@ const ( SYS_UNLINK = 10 // { int unlink(char *path); } SYS_CHDIR = 12 // { int chdir(char *path); } SYS_FCHDIR = 13 // { int fchdir(int fd); } - SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } SYS_CHMOD = 15 // { int chmod(char *path, int mode); } SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } - SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int + SYS_BREAK = 17 // { caddr_t break(char *nsize); } SYS_GETPID = 20 // { pid_t getpid(void); } SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } @@ -42,7 +41,6 @@ const ( SYS_KILL = 37 // { int kill(int pid, int signum); } SYS_GETPPID = 39 // { pid_t getppid(void); } SYS_DUP = 41 // { int dup(u_int fd); } - SYS_PIPE = 42 // { int pipe(void); } SYS_GETEGID = 43 // { gid_t getegid(void); } SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } @@ -57,15 +55,14 @@ const ( SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } SYS_READLINK = 58 // { ssize_t readlink(char *path, char *buf, size_t count); } SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } - SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int + SYS_UMASK = 60 // { int umask(int newmask); } SYS_CHROOT = 61 // { int chroot(char *path); } SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } SYS_VFORK = 66 // { int vfork(void); } SYS_SBRK = 69 // { int sbrk(int incr); } SYS_SSTK = 70 // { int sstk(int incr); } - SYS_OVADVISE = 72 // { int ovadvise(int anom); } vadvise ovadvise_args int SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } - SYS_MPROTECT = 74 // { int mprotect(const void *addr, size_t len, int prot); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } @@ -123,14 +120,10 @@ const ( SYS_SETGID = 181 // { int setgid(gid_t gid); } SYS_SETEGID = 182 // { int setegid(gid_t egid); } SYS_SETEUID = 183 // { int seteuid(uid_t euid); } - SYS_STAT = 188 // { int stat(char *path, struct stat *ub); } - SYS_FSTAT = 189 // { int fstat(int fd, struct stat *sb); } - SYS_LSTAT = 190 // { int lstat(char *path, struct stat *ub); } SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int - SYS_GETDIRENTRIES = 196 // { int getdirentries(int fd, char *buf, u_int count, long *basep); } SYS___SYSCTL = 202 // { int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } __sysctl sysctl_args int SYS_MLOCK = 203 // { int mlock(const void *addr, size_t len); } SYS_MUNLOCK = 204 // { int munlock(const void *addr, size_t len); } @@ -142,12 +135,12 @@ const ( SYS_SEMOP = 222 // { int semop(int semid, struct sembuf *sops, size_t nsops); } SYS_MSGGET = 225 // { int msgget(key_t key, int msgflg); } SYS_MSGSND = 226 // { int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } - SYS_MSGRCV = 227 // { int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_MSGRCV = 227 // { ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } SYS_SHMAT = 228 // { int shmat(int shmid, const void *shmaddr, int shmflg); } SYS_SHMDT = 230 // { int shmdt(const void *shmaddr); } SYS_SHMGET = 231 // { int shmget(key_t key, size_t size, int shmflg); } SYS_CLOCK_GETTIME = 232 // { int clock_gettime(clockid_t clock_id, struct timespec *tp); } - SYS_CLOCK_SETTIME = 233 // { int clock_settime( clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_SETTIME = 233 // { int clock_settime(clockid_t clock_id, const struct timespec *tp); } SYS_CLOCK_GETRES = 234 // { int clock_getres(clockid_t clock_id, struct timespec *tp); } SYS_KTIMER_CREATE = 235 // { int ktimer_create(clockid_t clock_id, struct sigevent *evp, int *timerid); } SYS_KTIMER_DELETE = 236 // { int ktimer_delete(int timerid); } @@ -156,50 +149,44 @@ const ( SYS_KTIMER_GETOVERRUN = 239 // { int ktimer_getoverrun(int timerid); } SYS_NANOSLEEP = 240 // { int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); } - SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( struct ffclock_estimate *cest); } - SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( struct ffclock_estimate *cest); } + SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate(struct ffclock_estimate *cest); } + SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate(struct ffclock_estimate *cest); } SYS_CLOCK_NANOSLEEP = 244 // { int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp); } - SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,int which, clockid_t *clock_id); } + SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id, int which, clockid_t *clock_id); } SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); } SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, int inherit); } SYS_RFORK = 251 // { int rfork(int flags); } - SYS_OPENBSD_POLL = 252 // { int openbsd_poll(struct pollfd *fds, u_int nfds, int timeout); } SYS_ISSETUGID = 253 // { int issetugid(void); } SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } SYS_AIO_READ = 255 // { int aio_read(struct aiocb *aiocbp); } SYS_AIO_WRITE = 256 // { int aio_write(struct aiocb *aiocbp); } - SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } - SYS_GETDENTS = 272 // { int getdents(int fd, char *buf, size_t count); } + SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb* const *acb_list, int nent, struct sigevent *sig); } SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } - SYS_NSTAT = 278 // { int nstat(char *path, struct nstat *ub); } - SYS_NFSTAT = 279 // { int nfstat(int fd, struct nstat *sb); } - SYS_NLSTAT = 280 // { int nlstat(char *path, struct nstat *ub); } SYS_PREADV = 289 // { ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_PWRITEV = 290 // { ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } - SYS_FHSTAT = 299 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } SYS_MODNEXT = 300 // { int modnext(int modid); } - SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat *stat); } + SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat* stat); } SYS_MODFNEXT = 302 // { int modfnext(int modid); } SYS_MODFIND = 303 // { int modfind(const char *name); } SYS_KLDLOAD = 304 // { int kldload(const char *file); } SYS_KLDUNLOAD = 305 // { int kldunload(int fileid); } SYS_KLDFIND = 306 // { int kldfind(const char *file); } SYS_KLDNEXT = 307 // { int kldnext(int fileid); } - SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat* stat); } + SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat *stat); } SYS_KLDFIRSTMOD = 309 // { int kldfirstmod(int fileid); } SYS_GETSID = 310 // { int getsid(pid_t pid); } SYS_SETRESUID = 311 // { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } SYS_SETRESGID = 312 // { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } SYS_AIO_RETURN = 314 // { ssize_t aio_return(struct aiocb *aiocbp); } - SYS_AIO_SUSPEND = 315 // { int aio_suspend( struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } + SYS_AIO_SUSPEND = 315 // { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } SYS_AIO_CANCEL = 316 // { int aio_cancel(int fd, struct aiocb *aiocbp); } SYS_AIO_ERROR = 317 // { int aio_error(struct aiocb *aiocbp); } SYS_YIELD = 321 // { int yield(void); } SYS_MLOCKALL = 324 // { int mlockall(int how); } SYS_MUNLOCKALL = 325 // { int munlockall(void); } - SYS___GETCWD = 326 // { int __getcwd(char *buf, u_int buflen); } + SYS___GETCWD = 326 // { int __getcwd(char *buf, size_t buflen); } SYS_SCHED_SETPARAM = 327 // { int sched_setparam (pid_t pid, const struct sched_param *param); } SYS_SCHED_GETPARAM = 328 // { int sched_getparam (pid_t pid, struct sched_param *param); } SYS_SCHED_SETSCHEDULER = 329 // { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } @@ -225,14 +212,13 @@ const ( SYS___ACL_ACLCHECK_FILE = 353 // { int __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); } SYS___ACL_ACLCHECK_FD = 354 // { int __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); } SYS_EXTATTRCTL = 355 // { int extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); } - SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FILE = 358 // { int extattr_delete_file(const char *path, int attrnamespace, const char *attrname); } - SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete( struct aiocb **aiocbp, struct timespec *timeout); } + SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } SYS_GETRESUID = 360 // { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } SYS_GETRESGID = 361 // { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } SYS_KQUEUE = 362 // { int kqueue(void); } - SYS_KEVENT = 363 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } SYS_EXTATTR_SET_FD = 371 // { ssize_t extattr_set_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_GET_FD = 372 // { ssize_t extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FD = 373 // { int extattr_delete_fd(int fd, int attrnamespace, const char *attrname); } @@ -250,10 +236,6 @@ const ( SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } SYS_MAC_SYSCALL = 394 // { int mac_syscall(const char *policy, int call, void *arg); } - SYS_GETFSSTAT = 395 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } - SYS_STATFS = 396 // { int statfs(char *path, struct statfs *buf); } - SYS_FSTATFS = 397 // { int fstatfs(int fd, struct statfs *buf); } - SYS_FHSTATFS = 398 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } SYS_KSEM_CLOSE = 400 // { int ksem_close(semid_t id); } SYS_KSEM_POST = 401 // { int ksem_post(semid_t id); } SYS_KSEM_WAIT = 402 // { int ksem_wait(semid_t id); } @@ -266,14 +248,14 @@ const ( SYS___MAC_GET_PID = 409 // { int __mac_get_pid(pid_t pid, struct mac *mac_p); } SYS___MAC_GET_LINK = 410 // { int __mac_get_link(const char *path_p, struct mac *mac_p); } SYS___MAC_SET_LINK = 411 // { int __mac_set_link(const char *path_p, struct mac *mac_p); } - SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link( const char *path, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link(const char *path, int attrnamespace, const char *attrname); } SYS___MAC_EXECVE = 415 // { int __mac_execve(char *fname, char **argv, char **envv, struct mac *mac_p); } SYS_SIGACTION = 416 // { int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); } - SYS_SIGRETURN = 417 // { int sigreturn( const struct __ucontext *sigcntxp); } + SYS_SIGRETURN = 417 // { int sigreturn(const struct __ucontext *sigcntxp); } SYS_GETCONTEXT = 421 // { int getcontext(struct __ucontext *ucp); } - SYS_SETCONTEXT = 422 // { int setcontext( const struct __ucontext *ucp); } + SYS_SETCONTEXT = 422 // { int setcontext(const struct __ucontext *ucp); } SYS_SWAPCONTEXT = 423 // { int swapcontext(struct __ucontext *oucp, const struct __ucontext *ucp); } SYS_SWAPOFF = 424 // { int swapoff(const char *name); } SYS___ACL_GET_LINK = 425 // { int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); } @@ -287,10 +269,10 @@ const ( SYS_THR_KILL = 433 // { int thr_kill(long id, int sig); } SYS_JAIL_ATTACH = 436 // { int jail_attach(int jid); } SYS_EXTATTR_LIST_FD = 437 // { ssize_t extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file( const char *path, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link( const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); } SYS_KSEM_TIMEDWAIT = 441 // { int ksem_timedwait(semid_t id, const struct timespec *abstime); } - SYS_THR_SUSPEND = 442 // { int thr_suspend( const struct timespec *timeout); } + SYS_THR_SUSPEND = 442 // { int thr_suspend(const struct timespec *timeout); } SYS_THR_WAKE = 443 // { int thr_wake(long id); } SYS_KLDUNLOADF = 444 // { int kldunloadf(int fileid, int flags); } SYS_AUDIT = 445 // { int audit(const void *record, u_int length); } @@ -299,17 +281,17 @@ const ( SYS_SETAUID = 448 // { int setauid(uid_t *auid); } SYS_GETAUDIT = 449 // { int getaudit(struct auditinfo *auditinfo); } SYS_SETAUDIT = 450 // { int setaudit(struct auditinfo *auditinfo); } - SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } - SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } SYS_AUDITCTL = 453 // { int auditctl(char *path); } SYS__UMTX_OP = 454 // { int _umtx_op(void *obj, int op, u_long val, void *uaddr1, void *uaddr2); } SYS_THR_NEW = 455 // { int thr_new(struct thr_param *param, int param_size); } SYS_SIGQUEUE = 456 // { int sigqueue(pid_t pid, int signum, void *value); } SYS_KMQ_OPEN = 457 // { int kmq_open(const char *path, int flags, mode_t mode, const struct mq_attr *attr); } - SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } - SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } - SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len,unsigned msg_prio, const struct timespec *abs_timeout);} - SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } + SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } + SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } SYS_KMQ_UNLINK = 462 // { int kmq_unlink(const char *path); } SYS_ABORT2 = 463 // { int abort2(const char *why, int nargs, void **args); } SYS_THR_SET_NAME = 464 // { int thr_set_name(long id, const char *name); } @@ -318,7 +300,7 @@ const ( SYS_SCTP_PEELOFF = 471 // { int sctp_peeloff(int sd, uint32_t name); } SYS_SCTP_GENERIC_SENDMSG = 472 // { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } SYS_SCTP_GENERIC_SENDMSG_IOV = 473 // { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } - SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr * from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } + SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr *from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } SYS_PREAD = 475 // { ssize_t pread(int fd, void *buf, size_t nbyte, off_t offset); } SYS_PWRITE = 476 // { ssize_t pwrite(int fd, const void *buf, size_t nbyte, off_t offset); } SYS_MMAP = 477 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos); } @@ -337,14 +319,12 @@ const ( SYS_FCHMODAT = 490 // { int fchmodat(int fd, char *path, mode_t mode, int flag); } SYS_FCHOWNAT = 491 // { int fchownat(int fd, char *path, uid_t uid, gid_t gid, int flag); } SYS_FEXECVE = 492 // { int fexecve(int fd, char **argv, char **envv); } - SYS_FSTATAT = 493 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } SYS_FUTIMESAT = 494 // { int futimesat(int fd, char *path, struct timeval *times); } SYS_LINKAT = 495 // { int linkat(int fd1, char *path1, int fd2, char *path2, int flag); } SYS_MKDIRAT = 496 // { int mkdirat(int fd, char *path, mode_t mode); } SYS_MKFIFOAT = 497 // { int mkfifoat(int fd, char *path, mode_t mode); } - SYS_MKNODAT = 498 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } SYS_OPENAT = 499 // { int openat(int fd, char *path, int flag, mode_t mode); } - SYS_READLINKAT = 500 // { int readlinkat(int fd, char *path, char *buf, size_t bufsize); } + SYS_READLINKAT = 500 // { ssize_t readlinkat(int fd, char *path, char *buf, size_t bufsize); } SYS_RENAMEAT = 501 // { int renameat(int oldfd, char *old, int newfd, char *new); } SYS_SYMLINKAT = 502 // { int symlinkat(char *path1, int fd, char *path2); } SYS_UNLINKAT = 503 // { int unlinkat(int fd, char *path, int flag); } @@ -390,7 +370,24 @@ const ( SYS_PPOLL = 545 // { int ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *set); } SYS_FUTIMENS = 546 // { int futimens(int fd, struct timespec *times); } SYS_UTIMENSAT = 547 // { int utimensat(int fd, char *path, struct timespec *times, int flag); } - SYS_NUMA_GETAFFINITY = 548 // { int numa_getaffinity(cpuwhich_t which, id_t id, struct vm_domain_policy_entry *policy); } - SYS_NUMA_SETAFFINITY = 549 // { int numa_setaffinity(cpuwhich_t which, id_t id, const struct vm_domain_policy_entry *policy); } SYS_FDATASYNC = 550 // { int fdatasync(int fd); } + SYS_FSTAT = 551 // { int fstat(int fd, struct stat *sb); } + SYS_FSTATAT = 552 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } + SYS_FHSTAT = 553 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } + SYS_GETDIRENTRIES = 554 // { ssize_t getdirentries(int fd, char *buf, size_t count, off_t *basep); } + SYS_STATFS = 555 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 556 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFSSTAT = 557 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } + SYS_FHSTATFS = 558 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } + SYS_MKNODAT = 559 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } + SYS_KEVENT = 560 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_CPUSET_GETDOMAIN = 561 // { int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int *policy); } + SYS_CPUSET_SETDOMAIN = 562 // { int cpuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int policy); } + SYS_GETRANDOM = 563 // { int getrandom(void *buf, size_t buflen, unsigned int flags); } + SYS_GETFHAT = 564 // { int getfhat(int fd, char *path, struct fhandle *fhp, int flags); } + SYS_FHLINK = 565 // { int fhlink(struct fhandle *fhp, const char *to); } + SYS_FHLINKAT = 566 // { int fhlinkat(struct fhandle *fhp, int tofd, const char *to,); } + SYS_FHREADLINK = 567 // { int fhreadlink(struct fhandle *fhp, char *buf, size_t bufsize); } + SYS___SYSCTLBYNAME = 570 // { int __sysctlbyname(const char *name, size_t namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_CLOSE_RANGE = 575 // { int close_range(u_int lowfd, u_int highfd, int flags); } ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go index 3e51af8..e32df1c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go @@ -1,7 +1,7 @@ -// go run mksysnum.go https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master +// go run mksysnum.go https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12 // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,freebsd +//go:build arm64 && freebsd package unix @@ -18,10 +18,9 @@ const ( SYS_UNLINK = 10 // { int unlink(char *path); } SYS_CHDIR = 12 // { int chdir(char *path); } SYS_FCHDIR = 13 // { int fchdir(int fd); } - SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } SYS_CHMOD = 15 // { int chmod(char *path, int mode); } SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } - SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int + SYS_BREAK = 17 // { caddr_t break(char *nsize); } SYS_GETPID = 20 // { pid_t getpid(void); } SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } @@ -42,7 +41,6 @@ const ( SYS_KILL = 37 // { int kill(int pid, int signum); } SYS_GETPPID = 39 // { pid_t getppid(void); } SYS_DUP = 41 // { int dup(u_int fd); } - SYS_PIPE = 42 // { int pipe(void); } SYS_GETEGID = 43 // { gid_t getegid(void); } SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } @@ -57,15 +55,14 @@ const ( SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } SYS_READLINK = 58 // { ssize_t readlink(char *path, char *buf, size_t count); } SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } - SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int + SYS_UMASK = 60 // { int umask(int newmask); } SYS_CHROOT = 61 // { int chroot(char *path); } SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } SYS_VFORK = 66 // { int vfork(void); } SYS_SBRK = 69 // { int sbrk(int incr); } SYS_SSTK = 70 // { int sstk(int incr); } - SYS_OVADVISE = 72 // { int ovadvise(int anom); } vadvise ovadvise_args int SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } - SYS_MPROTECT = 74 // { int mprotect(const void *addr, size_t len, int prot); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } @@ -123,14 +120,10 @@ const ( SYS_SETGID = 181 // { int setgid(gid_t gid); } SYS_SETEGID = 182 // { int setegid(gid_t egid); } SYS_SETEUID = 183 // { int seteuid(uid_t euid); } - SYS_STAT = 188 // { int stat(char *path, struct stat *ub); } - SYS_FSTAT = 189 // { int fstat(int fd, struct stat *sb); } - SYS_LSTAT = 190 // { int lstat(char *path, struct stat *ub); } SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int - SYS_GETDIRENTRIES = 196 // { int getdirentries(int fd, char *buf, u_int count, long *basep); } SYS___SYSCTL = 202 // { int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } __sysctl sysctl_args int SYS_MLOCK = 203 // { int mlock(const void *addr, size_t len); } SYS_MUNLOCK = 204 // { int munlock(const void *addr, size_t len); } @@ -142,12 +135,12 @@ const ( SYS_SEMOP = 222 // { int semop(int semid, struct sembuf *sops, size_t nsops); } SYS_MSGGET = 225 // { int msgget(key_t key, int msgflg); } SYS_MSGSND = 226 // { int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } - SYS_MSGRCV = 227 // { int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_MSGRCV = 227 // { ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } SYS_SHMAT = 228 // { int shmat(int shmid, const void *shmaddr, int shmflg); } SYS_SHMDT = 230 // { int shmdt(const void *shmaddr); } SYS_SHMGET = 231 // { int shmget(key_t key, size_t size, int shmflg); } SYS_CLOCK_GETTIME = 232 // { int clock_gettime(clockid_t clock_id, struct timespec *tp); } - SYS_CLOCK_SETTIME = 233 // { int clock_settime( clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_SETTIME = 233 // { int clock_settime(clockid_t clock_id, const struct timespec *tp); } SYS_CLOCK_GETRES = 234 // { int clock_getres(clockid_t clock_id, struct timespec *tp); } SYS_KTIMER_CREATE = 235 // { int ktimer_create(clockid_t clock_id, struct sigevent *evp, int *timerid); } SYS_KTIMER_DELETE = 236 // { int ktimer_delete(int timerid); } @@ -156,50 +149,44 @@ const ( SYS_KTIMER_GETOVERRUN = 239 // { int ktimer_getoverrun(int timerid); } SYS_NANOSLEEP = 240 // { int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); } - SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( struct ffclock_estimate *cest); } - SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( struct ffclock_estimate *cest); } + SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate(struct ffclock_estimate *cest); } + SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate(struct ffclock_estimate *cest); } SYS_CLOCK_NANOSLEEP = 244 // { int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp); } - SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,int which, clockid_t *clock_id); } + SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id, int which, clockid_t *clock_id); } SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); } SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, int inherit); } SYS_RFORK = 251 // { int rfork(int flags); } - SYS_OPENBSD_POLL = 252 // { int openbsd_poll(struct pollfd *fds, u_int nfds, int timeout); } SYS_ISSETUGID = 253 // { int issetugid(void); } SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } SYS_AIO_READ = 255 // { int aio_read(struct aiocb *aiocbp); } SYS_AIO_WRITE = 256 // { int aio_write(struct aiocb *aiocbp); } - SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); } - SYS_GETDENTS = 272 // { int getdents(int fd, char *buf, size_t count); } + SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb* const *acb_list, int nent, struct sigevent *sig); } SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } - SYS_NSTAT = 278 // { int nstat(char *path, struct nstat *ub); } - SYS_NFSTAT = 279 // { int nfstat(int fd, struct nstat *sb); } - SYS_NLSTAT = 280 // { int nlstat(char *path, struct nstat *ub); } SYS_PREADV = 289 // { ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_PWRITEV = 290 // { ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } - SYS_FHSTAT = 299 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } SYS_MODNEXT = 300 // { int modnext(int modid); } - SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat *stat); } + SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat* stat); } SYS_MODFNEXT = 302 // { int modfnext(int modid); } SYS_MODFIND = 303 // { int modfind(const char *name); } SYS_KLDLOAD = 304 // { int kldload(const char *file); } SYS_KLDUNLOAD = 305 // { int kldunload(int fileid); } SYS_KLDFIND = 306 // { int kldfind(const char *file); } SYS_KLDNEXT = 307 // { int kldnext(int fileid); } - SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat* stat); } + SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat *stat); } SYS_KLDFIRSTMOD = 309 // { int kldfirstmod(int fileid); } SYS_GETSID = 310 // { int getsid(pid_t pid); } SYS_SETRESUID = 311 // { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } SYS_SETRESGID = 312 // { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } SYS_AIO_RETURN = 314 // { ssize_t aio_return(struct aiocb *aiocbp); } - SYS_AIO_SUSPEND = 315 // { int aio_suspend( struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } + SYS_AIO_SUSPEND = 315 // { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } SYS_AIO_CANCEL = 316 // { int aio_cancel(int fd, struct aiocb *aiocbp); } SYS_AIO_ERROR = 317 // { int aio_error(struct aiocb *aiocbp); } SYS_YIELD = 321 // { int yield(void); } SYS_MLOCKALL = 324 // { int mlockall(int how); } SYS_MUNLOCKALL = 325 // { int munlockall(void); } - SYS___GETCWD = 326 // { int __getcwd(char *buf, u_int buflen); } + SYS___GETCWD = 326 // { int __getcwd(char *buf, size_t buflen); } SYS_SCHED_SETPARAM = 327 // { int sched_setparam (pid_t pid, const struct sched_param *param); } SYS_SCHED_GETPARAM = 328 // { int sched_getparam (pid_t pid, struct sched_param *param); } SYS_SCHED_SETSCHEDULER = 329 // { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } @@ -225,14 +212,13 @@ const ( SYS___ACL_ACLCHECK_FILE = 353 // { int __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); } SYS___ACL_ACLCHECK_FD = 354 // { int __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); } SYS_EXTATTRCTL = 355 // { int extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); } - SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FILE = 358 // { int extattr_delete_file(const char *path, int attrnamespace, const char *attrname); } - SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete( struct aiocb **aiocbp, struct timespec *timeout); } + SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } SYS_GETRESUID = 360 // { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } SYS_GETRESGID = 361 // { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } SYS_KQUEUE = 362 // { int kqueue(void); } - SYS_KEVENT = 363 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } SYS_EXTATTR_SET_FD = 371 // { ssize_t extattr_set_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_GET_FD = 372 // { ssize_t extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } SYS_EXTATTR_DELETE_FD = 373 // { int extattr_delete_fd(int fd, int attrnamespace, const char *attrname); } @@ -250,10 +236,6 @@ const ( SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } SYS_MAC_SYSCALL = 394 // { int mac_syscall(const char *policy, int call, void *arg); } - SYS_GETFSSTAT = 395 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } - SYS_STATFS = 396 // { int statfs(char *path, struct statfs *buf); } - SYS_FSTATFS = 397 // { int fstatfs(int fd, struct statfs *buf); } - SYS_FHSTATFS = 398 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } SYS_KSEM_CLOSE = 400 // { int ksem_close(semid_t id); } SYS_KSEM_POST = 401 // { int ksem_post(semid_t id); } SYS_KSEM_WAIT = 402 // { int ksem_wait(semid_t id); } @@ -266,14 +248,14 @@ const ( SYS___MAC_GET_PID = 409 // { int __mac_get_pid(pid_t pid, struct mac *mac_p); } SYS___MAC_GET_LINK = 410 // { int __mac_get_link(const char *path_p, struct mac *mac_p); } SYS___MAC_SET_LINK = 411 // { int __mac_set_link(const char *path_p, struct mac *mac_p); } - SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link( const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } - SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link( const char *path, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link(const char *path, int attrnamespace, const char *attrname); } SYS___MAC_EXECVE = 415 // { int __mac_execve(char *fname, char **argv, char **envv, struct mac *mac_p); } SYS_SIGACTION = 416 // { int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); } - SYS_SIGRETURN = 417 // { int sigreturn( const struct __ucontext *sigcntxp); } + SYS_SIGRETURN = 417 // { int sigreturn(const struct __ucontext *sigcntxp); } SYS_GETCONTEXT = 421 // { int getcontext(struct __ucontext *ucp); } - SYS_SETCONTEXT = 422 // { int setcontext( const struct __ucontext *ucp); } + SYS_SETCONTEXT = 422 // { int setcontext(const struct __ucontext *ucp); } SYS_SWAPCONTEXT = 423 // { int swapcontext(struct __ucontext *oucp, const struct __ucontext *ucp); } SYS_SWAPOFF = 424 // { int swapoff(const char *name); } SYS___ACL_GET_LINK = 425 // { int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); } @@ -287,10 +269,10 @@ const ( SYS_THR_KILL = 433 // { int thr_kill(long id, int sig); } SYS_JAIL_ATTACH = 436 // { int jail_attach(int jid); } SYS_EXTATTR_LIST_FD = 437 // { ssize_t extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file( const char *path, int attrnamespace, void *data, size_t nbytes); } - SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link( const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); } SYS_KSEM_TIMEDWAIT = 441 // { int ksem_timedwait(semid_t id, const struct timespec *abstime); } - SYS_THR_SUSPEND = 442 // { int thr_suspend( const struct timespec *timeout); } + SYS_THR_SUSPEND = 442 // { int thr_suspend(const struct timespec *timeout); } SYS_THR_WAKE = 443 // { int thr_wake(long id); } SYS_KLDUNLOADF = 444 // { int kldunloadf(int fileid, int flags); } SYS_AUDIT = 445 // { int audit(const void *record, u_int length); } @@ -299,17 +281,17 @@ const ( SYS_SETAUID = 448 // { int setauid(uid_t *auid); } SYS_GETAUDIT = 449 // { int getaudit(struct auditinfo *auditinfo); } SYS_SETAUDIT = 450 // { int setaudit(struct auditinfo *auditinfo); } - SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } - SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr( struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } SYS_AUDITCTL = 453 // { int auditctl(char *path); } SYS__UMTX_OP = 454 // { int _umtx_op(void *obj, int op, u_long val, void *uaddr1, void *uaddr2); } SYS_THR_NEW = 455 // { int thr_new(struct thr_param *param, int param_size); } SYS_SIGQUEUE = 456 // { int sigqueue(pid_t pid, int signum, void *value); } SYS_KMQ_OPEN = 457 // { int kmq_open(const char *path, int flags, mode_t mode, const struct mq_attr *attr); } - SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } - SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } - SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len,unsigned msg_prio, const struct timespec *abs_timeout);} - SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } + SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } + SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } SYS_KMQ_UNLINK = 462 // { int kmq_unlink(const char *path); } SYS_ABORT2 = 463 // { int abort2(const char *why, int nargs, void **args); } SYS_THR_SET_NAME = 464 // { int thr_set_name(long id, const char *name); } @@ -318,7 +300,7 @@ const ( SYS_SCTP_PEELOFF = 471 // { int sctp_peeloff(int sd, uint32_t name); } SYS_SCTP_GENERIC_SENDMSG = 472 // { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } SYS_SCTP_GENERIC_SENDMSG_IOV = 473 // { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } - SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr * from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } + SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr *from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } SYS_PREAD = 475 // { ssize_t pread(int fd, void *buf, size_t nbyte, off_t offset); } SYS_PWRITE = 476 // { ssize_t pwrite(int fd, const void *buf, size_t nbyte, off_t offset); } SYS_MMAP = 477 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos); } @@ -337,14 +319,12 @@ const ( SYS_FCHMODAT = 490 // { int fchmodat(int fd, char *path, mode_t mode, int flag); } SYS_FCHOWNAT = 491 // { int fchownat(int fd, char *path, uid_t uid, gid_t gid, int flag); } SYS_FEXECVE = 492 // { int fexecve(int fd, char **argv, char **envv); } - SYS_FSTATAT = 493 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } SYS_FUTIMESAT = 494 // { int futimesat(int fd, char *path, struct timeval *times); } SYS_LINKAT = 495 // { int linkat(int fd1, char *path1, int fd2, char *path2, int flag); } SYS_MKDIRAT = 496 // { int mkdirat(int fd, char *path, mode_t mode); } SYS_MKFIFOAT = 497 // { int mkfifoat(int fd, char *path, mode_t mode); } - SYS_MKNODAT = 498 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } SYS_OPENAT = 499 // { int openat(int fd, char *path, int flag, mode_t mode); } - SYS_READLINKAT = 500 // { int readlinkat(int fd, char *path, char *buf, size_t bufsize); } + SYS_READLINKAT = 500 // { ssize_t readlinkat(int fd, char *path, char *buf, size_t bufsize); } SYS_RENAMEAT = 501 // { int renameat(int oldfd, char *old, int newfd, char *new); } SYS_SYMLINKAT = 502 // { int symlinkat(char *path1, int fd, char *path2); } SYS_UNLINKAT = 503 // { int unlinkat(int fd, char *path, int flag); } @@ -390,7 +370,24 @@ const ( SYS_PPOLL = 545 // { int ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *set); } SYS_FUTIMENS = 546 // { int futimens(int fd, struct timespec *times); } SYS_UTIMENSAT = 547 // { int utimensat(int fd, char *path, struct timespec *times, int flag); } - SYS_NUMA_GETAFFINITY = 548 // { int numa_getaffinity(cpuwhich_t which, id_t id, struct vm_domain_policy_entry *policy); } - SYS_NUMA_SETAFFINITY = 549 // { int numa_setaffinity(cpuwhich_t which, id_t id, const struct vm_domain_policy_entry *policy); } SYS_FDATASYNC = 550 // { int fdatasync(int fd); } + SYS_FSTAT = 551 // { int fstat(int fd, struct stat *sb); } + SYS_FSTATAT = 552 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } + SYS_FHSTAT = 553 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } + SYS_GETDIRENTRIES = 554 // { ssize_t getdirentries(int fd, char *buf, size_t count, off_t *basep); } + SYS_STATFS = 555 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 556 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFSSTAT = 557 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } + SYS_FHSTATFS = 558 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } + SYS_MKNODAT = 559 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } + SYS_KEVENT = 560 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_CPUSET_GETDOMAIN = 561 // { int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int *policy); } + SYS_CPUSET_SETDOMAIN = 562 // { int cpuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int policy); } + SYS_GETRANDOM = 563 // { int getrandom(void *buf, size_t buflen, unsigned int flags); } + SYS_GETFHAT = 564 // { int getfhat(int fd, char *path, struct fhandle *fhp, int flags); } + SYS_FHLINK = 565 // { int fhlink(struct fhandle *fhp, const char *to); } + SYS_FHLINKAT = 566 // { int fhlinkat(struct fhandle *fhp, int tofd, const char *to,); } + SYS_FHREADLINK = 567 // { int fhreadlink(struct fhandle *fhp, char *buf, size_t bufsize); } + SYS___SYSCTLBYNAME = 570 // { int __sysctlbyname(const char *name, size_t namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_CLOSE_RANGE = 575 // { int close_range(u_int lowfd, u_int highfd, int flags); } ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go new file mode 100644 index 0000000..15ad611 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go @@ -0,0 +1,393 @@ +// go run mksysnum.go https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master?h=stable/12 +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build riscv64 && freebsd + +package unix + +const ( + // SYS_NOSYS = 0; // { int nosys(void); } syscall nosys_args int + SYS_EXIT = 1 // { void sys_exit(int rval); } exit sys_exit_args void + SYS_FORK = 2 // { int fork(void); } + SYS_READ = 3 // { ssize_t read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int open(char *path, int flags, int mode); } + SYS_CLOSE = 6 // { int close(int fd); } + SYS_WAIT4 = 7 // { int wait4(int pid, int *status, int options, struct rusage *rusage); } + SYS_LINK = 9 // { int link(char *path, char *link); } + SYS_UNLINK = 10 // { int unlink(char *path); } + SYS_CHDIR = 12 // { int chdir(char *path); } + SYS_FCHDIR = 13 // { int fchdir(int fd); } + SYS_CHMOD = 15 // { int chmod(char *path, int mode); } + SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } + SYS_BREAK = 17 // { caddr_t break(char *nsize); } + SYS_GETPID = 20 // { pid_t getpid(void); } + SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } + SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } + SYS_SETUID = 23 // { int setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t getuid(void); } + SYS_GETEUID = 25 // { uid_t geteuid(void); } + SYS_PTRACE = 26 // { int ptrace(int req, pid_t pid, caddr_t addr, int data); } + SYS_RECVMSG = 27 // { int recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { int sendmsg(int s, struct msghdr *msg, int flags); } + SYS_RECVFROM = 29 // { int recvfrom(int s, caddr_t buf, size_t len, int flags, struct sockaddr * __restrict from, __socklen_t * __restrict fromlenaddr); } + SYS_ACCEPT = 30 // { int accept(int s, struct sockaddr * __restrict name, __socklen_t * __restrict anamelen); } + SYS_GETPEERNAME = 31 // { int getpeername(int fdes, struct sockaddr * __restrict asa, __socklen_t * __restrict alen); } + SYS_GETSOCKNAME = 32 // { int getsockname(int fdes, struct sockaddr * __restrict asa, __socklen_t * __restrict alen); } + SYS_ACCESS = 33 // { int access(char *path, int amode); } + SYS_CHFLAGS = 34 // { int chflags(const char *path, u_long flags); } + SYS_FCHFLAGS = 35 // { int fchflags(int fd, u_long flags); } + SYS_SYNC = 36 // { int sync(void); } + SYS_KILL = 37 // { int kill(int pid, int signum); } + SYS_GETPPID = 39 // { pid_t getppid(void); } + SYS_DUP = 41 // { int dup(u_int fd); } + SYS_GETEGID = 43 // { gid_t getegid(void); } + SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } + SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } + SYS_GETGID = 47 // { gid_t getgid(void); } + SYS_GETLOGIN = 49 // { int getlogin(char *namebuf, u_int namelen); } + SYS_SETLOGIN = 50 // { int setlogin(char *namebuf); } + SYS_ACCT = 51 // { int acct(char *path); } + SYS_SIGALTSTACK = 53 // { int sigaltstack(stack_t *ss, stack_t *oss); } + SYS_IOCTL = 54 // { int ioctl(int fd, u_long com, caddr_t data); } + SYS_REBOOT = 55 // { int reboot(int opt); } + SYS_REVOKE = 56 // { int revoke(char *path); } + SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } + SYS_READLINK = 58 // { ssize_t readlink(char *path, char *buf, size_t count); } + SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } + SYS_UMASK = 60 // { int umask(int newmask); } + SYS_CHROOT = 61 // { int chroot(char *path); } + SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } + SYS_VFORK = 66 // { int vfork(void); } + SYS_SBRK = 69 // { int sbrk(int incr); } + SYS_SSTK = 70 // { int sstk(int incr); } + SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } + SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } + SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int setgroups(u_int gidsetsize, gid_t *gidset); } + SYS_GETPGRP = 81 // { int getpgrp(void); } + SYS_SETPGID = 82 // { int setpgid(int pid, int pgid); } + SYS_SETITIMER = 83 // { int setitimer(u_int which, struct itimerval *itv, struct itimerval *oitv); } + SYS_SWAPON = 85 // { int swapon(char *name); } + SYS_GETITIMER = 86 // { int getitimer(u_int which, struct itimerval *itv); } + SYS_GETDTABLESIZE = 89 // { int getdtablesize(void); } + SYS_DUP2 = 90 // { int dup2(u_int from, u_int to); } + SYS_FCNTL = 92 // { int fcntl(int fd, int cmd, long arg); } + SYS_SELECT = 93 // { int select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_FSYNC = 95 // { int fsync(int fd); } + SYS_SETPRIORITY = 96 // { int setpriority(int which, int who, int prio); } + SYS_SOCKET = 97 // { int socket(int domain, int type, int protocol); } + SYS_CONNECT = 98 // { int connect(int s, caddr_t name, int namelen); } + SYS_GETPRIORITY = 100 // { int getpriority(int which, int who); } + SYS_BIND = 104 // { int bind(int s, caddr_t name, int namelen); } + SYS_SETSOCKOPT = 105 // { int setsockopt(int s, int level, int name, caddr_t val, int valsize); } + SYS_LISTEN = 106 // { int listen(int s, int backlog); } + SYS_GETTIMEOFDAY = 116 // { int gettimeofday(struct timeval *tp, struct timezone *tzp); } + SYS_GETRUSAGE = 117 // { int getrusage(int who, struct rusage *rusage); } + SYS_GETSOCKOPT = 118 // { int getsockopt(int s, int level, int name, caddr_t val, int *avalsize); } + SYS_READV = 120 // { int readv(int fd, struct iovec *iovp, u_int iovcnt); } + SYS_WRITEV = 121 // { int writev(int fd, struct iovec *iovp, u_int iovcnt); } + SYS_SETTIMEOFDAY = 122 // { int settimeofday(struct timeval *tv, struct timezone *tzp); } + SYS_FCHOWN = 123 // { int fchown(int fd, int uid, int gid); } + SYS_FCHMOD = 124 // { int fchmod(int fd, int mode); } + SYS_SETREUID = 126 // { int setreuid(int ruid, int euid); } + SYS_SETREGID = 127 // { int setregid(int rgid, int egid); } + SYS_RENAME = 128 // { int rename(char *from, char *to); } + SYS_FLOCK = 131 // { int flock(int fd, int how); } + SYS_MKFIFO = 132 // { int mkfifo(char *path, int mode); } + SYS_SENDTO = 133 // { int sendto(int s, caddr_t buf, size_t len, int flags, caddr_t to, int tolen); } + SYS_SHUTDOWN = 134 // { int shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int mkdir(char *path, int mode); } + SYS_RMDIR = 137 // { int rmdir(char *path); } + SYS_UTIMES = 138 // { int utimes(char *path, struct timeval *tptr); } + SYS_ADJTIME = 140 // { int adjtime(struct timeval *delta, struct timeval *olddelta); } + SYS_SETSID = 147 // { int setsid(void); } + SYS_QUOTACTL = 148 // { int quotactl(char *path, int cmd, int uid, caddr_t arg); } + SYS_NLM_SYSCALL = 154 // { int nlm_syscall(int debug_level, int grace_period, int addr_count, char **addrs); } + SYS_NFSSVC = 155 // { int nfssvc(int flag, caddr_t argp); } + SYS_LGETFH = 160 // { int lgetfh(char *fname, struct fhandle *fhp); } + SYS_GETFH = 161 // { int getfh(char *fname, struct fhandle *fhp); } + SYS_SYSARCH = 165 // { int sysarch(int op, char *parms); } + SYS_RTPRIO = 166 // { int rtprio(int function, pid_t pid, struct rtprio *rtp); } + SYS_SEMSYS = 169 // { int semsys(int which, int a2, int a3, int a4, int a5); } + SYS_MSGSYS = 170 // { int msgsys(int which, int a2, int a3, int a4, int a5, int a6); } + SYS_SHMSYS = 171 // { int shmsys(int which, int a2, int a3, int a4); } + SYS_SETFIB = 175 // { int setfib(int fibnum); } + SYS_NTP_ADJTIME = 176 // { int ntp_adjtime(struct timex *tp); } + SYS_SETGID = 181 // { int setgid(gid_t gid); } + SYS_SETEGID = 182 // { int setegid(gid_t egid); } + SYS_SETEUID = 183 // { int seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } + SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } + SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int + SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int + SYS___SYSCTL = 202 // { int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } __sysctl sysctl_args int + SYS_MLOCK = 203 // { int mlock(const void *addr, size_t len); } + SYS_MUNLOCK = 204 // { int munlock(const void *addr, size_t len); } + SYS_UNDELETE = 205 // { int undelete(char *path); } + SYS_FUTIMES = 206 // { int futimes(int fd, struct timeval *tptr); } + SYS_GETPGID = 207 // { int getpgid(pid_t pid); } + SYS_POLL = 209 // { int poll(struct pollfd *fds, u_int nfds, int timeout); } + SYS_SEMGET = 221 // { int semget(key_t key, int nsems, int semflg); } + SYS_SEMOP = 222 // { int semop(int semid, struct sembuf *sops, size_t nsops); } + SYS_MSGGET = 225 // { int msgget(key_t key, int msgflg); } + SYS_MSGSND = 226 // { int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } + SYS_MSGRCV = 227 // { ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_SHMAT = 228 // { int shmat(int shmid, const void *shmaddr, int shmflg); } + SYS_SHMDT = 230 // { int shmdt(const void *shmaddr); } + SYS_SHMGET = 231 // { int shmget(key_t key, size_t size, int shmflg); } + SYS_CLOCK_GETTIME = 232 // { int clock_gettime(clockid_t clock_id, struct timespec *tp); } + SYS_CLOCK_SETTIME = 233 // { int clock_settime(clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_GETRES = 234 // { int clock_getres(clockid_t clock_id, struct timespec *tp); } + SYS_KTIMER_CREATE = 235 // { int ktimer_create(clockid_t clock_id, struct sigevent *evp, int *timerid); } + SYS_KTIMER_DELETE = 236 // { int ktimer_delete(int timerid); } + SYS_KTIMER_SETTIME = 237 // { int ktimer_settime(int timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); } + SYS_KTIMER_GETTIME = 238 // { int ktimer_gettime(int timerid, struct itimerspec *value); } + SYS_KTIMER_GETOVERRUN = 239 // { int ktimer_getoverrun(int timerid); } + SYS_NANOSLEEP = 240 // { int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } + SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); } + SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate(struct ffclock_estimate *cest); } + SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate(struct ffclock_estimate *cest); } + SYS_CLOCK_NANOSLEEP = 244 // { int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp); } + SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id, int which, clockid_t *clock_id); } + SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); } + SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, int inherit); } + SYS_RFORK = 251 // { int rfork(int flags); } + SYS_ISSETUGID = 253 // { int issetugid(void); } + SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } + SYS_AIO_READ = 255 // { int aio_read(struct aiocb *aiocbp); } + SYS_AIO_WRITE = 256 // { int aio_write(struct aiocb *aiocbp); } + SYS_LIO_LISTIO = 257 // { int lio_listio(int mode, struct aiocb* const *acb_list, int nent, struct sigevent *sig); } + SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } + SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } + SYS_PREADV = 289 // { ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } + SYS_PWRITEV = 290 // { ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt, off_t offset); } + SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } + SYS_MODNEXT = 300 // { int modnext(int modid); } + SYS_MODSTAT = 301 // { int modstat(int modid, struct module_stat* stat); } + SYS_MODFNEXT = 302 // { int modfnext(int modid); } + SYS_MODFIND = 303 // { int modfind(const char *name); } + SYS_KLDLOAD = 304 // { int kldload(const char *file); } + SYS_KLDUNLOAD = 305 // { int kldunload(int fileid); } + SYS_KLDFIND = 306 // { int kldfind(const char *file); } + SYS_KLDNEXT = 307 // { int kldnext(int fileid); } + SYS_KLDSTAT = 308 // { int kldstat(int fileid, struct kld_file_stat *stat); } + SYS_KLDFIRSTMOD = 309 // { int kldfirstmod(int fileid); } + SYS_GETSID = 310 // { int getsid(pid_t pid); } + SYS_SETRESUID = 311 // { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } + SYS_SETRESGID = 312 // { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } + SYS_AIO_RETURN = 314 // { ssize_t aio_return(struct aiocb *aiocbp); } + SYS_AIO_SUSPEND = 315 // { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); } + SYS_AIO_CANCEL = 316 // { int aio_cancel(int fd, struct aiocb *aiocbp); } + SYS_AIO_ERROR = 317 // { int aio_error(struct aiocb *aiocbp); } + SYS_YIELD = 321 // { int yield(void); } + SYS_MLOCKALL = 324 // { int mlockall(int how); } + SYS_MUNLOCKALL = 325 // { int munlockall(void); } + SYS___GETCWD = 326 // { int __getcwd(char *buf, size_t buflen); } + SYS_SCHED_SETPARAM = 327 // { int sched_setparam (pid_t pid, const struct sched_param *param); } + SYS_SCHED_GETPARAM = 328 // { int sched_getparam (pid_t pid, struct sched_param *param); } + SYS_SCHED_SETSCHEDULER = 329 // { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } + SYS_SCHED_GETSCHEDULER = 330 // { int sched_getscheduler (pid_t pid); } + SYS_SCHED_YIELD = 331 // { int sched_yield (void); } + SYS_SCHED_GET_PRIORITY_MAX = 332 // { int sched_get_priority_max (int policy); } + SYS_SCHED_GET_PRIORITY_MIN = 333 // { int sched_get_priority_min (int policy); } + SYS_SCHED_RR_GET_INTERVAL = 334 // { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } + SYS_UTRACE = 335 // { int utrace(const void *addr, size_t len); } + SYS_KLDSYM = 337 // { int kldsym(int fileid, int cmd, void *data); } + SYS_JAIL = 338 // { int jail(struct jail *jail); } + SYS_SIGPROCMASK = 340 // { int sigprocmask(int how, const sigset_t *set, sigset_t *oset); } + SYS_SIGSUSPEND = 341 // { int sigsuspend(const sigset_t *sigmask); } + SYS_SIGPENDING = 343 // { int sigpending(sigset_t *set); } + SYS_SIGTIMEDWAIT = 345 // { int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout); } + SYS_SIGWAITINFO = 346 // { int sigwaitinfo(const sigset_t *set, siginfo_t *info); } + SYS___ACL_GET_FILE = 347 // { int __acl_get_file(const char *path, acl_type_t type, struct acl *aclp); } + SYS___ACL_SET_FILE = 348 // { int __acl_set_file(const char *path, acl_type_t type, struct acl *aclp); } + SYS___ACL_GET_FD = 349 // { int __acl_get_fd(int filedes, acl_type_t type, struct acl *aclp); } + SYS___ACL_SET_FD = 350 // { int __acl_set_fd(int filedes, acl_type_t type, struct acl *aclp); } + SYS___ACL_DELETE_FILE = 351 // { int __acl_delete_file(const char *path, acl_type_t type); } + SYS___ACL_DELETE_FD = 352 // { int __acl_delete_fd(int filedes, acl_type_t type); } + SYS___ACL_ACLCHECK_FILE = 353 // { int __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); } + SYS___ACL_ACLCHECK_FD = 354 // { int __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); } + SYS_EXTATTRCTL = 355 // { int extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_FILE = 356 // { ssize_t extattr_set_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_FILE = 357 // { ssize_t extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_FILE = 358 // { int extattr_delete_file(const char *path, int attrnamespace, const char *attrname); } + SYS_AIO_WAITCOMPLETE = 359 // { ssize_t aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); } + SYS_GETRESUID = 360 // { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } + SYS_GETRESGID = 361 // { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } + SYS_KQUEUE = 362 // { int kqueue(void); } + SYS_EXTATTR_SET_FD = 371 // { ssize_t extattr_set_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_FD = 372 // { ssize_t extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_FD = 373 // { int extattr_delete_fd(int fd, int attrnamespace, const char *attrname); } + SYS___SETUGID = 374 // { int __setugid(int flag); } + SYS_EACCESS = 376 // { int eaccess(char *path, int amode); } + SYS_NMOUNT = 378 // { int nmount(struct iovec *iovp, unsigned int iovcnt, int flags); } + SYS___MAC_GET_PROC = 384 // { int __mac_get_proc(struct mac *mac_p); } + SYS___MAC_SET_PROC = 385 // { int __mac_set_proc(struct mac *mac_p); } + SYS___MAC_GET_FD = 386 // { int __mac_get_fd(int fd, struct mac *mac_p); } + SYS___MAC_GET_FILE = 387 // { int __mac_get_file(const char *path_p, struct mac *mac_p); } + SYS___MAC_SET_FD = 388 // { int __mac_set_fd(int fd, struct mac *mac_p); } + SYS___MAC_SET_FILE = 389 // { int __mac_set_file(const char *path_p, struct mac *mac_p); } + SYS_KENV = 390 // { int kenv(int what, const char *name, char *value, int len); } + SYS_LCHFLAGS = 391 // { int lchflags(const char *path, u_long flags); } + SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } + SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } + SYS_MAC_SYSCALL = 394 // { int mac_syscall(const char *policy, int call, void *arg); } + SYS_KSEM_CLOSE = 400 // { int ksem_close(semid_t id); } + SYS_KSEM_POST = 401 // { int ksem_post(semid_t id); } + SYS_KSEM_WAIT = 402 // { int ksem_wait(semid_t id); } + SYS_KSEM_TRYWAIT = 403 // { int ksem_trywait(semid_t id); } + SYS_KSEM_INIT = 404 // { int ksem_init(semid_t *idp, unsigned int value); } + SYS_KSEM_OPEN = 405 // { int ksem_open(semid_t *idp, const char *name, int oflag, mode_t mode, unsigned int value); } + SYS_KSEM_UNLINK = 406 // { int ksem_unlink(const char *name); } + SYS_KSEM_GETVALUE = 407 // { int ksem_getvalue(semid_t id, int *val); } + SYS_KSEM_DESTROY = 408 // { int ksem_destroy(semid_t id); } + SYS___MAC_GET_PID = 409 // { int __mac_get_pid(pid_t pid, struct mac *mac_p); } + SYS___MAC_GET_LINK = 410 // { int __mac_get_link(const char *path_p, struct mac *mac_p); } + SYS___MAC_SET_LINK = 411 // { int __mac_set_link(const char *path_p, struct mac *mac_p); } + SYS_EXTATTR_SET_LINK = 412 // { ssize_t extattr_set_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_GET_LINK = 413 // { ssize_t extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_LINK = 414 // { int extattr_delete_link(const char *path, int attrnamespace, const char *attrname); } + SYS___MAC_EXECVE = 415 // { int __mac_execve(char *fname, char **argv, char **envv, struct mac *mac_p); } + SYS_SIGACTION = 416 // { int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); } + SYS_SIGRETURN = 417 // { int sigreturn(const struct __ucontext *sigcntxp); } + SYS_GETCONTEXT = 421 // { int getcontext(struct __ucontext *ucp); } + SYS_SETCONTEXT = 422 // { int setcontext(const struct __ucontext *ucp); } + SYS_SWAPCONTEXT = 423 // { int swapcontext(struct __ucontext *oucp, const struct __ucontext *ucp); } + SYS_SWAPOFF = 424 // { int swapoff(const char *name); } + SYS___ACL_GET_LINK = 425 // { int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); } + SYS___ACL_SET_LINK = 426 // { int __acl_set_link(const char *path, acl_type_t type, struct acl *aclp); } + SYS___ACL_DELETE_LINK = 427 // { int __acl_delete_link(const char *path, acl_type_t type); } + SYS___ACL_ACLCHECK_LINK = 428 // { int __acl_aclcheck_link(const char *path, acl_type_t type, struct acl *aclp); } + SYS_SIGWAIT = 429 // { int sigwait(const sigset_t *set, int *sig); } + SYS_THR_CREATE = 430 // { int thr_create(ucontext_t *ctx, long *id, int flags); } + SYS_THR_EXIT = 431 // { void thr_exit(long *state); } + SYS_THR_SELF = 432 // { int thr_self(long *id); } + SYS_THR_KILL = 433 // { int thr_kill(long id, int sig); } + SYS_JAIL_ATTACH = 436 // { int jail_attach(int jid); } + SYS_EXTATTR_LIST_FD = 437 // { ssize_t extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_FILE = 438 // { ssize_t extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_LINK = 439 // { ssize_t extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_KSEM_TIMEDWAIT = 441 // { int ksem_timedwait(semid_t id, const struct timespec *abstime); } + SYS_THR_SUSPEND = 442 // { int thr_suspend(const struct timespec *timeout); } + SYS_THR_WAKE = 443 // { int thr_wake(long id); } + SYS_KLDUNLOADF = 444 // { int kldunloadf(int fileid, int flags); } + SYS_AUDIT = 445 // { int audit(const void *record, u_int length); } + SYS_AUDITON = 446 // { int auditon(int cmd, void *data, u_int length); } + SYS_GETAUID = 447 // { int getauid(uid_t *auid); } + SYS_SETAUID = 448 // { int setauid(uid_t *auid); } + SYS_GETAUDIT = 449 // { int getaudit(struct auditinfo *auditinfo); } + SYS_SETAUDIT = 450 // { int setaudit(struct auditinfo *auditinfo); } + SYS_GETAUDIT_ADDR = 451 // { int getaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_SETAUDIT_ADDR = 452 // { int setaudit_addr(struct auditinfo_addr *auditinfo_addr, u_int length); } + SYS_AUDITCTL = 453 // { int auditctl(char *path); } + SYS__UMTX_OP = 454 // { int _umtx_op(void *obj, int op, u_long val, void *uaddr1, void *uaddr2); } + SYS_THR_NEW = 455 // { int thr_new(struct thr_param *param, int param_size); } + SYS_SIGQUEUE = 456 // { int sigqueue(pid_t pid, int signum, void *value); } + SYS_KMQ_OPEN = 457 // { int kmq_open(const char *path, int flags, mode_t mode, const struct mq_attr *attr); } + SYS_KMQ_SETATTR = 458 // { int kmq_setattr(int mqd, const struct mq_attr *attr, struct mq_attr *oattr); } + SYS_KMQ_TIMEDRECEIVE = 459 // { int kmq_timedreceive(int mqd, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_TIMEDSEND = 460 // { int kmq_timedsend(int mqd, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout); } + SYS_KMQ_NOTIFY = 461 // { int kmq_notify(int mqd, const struct sigevent *sigev); } + SYS_KMQ_UNLINK = 462 // { int kmq_unlink(const char *path); } + SYS_ABORT2 = 463 // { int abort2(const char *why, int nargs, void **args); } + SYS_THR_SET_NAME = 464 // { int thr_set_name(long id, const char *name); } + SYS_AIO_FSYNC = 465 // { int aio_fsync(int op, struct aiocb *aiocbp); } + SYS_RTPRIO_THREAD = 466 // { int rtprio_thread(int function, lwpid_t lwpid, struct rtprio *rtp); } + SYS_SCTP_PEELOFF = 471 // { int sctp_peeloff(int sd, uint32_t name); } + SYS_SCTP_GENERIC_SENDMSG = 472 // { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } + SYS_SCTP_GENERIC_SENDMSG_IOV = 473 // { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, caddr_t to, __socklen_t tolen, struct sctp_sndrcvinfo *sinfo, int flags); } + SYS_SCTP_GENERIC_RECVMSG = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, struct sockaddr *from, __socklen_t *fromlenaddr, struct sctp_sndrcvinfo *sinfo, int *msg_flags); } + SYS_PREAD = 475 // { ssize_t pread(int fd, void *buf, size_t nbyte, off_t offset); } + SYS_PWRITE = 476 // { ssize_t pwrite(int fd, const void *buf, size_t nbyte, off_t offset); } + SYS_MMAP = 477 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos); } + SYS_LSEEK = 478 // { off_t lseek(int fd, off_t offset, int whence); } + SYS_TRUNCATE = 479 // { int truncate(char *path, off_t length); } + SYS_FTRUNCATE = 480 // { int ftruncate(int fd, off_t length); } + SYS_THR_KILL2 = 481 // { int thr_kill2(pid_t pid, long id, int sig); } + SYS_SHM_OPEN = 482 // { int shm_open(const char *path, int flags, mode_t mode); } + SYS_SHM_UNLINK = 483 // { int shm_unlink(const char *path); } + SYS_CPUSET = 484 // { int cpuset(cpusetid_t *setid); } + SYS_CPUSET_SETID = 485 // { int cpuset_setid(cpuwhich_t which, id_t id, cpusetid_t setid); } + SYS_CPUSET_GETID = 486 // { int cpuset_getid(cpulevel_t level, cpuwhich_t which, id_t id, cpusetid_t *setid); } + SYS_CPUSET_GETAFFINITY = 487 // { int cpuset_getaffinity(cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, cpuset_t *mask); } + SYS_CPUSET_SETAFFINITY = 488 // { int cpuset_setaffinity(cpulevel_t level, cpuwhich_t which, id_t id, size_t cpusetsize, const cpuset_t *mask); } + SYS_FACCESSAT = 489 // { int faccessat(int fd, char *path, int amode, int flag); } + SYS_FCHMODAT = 490 // { int fchmodat(int fd, char *path, mode_t mode, int flag); } + SYS_FCHOWNAT = 491 // { int fchownat(int fd, char *path, uid_t uid, gid_t gid, int flag); } + SYS_FEXECVE = 492 // { int fexecve(int fd, char **argv, char **envv); } + SYS_FUTIMESAT = 494 // { int futimesat(int fd, char *path, struct timeval *times); } + SYS_LINKAT = 495 // { int linkat(int fd1, char *path1, int fd2, char *path2, int flag); } + SYS_MKDIRAT = 496 // { int mkdirat(int fd, char *path, mode_t mode); } + SYS_MKFIFOAT = 497 // { int mkfifoat(int fd, char *path, mode_t mode); } + SYS_OPENAT = 499 // { int openat(int fd, char *path, int flag, mode_t mode); } + SYS_READLINKAT = 500 // { ssize_t readlinkat(int fd, char *path, char *buf, size_t bufsize); } + SYS_RENAMEAT = 501 // { int renameat(int oldfd, char *old, int newfd, char *new); } + SYS_SYMLINKAT = 502 // { int symlinkat(char *path1, int fd, char *path2); } + SYS_UNLINKAT = 503 // { int unlinkat(int fd, char *path, int flag); } + SYS_POSIX_OPENPT = 504 // { int posix_openpt(int flags); } + SYS_GSSD_SYSCALL = 505 // { int gssd_syscall(char *path); } + SYS_JAIL_GET = 506 // { int jail_get(struct iovec *iovp, unsigned int iovcnt, int flags); } + SYS_JAIL_SET = 507 // { int jail_set(struct iovec *iovp, unsigned int iovcnt, int flags); } + SYS_JAIL_REMOVE = 508 // { int jail_remove(int jid); } + SYS_CLOSEFROM = 509 // { int closefrom(int lowfd); } + SYS___SEMCTL = 510 // { int __semctl(int semid, int semnum, int cmd, union semun *arg); } + SYS_MSGCTL = 511 // { int msgctl(int msqid, int cmd, struct msqid_ds *buf); } + SYS_SHMCTL = 512 // { int shmctl(int shmid, int cmd, struct shmid_ds *buf); } + SYS_LPATHCONF = 513 // { int lpathconf(char *path, int name); } + SYS___CAP_RIGHTS_GET = 515 // { int __cap_rights_get(int version, int fd, cap_rights_t *rightsp); } + SYS_CAP_ENTER = 516 // { int cap_enter(void); } + SYS_CAP_GETMODE = 517 // { int cap_getmode(u_int *modep); } + SYS_PDFORK = 518 // { int pdfork(int *fdp, int flags); } + SYS_PDKILL = 519 // { int pdkill(int fd, int signum); } + SYS_PDGETPID = 520 // { int pdgetpid(int fd, pid_t *pidp); } + SYS_PSELECT = 522 // { int pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *sm); } + SYS_GETLOGINCLASS = 523 // { int getloginclass(char *namebuf, size_t namelen); } + SYS_SETLOGINCLASS = 524 // { int setloginclass(const char *namebuf); } + SYS_RCTL_GET_RACCT = 525 // { int rctl_get_racct(const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); } + SYS_RCTL_GET_RULES = 526 // { int rctl_get_rules(const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); } + SYS_RCTL_GET_LIMITS = 527 // { int rctl_get_limits(const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); } + SYS_RCTL_ADD_RULE = 528 // { int rctl_add_rule(const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); } + SYS_RCTL_REMOVE_RULE = 529 // { int rctl_remove_rule(const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); } + SYS_POSIX_FALLOCATE = 530 // { int posix_fallocate(int fd, off_t offset, off_t len); } + SYS_POSIX_FADVISE = 531 // { int posix_fadvise(int fd, off_t offset, off_t len, int advice); } + SYS_WAIT6 = 532 // { int wait6(idtype_t idtype, id_t id, int *status, int options, struct __wrusage *wrusage, siginfo_t *info); } + SYS_CAP_RIGHTS_LIMIT = 533 // { int cap_rights_limit(int fd, cap_rights_t *rightsp); } + SYS_CAP_IOCTLS_LIMIT = 534 // { int cap_ioctls_limit(int fd, const u_long *cmds, size_t ncmds); } + SYS_CAP_IOCTLS_GET = 535 // { ssize_t cap_ioctls_get(int fd, u_long *cmds, size_t maxcmds); } + SYS_CAP_FCNTLS_LIMIT = 536 // { int cap_fcntls_limit(int fd, uint32_t fcntlrights); } + SYS_CAP_FCNTLS_GET = 537 // { int cap_fcntls_get(int fd, uint32_t *fcntlrightsp); } + SYS_BINDAT = 538 // { int bindat(int fd, int s, caddr_t name, int namelen); } + SYS_CONNECTAT = 539 // { int connectat(int fd, int s, caddr_t name, int namelen); } + SYS_CHFLAGSAT = 540 // { int chflagsat(int fd, const char *path, u_long flags, int atflag); } + SYS_ACCEPT4 = 541 // { int accept4(int s, struct sockaddr * __restrict name, __socklen_t * __restrict anamelen, int flags); } + SYS_PIPE2 = 542 // { int pipe2(int *fildes, int flags); } + SYS_AIO_MLOCK = 543 // { int aio_mlock(struct aiocb *aiocbp); } + SYS_PROCCTL = 544 // { int procctl(idtype_t idtype, id_t id, int com, void *data); } + SYS_PPOLL = 545 // { int ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *set); } + SYS_FUTIMENS = 546 // { int futimens(int fd, struct timespec *times); } + SYS_UTIMENSAT = 547 // { int utimensat(int fd, char *path, struct timespec *times, int flag); } + SYS_FDATASYNC = 550 // { int fdatasync(int fd); } + SYS_FSTAT = 551 // { int fstat(int fd, struct stat *sb); } + SYS_FSTATAT = 552 // { int fstatat(int fd, char *path, struct stat *buf, int flag); } + SYS_FHSTAT = 553 // { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } + SYS_GETDIRENTRIES = 554 // { ssize_t getdirentries(int fd, char *buf, size_t count, off_t *basep); } + SYS_STATFS = 555 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 556 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFSSTAT = 557 // { int getfsstat(struct statfs *buf, long bufsize, int mode); } + SYS_FHSTATFS = 558 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } + SYS_MKNODAT = 559 // { int mknodat(int fd, char *path, mode_t mode, dev_t dev); } + SYS_KEVENT = 560 // { int kevent(int fd, struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_CPUSET_GETDOMAIN = 561 // { int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int *policy); } + SYS_CPUSET_SETDOMAIN = 562 // { int cpuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id, size_t domainsetsize, domainset_t *mask, int policy); } + SYS_GETRANDOM = 563 // { int getrandom(void *buf, size_t buflen, unsigned int flags); } + SYS_GETFHAT = 564 // { int getfhat(int fd, char *path, struct fhandle *fhp, int flags); } + SYS_FHLINK = 565 // { int fhlink(struct fhandle *fhp, const char *to); } + SYS_FHLINKAT = 566 // { int fhlinkat(struct fhandle *fhp, int tofd, const char *to,); } + SYS_FHREADLINK = 567 // { int fhreadlink(struct fhandle *fhp, char *buf, size_t bufsize); } + SYS___SYSCTLBYNAME = 570 // { int __sysctlbyname(const char *name, size_t namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_CLOSE_RANGE = 575 // { int close_range(u_int lowfd, u_int highfd, int flags); } +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 7aae554..aca56ee 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -1,7 +1,7 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include -m32 /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/386/include -m32 /tmp/386/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,linux +//go:build 386 && linux package unix @@ -431,4 +431,36 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 7968439..2ea1ef5 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -1,356 +1,389 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include -m64 /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/amd64/include -m64 /tmp/amd64/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,linux +//go:build amd64 && linux package unix const ( - SYS_READ = 0 - SYS_WRITE = 1 - SYS_OPEN = 2 - SYS_CLOSE = 3 - SYS_STAT = 4 - SYS_FSTAT = 5 - SYS_LSTAT = 6 - SYS_POLL = 7 - SYS_LSEEK = 8 - SYS_MMAP = 9 - SYS_MPROTECT = 10 - SYS_MUNMAP = 11 - SYS_BRK = 12 - SYS_RT_SIGACTION = 13 - SYS_RT_SIGPROCMASK = 14 - SYS_RT_SIGRETURN = 15 - SYS_IOCTL = 16 - SYS_PREAD64 = 17 - SYS_PWRITE64 = 18 - SYS_READV = 19 - SYS_WRITEV = 20 - SYS_ACCESS = 21 - SYS_PIPE = 22 - SYS_SELECT = 23 - SYS_SCHED_YIELD = 24 - SYS_MREMAP = 25 - SYS_MSYNC = 26 - SYS_MINCORE = 27 - SYS_MADVISE = 28 - SYS_SHMGET = 29 - SYS_SHMAT = 30 - SYS_SHMCTL = 31 - SYS_DUP = 32 - SYS_DUP2 = 33 - SYS_PAUSE = 34 - SYS_NANOSLEEP = 35 - SYS_GETITIMER = 36 - SYS_ALARM = 37 - SYS_SETITIMER = 38 - SYS_GETPID = 39 - SYS_SENDFILE = 40 - SYS_SOCKET = 41 - SYS_CONNECT = 42 - SYS_ACCEPT = 43 - SYS_SENDTO = 44 - SYS_RECVFROM = 45 - SYS_SENDMSG = 46 - SYS_RECVMSG = 47 - SYS_SHUTDOWN = 48 - SYS_BIND = 49 - SYS_LISTEN = 50 - SYS_GETSOCKNAME = 51 - SYS_GETPEERNAME = 52 - SYS_SOCKETPAIR = 53 - SYS_SETSOCKOPT = 54 - SYS_GETSOCKOPT = 55 - SYS_CLONE = 56 - SYS_FORK = 57 - SYS_VFORK = 58 - SYS_EXECVE = 59 - SYS_EXIT = 60 - SYS_WAIT4 = 61 - SYS_KILL = 62 - SYS_UNAME = 63 - SYS_SEMGET = 64 - SYS_SEMOP = 65 - SYS_SEMCTL = 66 - SYS_SHMDT = 67 - SYS_MSGGET = 68 - SYS_MSGSND = 69 - SYS_MSGRCV = 70 - SYS_MSGCTL = 71 - SYS_FCNTL = 72 - SYS_FLOCK = 73 - SYS_FSYNC = 74 - SYS_FDATASYNC = 75 - SYS_TRUNCATE = 76 - SYS_FTRUNCATE = 77 - SYS_GETDENTS = 78 - SYS_GETCWD = 79 - SYS_CHDIR = 80 - SYS_FCHDIR = 81 - SYS_RENAME = 82 - SYS_MKDIR = 83 - SYS_RMDIR = 84 - SYS_CREAT = 85 - SYS_LINK = 86 - SYS_UNLINK = 87 - SYS_SYMLINK = 88 - SYS_READLINK = 89 - SYS_CHMOD = 90 - SYS_FCHMOD = 91 - SYS_CHOWN = 92 - SYS_FCHOWN = 93 - SYS_LCHOWN = 94 - SYS_UMASK = 95 - SYS_GETTIMEOFDAY = 96 - SYS_GETRLIMIT = 97 - SYS_GETRUSAGE = 98 - SYS_SYSINFO = 99 - SYS_TIMES = 100 - SYS_PTRACE = 101 - SYS_GETUID = 102 - SYS_SYSLOG = 103 - SYS_GETGID = 104 - SYS_SETUID = 105 - SYS_SETGID = 106 - SYS_GETEUID = 107 - SYS_GETEGID = 108 - SYS_SETPGID = 109 - SYS_GETPPID = 110 - SYS_GETPGRP = 111 - SYS_SETSID = 112 - SYS_SETREUID = 113 - SYS_SETREGID = 114 - SYS_GETGROUPS = 115 - SYS_SETGROUPS = 116 - SYS_SETRESUID = 117 - SYS_GETRESUID = 118 - SYS_SETRESGID = 119 - SYS_GETRESGID = 120 - SYS_GETPGID = 121 - SYS_SETFSUID = 122 - SYS_SETFSGID = 123 - SYS_GETSID = 124 - SYS_CAPGET = 125 - SYS_CAPSET = 126 - SYS_RT_SIGPENDING = 127 - SYS_RT_SIGTIMEDWAIT = 128 - SYS_RT_SIGQUEUEINFO = 129 - SYS_RT_SIGSUSPEND = 130 - SYS_SIGALTSTACK = 131 - SYS_UTIME = 132 - SYS_MKNOD = 133 - SYS_USELIB = 134 - SYS_PERSONALITY = 135 - SYS_USTAT = 136 - SYS_STATFS = 137 - SYS_FSTATFS = 138 - SYS_SYSFS = 139 - SYS_GETPRIORITY = 140 - SYS_SETPRIORITY = 141 - SYS_SCHED_SETPARAM = 142 - SYS_SCHED_GETPARAM = 143 - SYS_SCHED_SETSCHEDULER = 144 - SYS_SCHED_GETSCHEDULER = 145 - SYS_SCHED_GET_PRIORITY_MAX = 146 - SYS_SCHED_GET_PRIORITY_MIN = 147 - SYS_SCHED_RR_GET_INTERVAL = 148 - SYS_MLOCK = 149 - SYS_MUNLOCK = 150 - SYS_MLOCKALL = 151 - SYS_MUNLOCKALL = 152 - SYS_VHANGUP = 153 - SYS_MODIFY_LDT = 154 - SYS_PIVOT_ROOT = 155 - SYS__SYSCTL = 156 - SYS_PRCTL = 157 - SYS_ARCH_PRCTL = 158 - SYS_ADJTIMEX = 159 - SYS_SETRLIMIT = 160 - SYS_CHROOT = 161 - SYS_SYNC = 162 - SYS_ACCT = 163 - SYS_SETTIMEOFDAY = 164 - SYS_MOUNT = 165 - SYS_UMOUNT2 = 166 - SYS_SWAPON = 167 - SYS_SWAPOFF = 168 - SYS_REBOOT = 169 - SYS_SETHOSTNAME = 170 - SYS_SETDOMAINNAME = 171 - SYS_IOPL = 172 - SYS_IOPERM = 173 - SYS_CREATE_MODULE = 174 - SYS_INIT_MODULE = 175 - SYS_DELETE_MODULE = 176 - SYS_GET_KERNEL_SYMS = 177 - SYS_QUERY_MODULE = 178 - SYS_QUOTACTL = 179 - SYS_NFSSERVCTL = 180 - SYS_GETPMSG = 181 - SYS_PUTPMSG = 182 - SYS_AFS_SYSCALL = 183 - SYS_TUXCALL = 184 - SYS_SECURITY = 185 - SYS_GETTID = 186 - SYS_READAHEAD = 187 - SYS_SETXATTR = 188 - SYS_LSETXATTR = 189 - SYS_FSETXATTR = 190 - SYS_GETXATTR = 191 - SYS_LGETXATTR = 192 - SYS_FGETXATTR = 193 - SYS_LISTXATTR = 194 - SYS_LLISTXATTR = 195 - SYS_FLISTXATTR = 196 - SYS_REMOVEXATTR = 197 - SYS_LREMOVEXATTR = 198 - SYS_FREMOVEXATTR = 199 - SYS_TKILL = 200 - SYS_TIME = 201 - SYS_FUTEX = 202 - SYS_SCHED_SETAFFINITY = 203 - SYS_SCHED_GETAFFINITY = 204 - SYS_SET_THREAD_AREA = 205 - SYS_IO_SETUP = 206 - SYS_IO_DESTROY = 207 - SYS_IO_GETEVENTS = 208 - SYS_IO_SUBMIT = 209 - SYS_IO_CANCEL = 210 - SYS_GET_THREAD_AREA = 211 - SYS_LOOKUP_DCOOKIE = 212 - SYS_EPOLL_CREATE = 213 - SYS_EPOLL_CTL_OLD = 214 - SYS_EPOLL_WAIT_OLD = 215 - SYS_REMAP_FILE_PAGES = 216 - SYS_GETDENTS64 = 217 - SYS_SET_TID_ADDRESS = 218 - SYS_RESTART_SYSCALL = 219 - SYS_SEMTIMEDOP = 220 - SYS_FADVISE64 = 221 - SYS_TIMER_CREATE = 222 - SYS_TIMER_SETTIME = 223 - SYS_TIMER_GETTIME = 224 - SYS_TIMER_GETOVERRUN = 225 - SYS_TIMER_DELETE = 226 - SYS_CLOCK_SETTIME = 227 - SYS_CLOCK_GETTIME = 228 - SYS_CLOCK_GETRES = 229 - SYS_CLOCK_NANOSLEEP = 230 - SYS_EXIT_GROUP = 231 - SYS_EPOLL_WAIT = 232 - SYS_EPOLL_CTL = 233 - SYS_TGKILL = 234 - SYS_UTIMES = 235 - SYS_VSERVER = 236 - SYS_MBIND = 237 - SYS_SET_MEMPOLICY = 238 - SYS_GET_MEMPOLICY = 239 - SYS_MQ_OPEN = 240 - SYS_MQ_UNLINK = 241 - SYS_MQ_TIMEDSEND = 242 - SYS_MQ_TIMEDRECEIVE = 243 - SYS_MQ_NOTIFY = 244 - SYS_MQ_GETSETATTR = 245 - SYS_KEXEC_LOAD = 246 - SYS_WAITID = 247 - SYS_ADD_KEY = 248 - SYS_REQUEST_KEY = 249 - SYS_KEYCTL = 250 - SYS_IOPRIO_SET = 251 - SYS_IOPRIO_GET = 252 - SYS_INOTIFY_INIT = 253 - SYS_INOTIFY_ADD_WATCH = 254 - SYS_INOTIFY_RM_WATCH = 255 - SYS_MIGRATE_PAGES = 256 - SYS_OPENAT = 257 - SYS_MKDIRAT = 258 - SYS_MKNODAT = 259 - SYS_FCHOWNAT = 260 - SYS_FUTIMESAT = 261 - SYS_NEWFSTATAT = 262 - SYS_UNLINKAT = 263 - SYS_RENAMEAT = 264 - SYS_LINKAT = 265 - SYS_SYMLINKAT = 266 - SYS_READLINKAT = 267 - SYS_FCHMODAT = 268 - SYS_FACCESSAT = 269 - SYS_PSELECT6 = 270 - SYS_PPOLL = 271 - SYS_UNSHARE = 272 - SYS_SET_ROBUST_LIST = 273 - SYS_GET_ROBUST_LIST = 274 - SYS_SPLICE = 275 - SYS_TEE = 276 - SYS_SYNC_FILE_RANGE = 277 - SYS_VMSPLICE = 278 - SYS_MOVE_PAGES = 279 - SYS_UTIMENSAT = 280 - SYS_EPOLL_PWAIT = 281 - SYS_SIGNALFD = 282 - SYS_TIMERFD_CREATE = 283 - SYS_EVENTFD = 284 - SYS_FALLOCATE = 285 - SYS_TIMERFD_SETTIME = 286 - SYS_TIMERFD_GETTIME = 287 - SYS_ACCEPT4 = 288 - SYS_SIGNALFD4 = 289 - SYS_EVENTFD2 = 290 - SYS_EPOLL_CREATE1 = 291 - SYS_DUP3 = 292 - SYS_PIPE2 = 293 - SYS_INOTIFY_INIT1 = 294 - SYS_PREADV = 295 - SYS_PWRITEV = 296 - SYS_RT_TGSIGQUEUEINFO = 297 - SYS_PERF_EVENT_OPEN = 298 - SYS_RECVMMSG = 299 - SYS_FANOTIFY_INIT = 300 - SYS_FANOTIFY_MARK = 301 - SYS_PRLIMIT64 = 302 - SYS_NAME_TO_HANDLE_AT = 303 - SYS_OPEN_BY_HANDLE_AT = 304 - SYS_CLOCK_ADJTIME = 305 - SYS_SYNCFS = 306 - SYS_SENDMMSG = 307 - SYS_SETNS = 308 - SYS_GETCPU = 309 - SYS_PROCESS_VM_READV = 310 - SYS_PROCESS_VM_WRITEV = 311 - SYS_KCMP = 312 - SYS_FINIT_MODULE = 313 - SYS_SCHED_SETATTR = 314 - SYS_SCHED_GETATTR = 315 - SYS_RENAMEAT2 = 316 - SYS_SECCOMP = 317 - SYS_GETRANDOM = 318 - SYS_MEMFD_CREATE = 319 - SYS_KEXEC_FILE_LOAD = 320 - SYS_BPF = 321 - SYS_EXECVEAT = 322 - SYS_USERFAULTFD = 323 - SYS_MEMBARRIER = 324 - SYS_MLOCK2 = 325 - SYS_COPY_FILE_RANGE = 326 - SYS_PREADV2 = 327 - SYS_PWRITEV2 = 328 - SYS_PKEY_MPROTECT = 329 - SYS_PKEY_ALLOC = 330 - SYS_PKEY_FREE = 331 - SYS_STATX = 332 - SYS_IO_PGETEVENTS = 333 - SYS_RSEQ = 334 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 + SYS_READ = 0 + SYS_WRITE = 1 + SYS_OPEN = 2 + SYS_CLOSE = 3 + SYS_STAT = 4 + SYS_FSTAT = 5 + SYS_LSTAT = 6 + SYS_POLL = 7 + SYS_LSEEK = 8 + SYS_MMAP = 9 + SYS_MPROTECT = 10 + SYS_MUNMAP = 11 + SYS_BRK = 12 + SYS_RT_SIGACTION = 13 + SYS_RT_SIGPROCMASK = 14 + SYS_RT_SIGRETURN = 15 + SYS_IOCTL = 16 + SYS_PREAD64 = 17 + SYS_PWRITE64 = 18 + SYS_READV = 19 + SYS_WRITEV = 20 + SYS_ACCESS = 21 + SYS_PIPE = 22 + SYS_SELECT = 23 + SYS_SCHED_YIELD = 24 + SYS_MREMAP = 25 + SYS_MSYNC = 26 + SYS_MINCORE = 27 + SYS_MADVISE = 28 + SYS_SHMGET = 29 + SYS_SHMAT = 30 + SYS_SHMCTL = 31 + SYS_DUP = 32 + SYS_DUP2 = 33 + SYS_PAUSE = 34 + SYS_NANOSLEEP = 35 + SYS_GETITIMER = 36 + SYS_ALARM = 37 + SYS_SETITIMER = 38 + SYS_GETPID = 39 + SYS_SENDFILE = 40 + SYS_SOCKET = 41 + SYS_CONNECT = 42 + SYS_ACCEPT = 43 + SYS_SENDTO = 44 + SYS_RECVFROM = 45 + SYS_SENDMSG = 46 + SYS_RECVMSG = 47 + SYS_SHUTDOWN = 48 + SYS_BIND = 49 + SYS_LISTEN = 50 + SYS_GETSOCKNAME = 51 + SYS_GETPEERNAME = 52 + SYS_SOCKETPAIR = 53 + SYS_SETSOCKOPT = 54 + SYS_GETSOCKOPT = 55 + SYS_CLONE = 56 + SYS_FORK = 57 + SYS_VFORK = 58 + SYS_EXECVE = 59 + SYS_EXIT = 60 + SYS_WAIT4 = 61 + SYS_KILL = 62 + SYS_UNAME = 63 + SYS_SEMGET = 64 + SYS_SEMOP = 65 + SYS_SEMCTL = 66 + SYS_SHMDT = 67 + SYS_MSGGET = 68 + SYS_MSGSND = 69 + SYS_MSGRCV = 70 + SYS_MSGCTL = 71 + SYS_FCNTL = 72 + SYS_FLOCK = 73 + SYS_FSYNC = 74 + SYS_FDATASYNC = 75 + SYS_TRUNCATE = 76 + SYS_FTRUNCATE = 77 + SYS_GETDENTS = 78 + SYS_GETCWD = 79 + SYS_CHDIR = 80 + SYS_FCHDIR = 81 + SYS_RENAME = 82 + SYS_MKDIR = 83 + SYS_RMDIR = 84 + SYS_CREAT = 85 + SYS_LINK = 86 + SYS_UNLINK = 87 + SYS_SYMLINK = 88 + SYS_READLINK = 89 + SYS_CHMOD = 90 + SYS_FCHMOD = 91 + SYS_CHOWN = 92 + SYS_FCHOWN = 93 + SYS_LCHOWN = 94 + SYS_UMASK = 95 + SYS_GETTIMEOFDAY = 96 + SYS_GETRLIMIT = 97 + SYS_GETRUSAGE = 98 + SYS_SYSINFO = 99 + SYS_TIMES = 100 + SYS_PTRACE = 101 + SYS_GETUID = 102 + SYS_SYSLOG = 103 + SYS_GETGID = 104 + SYS_SETUID = 105 + SYS_SETGID = 106 + SYS_GETEUID = 107 + SYS_GETEGID = 108 + SYS_SETPGID = 109 + SYS_GETPPID = 110 + SYS_GETPGRP = 111 + SYS_SETSID = 112 + SYS_SETREUID = 113 + SYS_SETREGID = 114 + SYS_GETGROUPS = 115 + SYS_SETGROUPS = 116 + SYS_SETRESUID = 117 + SYS_GETRESUID = 118 + SYS_SETRESGID = 119 + SYS_GETRESGID = 120 + SYS_GETPGID = 121 + SYS_SETFSUID = 122 + SYS_SETFSGID = 123 + SYS_GETSID = 124 + SYS_CAPGET = 125 + SYS_CAPSET = 126 + SYS_RT_SIGPENDING = 127 + SYS_RT_SIGTIMEDWAIT = 128 + SYS_RT_SIGQUEUEINFO = 129 + SYS_RT_SIGSUSPEND = 130 + SYS_SIGALTSTACK = 131 + SYS_UTIME = 132 + SYS_MKNOD = 133 + SYS_USELIB = 134 + SYS_PERSONALITY = 135 + SYS_USTAT = 136 + SYS_STATFS = 137 + SYS_FSTATFS = 138 + SYS_SYSFS = 139 + SYS_GETPRIORITY = 140 + SYS_SETPRIORITY = 141 + SYS_SCHED_SETPARAM = 142 + SYS_SCHED_GETPARAM = 143 + SYS_SCHED_SETSCHEDULER = 144 + SYS_SCHED_GETSCHEDULER = 145 + SYS_SCHED_GET_PRIORITY_MAX = 146 + SYS_SCHED_GET_PRIORITY_MIN = 147 + SYS_SCHED_RR_GET_INTERVAL = 148 + SYS_MLOCK = 149 + SYS_MUNLOCK = 150 + SYS_MLOCKALL = 151 + SYS_MUNLOCKALL = 152 + SYS_VHANGUP = 153 + SYS_MODIFY_LDT = 154 + SYS_PIVOT_ROOT = 155 + SYS__SYSCTL = 156 + SYS_PRCTL = 157 + SYS_ARCH_PRCTL = 158 + SYS_ADJTIMEX = 159 + SYS_SETRLIMIT = 160 + SYS_CHROOT = 161 + SYS_SYNC = 162 + SYS_ACCT = 163 + SYS_SETTIMEOFDAY = 164 + SYS_MOUNT = 165 + SYS_UMOUNT2 = 166 + SYS_SWAPON = 167 + SYS_SWAPOFF = 168 + SYS_REBOOT = 169 + SYS_SETHOSTNAME = 170 + SYS_SETDOMAINNAME = 171 + SYS_IOPL = 172 + SYS_IOPERM = 173 + SYS_CREATE_MODULE = 174 + SYS_INIT_MODULE = 175 + SYS_DELETE_MODULE = 176 + SYS_GET_KERNEL_SYMS = 177 + SYS_QUERY_MODULE = 178 + SYS_QUOTACTL = 179 + SYS_NFSSERVCTL = 180 + SYS_GETPMSG = 181 + SYS_PUTPMSG = 182 + SYS_AFS_SYSCALL = 183 + SYS_TUXCALL = 184 + SYS_SECURITY = 185 + SYS_GETTID = 186 + SYS_READAHEAD = 187 + SYS_SETXATTR = 188 + SYS_LSETXATTR = 189 + SYS_FSETXATTR = 190 + SYS_GETXATTR = 191 + SYS_LGETXATTR = 192 + SYS_FGETXATTR = 193 + SYS_LISTXATTR = 194 + SYS_LLISTXATTR = 195 + SYS_FLISTXATTR = 196 + SYS_REMOVEXATTR = 197 + SYS_LREMOVEXATTR = 198 + SYS_FREMOVEXATTR = 199 + SYS_TKILL = 200 + SYS_TIME = 201 + SYS_FUTEX = 202 + SYS_SCHED_SETAFFINITY = 203 + SYS_SCHED_GETAFFINITY = 204 + SYS_SET_THREAD_AREA = 205 + SYS_IO_SETUP = 206 + SYS_IO_DESTROY = 207 + SYS_IO_GETEVENTS = 208 + SYS_IO_SUBMIT = 209 + SYS_IO_CANCEL = 210 + SYS_GET_THREAD_AREA = 211 + SYS_LOOKUP_DCOOKIE = 212 + SYS_EPOLL_CREATE = 213 + SYS_EPOLL_CTL_OLD = 214 + SYS_EPOLL_WAIT_OLD = 215 + SYS_REMAP_FILE_PAGES = 216 + SYS_GETDENTS64 = 217 + SYS_SET_TID_ADDRESS = 218 + SYS_RESTART_SYSCALL = 219 + SYS_SEMTIMEDOP = 220 + SYS_FADVISE64 = 221 + SYS_TIMER_CREATE = 222 + SYS_TIMER_SETTIME = 223 + SYS_TIMER_GETTIME = 224 + SYS_TIMER_GETOVERRUN = 225 + SYS_TIMER_DELETE = 226 + SYS_CLOCK_SETTIME = 227 + SYS_CLOCK_GETTIME = 228 + SYS_CLOCK_GETRES = 229 + SYS_CLOCK_NANOSLEEP = 230 + SYS_EXIT_GROUP = 231 + SYS_EPOLL_WAIT = 232 + SYS_EPOLL_CTL = 233 + SYS_TGKILL = 234 + SYS_UTIMES = 235 + SYS_VSERVER = 236 + SYS_MBIND = 237 + SYS_SET_MEMPOLICY = 238 + SYS_GET_MEMPOLICY = 239 + SYS_MQ_OPEN = 240 + SYS_MQ_UNLINK = 241 + SYS_MQ_TIMEDSEND = 242 + SYS_MQ_TIMEDRECEIVE = 243 + SYS_MQ_NOTIFY = 244 + SYS_MQ_GETSETATTR = 245 + SYS_KEXEC_LOAD = 246 + SYS_WAITID = 247 + SYS_ADD_KEY = 248 + SYS_REQUEST_KEY = 249 + SYS_KEYCTL = 250 + SYS_IOPRIO_SET = 251 + SYS_IOPRIO_GET = 252 + SYS_INOTIFY_INIT = 253 + SYS_INOTIFY_ADD_WATCH = 254 + SYS_INOTIFY_RM_WATCH = 255 + SYS_MIGRATE_PAGES = 256 + SYS_OPENAT = 257 + SYS_MKDIRAT = 258 + SYS_MKNODAT = 259 + SYS_FCHOWNAT = 260 + SYS_FUTIMESAT = 261 + SYS_NEWFSTATAT = 262 + SYS_UNLINKAT = 263 + SYS_RENAMEAT = 264 + SYS_LINKAT = 265 + SYS_SYMLINKAT = 266 + SYS_READLINKAT = 267 + SYS_FCHMODAT = 268 + SYS_FACCESSAT = 269 + SYS_PSELECT6 = 270 + SYS_PPOLL = 271 + SYS_UNSHARE = 272 + SYS_SET_ROBUST_LIST = 273 + SYS_GET_ROBUST_LIST = 274 + SYS_SPLICE = 275 + SYS_TEE = 276 + SYS_SYNC_FILE_RANGE = 277 + SYS_VMSPLICE = 278 + SYS_MOVE_PAGES = 279 + SYS_UTIMENSAT = 280 + SYS_EPOLL_PWAIT = 281 + SYS_SIGNALFD = 282 + SYS_TIMERFD_CREATE = 283 + SYS_EVENTFD = 284 + SYS_FALLOCATE = 285 + SYS_TIMERFD_SETTIME = 286 + SYS_TIMERFD_GETTIME = 287 + SYS_ACCEPT4 = 288 + SYS_SIGNALFD4 = 289 + SYS_EVENTFD2 = 290 + SYS_EPOLL_CREATE1 = 291 + SYS_DUP3 = 292 + SYS_PIPE2 = 293 + SYS_INOTIFY_INIT1 = 294 + SYS_PREADV = 295 + SYS_PWRITEV = 296 + SYS_RT_TGSIGQUEUEINFO = 297 + SYS_PERF_EVENT_OPEN = 298 + SYS_RECVMMSG = 299 + SYS_FANOTIFY_INIT = 300 + SYS_FANOTIFY_MARK = 301 + SYS_PRLIMIT64 = 302 + SYS_NAME_TO_HANDLE_AT = 303 + SYS_OPEN_BY_HANDLE_AT = 304 + SYS_CLOCK_ADJTIME = 305 + SYS_SYNCFS = 306 + SYS_SENDMMSG = 307 + SYS_SETNS = 308 + SYS_GETCPU = 309 + SYS_PROCESS_VM_READV = 310 + SYS_PROCESS_VM_WRITEV = 311 + SYS_KCMP = 312 + SYS_FINIT_MODULE = 313 + SYS_SCHED_SETATTR = 314 + SYS_SCHED_GETATTR = 315 + SYS_RENAMEAT2 = 316 + SYS_SECCOMP = 317 + SYS_GETRANDOM = 318 + SYS_MEMFD_CREATE = 319 + SYS_KEXEC_FILE_LOAD = 320 + SYS_BPF = 321 + SYS_EXECVEAT = 322 + SYS_USERFAULTFD = 323 + SYS_MEMBARRIER = 324 + SYS_MLOCK2 = 325 + SYS_COPY_FILE_RANGE = 326 + SYS_PREADV2 = 327 + SYS_PWRITEV2 = 328 + SYS_PKEY_MPROTECT = 329 + SYS_PKEY_ALLOC = 330 + SYS_PKEY_FREE = 331 + SYS_STATX = 332 + SYS_IO_PGETEVENTS = 333 + SYS_RSEQ = 334 + SYS_URETPROBE = 335 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 3c663c6..d22c8af 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -1,11 +1,12 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/arm/include /tmp/arm/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,linux +//go:build arm && linux package unix const ( + SYS_SYSCALL_MASK = 0 SYS_RESTART_SYSCALL = 0 SYS_EXIT = 1 SYS_FORK = 2 @@ -395,4 +396,35 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 1f3b4d1..5ee264a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -1,301 +1,333 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include -fsigned-char /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/arm64/include -fsigned-char /tmp/arm64/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,linux +//go:build arm64 && linux package unix const ( - SYS_IO_SETUP = 0 - SYS_IO_DESTROY = 1 - SYS_IO_SUBMIT = 2 - SYS_IO_CANCEL = 3 - SYS_IO_GETEVENTS = 4 - SYS_SETXATTR = 5 - SYS_LSETXATTR = 6 - SYS_FSETXATTR = 7 - SYS_GETXATTR = 8 - SYS_LGETXATTR = 9 - SYS_FGETXATTR = 10 - SYS_LISTXATTR = 11 - SYS_LLISTXATTR = 12 - SYS_FLISTXATTR = 13 - SYS_REMOVEXATTR = 14 - SYS_LREMOVEXATTR = 15 - SYS_FREMOVEXATTR = 16 - SYS_GETCWD = 17 - SYS_LOOKUP_DCOOKIE = 18 - SYS_EVENTFD2 = 19 - SYS_EPOLL_CREATE1 = 20 - SYS_EPOLL_CTL = 21 - SYS_EPOLL_PWAIT = 22 - SYS_DUP = 23 - SYS_DUP3 = 24 - SYS_FCNTL = 25 - SYS_INOTIFY_INIT1 = 26 - SYS_INOTIFY_ADD_WATCH = 27 - SYS_INOTIFY_RM_WATCH = 28 - SYS_IOCTL = 29 - SYS_IOPRIO_SET = 30 - SYS_IOPRIO_GET = 31 - SYS_FLOCK = 32 - SYS_MKNODAT = 33 - SYS_MKDIRAT = 34 - SYS_UNLINKAT = 35 - SYS_SYMLINKAT = 36 - SYS_LINKAT = 37 - SYS_RENAMEAT = 38 - SYS_UMOUNT2 = 39 - SYS_MOUNT = 40 - SYS_PIVOT_ROOT = 41 - SYS_NFSSERVCTL = 42 - SYS_STATFS = 43 - SYS_FSTATFS = 44 - SYS_TRUNCATE = 45 - SYS_FTRUNCATE = 46 - SYS_FALLOCATE = 47 - SYS_FACCESSAT = 48 - SYS_CHDIR = 49 - SYS_FCHDIR = 50 - SYS_CHROOT = 51 - SYS_FCHMOD = 52 - SYS_FCHMODAT = 53 - SYS_FCHOWNAT = 54 - SYS_FCHOWN = 55 - SYS_OPENAT = 56 - SYS_CLOSE = 57 - SYS_VHANGUP = 58 - SYS_PIPE2 = 59 - SYS_QUOTACTL = 60 - SYS_GETDENTS64 = 61 - SYS_LSEEK = 62 - SYS_READ = 63 - SYS_WRITE = 64 - SYS_READV = 65 - SYS_WRITEV = 66 - SYS_PREAD64 = 67 - SYS_PWRITE64 = 68 - SYS_PREADV = 69 - SYS_PWRITEV = 70 - SYS_SENDFILE = 71 - SYS_PSELECT6 = 72 - SYS_PPOLL = 73 - SYS_SIGNALFD4 = 74 - SYS_VMSPLICE = 75 - SYS_SPLICE = 76 - SYS_TEE = 77 - SYS_READLINKAT = 78 - SYS_FSTATAT = 79 - SYS_FSTAT = 80 - SYS_SYNC = 81 - SYS_FSYNC = 82 - SYS_FDATASYNC = 83 - SYS_SYNC_FILE_RANGE = 84 - SYS_TIMERFD_CREATE = 85 - SYS_TIMERFD_SETTIME = 86 - SYS_TIMERFD_GETTIME = 87 - SYS_UTIMENSAT = 88 - SYS_ACCT = 89 - SYS_CAPGET = 90 - SYS_CAPSET = 91 - SYS_PERSONALITY = 92 - SYS_EXIT = 93 - SYS_EXIT_GROUP = 94 - SYS_WAITID = 95 - SYS_SET_TID_ADDRESS = 96 - SYS_UNSHARE = 97 - SYS_FUTEX = 98 - SYS_SET_ROBUST_LIST = 99 - SYS_GET_ROBUST_LIST = 100 - SYS_NANOSLEEP = 101 - SYS_GETITIMER = 102 - SYS_SETITIMER = 103 - SYS_KEXEC_LOAD = 104 - SYS_INIT_MODULE = 105 - SYS_DELETE_MODULE = 106 - SYS_TIMER_CREATE = 107 - SYS_TIMER_GETTIME = 108 - SYS_TIMER_GETOVERRUN = 109 - SYS_TIMER_SETTIME = 110 - SYS_TIMER_DELETE = 111 - SYS_CLOCK_SETTIME = 112 - SYS_CLOCK_GETTIME = 113 - SYS_CLOCK_GETRES = 114 - SYS_CLOCK_NANOSLEEP = 115 - SYS_SYSLOG = 116 - SYS_PTRACE = 117 - SYS_SCHED_SETPARAM = 118 - SYS_SCHED_SETSCHEDULER = 119 - SYS_SCHED_GETSCHEDULER = 120 - SYS_SCHED_GETPARAM = 121 - SYS_SCHED_SETAFFINITY = 122 - SYS_SCHED_GETAFFINITY = 123 - SYS_SCHED_YIELD = 124 - SYS_SCHED_GET_PRIORITY_MAX = 125 - SYS_SCHED_GET_PRIORITY_MIN = 126 - SYS_SCHED_RR_GET_INTERVAL = 127 - SYS_RESTART_SYSCALL = 128 - SYS_KILL = 129 - SYS_TKILL = 130 - SYS_TGKILL = 131 - SYS_SIGALTSTACK = 132 - SYS_RT_SIGSUSPEND = 133 - SYS_RT_SIGACTION = 134 - SYS_RT_SIGPROCMASK = 135 - SYS_RT_SIGPENDING = 136 - SYS_RT_SIGTIMEDWAIT = 137 - SYS_RT_SIGQUEUEINFO = 138 - SYS_RT_SIGRETURN = 139 - SYS_SETPRIORITY = 140 - SYS_GETPRIORITY = 141 - SYS_REBOOT = 142 - SYS_SETREGID = 143 - SYS_SETGID = 144 - SYS_SETREUID = 145 - SYS_SETUID = 146 - SYS_SETRESUID = 147 - SYS_GETRESUID = 148 - SYS_SETRESGID = 149 - SYS_GETRESGID = 150 - SYS_SETFSUID = 151 - SYS_SETFSGID = 152 - SYS_TIMES = 153 - SYS_SETPGID = 154 - SYS_GETPGID = 155 - SYS_GETSID = 156 - SYS_SETSID = 157 - SYS_GETGROUPS = 158 - SYS_SETGROUPS = 159 - SYS_UNAME = 160 - SYS_SETHOSTNAME = 161 - SYS_SETDOMAINNAME = 162 - SYS_GETRLIMIT = 163 - SYS_SETRLIMIT = 164 - SYS_GETRUSAGE = 165 - SYS_UMASK = 166 - SYS_PRCTL = 167 - SYS_GETCPU = 168 - SYS_GETTIMEOFDAY = 169 - SYS_SETTIMEOFDAY = 170 - SYS_ADJTIMEX = 171 - SYS_GETPID = 172 - SYS_GETPPID = 173 - SYS_GETUID = 174 - SYS_GETEUID = 175 - SYS_GETGID = 176 - SYS_GETEGID = 177 - SYS_GETTID = 178 - SYS_SYSINFO = 179 - SYS_MQ_OPEN = 180 - SYS_MQ_UNLINK = 181 - SYS_MQ_TIMEDSEND = 182 - SYS_MQ_TIMEDRECEIVE = 183 - SYS_MQ_NOTIFY = 184 - SYS_MQ_GETSETATTR = 185 - SYS_MSGGET = 186 - SYS_MSGCTL = 187 - SYS_MSGRCV = 188 - SYS_MSGSND = 189 - SYS_SEMGET = 190 - SYS_SEMCTL = 191 - SYS_SEMTIMEDOP = 192 - SYS_SEMOP = 193 - SYS_SHMGET = 194 - SYS_SHMCTL = 195 - SYS_SHMAT = 196 - SYS_SHMDT = 197 - SYS_SOCKET = 198 - SYS_SOCKETPAIR = 199 - SYS_BIND = 200 - SYS_LISTEN = 201 - SYS_ACCEPT = 202 - SYS_CONNECT = 203 - SYS_GETSOCKNAME = 204 - SYS_GETPEERNAME = 205 - SYS_SENDTO = 206 - SYS_RECVFROM = 207 - SYS_SETSOCKOPT = 208 - SYS_GETSOCKOPT = 209 - SYS_SHUTDOWN = 210 - SYS_SENDMSG = 211 - SYS_RECVMSG = 212 - SYS_READAHEAD = 213 - SYS_BRK = 214 - SYS_MUNMAP = 215 - SYS_MREMAP = 216 - SYS_ADD_KEY = 217 - SYS_REQUEST_KEY = 218 - SYS_KEYCTL = 219 - SYS_CLONE = 220 - SYS_EXECVE = 221 - SYS_MMAP = 222 - SYS_FADVISE64 = 223 - SYS_SWAPON = 224 - SYS_SWAPOFF = 225 - SYS_MPROTECT = 226 - SYS_MSYNC = 227 - SYS_MLOCK = 228 - SYS_MUNLOCK = 229 - SYS_MLOCKALL = 230 - SYS_MUNLOCKALL = 231 - SYS_MINCORE = 232 - SYS_MADVISE = 233 - SYS_REMAP_FILE_PAGES = 234 - SYS_MBIND = 235 - SYS_GET_MEMPOLICY = 236 - SYS_SET_MEMPOLICY = 237 - SYS_MIGRATE_PAGES = 238 - SYS_MOVE_PAGES = 239 - SYS_RT_TGSIGQUEUEINFO = 240 - SYS_PERF_EVENT_OPEN = 241 - SYS_ACCEPT4 = 242 - SYS_RECVMMSG = 243 - SYS_ARCH_SPECIFIC_SYSCALL = 244 - SYS_WAIT4 = 260 - SYS_PRLIMIT64 = 261 - SYS_FANOTIFY_INIT = 262 - SYS_FANOTIFY_MARK = 263 - SYS_NAME_TO_HANDLE_AT = 264 - SYS_OPEN_BY_HANDLE_AT = 265 - SYS_CLOCK_ADJTIME = 266 - SYS_SYNCFS = 267 - SYS_SETNS = 268 - SYS_SENDMMSG = 269 - SYS_PROCESS_VM_READV = 270 - SYS_PROCESS_VM_WRITEV = 271 - SYS_KCMP = 272 - SYS_FINIT_MODULE = 273 - SYS_SCHED_SETATTR = 274 - SYS_SCHED_GETATTR = 275 - SYS_RENAMEAT2 = 276 - SYS_SECCOMP = 277 - SYS_GETRANDOM = 278 - SYS_MEMFD_CREATE = 279 - SYS_BPF = 280 - SYS_EXECVEAT = 281 - SYS_USERFAULTFD = 282 - SYS_MEMBARRIER = 283 - SYS_MLOCK2 = 284 - SYS_COPY_FILE_RANGE = 285 - SYS_PREADV2 = 286 - SYS_PWRITEV2 = 287 - SYS_PKEY_MPROTECT = 288 - SYS_PKEY_ALLOC = 289 - SYS_PKEY_FREE = 290 - SYS_STATX = 291 - SYS_IO_PGETEVENTS = 292 - SYS_RSEQ = 293 - SYS_KEXEC_FILE_LOAD = 294 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 + SYS_IO_SETUP = 0 + SYS_IO_DESTROY = 1 + SYS_IO_SUBMIT = 2 + SYS_IO_CANCEL = 3 + SYS_IO_GETEVENTS = 4 + SYS_SETXATTR = 5 + SYS_LSETXATTR = 6 + SYS_FSETXATTR = 7 + SYS_GETXATTR = 8 + SYS_LGETXATTR = 9 + SYS_FGETXATTR = 10 + SYS_LISTXATTR = 11 + SYS_LLISTXATTR = 12 + SYS_FLISTXATTR = 13 + SYS_REMOVEXATTR = 14 + SYS_LREMOVEXATTR = 15 + SYS_FREMOVEXATTR = 16 + SYS_GETCWD = 17 + SYS_LOOKUP_DCOOKIE = 18 + SYS_EVENTFD2 = 19 + SYS_EPOLL_CREATE1 = 20 + SYS_EPOLL_CTL = 21 + SYS_EPOLL_PWAIT = 22 + SYS_DUP = 23 + SYS_DUP3 = 24 + SYS_FCNTL = 25 + SYS_INOTIFY_INIT1 = 26 + SYS_INOTIFY_ADD_WATCH = 27 + SYS_INOTIFY_RM_WATCH = 28 + SYS_IOCTL = 29 + SYS_IOPRIO_SET = 30 + SYS_IOPRIO_GET = 31 + SYS_FLOCK = 32 + SYS_MKNODAT = 33 + SYS_MKDIRAT = 34 + SYS_UNLINKAT = 35 + SYS_SYMLINKAT = 36 + SYS_LINKAT = 37 + SYS_RENAMEAT = 38 + SYS_UMOUNT2 = 39 + SYS_MOUNT = 40 + SYS_PIVOT_ROOT = 41 + SYS_NFSSERVCTL = 42 + SYS_STATFS = 43 + SYS_FSTATFS = 44 + SYS_TRUNCATE = 45 + SYS_FTRUNCATE = 46 + SYS_FALLOCATE = 47 + SYS_FACCESSAT = 48 + SYS_CHDIR = 49 + SYS_FCHDIR = 50 + SYS_CHROOT = 51 + SYS_FCHMOD = 52 + SYS_FCHMODAT = 53 + SYS_FCHOWNAT = 54 + SYS_FCHOWN = 55 + SYS_OPENAT = 56 + SYS_CLOSE = 57 + SYS_VHANGUP = 58 + SYS_PIPE2 = 59 + SYS_QUOTACTL = 60 + SYS_GETDENTS64 = 61 + SYS_LSEEK = 62 + SYS_READ = 63 + SYS_WRITE = 64 + SYS_READV = 65 + SYS_WRITEV = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_PREADV = 69 + SYS_PWRITEV = 70 + SYS_SENDFILE = 71 + SYS_PSELECT6 = 72 + SYS_PPOLL = 73 + SYS_SIGNALFD4 = 74 + SYS_VMSPLICE = 75 + SYS_SPLICE = 76 + SYS_TEE = 77 + SYS_READLINKAT = 78 + SYS_NEWFSTATAT = 79 + SYS_FSTAT = 80 + SYS_SYNC = 81 + SYS_FSYNC = 82 + SYS_FDATASYNC = 83 + SYS_SYNC_FILE_RANGE = 84 + SYS_TIMERFD_CREATE = 85 + SYS_TIMERFD_SETTIME = 86 + SYS_TIMERFD_GETTIME = 87 + SYS_UTIMENSAT = 88 + SYS_ACCT = 89 + SYS_CAPGET = 90 + SYS_CAPSET = 91 + SYS_PERSONALITY = 92 + SYS_EXIT = 93 + SYS_EXIT_GROUP = 94 + SYS_WAITID = 95 + SYS_SET_TID_ADDRESS = 96 + SYS_UNSHARE = 97 + SYS_FUTEX = 98 + SYS_SET_ROBUST_LIST = 99 + SYS_GET_ROBUST_LIST = 100 + SYS_NANOSLEEP = 101 + SYS_GETITIMER = 102 + SYS_SETITIMER = 103 + SYS_KEXEC_LOAD = 104 + SYS_INIT_MODULE = 105 + SYS_DELETE_MODULE = 106 + SYS_TIMER_CREATE = 107 + SYS_TIMER_GETTIME = 108 + SYS_TIMER_GETOVERRUN = 109 + SYS_TIMER_SETTIME = 110 + SYS_TIMER_DELETE = 111 + SYS_CLOCK_SETTIME = 112 + SYS_CLOCK_GETTIME = 113 + SYS_CLOCK_GETRES = 114 + SYS_CLOCK_NANOSLEEP = 115 + SYS_SYSLOG = 116 + SYS_PTRACE = 117 + SYS_SCHED_SETPARAM = 118 + SYS_SCHED_SETSCHEDULER = 119 + SYS_SCHED_GETSCHEDULER = 120 + SYS_SCHED_GETPARAM = 121 + SYS_SCHED_SETAFFINITY = 122 + SYS_SCHED_GETAFFINITY = 123 + SYS_SCHED_YIELD = 124 + SYS_SCHED_GET_PRIORITY_MAX = 125 + SYS_SCHED_GET_PRIORITY_MIN = 126 + SYS_SCHED_RR_GET_INTERVAL = 127 + SYS_RESTART_SYSCALL = 128 + SYS_KILL = 129 + SYS_TKILL = 130 + SYS_TGKILL = 131 + SYS_SIGALTSTACK = 132 + SYS_RT_SIGSUSPEND = 133 + SYS_RT_SIGACTION = 134 + SYS_RT_SIGPROCMASK = 135 + SYS_RT_SIGPENDING = 136 + SYS_RT_SIGTIMEDWAIT = 137 + SYS_RT_SIGQUEUEINFO = 138 + SYS_RT_SIGRETURN = 139 + SYS_SETPRIORITY = 140 + SYS_GETPRIORITY = 141 + SYS_REBOOT = 142 + SYS_SETREGID = 143 + SYS_SETGID = 144 + SYS_SETREUID = 145 + SYS_SETUID = 146 + SYS_SETRESUID = 147 + SYS_GETRESUID = 148 + SYS_SETRESGID = 149 + SYS_GETRESGID = 150 + SYS_SETFSUID = 151 + SYS_SETFSGID = 152 + SYS_TIMES = 153 + SYS_SETPGID = 154 + SYS_GETPGID = 155 + SYS_GETSID = 156 + SYS_SETSID = 157 + SYS_GETGROUPS = 158 + SYS_SETGROUPS = 159 + SYS_UNAME = 160 + SYS_SETHOSTNAME = 161 + SYS_SETDOMAINNAME = 162 + SYS_GETRLIMIT = 163 + SYS_SETRLIMIT = 164 + SYS_GETRUSAGE = 165 + SYS_UMASK = 166 + SYS_PRCTL = 167 + SYS_GETCPU = 168 + SYS_GETTIMEOFDAY = 169 + SYS_SETTIMEOFDAY = 170 + SYS_ADJTIMEX = 171 + SYS_GETPID = 172 + SYS_GETPPID = 173 + SYS_GETUID = 174 + SYS_GETEUID = 175 + SYS_GETGID = 176 + SYS_GETEGID = 177 + SYS_GETTID = 178 + SYS_SYSINFO = 179 + SYS_MQ_OPEN = 180 + SYS_MQ_UNLINK = 181 + SYS_MQ_TIMEDSEND = 182 + SYS_MQ_TIMEDRECEIVE = 183 + SYS_MQ_NOTIFY = 184 + SYS_MQ_GETSETATTR = 185 + SYS_MSGGET = 186 + SYS_MSGCTL = 187 + SYS_MSGRCV = 188 + SYS_MSGSND = 189 + SYS_SEMGET = 190 + SYS_SEMCTL = 191 + SYS_SEMTIMEDOP = 192 + SYS_SEMOP = 193 + SYS_SHMGET = 194 + SYS_SHMCTL = 195 + SYS_SHMAT = 196 + SYS_SHMDT = 197 + SYS_SOCKET = 198 + SYS_SOCKETPAIR = 199 + SYS_BIND = 200 + SYS_LISTEN = 201 + SYS_ACCEPT = 202 + SYS_CONNECT = 203 + SYS_GETSOCKNAME = 204 + SYS_GETPEERNAME = 205 + SYS_SENDTO = 206 + SYS_RECVFROM = 207 + SYS_SETSOCKOPT = 208 + SYS_GETSOCKOPT = 209 + SYS_SHUTDOWN = 210 + SYS_SENDMSG = 211 + SYS_RECVMSG = 212 + SYS_READAHEAD = 213 + SYS_BRK = 214 + SYS_MUNMAP = 215 + SYS_MREMAP = 216 + SYS_ADD_KEY = 217 + SYS_REQUEST_KEY = 218 + SYS_KEYCTL = 219 + SYS_CLONE = 220 + SYS_EXECVE = 221 + SYS_MMAP = 222 + SYS_FADVISE64 = 223 + SYS_SWAPON = 224 + SYS_SWAPOFF = 225 + SYS_MPROTECT = 226 + SYS_MSYNC = 227 + SYS_MLOCK = 228 + SYS_MUNLOCK = 229 + SYS_MLOCKALL = 230 + SYS_MUNLOCKALL = 231 + SYS_MINCORE = 232 + SYS_MADVISE = 233 + SYS_REMAP_FILE_PAGES = 234 + SYS_MBIND = 235 + SYS_GET_MEMPOLICY = 236 + SYS_SET_MEMPOLICY = 237 + SYS_MIGRATE_PAGES = 238 + SYS_MOVE_PAGES = 239 + SYS_RT_TGSIGQUEUEINFO = 240 + SYS_PERF_EVENT_OPEN = 241 + SYS_ACCEPT4 = 242 + SYS_RECVMMSG = 243 + SYS_ARCH_SPECIFIC_SYSCALL = 244 + SYS_WAIT4 = 260 + SYS_PRLIMIT64 = 261 + SYS_FANOTIFY_INIT = 262 + SYS_FANOTIFY_MARK = 263 + SYS_NAME_TO_HANDLE_AT = 264 + SYS_OPEN_BY_HANDLE_AT = 265 + SYS_CLOCK_ADJTIME = 266 + SYS_SYNCFS = 267 + SYS_SETNS = 268 + SYS_SENDMMSG = 269 + SYS_PROCESS_VM_READV = 270 + SYS_PROCESS_VM_WRITEV = 271 + SYS_KCMP = 272 + SYS_FINIT_MODULE = 273 + SYS_SCHED_SETATTR = 274 + SYS_SCHED_GETATTR = 275 + SYS_RENAMEAT2 = 276 + SYS_SECCOMP = 277 + SYS_GETRANDOM = 278 + SYS_MEMFD_CREATE = 279 + SYS_BPF = 280 + SYS_EXECVEAT = 281 + SYS_USERFAULTFD = 282 + SYS_MEMBARRIER = 283 + SYS_MLOCK2 = 284 + SYS_COPY_FILE_RANGE = 285 + SYS_PREADV2 = 286 + SYS_PWRITEV2 = 287 + SYS_PKEY_MPROTECT = 288 + SYS_PKEY_ALLOC = 289 + SYS_PKEY_FREE = 290 + SYS_STATX = 291 + SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 + SYS_KEXEC_FILE_LOAD = 294 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go new file mode 100644 index 0000000..f9f03eb --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -0,0 +1,329 @@ +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/loong64/include /tmp/loong64/include/asm/unistd.h +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build loong64 && linux + +package unix + +const ( + SYS_IO_SETUP = 0 + SYS_IO_DESTROY = 1 + SYS_IO_SUBMIT = 2 + SYS_IO_CANCEL = 3 + SYS_IO_GETEVENTS = 4 + SYS_SETXATTR = 5 + SYS_LSETXATTR = 6 + SYS_FSETXATTR = 7 + SYS_GETXATTR = 8 + SYS_LGETXATTR = 9 + SYS_FGETXATTR = 10 + SYS_LISTXATTR = 11 + SYS_LLISTXATTR = 12 + SYS_FLISTXATTR = 13 + SYS_REMOVEXATTR = 14 + SYS_LREMOVEXATTR = 15 + SYS_FREMOVEXATTR = 16 + SYS_GETCWD = 17 + SYS_LOOKUP_DCOOKIE = 18 + SYS_EVENTFD2 = 19 + SYS_EPOLL_CREATE1 = 20 + SYS_EPOLL_CTL = 21 + SYS_EPOLL_PWAIT = 22 + SYS_DUP = 23 + SYS_DUP3 = 24 + SYS_FCNTL = 25 + SYS_INOTIFY_INIT1 = 26 + SYS_INOTIFY_ADD_WATCH = 27 + SYS_INOTIFY_RM_WATCH = 28 + SYS_IOCTL = 29 + SYS_IOPRIO_SET = 30 + SYS_IOPRIO_GET = 31 + SYS_FLOCK = 32 + SYS_MKNODAT = 33 + SYS_MKDIRAT = 34 + SYS_UNLINKAT = 35 + SYS_SYMLINKAT = 36 + SYS_LINKAT = 37 + SYS_UMOUNT2 = 39 + SYS_MOUNT = 40 + SYS_PIVOT_ROOT = 41 + SYS_NFSSERVCTL = 42 + SYS_STATFS = 43 + SYS_FSTATFS = 44 + SYS_TRUNCATE = 45 + SYS_FTRUNCATE = 46 + SYS_FALLOCATE = 47 + SYS_FACCESSAT = 48 + SYS_CHDIR = 49 + SYS_FCHDIR = 50 + SYS_CHROOT = 51 + SYS_FCHMOD = 52 + SYS_FCHMODAT = 53 + SYS_FCHOWNAT = 54 + SYS_FCHOWN = 55 + SYS_OPENAT = 56 + SYS_CLOSE = 57 + SYS_VHANGUP = 58 + SYS_PIPE2 = 59 + SYS_QUOTACTL = 60 + SYS_GETDENTS64 = 61 + SYS_LSEEK = 62 + SYS_READ = 63 + SYS_WRITE = 64 + SYS_READV = 65 + SYS_WRITEV = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_PREADV = 69 + SYS_PWRITEV = 70 + SYS_SENDFILE = 71 + SYS_PSELECT6 = 72 + SYS_PPOLL = 73 + SYS_SIGNALFD4 = 74 + SYS_VMSPLICE = 75 + SYS_SPLICE = 76 + SYS_TEE = 77 + SYS_READLINKAT = 78 + SYS_NEWFSTATAT = 79 + SYS_FSTAT = 80 + SYS_SYNC = 81 + SYS_FSYNC = 82 + SYS_FDATASYNC = 83 + SYS_SYNC_FILE_RANGE = 84 + SYS_TIMERFD_CREATE = 85 + SYS_TIMERFD_SETTIME = 86 + SYS_TIMERFD_GETTIME = 87 + SYS_UTIMENSAT = 88 + SYS_ACCT = 89 + SYS_CAPGET = 90 + SYS_CAPSET = 91 + SYS_PERSONALITY = 92 + SYS_EXIT = 93 + SYS_EXIT_GROUP = 94 + SYS_WAITID = 95 + SYS_SET_TID_ADDRESS = 96 + SYS_UNSHARE = 97 + SYS_FUTEX = 98 + SYS_SET_ROBUST_LIST = 99 + SYS_GET_ROBUST_LIST = 100 + SYS_NANOSLEEP = 101 + SYS_GETITIMER = 102 + SYS_SETITIMER = 103 + SYS_KEXEC_LOAD = 104 + SYS_INIT_MODULE = 105 + SYS_DELETE_MODULE = 106 + SYS_TIMER_CREATE = 107 + SYS_TIMER_GETTIME = 108 + SYS_TIMER_GETOVERRUN = 109 + SYS_TIMER_SETTIME = 110 + SYS_TIMER_DELETE = 111 + SYS_CLOCK_SETTIME = 112 + SYS_CLOCK_GETTIME = 113 + SYS_CLOCK_GETRES = 114 + SYS_CLOCK_NANOSLEEP = 115 + SYS_SYSLOG = 116 + SYS_PTRACE = 117 + SYS_SCHED_SETPARAM = 118 + SYS_SCHED_SETSCHEDULER = 119 + SYS_SCHED_GETSCHEDULER = 120 + SYS_SCHED_GETPARAM = 121 + SYS_SCHED_SETAFFINITY = 122 + SYS_SCHED_GETAFFINITY = 123 + SYS_SCHED_YIELD = 124 + SYS_SCHED_GET_PRIORITY_MAX = 125 + SYS_SCHED_GET_PRIORITY_MIN = 126 + SYS_SCHED_RR_GET_INTERVAL = 127 + SYS_RESTART_SYSCALL = 128 + SYS_KILL = 129 + SYS_TKILL = 130 + SYS_TGKILL = 131 + SYS_SIGALTSTACK = 132 + SYS_RT_SIGSUSPEND = 133 + SYS_RT_SIGACTION = 134 + SYS_RT_SIGPROCMASK = 135 + SYS_RT_SIGPENDING = 136 + SYS_RT_SIGTIMEDWAIT = 137 + SYS_RT_SIGQUEUEINFO = 138 + SYS_RT_SIGRETURN = 139 + SYS_SETPRIORITY = 140 + SYS_GETPRIORITY = 141 + SYS_REBOOT = 142 + SYS_SETREGID = 143 + SYS_SETGID = 144 + SYS_SETREUID = 145 + SYS_SETUID = 146 + SYS_SETRESUID = 147 + SYS_GETRESUID = 148 + SYS_SETRESGID = 149 + SYS_GETRESGID = 150 + SYS_SETFSUID = 151 + SYS_SETFSGID = 152 + SYS_TIMES = 153 + SYS_SETPGID = 154 + SYS_GETPGID = 155 + SYS_GETSID = 156 + SYS_SETSID = 157 + SYS_GETGROUPS = 158 + SYS_SETGROUPS = 159 + SYS_UNAME = 160 + SYS_SETHOSTNAME = 161 + SYS_SETDOMAINNAME = 162 + SYS_GETRUSAGE = 165 + SYS_UMASK = 166 + SYS_PRCTL = 167 + SYS_GETCPU = 168 + SYS_GETTIMEOFDAY = 169 + SYS_SETTIMEOFDAY = 170 + SYS_ADJTIMEX = 171 + SYS_GETPID = 172 + SYS_GETPPID = 173 + SYS_GETUID = 174 + SYS_GETEUID = 175 + SYS_GETGID = 176 + SYS_GETEGID = 177 + SYS_GETTID = 178 + SYS_SYSINFO = 179 + SYS_MQ_OPEN = 180 + SYS_MQ_UNLINK = 181 + SYS_MQ_TIMEDSEND = 182 + SYS_MQ_TIMEDRECEIVE = 183 + SYS_MQ_NOTIFY = 184 + SYS_MQ_GETSETATTR = 185 + SYS_MSGGET = 186 + SYS_MSGCTL = 187 + SYS_MSGRCV = 188 + SYS_MSGSND = 189 + SYS_SEMGET = 190 + SYS_SEMCTL = 191 + SYS_SEMTIMEDOP = 192 + SYS_SEMOP = 193 + SYS_SHMGET = 194 + SYS_SHMCTL = 195 + SYS_SHMAT = 196 + SYS_SHMDT = 197 + SYS_SOCKET = 198 + SYS_SOCKETPAIR = 199 + SYS_BIND = 200 + SYS_LISTEN = 201 + SYS_ACCEPT = 202 + SYS_CONNECT = 203 + SYS_GETSOCKNAME = 204 + SYS_GETPEERNAME = 205 + SYS_SENDTO = 206 + SYS_RECVFROM = 207 + SYS_SETSOCKOPT = 208 + SYS_GETSOCKOPT = 209 + SYS_SHUTDOWN = 210 + SYS_SENDMSG = 211 + SYS_RECVMSG = 212 + SYS_READAHEAD = 213 + SYS_BRK = 214 + SYS_MUNMAP = 215 + SYS_MREMAP = 216 + SYS_ADD_KEY = 217 + SYS_REQUEST_KEY = 218 + SYS_KEYCTL = 219 + SYS_CLONE = 220 + SYS_EXECVE = 221 + SYS_MMAP = 222 + SYS_FADVISE64 = 223 + SYS_SWAPON = 224 + SYS_SWAPOFF = 225 + SYS_MPROTECT = 226 + SYS_MSYNC = 227 + SYS_MLOCK = 228 + SYS_MUNLOCK = 229 + SYS_MLOCKALL = 230 + SYS_MUNLOCKALL = 231 + SYS_MINCORE = 232 + SYS_MADVISE = 233 + SYS_REMAP_FILE_PAGES = 234 + SYS_MBIND = 235 + SYS_GET_MEMPOLICY = 236 + SYS_SET_MEMPOLICY = 237 + SYS_MIGRATE_PAGES = 238 + SYS_MOVE_PAGES = 239 + SYS_RT_TGSIGQUEUEINFO = 240 + SYS_PERF_EVENT_OPEN = 241 + SYS_ACCEPT4 = 242 + SYS_RECVMMSG = 243 + SYS_ARCH_SPECIFIC_SYSCALL = 244 + SYS_WAIT4 = 260 + SYS_PRLIMIT64 = 261 + SYS_FANOTIFY_INIT = 262 + SYS_FANOTIFY_MARK = 263 + SYS_NAME_TO_HANDLE_AT = 264 + SYS_OPEN_BY_HANDLE_AT = 265 + SYS_CLOCK_ADJTIME = 266 + SYS_SYNCFS = 267 + SYS_SETNS = 268 + SYS_SENDMMSG = 269 + SYS_PROCESS_VM_READV = 270 + SYS_PROCESS_VM_WRITEV = 271 + SYS_KCMP = 272 + SYS_FINIT_MODULE = 273 + SYS_SCHED_SETATTR = 274 + SYS_SCHED_GETATTR = 275 + SYS_RENAMEAT2 = 276 + SYS_SECCOMP = 277 + SYS_GETRANDOM = 278 + SYS_MEMFD_CREATE = 279 + SYS_BPF = 280 + SYS_EXECVEAT = 281 + SYS_USERFAULTFD = 282 + SYS_MEMBARRIER = 283 + SYS_MLOCK2 = 284 + SYS_COPY_FILE_RANGE = 285 + SYS_PREADV2 = 286 + SYS_PWRITEV2 = 287 + SYS_PKEY_MPROTECT = 288 + SYS_PKEY_ALLOC = 289 + SYS_PKEY_FREE = 290 + SYS_STATX = 291 + SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 + SYS_KEXEC_FILE_LOAD = 294 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 00da3de..87c2118 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -1,7 +1,7 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/mips/include /tmp/mips/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips,linux +//go:build mips && linux package unix @@ -416,4 +416,35 @@ const ( SYS_FSPICK = 4433 SYS_PIDFD_OPEN = 4434 SYS_CLONE3 = 4435 + SYS_CLOSE_RANGE = 4436 + SYS_OPENAT2 = 4437 + SYS_PIDFD_GETFD = 4438 + SYS_FACCESSAT2 = 4439 + SYS_PROCESS_MADVISE = 4440 + SYS_EPOLL_PWAIT2 = 4441 + SYS_MOUNT_SETATTR = 4442 + SYS_QUOTACTL_FD = 4443 + SYS_LANDLOCK_CREATE_RULESET = 4444 + SYS_LANDLOCK_ADD_RULE = 4445 + SYS_LANDLOCK_RESTRICT_SELF = 4446 + SYS_PROCESS_MRELEASE = 4448 + SYS_FUTEX_WAITV = 4449 + SYS_SET_MEMPOLICY_HOME_NODE = 4450 + SYS_CACHESTAT = 4451 + SYS_FCHMODAT2 = 4452 + SYS_MAP_SHADOW_STACK = 4453 + SYS_FUTEX_WAKE = 4454 + SYS_FUTEX_WAIT = 4455 + SYS_FUTEX_REQUEUE = 4456 + SYS_STATMOUNT = 4457 + SYS_LISTMOUNT = 4458 + SYS_LSM_GET_SELF_ATTR = 4459 + SYS_LSM_SET_SELF_ATTR = 4460 + SYS_LSM_LIST_MODULES = 4461 + SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index d404fbd..391ad10 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -1,349 +1,380 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/mips64/include /tmp/mips64/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips64,linux +//go:build mips64 && linux package unix const ( - SYS_READ = 5000 - SYS_WRITE = 5001 - SYS_OPEN = 5002 - SYS_CLOSE = 5003 - SYS_STAT = 5004 - SYS_FSTAT = 5005 - SYS_LSTAT = 5006 - SYS_POLL = 5007 - SYS_LSEEK = 5008 - SYS_MMAP = 5009 - SYS_MPROTECT = 5010 - SYS_MUNMAP = 5011 - SYS_BRK = 5012 - SYS_RT_SIGACTION = 5013 - SYS_RT_SIGPROCMASK = 5014 - SYS_IOCTL = 5015 - SYS_PREAD64 = 5016 - SYS_PWRITE64 = 5017 - SYS_READV = 5018 - SYS_WRITEV = 5019 - SYS_ACCESS = 5020 - SYS_PIPE = 5021 - SYS__NEWSELECT = 5022 - SYS_SCHED_YIELD = 5023 - SYS_MREMAP = 5024 - SYS_MSYNC = 5025 - SYS_MINCORE = 5026 - SYS_MADVISE = 5027 - SYS_SHMGET = 5028 - SYS_SHMAT = 5029 - SYS_SHMCTL = 5030 - SYS_DUP = 5031 - SYS_DUP2 = 5032 - SYS_PAUSE = 5033 - SYS_NANOSLEEP = 5034 - SYS_GETITIMER = 5035 - SYS_SETITIMER = 5036 - SYS_ALARM = 5037 - SYS_GETPID = 5038 - SYS_SENDFILE = 5039 - SYS_SOCKET = 5040 - SYS_CONNECT = 5041 - SYS_ACCEPT = 5042 - SYS_SENDTO = 5043 - SYS_RECVFROM = 5044 - SYS_SENDMSG = 5045 - SYS_RECVMSG = 5046 - SYS_SHUTDOWN = 5047 - SYS_BIND = 5048 - SYS_LISTEN = 5049 - SYS_GETSOCKNAME = 5050 - SYS_GETPEERNAME = 5051 - SYS_SOCKETPAIR = 5052 - SYS_SETSOCKOPT = 5053 - SYS_GETSOCKOPT = 5054 - SYS_CLONE = 5055 - SYS_FORK = 5056 - SYS_EXECVE = 5057 - SYS_EXIT = 5058 - SYS_WAIT4 = 5059 - SYS_KILL = 5060 - SYS_UNAME = 5061 - SYS_SEMGET = 5062 - SYS_SEMOP = 5063 - SYS_SEMCTL = 5064 - SYS_SHMDT = 5065 - SYS_MSGGET = 5066 - SYS_MSGSND = 5067 - SYS_MSGRCV = 5068 - SYS_MSGCTL = 5069 - SYS_FCNTL = 5070 - SYS_FLOCK = 5071 - SYS_FSYNC = 5072 - SYS_FDATASYNC = 5073 - SYS_TRUNCATE = 5074 - SYS_FTRUNCATE = 5075 - SYS_GETDENTS = 5076 - SYS_GETCWD = 5077 - SYS_CHDIR = 5078 - SYS_FCHDIR = 5079 - SYS_RENAME = 5080 - SYS_MKDIR = 5081 - SYS_RMDIR = 5082 - SYS_CREAT = 5083 - SYS_LINK = 5084 - SYS_UNLINK = 5085 - SYS_SYMLINK = 5086 - SYS_READLINK = 5087 - SYS_CHMOD = 5088 - SYS_FCHMOD = 5089 - SYS_CHOWN = 5090 - SYS_FCHOWN = 5091 - SYS_LCHOWN = 5092 - SYS_UMASK = 5093 - SYS_GETTIMEOFDAY = 5094 - SYS_GETRLIMIT = 5095 - SYS_GETRUSAGE = 5096 - SYS_SYSINFO = 5097 - SYS_TIMES = 5098 - SYS_PTRACE = 5099 - SYS_GETUID = 5100 - SYS_SYSLOG = 5101 - SYS_GETGID = 5102 - SYS_SETUID = 5103 - SYS_SETGID = 5104 - SYS_GETEUID = 5105 - SYS_GETEGID = 5106 - SYS_SETPGID = 5107 - SYS_GETPPID = 5108 - SYS_GETPGRP = 5109 - SYS_SETSID = 5110 - SYS_SETREUID = 5111 - SYS_SETREGID = 5112 - SYS_GETGROUPS = 5113 - SYS_SETGROUPS = 5114 - SYS_SETRESUID = 5115 - SYS_GETRESUID = 5116 - SYS_SETRESGID = 5117 - SYS_GETRESGID = 5118 - SYS_GETPGID = 5119 - SYS_SETFSUID = 5120 - SYS_SETFSGID = 5121 - SYS_GETSID = 5122 - SYS_CAPGET = 5123 - SYS_CAPSET = 5124 - SYS_RT_SIGPENDING = 5125 - SYS_RT_SIGTIMEDWAIT = 5126 - SYS_RT_SIGQUEUEINFO = 5127 - SYS_RT_SIGSUSPEND = 5128 - SYS_SIGALTSTACK = 5129 - SYS_UTIME = 5130 - SYS_MKNOD = 5131 - SYS_PERSONALITY = 5132 - SYS_USTAT = 5133 - SYS_STATFS = 5134 - SYS_FSTATFS = 5135 - SYS_SYSFS = 5136 - SYS_GETPRIORITY = 5137 - SYS_SETPRIORITY = 5138 - SYS_SCHED_SETPARAM = 5139 - SYS_SCHED_GETPARAM = 5140 - SYS_SCHED_SETSCHEDULER = 5141 - SYS_SCHED_GETSCHEDULER = 5142 - SYS_SCHED_GET_PRIORITY_MAX = 5143 - SYS_SCHED_GET_PRIORITY_MIN = 5144 - SYS_SCHED_RR_GET_INTERVAL = 5145 - SYS_MLOCK = 5146 - SYS_MUNLOCK = 5147 - SYS_MLOCKALL = 5148 - SYS_MUNLOCKALL = 5149 - SYS_VHANGUP = 5150 - SYS_PIVOT_ROOT = 5151 - SYS__SYSCTL = 5152 - SYS_PRCTL = 5153 - SYS_ADJTIMEX = 5154 - SYS_SETRLIMIT = 5155 - SYS_CHROOT = 5156 - SYS_SYNC = 5157 - SYS_ACCT = 5158 - SYS_SETTIMEOFDAY = 5159 - SYS_MOUNT = 5160 - SYS_UMOUNT2 = 5161 - SYS_SWAPON = 5162 - SYS_SWAPOFF = 5163 - SYS_REBOOT = 5164 - SYS_SETHOSTNAME = 5165 - SYS_SETDOMAINNAME = 5166 - SYS_CREATE_MODULE = 5167 - SYS_INIT_MODULE = 5168 - SYS_DELETE_MODULE = 5169 - SYS_GET_KERNEL_SYMS = 5170 - SYS_QUERY_MODULE = 5171 - SYS_QUOTACTL = 5172 - SYS_NFSSERVCTL = 5173 - SYS_GETPMSG = 5174 - SYS_PUTPMSG = 5175 - SYS_AFS_SYSCALL = 5176 - SYS_RESERVED177 = 5177 - SYS_GETTID = 5178 - SYS_READAHEAD = 5179 - SYS_SETXATTR = 5180 - SYS_LSETXATTR = 5181 - SYS_FSETXATTR = 5182 - SYS_GETXATTR = 5183 - SYS_LGETXATTR = 5184 - SYS_FGETXATTR = 5185 - SYS_LISTXATTR = 5186 - SYS_LLISTXATTR = 5187 - SYS_FLISTXATTR = 5188 - SYS_REMOVEXATTR = 5189 - SYS_LREMOVEXATTR = 5190 - SYS_FREMOVEXATTR = 5191 - SYS_TKILL = 5192 - SYS_RESERVED193 = 5193 - SYS_FUTEX = 5194 - SYS_SCHED_SETAFFINITY = 5195 - SYS_SCHED_GETAFFINITY = 5196 - SYS_CACHEFLUSH = 5197 - SYS_CACHECTL = 5198 - SYS_SYSMIPS = 5199 - SYS_IO_SETUP = 5200 - SYS_IO_DESTROY = 5201 - SYS_IO_GETEVENTS = 5202 - SYS_IO_SUBMIT = 5203 - SYS_IO_CANCEL = 5204 - SYS_EXIT_GROUP = 5205 - SYS_LOOKUP_DCOOKIE = 5206 - SYS_EPOLL_CREATE = 5207 - SYS_EPOLL_CTL = 5208 - SYS_EPOLL_WAIT = 5209 - SYS_REMAP_FILE_PAGES = 5210 - SYS_RT_SIGRETURN = 5211 - SYS_SET_TID_ADDRESS = 5212 - SYS_RESTART_SYSCALL = 5213 - SYS_SEMTIMEDOP = 5214 - SYS_FADVISE64 = 5215 - SYS_TIMER_CREATE = 5216 - SYS_TIMER_SETTIME = 5217 - SYS_TIMER_GETTIME = 5218 - SYS_TIMER_GETOVERRUN = 5219 - SYS_TIMER_DELETE = 5220 - SYS_CLOCK_SETTIME = 5221 - SYS_CLOCK_GETTIME = 5222 - SYS_CLOCK_GETRES = 5223 - SYS_CLOCK_NANOSLEEP = 5224 - SYS_TGKILL = 5225 - SYS_UTIMES = 5226 - SYS_MBIND = 5227 - SYS_GET_MEMPOLICY = 5228 - SYS_SET_MEMPOLICY = 5229 - SYS_MQ_OPEN = 5230 - SYS_MQ_UNLINK = 5231 - SYS_MQ_TIMEDSEND = 5232 - SYS_MQ_TIMEDRECEIVE = 5233 - SYS_MQ_NOTIFY = 5234 - SYS_MQ_GETSETATTR = 5235 - SYS_VSERVER = 5236 - SYS_WAITID = 5237 - SYS_ADD_KEY = 5239 - SYS_REQUEST_KEY = 5240 - SYS_KEYCTL = 5241 - SYS_SET_THREAD_AREA = 5242 - SYS_INOTIFY_INIT = 5243 - SYS_INOTIFY_ADD_WATCH = 5244 - SYS_INOTIFY_RM_WATCH = 5245 - SYS_MIGRATE_PAGES = 5246 - SYS_OPENAT = 5247 - SYS_MKDIRAT = 5248 - SYS_MKNODAT = 5249 - SYS_FCHOWNAT = 5250 - SYS_FUTIMESAT = 5251 - SYS_NEWFSTATAT = 5252 - SYS_UNLINKAT = 5253 - SYS_RENAMEAT = 5254 - SYS_LINKAT = 5255 - SYS_SYMLINKAT = 5256 - SYS_READLINKAT = 5257 - SYS_FCHMODAT = 5258 - SYS_FACCESSAT = 5259 - SYS_PSELECT6 = 5260 - SYS_PPOLL = 5261 - SYS_UNSHARE = 5262 - SYS_SPLICE = 5263 - SYS_SYNC_FILE_RANGE = 5264 - SYS_TEE = 5265 - SYS_VMSPLICE = 5266 - SYS_MOVE_PAGES = 5267 - SYS_SET_ROBUST_LIST = 5268 - SYS_GET_ROBUST_LIST = 5269 - SYS_KEXEC_LOAD = 5270 - SYS_GETCPU = 5271 - SYS_EPOLL_PWAIT = 5272 - SYS_IOPRIO_SET = 5273 - SYS_IOPRIO_GET = 5274 - SYS_UTIMENSAT = 5275 - SYS_SIGNALFD = 5276 - SYS_TIMERFD = 5277 - SYS_EVENTFD = 5278 - SYS_FALLOCATE = 5279 - SYS_TIMERFD_CREATE = 5280 - SYS_TIMERFD_GETTIME = 5281 - SYS_TIMERFD_SETTIME = 5282 - SYS_SIGNALFD4 = 5283 - SYS_EVENTFD2 = 5284 - SYS_EPOLL_CREATE1 = 5285 - SYS_DUP3 = 5286 - SYS_PIPE2 = 5287 - SYS_INOTIFY_INIT1 = 5288 - SYS_PREADV = 5289 - SYS_PWRITEV = 5290 - SYS_RT_TGSIGQUEUEINFO = 5291 - SYS_PERF_EVENT_OPEN = 5292 - SYS_ACCEPT4 = 5293 - SYS_RECVMMSG = 5294 - SYS_FANOTIFY_INIT = 5295 - SYS_FANOTIFY_MARK = 5296 - SYS_PRLIMIT64 = 5297 - SYS_NAME_TO_HANDLE_AT = 5298 - SYS_OPEN_BY_HANDLE_AT = 5299 - SYS_CLOCK_ADJTIME = 5300 - SYS_SYNCFS = 5301 - SYS_SENDMMSG = 5302 - SYS_SETNS = 5303 - SYS_PROCESS_VM_READV = 5304 - SYS_PROCESS_VM_WRITEV = 5305 - SYS_KCMP = 5306 - SYS_FINIT_MODULE = 5307 - SYS_GETDENTS64 = 5308 - SYS_SCHED_SETATTR = 5309 - SYS_SCHED_GETATTR = 5310 - SYS_RENAMEAT2 = 5311 - SYS_SECCOMP = 5312 - SYS_GETRANDOM = 5313 - SYS_MEMFD_CREATE = 5314 - SYS_BPF = 5315 - SYS_EXECVEAT = 5316 - SYS_USERFAULTFD = 5317 - SYS_MEMBARRIER = 5318 - SYS_MLOCK2 = 5319 - SYS_COPY_FILE_RANGE = 5320 - SYS_PREADV2 = 5321 - SYS_PWRITEV2 = 5322 - SYS_PKEY_MPROTECT = 5323 - SYS_PKEY_ALLOC = 5324 - SYS_PKEY_FREE = 5325 - SYS_STATX = 5326 - SYS_RSEQ = 5327 - SYS_IO_PGETEVENTS = 5328 - SYS_PIDFD_SEND_SIGNAL = 5424 - SYS_IO_URING_SETUP = 5425 - SYS_IO_URING_ENTER = 5426 - SYS_IO_URING_REGISTER = 5427 - SYS_OPEN_TREE = 5428 - SYS_MOVE_MOUNT = 5429 - SYS_FSOPEN = 5430 - SYS_FSCONFIG = 5431 - SYS_FSMOUNT = 5432 - SYS_FSPICK = 5433 - SYS_PIDFD_OPEN = 5434 - SYS_CLONE3 = 5435 + SYS_READ = 5000 + SYS_WRITE = 5001 + SYS_OPEN = 5002 + SYS_CLOSE = 5003 + SYS_STAT = 5004 + SYS_FSTAT = 5005 + SYS_LSTAT = 5006 + SYS_POLL = 5007 + SYS_LSEEK = 5008 + SYS_MMAP = 5009 + SYS_MPROTECT = 5010 + SYS_MUNMAP = 5011 + SYS_BRK = 5012 + SYS_RT_SIGACTION = 5013 + SYS_RT_SIGPROCMASK = 5014 + SYS_IOCTL = 5015 + SYS_PREAD64 = 5016 + SYS_PWRITE64 = 5017 + SYS_READV = 5018 + SYS_WRITEV = 5019 + SYS_ACCESS = 5020 + SYS_PIPE = 5021 + SYS__NEWSELECT = 5022 + SYS_SCHED_YIELD = 5023 + SYS_MREMAP = 5024 + SYS_MSYNC = 5025 + SYS_MINCORE = 5026 + SYS_MADVISE = 5027 + SYS_SHMGET = 5028 + SYS_SHMAT = 5029 + SYS_SHMCTL = 5030 + SYS_DUP = 5031 + SYS_DUP2 = 5032 + SYS_PAUSE = 5033 + SYS_NANOSLEEP = 5034 + SYS_GETITIMER = 5035 + SYS_SETITIMER = 5036 + SYS_ALARM = 5037 + SYS_GETPID = 5038 + SYS_SENDFILE = 5039 + SYS_SOCKET = 5040 + SYS_CONNECT = 5041 + SYS_ACCEPT = 5042 + SYS_SENDTO = 5043 + SYS_RECVFROM = 5044 + SYS_SENDMSG = 5045 + SYS_RECVMSG = 5046 + SYS_SHUTDOWN = 5047 + SYS_BIND = 5048 + SYS_LISTEN = 5049 + SYS_GETSOCKNAME = 5050 + SYS_GETPEERNAME = 5051 + SYS_SOCKETPAIR = 5052 + SYS_SETSOCKOPT = 5053 + SYS_GETSOCKOPT = 5054 + SYS_CLONE = 5055 + SYS_FORK = 5056 + SYS_EXECVE = 5057 + SYS_EXIT = 5058 + SYS_WAIT4 = 5059 + SYS_KILL = 5060 + SYS_UNAME = 5061 + SYS_SEMGET = 5062 + SYS_SEMOP = 5063 + SYS_SEMCTL = 5064 + SYS_SHMDT = 5065 + SYS_MSGGET = 5066 + SYS_MSGSND = 5067 + SYS_MSGRCV = 5068 + SYS_MSGCTL = 5069 + SYS_FCNTL = 5070 + SYS_FLOCK = 5071 + SYS_FSYNC = 5072 + SYS_FDATASYNC = 5073 + SYS_TRUNCATE = 5074 + SYS_FTRUNCATE = 5075 + SYS_GETDENTS = 5076 + SYS_GETCWD = 5077 + SYS_CHDIR = 5078 + SYS_FCHDIR = 5079 + SYS_RENAME = 5080 + SYS_MKDIR = 5081 + SYS_RMDIR = 5082 + SYS_CREAT = 5083 + SYS_LINK = 5084 + SYS_UNLINK = 5085 + SYS_SYMLINK = 5086 + SYS_READLINK = 5087 + SYS_CHMOD = 5088 + SYS_FCHMOD = 5089 + SYS_CHOWN = 5090 + SYS_FCHOWN = 5091 + SYS_LCHOWN = 5092 + SYS_UMASK = 5093 + SYS_GETTIMEOFDAY = 5094 + SYS_GETRLIMIT = 5095 + SYS_GETRUSAGE = 5096 + SYS_SYSINFO = 5097 + SYS_TIMES = 5098 + SYS_PTRACE = 5099 + SYS_GETUID = 5100 + SYS_SYSLOG = 5101 + SYS_GETGID = 5102 + SYS_SETUID = 5103 + SYS_SETGID = 5104 + SYS_GETEUID = 5105 + SYS_GETEGID = 5106 + SYS_SETPGID = 5107 + SYS_GETPPID = 5108 + SYS_GETPGRP = 5109 + SYS_SETSID = 5110 + SYS_SETREUID = 5111 + SYS_SETREGID = 5112 + SYS_GETGROUPS = 5113 + SYS_SETGROUPS = 5114 + SYS_SETRESUID = 5115 + SYS_GETRESUID = 5116 + SYS_SETRESGID = 5117 + SYS_GETRESGID = 5118 + SYS_GETPGID = 5119 + SYS_SETFSUID = 5120 + SYS_SETFSGID = 5121 + SYS_GETSID = 5122 + SYS_CAPGET = 5123 + SYS_CAPSET = 5124 + SYS_RT_SIGPENDING = 5125 + SYS_RT_SIGTIMEDWAIT = 5126 + SYS_RT_SIGQUEUEINFO = 5127 + SYS_RT_SIGSUSPEND = 5128 + SYS_SIGALTSTACK = 5129 + SYS_UTIME = 5130 + SYS_MKNOD = 5131 + SYS_PERSONALITY = 5132 + SYS_USTAT = 5133 + SYS_STATFS = 5134 + SYS_FSTATFS = 5135 + SYS_SYSFS = 5136 + SYS_GETPRIORITY = 5137 + SYS_SETPRIORITY = 5138 + SYS_SCHED_SETPARAM = 5139 + SYS_SCHED_GETPARAM = 5140 + SYS_SCHED_SETSCHEDULER = 5141 + SYS_SCHED_GETSCHEDULER = 5142 + SYS_SCHED_GET_PRIORITY_MAX = 5143 + SYS_SCHED_GET_PRIORITY_MIN = 5144 + SYS_SCHED_RR_GET_INTERVAL = 5145 + SYS_MLOCK = 5146 + SYS_MUNLOCK = 5147 + SYS_MLOCKALL = 5148 + SYS_MUNLOCKALL = 5149 + SYS_VHANGUP = 5150 + SYS_PIVOT_ROOT = 5151 + SYS__SYSCTL = 5152 + SYS_PRCTL = 5153 + SYS_ADJTIMEX = 5154 + SYS_SETRLIMIT = 5155 + SYS_CHROOT = 5156 + SYS_SYNC = 5157 + SYS_ACCT = 5158 + SYS_SETTIMEOFDAY = 5159 + SYS_MOUNT = 5160 + SYS_UMOUNT2 = 5161 + SYS_SWAPON = 5162 + SYS_SWAPOFF = 5163 + SYS_REBOOT = 5164 + SYS_SETHOSTNAME = 5165 + SYS_SETDOMAINNAME = 5166 + SYS_CREATE_MODULE = 5167 + SYS_INIT_MODULE = 5168 + SYS_DELETE_MODULE = 5169 + SYS_GET_KERNEL_SYMS = 5170 + SYS_QUERY_MODULE = 5171 + SYS_QUOTACTL = 5172 + SYS_NFSSERVCTL = 5173 + SYS_GETPMSG = 5174 + SYS_PUTPMSG = 5175 + SYS_AFS_SYSCALL = 5176 + SYS_RESERVED177 = 5177 + SYS_GETTID = 5178 + SYS_READAHEAD = 5179 + SYS_SETXATTR = 5180 + SYS_LSETXATTR = 5181 + SYS_FSETXATTR = 5182 + SYS_GETXATTR = 5183 + SYS_LGETXATTR = 5184 + SYS_FGETXATTR = 5185 + SYS_LISTXATTR = 5186 + SYS_LLISTXATTR = 5187 + SYS_FLISTXATTR = 5188 + SYS_REMOVEXATTR = 5189 + SYS_LREMOVEXATTR = 5190 + SYS_FREMOVEXATTR = 5191 + SYS_TKILL = 5192 + SYS_RESERVED193 = 5193 + SYS_FUTEX = 5194 + SYS_SCHED_SETAFFINITY = 5195 + SYS_SCHED_GETAFFINITY = 5196 + SYS_CACHEFLUSH = 5197 + SYS_CACHECTL = 5198 + SYS_SYSMIPS = 5199 + SYS_IO_SETUP = 5200 + SYS_IO_DESTROY = 5201 + SYS_IO_GETEVENTS = 5202 + SYS_IO_SUBMIT = 5203 + SYS_IO_CANCEL = 5204 + SYS_EXIT_GROUP = 5205 + SYS_LOOKUP_DCOOKIE = 5206 + SYS_EPOLL_CREATE = 5207 + SYS_EPOLL_CTL = 5208 + SYS_EPOLL_WAIT = 5209 + SYS_REMAP_FILE_PAGES = 5210 + SYS_RT_SIGRETURN = 5211 + SYS_SET_TID_ADDRESS = 5212 + SYS_RESTART_SYSCALL = 5213 + SYS_SEMTIMEDOP = 5214 + SYS_FADVISE64 = 5215 + SYS_TIMER_CREATE = 5216 + SYS_TIMER_SETTIME = 5217 + SYS_TIMER_GETTIME = 5218 + SYS_TIMER_GETOVERRUN = 5219 + SYS_TIMER_DELETE = 5220 + SYS_CLOCK_SETTIME = 5221 + SYS_CLOCK_GETTIME = 5222 + SYS_CLOCK_GETRES = 5223 + SYS_CLOCK_NANOSLEEP = 5224 + SYS_TGKILL = 5225 + SYS_UTIMES = 5226 + SYS_MBIND = 5227 + SYS_GET_MEMPOLICY = 5228 + SYS_SET_MEMPOLICY = 5229 + SYS_MQ_OPEN = 5230 + SYS_MQ_UNLINK = 5231 + SYS_MQ_TIMEDSEND = 5232 + SYS_MQ_TIMEDRECEIVE = 5233 + SYS_MQ_NOTIFY = 5234 + SYS_MQ_GETSETATTR = 5235 + SYS_VSERVER = 5236 + SYS_WAITID = 5237 + SYS_ADD_KEY = 5239 + SYS_REQUEST_KEY = 5240 + SYS_KEYCTL = 5241 + SYS_SET_THREAD_AREA = 5242 + SYS_INOTIFY_INIT = 5243 + SYS_INOTIFY_ADD_WATCH = 5244 + SYS_INOTIFY_RM_WATCH = 5245 + SYS_MIGRATE_PAGES = 5246 + SYS_OPENAT = 5247 + SYS_MKDIRAT = 5248 + SYS_MKNODAT = 5249 + SYS_FCHOWNAT = 5250 + SYS_FUTIMESAT = 5251 + SYS_NEWFSTATAT = 5252 + SYS_UNLINKAT = 5253 + SYS_RENAMEAT = 5254 + SYS_LINKAT = 5255 + SYS_SYMLINKAT = 5256 + SYS_READLINKAT = 5257 + SYS_FCHMODAT = 5258 + SYS_FACCESSAT = 5259 + SYS_PSELECT6 = 5260 + SYS_PPOLL = 5261 + SYS_UNSHARE = 5262 + SYS_SPLICE = 5263 + SYS_SYNC_FILE_RANGE = 5264 + SYS_TEE = 5265 + SYS_VMSPLICE = 5266 + SYS_MOVE_PAGES = 5267 + SYS_SET_ROBUST_LIST = 5268 + SYS_GET_ROBUST_LIST = 5269 + SYS_KEXEC_LOAD = 5270 + SYS_GETCPU = 5271 + SYS_EPOLL_PWAIT = 5272 + SYS_IOPRIO_SET = 5273 + SYS_IOPRIO_GET = 5274 + SYS_UTIMENSAT = 5275 + SYS_SIGNALFD = 5276 + SYS_TIMERFD = 5277 + SYS_EVENTFD = 5278 + SYS_FALLOCATE = 5279 + SYS_TIMERFD_CREATE = 5280 + SYS_TIMERFD_GETTIME = 5281 + SYS_TIMERFD_SETTIME = 5282 + SYS_SIGNALFD4 = 5283 + SYS_EVENTFD2 = 5284 + SYS_EPOLL_CREATE1 = 5285 + SYS_DUP3 = 5286 + SYS_PIPE2 = 5287 + SYS_INOTIFY_INIT1 = 5288 + SYS_PREADV = 5289 + SYS_PWRITEV = 5290 + SYS_RT_TGSIGQUEUEINFO = 5291 + SYS_PERF_EVENT_OPEN = 5292 + SYS_ACCEPT4 = 5293 + SYS_RECVMMSG = 5294 + SYS_FANOTIFY_INIT = 5295 + SYS_FANOTIFY_MARK = 5296 + SYS_PRLIMIT64 = 5297 + SYS_NAME_TO_HANDLE_AT = 5298 + SYS_OPEN_BY_HANDLE_AT = 5299 + SYS_CLOCK_ADJTIME = 5300 + SYS_SYNCFS = 5301 + SYS_SENDMMSG = 5302 + SYS_SETNS = 5303 + SYS_PROCESS_VM_READV = 5304 + SYS_PROCESS_VM_WRITEV = 5305 + SYS_KCMP = 5306 + SYS_FINIT_MODULE = 5307 + SYS_GETDENTS64 = 5308 + SYS_SCHED_SETATTR = 5309 + SYS_SCHED_GETATTR = 5310 + SYS_RENAMEAT2 = 5311 + SYS_SECCOMP = 5312 + SYS_GETRANDOM = 5313 + SYS_MEMFD_CREATE = 5314 + SYS_BPF = 5315 + SYS_EXECVEAT = 5316 + SYS_USERFAULTFD = 5317 + SYS_MEMBARRIER = 5318 + SYS_MLOCK2 = 5319 + SYS_COPY_FILE_RANGE = 5320 + SYS_PREADV2 = 5321 + SYS_PWRITEV2 = 5322 + SYS_PKEY_MPROTECT = 5323 + SYS_PKEY_ALLOC = 5324 + SYS_PKEY_FREE = 5325 + SYS_STATX = 5326 + SYS_RSEQ = 5327 + SYS_IO_PGETEVENTS = 5328 + SYS_PIDFD_SEND_SIGNAL = 5424 + SYS_IO_URING_SETUP = 5425 + SYS_IO_URING_ENTER = 5426 + SYS_IO_URING_REGISTER = 5427 + SYS_OPEN_TREE = 5428 + SYS_MOVE_MOUNT = 5429 + SYS_FSOPEN = 5430 + SYS_FSCONFIG = 5431 + SYS_FSMOUNT = 5432 + SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 + SYS_CLONE3 = 5435 + SYS_CLOSE_RANGE = 5436 + SYS_OPENAT2 = 5437 + SYS_PIDFD_GETFD = 5438 + SYS_FACCESSAT2 = 5439 + SYS_PROCESS_MADVISE = 5440 + SYS_EPOLL_PWAIT2 = 5441 + SYS_MOUNT_SETATTR = 5442 + SYS_QUOTACTL_FD = 5443 + SYS_LANDLOCK_CREATE_RULESET = 5444 + SYS_LANDLOCK_ADD_RULE = 5445 + SYS_LANDLOCK_RESTRICT_SELF = 5446 + SYS_PROCESS_MRELEASE = 5448 + SYS_FUTEX_WAITV = 5449 + SYS_SET_MEMPOLICY_HOME_NODE = 5450 + SYS_CACHESTAT = 5451 + SYS_FCHMODAT2 = 5452 + SYS_MAP_SHADOW_STACK = 5453 + SYS_FUTEX_WAKE = 5454 + SYS_FUTEX_WAIT = 5455 + SYS_FUTEX_REQUEUE = 5456 + SYS_STATMOUNT = 5457 + SYS_LISTMOUNT = 5458 + SYS_LSM_GET_SELF_ATTR = 5459 + SYS_LSM_SET_SELF_ATTR = 5460 + SYS_LSM_LIST_MODULES = 5461 + SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index bfbf242..5656157 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -1,349 +1,380 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/mips64le/include /tmp/mips64le/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips64le,linux +//go:build mips64le && linux package unix const ( - SYS_READ = 5000 - SYS_WRITE = 5001 - SYS_OPEN = 5002 - SYS_CLOSE = 5003 - SYS_STAT = 5004 - SYS_FSTAT = 5005 - SYS_LSTAT = 5006 - SYS_POLL = 5007 - SYS_LSEEK = 5008 - SYS_MMAP = 5009 - SYS_MPROTECT = 5010 - SYS_MUNMAP = 5011 - SYS_BRK = 5012 - SYS_RT_SIGACTION = 5013 - SYS_RT_SIGPROCMASK = 5014 - SYS_IOCTL = 5015 - SYS_PREAD64 = 5016 - SYS_PWRITE64 = 5017 - SYS_READV = 5018 - SYS_WRITEV = 5019 - SYS_ACCESS = 5020 - SYS_PIPE = 5021 - SYS__NEWSELECT = 5022 - SYS_SCHED_YIELD = 5023 - SYS_MREMAP = 5024 - SYS_MSYNC = 5025 - SYS_MINCORE = 5026 - SYS_MADVISE = 5027 - SYS_SHMGET = 5028 - SYS_SHMAT = 5029 - SYS_SHMCTL = 5030 - SYS_DUP = 5031 - SYS_DUP2 = 5032 - SYS_PAUSE = 5033 - SYS_NANOSLEEP = 5034 - SYS_GETITIMER = 5035 - SYS_SETITIMER = 5036 - SYS_ALARM = 5037 - SYS_GETPID = 5038 - SYS_SENDFILE = 5039 - SYS_SOCKET = 5040 - SYS_CONNECT = 5041 - SYS_ACCEPT = 5042 - SYS_SENDTO = 5043 - SYS_RECVFROM = 5044 - SYS_SENDMSG = 5045 - SYS_RECVMSG = 5046 - SYS_SHUTDOWN = 5047 - SYS_BIND = 5048 - SYS_LISTEN = 5049 - SYS_GETSOCKNAME = 5050 - SYS_GETPEERNAME = 5051 - SYS_SOCKETPAIR = 5052 - SYS_SETSOCKOPT = 5053 - SYS_GETSOCKOPT = 5054 - SYS_CLONE = 5055 - SYS_FORK = 5056 - SYS_EXECVE = 5057 - SYS_EXIT = 5058 - SYS_WAIT4 = 5059 - SYS_KILL = 5060 - SYS_UNAME = 5061 - SYS_SEMGET = 5062 - SYS_SEMOP = 5063 - SYS_SEMCTL = 5064 - SYS_SHMDT = 5065 - SYS_MSGGET = 5066 - SYS_MSGSND = 5067 - SYS_MSGRCV = 5068 - SYS_MSGCTL = 5069 - SYS_FCNTL = 5070 - SYS_FLOCK = 5071 - SYS_FSYNC = 5072 - SYS_FDATASYNC = 5073 - SYS_TRUNCATE = 5074 - SYS_FTRUNCATE = 5075 - SYS_GETDENTS = 5076 - SYS_GETCWD = 5077 - SYS_CHDIR = 5078 - SYS_FCHDIR = 5079 - SYS_RENAME = 5080 - SYS_MKDIR = 5081 - SYS_RMDIR = 5082 - SYS_CREAT = 5083 - SYS_LINK = 5084 - SYS_UNLINK = 5085 - SYS_SYMLINK = 5086 - SYS_READLINK = 5087 - SYS_CHMOD = 5088 - SYS_FCHMOD = 5089 - SYS_CHOWN = 5090 - SYS_FCHOWN = 5091 - SYS_LCHOWN = 5092 - SYS_UMASK = 5093 - SYS_GETTIMEOFDAY = 5094 - SYS_GETRLIMIT = 5095 - SYS_GETRUSAGE = 5096 - SYS_SYSINFO = 5097 - SYS_TIMES = 5098 - SYS_PTRACE = 5099 - SYS_GETUID = 5100 - SYS_SYSLOG = 5101 - SYS_GETGID = 5102 - SYS_SETUID = 5103 - SYS_SETGID = 5104 - SYS_GETEUID = 5105 - SYS_GETEGID = 5106 - SYS_SETPGID = 5107 - SYS_GETPPID = 5108 - SYS_GETPGRP = 5109 - SYS_SETSID = 5110 - SYS_SETREUID = 5111 - SYS_SETREGID = 5112 - SYS_GETGROUPS = 5113 - SYS_SETGROUPS = 5114 - SYS_SETRESUID = 5115 - SYS_GETRESUID = 5116 - SYS_SETRESGID = 5117 - SYS_GETRESGID = 5118 - SYS_GETPGID = 5119 - SYS_SETFSUID = 5120 - SYS_SETFSGID = 5121 - SYS_GETSID = 5122 - SYS_CAPGET = 5123 - SYS_CAPSET = 5124 - SYS_RT_SIGPENDING = 5125 - SYS_RT_SIGTIMEDWAIT = 5126 - SYS_RT_SIGQUEUEINFO = 5127 - SYS_RT_SIGSUSPEND = 5128 - SYS_SIGALTSTACK = 5129 - SYS_UTIME = 5130 - SYS_MKNOD = 5131 - SYS_PERSONALITY = 5132 - SYS_USTAT = 5133 - SYS_STATFS = 5134 - SYS_FSTATFS = 5135 - SYS_SYSFS = 5136 - SYS_GETPRIORITY = 5137 - SYS_SETPRIORITY = 5138 - SYS_SCHED_SETPARAM = 5139 - SYS_SCHED_GETPARAM = 5140 - SYS_SCHED_SETSCHEDULER = 5141 - SYS_SCHED_GETSCHEDULER = 5142 - SYS_SCHED_GET_PRIORITY_MAX = 5143 - SYS_SCHED_GET_PRIORITY_MIN = 5144 - SYS_SCHED_RR_GET_INTERVAL = 5145 - SYS_MLOCK = 5146 - SYS_MUNLOCK = 5147 - SYS_MLOCKALL = 5148 - SYS_MUNLOCKALL = 5149 - SYS_VHANGUP = 5150 - SYS_PIVOT_ROOT = 5151 - SYS__SYSCTL = 5152 - SYS_PRCTL = 5153 - SYS_ADJTIMEX = 5154 - SYS_SETRLIMIT = 5155 - SYS_CHROOT = 5156 - SYS_SYNC = 5157 - SYS_ACCT = 5158 - SYS_SETTIMEOFDAY = 5159 - SYS_MOUNT = 5160 - SYS_UMOUNT2 = 5161 - SYS_SWAPON = 5162 - SYS_SWAPOFF = 5163 - SYS_REBOOT = 5164 - SYS_SETHOSTNAME = 5165 - SYS_SETDOMAINNAME = 5166 - SYS_CREATE_MODULE = 5167 - SYS_INIT_MODULE = 5168 - SYS_DELETE_MODULE = 5169 - SYS_GET_KERNEL_SYMS = 5170 - SYS_QUERY_MODULE = 5171 - SYS_QUOTACTL = 5172 - SYS_NFSSERVCTL = 5173 - SYS_GETPMSG = 5174 - SYS_PUTPMSG = 5175 - SYS_AFS_SYSCALL = 5176 - SYS_RESERVED177 = 5177 - SYS_GETTID = 5178 - SYS_READAHEAD = 5179 - SYS_SETXATTR = 5180 - SYS_LSETXATTR = 5181 - SYS_FSETXATTR = 5182 - SYS_GETXATTR = 5183 - SYS_LGETXATTR = 5184 - SYS_FGETXATTR = 5185 - SYS_LISTXATTR = 5186 - SYS_LLISTXATTR = 5187 - SYS_FLISTXATTR = 5188 - SYS_REMOVEXATTR = 5189 - SYS_LREMOVEXATTR = 5190 - SYS_FREMOVEXATTR = 5191 - SYS_TKILL = 5192 - SYS_RESERVED193 = 5193 - SYS_FUTEX = 5194 - SYS_SCHED_SETAFFINITY = 5195 - SYS_SCHED_GETAFFINITY = 5196 - SYS_CACHEFLUSH = 5197 - SYS_CACHECTL = 5198 - SYS_SYSMIPS = 5199 - SYS_IO_SETUP = 5200 - SYS_IO_DESTROY = 5201 - SYS_IO_GETEVENTS = 5202 - SYS_IO_SUBMIT = 5203 - SYS_IO_CANCEL = 5204 - SYS_EXIT_GROUP = 5205 - SYS_LOOKUP_DCOOKIE = 5206 - SYS_EPOLL_CREATE = 5207 - SYS_EPOLL_CTL = 5208 - SYS_EPOLL_WAIT = 5209 - SYS_REMAP_FILE_PAGES = 5210 - SYS_RT_SIGRETURN = 5211 - SYS_SET_TID_ADDRESS = 5212 - SYS_RESTART_SYSCALL = 5213 - SYS_SEMTIMEDOP = 5214 - SYS_FADVISE64 = 5215 - SYS_TIMER_CREATE = 5216 - SYS_TIMER_SETTIME = 5217 - SYS_TIMER_GETTIME = 5218 - SYS_TIMER_GETOVERRUN = 5219 - SYS_TIMER_DELETE = 5220 - SYS_CLOCK_SETTIME = 5221 - SYS_CLOCK_GETTIME = 5222 - SYS_CLOCK_GETRES = 5223 - SYS_CLOCK_NANOSLEEP = 5224 - SYS_TGKILL = 5225 - SYS_UTIMES = 5226 - SYS_MBIND = 5227 - SYS_GET_MEMPOLICY = 5228 - SYS_SET_MEMPOLICY = 5229 - SYS_MQ_OPEN = 5230 - SYS_MQ_UNLINK = 5231 - SYS_MQ_TIMEDSEND = 5232 - SYS_MQ_TIMEDRECEIVE = 5233 - SYS_MQ_NOTIFY = 5234 - SYS_MQ_GETSETATTR = 5235 - SYS_VSERVER = 5236 - SYS_WAITID = 5237 - SYS_ADD_KEY = 5239 - SYS_REQUEST_KEY = 5240 - SYS_KEYCTL = 5241 - SYS_SET_THREAD_AREA = 5242 - SYS_INOTIFY_INIT = 5243 - SYS_INOTIFY_ADD_WATCH = 5244 - SYS_INOTIFY_RM_WATCH = 5245 - SYS_MIGRATE_PAGES = 5246 - SYS_OPENAT = 5247 - SYS_MKDIRAT = 5248 - SYS_MKNODAT = 5249 - SYS_FCHOWNAT = 5250 - SYS_FUTIMESAT = 5251 - SYS_NEWFSTATAT = 5252 - SYS_UNLINKAT = 5253 - SYS_RENAMEAT = 5254 - SYS_LINKAT = 5255 - SYS_SYMLINKAT = 5256 - SYS_READLINKAT = 5257 - SYS_FCHMODAT = 5258 - SYS_FACCESSAT = 5259 - SYS_PSELECT6 = 5260 - SYS_PPOLL = 5261 - SYS_UNSHARE = 5262 - SYS_SPLICE = 5263 - SYS_SYNC_FILE_RANGE = 5264 - SYS_TEE = 5265 - SYS_VMSPLICE = 5266 - SYS_MOVE_PAGES = 5267 - SYS_SET_ROBUST_LIST = 5268 - SYS_GET_ROBUST_LIST = 5269 - SYS_KEXEC_LOAD = 5270 - SYS_GETCPU = 5271 - SYS_EPOLL_PWAIT = 5272 - SYS_IOPRIO_SET = 5273 - SYS_IOPRIO_GET = 5274 - SYS_UTIMENSAT = 5275 - SYS_SIGNALFD = 5276 - SYS_TIMERFD = 5277 - SYS_EVENTFD = 5278 - SYS_FALLOCATE = 5279 - SYS_TIMERFD_CREATE = 5280 - SYS_TIMERFD_GETTIME = 5281 - SYS_TIMERFD_SETTIME = 5282 - SYS_SIGNALFD4 = 5283 - SYS_EVENTFD2 = 5284 - SYS_EPOLL_CREATE1 = 5285 - SYS_DUP3 = 5286 - SYS_PIPE2 = 5287 - SYS_INOTIFY_INIT1 = 5288 - SYS_PREADV = 5289 - SYS_PWRITEV = 5290 - SYS_RT_TGSIGQUEUEINFO = 5291 - SYS_PERF_EVENT_OPEN = 5292 - SYS_ACCEPT4 = 5293 - SYS_RECVMMSG = 5294 - SYS_FANOTIFY_INIT = 5295 - SYS_FANOTIFY_MARK = 5296 - SYS_PRLIMIT64 = 5297 - SYS_NAME_TO_HANDLE_AT = 5298 - SYS_OPEN_BY_HANDLE_AT = 5299 - SYS_CLOCK_ADJTIME = 5300 - SYS_SYNCFS = 5301 - SYS_SENDMMSG = 5302 - SYS_SETNS = 5303 - SYS_PROCESS_VM_READV = 5304 - SYS_PROCESS_VM_WRITEV = 5305 - SYS_KCMP = 5306 - SYS_FINIT_MODULE = 5307 - SYS_GETDENTS64 = 5308 - SYS_SCHED_SETATTR = 5309 - SYS_SCHED_GETATTR = 5310 - SYS_RENAMEAT2 = 5311 - SYS_SECCOMP = 5312 - SYS_GETRANDOM = 5313 - SYS_MEMFD_CREATE = 5314 - SYS_BPF = 5315 - SYS_EXECVEAT = 5316 - SYS_USERFAULTFD = 5317 - SYS_MEMBARRIER = 5318 - SYS_MLOCK2 = 5319 - SYS_COPY_FILE_RANGE = 5320 - SYS_PREADV2 = 5321 - SYS_PWRITEV2 = 5322 - SYS_PKEY_MPROTECT = 5323 - SYS_PKEY_ALLOC = 5324 - SYS_PKEY_FREE = 5325 - SYS_STATX = 5326 - SYS_RSEQ = 5327 - SYS_IO_PGETEVENTS = 5328 - SYS_PIDFD_SEND_SIGNAL = 5424 - SYS_IO_URING_SETUP = 5425 - SYS_IO_URING_ENTER = 5426 - SYS_IO_URING_REGISTER = 5427 - SYS_OPEN_TREE = 5428 - SYS_MOVE_MOUNT = 5429 - SYS_FSOPEN = 5430 - SYS_FSCONFIG = 5431 - SYS_FSMOUNT = 5432 - SYS_FSPICK = 5433 - SYS_PIDFD_OPEN = 5434 - SYS_CLONE3 = 5435 + SYS_READ = 5000 + SYS_WRITE = 5001 + SYS_OPEN = 5002 + SYS_CLOSE = 5003 + SYS_STAT = 5004 + SYS_FSTAT = 5005 + SYS_LSTAT = 5006 + SYS_POLL = 5007 + SYS_LSEEK = 5008 + SYS_MMAP = 5009 + SYS_MPROTECT = 5010 + SYS_MUNMAP = 5011 + SYS_BRK = 5012 + SYS_RT_SIGACTION = 5013 + SYS_RT_SIGPROCMASK = 5014 + SYS_IOCTL = 5015 + SYS_PREAD64 = 5016 + SYS_PWRITE64 = 5017 + SYS_READV = 5018 + SYS_WRITEV = 5019 + SYS_ACCESS = 5020 + SYS_PIPE = 5021 + SYS__NEWSELECT = 5022 + SYS_SCHED_YIELD = 5023 + SYS_MREMAP = 5024 + SYS_MSYNC = 5025 + SYS_MINCORE = 5026 + SYS_MADVISE = 5027 + SYS_SHMGET = 5028 + SYS_SHMAT = 5029 + SYS_SHMCTL = 5030 + SYS_DUP = 5031 + SYS_DUP2 = 5032 + SYS_PAUSE = 5033 + SYS_NANOSLEEP = 5034 + SYS_GETITIMER = 5035 + SYS_SETITIMER = 5036 + SYS_ALARM = 5037 + SYS_GETPID = 5038 + SYS_SENDFILE = 5039 + SYS_SOCKET = 5040 + SYS_CONNECT = 5041 + SYS_ACCEPT = 5042 + SYS_SENDTO = 5043 + SYS_RECVFROM = 5044 + SYS_SENDMSG = 5045 + SYS_RECVMSG = 5046 + SYS_SHUTDOWN = 5047 + SYS_BIND = 5048 + SYS_LISTEN = 5049 + SYS_GETSOCKNAME = 5050 + SYS_GETPEERNAME = 5051 + SYS_SOCKETPAIR = 5052 + SYS_SETSOCKOPT = 5053 + SYS_GETSOCKOPT = 5054 + SYS_CLONE = 5055 + SYS_FORK = 5056 + SYS_EXECVE = 5057 + SYS_EXIT = 5058 + SYS_WAIT4 = 5059 + SYS_KILL = 5060 + SYS_UNAME = 5061 + SYS_SEMGET = 5062 + SYS_SEMOP = 5063 + SYS_SEMCTL = 5064 + SYS_SHMDT = 5065 + SYS_MSGGET = 5066 + SYS_MSGSND = 5067 + SYS_MSGRCV = 5068 + SYS_MSGCTL = 5069 + SYS_FCNTL = 5070 + SYS_FLOCK = 5071 + SYS_FSYNC = 5072 + SYS_FDATASYNC = 5073 + SYS_TRUNCATE = 5074 + SYS_FTRUNCATE = 5075 + SYS_GETDENTS = 5076 + SYS_GETCWD = 5077 + SYS_CHDIR = 5078 + SYS_FCHDIR = 5079 + SYS_RENAME = 5080 + SYS_MKDIR = 5081 + SYS_RMDIR = 5082 + SYS_CREAT = 5083 + SYS_LINK = 5084 + SYS_UNLINK = 5085 + SYS_SYMLINK = 5086 + SYS_READLINK = 5087 + SYS_CHMOD = 5088 + SYS_FCHMOD = 5089 + SYS_CHOWN = 5090 + SYS_FCHOWN = 5091 + SYS_LCHOWN = 5092 + SYS_UMASK = 5093 + SYS_GETTIMEOFDAY = 5094 + SYS_GETRLIMIT = 5095 + SYS_GETRUSAGE = 5096 + SYS_SYSINFO = 5097 + SYS_TIMES = 5098 + SYS_PTRACE = 5099 + SYS_GETUID = 5100 + SYS_SYSLOG = 5101 + SYS_GETGID = 5102 + SYS_SETUID = 5103 + SYS_SETGID = 5104 + SYS_GETEUID = 5105 + SYS_GETEGID = 5106 + SYS_SETPGID = 5107 + SYS_GETPPID = 5108 + SYS_GETPGRP = 5109 + SYS_SETSID = 5110 + SYS_SETREUID = 5111 + SYS_SETREGID = 5112 + SYS_GETGROUPS = 5113 + SYS_SETGROUPS = 5114 + SYS_SETRESUID = 5115 + SYS_GETRESUID = 5116 + SYS_SETRESGID = 5117 + SYS_GETRESGID = 5118 + SYS_GETPGID = 5119 + SYS_SETFSUID = 5120 + SYS_SETFSGID = 5121 + SYS_GETSID = 5122 + SYS_CAPGET = 5123 + SYS_CAPSET = 5124 + SYS_RT_SIGPENDING = 5125 + SYS_RT_SIGTIMEDWAIT = 5126 + SYS_RT_SIGQUEUEINFO = 5127 + SYS_RT_SIGSUSPEND = 5128 + SYS_SIGALTSTACK = 5129 + SYS_UTIME = 5130 + SYS_MKNOD = 5131 + SYS_PERSONALITY = 5132 + SYS_USTAT = 5133 + SYS_STATFS = 5134 + SYS_FSTATFS = 5135 + SYS_SYSFS = 5136 + SYS_GETPRIORITY = 5137 + SYS_SETPRIORITY = 5138 + SYS_SCHED_SETPARAM = 5139 + SYS_SCHED_GETPARAM = 5140 + SYS_SCHED_SETSCHEDULER = 5141 + SYS_SCHED_GETSCHEDULER = 5142 + SYS_SCHED_GET_PRIORITY_MAX = 5143 + SYS_SCHED_GET_PRIORITY_MIN = 5144 + SYS_SCHED_RR_GET_INTERVAL = 5145 + SYS_MLOCK = 5146 + SYS_MUNLOCK = 5147 + SYS_MLOCKALL = 5148 + SYS_MUNLOCKALL = 5149 + SYS_VHANGUP = 5150 + SYS_PIVOT_ROOT = 5151 + SYS__SYSCTL = 5152 + SYS_PRCTL = 5153 + SYS_ADJTIMEX = 5154 + SYS_SETRLIMIT = 5155 + SYS_CHROOT = 5156 + SYS_SYNC = 5157 + SYS_ACCT = 5158 + SYS_SETTIMEOFDAY = 5159 + SYS_MOUNT = 5160 + SYS_UMOUNT2 = 5161 + SYS_SWAPON = 5162 + SYS_SWAPOFF = 5163 + SYS_REBOOT = 5164 + SYS_SETHOSTNAME = 5165 + SYS_SETDOMAINNAME = 5166 + SYS_CREATE_MODULE = 5167 + SYS_INIT_MODULE = 5168 + SYS_DELETE_MODULE = 5169 + SYS_GET_KERNEL_SYMS = 5170 + SYS_QUERY_MODULE = 5171 + SYS_QUOTACTL = 5172 + SYS_NFSSERVCTL = 5173 + SYS_GETPMSG = 5174 + SYS_PUTPMSG = 5175 + SYS_AFS_SYSCALL = 5176 + SYS_RESERVED177 = 5177 + SYS_GETTID = 5178 + SYS_READAHEAD = 5179 + SYS_SETXATTR = 5180 + SYS_LSETXATTR = 5181 + SYS_FSETXATTR = 5182 + SYS_GETXATTR = 5183 + SYS_LGETXATTR = 5184 + SYS_FGETXATTR = 5185 + SYS_LISTXATTR = 5186 + SYS_LLISTXATTR = 5187 + SYS_FLISTXATTR = 5188 + SYS_REMOVEXATTR = 5189 + SYS_LREMOVEXATTR = 5190 + SYS_FREMOVEXATTR = 5191 + SYS_TKILL = 5192 + SYS_RESERVED193 = 5193 + SYS_FUTEX = 5194 + SYS_SCHED_SETAFFINITY = 5195 + SYS_SCHED_GETAFFINITY = 5196 + SYS_CACHEFLUSH = 5197 + SYS_CACHECTL = 5198 + SYS_SYSMIPS = 5199 + SYS_IO_SETUP = 5200 + SYS_IO_DESTROY = 5201 + SYS_IO_GETEVENTS = 5202 + SYS_IO_SUBMIT = 5203 + SYS_IO_CANCEL = 5204 + SYS_EXIT_GROUP = 5205 + SYS_LOOKUP_DCOOKIE = 5206 + SYS_EPOLL_CREATE = 5207 + SYS_EPOLL_CTL = 5208 + SYS_EPOLL_WAIT = 5209 + SYS_REMAP_FILE_PAGES = 5210 + SYS_RT_SIGRETURN = 5211 + SYS_SET_TID_ADDRESS = 5212 + SYS_RESTART_SYSCALL = 5213 + SYS_SEMTIMEDOP = 5214 + SYS_FADVISE64 = 5215 + SYS_TIMER_CREATE = 5216 + SYS_TIMER_SETTIME = 5217 + SYS_TIMER_GETTIME = 5218 + SYS_TIMER_GETOVERRUN = 5219 + SYS_TIMER_DELETE = 5220 + SYS_CLOCK_SETTIME = 5221 + SYS_CLOCK_GETTIME = 5222 + SYS_CLOCK_GETRES = 5223 + SYS_CLOCK_NANOSLEEP = 5224 + SYS_TGKILL = 5225 + SYS_UTIMES = 5226 + SYS_MBIND = 5227 + SYS_GET_MEMPOLICY = 5228 + SYS_SET_MEMPOLICY = 5229 + SYS_MQ_OPEN = 5230 + SYS_MQ_UNLINK = 5231 + SYS_MQ_TIMEDSEND = 5232 + SYS_MQ_TIMEDRECEIVE = 5233 + SYS_MQ_NOTIFY = 5234 + SYS_MQ_GETSETATTR = 5235 + SYS_VSERVER = 5236 + SYS_WAITID = 5237 + SYS_ADD_KEY = 5239 + SYS_REQUEST_KEY = 5240 + SYS_KEYCTL = 5241 + SYS_SET_THREAD_AREA = 5242 + SYS_INOTIFY_INIT = 5243 + SYS_INOTIFY_ADD_WATCH = 5244 + SYS_INOTIFY_RM_WATCH = 5245 + SYS_MIGRATE_PAGES = 5246 + SYS_OPENAT = 5247 + SYS_MKDIRAT = 5248 + SYS_MKNODAT = 5249 + SYS_FCHOWNAT = 5250 + SYS_FUTIMESAT = 5251 + SYS_NEWFSTATAT = 5252 + SYS_UNLINKAT = 5253 + SYS_RENAMEAT = 5254 + SYS_LINKAT = 5255 + SYS_SYMLINKAT = 5256 + SYS_READLINKAT = 5257 + SYS_FCHMODAT = 5258 + SYS_FACCESSAT = 5259 + SYS_PSELECT6 = 5260 + SYS_PPOLL = 5261 + SYS_UNSHARE = 5262 + SYS_SPLICE = 5263 + SYS_SYNC_FILE_RANGE = 5264 + SYS_TEE = 5265 + SYS_VMSPLICE = 5266 + SYS_MOVE_PAGES = 5267 + SYS_SET_ROBUST_LIST = 5268 + SYS_GET_ROBUST_LIST = 5269 + SYS_KEXEC_LOAD = 5270 + SYS_GETCPU = 5271 + SYS_EPOLL_PWAIT = 5272 + SYS_IOPRIO_SET = 5273 + SYS_IOPRIO_GET = 5274 + SYS_UTIMENSAT = 5275 + SYS_SIGNALFD = 5276 + SYS_TIMERFD = 5277 + SYS_EVENTFD = 5278 + SYS_FALLOCATE = 5279 + SYS_TIMERFD_CREATE = 5280 + SYS_TIMERFD_GETTIME = 5281 + SYS_TIMERFD_SETTIME = 5282 + SYS_SIGNALFD4 = 5283 + SYS_EVENTFD2 = 5284 + SYS_EPOLL_CREATE1 = 5285 + SYS_DUP3 = 5286 + SYS_PIPE2 = 5287 + SYS_INOTIFY_INIT1 = 5288 + SYS_PREADV = 5289 + SYS_PWRITEV = 5290 + SYS_RT_TGSIGQUEUEINFO = 5291 + SYS_PERF_EVENT_OPEN = 5292 + SYS_ACCEPT4 = 5293 + SYS_RECVMMSG = 5294 + SYS_FANOTIFY_INIT = 5295 + SYS_FANOTIFY_MARK = 5296 + SYS_PRLIMIT64 = 5297 + SYS_NAME_TO_HANDLE_AT = 5298 + SYS_OPEN_BY_HANDLE_AT = 5299 + SYS_CLOCK_ADJTIME = 5300 + SYS_SYNCFS = 5301 + SYS_SENDMMSG = 5302 + SYS_SETNS = 5303 + SYS_PROCESS_VM_READV = 5304 + SYS_PROCESS_VM_WRITEV = 5305 + SYS_KCMP = 5306 + SYS_FINIT_MODULE = 5307 + SYS_GETDENTS64 = 5308 + SYS_SCHED_SETATTR = 5309 + SYS_SCHED_GETATTR = 5310 + SYS_RENAMEAT2 = 5311 + SYS_SECCOMP = 5312 + SYS_GETRANDOM = 5313 + SYS_MEMFD_CREATE = 5314 + SYS_BPF = 5315 + SYS_EXECVEAT = 5316 + SYS_USERFAULTFD = 5317 + SYS_MEMBARRIER = 5318 + SYS_MLOCK2 = 5319 + SYS_COPY_FILE_RANGE = 5320 + SYS_PREADV2 = 5321 + SYS_PWRITEV2 = 5322 + SYS_PKEY_MPROTECT = 5323 + SYS_PKEY_ALLOC = 5324 + SYS_PKEY_FREE = 5325 + SYS_STATX = 5326 + SYS_RSEQ = 5327 + SYS_IO_PGETEVENTS = 5328 + SYS_PIDFD_SEND_SIGNAL = 5424 + SYS_IO_URING_SETUP = 5425 + SYS_IO_URING_ENTER = 5426 + SYS_IO_URING_REGISTER = 5427 + SYS_OPEN_TREE = 5428 + SYS_MOVE_MOUNT = 5429 + SYS_FSOPEN = 5430 + SYS_FSCONFIG = 5431 + SYS_FSMOUNT = 5432 + SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 + SYS_CLONE3 = 5435 + SYS_CLOSE_RANGE = 5436 + SYS_OPENAT2 = 5437 + SYS_PIDFD_GETFD = 5438 + SYS_FACCESSAT2 = 5439 + SYS_PROCESS_MADVISE = 5440 + SYS_EPOLL_PWAIT2 = 5441 + SYS_MOUNT_SETATTR = 5442 + SYS_QUOTACTL_FD = 5443 + SYS_LANDLOCK_CREATE_RULESET = 5444 + SYS_LANDLOCK_ADD_RULE = 5445 + SYS_LANDLOCK_RESTRICT_SELF = 5446 + SYS_PROCESS_MRELEASE = 5448 + SYS_FUTEX_WAITV = 5449 + SYS_SET_MEMPOLICY_HOME_NODE = 5450 + SYS_CACHESTAT = 5451 + SYS_FCHMODAT2 = 5452 + SYS_MAP_SHADOW_STACK = 5453 + SYS_FUTEX_WAKE = 5454 + SYS_FUTEX_WAIT = 5455 + SYS_FUTEX_REQUEUE = 5456 + SYS_STATMOUNT = 5457 + SYS_LISTMOUNT = 5458 + SYS_LSM_GET_SELF_ATTR = 5459 + SYS_LSM_SET_SELF_ATTR = 5460 + SYS_LSM_LIST_MODULES = 5461 + SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 + SYS_OPEN_TREE_ATTR = 5467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 3826f49..0482b52 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -1,7 +1,7 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/mipsle/include /tmp/mipsle/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mipsle,linux +//go:build mipsle && linux package unix @@ -416,4 +416,35 @@ const ( SYS_FSPICK = 4433 SYS_PIDFD_OPEN = 4434 SYS_CLONE3 = 4435 + SYS_CLOSE_RANGE = 4436 + SYS_OPENAT2 = 4437 + SYS_PIDFD_GETFD = 4438 + SYS_FACCESSAT2 = 4439 + SYS_PROCESS_MADVISE = 4440 + SYS_EPOLL_PWAIT2 = 4441 + SYS_MOUNT_SETATTR = 4442 + SYS_QUOTACTL_FD = 4443 + SYS_LANDLOCK_CREATE_RULESET = 4444 + SYS_LANDLOCK_ADD_RULE = 4445 + SYS_LANDLOCK_RESTRICT_SELF = 4446 + SYS_PROCESS_MRELEASE = 4448 + SYS_FUTEX_WAITV = 4449 + SYS_SET_MEMPOLICY_HOME_NODE = 4450 + SYS_CACHESTAT = 4451 + SYS_FCHMODAT2 = 4452 + SYS_MAP_SHADOW_STACK = 4453 + SYS_FUTEX_WAKE = 4454 + SYS_FUTEX_WAIT = 4455 + SYS_FUTEX_REQUEUE = 4456 + SYS_STATMOUNT = 4457 + SYS_LISTMOUNT = 4458 + SYS_LSM_GET_SELF_ATTR = 4459 + SYS_LSM_SET_SELF_ATTR = 4460 + SYS_LSM_LIST_MODULES = 4461 + SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 + SYS_OPEN_TREE_ATTR = 4467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go new file mode 100644 index 0000000..71806f0 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -0,0 +1,457 @@ +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/ppc/include /tmp/ppc/include/asm/unistd.h +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build ppc && linux + +package unix + +const ( + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAITPID = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_TIME = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BREAK = 17 + SYS_OLDSTAT = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_STIME = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_OLDFSTAT = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_STTY = 31 + SYS_GTTY = 32 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_FTIME = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_PROF = 44 + SYS_BRK = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_LOCK = 53 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_MPX = 56 + SYS_SETPGID = 57 + SYS_ULIMIT = 58 + SYS_OLDOLDUNAME = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SGETMASK = 68 + SYS_SSETMASK = 69 + SYS_SETREUID = 70 + SYS_SETREGID = 71 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRLIMIT = 76 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_GETGROUPS = 80 + SYS_SETGROUPS = 81 + SYS_SELECT = 82 + SYS_SYMLINK = 83 + SYS_OLDLSTAT = 84 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_FCHOWN = 95 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_PROFIL = 98 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_IOPERM = 101 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_OLDUNAME = 109 + SYS_IOPL = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_VM86 = 113 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_MODIFY_LDT = 123 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_SETFSUID = 138 + SYS_SETFSGID = 139 + SYS__LLSEEK = 140 + SYS_GETDENTS = 141 + SYS__NEWSELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_SETRESUID = 164 + SYS_GETRESUID = 165 + SYS_QUERY_MODULE = 166 + SYS_POLL = 167 + SYS_NFSSERVCTL = 168 + SYS_SETRESGID = 169 + SYS_GETRESGID = 170 + SYS_PRCTL = 171 + SYS_RT_SIGRETURN = 172 + SYS_RT_SIGACTION = 173 + SYS_RT_SIGPROCMASK = 174 + SYS_RT_SIGPENDING = 175 + SYS_RT_SIGTIMEDWAIT = 176 + SYS_RT_SIGQUEUEINFO = 177 + SYS_RT_SIGSUSPEND = 178 + SYS_PREAD64 = 179 + SYS_PWRITE64 = 180 + SYS_CHOWN = 181 + SYS_GETCWD = 182 + SYS_CAPGET = 183 + SYS_CAPSET = 184 + SYS_SIGALTSTACK = 185 + SYS_SENDFILE = 186 + SYS_GETPMSG = 187 + SYS_PUTPMSG = 188 + SYS_VFORK = 189 + SYS_UGETRLIMIT = 190 + SYS_READAHEAD = 191 + SYS_MMAP2 = 192 + SYS_TRUNCATE64 = 193 + SYS_FTRUNCATE64 = 194 + SYS_STAT64 = 195 + SYS_LSTAT64 = 196 + SYS_FSTAT64 = 197 + SYS_PCICONFIG_READ = 198 + SYS_PCICONFIG_WRITE = 199 + SYS_PCICONFIG_IOBASE = 200 + SYS_MULTIPLEXER = 201 + SYS_GETDENTS64 = 202 + SYS_PIVOT_ROOT = 203 + SYS_FCNTL64 = 204 + SYS_MADVISE = 205 + SYS_MINCORE = 206 + SYS_GETTID = 207 + SYS_TKILL = 208 + SYS_SETXATTR = 209 + SYS_LSETXATTR = 210 + SYS_FSETXATTR = 211 + SYS_GETXATTR = 212 + SYS_LGETXATTR = 213 + SYS_FGETXATTR = 214 + SYS_LISTXATTR = 215 + SYS_LLISTXATTR = 216 + SYS_FLISTXATTR = 217 + SYS_REMOVEXATTR = 218 + SYS_LREMOVEXATTR = 219 + SYS_FREMOVEXATTR = 220 + SYS_FUTEX = 221 + SYS_SCHED_SETAFFINITY = 222 + SYS_SCHED_GETAFFINITY = 223 + SYS_TUXCALL = 225 + SYS_SENDFILE64 = 226 + SYS_IO_SETUP = 227 + SYS_IO_DESTROY = 228 + SYS_IO_GETEVENTS = 229 + SYS_IO_SUBMIT = 230 + SYS_IO_CANCEL = 231 + SYS_SET_TID_ADDRESS = 232 + SYS_FADVISE64 = 233 + SYS_EXIT_GROUP = 234 + SYS_LOOKUP_DCOOKIE = 235 + SYS_EPOLL_CREATE = 236 + SYS_EPOLL_CTL = 237 + SYS_EPOLL_WAIT = 238 + SYS_REMAP_FILE_PAGES = 239 + SYS_TIMER_CREATE = 240 + SYS_TIMER_SETTIME = 241 + SYS_TIMER_GETTIME = 242 + SYS_TIMER_GETOVERRUN = 243 + SYS_TIMER_DELETE = 244 + SYS_CLOCK_SETTIME = 245 + SYS_CLOCK_GETTIME = 246 + SYS_CLOCK_GETRES = 247 + SYS_CLOCK_NANOSLEEP = 248 + SYS_SWAPCONTEXT = 249 + SYS_TGKILL = 250 + SYS_UTIMES = 251 + SYS_STATFS64 = 252 + SYS_FSTATFS64 = 253 + SYS_FADVISE64_64 = 254 + SYS_RTAS = 255 + SYS_SYS_DEBUG_SETCONTEXT = 256 + SYS_MIGRATE_PAGES = 258 + SYS_MBIND = 259 + SYS_GET_MEMPOLICY = 260 + SYS_SET_MEMPOLICY = 261 + SYS_MQ_OPEN = 262 + SYS_MQ_UNLINK = 263 + SYS_MQ_TIMEDSEND = 264 + SYS_MQ_TIMEDRECEIVE = 265 + SYS_MQ_NOTIFY = 266 + SYS_MQ_GETSETATTR = 267 + SYS_KEXEC_LOAD = 268 + SYS_ADD_KEY = 269 + SYS_REQUEST_KEY = 270 + SYS_KEYCTL = 271 + SYS_WAITID = 272 + SYS_IOPRIO_SET = 273 + SYS_IOPRIO_GET = 274 + SYS_INOTIFY_INIT = 275 + SYS_INOTIFY_ADD_WATCH = 276 + SYS_INOTIFY_RM_WATCH = 277 + SYS_SPU_RUN = 278 + SYS_SPU_CREATE = 279 + SYS_PSELECT6 = 280 + SYS_PPOLL = 281 + SYS_UNSHARE = 282 + SYS_SPLICE = 283 + SYS_TEE = 284 + SYS_VMSPLICE = 285 + SYS_OPENAT = 286 + SYS_MKDIRAT = 287 + SYS_MKNODAT = 288 + SYS_FCHOWNAT = 289 + SYS_FUTIMESAT = 290 + SYS_FSTATAT64 = 291 + SYS_UNLINKAT = 292 + SYS_RENAMEAT = 293 + SYS_LINKAT = 294 + SYS_SYMLINKAT = 295 + SYS_READLINKAT = 296 + SYS_FCHMODAT = 297 + SYS_FACCESSAT = 298 + SYS_GET_ROBUST_LIST = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_MOVE_PAGES = 301 + SYS_GETCPU = 302 + SYS_EPOLL_PWAIT = 303 + SYS_UTIMENSAT = 304 + SYS_SIGNALFD = 305 + SYS_TIMERFD_CREATE = 306 + SYS_EVENTFD = 307 + SYS_SYNC_FILE_RANGE2 = 308 + SYS_FALLOCATE = 309 + SYS_SUBPAGE_PROT = 310 + SYS_TIMERFD_SETTIME = 311 + SYS_TIMERFD_GETTIME = 312 + SYS_SIGNALFD4 = 313 + SYS_EVENTFD2 = 314 + SYS_EPOLL_CREATE1 = 315 + SYS_DUP3 = 316 + SYS_PIPE2 = 317 + SYS_INOTIFY_INIT1 = 318 + SYS_PERF_EVENT_OPEN = 319 + SYS_PREADV = 320 + SYS_PWRITEV = 321 + SYS_RT_TGSIGQUEUEINFO = 322 + SYS_FANOTIFY_INIT = 323 + SYS_FANOTIFY_MARK = 324 + SYS_PRLIMIT64 = 325 + SYS_SOCKET = 326 + SYS_BIND = 327 + SYS_CONNECT = 328 + SYS_LISTEN = 329 + SYS_ACCEPT = 330 + SYS_GETSOCKNAME = 331 + SYS_GETPEERNAME = 332 + SYS_SOCKETPAIR = 333 + SYS_SEND = 334 + SYS_SENDTO = 335 + SYS_RECV = 336 + SYS_RECVFROM = 337 + SYS_SHUTDOWN = 338 + SYS_SETSOCKOPT = 339 + SYS_GETSOCKOPT = 340 + SYS_SENDMSG = 341 + SYS_RECVMSG = 342 + SYS_RECVMMSG = 343 + SYS_ACCEPT4 = 344 + SYS_NAME_TO_HANDLE_AT = 345 + SYS_OPEN_BY_HANDLE_AT = 346 + SYS_CLOCK_ADJTIME = 347 + SYS_SYNCFS = 348 + SYS_SENDMMSG = 349 + SYS_SETNS = 350 + SYS_PROCESS_VM_READV = 351 + SYS_PROCESS_VM_WRITEV = 352 + SYS_FINIT_MODULE = 353 + SYS_KCMP = 354 + SYS_SCHED_SETATTR = 355 + SYS_SCHED_GETATTR = 356 + SYS_RENAMEAT2 = 357 + SYS_SECCOMP = 358 + SYS_GETRANDOM = 359 + SYS_MEMFD_CREATE = 360 + SYS_BPF = 361 + SYS_EXECVEAT = 362 + SYS_SWITCH_ENDIAN = 363 + SYS_USERFAULTFD = 364 + SYS_MEMBARRIER = 365 + SYS_MLOCK2 = 378 + SYS_COPY_FILE_RANGE = 379 + SYS_PREADV2 = 380 + SYS_PWRITEV2 = 381 + SYS_KEXEC_FILE_LOAD = 382 + SYS_STATX = 383 + SYS_PKEY_ALLOC = 384 + SYS_PKEY_FREE = 385 + SYS_PKEY_MPROTECT = 386 + SYS_RSEQ = 387 + SYS_IO_PGETEVENTS = 388 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_CLOCK_GETTIME64 = 403 + SYS_CLOCK_SETTIME64 = 404 + SYS_CLOCK_ADJTIME64 = 405 + SYS_CLOCK_GETRES_TIME64 = 406 + SYS_CLOCK_NANOSLEEP_TIME64 = 407 + SYS_TIMER_GETTIME64 = 408 + SYS_TIMER_SETTIME64 = 409 + SYS_TIMERFD_GETTIME64 = 410 + SYS_TIMERFD_SETTIME64 = 411 + SYS_UTIMENSAT_TIME64 = 412 + SYS_PSELECT6_TIME64 = 413 + SYS_PPOLL_TIME64 = 414 + SYS_IO_PGETEVENTS_TIME64 = 416 + SYS_RECVMMSG_TIME64 = 417 + SYS_MQ_TIMEDSEND_TIME64 = 418 + SYS_MQ_TIMEDRECEIVE_TIME64 = 419 + SYS_SEMTIMEDOP_TIME64 = 420 + SYS_RT_SIGTIMEDWAIT_TIME64 = 421 + SYS_FUTEX_TIME64 = 422 + SYS_SCHED_RR_GET_INTERVAL_TIME64 = 423 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 52e3da6..e35a710 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -1,398 +1,429 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/ppc64/include /tmp/ppc64/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64,linux +//go:build ppc64 && linux package unix const ( - SYS_RESTART_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAITPID = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECVE = 11 - SYS_CHDIR = 12 - SYS_TIME = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LCHOWN = 16 - SYS_BREAK = 17 - SYS_OLDSTAT = 18 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_MOUNT = 21 - SYS_UMOUNT = 22 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_STIME = 25 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_OLDFSTAT = 28 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_STTY = 31 - SYS_GTTY = 32 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_FTIME = 35 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_RENAME = 38 - SYS_MKDIR = 39 - SYS_RMDIR = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_PROF = 44 - SYS_BRK = 45 - SYS_SETGID = 46 - SYS_GETGID = 47 - SYS_SIGNAL = 48 - SYS_GETEUID = 49 - SYS_GETEGID = 50 - SYS_ACCT = 51 - SYS_UMOUNT2 = 52 - SYS_LOCK = 53 - SYS_IOCTL = 54 - SYS_FCNTL = 55 - SYS_MPX = 56 - SYS_SETPGID = 57 - SYS_ULIMIT = 58 - SYS_OLDOLDUNAME = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_USTAT = 62 - SYS_DUP2 = 63 - SYS_GETPPID = 64 - SYS_GETPGRP = 65 - SYS_SETSID = 66 - SYS_SIGACTION = 67 - SYS_SGETMASK = 68 - SYS_SSETMASK = 69 - SYS_SETREUID = 70 - SYS_SETREGID = 71 - SYS_SIGSUSPEND = 72 - SYS_SIGPENDING = 73 - SYS_SETHOSTNAME = 74 - SYS_SETRLIMIT = 75 - SYS_GETRLIMIT = 76 - SYS_GETRUSAGE = 77 - SYS_GETTIMEOFDAY = 78 - SYS_SETTIMEOFDAY = 79 - SYS_GETGROUPS = 80 - SYS_SETGROUPS = 81 - SYS_SELECT = 82 - SYS_SYMLINK = 83 - SYS_OLDLSTAT = 84 - SYS_READLINK = 85 - SYS_USELIB = 86 - SYS_SWAPON = 87 - SYS_REBOOT = 88 - SYS_READDIR = 89 - SYS_MMAP = 90 - SYS_MUNMAP = 91 - SYS_TRUNCATE = 92 - SYS_FTRUNCATE = 93 - SYS_FCHMOD = 94 - SYS_FCHOWN = 95 - SYS_GETPRIORITY = 96 - SYS_SETPRIORITY = 97 - SYS_PROFIL = 98 - SYS_STATFS = 99 - SYS_FSTATFS = 100 - SYS_IOPERM = 101 - SYS_SOCKETCALL = 102 - SYS_SYSLOG = 103 - SYS_SETITIMER = 104 - SYS_GETITIMER = 105 - SYS_STAT = 106 - SYS_LSTAT = 107 - SYS_FSTAT = 108 - SYS_OLDUNAME = 109 - SYS_IOPL = 110 - SYS_VHANGUP = 111 - SYS_IDLE = 112 - SYS_VM86 = 113 - SYS_WAIT4 = 114 - SYS_SWAPOFF = 115 - SYS_SYSINFO = 116 - SYS_IPC = 117 - SYS_FSYNC = 118 - SYS_SIGRETURN = 119 - SYS_CLONE = 120 - SYS_SETDOMAINNAME = 121 - SYS_UNAME = 122 - SYS_MODIFY_LDT = 123 - SYS_ADJTIMEX = 124 - SYS_MPROTECT = 125 - SYS_SIGPROCMASK = 126 - SYS_CREATE_MODULE = 127 - SYS_INIT_MODULE = 128 - SYS_DELETE_MODULE = 129 - SYS_GET_KERNEL_SYMS = 130 - SYS_QUOTACTL = 131 - SYS_GETPGID = 132 - SYS_FCHDIR = 133 - SYS_BDFLUSH = 134 - SYS_SYSFS = 135 - SYS_PERSONALITY = 136 - SYS_AFS_SYSCALL = 137 - SYS_SETFSUID = 138 - SYS_SETFSGID = 139 - SYS__LLSEEK = 140 - SYS_GETDENTS = 141 - SYS__NEWSELECT = 142 - SYS_FLOCK = 143 - SYS_MSYNC = 144 - SYS_READV = 145 - SYS_WRITEV = 146 - SYS_GETSID = 147 - SYS_FDATASYNC = 148 - SYS__SYSCTL = 149 - SYS_MLOCK = 150 - SYS_MUNLOCK = 151 - SYS_MLOCKALL = 152 - SYS_MUNLOCKALL = 153 - SYS_SCHED_SETPARAM = 154 - SYS_SCHED_GETPARAM = 155 - SYS_SCHED_SETSCHEDULER = 156 - SYS_SCHED_GETSCHEDULER = 157 - SYS_SCHED_YIELD = 158 - SYS_SCHED_GET_PRIORITY_MAX = 159 - SYS_SCHED_GET_PRIORITY_MIN = 160 - SYS_SCHED_RR_GET_INTERVAL = 161 - SYS_NANOSLEEP = 162 - SYS_MREMAP = 163 - SYS_SETRESUID = 164 - SYS_GETRESUID = 165 - SYS_QUERY_MODULE = 166 - SYS_POLL = 167 - SYS_NFSSERVCTL = 168 - SYS_SETRESGID = 169 - SYS_GETRESGID = 170 - SYS_PRCTL = 171 - SYS_RT_SIGRETURN = 172 - SYS_RT_SIGACTION = 173 - SYS_RT_SIGPROCMASK = 174 - SYS_RT_SIGPENDING = 175 - SYS_RT_SIGTIMEDWAIT = 176 - SYS_RT_SIGQUEUEINFO = 177 - SYS_RT_SIGSUSPEND = 178 - SYS_PREAD64 = 179 - SYS_PWRITE64 = 180 - SYS_CHOWN = 181 - SYS_GETCWD = 182 - SYS_CAPGET = 183 - SYS_CAPSET = 184 - SYS_SIGALTSTACK = 185 - SYS_SENDFILE = 186 - SYS_GETPMSG = 187 - SYS_PUTPMSG = 188 - SYS_VFORK = 189 - SYS_UGETRLIMIT = 190 - SYS_READAHEAD = 191 - SYS_PCICONFIG_READ = 198 - SYS_PCICONFIG_WRITE = 199 - SYS_PCICONFIG_IOBASE = 200 - SYS_MULTIPLEXER = 201 - SYS_GETDENTS64 = 202 - SYS_PIVOT_ROOT = 203 - SYS_MADVISE = 205 - SYS_MINCORE = 206 - SYS_GETTID = 207 - SYS_TKILL = 208 - SYS_SETXATTR = 209 - SYS_LSETXATTR = 210 - SYS_FSETXATTR = 211 - SYS_GETXATTR = 212 - SYS_LGETXATTR = 213 - SYS_FGETXATTR = 214 - SYS_LISTXATTR = 215 - SYS_LLISTXATTR = 216 - SYS_FLISTXATTR = 217 - SYS_REMOVEXATTR = 218 - SYS_LREMOVEXATTR = 219 - SYS_FREMOVEXATTR = 220 - SYS_FUTEX = 221 - SYS_SCHED_SETAFFINITY = 222 - SYS_SCHED_GETAFFINITY = 223 - SYS_TUXCALL = 225 - SYS_IO_SETUP = 227 - SYS_IO_DESTROY = 228 - SYS_IO_GETEVENTS = 229 - SYS_IO_SUBMIT = 230 - SYS_IO_CANCEL = 231 - SYS_SET_TID_ADDRESS = 232 - SYS_FADVISE64 = 233 - SYS_EXIT_GROUP = 234 - SYS_LOOKUP_DCOOKIE = 235 - SYS_EPOLL_CREATE = 236 - SYS_EPOLL_CTL = 237 - SYS_EPOLL_WAIT = 238 - SYS_REMAP_FILE_PAGES = 239 - SYS_TIMER_CREATE = 240 - SYS_TIMER_SETTIME = 241 - SYS_TIMER_GETTIME = 242 - SYS_TIMER_GETOVERRUN = 243 - SYS_TIMER_DELETE = 244 - SYS_CLOCK_SETTIME = 245 - SYS_CLOCK_GETTIME = 246 - SYS_CLOCK_GETRES = 247 - SYS_CLOCK_NANOSLEEP = 248 - SYS_SWAPCONTEXT = 249 - SYS_TGKILL = 250 - SYS_UTIMES = 251 - SYS_STATFS64 = 252 - SYS_FSTATFS64 = 253 - SYS_RTAS = 255 - SYS_SYS_DEBUG_SETCONTEXT = 256 - SYS_MIGRATE_PAGES = 258 - SYS_MBIND = 259 - SYS_GET_MEMPOLICY = 260 - SYS_SET_MEMPOLICY = 261 - SYS_MQ_OPEN = 262 - SYS_MQ_UNLINK = 263 - SYS_MQ_TIMEDSEND = 264 - SYS_MQ_TIMEDRECEIVE = 265 - SYS_MQ_NOTIFY = 266 - SYS_MQ_GETSETATTR = 267 - SYS_KEXEC_LOAD = 268 - SYS_ADD_KEY = 269 - SYS_REQUEST_KEY = 270 - SYS_KEYCTL = 271 - SYS_WAITID = 272 - SYS_IOPRIO_SET = 273 - SYS_IOPRIO_GET = 274 - SYS_INOTIFY_INIT = 275 - SYS_INOTIFY_ADD_WATCH = 276 - SYS_INOTIFY_RM_WATCH = 277 - SYS_SPU_RUN = 278 - SYS_SPU_CREATE = 279 - SYS_PSELECT6 = 280 - SYS_PPOLL = 281 - SYS_UNSHARE = 282 - SYS_SPLICE = 283 - SYS_TEE = 284 - SYS_VMSPLICE = 285 - SYS_OPENAT = 286 - SYS_MKDIRAT = 287 - SYS_MKNODAT = 288 - SYS_FCHOWNAT = 289 - SYS_FUTIMESAT = 290 - SYS_NEWFSTATAT = 291 - SYS_UNLINKAT = 292 - SYS_RENAMEAT = 293 - SYS_LINKAT = 294 - SYS_SYMLINKAT = 295 - SYS_READLINKAT = 296 - SYS_FCHMODAT = 297 - SYS_FACCESSAT = 298 - SYS_GET_ROBUST_LIST = 299 - SYS_SET_ROBUST_LIST = 300 - SYS_MOVE_PAGES = 301 - SYS_GETCPU = 302 - SYS_EPOLL_PWAIT = 303 - SYS_UTIMENSAT = 304 - SYS_SIGNALFD = 305 - SYS_TIMERFD_CREATE = 306 - SYS_EVENTFD = 307 - SYS_SYNC_FILE_RANGE2 = 308 - SYS_FALLOCATE = 309 - SYS_SUBPAGE_PROT = 310 - SYS_TIMERFD_SETTIME = 311 - SYS_TIMERFD_GETTIME = 312 - SYS_SIGNALFD4 = 313 - SYS_EVENTFD2 = 314 - SYS_EPOLL_CREATE1 = 315 - SYS_DUP3 = 316 - SYS_PIPE2 = 317 - SYS_INOTIFY_INIT1 = 318 - SYS_PERF_EVENT_OPEN = 319 - SYS_PREADV = 320 - SYS_PWRITEV = 321 - SYS_RT_TGSIGQUEUEINFO = 322 - SYS_FANOTIFY_INIT = 323 - SYS_FANOTIFY_MARK = 324 - SYS_PRLIMIT64 = 325 - SYS_SOCKET = 326 - SYS_BIND = 327 - SYS_CONNECT = 328 - SYS_LISTEN = 329 - SYS_ACCEPT = 330 - SYS_GETSOCKNAME = 331 - SYS_GETPEERNAME = 332 - SYS_SOCKETPAIR = 333 - SYS_SEND = 334 - SYS_SENDTO = 335 - SYS_RECV = 336 - SYS_RECVFROM = 337 - SYS_SHUTDOWN = 338 - SYS_SETSOCKOPT = 339 - SYS_GETSOCKOPT = 340 - SYS_SENDMSG = 341 - SYS_RECVMSG = 342 - SYS_RECVMMSG = 343 - SYS_ACCEPT4 = 344 - SYS_NAME_TO_HANDLE_AT = 345 - SYS_OPEN_BY_HANDLE_AT = 346 - SYS_CLOCK_ADJTIME = 347 - SYS_SYNCFS = 348 - SYS_SENDMMSG = 349 - SYS_SETNS = 350 - SYS_PROCESS_VM_READV = 351 - SYS_PROCESS_VM_WRITEV = 352 - SYS_FINIT_MODULE = 353 - SYS_KCMP = 354 - SYS_SCHED_SETATTR = 355 - SYS_SCHED_GETATTR = 356 - SYS_RENAMEAT2 = 357 - SYS_SECCOMP = 358 - SYS_GETRANDOM = 359 - SYS_MEMFD_CREATE = 360 - SYS_BPF = 361 - SYS_EXECVEAT = 362 - SYS_SWITCH_ENDIAN = 363 - SYS_USERFAULTFD = 364 - SYS_MEMBARRIER = 365 - SYS_MLOCK2 = 378 - SYS_COPY_FILE_RANGE = 379 - SYS_PREADV2 = 380 - SYS_PWRITEV2 = 381 - SYS_KEXEC_FILE_LOAD = 382 - SYS_STATX = 383 - SYS_PKEY_ALLOC = 384 - SYS_PKEY_FREE = 385 - SYS_PKEY_MPROTECT = 386 - SYS_RSEQ = 387 - SYS_IO_PGETEVENTS = 388 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAITPID = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_TIME = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BREAK = 17 + SYS_OLDSTAT = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_STIME = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_OLDFSTAT = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_STTY = 31 + SYS_GTTY = 32 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_FTIME = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_PROF = 44 + SYS_BRK = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_LOCK = 53 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_MPX = 56 + SYS_SETPGID = 57 + SYS_ULIMIT = 58 + SYS_OLDOLDUNAME = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SGETMASK = 68 + SYS_SSETMASK = 69 + SYS_SETREUID = 70 + SYS_SETREGID = 71 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRLIMIT = 76 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_GETGROUPS = 80 + SYS_SETGROUPS = 81 + SYS_SELECT = 82 + SYS_SYMLINK = 83 + SYS_OLDLSTAT = 84 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_FCHOWN = 95 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_PROFIL = 98 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_IOPERM = 101 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_OLDUNAME = 109 + SYS_IOPL = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_VM86 = 113 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_MODIFY_LDT = 123 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_SETFSUID = 138 + SYS_SETFSGID = 139 + SYS__LLSEEK = 140 + SYS_GETDENTS = 141 + SYS__NEWSELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_SETRESUID = 164 + SYS_GETRESUID = 165 + SYS_QUERY_MODULE = 166 + SYS_POLL = 167 + SYS_NFSSERVCTL = 168 + SYS_SETRESGID = 169 + SYS_GETRESGID = 170 + SYS_PRCTL = 171 + SYS_RT_SIGRETURN = 172 + SYS_RT_SIGACTION = 173 + SYS_RT_SIGPROCMASK = 174 + SYS_RT_SIGPENDING = 175 + SYS_RT_SIGTIMEDWAIT = 176 + SYS_RT_SIGQUEUEINFO = 177 + SYS_RT_SIGSUSPEND = 178 + SYS_PREAD64 = 179 + SYS_PWRITE64 = 180 + SYS_CHOWN = 181 + SYS_GETCWD = 182 + SYS_CAPGET = 183 + SYS_CAPSET = 184 + SYS_SIGALTSTACK = 185 + SYS_SENDFILE = 186 + SYS_GETPMSG = 187 + SYS_PUTPMSG = 188 + SYS_VFORK = 189 + SYS_UGETRLIMIT = 190 + SYS_READAHEAD = 191 + SYS_PCICONFIG_READ = 198 + SYS_PCICONFIG_WRITE = 199 + SYS_PCICONFIG_IOBASE = 200 + SYS_MULTIPLEXER = 201 + SYS_GETDENTS64 = 202 + SYS_PIVOT_ROOT = 203 + SYS_MADVISE = 205 + SYS_MINCORE = 206 + SYS_GETTID = 207 + SYS_TKILL = 208 + SYS_SETXATTR = 209 + SYS_LSETXATTR = 210 + SYS_FSETXATTR = 211 + SYS_GETXATTR = 212 + SYS_LGETXATTR = 213 + SYS_FGETXATTR = 214 + SYS_LISTXATTR = 215 + SYS_LLISTXATTR = 216 + SYS_FLISTXATTR = 217 + SYS_REMOVEXATTR = 218 + SYS_LREMOVEXATTR = 219 + SYS_FREMOVEXATTR = 220 + SYS_FUTEX = 221 + SYS_SCHED_SETAFFINITY = 222 + SYS_SCHED_GETAFFINITY = 223 + SYS_TUXCALL = 225 + SYS_IO_SETUP = 227 + SYS_IO_DESTROY = 228 + SYS_IO_GETEVENTS = 229 + SYS_IO_SUBMIT = 230 + SYS_IO_CANCEL = 231 + SYS_SET_TID_ADDRESS = 232 + SYS_FADVISE64 = 233 + SYS_EXIT_GROUP = 234 + SYS_LOOKUP_DCOOKIE = 235 + SYS_EPOLL_CREATE = 236 + SYS_EPOLL_CTL = 237 + SYS_EPOLL_WAIT = 238 + SYS_REMAP_FILE_PAGES = 239 + SYS_TIMER_CREATE = 240 + SYS_TIMER_SETTIME = 241 + SYS_TIMER_GETTIME = 242 + SYS_TIMER_GETOVERRUN = 243 + SYS_TIMER_DELETE = 244 + SYS_CLOCK_SETTIME = 245 + SYS_CLOCK_GETTIME = 246 + SYS_CLOCK_GETRES = 247 + SYS_CLOCK_NANOSLEEP = 248 + SYS_SWAPCONTEXT = 249 + SYS_TGKILL = 250 + SYS_UTIMES = 251 + SYS_STATFS64 = 252 + SYS_FSTATFS64 = 253 + SYS_RTAS = 255 + SYS_SYS_DEBUG_SETCONTEXT = 256 + SYS_MIGRATE_PAGES = 258 + SYS_MBIND = 259 + SYS_GET_MEMPOLICY = 260 + SYS_SET_MEMPOLICY = 261 + SYS_MQ_OPEN = 262 + SYS_MQ_UNLINK = 263 + SYS_MQ_TIMEDSEND = 264 + SYS_MQ_TIMEDRECEIVE = 265 + SYS_MQ_NOTIFY = 266 + SYS_MQ_GETSETATTR = 267 + SYS_KEXEC_LOAD = 268 + SYS_ADD_KEY = 269 + SYS_REQUEST_KEY = 270 + SYS_KEYCTL = 271 + SYS_WAITID = 272 + SYS_IOPRIO_SET = 273 + SYS_IOPRIO_GET = 274 + SYS_INOTIFY_INIT = 275 + SYS_INOTIFY_ADD_WATCH = 276 + SYS_INOTIFY_RM_WATCH = 277 + SYS_SPU_RUN = 278 + SYS_SPU_CREATE = 279 + SYS_PSELECT6 = 280 + SYS_PPOLL = 281 + SYS_UNSHARE = 282 + SYS_SPLICE = 283 + SYS_TEE = 284 + SYS_VMSPLICE = 285 + SYS_OPENAT = 286 + SYS_MKDIRAT = 287 + SYS_MKNODAT = 288 + SYS_FCHOWNAT = 289 + SYS_FUTIMESAT = 290 + SYS_NEWFSTATAT = 291 + SYS_UNLINKAT = 292 + SYS_RENAMEAT = 293 + SYS_LINKAT = 294 + SYS_SYMLINKAT = 295 + SYS_READLINKAT = 296 + SYS_FCHMODAT = 297 + SYS_FACCESSAT = 298 + SYS_GET_ROBUST_LIST = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_MOVE_PAGES = 301 + SYS_GETCPU = 302 + SYS_EPOLL_PWAIT = 303 + SYS_UTIMENSAT = 304 + SYS_SIGNALFD = 305 + SYS_TIMERFD_CREATE = 306 + SYS_EVENTFD = 307 + SYS_SYNC_FILE_RANGE2 = 308 + SYS_FALLOCATE = 309 + SYS_SUBPAGE_PROT = 310 + SYS_TIMERFD_SETTIME = 311 + SYS_TIMERFD_GETTIME = 312 + SYS_SIGNALFD4 = 313 + SYS_EVENTFD2 = 314 + SYS_EPOLL_CREATE1 = 315 + SYS_DUP3 = 316 + SYS_PIPE2 = 317 + SYS_INOTIFY_INIT1 = 318 + SYS_PERF_EVENT_OPEN = 319 + SYS_PREADV = 320 + SYS_PWRITEV = 321 + SYS_RT_TGSIGQUEUEINFO = 322 + SYS_FANOTIFY_INIT = 323 + SYS_FANOTIFY_MARK = 324 + SYS_PRLIMIT64 = 325 + SYS_SOCKET = 326 + SYS_BIND = 327 + SYS_CONNECT = 328 + SYS_LISTEN = 329 + SYS_ACCEPT = 330 + SYS_GETSOCKNAME = 331 + SYS_GETPEERNAME = 332 + SYS_SOCKETPAIR = 333 + SYS_SEND = 334 + SYS_SENDTO = 335 + SYS_RECV = 336 + SYS_RECVFROM = 337 + SYS_SHUTDOWN = 338 + SYS_SETSOCKOPT = 339 + SYS_GETSOCKOPT = 340 + SYS_SENDMSG = 341 + SYS_RECVMSG = 342 + SYS_RECVMMSG = 343 + SYS_ACCEPT4 = 344 + SYS_NAME_TO_HANDLE_AT = 345 + SYS_OPEN_BY_HANDLE_AT = 346 + SYS_CLOCK_ADJTIME = 347 + SYS_SYNCFS = 348 + SYS_SENDMMSG = 349 + SYS_SETNS = 350 + SYS_PROCESS_VM_READV = 351 + SYS_PROCESS_VM_WRITEV = 352 + SYS_FINIT_MODULE = 353 + SYS_KCMP = 354 + SYS_SCHED_SETATTR = 355 + SYS_SCHED_GETATTR = 356 + SYS_RENAMEAT2 = 357 + SYS_SECCOMP = 358 + SYS_GETRANDOM = 359 + SYS_MEMFD_CREATE = 360 + SYS_BPF = 361 + SYS_EXECVEAT = 362 + SYS_SWITCH_ENDIAN = 363 + SYS_USERFAULTFD = 364 + SYS_MEMBARRIER = 365 + SYS_MLOCK2 = 378 + SYS_COPY_FILE_RANGE = 379 + SYS_PREADV2 = 380 + SYS_PWRITEV2 = 381 + SYS_KEXEC_FILE_LOAD = 382 + SYS_STATX = 383 + SYS_PKEY_ALLOC = 384 + SYS_PKEY_FREE = 385 + SYS_PKEY_MPROTECT = 386 + SYS_RSEQ = 387 + SYS_IO_PGETEVENTS = 388 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 6141f90..2aea476 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -1,398 +1,429 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/ppc64le/include /tmp/ppc64le/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64le,linux +//go:build ppc64le && linux package unix const ( - SYS_RESTART_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAITPID = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECVE = 11 - SYS_CHDIR = 12 - SYS_TIME = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LCHOWN = 16 - SYS_BREAK = 17 - SYS_OLDSTAT = 18 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_MOUNT = 21 - SYS_UMOUNT = 22 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_STIME = 25 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_OLDFSTAT = 28 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_STTY = 31 - SYS_GTTY = 32 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_FTIME = 35 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_RENAME = 38 - SYS_MKDIR = 39 - SYS_RMDIR = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_PROF = 44 - SYS_BRK = 45 - SYS_SETGID = 46 - SYS_GETGID = 47 - SYS_SIGNAL = 48 - SYS_GETEUID = 49 - SYS_GETEGID = 50 - SYS_ACCT = 51 - SYS_UMOUNT2 = 52 - SYS_LOCK = 53 - SYS_IOCTL = 54 - SYS_FCNTL = 55 - SYS_MPX = 56 - SYS_SETPGID = 57 - SYS_ULIMIT = 58 - SYS_OLDOLDUNAME = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_USTAT = 62 - SYS_DUP2 = 63 - SYS_GETPPID = 64 - SYS_GETPGRP = 65 - SYS_SETSID = 66 - SYS_SIGACTION = 67 - SYS_SGETMASK = 68 - SYS_SSETMASK = 69 - SYS_SETREUID = 70 - SYS_SETREGID = 71 - SYS_SIGSUSPEND = 72 - SYS_SIGPENDING = 73 - SYS_SETHOSTNAME = 74 - SYS_SETRLIMIT = 75 - SYS_GETRLIMIT = 76 - SYS_GETRUSAGE = 77 - SYS_GETTIMEOFDAY = 78 - SYS_SETTIMEOFDAY = 79 - SYS_GETGROUPS = 80 - SYS_SETGROUPS = 81 - SYS_SELECT = 82 - SYS_SYMLINK = 83 - SYS_OLDLSTAT = 84 - SYS_READLINK = 85 - SYS_USELIB = 86 - SYS_SWAPON = 87 - SYS_REBOOT = 88 - SYS_READDIR = 89 - SYS_MMAP = 90 - SYS_MUNMAP = 91 - SYS_TRUNCATE = 92 - SYS_FTRUNCATE = 93 - SYS_FCHMOD = 94 - SYS_FCHOWN = 95 - SYS_GETPRIORITY = 96 - SYS_SETPRIORITY = 97 - SYS_PROFIL = 98 - SYS_STATFS = 99 - SYS_FSTATFS = 100 - SYS_IOPERM = 101 - SYS_SOCKETCALL = 102 - SYS_SYSLOG = 103 - SYS_SETITIMER = 104 - SYS_GETITIMER = 105 - SYS_STAT = 106 - SYS_LSTAT = 107 - SYS_FSTAT = 108 - SYS_OLDUNAME = 109 - SYS_IOPL = 110 - SYS_VHANGUP = 111 - SYS_IDLE = 112 - SYS_VM86 = 113 - SYS_WAIT4 = 114 - SYS_SWAPOFF = 115 - SYS_SYSINFO = 116 - SYS_IPC = 117 - SYS_FSYNC = 118 - SYS_SIGRETURN = 119 - SYS_CLONE = 120 - SYS_SETDOMAINNAME = 121 - SYS_UNAME = 122 - SYS_MODIFY_LDT = 123 - SYS_ADJTIMEX = 124 - SYS_MPROTECT = 125 - SYS_SIGPROCMASK = 126 - SYS_CREATE_MODULE = 127 - SYS_INIT_MODULE = 128 - SYS_DELETE_MODULE = 129 - SYS_GET_KERNEL_SYMS = 130 - SYS_QUOTACTL = 131 - SYS_GETPGID = 132 - SYS_FCHDIR = 133 - SYS_BDFLUSH = 134 - SYS_SYSFS = 135 - SYS_PERSONALITY = 136 - SYS_AFS_SYSCALL = 137 - SYS_SETFSUID = 138 - SYS_SETFSGID = 139 - SYS__LLSEEK = 140 - SYS_GETDENTS = 141 - SYS__NEWSELECT = 142 - SYS_FLOCK = 143 - SYS_MSYNC = 144 - SYS_READV = 145 - SYS_WRITEV = 146 - SYS_GETSID = 147 - SYS_FDATASYNC = 148 - SYS__SYSCTL = 149 - SYS_MLOCK = 150 - SYS_MUNLOCK = 151 - SYS_MLOCKALL = 152 - SYS_MUNLOCKALL = 153 - SYS_SCHED_SETPARAM = 154 - SYS_SCHED_GETPARAM = 155 - SYS_SCHED_SETSCHEDULER = 156 - SYS_SCHED_GETSCHEDULER = 157 - SYS_SCHED_YIELD = 158 - SYS_SCHED_GET_PRIORITY_MAX = 159 - SYS_SCHED_GET_PRIORITY_MIN = 160 - SYS_SCHED_RR_GET_INTERVAL = 161 - SYS_NANOSLEEP = 162 - SYS_MREMAP = 163 - SYS_SETRESUID = 164 - SYS_GETRESUID = 165 - SYS_QUERY_MODULE = 166 - SYS_POLL = 167 - SYS_NFSSERVCTL = 168 - SYS_SETRESGID = 169 - SYS_GETRESGID = 170 - SYS_PRCTL = 171 - SYS_RT_SIGRETURN = 172 - SYS_RT_SIGACTION = 173 - SYS_RT_SIGPROCMASK = 174 - SYS_RT_SIGPENDING = 175 - SYS_RT_SIGTIMEDWAIT = 176 - SYS_RT_SIGQUEUEINFO = 177 - SYS_RT_SIGSUSPEND = 178 - SYS_PREAD64 = 179 - SYS_PWRITE64 = 180 - SYS_CHOWN = 181 - SYS_GETCWD = 182 - SYS_CAPGET = 183 - SYS_CAPSET = 184 - SYS_SIGALTSTACK = 185 - SYS_SENDFILE = 186 - SYS_GETPMSG = 187 - SYS_PUTPMSG = 188 - SYS_VFORK = 189 - SYS_UGETRLIMIT = 190 - SYS_READAHEAD = 191 - SYS_PCICONFIG_READ = 198 - SYS_PCICONFIG_WRITE = 199 - SYS_PCICONFIG_IOBASE = 200 - SYS_MULTIPLEXER = 201 - SYS_GETDENTS64 = 202 - SYS_PIVOT_ROOT = 203 - SYS_MADVISE = 205 - SYS_MINCORE = 206 - SYS_GETTID = 207 - SYS_TKILL = 208 - SYS_SETXATTR = 209 - SYS_LSETXATTR = 210 - SYS_FSETXATTR = 211 - SYS_GETXATTR = 212 - SYS_LGETXATTR = 213 - SYS_FGETXATTR = 214 - SYS_LISTXATTR = 215 - SYS_LLISTXATTR = 216 - SYS_FLISTXATTR = 217 - SYS_REMOVEXATTR = 218 - SYS_LREMOVEXATTR = 219 - SYS_FREMOVEXATTR = 220 - SYS_FUTEX = 221 - SYS_SCHED_SETAFFINITY = 222 - SYS_SCHED_GETAFFINITY = 223 - SYS_TUXCALL = 225 - SYS_IO_SETUP = 227 - SYS_IO_DESTROY = 228 - SYS_IO_GETEVENTS = 229 - SYS_IO_SUBMIT = 230 - SYS_IO_CANCEL = 231 - SYS_SET_TID_ADDRESS = 232 - SYS_FADVISE64 = 233 - SYS_EXIT_GROUP = 234 - SYS_LOOKUP_DCOOKIE = 235 - SYS_EPOLL_CREATE = 236 - SYS_EPOLL_CTL = 237 - SYS_EPOLL_WAIT = 238 - SYS_REMAP_FILE_PAGES = 239 - SYS_TIMER_CREATE = 240 - SYS_TIMER_SETTIME = 241 - SYS_TIMER_GETTIME = 242 - SYS_TIMER_GETOVERRUN = 243 - SYS_TIMER_DELETE = 244 - SYS_CLOCK_SETTIME = 245 - SYS_CLOCK_GETTIME = 246 - SYS_CLOCK_GETRES = 247 - SYS_CLOCK_NANOSLEEP = 248 - SYS_SWAPCONTEXT = 249 - SYS_TGKILL = 250 - SYS_UTIMES = 251 - SYS_STATFS64 = 252 - SYS_FSTATFS64 = 253 - SYS_RTAS = 255 - SYS_SYS_DEBUG_SETCONTEXT = 256 - SYS_MIGRATE_PAGES = 258 - SYS_MBIND = 259 - SYS_GET_MEMPOLICY = 260 - SYS_SET_MEMPOLICY = 261 - SYS_MQ_OPEN = 262 - SYS_MQ_UNLINK = 263 - SYS_MQ_TIMEDSEND = 264 - SYS_MQ_TIMEDRECEIVE = 265 - SYS_MQ_NOTIFY = 266 - SYS_MQ_GETSETATTR = 267 - SYS_KEXEC_LOAD = 268 - SYS_ADD_KEY = 269 - SYS_REQUEST_KEY = 270 - SYS_KEYCTL = 271 - SYS_WAITID = 272 - SYS_IOPRIO_SET = 273 - SYS_IOPRIO_GET = 274 - SYS_INOTIFY_INIT = 275 - SYS_INOTIFY_ADD_WATCH = 276 - SYS_INOTIFY_RM_WATCH = 277 - SYS_SPU_RUN = 278 - SYS_SPU_CREATE = 279 - SYS_PSELECT6 = 280 - SYS_PPOLL = 281 - SYS_UNSHARE = 282 - SYS_SPLICE = 283 - SYS_TEE = 284 - SYS_VMSPLICE = 285 - SYS_OPENAT = 286 - SYS_MKDIRAT = 287 - SYS_MKNODAT = 288 - SYS_FCHOWNAT = 289 - SYS_FUTIMESAT = 290 - SYS_NEWFSTATAT = 291 - SYS_UNLINKAT = 292 - SYS_RENAMEAT = 293 - SYS_LINKAT = 294 - SYS_SYMLINKAT = 295 - SYS_READLINKAT = 296 - SYS_FCHMODAT = 297 - SYS_FACCESSAT = 298 - SYS_GET_ROBUST_LIST = 299 - SYS_SET_ROBUST_LIST = 300 - SYS_MOVE_PAGES = 301 - SYS_GETCPU = 302 - SYS_EPOLL_PWAIT = 303 - SYS_UTIMENSAT = 304 - SYS_SIGNALFD = 305 - SYS_TIMERFD_CREATE = 306 - SYS_EVENTFD = 307 - SYS_SYNC_FILE_RANGE2 = 308 - SYS_FALLOCATE = 309 - SYS_SUBPAGE_PROT = 310 - SYS_TIMERFD_SETTIME = 311 - SYS_TIMERFD_GETTIME = 312 - SYS_SIGNALFD4 = 313 - SYS_EVENTFD2 = 314 - SYS_EPOLL_CREATE1 = 315 - SYS_DUP3 = 316 - SYS_PIPE2 = 317 - SYS_INOTIFY_INIT1 = 318 - SYS_PERF_EVENT_OPEN = 319 - SYS_PREADV = 320 - SYS_PWRITEV = 321 - SYS_RT_TGSIGQUEUEINFO = 322 - SYS_FANOTIFY_INIT = 323 - SYS_FANOTIFY_MARK = 324 - SYS_PRLIMIT64 = 325 - SYS_SOCKET = 326 - SYS_BIND = 327 - SYS_CONNECT = 328 - SYS_LISTEN = 329 - SYS_ACCEPT = 330 - SYS_GETSOCKNAME = 331 - SYS_GETPEERNAME = 332 - SYS_SOCKETPAIR = 333 - SYS_SEND = 334 - SYS_SENDTO = 335 - SYS_RECV = 336 - SYS_RECVFROM = 337 - SYS_SHUTDOWN = 338 - SYS_SETSOCKOPT = 339 - SYS_GETSOCKOPT = 340 - SYS_SENDMSG = 341 - SYS_RECVMSG = 342 - SYS_RECVMMSG = 343 - SYS_ACCEPT4 = 344 - SYS_NAME_TO_HANDLE_AT = 345 - SYS_OPEN_BY_HANDLE_AT = 346 - SYS_CLOCK_ADJTIME = 347 - SYS_SYNCFS = 348 - SYS_SENDMMSG = 349 - SYS_SETNS = 350 - SYS_PROCESS_VM_READV = 351 - SYS_PROCESS_VM_WRITEV = 352 - SYS_FINIT_MODULE = 353 - SYS_KCMP = 354 - SYS_SCHED_SETATTR = 355 - SYS_SCHED_GETATTR = 356 - SYS_RENAMEAT2 = 357 - SYS_SECCOMP = 358 - SYS_GETRANDOM = 359 - SYS_MEMFD_CREATE = 360 - SYS_BPF = 361 - SYS_EXECVEAT = 362 - SYS_SWITCH_ENDIAN = 363 - SYS_USERFAULTFD = 364 - SYS_MEMBARRIER = 365 - SYS_MLOCK2 = 378 - SYS_COPY_FILE_RANGE = 379 - SYS_PREADV2 = 380 - SYS_PWRITEV2 = 381 - SYS_KEXEC_FILE_LOAD = 382 - SYS_STATX = 383 - SYS_PKEY_ALLOC = 384 - SYS_PKEY_FREE = 385 - SYS_PKEY_MPROTECT = 386 - SYS_RSEQ = 387 - SYS_IO_PGETEVENTS = 388 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAITPID = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_TIME = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BREAK = 17 + SYS_OLDSTAT = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_STIME = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_OLDFSTAT = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_STTY = 31 + SYS_GTTY = 32 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_FTIME = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_PROF = 44 + SYS_BRK = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_LOCK = 53 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_MPX = 56 + SYS_SETPGID = 57 + SYS_ULIMIT = 58 + SYS_OLDOLDUNAME = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SGETMASK = 68 + SYS_SSETMASK = 69 + SYS_SETREUID = 70 + SYS_SETREGID = 71 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRLIMIT = 76 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_GETGROUPS = 80 + SYS_SETGROUPS = 81 + SYS_SELECT = 82 + SYS_SYMLINK = 83 + SYS_OLDLSTAT = 84 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_FCHOWN = 95 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_PROFIL = 98 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_IOPERM = 101 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_OLDUNAME = 109 + SYS_IOPL = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_VM86 = 113 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_MODIFY_LDT = 123 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_SETFSUID = 138 + SYS_SETFSGID = 139 + SYS__LLSEEK = 140 + SYS_GETDENTS = 141 + SYS__NEWSELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_SETRESUID = 164 + SYS_GETRESUID = 165 + SYS_QUERY_MODULE = 166 + SYS_POLL = 167 + SYS_NFSSERVCTL = 168 + SYS_SETRESGID = 169 + SYS_GETRESGID = 170 + SYS_PRCTL = 171 + SYS_RT_SIGRETURN = 172 + SYS_RT_SIGACTION = 173 + SYS_RT_SIGPROCMASK = 174 + SYS_RT_SIGPENDING = 175 + SYS_RT_SIGTIMEDWAIT = 176 + SYS_RT_SIGQUEUEINFO = 177 + SYS_RT_SIGSUSPEND = 178 + SYS_PREAD64 = 179 + SYS_PWRITE64 = 180 + SYS_CHOWN = 181 + SYS_GETCWD = 182 + SYS_CAPGET = 183 + SYS_CAPSET = 184 + SYS_SIGALTSTACK = 185 + SYS_SENDFILE = 186 + SYS_GETPMSG = 187 + SYS_PUTPMSG = 188 + SYS_VFORK = 189 + SYS_UGETRLIMIT = 190 + SYS_READAHEAD = 191 + SYS_PCICONFIG_READ = 198 + SYS_PCICONFIG_WRITE = 199 + SYS_PCICONFIG_IOBASE = 200 + SYS_MULTIPLEXER = 201 + SYS_GETDENTS64 = 202 + SYS_PIVOT_ROOT = 203 + SYS_MADVISE = 205 + SYS_MINCORE = 206 + SYS_GETTID = 207 + SYS_TKILL = 208 + SYS_SETXATTR = 209 + SYS_LSETXATTR = 210 + SYS_FSETXATTR = 211 + SYS_GETXATTR = 212 + SYS_LGETXATTR = 213 + SYS_FGETXATTR = 214 + SYS_LISTXATTR = 215 + SYS_LLISTXATTR = 216 + SYS_FLISTXATTR = 217 + SYS_REMOVEXATTR = 218 + SYS_LREMOVEXATTR = 219 + SYS_FREMOVEXATTR = 220 + SYS_FUTEX = 221 + SYS_SCHED_SETAFFINITY = 222 + SYS_SCHED_GETAFFINITY = 223 + SYS_TUXCALL = 225 + SYS_IO_SETUP = 227 + SYS_IO_DESTROY = 228 + SYS_IO_GETEVENTS = 229 + SYS_IO_SUBMIT = 230 + SYS_IO_CANCEL = 231 + SYS_SET_TID_ADDRESS = 232 + SYS_FADVISE64 = 233 + SYS_EXIT_GROUP = 234 + SYS_LOOKUP_DCOOKIE = 235 + SYS_EPOLL_CREATE = 236 + SYS_EPOLL_CTL = 237 + SYS_EPOLL_WAIT = 238 + SYS_REMAP_FILE_PAGES = 239 + SYS_TIMER_CREATE = 240 + SYS_TIMER_SETTIME = 241 + SYS_TIMER_GETTIME = 242 + SYS_TIMER_GETOVERRUN = 243 + SYS_TIMER_DELETE = 244 + SYS_CLOCK_SETTIME = 245 + SYS_CLOCK_GETTIME = 246 + SYS_CLOCK_GETRES = 247 + SYS_CLOCK_NANOSLEEP = 248 + SYS_SWAPCONTEXT = 249 + SYS_TGKILL = 250 + SYS_UTIMES = 251 + SYS_STATFS64 = 252 + SYS_FSTATFS64 = 253 + SYS_RTAS = 255 + SYS_SYS_DEBUG_SETCONTEXT = 256 + SYS_MIGRATE_PAGES = 258 + SYS_MBIND = 259 + SYS_GET_MEMPOLICY = 260 + SYS_SET_MEMPOLICY = 261 + SYS_MQ_OPEN = 262 + SYS_MQ_UNLINK = 263 + SYS_MQ_TIMEDSEND = 264 + SYS_MQ_TIMEDRECEIVE = 265 + SYS_MQ_NOTIFY = 266 + SYS_MQ_GETSETATTR = 267 + SYS_KEXEC_LOAD = 268 + SYS_ADD_KEY = 269 + SYS_REQUEST_KEY = 270 + SYS_KEYCTL = 271 + SYS_WAITID = 272 + SYS_IOPRIO_SET = 273 + SYS_IOPRIO_GET = 274 + SYS_INOTIFY_INIT = 275 + SYS_INOTIFY_ADD_WATCH = 276 + SYS_INOTIFY_RM_WATCH = 277 + SYS_SPU_RUN = 278 + SYS_SPU_CREATE = 279 + SYS_PSELECT6 = 280 + SYS_PPOLL = 281 + SYS_UNSHARE = 282 + SYS_SPLICE = 283 + SYS_TEE = 284 + SYS_VMSPLICE = 285 + SYS_OPENAT = 286 + SYS_MKDIRAT = 287 + SYS_MKNODAT = 288 + SYS_FCHOWNAT = 289 + SYS_FUTIMESAT = 290 + SYS_NEWFSTATAT = 291 + SYS_UNLINKAT = 292 + SYS_RENAMEAT = 293 + SYS_LINKAT = 294 + SYS_SYMLINKAT = 295 + SYS_READLINKAT = 296 + SYS_FCHMODAT = 297 + SYS_FACCESSAT = 298 + SYS_GET_ROBUST_LIST = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_MOVE_PAGES = 301 + SYS_GETCPU = 302 + SYS_EPOLL_PWAIT = 303 + SYS_UTIMENSAT = 304 + SYS_SIGNALFD = 305 + SYS_TIMERFD_CREATE = 306 + SYS_EVENTFD = 307 + SYS_SYNC_FILE_RANGE2 = 308 + SYS_FALLOCATE = 309 + SYS_SUBPAGE_PROT = 310 + SYS_TIMERFD_SETTIME = 311 + SYS_TIMERFD_GETTIME = 312 + SYS_SIGNALFD4 = 313 + SYS_EVENTFD2 = 314 + SYS_EPOLL_CREATE1 = 315 + SYS_DUP3 = 316 + SYS_PIPE2 = 317 + SYS_INOTIFY_INIT1 = 318 + SYS_PERF_EVENT_OPEN = 319 + SYS_PREADV = 320 + SYS_PWRITEV = 321 + SYS_RT_TGSIGQUEUEINFO = 322 + SYS_FANOTIFY_INIT = 323 + SYS_FANOTIFY_MARK = 324 + SYS_PRLIMIT64 = 325 + SYS_SOCKET = 326 + SYS_BIND = 327 + SYS_CONNECT = 328 + SYS_LISTEN = 329 + SYS_ACCEPT = 330 + SYS_GETSOCKNAME = 331 + SYS_GETPEERNAME = 332 + SYS_SOCKETPAIR = 333 + SYS_SEND = 334 + SYS_SENDTO = 335 + SYS_RECV = 336 + SYS_RECVFROM = 337 + SYS_SHUTDOWN = 338 + SYS_SETSOCKOPT = 339 + SYS_GETSOCKOPT = 340 + SYS_SENDMSG = 341 + SYS_RECVMSG = 342 + SYS_RECVMMSG = 343 + SYS_ACCEPT4 = 344 + SYS_NAME_TO_HANDLE_AT = 345 + SYS_OPEN_BY_HANDLE_AT = 346 + SYS_CLOCK_ADJTIME = 347 + SYS_SYNCFS = 348 + SYS_SENDMMSG = 349 + SYS_SETNS = 350 + SYS_PROCESS_VM_READV = 351 + SYS_PROCESS_VM_WRITEV = 352 + SYS_FINIT_MODULE = 353 + SYS_KCMP = 354 + SYS_SCHED_SETATTR = 355 + SYS_SCHED_GETATTR = 356 + SYS_RENAMEAT2 = 357 + SYS_SECCOMP = 358 + SYS_GETRANDOM = 359 + SYS_MEMFD_CREATE = 360 + SYS_BPF = 361 + SYS_EXECVEAT = 362 + SYS_SWITCH_ENDIAN = 363 + SYS_USERFAULTFD = 364 + SYS_MEMBARRIER = 365 + SYS_MLOCK2 = 378 + SYS_COPY_FILE_RANGE = 379 + SYS_PREADV2 = 380 + SYS_PWRITEV2 = 381 + SYS_KEXEC_FILE_LOAD = 382 + SYS_STATX = 383 + SYS_PKEY_ALLOC = 384 + SYS_PKEY_FREE = 385 + SYS_PKEY_MPROTECT = 386 + SYS_RSEQ = 387 + SYS_IO_PGETEVENTS = 388 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 4f7261a..6c9bb4e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -1,300 +1,334 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/riscv64/include /tmp/riscv64/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build riscv64,linux +//go:build riscv64 && linux package unix const ( - SYS_IO_SETUP = 0 - SYS_IO_DESTROY = 1 - SYS_IO_SUBMIT = 2 - SYS_IO_CANCEL = 3 - SYS_IO_GETEVENTS = 4 - SYS_SETXATTR = 5 - SYS_LSETXATTR = 6 - SYS_FSETXATTR = 7 - SYS_GETXATTR = 8 - SYS_LGETXATTR = 9 - SYS_FGETXATTR = 10 - SYS_LISTXATTR = 11 - SYS_LLISTXATTR = 12 - SYS_FLISTXATTR = 13 - SYS_REMOVEXATTR = 14 - SYS_LREMOVEXATTR = 15 - SYS_FREMOVEXATTR = 16 - SYS_GETCWD = 17 - SYS_LOOKUP_DCOOKIE = 18 - SYS_EVENTFD2 = 19 - SYS_EPOLL_CREATE1 = 20 - SYS_EPOLL_CTL = 21 - SYS_EPOLL_PWAIT = 22 - SYS_DUP = 23 - SYS_DUP3 = 24 - SYS_FCNTL = 25 - SYS_INOTIFY_INIT1 = 26 - SYS_INOTIFY_ADD_WATCH = 27 - SYS_INOTIFY_RM_WATCH = 28 - SYS_IOCTL = 29 - SYS_IOPRIO_SET = 30 - SYS_IOPRIO_GET = 31 - SYS_FLOCK = 32 - SYS_MKNODAT = 33 - SYS_MKDIRAT = 34 - SYS_UNLINKAT = 35 - SYS_SYMLINKAT = 36 - SYS_LINKAT = 37 - SYS_UMOUNT2 = 39 - SYS_MOUNT = 40 - SYS_PIVOT_ROOT = 41 - SYS_NFSSERVCTL = 42 - SYS_STATFS = 43 - SYS_FSTATFS = 44 - SYS_TRUNCATE = 45 - SYS_FTRUNCATE = 46 - SYS_FALLOCATE = 47 - SYS_FACCESSAT = 48 - SYS_CHDIR = 49 - SYS_FCHDIR = 50 - SYS_CHROOT = 51 - SYS_FCHMOD = 52 - SYS_FCHMODAT = 53 - SYS_FCHOWNAT = 54 - SYS_FCHOWN = 55 - SYS_OPENAT = 56 - SYS_CLOSE = 57 - SYS_VHANGUP = 58 - SYS_PIPE2 = 59 - SYS_QUOTACTL = 60 - SYS_GETDENTS64 = 61 - SYS_LSEEK = 62 - SYS_READ = 63 - SYS_WRITE = 64 - SYS_READV = 65 - SYS_WRITEV = 66 - SYS_PREAD64 = 67 - SYS_PWRITE64 = 68 - SYS_PREADV = 69 - SYS_PWRITEV = 70 - SYS_SENDFILE = 71 - SYS_PSELECT6 = 72 - SYS_PPOLL = 73 - SYS_SIGNALFD4 = 74 - SYS_VMSPLICE = 75 - SYS_SPLICE = 76 - SYS_TEE = 77 - SYS_READLINKAT = 78 - SYS_FSTATAT = 79 - SYS_FSTAT = 80 - SYS_SYNC = 81 - SYS_FSYNC = 82 - SYS_FDATASYNC = 83 - SYS_SYNC_FILE_RANGE = 84 - SYS_TIMERFD_CREATE = 85 - SYS_TIMERFD_SETTIME = 86 - SYS_TIMERFD_GETTIME = 87 - SYS_UTIMENSAT = 88 - SYS_ACCT = 89 - SYS_CAPGET = 90 - SYS_CAPSET = 91 - SYS_PERSONALITY = 92 - SYS_EXIT = 93 - SYS_EXIT_GROUP = 94 - SYS_WAITID = 95 - SYS_SET_TID_ADDRESS = 96 - SYS_UNSHARE = 97 - SYS_FUTEX = 98 - SYS_SET_ROBUST_LIST = 99 - SYS_GET_ROBUST_LIST = 100 - SYS_NANOSLEEP = 101 - SYS_GETITIMER = 102 - SYS_SETITIMER = 103 - SYS_KEXEC_LOAD = 104 - SYS_INIT_MODULE = 105 - SYS_DELETE_MODULE = 106 - SYS_TIMER_CREATE = 107 - SYS_TIMER_GETTIME = 108 - SYS_TIMER_GETOVERRUN = 109 - SYS_TIMER_SETTIME = 110 - SYS_TIMER_DELETE = 111 - SYS_CLOCK_SETTIME = 112 - SYS_CLOCK_GETTIME = 113 - SYS_CLOCK_GETRES = 114 - SYS_CLOCK_NANOSLEEP = 115 - SYS_SYSLOG = 116 - SYS_PTRACE = 117 - SYS_SCHED_SETPARAM = 118 - SYS_SCHED_SETSCHEDULER = 119 - SYS_SCHED_GETSCHEDULER = 120 - SYS_SCHED_GETPARAM = 121 - SYS_SCHED_SETAFFINITY = 122 - SYS_SCHED_GETAFFINITY = 123 - SYS_SCHED_YIELD = 124 - SYS_SCHED_GET_PRIORITY_MAX = 125 - SYS_SCHED_GET_PRIORITY_MIN = 126 - SYS_SCHED_RR_GET_INTERVAL = 127 - SYS_RESTART_SYSCALL = 128 - SYS_KILL = 129 - SYS_TKILL = 130 - SYS_TGKILL = 131 - SYS_SIGALTSTACK = 132 - SYS_RT_SIGSUSPEND = 133 - SYS_RT_SIGACTION = 134 - SYS_RT_SIGPROCMASK = 135 - SYS_RT_SIGPENDING = 136 - SYS_RT_SIGTIMEDWAIT = 137 - SYS_RT_SIGQUEUEINFO = 138 - SYS_RT_SIGRETURN = 139 - SYS_SETPRIORITY = 140 - SYS_GETPRIORITY = 141 - SYS_REBOOT = 142 - SYS_SETREGID = 143 - SYS_SETGID = 144 - SYS_SETREUID = 145 - SYS_SETUID = 146 - SYS_SETRESUID = 147 - SYS_GETRESUID = 148 - SYS_SETRESGID = 149 - SYS_GETRESGID = 150 - SYS_SETFSUID = 151 - SYS_SETFSGID = 152 - SYS_TIMES = 153 - SYS_SETPGID = 154 - SYS_GETPGID = 155 - SYS_GETSID = 156 - SYS_SETSID = 157 - SYS_GETGROUPS = 158 - SYS_SETGROUPS = 159 - SYS_UNAME = 160 - SYS_SETHOSTNAME = 161 - SYS_SETDOMAINNAME = 162 - SYS_GETRLIMIT = 163 - SYS_SETRLIMIT = 164 - SYS_GETRUSAGE = 165 - SYS_UMASK = 166 - SYS_PRCTL = 167 - SYS_GETCPU = 168 - SYS_GETTIMEOFDAY = 169 - SYS_SETTIMEOFDAY = 170 - SYS_ADJTIMEX = 171 - SYS_GETPID = 172 - SYS_GETPPID = 173 - SYS_GETUID = 174 - SYS_GETEUID = 175 - SYS_GETGID = 176 - SYS_GETEGID = 177 - SYS_GETTID = 178 - SYS_SYSINFO = 179 - SYS_MQ_OPEN = 180 - SYS_MQ_UNLINK = 181 - SYS_MQ_TIMEDSEND = 182 - SYS_MQ_TIMEDRECEIVE = 183 - SYS_MQ_NOTIFY = 184 - SYS_MQ_GETSETATTR = 185 - SYS_MSGGET = 186 - SYS_MSGCTL = 187 - SYS_MSGRCV = 188 - SYS_MSGSND = 189 - SYS_SEMGET = 190 - SYS_SEMCTL = 191 - SYS_SEMTIMEDOP = 192 - SYS_SEMOP = 193 - SYS_SHMGET = 194 - SYS_SHMCTL = 195 - SYS_SHMAT = 196 - SYS_SHMDT = 197 - SYS_SOCKET = 198 - SYS_SOCKETPAIR = 199 - SYS_BIND = 200 - SYS_LISTEN = 201 - SYS_ACCEPT = 202 - SYS_CONNECT = 203 - SYS_GETSOCKNAME = 204 - SYS_GETPEERNAME = 205 - SYS_SENDTO = 206 - SYS_RECVFROM = 207 - SYS_SETSOCKOPT = 208 - SYS_GETSOCKOPT = 209 - SYS_SHUTDOWN = 210 - SYS_SENDMSG = 211 - SYS_RECVMSG = 212 - SYS_READAHEAD = 213 - SYS_BRK = 214 - SYS_MUNMAP = 215 - SYS_MREMAP = 216 - SYS_ADD_KEY = 217 - SYS_REQUEST_KEY = 218 - SYS_KEYCTL = 219 - SYS_CLONE = 220 - SYS_EXECVE = 221 - SYS_MMAP = 222 - SYS_FADVISE64 = 223 - SYS_SWAPON = 224 - SYS_SWAPOFF = 225 - SYS_MPROTECT = 226 - SYS_MSYNC = 227 - SYS_MLOCK = 228 - SYS_MUNLOCK = 229 - SYS_MLOCKALL = 230 - SYS_MUNLOCKALL = 231 - SYS_MINCORE = 232 - SYS_MADVISE = 233 - SYS_REMAP_FILE_PAGES = 234 - SYS_MBIND = 235 - SYS_GET_MEMPOLICY = 236 - SYS_SET_MEMPOLICY = 237 - SYS_MIGRATE_PAGES = 238 - SYS_MOVE_PAGES = 239 - SYS_RT_TGSIGQUEUEINFO = 240 - SYS_PERF_EVENT_OPEN = 241 - SYS_ACCEPT4 = 242 - SYS_RECVMMSG = 243 - SYS_ARCH_SPECIFIC_SYSCALL = 244 - SYS_WAIT4 = 260 - SYS_PRLIMIT64 = 261 - SYS_FANOTIFY_INIT = 262 - SYS_FANOTIFY_MARK = 263 - SYS_NAME_TO_HANDLE_AT = 264 - SYS_OPEN_BY_HANDLE_AT = 265 - SYS_CLOCK_ADJTIME = 266 - SYS_SYNCFS = 267 - SYS_SETNS = 268 - SYS_SENDMMSG = 269 - SYS_PROCESS_VM_READV = 270 - SYS_PROCESS_VM_WRITEV = 271 - SYS_KCMP = 272 - SYS_FINIT_MODULE = 273 - SYS_SCHED_SETATTR = 274 - SYS_SCHED_GETATTR = 275 - SYS_RENAMEAT2 = 276 - SYS_SECCOMP = 277 - SYS_GETRANDOM = 278 - SYS_MEMFD_CREATE = 279 - SYS_BPF = 280 - SYS_EXECVEAT = 281 - SYS_USERFAULTFD = 282 - SYS_MEMBARRIER = 283 - SYS_MLOCK2 = 284 - SYS_COPY_FILE_RANGE = 285 - SYS_PREADV2 = 286 - SYS_PWRITEV2 = 287 - SYS_PKEY_MPROTECT = 288 - SYS_PKEY_ALLOC = 289 - SYS_PKEY_FREE = 290 - SYS_STATX = 291 - SYS_IO_PGETEVENTS = 292 - SYS_RSEQ = 293 - SYS_KEXEC_FILE_LOAD = 294 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 + SYS_IO_SETUP = 0 + SYS_IO_DESTROY = 1 + SYS_IO_SUBMIT = 2 + SYS_IO_CANCEL = 3 + SYS_IO_GETEVENTS = 4 + SYS_SETXATTR = 5 + SYS_LSETXATTR = 6 + SYS_FSETXATTR = 7 + SYS_GETXATTR = 8 + SYS_LGETXATTR = 9 + SYS_FGETXATTR = 10 + SYS_LISTXATTR = 11 + SYS_LLISTXATTR = 12 + SYS_FLISTXATTR = 13 + SYS_REMOVEXATTR = 14 + SYS_LREMOVEXATTR = 15 + SYS_FREMOVEXATTR = 16 + SYS_GETCWD = 17 + SYS_LOOKUP_DCOOKIE = 18 + SYS_EVENTFD2 = 19 + SYS_EPOLL_CREATE1 = 20 + SYS_EPOLL_CTL = 21 + SYS_EPOLL_PWAIT = 22 + SYS_DUP = 23 + SYS_DUP3 = 24 + SYS_FCNTL = 25 + SYS_INOTIFY_INIT1 = 26 + SYS_INOTIFY_ADD_WATCH = 27 + SYS_INOTIFY_RM_WATCH = 28 + SYS_IOCTL = 29 + SYS_IOPRIO_SET = 30 + SYS_IOPRIO_GET = 31 + SYS_FLOCK = 32 + SYS_MKNODAT = 33 + SYS_MKDIRAT = 34 + SYS_UNLINKAT = 35 + SYS_SYMLINKAT = 36 + SYS_LINKAT = 37 + SYS_UMOUNT2 = 39 + SYS_MOUNT = 40 + SYS_PIVOT_ROOT = 41 + SYS_NFSSERVCTL = 42 + SYS_STATFS = 43 + SYS_FSTATFS = 44 + SYS_TRUNCATE = 45 + SYS_FTRUNCATE = 46 + SYS_FALLOCATE = 47 + SYS_FACCESSAT = 48 + SYS_CHDIR = 49 + SYS_FCHDIR = 50 + SYS_CHROOT = 51 + SYS_FCHMOD = 52 + SYS_FCHMODAT = 53 + SYS_FCHOWNAT = 54 + SYS_FCHOWN = 55 + SYS_OPENAT = 56 + SYS_CLOSE = 57 + SYS_VHANGUP = 58 + SYS_PIPE2 = 59 + SYS_QUOTACTL = 60 + SYS_GETDENTS64 = 61 + SYS_LSEEK = 62 + SYS_READ = 63 + SYS_WRITE = 64 + SYS_READV = 65 + SYS_WRITEV = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_PREADV = 69 + SYS_PWRITEV = 70 + SYS_SENDFILE = 71 + SYS_PSELECT6 = 72 + SYS_PPOLL = 73 + SYS_SIGNALFD4 = 74 + SYS_VMSPLICE = 75 + SYS_SPLICE = 76 + SYS_TEE = 77 + SYS_READLINKAT = 78 + SYS_NEWFSTATAT = 79 + SYS_FSTAT = 80 + SYS_SYNC = 81 + SYS_FSYNC = 82 + SYS_FDATASYNC = 83 + SYS_SYNC_FILE_RANGE = 84 + SYS_TIMERFD_CREATE = 85 + SYS_TIMERFD_SETTIME = 86 + SYS_TIMERFD_GETTIME = 87 + SYS_UTIMENSAT = 88 + SYS_ACCT = 89 + SYS_CAPGET = 90 + SYS_CAPSET = 91 + SYS_PERSONALITY = 92 + SYS_EXIT = 93 + SYS_EXIT_GROUP = 94 + SYS_WAITID = 95 + SYS_SET_TID_ADDRESS = 96 + SYS_UNSHARE = 97 + SYS_FUTEX = 98 + SYS_SET_ROBUST_LIST = 99 + SYS_GET_ROBUST_LIST = 100 + SYS_NANOSLEEP = 101 + SYS_GETITIMER = 102 + SYS_SETITIMER = 103 + SYS_KEXEC_LOAD = 104 + SYS_INIT_MODULE = 105 + SYS_DELETE_MODULE = 106 + SYS_TIMER_CREATE = 107 + SYS_TIMER_GETTIME = 108 + SYS_TIMER_GETOVERRUN = 109 + SYS_TIMER_SETTIME = 110 + SYS_TIMER_DELETE = 111 + SYS_CLOCK_SETTIME = 112 + SYS_CLOCK_GETTIME = 113 + SYS_CLOCK_GETRES = 114 + SYS_CLOCK_NANOSLEEP = 115 + SYS_SYSLOG = 116 + SYS_PTRACE = 117 + SYS_SCHED_SETPARAM = 118 + SYS_SCHED_SETSCHEDULER = 119 + SYS_SCHED_GETSCHEDULER = 120 + SYS_SCHED_GETPARAM = 121 + SYS_SCHED_SETAFFINITY = 122 + SYS_SCHED_GETAFFINITY = 123 + SYS_SCHED_YIELD = 124 + SYS_SCHED_GET_PRIORITY_MAX = 125 + SYS_SCHED_GET_PRIORITY_MIN = 126 + SYS_SCHED_RR_GET_INTERVAL = 127 + SYS_RESTART_SYSCALL = 128 + SYS_KILL = 129 + SYS_TKILL = 130 + SYS_TGKILL = 131 + SYS_SIGALTSTACK = 132 + SYS_RT_SIGSUSPEND = 133 + SYS_RT_SIGACTION = 134 + SYS_RT_SIGPROCMASK = 135 + SYS_RT_SIGPENDING = 136 + SYS_RT_SIGTIMEDWAIT = 137 + SYS_RT_SIGQUEUEINFO = 138 + SYS_RT_SIGRETURN = 139 + SYS_SETPRIORITY = 140 + SYS_GETPRIORITY = 141 + SYS_REBOOT = 142 + SYS_SETREGID = 143 + SYS_SETGID = 144 + SYS_SETREUID = 145 + SYS_SETUID = 146 + SYS_SETRESUID = 147 + SYS_GETRESUID = 148 + SYS_SETRESGID = 149 + SYS_GETRESGID = 150 + SYS_SETFSUID = 151 + SYS_SETFSGID = 152 + SYS_TIMES = 153 + SYS_SETPGID = 154 + SYS_GETPGID = 155 + SYS_GETSID = 156 + SYS_SETSID = 157 + SYS_GETGROUPS = 158 + SYS_SETGROUPS = 159 + SYS_UNAME = 160 + SYS_SETHOSTNAME = 161 + SYS_SETDOMAINNAME = 162 + SYS_GETRLIMIT = 163 + SYS_SETRLIMIT = 164 + SYS_GETRUSAGE = 165 + SYS_UMASK = 166 + SYS_PRCTL = 167 + SYS_GETCPU = 168 + SYS_GETTIMEOFDAY = 169 + SYS_SETTIMEOFDAY = 170 + SYS_ADJTIMEX = 171 + SYS_GETPID = 172 + SYS_GETPPID = 173 + SYS_GETUID = 174 + SYS_GETEUID = 175 + SYS_GETGID = 176 + SYS_GETEGID = 177 + SYS_GETTID = 178 + SYS_SYSINFO = 179 + SYS_MQ_OPEN = 180 + SYS_MQ_UNLINK = 181 + SYS_MQ_TIMEDSEND = 182 + SYS_MQ_TIMEDRECEIVE = 183 + SYS_MQ_NOTIFY = 184 + SYS_MQ_GETSETATTR = 185 + SYS_MSGGET = 186 + SYS_MSGCTL = 187 + SYS_MSGRCV = 188 + SYS_MSGSND = 189 + SYS_SEMGET = 190 + SYS_SEMCTL = 191 + SYS_SEMTIMEDOP = 192 + SYS_SEMOP = 193 + SYS_SHMGET = 194 + SYS_SHMCTL = 195 + SYS_SHMAT = 196 + SYS_SHMDT = 197 + SYS_SOCKET = 198 + SYS_SOCKETPAIR = 199 + SYS_BIND = 200 + SYS_LISTEN = 201 + SYS_ACCEPT = 202 + SYS_CONNECT = 203 + SYS_GETSOCKNAME = 204 + SYS_GETPEERNAME = 205 + SYS_SENDTO = 206 + SYS_RECVFROM = 207 + SYS_SETSOCKOPT = 208 + SYS_GETSOCKOPT = 209 + SYS_SHUTDOWN = 210 + SYS_SENDMSG = 211 + SYS_RECVMSG = 212 + SYS_READAHEAD = 213 + SYS_BRK = 214 + SYS_MUNMAP = 215 + SYS_MREMAP = 216 + SYS_ADD_KEY = 217 + SYS_REQUEST_KEY = 218 + SYS_KEYCTL = 219 + SYS_CLONE = 220 + SYS_EXECVE = 221 + SYS_MMAP = 222 + SYS_FADVISE64 = 223 + SYS_SWAPON = 224 + SYS_SWAPOFF = 225 + SYS_MPROTECT = 226 + SYS_MSYNC = 227 + SYS_MLOCK = 228 + SYS_MUNLOCK = 229 + SYS_MLOCKALL = 230 + SYS_MUNLOCKALL = 231 + SYS_MINCORE = 232 + SYS_MADVISE = 233 + SYS_REMAP_FILE_PAGES = 234 + SYS_MBIND = 235 + SYS_GET_MEMPOLICY = 236 + SYS_SET_MEMPOLICY = 237 + SYS_MIGRATE_PAGES = 238 + SYS_MOVE_PAGES = 239 + SYS_RT_TGSIGQUEUEINFO = 240 + SYS_PERF_EVENT_OPEN = 241 + SYS_ACCEPT4 = 242 + SYS_RECVMMSG = 243 + SYS_ARCH_SPECIFIC_SYSCALL = 244 + SYS_RISCV_HWPROBE = 258 + SYS_RISCV_FLUSH_ICACHE = 259 + SYS_WAIT4 = 260 + SYS_PRLIMIT64 = 261 + SYS_FANOTIFY_INIT = 262 + SYS_FANOTIFY_MARK = 263 + SYS_NAME_TO_HANDLE_AT = 264 + SYS_OPEN_BY_HANDLE_AT = 265 + SYS_CLOCK_ADJTIME = 266 + SYS_SYNCFS = 267 + SYS_SETNS = 268 + SYS_SENDMMSG = 269 + SYS_PROCESS_VM_READV = 270 + SYS_PROCESS_VM_WRITEV = 271 + SYS_KCMP = 272 + SYS_FINIT_MODULE = 273 + SYS_SCHED_SETATTR = 274 + SYS_SCHED_GETATTR = 275 + SYS_RENAMEAT2 = 276 + SYS_SECCOMP = 277 + SYS_GETRANDOM = 278 + SYS_MEMFD_CREATE = 279 + SYS_BPF = 280 + SYS_EXECVEAT = 281 + SYS_USERFAULTFD = 282 + SYS_MEMBARRIER = 283 + SYS_MLOCK2 = 284 + SYS_COPY_FILE_RANGE = 285 + SYS_PREADV2 = 286 + SYS_PWRITEV2 = 287 + SYS_PKEY_MPROTECT = 288 + SYS_PKEY_ALLOC = 289 + SYS_PKEY_FREE = 290 + SYS_STATX = 291 + SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 + SYS_KEXEC_FILE_LOAD = 294 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index f47014a..680bc99 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -1,363 +1,395 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include -fsigned-char /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/s390x/include -fsigned-char /tmp/s390x/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build s390x,linux +//go:build s390x && linux package unix const ( - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_RESTART_SYSCALL = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECVE = 11 - SYS_CHDIR = 12 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_MOUNT = 21 - SYS_UMOUNT = 22 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_RENAME = 38 - SYS_MKDIR = 39 - SYS_RMDIR = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_BRK = 45 - SYS_SIGNAL = 48 - SYS_ACCT = 51 - SYS_UMOUNT2 = 52 - SYS_IOCTL = 54 - SYS_FCNTL = 55 - SYS_SETPGID = 57 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_USTAT = 62 - SYS_DUP2 = 63 - SYS_GETPPID = 64 - SYS_GETPGRP = 65 - SYS_SETSID = 66 - SYS_SIGACTION = 67 - SYS_SIGSUSPEND = 72 - SYS_SIGPENDING = 73 - SYS_SETHOSTNAME = 74 - SYS_SETRLIMIT = 75 - SYS_GETRUSAGE = 77 - SYS_GETTIMEOFDAY = 78 - SYS_SETTIMEOFDAY = 79 - SYS_SYMLINK = 83 - SYS_READLINK = 85 - SYS_USELIB = 86 - SYS_SWAPON = 87 - SYS_REBOOT = 88 - SYS_READDIR = 89 - SYS_MMAP = 90 - SYS_MUNMAP = 91 - SYS_TRUNCATE = 92 - SYS_FTRUNCATE = 93 - SYS_FCHMOD = 94 - SYS_GETPRIORITY = 96 - SYS_SETPRIORITY = 97 - SYS_STATFS = 99 - SYS_FSTATFS = 100 - SYS_SOCKETCALL = 102 - SYS_SYSLOG = 103 - SYS_SETITIMER = 104 - SYS_GETITIMER = 105 - SYS_STAT = 106 - SYS_LSTAT = 107 - SYS_FSTAT = 108 - SYS_LOOKUP_DCOOKIE = 110 - SYS_VHANGUP = 111 - SYS_IDLE = 112 - SYS_WAIT4 = 114 - SYS_SWAPOFF = 115 - SYS_SYSINFO = 116 - SYS_IPC = 117 - SYS_FSYNC = 118 - SYS_SIGRETURN = 119 - SYS_CLONE = 120 - SYS_SETDOMAINNAME = 121 - SYS_UNAME = 122 - SYS_ADJTIMEX = 124 - SYS_MPROTECT = 125 - SYS_SIGPROCMASK = 126 - SYS_CREATE_MODULE = 127 - SYS_INIT_MODULE = 128 - SYS_DELETE_MODULE = 129 - SYS_GET_KERNEL_SYMS = 130 - SYS_QUOTACTL = 131 - SYS_GETPGID = 132 - SYS_FCHDIR = 133 - SYS_BDFLUSH = 134 - SYS_SYSFS = 135 - SYS_PERSONALITY = 136 - SYS_AFS_SYSCALL = 137 - SYS_GETDENTS = 141 - SYS_SELECT = 142 - SYS_FLOCK = 143 - SYS_MSYNC = 144 - SYS_READV = 145 - SYS_WRITEV = 146 - SYS_GETSID = 147 - SYS_FDATASYNC = 148 - SYS__SYSCTL = 149 - SYS_MLOCK = 150 - SYS_MUNLOCK = 151 - SYS_MLOCKALL = 152 - SYS_MUNLOCKALL = 153 - SYS_SCHED_SETPARAM = 154 - SYS_SCHED_GETPARAM = 155 - SYS_SCHED_SETSCHEDULER = 156 - SYS_SCHED_GETSCHEDULER = 157 - SYS_SCHED_YIELD = 158 - SYS_SCHED_GET_PRIORITY_MAX = 159 - SYS_SCHED_GET_PRIORITY_MIN = 160 - SYS_SCHED_RR_GET_INTERVAL = 161 - SYS_NANOSLEEP = 162 - SYS_MREMAP = 163 - SYS_QUERY_MODULE = 167 - SYS_POLL = 168 - SYS_NFSSERVCTL = 169 - SYS_PRCTL = 172 - SYS_RT_SIGRETURN = 173 - SYS_RT_SIGACTION = 174 - SYS_RT_SIGPROCMASK = 175 - SYS_RT_SIGPENDING = 176 - SYS_RT_SIGTIMEDWAIT = 177 - SYS_RT_SIGQUEUEINFO = 178 - SYS_RT_SIGSUSPEND = 179 - SYS_PREAD64 = 180 - SYS_PWRITE64 = 181 - SYS_GETCWD = 183 - SYS_CAPGET = 184 - SYS_CAPSET = 185 - SYS_SIGALTSTACK = 186 - SYS_SENDFILE = 187 - SYS_GETPMSG = 188 - SYS_PUTPMSG = 189 - SYS_VFORK = 190 - SYS_GETRLIMIT = 191 - SYS_LCHOWN = 198 - SYS_GETUID = 199 - SYS_GETGID = 200 - SYS_GETEUID = 201 - SYS_GETEGID = 202 - SYS_SETREUID = 203 - SYS_SETREGID = 204 - SYS_GETGROUPS = 205 - SYS_SETGROUPS = 206 - SYS_FCHOWN = 207 - SYS_SETRESUID = 208 - SYS_GETRESUID = 209 - SYS_SETRESGID = 210 - SYS_GETRESGID = 211 - SYS_CHOWN = 212 - SYS_SETUID = 213 - SYS_SETGID = 214 - SYS_SETFSUID = 215 - SYS_SETFSGID = 216 - SYS_PIVOT_ROOT = 217 - SYS_MINCORE = 218 - SYS_MADVISE = 219 - SYS_GETDENTS64 = 220 - SYS_READAHEAD = 222 - SYS_SETXATTR = 224 - SYS_LSETXATTR = 225 - SYS_FSETXATTR = 226 - SYS_GETXATTR = 227 - SYS_LGETXATTR = 228 - SYS_FGETXATTR = 229 - SYS_LISTXATTR = 230 - SYS_LLISTXATTR = 231 - SYS_FLISTXATTR = 232 - SYS_REMOVEXATTR = 233 - SYS_LREMOVEXATTR = 234 - SYS_FREMOVEXATTR = 235 - SYS_GETTID = 236 - SYS_TKILL = 237 - SYS_FUTEX = 238 - SYS_SCHED_SETAFFINITY = 239 - SYS_SCHED_GETAFFINITY = 240 - SYS_TGKILL = 241 - SYS_IO_SETUP = 243 - SYS_IO_DESTROY = 244 - SYS_IO_GETEVENTS = 245 - SYS_IO_SUBMIT = 246 - SYS_IO_CANCEL = 247 - SYS_EXIT_GROUP = 248 - SYS_EPOLL_CREATE = 249 - SYS_EPOLL_CTL = 250 - SYS_EPOLL_WAIT = 251 - SYS_SET_TID_ADDRESS = 252 - SYS_FADVISE64 = 253 - SYS_TIMER_CREATE = 254 - SYS_TIMER_SETTIME = 255 - SYS_TIMER_GETTIME = 256 - SYS_TIMER_GETOVERRUN = 257 - SYS_TIMER_DELETE = 258 - SYS_CLOCK_SETTIME = 259 - SYS_CLOCK_GETTIME = 260 - SYS_CLOCK_GETRES = 261 - SYS_CLOCK_NANOSLEEP = 262 - SYS_STATFS64 = 265 - SYS_FSTATFS64 = 266 - SYS_REMAP_FILE_PAGES = 267 - SYS_MBIND = 268 - SYS_GET_MEMPOLICY = 269 - SYS_SET_MEMPOLICY = 270 - SYS_MQ_OPEN = 271 - SYS_MQ_UNLINK = 272 - SYS_MQ_TIMEDSEND = 273 - SYS_MQ_TIMEDRECEIVE = 274 - SYS_MQ_NOTIFY = 275 - SYS_MQ_GETSETATTR = 276 - SYS_KEXEC_LOAD = 277 - SYS_ADD_KEY = 278 - SYS_REQUEST_KEY = 279 - SYS_KEYCTL = 280 - SYS_WAITID = 281 - SYS_IOPRIO_SET = 282 - SYS_IOPRIO_GET = 283 - SYS_INOTIFY_INIT = 284 - SYS_INOTIFY_ADD_WATCH = 285 - SYS_INOTIFY_RM_WATCH = 286 - SYS_MIGRATE_PAGES = 287 - SYS_OPENAT = 288 - SYS_MKDIRAT = 289 - SYS_MKNODAT = 290 - SYS_FCHOWNAT = 291 - SYS_FUTIMESAT = 292 - SYS_NEWFSTATAT = 293 - SYS_UNLINKAT = 294 - SYS_RENAMEAT = 295 - SYS_LINKAT = 296 - SYS_SYMLINKAT = 297 - SYS_READLINKAT = 298 - SYS_FCHMODAT = 299 - SYS_FACCESSAT = 300 - SYS_PSELECT6 = 301 - SYS_PPOLL = 302 - SYS_UNSHARE = 303 - SYS_SET_ROBUST_LIST = 304 - SYS_GET_ROBUST_LIST = 305 - SYS_SPLICE = 306 - SYS_SYNC_FILE_RANGE = 307 - SYS_TEE = 308 - SYS_VMSPLICE = 309 - SYS_MOVE_PAGES = 310 - SYS_GETCPU = 311 - SYS_EPOLL_PWAIT = 312 - SYS_UTIMES = 313 - SYS_FALLOCATE = 314 - SYS_UTIMENSAT = 315 - SYS_SIGNALFD = 316 - SYS_TIMERFD = 317 - SYS_EVENTFD = 318 - SYS_TIMERFD_CREATE = 319 - SYS_TIMERFD_SETTIME = 320 - SYS_TIMERFD_GETTIME = 321 - SYS_SIGNALFD4 = 322 - SYS_EVENTFD2 = 323 - SYS_INOTIFY_INIT1 = 324 - SYS_PIPE2 = 325 - SYS_DUP3 = 326 - SYS_EPOLL_CREATE1 = 327 - SYS_PREADV = 328 - SYS_PWRITEV = 329 - SYS_RT_TGSIGQUEUEINFO = 330 - SYS_PERF_EVENT_OPEN = 331 - SYS_FANOTIFY_INIT = 332 - SYS_FANOTIFY_MARK = 333 - SYS_PRLIMIT64 = 334 - SYS_NAME_TO_HANDLE_AT = 335 - SYS_OPEN_BY_HANDLE_AT = 336 - SYS_CLOCK_ADJTIME = 337 - SYS_SYNCFS = 338 - SYS_SETNS = 339 - SYS_PROCESS_VM_READV = 340 - SYS_PROCESS_VM_WRITEV = 341 - SYS_S390_RUNTIME_INSTR = 342 - SYS_KCMP = 343 - SYS_FINIT_MODULE = 344 - SYS_SCHED_SETATTR = 345 - SYS_SCHED_GETATTR = 346 - SYS_RENAMEAT2 = 347 - SYS_SECCOMP = 348 - SYS_GETRANDOM = 349 - SYS_MEMFD_CREATE = 350 - SYS_BPF = 351 - SYS_S390_PCI_MMIO_WRITE = 352 - SYS_S390_PCI_MMIO_READ = 353 - SYS_EXECVEAT = 354 - SYS_USERFAULTFD = 355 - SYS_MEMBARRIER = 356 - SYS_RECVMMSG = 357 - SYS_SENDMMSG = 358 - SYS_SOCKET = 359 - SYS_SOCKETPAIR = 360 - SYS_BIND = 361 - SYS_CONNECT = 362 - SYS_LISTEN = 363 - SYS_ACCEPT4 = 364 - SYS_GETSOCKOPT = 365 - SYS_SETSOCKOPT = 366 - SYS_GETSOCKNAME = 367 - SYS_GETPEERNAME = 368 - SYS_SENDTO = 369 - SYS_SENDMSG = 370 - SYS_RECVFROM = 371 - SYS_RECVMSG = 372 - SYS_SHUTDOWN = 373 - SYS_MLOCK2 = 374 - SYS_COPY_FILE_RANGE = 375 - SYS_PREADV2 = 376 - SYS_PWRITEV2 = 377 - SYS_S390_GUARDED_STORAGE = 378 - SYS_STATX = 379 - SYS_S390_STHYI = 380 - SYS_KEXEC_FILE_LOAD = 381 - SYS_IO_PGETEVENTS = 382 - SYS_RSEQ = 383 - SYS_PKEY_MPROTECT = 384 - SYS_PKEY_ALLOC = 385 - SYS_PKEY_FREE = 386 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_RESTART_SYSCALL = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_BRK = 45 + SYS_SIGNAL = 48 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_SETPGID = 57 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_SYMLINK = 83 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_LOOKUP_DCOOKIE = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_GETDENTS = 141 + SYS_SELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_QUERY_MODULE = 167 + SYS_POLL = 168 + SYS_NFSSERVCTL = 169 + SYS_PRCTL = 172 + SYS_RT_SIGRETURN = 173 + SYS_RT_SIGACTION = 174 + SYS_RT_SIGPROCMASK = 175 + SYS_RT_SIGPENDING = 176 + SYS_RT_SIGTIMEDWAIT = 177 + SYS_RT_SIGQUEUEINFO = 178 + SYS_RT_SIGSUSPEND = 179 + SYS_PREAD64 = 180 + SYS_PWRITE64 = 181 + SYS_GETCWD = 183 + SYS_CAPGET = 184 + SYS_CAPSET = 185 + SYS_SIGALTSTACK = 186 + SYS_SENDFILE = 187 + SYS_GETPMSG = 188 + SYS_PUTPMSG = 189 + SYS_VFORK = 190 + SYS_GETRLIMIT = 191 + SYS_LCHOWN = 198 + SYS_GETUID = 199 + SYS_GETGID = 200 + SYS_GETEUID = 201 + SYS_GETEGID = 202 + SYS_SETREUID = 203 + SYS_SETREGID = 204 + SYS_GETGROUPS = 205 + SYS_SETGROUPS = 206 + SYS_FCHOWN = 207 + SYS_SETRESUID = 208 + SYS_GETRESUID = 209 + SYS_SETRESGID = 210 + SYS_GETRESGID = 211 + SYS_CHOWN = 212 + SYS_SETUID = 213 + SYS_SETGID = 214 + SYS_SETFSUID = 215 + SYS_SETFSGID = 216 + SYS_PIVOT_ROOT = 217 + SYS_MINCORE = 218 + SYS_MADVISE = 219 + SYS_GETDENTS64 = 220 + SYS_READAHEAD = 222 + SYS_SETXATTR = 224 + SYS_LSETXATTR = 225 + SYS_FSETXATTR = 226 + SYS_GETXATTR = 227 + SYS_LGETXATTR = 228 + SYS_FGETXATTR = 229 + SYS_LISTXATTR = 230 + SYS_LLISTXATTR = 231 + SYS_FLISTXATTR = 232 + SYS_REMOVEXATTR = 233 + SYS_LREMOVEXATTR = 234 + SYS_FREMOVEXATTR = 235 + SYS_GETTID = 236 + SYS_TKILL = 237 + SYS_FUTEX = 238 + SYS_SCHED_SETAFFINITY = 239 + SYS_SCHED_GETAFFINITY = 240 + SYS_TGKILL = 241 + SYS_IO_SETUP = 243 + SYS_IO_DESTROY = 244 + SYS_IO_GETEVENTS = 245 + SYS_IO_SUBMIT = 246 + SYS_IO_CANCEL = 247 + SYS_EXIT_GROUP = 248 + SYS_EPOLL_CREATE = 249 + SYS_EPOLL_CTL = 250 + SYS_EPOLL_WAIT = 251 + SYS_SET_TID_ADDRESS = 252 + SYS_FADVISE64 = 253 + SYS_TIMER_CREATE = 254 + SYS_TIMER_SETTIME = 255 + SYS_TIMER_GETTIME = 256 + SYS_TIMER_GETOVERRUN = 257 + SYS_TIMER_DELETE = 258 + SYS_CLOCK_SETTIME = 259 + SYS_CLOCK_GETTIME = 260 + SYS_CLOCK_GETRES = 261 + SYS_CLOCK_NANOSLEEP = 262 + SYS_STATFS64 = 265 + SYS_FSTATFS64 = 266 + SYS_REMAP_FILE_PAGES = 267 + SYS_MBIND = 268 + SYS_GET_MEMPOLICY = 269 + SYS_SET_MEMPOLICY = 270 + SYS_MQ_OPEN = 271 + SYS_MQ_UNLINK = 272 + SYS_MQ_TIMEDSEND = 273 + SYS_MQ_TIMEDRECEIVE = 274 + SYS_MQ_NOTIFY = 275 + SYS_MQ_GETSETATTR = 276 + SYS_KEXEC_LOAD = 277 + SYS_ADD_KEY = 278 + SYS_REQUEST_KEY = 279 + SYS_KEYCTL = 280 + SYS_WAITID = 281 + SYS_IOPRIO_SET = 282 + SYS_IOPRIO_GET = 283 + SYS_INOTIFY_INIT = 284 + SYS_INOTIFY_ADD_WATCH = 285 + SYS_INOTIFY_RM_WATCH = 286 + SYS_MIGRATE_PAGES = 287 + SYS_OPENAT = 288 + SYS_MKDIRAT = 289 + SYS_MKNODAT = 290 + SYS_FCHOWNAT = 291 + SYS_FUTIMESAT = 292 + SYS_NEWFSTATAT = 293 + SYS_UNLINKAT = 294 + SYS_RENAMEAT = 295 + SYS_LINKAT = 296 + SYS_SYMLINKAT = 297 + SYS_READLINKAT = 298 + SYS_FCHMODAT = 299 + SYS_FACCESSAT = 300 + SYS_PSELECT6 = 301 + SYS_PPOLL = 302 + SYS_UNSHARE = 303 + SYS_SET_ROBUST_LIST = 304 + SYS_GET_ROBUST_LIST = 305 + SYS_SPLICE = 306 + SYS_SYNC_FILE_RANGE = 307 + SYS_TEE = 308 + SYS_VMSPLICE = 309 + SYS_MOVE_PAGES = 310 + SYS_GETCPU = 311 + SYS_EPOLL_PWAIT = 312 + SYS_UTIMES = 313 + SYS_FALLOCATE = 314 + SYS_UTIMENSAT = 315 + SYS_SIGNALFD = 316 + SYS_TIMERFD = 317 + SYS_EVENTFD = 318 + SYS_TIMERFD_CREATE = 319 + SYS_TIMERFD_SETTIME = 320 + SYS_TIMERFD_GETTIME = 321 + SYS_SIGNALFD4 = 322 + SYS_EVENTFD2 = 323 + SYS_INOTIFY_INIT1 = 324 + SYS_PIPE2 = 325 + SYS_DUP3 = 326 + SYS_EPOLL_CREATE1 = 327 + SYS_PREADV = 328 + SYS_PWRITEV = 329 + SYS_RT_TGSIGQUEUEINFO = 330 + SYS_PERF_EVENT_OPEN = 331 + SYS_FANOTIFY_INIT = 332 + SYS_FANOTIFY_MARK = 333 + SYS_PRLIMIT64 = 334 + SYS_NAME_TO_HANDLE_AT = 335 + SYS_OPEN_BY_HANDLE_AT = 336 + SYS_CLOCK_ADJTIME = 337 + SYS_SYNCFS = 338 + SYS_SETNS = 339 + SYS_PROCESS_VM_READV = 340 + SYS_PROCESS_VM_WRITEV = 341 + SYS_S390_RUNTIME_INSTR = 342 + SYS_KCMP = 343 + SYS_FINIT_MODULE = 344 + SYS_SCHED_SETATTR = 345 + SYS_SCHED_GETATTR = 346 + SYS_RENAMEAT2 = 347 + SYS_SECCOMP = 348 + SYS_GETRANDOM = 349 + SYS_MEMFD_CREATE = 350 + SYS_BPF = 351 + SYS_S390_PCI_MMIO_WRITE = 352 + SYS_S390_PCI_MMIO_READ = 353 + SYS_EXECVEAT = 354 + SYS_USERFAULTFD = 355 + SYS_MEMBARRIER = 356 + SYS_RECVMMSG = 357 + SYS_SENDMMSG = 358 + SYS_SOCKET = 359 + SYS_SOCKETPAIR = 360 + SYS_BIND = 361 + SYS_CONNECT = 362 + SYS_LISTEN = 363 + SYS_ACCEPT4 = 364 + SYS_GETSOCKOPT = 365 + SYS_SETSOCKOPT = 366 + SYS_GETSOCKNAME = 367 + SYS_GETPEERNAME = 368 + SYS_SENDTO = 369 + SYS_SENDMSG = 370 + SYS_RECVFROM = 371 + SYS_RECVMSG = 372 + SYS_SHUTDOWN = 373 + SYS_MLOCK2 = 374 + SYS_COPY_FILE_RANGE = 375 + SYS_PREADV2 = 376 + SYS_PWRITEV2 = 377 + SYS_S390_GUARDED_STORAGE = 378 + SYS_STATX = 379 + SYS_S390_STHYI = 380 + SYS_KEXEC_FILE_LOAD = 381 + SYS_IO_PGETEVENTS = 382 + SYS_RSEQ = 383 + SYS_PKEY_MPROTECT = 384 + SYS_PKEY_ALLOC = 385 + SYS_PKEY_FREE = 386 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index dd78abb..620f271 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -1,377 +1,408 @@ -// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/include /tmp/include/asm/unistd.h +// go run linux/mksysnum.go -Wall -Werror -static -I/tmp/sparc64/include /tmp/sparc64/include/asm/unistd.h // Code generated by the command above; see README.md. DO NOT EDIT. -// +build sparc64,linux +//go:build sparc64 && linux package unix const ( - SYS_RESTART_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAIT4 = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECV = 11 - SYS_CHDIR = 12 - SYS_CHOWN = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LCHOWN = 16 - SYS_BRK = 17 - SYS_PERFCTR = 18 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_CAPGET = 21 - SYS_CAPSET = 22 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_VMSPLICE = 25 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_SIGALTSTACK = 28 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_STAT = 38 - SYS_SENDFILE = 39 - SYS_LSTAT = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_UMOUNT2 = 45 - SYS_SETGID = 46 - SYS_GETGID = 47 - SYS_SIGNAL = 48 - SYS_GETEUID = 49 - SYS_GETEGID = 50 - SYS_ACCT = 51 - SYS_MEMORY_ORDERING = 52 - SYS_IOCTL = 54 - SYS_REBOOT = 55 - SYS_SYMLINK = 57 - SYS_READLINK = 58 - SYS_EXECVE = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_FSTAT = 62 - SYS_FSTAT64 = 63 - SYS_GETPAGESIZE = 64 - SYS_MSYNC = 65 - SYS_VFORK = 66 - SYS_PREAD64 = 67 - SYS_PWRITE64 = 68 - SYS_MMAP = 71 - SYS_MUNMAP = 73 - SYS_MPROTECT = 74 - SYS_MADVISE = 75 - SYS_VHANGUP = 76 - SYS_MINCORE = 78 - SYS_GETGROUPS = 79 - SYS_SETGROUPS = 80 - SYS_GETPGRP = 81 - SYS_SETITIMER = 83 - SYS_SWAPON = 85 - SYS_GETITIMER = 86 - SYS_SETHOSTNAME = 88 - SYS_DUP2 = 90 - SYS_FCNTL = 92 - SYS_SELECT = 93 - SYS_FSYNC = 95 - SYS_SETPRIORITY = 96 - SYS_SOCKET = 97 - SYS_CONNECT = 98 - SYS_ACCEPT = 99 - SYS_GETPRIORITY = 100 - SYS_RT_SIGRETURN = 101 - SYS_RT_SIGACTION = 102 - SYS_RT_SIGPROCMASK = 103 - SYS_RT_SIGPENDING = 104 - SYS_RT_SIGTIMEDWAIT = 105 - SYS_RT_SIGQUEUEINFO = 106 - SYS_RT_SIGSUSPEND = 107 - SYS_SETRESUID = 108 - SYS_GETRESUID = 109 - SYS_SETRESGID = 110 - SYS_GETRESGID = 111 - SYS_RECVMSG = 113 - SYS_SENDMSG = 114 - SYS_GETTIMEOFDAY = 116 - SYS_GETRUSAGE = 117 - SYS_GETSOCKOPT = 118 - SYS_GETCWD = 119 - SYS_READV = 120 - SYS_WRITEV = 121 - SYS_SETTIMEOFDAY = 122 - SYS_FCHOWN = 123 - SYS_FCHMOD = 124 - SYS_RECVFROM = 125 - SYS_SETREUID = 126 - SYS_SETREGID = 127 - SYS_RENAME = 128 - SYS_TRUNCATE = 129 - SYS_FTRUNCATE = 130 - SYS_FLOCK = 131 - SYS_LSTAT64 = 132 - SYS_SENDTO = 133 - SYS_SHUTDOWN = 134 - SYS_SOCKETPAIR = 135 - SYS_MKDIR = 136 - SYS_RMDIR = 137 - SYS_UTIMES = 138 - SYS_STAT64 = 139 - SYS_SENDFILE64 = 140 - SYS_GETPEERNAME = 141 - SYS_FUTEX = 142 - SYS_GETTID = 143 - SYS_GETRLIMIT = 144 - SYS_SETRLIMIT = 145 - SYS_PIVOT_ROOT = 146 - SYS_PRCTL = 147 - SYS_PCICONFIG_READ = 148 - SYS_PCICONFIG_WRITE = 149 - SYS_GETSOCKNAME = 150 - SYS_INOTIFY_INIT = 151 - SYS_INOTIFY_ADD_WATCH = 152 - SYS_POLL = 153 - SYS_GETDENTS64 = 154 - SYS_INOTIFY_RM_WATCH = 156 - SYS_STATFS = 157 - SYS_FSTATFS = 158 - SYS_UMOUNT = 159 - SYS_SCHED_SET_AFFINITY = 160 - SYS_SCHED_GET_AFFINITY = 161 - SYS_GETDOMAINNAME = 162 - SYS_SETDOMAINNAME = 163 - SYS_UTRAP_INSTALL = 164 - SYS_QUOTACTL = 165 - SYS_SET_TID_ADDRESS = 166 - SYS_MOUNT = 167 - SYS_USTAT = 168 - SYS_SETXATTR = 169 - SYS_LSETXATTR = 170 - SYS_FSETXATTR = 171 - SYS_GETXATTR = 172 - SYS_LGETXATTR = 173 - SYS_GETDENTS = 174 - SYS_SETSID = 175 - SYS_FCHDIR = 176 - SYS_FGETXATTR = 177 - SYS_LISTXATTR = 178 - SYS_LLISTXATTR = 179 - SYS_FLISTXATTR = 180 - SYS_REMOVEXATTR = 181 - SYS_LREMOVEXATTR = 182 - SYS_SIGPENDING = 183 - SYS_QUERY_MODULE = 184 - SYS_SETPGID = 185 - SYS_FREMOVEXATTR = 186 - SYS_TKILL = 187 - SYS_EXIT_GROUP = 188 - SYS_UNAME = 189 - SYS_INIT_MODULE = 190 - SYS_PERSONALITY = 191 - SYS_REMAP_FILE_PAGES = 192 - SYS_EPOLL_CREATE = 193 - SYS_EPOLL_CTL = 194 - SYS_EPOLL_WAIT = 195 - SYS_IOPRIO_SET = 196 - SYS_GETPPID = 197 - SYS_SIGACTION = 198 - SYS_SGETMASK = 199 - SYS_SSETMASK = 200 - SYS_SIGSUSPEND = 201 - SYS_OLDLSTAT = 202 - SYS_USELIB = 203 - SYS_READDIR = 204 - SYS_READAHEAD = 205 - SYS_SOCKETCALL = 206 - SYS_SYSLOG = 207 - SYS_LOOKUP_DCOOKIE = 208 - SYS_FADVISE64 = 209 - SYS_FADVISE64_64 = 210 - SYS_TGKILL = 211 - SYS_WAITPID = 212 - SYS_SWAPOFF = 213 - SYS_SYSINFO = 214 - SYS_IPC = 215 - SYS_SIGRETURN = 216 - SYS_CLONE = 217 - SYS_IOPRIO_GET = 218 - SYS_ADJTIMEX = 219 - SYS_SIGPROCMASK = 220 - SYS_CREATE_MODULE = 221 - SYS_DELETE_MODULE = 222 - SYS_GET_KERNEL_SYMS = 223 - SYS_GETPGID = 224 - SYS_BDFLUSH = 225 - SYS_SYSFS = 226 - SYS_AFS_SYSCALL = 227 - SYS_SETFSUID = 228 - SYS_SETFSGID = 229 - SYS__NEWSELECT = 230 - SYS_SPLICE = 232 - SYS_STIME = 233 - SYS_STATFS64 = 234 - SYS_FSTATFS64 = 235 - SYS__LLSEEK = 236 - SYS_MLOCK = 237 - SYS_MUNLOCK = 238 - SYS_MLOCKALL = 239 - SYS_MUNLOCKALL = 240 - SYS_SCHED_SETPARAM = 241 - SYS_SCHED_GETPARAM = 242 - SYS_SCHED_SETSCHEDULER = 243 - SYS_SCHED_GETSCHEDULER = 244 - SYS_SCHED_YIELD = 245 - SYS_SCHED_GET_PRIORITY_MAX = 246 - SYS_SCHED_GET_PRIORITY_MIN = 247 - SYS_SCHED_RR_GET_INTERVAL = 248 - SYS_NANOSLEEP = 249 - SYS_MREMAP = 250 - SYS__SYSCTL = 251 - SYS_GETSID = 252 - SYS_FDATASYNC = 253 - SYS_NFSSERVCTL = 254 - SYS_SYNC_FILE_RANGE = 255 - SYS_CLOCK_SETTIME = 256 - SYS_CLOCK_GETTIME = 257 - SYS_CLOCK_GETRES = 258 - SYS_CLOCK_NANOSLEEP = 259 - SYS_SCHED_GETAFFINITY = 260 - SYS_SCHED_SETAFFINITY = 261 - SYS_TIMER_SETTIME = 262 - SYS_TIMER_GETTIME = 263 - SYS_TIMER_GETOVERRUN = 264 - SYS_TIMER_DELETE = 265 - SYS_TIMER_CREATE = 266 - SYS_VSERVER = 267 - SYS_IO_SETUP = 268 - SYS_IO_DESTROY = 269 - SYS_IO_SUBMIT = 270 - SYS_IO_CANCEL = 271 - SYS_IO_GETEVENTS = 272 - SYS_MQ_OPEN = 273 - SYS_MQ_UNLINK = 274 - SYS_MQ_TIMEDSEND = 275 - SYS_MQ_TIMEDRECEIVE = 276 - SYS_MQ_NOTIFY = 277 - SYS_MQ_GETSETATTR = 278 - SYS_WAITID = 279 - SYS_TEE = 280 - SYS_ADD_KEY = 281 - SYS_REQUEST_KEY = 282 - SYS_KEYCTL = 283 - SYS_OPENAT = 284 - SYS_MKDIRAT = 285 - SYS_MKNODAT = 286 - SYS_FCHOWNAT = 287 - SYS_FUTIMESAT = 288 - SYS_FSTATAT64 = 289 - SYS_UNLINKAT = 290 - SYS_RENAMEAT = 291 - SYS_LINKAT = 292 - SYS_SYMLINKAT = 293 - SYS_READLINKAT = 294 - SYS_FCHMODAT = 295 - SYS_FACCESSAT = 296 - SYS_PSELECT6 = 297 - SYS_PPOLL = 298 - SYS_UNSHARE = 299 - SYS_SET_ROBUST_LIST = 300 - SYS_GET_ROBUST_LIST = 301 - SYS_MIGRATE_PAGES = 302 - SYS_MBIND = 303 - SYS_GET_MEMPOLICY = 304 - SYS_SET_MEMPOLICY = 305 - SYS_KEXEC_LOAD = 306 - SYS_MOVE_PAGES = 307 - SYS_GETCPU = 308 - SYS_EPOLL_PWAIT = 309 - SYS_UTIMENSAT = 310 - SYS_SIGNALFD = 311 - SYS_TIMERFD_CREATE = 312 - SYS_EVENTFD = 313 - SYS_FALLOCATE = 314 - SYS_TIMERFD_SETTIME = 315 - SYS_TIMERFD_GETTIME = 316 - SYS_SIGNALFD4 = 317 - SYS_EVENTFD2 = 318 - SYS_EPOLL_CREATE1 = 319 - SYS_DUP3 = 320 - SYS_PIPE2 = 321 - SYS_INOTIFY_INIT1 = 322 - SYS_ACCEPT4 = 323 - SYS_PREADV = 324 - SYS_PWRITEV = 325 - SYS_RT_TGSIGQUEUEINFO = 326 - SYS_PERF_EVENT_OPEN = 327 - SYS_RECVMMSG = 328 - SYS_FANOTIFY_INIT = 329 - SYS_FANOTIFY_MARK = 330 - SYS_PRLIMIT64 = 331 - SYS_NAME_TO_HANDLE_AT = 332 - SYS_OPEN_BY_HANDLE_AT = 333 - SYS_CLOCK_ADJTIME = 334 - SYS_SYNCFS = 335 - SYS_SENDMMSG = 336 - SYS_SETNS = 337 - SYS_PROCESS_VM_READV = 338 - SYS_PROCESS_VM_WRITEV = 339 - SYS_KERN_FEATURES = 340 - SYS_KCMP = 341 - SYS_FINIT_MODULE = 342 - SYS_SCHED_SETATTR = 343 - SYS_SCHED_GETATTR = 344 - SYS_RENAMEAT2 = 345 - SYS_SECCOMP = 346 - SYS_GETRANDOM = 347 - SYS_MEMFD_CREATE = 348 - SYS_BPF = 349 - SYS_EXECVEAT = 350 - SYS_MEMBARRIER = 351 - SYS_USERFAULTFD = 352 - SYS_BIND = 353 - SYS_LISTEN = 354 - SYS_SETSOCKOPT = 355 - SYS_MLOCK2 = 356 - SYS_COPY_FILE_RANGE = 357 - SYS_PREADV2 = 358 - SYS_PWRITEV2 = 359 - SYS_STATX = 360 - SYS_IO_PGETEVENTS = 361 - SYS_PKEY_MPROTECT = 362 - SYS_PKEY_ALLOC = 363 - SYS_PKEY_FREE = 364 - SYS_RSEQ = 365 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAIT4 = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECV = 11 + SYS_CHDIR = 12 + SYS_CHOWN = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BRK = 17 + SYS_PERFCTR = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_CAPGET = 21 + SYS_CAPSET = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_VMSPLICE = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_SIGALTSTACK = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_STAT = 38 + SYS_SENDFILE = 39 + SYS_LSTAT = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_UMOUNT2 = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_MEMORY_ORDERING = 52 + SYS_IOCTL = 54 + SYS_REBOOT = 55 + SYS_SYMLINK = 57 + SYS_READLINK = 58 + SYS_EXECVE = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_FSTAT = 62 + SYS_FSTAT64 = 63 + SYS_GETPAGESIZE = 64 + SYS_MSYNC = 65 + SYS_VFORK = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_MMAP = 71 + SYS_MUNMAP = 73 + SYS_MPROTECT = 74 + SYS_MADVISE = 75 + SYS_VHANGUP = 76 + SYS_MINCORE = 78 + SYS_GETGROUPS = 79 + SYS_SETGROUPS = 80 + SYS_GETPGRP = 81 + SYS_SETITIMER = 83 + SYS_SWAPON = 85 + SYS_GETITIMER = 86 + SYS_SETHOSTNAME = 88 + SYS_DUP2 = 90 + SYS_FCNTL = 92 + SYS_SELECT = 93 + SYS_FSYNC = 95 + SYS_SETPRIORITY = 96 + SYS_SOCKET = 97 + SYS_CONNECT = 98 + SYS_ACCEPT = 99 + SYS_GETPRIORITY = 100 + SYS_RT_SIGRETURN = 101 + SYS_RT_SIGACTION = 102 + SYS_RT_SIGPROCMASK = 103 + SYS_RT_SIGPENDING = 104 + SYS_RT_SIGTIMEDWAIT = 105 + SYS_RT_SIGQUEUEINFO = 106 + SYS_RT_SIGSUSPEND = 107 + SYS_SETRESUID = 108 + SYS_GETRESUID = 109 + SYS_SETRESGID = 110 + SYS_GETRESGID = 111 + SYS_RECVMSG = 113 + SYS_SENDMSG = 114 + SYS_GETTIMEOFDAY = 116 + SYS_GETRUSAGE = 117 + SYS_GETSOCKOPT = 118 + SYS_GETCWD = 119 + SYS_READV = 120 + SYS_WRITEV = 121 + SYS_SETTIMEOFDAY = 122 + SYS_FCHOWN = 123 + SYS_FCHMOD = 124 + SYS_RECVFROM = 125 + SYS_SETREUID = 126 + SYS_SETREGID = 127 + SYS_RENAME = 128 + SYS_TRUNCATE = 129 + SYS_FTRUNCATE = 130 + SYS_FLOCK = 131 + SYS_LSTAT64 = 132 + SYS_SENDTO = 133 + SYS_SHUTDOWN = 134 + SYS_SOCKETPAIR = 135 + SYS_MKDIR = 136 + SYS_RMDIR = 137 + SYS_UTIMES = 138 + SYS_STAT64 = 139 + SYS_SENDFILE64 = 140 + SYS_GETPEERNAME = 141 + SYS_FUTEX = 142 + SYS_GETTID = 143 + SYS_GETRLIMIT = 144 + SYS_SETRLIMIT = 145 + SYS_PIVOT_ROOT = 146 + SYS_PRCTL = 147 + SYS_PCICONFIG_READ = 148 + SYS_PCICONFIG_WRITE = 149 + SYS_GETSOCKNAME = 150 + SYS_INOTIFY_INIT = 151 + SYS_INOTIFY_ADD_WATCH = 152 + SYS_POLL = 153 + SYS_GETDENTS64 = 154 + SYS_INOTIFY_RM_WATCH = 156 + SYS_STATFS = 157 + SYS_FSTATFS = 158 + SYS_UMOUNT = 159 + SYS_SCHED_SET_AFFINITY = 160 + SYS_SCHED_GET_AFFINITY = 161 + SYS_GETDOMAINNAME = 162 + SYS_SETDOMAINNAME = 163 + SYS_UTRAP_INSTALL = 164 + SYS_QUOTACTL = 165 + SYS_SET_TID_ADDRESS = 166 + SYS_MOUNT = 167 + SYS_USTAT = 168 + SYS_SETXATTR = 169 + SYS_LSETXATTR = 170 + SYS_FSETXATTR = 171 + SYS_GETXATTR = 172 + SYS_LGETXATTR = 173 + SYS_GETDENTS = 174 + SYS_SETSID = 175 + SYS_FCHDIR = 176 + SYS_FGETXATTR = 177 + SYS_LISTXATTR = 178 + SYS_LLISTXATTR = 179 + SYS_FLISTXATTR = 180 + SYS_REMOVEXATTR = 181 + SYS_LREMOVEXATTR = 182 + SYS_SIGPENDING = 183 + SYS_QUERY_MODULE = 184 + SYS_SETPGID = 185 + SYS_FREMOVEXATTR = 186 + SYS_TKILL = 187 + SYS_EXIT_GROUP = 188 + SYS_UNAME = 189 + SYS_INIT_MODULE = 190 + SYS_PERSONALITY = 191 + SYS_REMAP_FILE_PAGES = 192 + SYS_EPOLL_CREATE = 193 + SYS_EPOLL_CTL = 194 + SYS_EPOLL_WAIT = 195 + SYS_IOPRIO_SET = 196 + SYS_GETPPID = 197 + SYS_SIGACTION = 198 + SYS_SGETMASK = 199 + SYS_SSETMASK = 200 + SYS_SIGSUSPEND = 201 + SYS_OLDLSTAT = 202 + SYS_USELIB = 203 + SYS_READDIR = 204 + SYS_READAHEAD = 205 + SYS_SOCKETCALL = 206 + SYS_SYSLOG = 207 + SYS_LOOKUP_DCOOKIE = 208 + SYS_FADVISE64 = 209 + SYS_FADVISE64_64 = 210 + SYS_TGKILL = 211 + SYS_WAITPID = 212 + SYS_SWAPOFF = 213 + SYS_SYSINFO = 214 + SYS_IPC = 215 + SYS_SIGRETURN = 216 + SYS_CLONE = 217 + SYS_IOPRIO_GET = 218 + SYS_ADJTIMEX = 219 + SYS_SIGPROCMASK = 220 + SYS_CREATE_MODULE = 221 + SYS_DELETE_MODULE = 222 + SYS_GET_KERNEL_SYMS = 223 + SYS_GETPGID = 224 + SYS_BDFLUSH = 225 + SYS_SYSFS = 226 + SYS_AFS_SYSCALL = 227 + SYS_SETFSUID = 228 + SYS_SETFSGID = 229 + SYS__NEWSELECT = 230 + SYS_SPLICE = 232 + SYS_STIME = 233 + SYS_STATFS64 = 234 + SYS_FSTATFS64 = 235 + SYS__LLSEEK = 236 + SYS_MLOCK = 237 + SYS_MUNLOCK = 238 + SYS_MLOCKALL = 239 + SYS_MUNLOCKALL = 240 + SYS_SCHED_SETPARAM = 241 + SYS_SCHED_GETPARAM = 242 + SYS_SCHED_SETSCHEDULER = 243 + SYS_SCHED_GETSCHEDULER = 244 + SYS_SCHED_YIELD = 245 + SYS_SCHED_GET_PRIORITY_MAX = 246 + SYS_SCHED_GET_PRIORITY_MIN = 247 + SYS_SCHED_RR_GET_INTERVAL = 248 + SYS_NANOSLEEP = 249 + SYS_MREMAP = 250 + SYS__SYSCTL = 251 + SYS_GETSID = 252 + SYS_FDATASYNC = 253 + SYS_NFSSERVCTL = 254 + SYS_SYNC_FILE_RANGE = 255 + SYS_CLOCK_SETTIME = 256 + SYS_CLOCK_GETTIME = 257 + SYS_CLOCK_GETRES = 258 + SYS_CLOCK_NANOSLEEP = 259 + SYS_SCHED_GETAFFINITY = 260 + SYS_SCHED_SETAFFINITY = 261 + SYS_TIMER_SETTIME = 262 + SYS_TIMER_GETTIME = 263 + SYS_TIMER_GETOVERRUN = 264 + SYS_TIMER_DELETE = 265 + SYS_TIMER_CREATE = 266 + SYS_VSERVER = 267 + SYS_IO_SETUP = 268 + SYS_IO_DESTROY = 269 + SYS_IO_SUBMIT = 270 + SYS_IO_CANCEL = 271 + SYS_IO_GETEVENTS = 272 + SYS_MQ_OPEN = 273 + SYS_MQ_UNLINK = 274 + SYS_MQ_TIMEDSEND = 275 + SYS_MQ_TIMEDRECEIVE = 276 + SYS_MQ_NOTIFY = 277 + SYS_MQ_GETSETATTR = 278 + SYS_WAITID = 279 + SYS_TEE = 280 + SYS_ADD_KEY = 281 + SYS_REQUEST_KEY = 282 + SYS_KEYCTL = 283 + SYS_OPENAT = 284 + SYS_MKDIRAT = 285 + SYS_MKNODAT = 286 + SYS_FCHOWNAT = 287 + SYS_FUTIMESAT = 288 + SYS_FSTATAT64 = 289 + SYS_UNLINKAT = 290 + SYS_RENAMEAT = 291 + SYS_LINKAT = 292 + SYS_SYMLINKAT = 293 + SYS_READLINKAT = 294 + SYS_FCHMODAT = 295 + SYS_FACCESSAT = 296 + SYS_PSELECT6 = 297 + SYS_PPOLL = 298 + SYS_UNSHARE = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_GET_ROBUST_LIST = 301 + SYS_MIGRATE_PAGES = 302 + SYS_MBIND = 303 + SYS_GET_MEMPOLICY = 304 + SYS_SET_MEMPOLICY = 305 + SYS_KEXEC_LOAD = 306 + SYS_MOVE_PAGES = 307 + SYS_GETCPU = 308 + SYS_EPOLL_PWAIT = 309 + SYS_UTIMENSAT = 310 + SYS_SIGNALFD = 311 + SYS_TIMERFD_CREATE = 312 + SYS_EVENTFD = 313 + SYS_FALLOCATE = 314 + SYS_TIMERFD_SETTIME = 315 + SYS_TIMERFD_GETTIME = 316 + SYS_SIGNALFD4 = 317 + SYS_EVENTFD2 = 318 + SYS_EPOLL_CREATE1 = 319 + SYS_DUP3 = 320 + SYS_PIPE2 = 321 + SYS_INOTIFY_INIT1 = 322 + SYS_ACCEPT4 = 323 + SYS_PREADV = 324 + SYS_PWRITEV = 325 + SYS_RT_TGSIGQUEUEINFO = 326 + SYS_PERF_EVENT_OPEN = 327 + SYS_RECVMMSG = 328 + SYS_FANOTIFY_INIT = 329 + SYS_FANOTIFY_MARK = 330 + SYS_PRLIMIT64 = 331 + SYS_NAME_TO_HANDLE_AT = 332 + SYS_OPEN_BY_HANDLE_AT = 333 + SYS_CLOCK_ADJTIME = 334 + SYS_SYNCFS = 335 + SYS_SENDMMSG = 336 + SYS_SETNS = 337 + SYS_PROCESS_VM_READV = 338 + SYS_PROCESS_VM_WRITEV = 339 + SYS_KERN_FEATURES = 340 + SYS_KCMP = 341 + SYS_FINIT_MODULE = 342 + SYS_SCHED_SETATTR = 343 + SYS_SCHED_GETATTR = 344 + SYS_RENAMEAT2 = 345 + SYS_SECCOMP = 346 + SYS_GETRANDOM = 347 + SYS_MEMFD_CREATE = 348 + SYS_BPF = 349 + SYS_EXECVEAT = 350 + SYS_MEMBARRIER = 351 + SYS_USERFAULTFD = 352 + SYS_BIND = 353 + SYS_LISTEN = 354 + SYS_SETSOCKOPT = 355 + SYS_MLOCK2 = 356 + SYS_COPY_FILE_RANGE = 357 + SYS_PREADV2 = 358 + SYS_PWRITEV2 = 359 + SYS_STATX = 360 + SYS_IO_PGETEVENTS = 361 + SYS_PKEY_MPROTECT = 362 + SYS_PKEY_ALLOC = 363 + SYS_PKEY_FREE = 364 + SYS_RSEQ = 365 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 + SYS_SET_MEMPOLICY_HOME_NODE = 450 + SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 + SYS_OPEN_TREE_ATTR = 467 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go index e66a8c9..b2aa8cd 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go @@ -1,7 +1,7 @@ // go run mksysnum.go http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,netbsd +//go:build 386 && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go index 42c788f..524a1b1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go @@ -1,7 +1,7 @@ // go run mksysnum.go http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,netbsd +//go:build amd64 && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go index 0a07571..d59b943 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go @@ -1,7 +1,7 @@ // go run mksysnum.go http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,netbsd +//go:build arm && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go index 0291c09..31e771d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go @@ -1,7 +1,7 @@ // go run mksysnum.go http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; DO NOT EDIT. -// +build arm64,netbsd +//go:build arm64 && netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go index b0207d1..9fd77c6 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go @@ -1,10 +1,11 @@ // go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,openbsd +//go:build 386 && openbsd package unix +// Deprecated: Use libc wrappers instead of direct syscalls. const ( SYS_EXIT = 1 // { void sys_exit(int rval); } SYS_FORK = 2 // { int sys_fork(void); } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go index f0dec6f..af10af2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go @@ -1,10 +1,11 @@ // go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,openbsd +//go:build amd64 && openbsd package unix +// Deprecated: Use libc wrappers instead of direct syscalls. const ( SYS_EXIT = 1 // { void sys_exit(int rval); } SYS_FORK = 2 // { int sys_fork(void); } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go index 33d1dc5..cc2028a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go @@ -1,10 +1,11 @@ // go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,openbsd +//go:build arm && openbsd package unix +// Deprecated: Use libc wrappers instead of direct syscalls. const ( SYS_EXIT = 1 // { void sys_exit(int rval); } SYS_FORK = 2 // { int sys_fork(void); } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go index fe2b689..c06dd44 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go @@ -1,10 +1,11 @@ // go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,openbsd +//go:build arm64 && openbsd package unix +// Deprecated: Use libc wrappers instead of direct syscalls. const ( SYS_EXIT = 1 // { void sys_exit(int rval); } SYS_FORK = 2 // { int sys_fork(void); } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go new file mode 100644 index 0000000..9ddbf3e --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go @@ -0,0 +1,221 @@ +// go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build mips64 && openbsd + +package unix + +// Deprecated: Use libc wrappers instead of direct syscalls. +const ( + SYS_EXIT = 1 // { void sys_exit(int rval); } + SYS_FORK = 2 // { int sys_fork(void); } + SYS_READ = 3 // { ssize_t sys_read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t sys_write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int sys_open(const char *path, int flags, ... mode_t mode); } + SYS_CLOSE = 6 // { int sys_close(int fd); } + SYS_GETENTROPY = 7 // { int sys_getentropy(void *buf, size_t nbyte); } + SYS___TFORK = 8 // { int sys___tfork(const struct __tfork *param, size_t psize); } + SYS_LINK = 9 // { int sys_link(const char *path, const char *link); } + SYS_UNLINK = 10 // { int sys_unlink(const char *path); } + SYS_WAIT4 = 11 // { pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage); } + SYS_CHDIR = 12 // { int sys_chdir(const char *path); } + SYS_FCHDIR = 13 // { int sys_fchdir(int fd); } + SYS_MKNOD = 14 // { int sys_mknod(const char *path, mode_t mode, dev_t dev); } + SYS_CHMOD = 15 // { int sys_chmod(const char *path, mode_t mode); } + SYS_CHOWN = 16 // { int sys_chown(const char *path, uid_t uid, gid_t gid); } + SYS_OBREAK = 17 // { int sys_obreak(char *nsize); } break + SYS_GETDTABLECOUNT = 18 // { int sys_getdtablecount(void); } + SYS_GETRUSAGE = 19 // { int sys_getrusage(int who, struct rusage *rusage); } + SYS_GETPID = 20 // { pid_t sys_getpid(void); } + SYS_MOUNT = 21 // { int sys_mount(const char *type, const char *path, int flags, void *data); } + SYS_UNMOUNT = 22 // { int sys_unmount(const char *path, int flags); } + SYS_SETUID = 23 // { int sys_setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t sys_getuid(void); } + SYS_GETEUID = 25 // { uid_t sys_geteuid(void); } + SYS_PTRACE = 26 // { int sys_ptrace(int req, pid_t pid, caddr_t addr, int data); } + SYS_RECVMSG = 27 // { ssize_t sys_recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { ssize_t sys_sendmsg(int s, const struct msghdr *msg, int flags); } + SYS_RECVFROM = 29 // { ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); } + SYS_ACCEPT = 30 // { int sys_accept(int s, struct sockaddr *name, socklen_t *anamelen); } + SYS_GETPEERNAME = 31 // { int sys_getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_GETSOCKNAME = 32 // { int sys_getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_ACCESS = 33 // { int sys_access(const char *path, int amode); } + SYS_CHFLAGS = 34 // { int sys_chflags(const char *path, u_int flags); } + SYS_FCHFLAGS = 35 // { int sys_fchflags(int fd, u_int flags); } + SYS_SYNC = 36 // { void sys_sync(void); } + SYS_MSYSCALL = 37 // { int sys_msyscall(void *addr, size_t len); } + SYS_STAT = 38 // { int sys_stat(const char *path, struct stat *ub); } + SYS_GETPPID = 39 // { pid_t sys_getppid(void); } + SYS_LSTAT = 40 // { int sys_lstat(const char *path, struct stat *ub); } + SYS_DUP = 41 // { int sys_dup(int fd); } + SYS_FSTATAT = 42 // { int sys_fstatat(int fd, const char *path, struct stat *buf, int flag); } + SYS_GETEGID = 43 // { gid_t sys_getegid(void); } + SYS_PROFIL = 44 // { int sys_profil(caddr_t samples, size_t size, u_long offset, u_int scale); } + SYS_KTRACE = 45 // { int sys_ktrace(const char *fname, int ops, int facs, pid_t pid); } + SYS_SIGACTION = 46 // { int sys_sigaction(int signum, const struct sigaction *nsa, struct sigaction *osa); } + SYS_GETGID = 47 // { gid_t sys_getgid(void); } + SYS_SIGPROCMASK = 48 // { int sys_sigprocmask(int how, sigset_t mask); } + SYS_SETLOGIN = 50 // { int sys_setlogin(const char *namebuf); } + SYS_ACCT = 51 // { int sys_acct(const char *path); } + SYS_SIGPENDING = 52 // { int sys_sigpending(void); } + SYS_FSTAT = 53 // { int sys_fstat(int fd, struct stat *sb); } + SYS_IOCTL = 54 // { int sys_ioctl(int fd, u_long com, ... void *data); } + SYS_REBOOT = 55 // { int sys_reboot(int opt); } + SYS_REVOKE = 56 // { int sys_revoke(const char *path); } + SYS_SYMLINK = 57 // { int sys_symlink(const char *path, const char *link); } + SYS_READLINK = 58 // { ssize_t sys_readlink(const char *path, char *buf, size_t count); } + SYS_EXECVE = 59 // { int sys_execve(const char *path, char * const *argp, char * const *envp); } + SYS_UMASK = 60 // { mode_t sys_umask(mode_t newmask); } + SYS_CHROOT = 61 // { int sys_chroot(const char *path); } + SYS_GETFSSTAT = 62 // { int sys_getfsstat(struct statfs *buf, size_t bufsize, int flags); } + SYS_STATFS = 63 // { int sys_statfs(const char *path, struct statfs *buf); } + SYS_FSTATFS = 64 // { int sys_fstatfs(int fd, struct statfs *buf); } + SYS_FHSTATFS = 65 // { int sys_fhstatfs(const fhandle_t *fhp, struct statfs *buf); } + SYS_VFORK = 66 // { int sys_vfork(void); } + SYS_GETTIMEOFDAY = 67 // { int sys_gettimeofday(struct timeval *tp, struct timezone *tzp); } + SYS_SETTIMEOFDAY = 68 // { int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp); } + SYS_SETITIMER = 69 // { int sys_setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); } + SYS_GETITIMER = 70 // { int sys_getitimer(int which, struct itimerval *itv); } + SYS_SELECT = 71 // { int sys_select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_KEVENT = 72 // { int sys_kevent(int fd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_MUNMAP = 73 // { int sys_munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int sys_mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int sys_madvise(void *addr, size_t len, int behav); } + SYS_UTIMES = 76 // { int sys_utimes(const char *path, const struct timeval *tptr); } + SYS_FUTIMES = 77 // { int sys_futimes(int fd, const struct timeval *tptr); } + SYS_GETGROUPS = 79 // { int sys_getgroups(int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int sys_setgroups(int gidsetsize, const gid_t *gidset); } + SYS_GETPGRP = 81 // { int sys_getpgrp(void); } + SYS_SETPGID = 82 // { int sys_setpgid(pid_t pid, pid_t pgid); } + SYS_FUTEX = 83 // { int sys_futex(uint32_t *f, int op, int val, const struct timespec *timeout, uint32_t *g); } + SYS_UTIMENSAT = 84 // { int sys_utimensat(int fd, const char *path, const struct timespec *times, int flag); } + SYS_FUTIMENS = 85 // { int sys_futimens(int fd, const struct timespec *times); } + SYS_KBIND = 86 // { int sys_kbind(const struct __kbind *param, size_t psize, int64_t proc_cookie); } + SYS_CLOCK_GETTIME = 87 // { int sys_clock_gettime(clockid_t clock_id, struct timespec *tp); } + SYS_CLOCK_SETTIME = 88 // { int sys_clock_settime(clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_GETRES = 89 // { int sys_clock_getres(clockid_t clock_id, struct timespec *tp); } + SYS_DUP2 = 90 // { int sys_dup2(int from, int to); } + SYS_NANOSLEEP = 91 // { int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } + SYS_FCNTL = 92 // { int sys_fcntl(int fd, int cmd, ... void *arg); } + SYS_ACCEPT4 = 93 // { int sys_accept4(int s, struct sockaddr *name, socklen_t *anamelen, int flags); } + SYS___THRSLEEP = 94 // { int sys___thrsleep(const volatile void *ident, clockid_t clock_id, const struct timespec *tp, void *lock, const int *abort); } + SYS_FSYNC = 95 // { int sys_fsync(int fd); } + SYS_SETPRIORITY = 96 // { int sys_setpriority(int which, id_t who, int prio); } + SYS_SOCKET = 97 // { int sys_socket(int domain, int type, int protocol); } + SYS_CONNECT = 98 // { int sys_connect(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_GETDENTS = 99 // { int sys_getdents(int fd, void *buf, size_t buflen); } + SYS_GETPRIORITY = 100 // { int sys_getpriority(int which, id_t who); } + SYS_PIPE2 = 101 // { int sys_pipe2(int *fdp, int flags); } + SYS_DUP3 = 102 // { int sys_dup3(int from, int to, int flags); } + SYS_SIGRETURN = 103 // { int sys_sigreturn(struct sigcontext *sigcntxp); } + SYS_BIND = 104 // { int sys_bind(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_SETSOCKOPT = 105 // { int sys_setsockopt(int s, int level, int name, const void *val, socklen_t valsize); } + SYS_LISTEN = 106 // { int sys_listen(int s, int backlog); } + SYS_CHFLAGSAT = 107 // { int sys_chflagsat(int fd, const char *path, u_int flags, int atflags); } + SYS_PLEDGE = 108 // { int sys_pledge(const char *promises, const char *execpromises); } + SYS_PPOLL = 109 // { int sys_ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); } + SYS_PSELECT = 110 // { int sys_pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); } + SYS_SIGSUSPEND = 111 // { int sys_sigsuspend(int mask); } + SYS_SENDSYSLOG = 112 // { int sys_sendsyslog(const char *buf, size_t nbyte, int flags); } + SYS_UNVEIL = 114 // { int sys_unveil(const char *path, const char *permissions); } + SYS___REALPATH = 115 // { int sys___realpath(const char *pathname, char *resolved); } + SYS_GETSOCKOPT = 118 // { int sys_getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); } + SYS_THRKILL = 119 // { int sys_thrkill(pid_t tid, int signum, void *tcb); } + SYS_READV = 120 // { ssize_t sys_readv(int fd, const struct iovec *iovp, int iovcnt); } + SYS_WRITEV = 121 // { ssize_t sys_writev(int fd, const struct iovec *iovp, int iovcnt); } + SYS_KILL = 122 // { int sys_kill(int pid, int signum); } + SYS_FCHOWN = 123 // { int sys_fchown(int fd, uid_t uid, gid_t gid); } + SYS_FCHMOD = 124 // { int sys_fchmod(int fd, mode_t mode); } + SYS_SETREUID = 126 // { int sys_setreuid(uid_t ruid, uid_t euid); } + SYS_SETREGID = 127 // { int sys_setregid(gid_t rgid, gid_t egid); } + SYS_RENAME = 128 // { int sys_rename(const char *from, const char *to); } + SYS_FLOCK = 131 // { int sys_flock(int fd, int how); } + SYS_MKFIFO = 132 // { int sys_mkfifo(const char *path, mode_t mode); } + SYS_SENDTO = 133 // { ssize_t sys_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); } + SYS_SHUTDOWN = 134 // { int sys_shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int sys_socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int sys_mkdir(const char *path, mode_t mode); } + SYS_RMDIR = 137 // { int sys_rmdir(const char *path); } + SYS_ADJTIME = 140 // { int sys_adjtime(const struct timeval *delta, struct timeval *olddelta); } + SYS_GETLOGIN_R = 141 // { int sys_getlogin_r(char *namebuf, u_int namelen); } + SYS_SETSID = 147 // { int sys_setsid(void); } + SYS_QUOTACTL = 148 // { int sys_quotactl(const char *path, int cmd, int uid, char *arg); } + SYS_NFSSVC = 155 // { int sys_nfssvc(int flag, void *argp); } + SYS_GETFH = 161 // { int sys_getfh(const char *fname, fhandle_t *fhp); } + SYS___TMPFD = 164 // { int sys___tmpfd(int flags); } + SYS_SYSARCH = 165 // { int sys_sysarch(int op, void *parms); } + SYS_PREAD = 173 // { ssize_t sys_pread(int fd, void *buf, size_t nbyte, int pad, off_t offset); } + SYS_PWRITE = 174 // { ssize_t sys_pwrite(int fd, const void *buf, size_t nbyte, int pad, off_t offset); } + SYS_SETGID = 181 // { int sys_setgid(gid_t gid); } + SYS_SETEGID = 182 // { int sys_setegid(gid_t egid); } + SYS_SETEUID = 183 // { int sys_seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { long sys_pathconf(const char *path, int name); } + SYS_FPATHCONF = 192 // { long sys_fpathconf(int fd, int name); } + SYS_SWAPCTL = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); } + SYS_GETRLIMIT = 194 // { int sys_getrlimit(int which, struct rlimit *rlp); } + SYS_SETRLIMIT = 195 // { int sys_setrlimit(int which, const struct rlimit *rlp); } + SYS_MMAP = 197 // { void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, long pad, off_t pos); } + SYS_LSEEK = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, int whence); } + SYS_TRUNCATE = 200 // { int sys_truncate(const char *path, int pad, off_t length); } + SYS_FTRUNCATE = 201 // { int sys_ftruncate(int fd, int pad, off_t length); } + SYS_SYSCTL = 202 // { int sys_sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_MLOCK = 203 // { int sys_mlock(const void *addr, size_t len); } + SYS_MUNLOCK = 204 // { int sys_munlock(const void *addr, size_t len); } + SYS_GETPGID = 207 // { pid_t sys_getpgid(pid_t pid); } + SYS_UTRACE = 209 // { int sys_utrace(const char *label, const void *addr, size_t len); } + SYS_SEMGET = 221 // { int sys_semget(key_t key, int nsems, int semflg); } + SYS_MSGGET = 225 // { int sys_msgget(key_t key, int msgflg); } + SYS_MSGSND = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } + SYS_MSGRCV = 227 // { int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_SHMAT = 228 // { void *sys_shmat(int shmid, const void *shmaddr, int shmflg); } + SYS_SHMDT = 230 // { int sys_shmdt(const void *shmaddr); } + SYS_MINHERIT = 250 // { int sys_minherit(void *addr, size_t len, int inherit); } + SYS_POLL = 252 // { int sys_poll(struct pollfd *fds, u_int nfds, int timeout); } + SYS_ISSETUGID = 253 // { int sys_issetugid(void); } + SYS_LCHOWN = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); } + SYS_GETSID = 255 // { pid_t sys_getsid(pid_t pid); } + SYS_MSYNC = 256 // { int sys_msync(void *addr, size_t len, int flags); } + SYS_PIPE = 263 // { int sys_pipe(int *fdp); } + SYS_FHOPEN = 264 // { int sys_fhopen(const fhandle_t *fhp, int flags); } + SYS_PREADV = 267 // { ssize_t sys_preadv(int fd, const struct iovec *iovp, int iovcnt, int pad, off_t offset); } + SYS_PWRITEV = 268 // { ssize_t sys_pwritev(int fd, const struct iovec *iovp, int iovcnt, int pad, off_t offset); } + SYS_KQUEUE = 269 // { int sys_kqueue(void); } + SYS_MLOCKALL = 271 // { int sys_mlockall(int flags); } + SYS_MUNLOCKALL = 272 // { int sys_munlockall(void); } + SYS_GETRESUID = 281 // { int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } + SYS_SETRESUID = 282 // { int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); } + SYS_GETRESGID = 283 // { int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } + SYS_SETRESGID = 284 // { int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); } + SYS_MQUERY = 286 // { void *sys_mquery(void *addr, size_t len, int prot, int flags, int fd, long pad, off_t pos); } + SYS_CLOSEFROM = 287 // { int sys_closefrom(int fd); } + SYS_SIGALTSTACK = 288 // { int sys_sigaltstack(const struct sigaltstack *nss, struct sigaltstack *oss); } + SYS_SHMGET = 289 // { int sys_shmget(key_t key, size_t size, int shmflg); } + SYS_SEMOP = 290 // { int sys_semop(int semid, struct sembuf *sops, size_t nsops); } + SYS_FHSTAT = 294 // { int sys_fhstat(const fhandle_t *fhp, struct stat *sb); } + SYS___SEMCTL = 295 // { int sys___semctl(int semid, int semnum, int cmd, union semun *arg); } + SYS_SHMCTL = 296 // { int sys_shmctl(int shmid, int cmd, struct shmid_ds *buf); } + SYS_MSGCTL = 297 // { int sys_msgctl(int msqid, int cmd, struct msqid_ds *buf); } + SYS_SCHED_YIELD = 298 // { int sys_sched_yield(void); } + SYS_GETTHRID = 299 // { pid_t sys_getthrid(void); } + SYS___THRWAKEUP = 301 // { int sys___thrwakeup(const volatile void *ident, int n); } + SYS___THREXIT = 302 // { void sys___threxit(pid_t *notdead); } + SYS___THRSIGDIVERT = 303 // { int sys___thrsigdivert(sigset_t sigmask, siginfo_t *info, const struct timespec *timeout); } + SYS___GETCWD = 304 // { int sys___getcwd(char *buf, size_t len); } + SYS_ADJFREQ = 305 // { int sys_adjfreq(const int64_t *freq, int64_t *oldfreq); } + SYS_SETRTABLE = 310 // { int sys_setrtable(int rtableid); } + SYS_GETRTABLE = 311 // { int sys_getrtable(void); } + SYS_FACCESSAT = 313 // { int sys_faccessat(int fd, const char *path, int amode, int flag); } + SYS_FCHMODAT = 314 // { int sys_fchmodat(int fd, const char *path, mode_t mode, int flag); } + SYS_FCHOWNAT = 315 // { int sys_fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flag); } + SYS_LINKAT = 317 // { int sys_linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); } + SYS_MKDIRAT = 318 // { int sys_mkdirat(int fd, const char *path, mode_t mode); } + SYS_MKFIFOAT = 319 // { int sys_mkfifoat(int fd, const char *path, mode_t mode); } + SYS_MKNODAT = 320 // { int sys_mknodat(int fd, const char *path, mode_t mode, dev_t dev); } + SYS_OPENAT = 321 // { int sys_openat(int fd, const char *path, int flags, ... mode_t mode); } + SYS_READLINKAT = 322 // { ssize_t sys_readlinkat(int fd, const char *path, char *buf, size_t count); } + SYS_RENAMEAT = 323 // { int sys_renameat(int fromfd, const char *from, int tofd, const char *to); } + SYS_SYMLINKAT = 324 // { int sys_symlinkat(const char *path, int fd, const char *link); } + SYS_UNLINKAT = 325 // { int sys_unlinkat(int fd, const char *path, int flag); } + SYS___SET_TCB = 329 // { void sys___set_tcb(void *tcb); } + SYS___GET_TCB = 330 // { void *sys___get_tcb(void); } +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go new file mode 100644 index 0000000..19a6ee4 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go @@ -0,0 +1,217 @@ +// go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build ppc64 && openbsd + +package unix + +const ( + SYS_EXIT = 1 // { void sys_exit(int rval); } + SYS_FORK = 2 // { int sys_fork(void); } + SYS_READ = 3 // { ssize_t sys_read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t sys_write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int sys_open(const char *path, int flags, ... mode_t mode); } + SYS_CLOSE = 6 // { int sys_close(int fd); } + SYS_GETENTROPY = 7 // { int sys_getentropy(void *buf, size_t nbyte); } + SYS___TFORK = 8 // { int sys___tfork(const struct __tfork *param, size_t psize); } + SYS_LINK = 9 // { int sys_link(const char *path, const char *link); } + SYS_UNLINK = 10 // { int sys_unlink(const char *path); } + SYS_WAIT4 = 11 // { pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage); } + SYS_CHDIR = 12 // { int sys_chdir(const char *path); } + SYS_FCHDIR = 13 // { int sys_fchdir(int fd); } + SYS_MKNOD = 14 // { int sys_mknod(const char *path, mode_t mode, dev_t dev); } + SYS_CHMOD = 15 // { int sys_chmod(const char *path, mode_t mode); } + SYS_CHOWN = 16 // { int sys_chown(const char *path, uid_t uid, gid_t gid); } + SYS_OBREAK = 17 // { int sys_obreak(char *nsize); } break + SYS_GETDTABLECOUNT = 18 // { int sys_getdtablecount(void); } + SYS_GETRUSAGE = 19 // { int sys_getrusage(int who, struct rusage *rusage); } + SYS_GETPID = 20 // { pid_t sys_getpid(void); } + SYS_MOUNT = 21 // { int sys_mount(const char *type, const char *path, int flags, void *data); } + SYS_UNMOUNT = 22 // { int sys_unmount(const char *path, int flags); } + SYS_SETUID = 23 // { int sys_setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t sys_getuid(void); } + SYS_GETEUID = 25 // { uid_t sys_geteuid(void); } + SYS_PTRACE = 26 // { int sys_ptrace(int req, pid_t pid, caddr_t addr, int data); } + SYS_RECVMSG = 27 // { ssize_t sys_recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { ssize_t sys_sendmsg(int s, const struct msghdr *msg, int flags); } + SYS_RECVFROM = 29 // { ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); } + SYS_ACCEPT = 30 // { int sys_accept(int s, struct sockaddr *name, socklen_t *anamelen); } + SYS_GETPEERNAME = 31 // { int sys_getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_GETSOCKNAME = 32 // { int sys_getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_ACCESS = 33 // { int sys_access(const char *path, int amode); } + SYS_CHFLAGS = 34 // { int sys_chflags(const char *path, u_int flags); } + SYS_FCHFLAGS = 35 // { int sys_fchflags(int fd, u_int flags); } + SYS_SYNC = 36 // { void sys_sync(void); } + SYS_STAT = 38 // { int sys_stat(const char *path, struct stat *ub); } + SYS_GETPPID = 39 // { pid_t sys_getppid(void); } + SYS_LSTAT = 40 // { int sys_lstat(const char *path, struct stat *ub); } + SYS_DUP = 41 // { int sys_dup(int fd); } + SYS_FSTATAT = 42 // { int sys_fstatat(int fd, const char *path, struct stat *buf, int flag); } + SYS_GETEGID = 43 // { gid_t sys_getegid(void); } + SYS_PROFIL = 44 // { int sys_profil(caddr_t samples, size_t size, u_long offset, u_int scale); } + SYS_KTRACE = 45 // { int sys_ktrace(const char *fname, int ops, int facs, pid_t pid); } + SYS_SIGACTION = 46 // { int sys_sigaction(int signum, const struct sigaction *nsa, struct sigaction *osa); } + SYS_GETGID = 47 // { gid_t sys_getgid(void); } + SYS_SIGPROCMASK = 48 // { int sys_sigprocmask(int how, sigset_t mask); } + SYS_SETLOGIN = 50 // { int sys_setlogin(const char *namebuf); } + SYS_ACCT = 51 // { int sys_acct(const char *path); } + SYS_SIGPENDING = 52 // { int sys_sigpending(void); } + SYS_FSTAT = 53 // { int sys_fstat(int fd, struct stat *sb); } + SYS_IOCTL = 54 // { int sys_ioctl(int fd, u_long com, ... void *data); } + SYS_REBOOT = 55 // { int sys_reboot(int opt); } + SYS_REVOKE = 56 // { int sys_revoke(const char *path); } + SYS_SYMLINK = 57 // { int sys_symlink(const char *path, const char *link); } + SYS_READLINK = 58 // { ssize_t sys_readlink(const char *path, char *buf, size_t count); } + SYS_EXECVE = 59 // { int sys_execve(const char *path, char * const *argp, char * const *envp); } + SYS_UMASK = 60 // { mode_t sys_umask(mode_t newmask); } + SYS_CHROOT = 61 // { int sys_chroot(const char *path); } + SYS_GETFSSTAT = 62 // { int sys_getfsstat(struct statfs *buf, size_t bufsize, int flags); } + SYS_STATFS = 63 // { int sys_statfs(const char *path, struct statfs *buf); } + SYS_FSTATFS = 64 // { int sys_fstatfs(int fd, struct statfs *buf); } + SYS_FHSTATFS = 65 // { int sys_fhstatfs(const fhandle_t *fhp, struct statfs *buf); } + SYS_VFORK = 66 // { int sys_vfork(void); } + SYS_GETTIMEOFDAY = 67 // { int sys_gettimeofday(struct timeval *tp, struct timezone *tzp); } + SYS_SETTIMEOFDAY = 68 // { int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp); } + SYS_SETITIMER = 69 // { int sys_setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); } + SYS_GETITIMER = 70 // { int sys_getitimer(int which, struct itimerval *itv); } + SYS_SELECT = 71 // { int sys_select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_KEVENT = 72 // { int sys_kevent(int fd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_MUNMAP = 73 // { int sys_munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int sys_mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int sys_madvise(void *addr, size_t len, int behav); } + SYS_UTIMES = 76 // { int sys_utimes(const char *path, const struct timeval *tptr); } + SYS_FUTIMES = 77 // { int sys_futimes(int fd, const struct timeval *tptr); } + SYS_GETGROUPS = 79 // { int sys_getgroups(int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int sys_setgroups(int gidsetsize, const gid_t *gidset); } + SYS_GETPGRP = 81 // { int sys_getpgrp(void); } + SYS_SETPGID = 82 // { int sys_setpgid(pid_t pid, pid_t pgid); } + SYS_FUTEX = 83 // { int sys_futex(uint32_t *f, int op, int val, const struct timespec *timeout, uint32_t *g); } + SYS_UTIMENSAT = 84 // { int sys_utimensat(int fd, const char *path, const struct timespec *times, int flag); } + SYS_FUTIMENS = 85 // { int sys_futimens(int fd, const struct timespec *times); } + SYS_KBIND = 86 // { int sys_kbind(const struct __kbind *param, size_t psize, int64_t proc_cookie); } + SYS_CLOCK_GETTIME = 87 // { int sys_clock_gettime(clockid_t clock_id, struct timespec *tp); } + SYS_CLOCK_SETTIME = 88 // { int sys_clock_settime(clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_GETRES = 89 // { int sys_clock_getres(clockid_t clock_id, struct timespec *tp); } + SYS_DUP2 = 90 // { int sys_dup2(int from, int to); } + SYS_NANOSLEEP = 91 // { int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } + SYS_FCNTL = 92 // { int sys_fcntl(int fd, int cmd, ... void *arg); } + SYS_ACCEPT4 = 93 // { int sys_accept4(int s, struct sockaddr *name, socklen_t *anamelen, int flags); } + SYS___THRSLEEP = 94 // { int sys___thrsleep(const volatile void *ident, clockid_t clock_id, const struct timespec *tp, void *lock, const int *abort); } + SYS_FSYNC = 95 // { int sys_fsync(int fd); } + SYS_SETPRIORITY = 96 // { int sys_setpriority(int which, id_t who, int prio); } + SYS_SOCKET = 97 // { int sys_socket(int domain, int type, int protocol); } + SYS_CONNECT = 98 // { int sys_connect(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_GETDENTS = 99 // { int sys_getdents(int fd, void *buf, size_t buflen); } + SYS_GETPRIORITY = 100 // { int sys_getpriority(int which, id_t who); } + SYS_PIPE2 = 101 // { int sys_pipe2(int *fdp, int flags); } + SYS_DUP3 = 102 // { int sys_dup3(int from, int to, int flags); } + SYS_SIGRETURN = 103 // { int sys_sigreturn(struct sigcontext *sigcntxp); } + SYS_BIND = 104 // { int sys_bind(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_SETSOCKOPT = 105 // { int sys_setsockopt(int s, int level, int name, const void *val, socklen_t valsize); } + SYS_LISTEN = 106 // { int sys_listen(int s, int backlog); } + SYS_CHFLAGSAT = 107 // { int sys_chflagsat(int fd, const char *path, u_int flags, int atflags); } + SYS_PLEDGE = 108 // { int sys_pledge(const char *promises, const char *execpromises); } + SYS_PPOLL = 109 // { int sys_ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); } + SYS_PSELECT = 110 // { int sys_pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); } + SYS_SIGSUSPEND = 111 // { int sys_sigsuspend(int mask); } + SYS_SENDSYSLOG = 112 // { int sys_sendsyslog(const char *buf, size_t nbyte, int flags); } + SYS_UNVEIL = 114 // { int sys_unveil(const char *path, const char *permissions); } + SYS_GETSOCKOPT = 118 // { int sys_getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); } + SYS_THRKILL = 119 // { int sys_thrkill(pid_t tid, int signum, void *tcb); } + SYS_READV = 120 // { ssize_t sys_readv(int fd, const struct iovec *iovp, int iovcnt); } + SYS_WRITEV = 121 // { ssize_t sys_writev(int fd, const struct iovec *iovp, int iovcnt); } + SYS_KILL = 122 // { int sys_kill(int pid, int signum); } + SYS_FCHOWN = 123 // { int sys_fchown(int fd, uid_t uid, gid_t gid); } + SYS_FCHMOD = 124 // { int sys_fchmod(int fd, mode_t mode); } + SYS_SETREUID = 126 // { int sys_setreuid(uid_t ruid, uid_t euid); } + SYS_SETREGID = 127 // { int sys_setregid(gid_t rgid, gid_t egid); } + SYS_RENAME = 128 // { int sys_rename(const char *from, const char *to); } + SYS_FLOCK = 131 // { int sys_flock(int fd, int how); } + SYS_MKFIFO = 132 // { int sys_mkfifo(const char *path, mode_t mode); } + SYS_SENDTO = 133 // { ssize_t sys_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); } + SYS_SHUTDOWN = 134 // { int sys_shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int sys_socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int sys_mkdir(const char *path, mode_t mode); } + SYS_RMDIR = 137 // { int sys_rmdir(const char *path); } + SYS_ADJTIME = 140 // { int sys_adjtime(const struct timeval *delta, struct timeval *olddelta); } + SYS_GETLOGIN_R = 141 // { int sys_getlogin_r(char *namebuf, u_int namelen); } + SYS_SETSID = 147 // { int sys_setsid(void); } + SYS_QUOTACTL = 148 // { int sys_quotactl(const char *path, int cmd, int uid, char *arg); } + SYS_NFSSVC = 155 // { int sys_nfssvc(int flag, void *argp); } + SYS_GETFH = 161 // { int sys_getfh(const char *fname, fhandle_t *fhp); } + SYS_SYSARCH = 165 // { int sys_sysarch(int op, void *parms); } + SYS_PREAD = 173 // { ssize_t sys_pread(int fd, void *buf, size_t nbyte, int pad, off_t offset); } + SYS_PWRITE = 174 // { ssize_t sys_pwrite(int fd, const void *buf, size_t nbyte, int pad, off_t offset); } + SYS_SETGID = 181 // { int sys_setgid(gid_t gid); } + SYS_SETEGID = 182 // { int sys_setegid(gid_t egid); } + SYS_SETEUID = 183 // { int sys_seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { long sys_pathconf(const char *path, int name); } + SYS_FPATHCONF = 192 // { long sys_fpathconf(int fd, int name); } + SYS_SWAPCTL = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); } + SYS_GETRLIMIT = 194 // { int sys_getrlimit(int which, struct rlimit *rlp); } + SYS_SETRLIMIT = 195 // { int sys_setrlimit(int which, const struct rlimit *rlp); } + SYS_MMAP = 197 // { void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, long pad, off_t pos); } + SYS_LSEEK = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, int whence); } + SYS_TRUNCATE = 200 // { int sys_truncate(const char *path, int pad, off_t length); } + SYS_FTRUNCATE = 201 // { int sys_ftruncate(int fd, int pad, off_t length); } + SYS_SYSCTL = 202 // { int sys_sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_MLOCK = 203 // { int sys_mlock(const void *addr, size_t len); } + SYS_MUNLOCK = 204 // { int sys_munlock(const void *addr, size_t len); } + SYS_GETPGID = 207 // { pid_t sys_getpgid(pid_t pid); } + SYS_UTRACE = 209 // { int sys_utrace(const char *label, const void *addr, size_t len); } + SYS_SEMGET = 221 // { int sys_semget(key_t key, int nsems, int semflg); } + SYS_MSGGET = 225 // { int sys_msgget(key_t key, int msgflg); } + SYS_MSGSND = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } + SYS_MSGRCV = 227 // { int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_SHMAT = 228 // { void *sys_shmat(int shmid, const void *shmaddr, int shmflg); } + SYS_SHMDT = 230 // { int sys_shmdt(const void *shmaddr); } + SYS_MINHERIT = 250 // { int sys_minherit(void *addr, size_t len, int inherit); } + SYS_POLL = 252 // { int sys_poll(struct pollfd *fds, u_int nfds, int timeout); } + SYS_ISSETUGID = 253 // { int sys_issetugid(void); } + SYS_LCHOWN = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); } + SYS_GETSID = 255 // { pid_t sys_getsid(pid_t pid); } + SYS_MSYNC = 256 // { int sys_msync(void *addr, size_t len, int flags); } + SYS_PIPE = 263 // { int sys_pipe(int *fdp); } + SYS_FHOPEN = 264 // { int sys_fhopen(const fhandle_t *fhp, int flags); } + SYS_PREADV = 267 // { ssize_t sys_preadv(int fd, const struct iovec *iovp, int iovcnt, int pad, off_t offset); } + SYS_PWRITEV = 268 // { ssize_t sys_pwritev(int fd, const struct iovec *iovp, int iovcnt, int pad, off_t offset); } + SYS_KQUEUE = 269 // { int sys_kqueue(void); } + SYS_MLOCKALL = 271 // { int sys_mlockall(int flags); } + SYS_MUNLOCKALL = 272 // { int sys_munlockall(void); } + SYS_GETRESUID = 281 // { int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } + SYS_SETRESUID = 282 // { int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); } + SYS_GETRESGID = 283 // { int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } + SYS_SETRESGID = 284 // { int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); } + SYS_MQUERY = 286 // { void *sys_mquery(void *addr, size_t len, int prot, int flags, int fd, long pad, off_t pos); } + SYS_CLOSEFROM = 287 // { int sys_closefrom(int fd); } + SYS_SIGALTSTACK = 288 // { int sys_sigaltstack(const struct sigaltstack *nss, struct sigaltstack *oss); } + SYS_SHMGET = 289 // { int sys_shmget(key_t key, size_t size, int shmflg); } + SYS_SEMOP = 290 // { int sys_semop(int semid, struct sembuf *sops, size_t nsops); } + SYS_FHSTAT = 294 // { int sys_fhstat(const fhandle_t *fhp, struct stat *sb); } + SYS___SEMCTL = 295 // { int sys___semctl(int semid, int semnum, int cmd, union semun *arg); } + SYS_SHMCTL = 296 // { int sys_shmctl(int shmid, int cmd, struct shmid_ds *buf); } + SYS_MSGCTL = 297 // { int sys_msgctl(int msqid, int cmd, struct msqid_ds *buf); } + SYS_SCHED_YIELD = 298 // { int sys_sched_yield(void); } + SYS_GETTHRID = 299 // { pid_t sys_getthrid(void); } + SYS___THRWAKEUP = 301 // { int sys___thrwakeup(const volatile void *ident, int n); } + SYS___THREXIT = 302 // { void sys___threxit(pid_t *notdead); } + SYS___THRSIGDIVERT = 303 // { int sys___thrsigdivert(sigset_t sigmask, siginfo_t *info, const struct timespec *timeout); } + SYS___GETCWD = 304 // { int sys___getcwd(char *buf, size_t len); } + SYS_ADJFREQ = 305 // { int sys_adjfreq(const int64_t *freq, int64_t *oldfreq); } + SYS_SETRTABLE = 310 // { int sys_setrtable(int rtableid); } + SYS_GETRTABLE = 311 // { int sys_getrtable(void); } + SYS_FACCESSAT = 313 // { int sys_faccessat(int fd, const char *path, int amode, int flag); } + SYS_FCHMODAT = 314 // { int sys_fchmodat(int fd, const char *path, mode_t mode, int flag); } + SYS_FCHOWNAT = 315 // { int sys_fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flag); } + SYS_LINKAT = 317 // { int sys_linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); } + SYS_MKDIRAT = 318 // { int sys_mkdirat(int fd, const char *path, mode_t mode); } + SYS_MKFIFOAT = 319 // { int sys_mkfifoat(int fd, const char *path, mode_t mode); } + SYS_MKNODAT = 320 // { int sys_mknodat(int fd, const char *path, mode_t mode, dev_t dev); } + SYS_OPENAT = 321 // { int sys_openat(int fd, const char *path, int flags, ... mode_t mode); } + SYS_READLINKAT = 322 // { ssize_t sys_readlinkat(int fd, const char *path, char *buf, size_t count); } + SYS_RENAMEAT = 323 // { int sys_renameat(int fromfd, const char *from, int tofd, const char *to); } + SYS_SYMLINKAT = 324 // { int sys_symlinkat(const char *path, int fd, const char *link); } + SYS_UNLINKAT = 325 // { int sys_unlinkat(int fd, const char *path, int flag); } + SYS___SET_TCB = 329 // { void sys___set_tcb(void *tcb); } + SYS___GET_TCB = 330 // { void *sys___get_tcb(void); } +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go new file mode 100644 index 0000000..05192a7 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go @@ -0,0 +1,218 @@ +// go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build riscv64 && openbsd + +package unix + +// Deprecated: Use libc wrappers instead of direct syscalls. +const ( + SYS_EXIT = 1 // { void sys_exit(int rval); } + SYS_FORK = 2 // { int sys_fork(void); } + SYS_READ = 3 // { ssize_t sys_read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t sys_write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int sys_open(const char *path, int flags, ... mode_t mode); } + SYS_CLOSE = 6 // { int sys_close(int fd); } + SYS_GETENTROPY = 7 // { int sys_getentropy(void *buf, size_t nbyte); } + SYS___TFORK = 8 // { int sys___tfork(const struct __tfork *param, size_t psize); } + SYS_LINK = 9 // { int sys_link(const char *path, const char *link); } + SYS_UNLINK = 10 // { int sys_unlink(const char *path); } + SYS_WAIT4 = 11 // { pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage); } + SYS_CHDIR = 12 // { int sys_chdir(const char *path); } + SYS_FCHDIR = 13 // { int sys_fchdir(int fd); } + SYS_MKNOD = 14 // { int sys_mknod(const char *path, mode_t mode, dev_t dev); } + SYS_CHMOD = 15 // { int sys_chmod(const char *path, mode_t mode); } + SYS_CHOWN = 16 // { int sys_chown(const char *path, uid_t uid, gid_t gid); } + SYS_OBREAK = 17 // { int sys_obreak(char *nsize); } break + SYS_GETDTABLECOUNT = 18 // { int sys_getdtablecount(void); } + SYS_GETRUSAGE = 19 // { int sys_getrusage(int who, struct rusage *rusage); } + SYS_GETPID = 20 // { pid_t sys_getpid(void); } + SYS_MOUNT = 21 // { int sys_mount(const char *type, const char *path, int flags, void *data); } + SYS_UNMOUNT = 22 // { int sys_unmount(const char *path, int flags); } + SYS_SETUID = 23 // { int sys_setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t sys_getuid(void); } + SYS_GETEUID = 25 // { uid_t sys_geteuid(void); } + SYS_PTRACE = 26 // { int sys_ptrace(int req, pid_t pid, caddr_t addr, int data); } + SYS_RECVMSG = 27 // { ssize_t sys_recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { ssize_t sys_sendmsg(int s, const struct msghdr *msg, int flags); } + SYS_RECVFROM = 29 // { ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); } + SYS_ACCEPT = 30 // { int sys_accept(int s, struct sockaddr *name, socklen_t *anamelen); } + SYS_GETPEERNAME = 31 // { int sys_getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_GETSOCKNAME = 32 // { int sys_getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_ACCESS = 33 // { int sys_access(const char *path, int amode); } + SYS_CHFLAGS = 34 // { int sys_chflags(const char *path, u_int flags); } + SYS_FCHFLAGS = 35 // { int sys_fchflags(int fd, u_int flags); } + SYS_SYNC = 36 // { void sys_sync(void); } + SYS_STAT = 38 // { int sys_stat(const char *path, struct stat *ub); } + SYS_GETPPID = 39 // { pid_t sys_getppid(void); } + SYS_LSTAT = 40 // { int sys_lstat(const char *path, struct stat *ub); } + SYS_DUP = 41 // { int sys_dup(int fd); } + SYS_FSTATAT = 42 // { int sys_fstatat(int fd, const char *path, struct stat *buf, int flag); } + SYS_GETEGID = 43 // { gid_t sys_getegid(void); } + SYS_PROFIL = 44 // { int sys_profil(caddr_t samples, size_t size, u_long offset, u_int scale); } + SYS_KTRACE = 45 // { int sys_ktrace(const char *fname, int ops, int facs, pid_t pid); } + SYS_SIGACTION = 46 // { int sys_sigaction(int signum, const struct sigaction *nsa, struct sigaction *osa); } + SYS_GETGID = 47 // { gid_t sys_getgid(void); } + SYS_SIGPROCMASK = 48 // { int sys_sigprocmask(int how, sigset_t mask); } + SYS_SETLOGIN = 50 // { int sys_setlogin(const char *namebuf); } + SYS_ACCT = 51 // { int sys_acct(const char *path); } + SYS_SIGPENDING = 52 // { int sys_sigpending(void); } + SYS_FSTAT = 53 // { int sys_fstat(int fd, struct stat *sb); } + SYS_IOCTL = 54 // { int sys_ioctl(int fd, u_long com, ... void *data); } + SYS_REBOOT = 55 // { int sys_reboot(int opt); } + SYS_REVOKE = 56 // { int sys_revoke(const char *path); } + SYS_SYMLINK = 57 // { int sys_symlink(const char *path, const char *link); } + SYS_READLINK = 58 // { ssize_t sys_readlink(const char *path, char *buf, size_t count); } + SYS_EXECVE = 59 // { int sys_execve(const char *path, char * const *argp, char * const *envp); } + SYS_UMASK = 60 // { mode_t sys_umask(mode_t newmask); } + SYS_CHROOT = 61 // { int sys_chroot(const char *path); } + SYS_GETFSSTAT = 62 // { int sys_getfsstat(struct statfs *buf, size_t bufsize, int flags); } + SYS_STATFS = 63 // { int sys_statfs(const char *path, struct statfs *buf); } + SYS_FSTATFS = 64 // { int sys_fstatfs(int fd, struct statfs *buf); } + SYS_FHSTATFS = 65 // { int sys_fhstatfs(const fhandle_t *fhp, struct statfs *buf); } + SYS_VFORK = 66 // { int sys_vfork(void); } + SYS_GETTIMEOFDAY = 67 // { int sys_gettimeofday(struct timeval *tp, struct timezone *tzp); } + SYS_SETTIMEOFDAY = 68 // { int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp); } + SYS_SETITIMER = 69 // { int sys_setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); } + SYS_GETITIMER = 70 // { int sys_getitimer(int which, struct itimerval *itv); } + SYS_SELECT = 71 // { int sys_select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_KEVENT = 72 // { int sys_kevent(int fd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } + SYS_MUNMAP = 73 // { int sys_munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int sys_mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int sys_madvise(void *addr, size_t len, int behav); } + SYS_UTIMES = 76 // { int sys_utimes(const char *path, const struct timeval *tptr); } + SYS_FUTIMES = 77 // { int sys_futimes(int fd, const struct timeval *tptr); } + SYS_GETGROUPS = 79 // { int sys_getgroups(int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int sys_setgroups(int gidsetsize, const gid_t *gidset); } + SYS_GETPGRP = 81 // { int sys_getpgrp(void); } + SYS_SETPGID = 82 // { int sys_setpgid(pid_t pid, pid_t pgid); } + SYS_FUTEX = 83 // { int sys_futex(uint32_t *f, int op, int val, const struct timespec *timeout, uint32_t *g); } + SYS_UTIMENSAT = 84 // { int sys_utimensat(int fd, const char *path, const struct timespec *times, int flag); } + SYS_FUTIMENS = 85 // { int sys_futimens(int fd, const struct timespec *times); } + SYS_KBIND = 86 // { int sys_kbind(const struct __kbind *param, size_t psize, int64_t proc_cookie); } + SYS_CLOCK_GETTIME = 87 // { int sys_clock_gettime(clockid_t clock_id, struct timespec *tp); } + SYS_CLOCK_SETTIME = 88 // { int sys_clock_settime(clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_GETRES = 89 // { int sys_clock_getres(clockid_t clock_id, struct timespec *tp); } + SYS_DUP2 = 90 // { int sys_dup2(int from, int to); } + SYS_NANOSLEEP = 91 // { int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } + SYS_FCNTL = 92 // { int sys_fcntl(int fd, int cmd, ... void *arg); } + SYS_ACCEPT4 = 93 // { int sys_accept4(int s, struct sockaddr *name, socklen_t *anamelen, int flags); } + SYS___THRSLEEP = 94 // { int sys___thrsleep(const volatile void *ident, clockid_t clock_id, const struct timespec *tp, void *lock, const int *abort); } + SYS_FSYNC = 95 // { int sys_fsync(int fd); } + SYS_SETPRIORITY = 96 // { int sys_setpriority(int which, id_t who, int prio); } + SYS_SOCKET = 97 // { int sys_socket(int domain, int type, int protocol); } + SYS_CONNECT = 98 // { int sys_connect(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_GETDENTS = 99 // { int sys_getdents(int fd, void *buf, size_t buflen); } + SYS_GETPRIORITY = 100 // { int sys_getpriority(int which, id_t who); } + SYS_PIPE2 = 101 // { int sys_pipe2(int *fdp, int flags); } + SYS_DUP3 = 102 // { int sys_dup3(int from, int to, int flags); } + SYS_SIGRETURN = 103 // { int sys_sigreturn(struct sigcontext *sigcntxp); } + SYS_BIND = 104 // { int sys_bind(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_SETSOCKOPT = 105 // { int sys_setsockopt(int s, int level, int name, const void *val, socklen_t valsize); } + SYS_LISTEN = 106 // { int sys_listen(int s, int backlog); } + SYS_CHFLAGSAT = 107 // { int sys_chflagsat(int fd, const char *path, u_int flags, int atflags); } + SYS_PLEDGE = 108 // { int sys_pledge(const char *promises, const char *execpromises); } + SYS_PPOLL = 109 // { int sys_ppoll(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); } + SYS_PSELECT = 110 // { int sys_pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); } + SYS_SIGSUSPEND = 111 // { int sys_sigsuspend(int mask); } + SYS_SENDSYSLOG = 112 // { int sys_sendsyslog(const char *buf, size_t nbyte, int flags); } + SYS_UNVEIL = 114 // { int sys_unveil(const char *path, const char *permissions); } + SYS_GETSOCKOPT = 118 // { int sys_getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); } + SYS_THRKILL = 119 // { int sys_thrkill(pid_t tid, int signum, void *tcb); } + SYS_READV = 120 // { ssize_t sys_readv(int fd, const struct iovec *iovp, int iovcnt); } + SYS_WRITEV = 121 // { ssize_t sys_writev(int fd, const struct iovec *iovp, int iovcnt); } + SYS_KILL = 122 // { int sys_kill(int pid, int signum); } + SYS_FCHOWN = 123 // { int sys_fchown(int fd, uid_t uid, gid_t gid); } + SYS_FCHMOD = 124 // { int sys_fchmod(int fd, mode_t mode); } + SYS_SETREUID = 126 // { int sys_setreuid(uid_t ruid, uid_t euid); } + SYS_SETREGID = 127 // { int sys_setregid(gid_t rgid, gid_t egid); } + SYS_RENAME = 128 // { int sys_rename(const char *from, const char *to); } + SYS_FLOCK = 131 // { int sys_flock(int fd, int how); } + SYS_MKFIFO = 132 // { int sys_mkfifo(const char *path, mode_t mode); } + SYS_SENDTO = 133 // { ssize_t sys_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); } + SYS_SHUTDOWN = 134 // { int sys_shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int sys_socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int sys_mkdir(const char *path, mode_t mode); } + SYS_RMDIR = 137 // { int sys_rmdir(const char *path); } + SYS_ADJTIME = 140 // { int sys_adjtime(const struct timeval *delta, struct timeval *olddelta); } + SYS_GETLOGIN_R = 141 // { int sys_getlogin_r(char *namebuf, u_int namelen); } + SYS_SETSID = 147 // { int sys_setsid(void); } + SYS_QUOTACTL = 148 // { int sys_quotactl(const char *path, int cmd, int uid, char *arg); } + SYS_NFSSVC = 155 // { int sys_nfssvc(int flag, void *argp); } + SYS_GETFH = 161 // { int sys_getfh(const char *fname, fhandle_t *fhp); } + SYS_SYSARCH = 165 // { int sys_sysarch(int op, void *parms); } + SYS_PREAD = 173 // { ssize_t sys_pread(int fd, void *buf, size_t nbyte, int pad, off_t offset); } + SYS_PWRITE = 174 // { ssize_t sys_pwrite(int fd, const void *buf, size_t nbyte, int pad, off_t offset); } + SYS_SETGID = 181 // { int sys_setgid(gid_t gid); } + SYS_SETEGID = 182 // { int sys_setegid(gid_t egid); } + SYS_SETEUID = 183 // { int sys_seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { long sys_pathconf(const char *path, int name); } + SYS_FPATHCONF = 192 // { long sys_fpathconf(int fd, int name); } + SYS_SWAPCTL = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); } + SYS_GETRLIMIT = 194 // { int sys_getrlimit(int which, struct rlimit *rlp); } + SYS_SETRLIMIT = 195 // { int sys_setrlimit(int which, const struct rlimit *rlp); } + SYS_MMAP = 197 // { void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, long pad, off_t pos); } + SYS_LSEEK = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, int whence); } + SYS_TRUNCATE = 200 // { int sys_truncate(const char *path, int pad, off_t length); } + SYS_FTRUNCATE = 201 // { int sys_ftruncate(int fd, int pad, off_t length); } + SYS_SYSCTL = 202 // { int sys_sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); } + SYS_MLOCK = 203 // { int sys_mlock(const void *addr, size_t len); } + SYS_MUNLOCK = 204 // { int sys_munlock(const void *addr, size_t len); } + SYS_GETPGID = 207 // { pid_t sys_getpgid(pid_t pid); } + SYS_UTRACE = 209 // { int sys_utrace(const char *label, const void *addr, size_t len); } + SYS_SEMGET = 221 // { int sys_semget(key_t key, int nsems, int semflg); } + SYS_MSGGET = 225 // { int sys_msgget(key_t key, int msgflg); } + SYS_MSGSND = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } + SYS_MSGRCV = 227 // { int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_SHMAT = 228 // { void *sys_shmat(int shmid, const void *shmaddr, int shmflg); } + SYS_SHMDT = 230 // { int sys_shmdt(const void *shmaddr); } + SYS_MINHERIT = 250 // { int sys_minherit(void *addr, size_t len, int inherit); } + SYS_POLL = 252 // { int sys_poll(struct pollfd *fds, u_int nfds, int timeout); } + SYS_ISSETUGID = 253 // { int sys_issetugid(void); } + SYS_LCHOWN = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); } + SYS_GETSID = 255 // { pid_t sys_getsid(pid_t pid); } + SYS_MSYNC = 256 // { int sys_msync(void *addr, size_t len, int flags); } + SYS_PIPE = 263 // { int sys_pipe(int *fdp); } + SYS_FHOPEN = 264 // { int sys_fhopen(const fhandle_t *fhp, int flags); } + SYS_PREADV = 267 // { ssize_t sys_preadv(int fd, const struct iovec *iovp, int iovcnt, int pad, off_t offset); } + SYS_PWRITEV = 268 // { ssize_t sys_pwritev(int fd, const struct iovec *iovp, int iovcnt, int pad, off_t offset); } + SYS_KQUEUE = 269 // { int sys_kqueue(void); } + SYS_MLOCKALL = 271 // { int sys_mlockall(int flags); } + SYS_MUNLOCKALL = 272 // { int sys_munlockall(void); } + SYS_GETRESUID = 281 // { int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } + SYS_SETRESUID = 282 // { int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); } + SYS_GETRESGID = 283 // { int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } + SYS_SETRESGID = 284 // { int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); } + SYS_MQUERY = 286 // { void *sys_mquery(void *addr, size_t len, int prot, int flags, int fd, long pad, off_t pos); } + SYS_CLOSEFROM = 287 // { int sys_closefrom(int fd); } + SYS_SIGALTSTACK = 288 // { int sys_sigaltstack(const struct sigaltstack *nss, struct sigaltstack *oss); } + SYS_SHMGET = 289 // { int sys_shmget(key_t key, size_t size, int shmflg); } + SYS_SEMOP = 290 // { int sys_semop(int semid, struct sembuf *sops, size_t nsops); } + SYS_FHSTAT = 294 // { int sys_fhstat(const fhandle_t *fhp, struct stat *sb); } + SYS___SEMCTL = 295 // { int sys___semctl(int semid, int semnum, int cmd, union semun *arg); } + SYS_SHMCTL = 296 // { int sys_shmctl(int shmid, int cmd, struct shmid_ds *buf); } + SYS_MSGCTL = 297 // { int sys_msgctl(int msqid, int cmd, struct msqid_ds *buf); } + SYS_SCHED_YIELD = 298 // { int sys_sched_yield(void); } + SYS_GETTHRID = 299 // { pid_t sys_getthrid(void); } + SYS___THRWAKEUP = 301 // { int sys___thrwakeup(const volatile void *ident, int n); } + SYS___THREXIT = 302 // { void sys___threxit(pid_t *notdead); } + SYS___THRSIGDIVERT = 303 // { int sys___thrsigdivert(sigset_t sigmask, siginfo_t *info, const struct timespec *timeout); } + SYS___GETCWD = 304 // { int sys___getcwd(char *buf, size_t len); } + SYS_ADJFREQ = 305 // { int sys_adjfreq(const int64_t *freq, int64_t *oldfreq); } + SYS_SETRTABLE = 310 // { int sys_setrtable(int rtableid); } + SYS_GETRTABLE = 311 // { int sys_getrtable(void); } + SYS_FACCESSAT = 313 // { int sys_faccessat(int fd, const char *path, int amode, int flag); } + SYS_FCHMODAT = 314 // { int sys_fchmodat(int fd, const char *path, mode_t mode, int flag); } + SYS_FCHOWNAT = 315 // { int sys_fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flag); } + SYS_LINKAT = 317 // { int sys_linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); } + SYS_MKDIRAT = 318 // { int sys_mkdirat(int fd, const char *path, mode_t mode); } + SYS_MKFIFOAT = 319 // { int sys_mkfifoat(int fd, const char *path, mode_t mode); } + SYS_MKNODAT = 320 // { int sys_mknodat(int fd, const char *path, mode_t mode, dev_t dev); } + SYS_OPENAT = 321 // { int sys_openat(int fd, const char *path, int flags, ... mode_t mode); } + SYS_READLINKAT = 322 // { ssize_t sys_readlinkat(int fd, const char *path, char *buf, size_t count); } + SYS_RENAMEAT = 323 // { int sys_renameat(int fromfd, const char *from, int tofd, const char *to); } + SYS_SYMLINKAT = 324 // { int sys_symlinkat(const char *path, int fd, const char *link); } + SYS_UNLINKAT = 325 // { int sys_unlinkat(int fd, const char *path, int flag); } + SYS___SET_TCB = 329 // { void sys___set_tcb(void *tcb); } + SYS___GET_TCB = 330 // { void *sys___get_tcb(void); } +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go new file mode 100644 index 0000000..5e8c263 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go @@ -0,0 +1,2852 @@ +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build zos && s390x + +package unix + +const ( + SYS_LOG = 0x17 // 23 + SYS_COSH = 0x18 // 24 + SYS_TANH = 0x19 // 25 + SYS_EXP = 0x1A // 26 + SYS_MODF = 0x1B // 27 + SYS_LOG10 = 0x1C // 28 + SYS_FREXP = 0x1D // 29 + SYS_LDEXP = 0x1E // 30 + SYS_CEIL = 0x1F // 31 + SYS_POW = 0x20 // 32 + SYS_SQRT = 0x21 // 33 + SYS_FLOOR = 0x22 // 34 + SYS_J1 = 0x23 // 35 + SYS_FABS = 0x24 // 36 + SYS_FMOD = 0x25 // 37 + SYS_J0 = 0x26 // 38 + SYS_YN = 0x27 // 39 + SYS_JN = 0x28 // 40 + SYS_Y0 = 0x29 // 41 + SYS_Y1 = 0x2A // 42 + SYS_HYPOT = 0x2B // 43 + SYS_ERF = 0x2C // 44 + SYS_ERFC = 0x2D // 45 + SYS_GAMMA = 0x2E // 46 + SYS_ISALPHA = 0x30 // 48 + SYS_ISALNUM = 0x31 // 49 + SYS_ISLOWER = 0x32 // 50 + SYS_ISCNTRL = 0x33 // 51 + SYS_ISDIGIT = 0x34 // 52 + SYS_ISGRAPH = 0x35 // 53 + SYS_ISUPPER = 0x36 // 54 + SYS_ISPRINT = 0x37 // 55 + SYS_ISPUNCT = 0x38 // 56 + SYS_ISSPACE = 0x39 // 57 + SYS_SETLOCAL = 0x3A // 58 + SYS_SETLOCALE = 0x3A // 58 + SYS_ISXDIGIT = 0x3B // 59 + SYS_TOLOWER = 0x3C // 60 + SYS_TOUPPER = 0x3D // 61 + SYS_ASIN = 0x3E // 62 + SYS_SIN = 0x3F // 63 + SYS_COS = 0x40 // 64 + SYS_TAN = 0x41 // 65 + SYS_SINH = 0x42 // 66 + SYS_ACOS = 0x43 // 67 + SYS_ATAN = 0x44 // 68 + SYS_ATAN2 = 0x45 // 69 + SYS_FTELL = 0x46 // 70 + SYS_FGETPOS = 0x47 // 71 + SYS_FSEEK = 0x48 // 72 + SYS_FSETPOS = 0x49 // 73 + SYS_FERROR = 0x4A // 74 + SYS_REWIND = 0x4B // 75 + SYS_CLEARERR = 0x4C // 76 + SYS_FEOF = 0x4D // 77 + SYS_ATOL = 0x4E // 78 + SYS_PERROR = 0x4F // 79 + SYS_ATOF = 0x50 // 80 + SYS_ATOI = 0x51 // 81 + SYS_RAND = 0x52 // 82 + SYS_STRTOD = 0x53 // 83 + SYS_STRTOL = 0x54 // 84 + SYS_STRTOUL = 0x55 // 85 + SYS_MALLOC = 0x56 // 86 + SYS_SRAND = 0x57 // 87 + SYS_CALLOC = 0x58 // 88 + SYS_FREE = 0x59 // 89 + SYS_EXIT = 0x5A // 90 + SYS_REALLOC = 0x5B // 91 + SYS_ABORT = 0x5C // 92 + SYS___ABORT = 0x5C // 92 + SYS_ATEXIT = 0x5D // 93 + SYS_RAISE = 0x5E // 94 + SYS_SETJMP = 0x5F // 95 + SYS_LONGJMP = 0x60 // 96 + SYS_SIGNAL = 0x61 // 97 + SYS_TMPNAM = 0x62 // 98 + SYS_REMOVE = 0x63 // 99 + SYS_RENAME = 0x64 // 100 + SYS_TMPFILE = 0x65 // 101 + SYS_FREOPEN = 0x66 // 102 + SYS_FCLOSE = 0x67 // 103 + SYS_FFLUSH = 0x68 // 104 + SYS_FOPEN = 0x69 // 105 + SYS_FSCANF = 0x6A // 106 + SYS_SETBUF = 0x6B // 107 + SYS_SETVBUF = 0x6C // 108 + SYS_FPRINTF = 0x6D // 109 + SYS_SSCANF = 0x6E // 110 + SYS_PRINTF = 0x6F // 111 + SYS_SCANF = 0x70 // 112 + SYS_SPRINTF = 0x71 // 113 + SYS_FGETC = 0x72 // 114 + SYS_VFPRINTF = 0x73 // 115 + SYS_VPRINTF = 0x74 // 116 + SYS_VSPRINTF = 0x75 // 117 + SYS_GETC = 0x76 // 118 + SYS_FGETS = 0x77 // 119 + SYS_FPUTC = 0x78 // 120 + SYS_FPUTS = 0x79 // 121 + SYS_PUTCHAR = 0x7A // 122 + SYS_GETCHAR = 0x7B // 123 + SYS_GETS = 0x7C // 124 + SYS_PUTC = 0x7D // 125 + SYS_FWRITE = 0x7E // 126 + SYS_PUTS = 0x7F // 127 + SYS_UNGETC = 0x80 // 128 + SYS_FREAD = 0x81 // 129 + SYS_WCSTOMBS = 0x82 // 130 + SYS_MBTOWC = 0x83 // 131 + SYS_WCTOMB = 0x84 // 132 + SYS_MBSTOWCS = 0x85 // 133 + SYS_WCSCPY = 0x86 // 134 + SYS_WCSCAT = 0x87 // 135 + SYS_WCSCHR = 0x88 // 136 + SYS_WCSCMP = 0x89 // 137 + SYS_WCSNCMP = 0x8A // 138 + SYS_WCSCSPN = 0x8B // 139 + SYS_WCSLEN = 0x8C // 140 + SYS_WCSNCAT = 0x8D // 141 + SYS_WCSSPN = 0x8E // 142 + SYS_WCSNCPY = 0x8F // 143 + SYS_ABS = 0x90 // 144 + SYS_DIV = 0x91 // 145 + SYS_LABS = 0x92 // 146 + SYS_STRNCPY = 0x93 // 147 + SYS_MEMCPY = 0x94 // 148 + SYS_MEMMOVE = 0x95 // 149 + SYS_STRCPY = 0x96 // 150 + SYS_STRCMP = 0x97 // 151 + SYS_STRCAT = 0x98 // 152 + SYS_STRNCAT = 0x99 // 153 + SYS_MEMCMP = 0x9A // 154 + SYS_MEMCHR = 0x9B // 155 + SYS_STRCOLL = 0x9C // 156 + SYS_STRNCMP = 0x9D // 157 + SYS_STRXFRM = 0x9E // 158 + SYS_STRRCHR = 0x9F // 159 + SYS_STRCHR = 0xA0 // 160 + SYS_STRCSPN = 0xA1 // 161 + SYS_STRPBRK = 0xA2 // 162 + SYS_MEMSET = 0xA3 // 163 + SYS_STRSPN = 0xA4 // 164 + SYS_STRSTR = 0xA5 // 165 + SYS_STRTOK = 0xA6 // 166 + SYS_DIFFTIME = 0xA7 // 167 + SYS_STRERROR = 0xA8 // 168 + SYS_STRLEN = 0xA9 // 169 + SYS_CLOCK = 0xAA // 170 + SYS_CTIME = 0xAB // 171 + SYS_MKTIME = 0xAC // 172 + SYS_TIME = 0xAD // 173 + SYS_ASCTIME = 0xAE // 174 + SYS_MBLEN = 0xAF // 175 + SYS_GMTIME = 0xB0 // 176 + SYS_LOCALTIM = 0xB1 // 177 + SYS_LOCALTIME = 0xB1 // 177 + SYS_STRFTIME = 0xB2 // 178 + SYS___GETCB = 0xB4 // 180 + SYS_FUPDATE = 0xB5 // 181 + SYS___FUPDT = 0xB5 // 181 + SYS_CLRMEMF = 0xBD // 189 + SYS___CLRMF = 0xBD // 189 + SYS_FETCHEP = 0xBF // 191 + SYS___FTCHEP = 0xBF // 191 + SYS_FLDATA = 0xC1 // 193 + SYS___FLDATA = 0xC1 // 193 + SYS_DYNFREE = 0xC2 // 194 + SYS___DYNFRE = 0xC2 // 194 + SYS_DYNALLOC = 0xC3 // 195 + SYS___DYNALL = 0xC3 // 195 + SYS___CDUMP = 0xC4 // 196 + SYS_CSNAP = 0xC5 // 197 + SYS___CSNAP = 0xC5 // 197 + SYS_CTRACE = 0xC6 // 198 + SYS___CTRACE = 0xC6 // 198 + SYS___CTEST = 0xC7 // 199 + SYS_SETENV = 0xC8 // 200 + SYS___SETENV = 0xC8 // 200 + SYS_CLEARENV = 0xC9 // 201 + SYS___CLRENV = 0xC9 // 201 + SYS___REGCOMP_STD = 0xEA // 234 + SYS_NL_LANGINFO = 0xFC // 252 + SYS_GETSYNTX = 0xFD // 253 + SYS_ISBLANK = 0xFE // 254 + SYS___ISBLNK = 0xFE // 254 + SYS_ISWALNUM = 0xFF // 255 + SYS_ISWALPHA = 0x100 // 256 + SYS_ISWBLANK = 0x101 // 257 + SYS___ISWBLK = 0x101 // 257 + SYS_ISWCNTRL = 0x102 // 258 + SYS_ISWDIGIT = 0x103 // 259 + SYS_ISWGRAPH = 0x104 // 260 + SYS_ISWLOWER = 0x105 // 261 + SYS_ISWPRINT = 0x106 // 262 + SYS_ISWPUNCT = 0x107 // 263 + SYS_ISWSPACE = 0x108 // 264 + SYS_ISWUPPER = 0x109 // 265 + SYS_ISWXDIGI = 0x10A // 266 + SYS_ISWXDIGIT = 0x10A // 266 + SYS_WCTYPE = 0x10B // 267 + SYS_ISWCTYPE = 0x10C // 268 + SYS_TOWLOWER = 0x10D // 269 + SYS_TOWUPPER = 0x10E // 270 + SYS_MBSINIT = 0x10F // 271 + SYS_WCTOB = 0x110 // 272 + SYS_MBRLEN = 0x111 // 273 + SYS_MBRTOWC = 0x112 // 274 + SYS_MBSRTOWC = 0x113 // 275 + SYS_MBSRTOWCS = 0x113 // 275 + SYS_WCRTOMB = 0x114 // 276 + SYS_WCSRTOMB = 0x115 // 277 + SYS_WCSRTOMBS = 0x115 // 277 + SYS___CSID = 0x116 // 278 + SYS___WCSID = 0x117 // 279 + SYS_STRPTIME = 0x118 // 280 + SYS___STRPTM = 0x118 // 280 + SYS_STRFMON = 0x119 // 281 + SYS___RPMTCH = 0x11A // 282 + SYS_WCSSTR = 0x11B // 283 + SYS_WCSTOK = 0x12C // 300 + SYS_WCSTOL = 0x12D // 301 + SYS_WCSTOD = 0x12E // 302 + SYS_WCSTOUL = 0x12F // 303 + SYS_WCSCOLL = 0x130 // 304 + SYS_WCSXFRM = 0x131 // 305 + SYS_WCSWIDTH = 0x132 // 306 + SYS_WCWIDTH = 0x133 // 307 + SYS_WCSFTIME = 0x134 // 308 + SYS_SWPRINTF = 0x135 // 309 + SYS_VSWPRINT = 0x136 // 310 + SYS_VSWPRINTF = 0x136 // 310 + SYS_SWSCANF = 0x137 // 311 + SYS_REGCOMP = 0x138 // 312 + SYS_REGEXEC = 0x139 // 313 + SYS_REGFREE = 0x13A // 314 + SYS_REGERROR = 0x13B // 315 + SYS_FGETWC = 0x13C // 316 + SYS_FGETWS = 0x13D // 317 + SYS_FPUTWC = 0x13E // 318 + SYS_FPUTWS = 0x13F // 319 + SYS_GETWC = 0x140 // 320 + SYS_GETWCHAR = 0x141 // 321 + SYS_PUTWC = 0x142 // 322 + SYS_PUTWCHAR = 0x143 // 323 + SYS_UNGETWC = 0x144 // 324 + SYS_ICONV_OPEN = 0x145 // 325 + SYS_ICONV = 0x146 // 326 + SYS_ICONV_CLOSE = 0x147 // 327 + SYS_ISMCCOLLEL = 0x14C // 332 + SYS_STRTOCOLL = 0x14D // 333 + SYS_COLLTOSTR = 0x14E // 334 + SYS_COLLEQUIV = 0x14F // 335 + SYS_COLLRANGE = 0x150 // 336 + SYS_CCLASS = 0x151 // 337 + SYS_COLLORDER = 0x152 // 338 + SYS___DEMANGLE = 0x154 // 340 + SYS_FDOPEN = 0x155 // 341 + SYS___ERRNO = 0x156 // 342 + SYS___ERRNO2 = 0x157 // 343 + SYS___TERROR = 0x158 // 344 + SYS_MAXCOLL = 0x169 // 361 + SYS_GETMCCOLL = 0x16A // 362 + SYS_GETWMCCOLL = 0x16B // 363 + SYS___ERR2AD = 0x16C // 364 + SYS_DLLQUERYFN = 0x16D // 365 + SYS_DLLQUERYVAR = 0x16E // 366 + SYS_DLLFREE = 0x16F // 367 + SYS_DLLLOAD = 0x170 // 368 + SYS__EXIT = 0x174 // 372 + SYS_ACCESS = 0x175 // 373 + SYS_ALARM = 0x176 // 374 + SYS_CFGETISPEED = 0x177 // 375 + SYS_CFGETOSPEED = 0x178 // 376 + SYS_CFSETISPEED = 0x179 // 377 + SYS_CFSETOSPEED = 0x17A // 378 + SYS_CHDIR = 0x17B // 379 + SYS_CHMOD = 0x17C // 380 + SYS_CHOWN = 0x17D // 381 + SYS_CLOSE = 0x17E // 382 + SYS_CLOSEDIR = 0x17F // 383 + SYS_CREAT = 0x180 // 384 + SYS_CTERMID = 0x181 // 385 + SYS_DUP = 0x182 // 386 + SYS_DUP2 = 0x183 // 387 + SYS_EXECL = 0x184 // 388 + SYS_EXECLE = 0x185 // 389 + SYS_EXECLP = 0x186 // 390 + SYS_EXECV = 0x187 // 391 + SYS_EXECVE = 0x188 // 392 + SYS_EXECVP = 0x189 // 393 + SYS_FCHMOD = 0x18A // 394 + SYS_FCHOWN = 0x18B // 395 + SYS_FCNTL = 0x18C // 396 + SYS_FILENO = 0x18D // 397 + SYS_FORK = 0x18E // 398 + SYS_FPATHCONF = 0x18F // 399 + SYS_FSTAT = 0x190 // 400 + SYS_FSYNC = 0x191 // 401 + SYS_FTRUNCATE = 0x192 // 402 + SYS_GETCWD = 0x193 // 403 + SYS_GETEGID = 0x194 // 404 + SYS_GETEUID = 0x195 // 405 + SYS_GETGID = 0x196 // 406 + SYS_GETGRGID = 0x197 // 407 + SYS_GETGRNAM = 0x198 // 408 + SYS_GETGROUPS = 0x199 // 409 + SYS_GETLOGIN = 0x19A // 410 + SYS_W_GETMNTENT = 0x19B // 411 + SYS_GETPGRP = 0x19C // 412 + SYS_GETPID = 0x19D // 413 + SYS_GETPPID = 0x19E // 414 + SYS_GETPWNAM = 0x19F // 415 + SYS_GETPWUID = 0x1A0 // 416 + SYS_GETUID = 0x1A1 // 417 + SYS_W_IOCTL = 0x1A2 // 418 + SYS_ISATTY = 0x1A3 // 419 + SYS_KILL = 0x1A4 // 420 + SYS_LINK = 0x1A5 // 421 + SYS_LSEEK = 0x1A6 // 422 + SYS_LSTAT = 0x1A7 // 423 + SYS_MKDIR = 0x1A8 // 424 + SYS_MKFIFO = 0x1A9 // 425 + SYS_MKNOD = 0x1AA // 426 + SYS_MOUNT = 0x1AB // 427 + SYS_OPEN = 0x1AC // 428 + SYS_OPENDIR = 0x1AD // 429 + SYS_PATHCONF = 0x1AE // 430 + SYS_PAUSE = 0x1AF // 431 + SYS_PIPE = 0x1B0 // 432 + SYS_W_GETPSENT = 0x1B1 // 433 + SYS_READ = 0x1B2 // 434 + SYS_READDIR = 0x1B3 // 435 + SYS_READLINK = 0x1B4 // 436 + SYS_REWINDDIR = 0x1B5 // 437 + SYS_RMDIR = 0x1B6 // 438 + SYS_SETEGID = 0x1B7 // 439 + SYS_SETEUID = 0x1B8 // 440 + SYS_SETGID = 0x1B9 // 441 + SYS_SETPGID = 0x1BA // 442 + SYS_SETSID = 0x1BB // 443 + SYS_SETUID = 0x1BC // 444 + SYS_SIGACTION = 0x1BD // 445 + SYS_SIGADDSET = 0x1BE // 446 + SYS_SIGDELSET = 0x1BF // 447 + SYS_SIGEMPTYSET = 0x1C0 // 448 + SYS_SIGFILLSET = 0x1C1 // 449 + SYS_SIGISMEMBER = 0x1C2 // 450 + SYS_SIGLONGJMP = 0x1C3 // 451 + SYS_SIGPENDING = 0x1C4 // 452 + SYS_SIGPROCMASK = 0x1C5 // 453 + SYS_SIGSETJMP = 0x1C6 // 454 + SYS_SIGSUSPEND = 0x1C7 // 455 + SYS_SLEEP = 0x1C8 // 456 + SYS_STAT = 0x1C9 // 457 + SYS_W_STATFS = 0x1CA // 458 + SYS_SYMLINK = 0x1CB // 459 + SYS_SYSCONF = 0x1CC // 460 + SYS_TCDRAIN = 0x1CD // 461 + SYS_TCFLOW = 0x1CE // 462 + SYS_TCFLUSH = 0x1CF // 463 + SYS_TCGETATTR = 0x1D0 // 464 + SYS_TCGETPGRP = 0x1D1 // 465 + SYS_TCSENDBREAK = 0x1D2 // 466 + SYS_TCSETATTR = 0x1D3 // 467 + SYS_TCSETPGRP = 0x1D4 // 468 + SYS_TIMES = 0x1D5 // 469 + SYS_TTYNAME = 0x1D6 // 470 + SYS_TZSET = 0x1D7 // 471 + SYS_UMASK = 0x1D8 // 472 + SYS_UMOUNT = 0x1D9 // 473 + SYS_UNAME = 0x1DA // 474 + SYS_UNLINK = 0x1DB // 475 + SYS_UTIME = 0x1DC // 476 + SYS_WAIT = 0x1DD // 477 + SYS_WAITPID = 0x1DE // 478 + SYS_WRITE = 0x1DF // 479 + SYS_CHAUDIT = 0x1E0 // 480 + SYS_FCHAUDIT = 0x1E1 // 481 + SYS_GETGROUPSBYNAME = 0x1E2 // 482 + SYS_SIGWAIT = 0x1E3 // 483 + SYS_PTHREAD_EXIT = 0x1E4 // 484 + SYS_PTHREAD_KILL = 0x1E5 // 485 + SYS_PTHREAD_ATTR_INIT = 0x1E6 // 486 + SYS_PTHREAD_ATTR_DESTROY = 0x1E7 // 487 + SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8 // 488 + SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9 // 489 + SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA // 490 + SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB // 491 + SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC // 492 + SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED // 493 + SYS_PTHREAD_CANCEL = 0x1EE // 494 + SYS_PTHREAD_CLEANUP_PUSH = 0x1EF // 495 + SYS_PTHREAD_CLEANUP_POP = 0x1F0 // 496 + SYS_PTHREAD_CONDATTR_INIT = 0x1F1 // 497 + SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2 // 498 + SYS_PTHREAD_COND_INIT = 0x1F3 // 499 + SYS_PTHREAD_COND_DESTROY = 0x1F4 // 500 + SYS_PTHREAD_COND_SIGNAL = 0x1F5 // 501 + SYS_PTHREAD_COND_BROADCAST = 0x1F6 // 502 + SYS_PTHREAD_COND_WAIT = 0x1F7 // 503 + SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8 // 504 + SYS_PTHREAD_CREATE = 0x1F9 // 505 + SYS_PTHREAD_DETACH = 0x1FA // 506 + SYS_PTHREAD_EQUAL = 0x1FB // 507 + SYS_PTHREAD_GETSPECIFIC = 0x1FC // 508 + SYS_PTHREAD_JOIN = 0x1FD // 509 + SYS_PTHREAD_KEY_CREATE = 0x1FE // 510 + SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF // 511 + SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200 // 512 + SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201 // 513 + SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202 // 514 + SYS_PTHREAD_MUTEX_INIT = 0x203 // 515 + SYS_PTHREAD_MUTEX_DESTROY = 0x204 // 516 + SYS_PTHREAD_MUTEX_LOCK = 0x205 // 517 + SYS_PTHREAD_MUTEX_TRYLOCK = 0x206 // 518 + SYS_PTHREAD_MUTEX_UNLOCK = 0x207 // 519 + SYS_PTHREAD_ONCE = 0x209 // 521 + SYS_PTHREAD_SELF = 0x20A // 522 + SYS_PTHREAD_SETINTR = 0x20B // 523 + SYS_PTHREAD_SETINTRTYPE = 0x20C // 524 + SYS_PTHREAD_SETSPECIFIC = 0x20D // 525 + SYS_PTHREAD_TESTINTR = 0x20E // 526 + SYS_PTHREAD_YIELD = 0x20F // 527 + SYS_TW_OPEN = 0x210 // 528 + SYS_TW_FCNTL = 0x211 // 529 + SYS_PTHREAD_JOIN_D4_NP = 0x212 // 530 + SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213 // 531 + SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214 // 532 + SYS_EXTLINK_NP = 0x215 // 533 + SYS___PASSWD = 0x216 // 534 + SYS_SETGROUPS = 0x217 // 535 + SYS_INITGROUPS = 0x218 // 536 + SYS_WCSPBRK = 0x23F // 575 + SYS_WCSRCHR = 0x240 // 576 + SYS_SVC99 = 0x241 // 577 + SYS___SVC99 = 0x241 // 577 + SYS_WCSWCS = 0x242 // 578 + SYS_LOCALECO = 0x243 // 579 + SYS_LOCALECONV = 0x243 // 579 + SYS___LIBREL = 0x244 // 580 + SYS_RELEASE = 0x245 // 581 + SYS___RLSE = 0x245 // 581 + SYS_FLOCATE = 0x246 // 582 + SYS___FLOCT = 0x246 // 582 + SYS_FDELREC = 0x247 // 583 + SYS___FDLREC = 0x247 // 583 + SYS_FETCH = 0x248 // 584 + SYS___FETCH = 0x248 // 584 + SYS_QSORT = 0x249 // 585 + SYS_GETENV = 0x24A // 586 + SYS_SYSTEM = 0x24B // 587 + SYS_BSEARCH = 0x24C // 588 + SYS_LDIV = 0x24D // 589 + SYS___THROW = 0x25E // 606 + SYS___RETHROW = 0x25F // 607 + SYS___CLEANUPCATCH = 0x260 // 608 + SYS___CATCHMATCH = 0x261 // 609 + SYS___CLEAN2UPCATCH = 0x262 // 610 + SYS_PUTENV = 0x26A // 618 + SYS___GETENV = 0x26F // 623 + SYS_GETPRIORITY = 0x270 // 624 + SYS_NICE = 0x271 // 625 + SYS_SETPRIORITY = 0x272 // 626 + SYS_GETITIMER = 0x273 // 627 + SYS_SETITIMER = 0x274 // 628 + SYS_MSGCTL = 0x275 // 629 + SYS_MSGGET = 0x276 // 630 + SYS_MSGRCV = 0x277 // 631 + SYS_MSGSND = 0x278 // 632 + SYS_MSGXRCV = 0x279 // 633 + SYS___MSGXR = 0x279 // 633 + SYS_SEMCTL = 0x27A // 634 + SYS_SEMGET = 0x27B // 635 + SYS_SEMOP = 0x27C // 636 + SYS_SHMAT = 0x27D // 637 + SYS_SHMCTL = 0x27E // 638 + SYS_SHMDT = 0x27F // 639 + SYS_SHMGET = 0x280 // 640 + SYS___GETIPC = 0x281 // 641 + SYS_SETGRENT = 0x282 // 642 + SYS_GETGRENT = 0x283 // 643 + SYS_ENDGRENT = 0x284 // 644 + SYS_SETPWENT = 0x285 // 645 + SYS_GETPWENT = 0x286 // 646 + SYS_ENDPWENT = 0x287 // 647 + SYS_BSD_SIGNAL = 0x288 // 648 + SYS_KILLPG = 0x289 // 649 + SYS_SIGALTSTACK = 0x28A // 650 + SYS_SIGHOLD = 0x28B // 651 + SYS_SIGIGNORE = 0x28C // 652 + SYS_SIGINTERRUPT = 0x28D // 653 + SYS_SIGPAUSE = 0x28E // 654 + SYS_SIGRELSE = 0x28F // 655 + SYS_SIGSET = 0x290 // 656 + SYS_SIGSTACK = 0x291 // 657 + SYS_GETRLIMIT = 0x292 // 658 + SYS_SETRLIMIT = 0x293 // 659 + SYS_GETRUSAGE = 0x294 // 660 + SYS_MMAP = 0x295 // 661 + SYS_MPROTECT = 0x296 // 662 + SYS_MSYNC = 0x297 // 663 + SYS_MUNMAP = 0x298 // 664 + SYS_CONFSTR = 0x299 // 665 + SYS_GETOPT = 0x29A // 666 + SYS_LCHOWN = 0x29B // 667 + SYS_TRUNCATE = 0x29C // 668 + SYS_GETSUBOPT = 0x29D // 669 + SYS_SETPGRP = 0x29E // 670 + SYS___GDERR = 0x29F // 671 + SYS___TZONE = 0x2A0 // 672 + SYS___DLGHT = 0x2A1 // 673 + SYS___OPARGF = 0x2A2 // 674 + SYS___OPOPTF = 0x2A3 // 675 + SYS___OPINDF = 0x2A4 // 676 + SYS___OPERRF = 0x2A5 // 677 + SYS_GETDATE = 0x2A6 // 678 + SYS_WAIT3 = 0x2A7 // 679 + SYS_WAITID = 0x2A8 // 680 + SYS___CATTRM = 0x2A9 // 681 + SYS___GDTRM = 0x2AA // 682 + SYS___RNDTRM = 0x2AB // 683 + SYS_CRYPT = 0x2AC // 684 + SYS_ENCRYPT = 0x2AD // 685 + SYS_SETKEY = 0x2AE // 686 + SYS___CNVBLK = 0x2AF // 687 + SYS___CRYTRM = 0x2B0 // 688 + SYS___ECRTRM = 0x2B1 // 689 + SYS_DRAND48 = 0x2B2 // 690 + SYS_ERAND48 = 0x2B3 // 691 + SYS_FSTATVFS = 0x2B4 // 692 + SYS_STATVFS = 0x2B5 // 693 + SYS_CATCLOSE = 0x2B6 // 694 + SYS_CATGETS = 0x2B7 // 695 + SYS_CATOPEN = 0x2B8 // 696 + SYS_BCMP = 0x2B9 // 697 + SYS_BCOPY = 0x2BA // 698 + SYS_BZERO = 0x2BB // 699 + SYS_FFS = 0x2BC // 700 + SYS_INDEX = 0x2BD // 701 + SYS_RINDEX = 0x2BE // 702 + SYS_STRCASECMP = 0x2BF // 703 + SYS_STRDUP = 0x2C0 // 704 + SYS_STRNCASECMP = 0x2C1 // 705 + SYS_INITSTATE = 0x2C2 // 706 + SYS_SETSTATE = 0x2C3 // 707 + SYS_RANDOM = 0x2C4 // 708 + SYS_SRANDOM = 0x2C5 // 709 + SYS_HCREATE = 0x2C6 // 710 + SYS_HDESTROY = 0x2C7 // 711 + SYS_HSEARCH = 0x2C8 // 712 + SYS_LFIND = 0x2C9 // 713 + SYS_LSEARCH = 0x2CA // 714 + SYS_TDELETE = 0x2CB // 715 + SYS_TFIND = 0x2CC // 716 + SYS_TSEARCH = 0x2CD // 717 + SYS_TWALK = 0x2CE // 718 + SYS_INSQUE = 0x2CF // 719 + SYS_REMQUE = 0x2D0 // 720 + SYS_POPEN = 0x2D1 // 721 + SYS_PCLOSE = 0x2D2 // 722 + SYS_SWAB = 0x2D3 // 723 + SYS_MEMCCPY = 0x2D4 // 724 + SYS_GETPAGESIZE = 0x2D8 // 728 + SYS_FCHDIR = 0x2D9 // 729 + SYS___OCLCK = 0x2DA // 730 + SYS___ATOE = 0x2DB // 731 + SYS___ATOE_L = 0x2DC // 732 + SYS___ETOA = 0x2DD // 733 + SYS___ETOA_L = 0x2DE // 734 + SYS_SETUTXENT = 0x2DF // 735 + SYS_GETUTXENT = 0x2E0 // 736 + SYS_ENDUTXENT = 0x2E1 // 737 + SYS_GETUTXID = 0x2E2 // 738 + SYS_GETUTXLINE = 0x2E3 // 739 + SYS_PUTUTXLINE = 0x2E4 // 740 + SYS_FMTMSG = 0x2E5 // 741 + SYS_JRAND48 = 0x2E6 // 742 + SYS_LRAND48 = 0x2E7 // 743 + SYS_MRAND48 = 0x2E8 // 744 + SYS_NRAND48 = 0x2E9 // 745 + SYS_LCONG48 = 0x2EA // 746 + SYS_SRAND48 = 0x2EB // 747 + SYS_SEED48 = 0x2EC // 748 + SYS_ISASCII = 0x2ED // 749 + SYS_TOASCII = 0x2EE // 750 + SYS_A64L = 0x2EF // 751 + SYS_L64A = 0x2F0 // 752 + SYS_UALARM = 0x2F1 // 753 + SYS_USLEEP = 0x2F2 // 754 + SYS___UTXTRM = 0x2F3 // 755 + SYS___SRCTRM = 0x2F4 // 756 + SYS_FTIME = 0x2F5 // 757 + SYS_GETTIMEOFDAY = 0x2F6 // 758 + SYS_DBM_CLEARERR = 0x2F7 // 759 + SYS_DBM_CLOSE = 0x2F8 // 760 + SYS_DBM_DELETE = 0x2F9 // 761 + SYS_DBM_ERROR = 0x2FA // 762 + SYS_DBM_FETCH = 0x2FB // 763 + SYS_DBM_FIRSTKEY = 0x2FC // 764 + SYS_DBM_NEXTKEY = 0x2FD // 765 + SYS_DBM_OPEN = 0x2FE // 766 + SYS_DBM_STORE = 0x2FF // 767 + SYS___NDMTRM = 0x300 // 768 + SYS_FTOK = 0x301 // 769 + SYS_BASENAME = 0x302 // 770 + SYS_DIRNAME = 0x303 // 771 + SYS_GETDTABLESIZE = 0x304 // 772 + SYS_MKSTEMP = 0x305 // 773 + SYS_MKTEMP = 0x306 // 774 + SYS_NFTW = 0x307 // 775 + SYS_GETWD = 0x308 // 776 + SYS_LOCKF = 0x309 // 777 + SYS__LONGJMP = 0x30D // 781 + SYS__SETJMP = 0x30E // 782 + SYS_VFORK = 0x30F // 783 + SYS_WORDEXP = 0x310 // 784 + SYS_WORDFREE = 0x311 // 785 + SYS_GETPGID = 0x312 // 786 + SYS_GETSID = 0x313 // 787 + SYS___UTMPXNAME = 0x314 // 788 + SYS_CUSERID = 0x315 // 789 + SYS_GETPASS = 0x316 // 790 + SYS_FNMATCH = 0x317 // 791 + SYS_FTW = 0x318 // 792 + SYS_GETW = 0x319 // 793 + SYS_GLOB = 0x31A // 794 + SYS_GLOBFREE = 0x31B // 795 + SYS_PUTW = 0x31C // 796 + SYS_SEEKDIR = 0x31D // 797 + SYS_TELLDIR = 0x31E // 798 + SYS_TEMPNAM = 0x31F // 799 + SYS_ACOSH = 0x320 // 800 + SYS_ASINH = 0x321 // 801 + SYS_ATANH = 0x322 // 802 + SYS_CBRT = 0x323 // 803 + SYS_EXPM1 = 0x324 // 804 + SYS_ILOGB = 0x325 // 805 + SYS_LOGB = 0x326 // 806 + SYS_LOG1P = 0x327 // 807 + SYS_NEXTAFTER = 0x328 // 808 + SYS_RINT = 0x329 // 809 + SYS_REMAINDER = 0x32A // 810 + SYS_SCALB = 0x32B // 811 + SYS_LGAMMA = 0x32C // 812 + SYS_TTYSLOT = 0x32D // 813 + SYS_GETTIMEOFDAY_R = 0x32E // 814 + SYS_SYNC = 0x32F // 815 + SYS_SPAWN = 0x330 // 816 + SYS_SPAWNP = 0x331 // 817 + SYS_GETLOGIN_UU = 0x332 // 818 + SYS_ECVT = 0x333 // 819 + SYS_FCVT = 0x334 // 820 + SYS_GCVT = 0x335 // 821 + SYS_ACCEPT = 0x336 // 822 + SYS_BIND = 0x337 // 823 + SYS_CONNECT = 0x338 // 824 + SYS_ENDHOSTENT = 0x339 // 825 + SYS_ENDPROTOENT = 0x33A // 826 + SYS_ENDSERVENT = 0x33B // 827 + SYS_GETHOSTBYADDR_R = 0x33C // 828 + SYS_GETHOSTBYADDR = 0x33D // 829 + SYS_GETHOSTBYNAME_R = 0x33E // 830 + SYS_GETHOSTBYNAME = 0x33F // 831 + SYS_GETHOSTENT = 0x340 // 832 + SYS_GETHOSTID = 0x341 // 833 + SYS_GETHOSTNAME = 0x342 // 834 + SYS_GETNETBYADDR = 0x343 // 835 + SYS_GETNETBYNAME = 0x344 // 836 + SYS_GETNETENT = 0x345 // 837 + SYS_GETPEERNAME = 0x346 // 838 + SYS_GETPROTOBYNAME = 0x347 // 839 + SYS_GETPROTOBYNUMBER = 0x348 // 840 + SYS_GETPROTOENT = 0x349 // 841 + SYS_GETSERVBYNAME = 0x34A // 842 + SYS_GETSERVBYPORT = 0x34B // 843 + SYS_GETSERVENT = 0x34C // 844 + SYS_GETSOCKNAME = 0x34D // 845 + SYS_GETSOCKOPT = 0x34E // 846 + SYS_INET_ADDR = 0x34F // 847 + SYS_INET_LNAOF = 0x350 // 848 + SYS_INET_MAKEADDR = 0x351 // 849 + SYS_INET_NETOF = 0x352 // 850 + SYS_INET_NETWORK = 0x353 // 851 + SYS_INET_NTOA = 0x354 // 852 + SYS_IOCTL = 0x355 // 853 + SYS_LISTEN = 0x356 // 854 + SYS_READV = 0x357 // 855 + SYS_RECV = 0x358 // 856 + SYS_RECVFROM = 0x359 // 857 + SYS_SELECT = 0x35B // 859 + SYS_SELECTEX = 0x35C // 860 + SYS_SEND = 0x35D // 861 + SYS_SENDTO = 0x35F // 863 + SYS_SETHOSTENT = 0x360 // 864 + SYS_SETNETENT = 0x361 // 865 + SYS_SETPEER = 0x362 // 866 + SYS_SETPROTOENT = 0x363 // 867 + SYS_SETSERVENT = 0x364 // 868 + SYS_SETSOCKOPT = 0x365 // 869 + SYS_SHUTDOWN = 0x366 // 870 + SYS_SOCKET = 0x367 // 871 + SYS_SOCKETPAIR = 0x368 // 872 + SYS_WRITEV = 0x369 // 873 + SYS_CHROOT = 0x36A // 874 + SYS_W_STATVFS = 0x36B // 875 + SYS_ULIMIT = 0x36C // 876 + SYS_ISNAN = 0x36D // 877 + SYS_UTIMES = 0x36E // 878 + SYS___H_ERRNO = 0x36F // 879 + SYS_ENDNETENT = 0x370 // 880 + SYS_CLOSELOG = 0x371 // 881 + SYS_OPENLOG = 0x372 // 882 + SYS_SETLOGMASK = 0x373 // 883 + SYS_SYSLOG = 0x374 // 884 + SYS_PTSNAME = 0x375 // 885 + SYS_SETREUID = 0x376 // 886 + SYS_SETREGID = 0x377 // 887 + SYS_REALPATH = 0x378 // 888 + SYS___SIGNGAM = 0x379 // 889 + SYS_GRANTPT = 0x37A // 890 + SYS_UNLOCKPT = 0x37B // 891 + SYS_TCGETSID = 0x37C // 892 + SYS___TCGETCP = 0x37D // 893 + SYS___TCSETCP = 0x37E // 894 + SYS___TCSETTABLES = 0x37F // 895 + SYS_POLL = 0x380 // 896 + SYS_REXEC = 0x381 // 897 + SYS___ISASCII2 = 0x382 // 898 + SYS___TOASCII2 = 0x383 // 899 + SYS_CHPRIORITY = 0x384 // 900 + SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385 // 901 + SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386 // 902 + SYS_PTHREAD_SET_LIMIT_NP = 0x387 // 903 + SYS___STNETENT = 0x388 // 904 + SYS___STPROTOENT = 0x389 // 905 + SYS___STSERVENT = 0x38A // 906 + SYS___STHOSTENT = 0x38B // 907 + SYS_NLIST = 0x38C // 908 + SYS___IPDBCS = 0x38D // 909 + SYS___IPDSPX = 0x38E // 910 + SYS___IPMSGC = 0x38F // 911 + SYS___SELECT1 = 0x390 // 912 + SYS_PTHREAD_SECURITY_NP = 0x391 // 913 + SYS___CHECK_RESOURCE_AUTH_NP = 0x392 // 914 + SYS___CONVERT_ID_NP = 0x393 // 915 + SYS___OPENVMREL = 0x394 // 916 + SYS_WMEMCHR = 0x395 // 917 + SYS_WMEMCMP = 0x396 // 918 + SYS_WMEMCPY = 0x397 // 919 + SYS_WMEMMOVE = 0x398 // 920 + SYS_WMEMSET = 0x399 // 921 + SYS___FPUTWC = 0x400 // 1024 + SYS___PUTWC = 0x401 // 1025 + SYS___PWCHAR = 0x402 // 1026 + SYS___WCSFTM = 0x403 // 1027 + SYS___WCSTOK = 0x404 // 1028 + SYS___WCWDTH = 0x405 // 1029 + SYS_T_ACCEPT = 0x409 // 1033 + SYS_T_ALLOC = 0x40A // 1034 + SYS_T_BIND = 0x40B // 1035 + SYS_T_CLOSE = 0x40C // 1036 + SYS_T_CONNECT = 0x40D // 1037 + SYS_T_ERROR = 0x40E // 1038 + SYS_T_FREE = 0x40F // 1039 + SYS_T_GETINFO = 0x410 // 1040 + SYS_T_GETPROTADDR = 0x411 // 1041 + SYS_T_GETSTATE = 0x412 // 1042 + SYS_T_LISTEN = 0x413 // 1043 + SYS_T_LOOK = 0x414 // 1044 + SYS_T_OPEN = 0x415 // 1045 + SYS_T_OPTMGMT = 0x416 // 1046 + SYS_T_RCV = 0x417 // 1047 + SYS_T_RCVCONNECT = 0x418 // 1048 + SYS_T_RCVDIS = 0x419 // 1049 + SYS_T_RCVREL = 0x41A // 1050 + SYS_T_RCVUDATA = 0x41B // 1051 + SYS_T_RCVUDERR = 0x41C // 1052 + SYS_T_SND = 0x41D // 1053 + SYS_T_SNDDIS = 0x41E // 1054 + SYS_T_SNDREL = 0x41F // 1055 + SYS_T_SNDUDATA = 0x420 // 1056 + SYS_T_STRERROR = 0x421 // 1057 + SYS_T_SYNC = 0x422 // 1058 + SYS_T_UNBIND = 0x423 // 1059 + SYS___T_ERRNO = 0x424 // 1060 + SYS___RECVMSG2 = 0x425 // 1061 + SYS___SENDMSG2 = 0x426 // 1062 + SYS_FATTACH = 0x427 // 1063 + SYS_FDETACH = 0x428 // 1064 + SYS_GETMSG = 0x429 // 1065 + SYS_GETPMSG = 0x42A // 1066 + SYS_ISASTREAM = 0x42B // 1067 + SYS_PUTMSG = 0x42C // 1068 + SYS_PUTPMSG = 0x42D // 1069 + SYS___ISPOSIXON = 0x42E // 1070 + SYS___OPENMVSREL = 0x42F // 1071 + SYS_GETCONTEXT = 0x430 // 1072 + SYS_SETCONTEXT = 0x431 // 1073 + SYS_MAKECONTEXT = 0x432 // 1074 + SYS_SWAPCONTEXT = 0x433 // 1075 + SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434 // 1076 + SYS_GETCLIENTID = 0x470 // 1136 + SYS___GETCLIENTID = 0x471 // 1137 + SYS_GETSTABLESIZE = 0x472 // 1138 + SYS_GETIBMOPT = 0x473 // 1139 + SYS_GETIBMSOCKOPT = 0x474 // 1140 + SYS_GIVESOCKET = 0x475 // 1141 + SYS_IBMSFLUSH = 0x476 // 1142 + SYS_MAXDESC = 0x477 // 1143 + SYS_SETIBMOPT = 0x478 // 1144 + SYS_SETIBMSOCKOPT = 0x479 // 1145 + SYS_SOCK_DEBUG = 0x47A // 1146 + SYS_SOCK_DO_TESTSTOR = 0x47D // 1149 + SYS_TAKESOCKET = 0x47E // 1150 + SYS___SERVER_INIT = 0x47F // 1151 + SYS___SERVER_PWU = 0x480 // 1152 + SYS_PTHREAD_TAG_NP = 0x481 // 1153 + SYS___CONSOLE = 0x482 // 1154 + SYS___WSINIT = 0x483 // 1155 + SYS___IPTCPN = 0x489 // 1161 + SYS___SMF_RECORD = 0x48A // 1162 + SYS___IPHOST = 0x48B // 1163 + SYS___IPNODE = 0x48C // 1164 + SYS___SERVER_CLASSIFY_CREATE = 0x48D // 1165 + SYS___SERVER_CLASSIFY_DESTROY = 0x48E // 1166 + SYS___SERVER_CLASSIFY_RESET = 0x48F // 1167 + SYS___SERVER_CLASSIFY = 0x490 // 1168 + SYS___HEAPRPT = 0x496 // 1174 + SYS___FNWSA = 0x49B // 1179 + SYS___SPAWN2 = 0x49D // 1181 + SYS___SPAWNP2 = 0x49E // 1182 + SYS___GDRR = 0x4A1 // 1185 + SYS___HRRNO = 0x4A2 // 1186 + SYS___OPRG = 0x4A3 // 1187 + SYS___OPRR = 0x4A4 // 1188 + SYS___OPND = 0x4A5 // 1189 + SYS___OPPT = 0x4A6 // 1190 + SYS___SIGGM = 0x4A7 // 1191 + SYS___DGHT = 0x4A8 // 1192 + SYS___TZNE = 0x4A9 // 1193 + SYS___TZZN = 0x4AA // 1194 + SYS___TRRNO = 0x4AF // 1199 + SYS___ENVN = 0x4B0 // 1200 + SYS___MLOCKALL = 0x4B1 // 1201 + SYS_CREATEWO = 0x4B2 // 1202 + SYS_CREATEWORKUNIT = 0x4B2 // 1202 + SYS_CONTINUE = 0x4B3 // 1203 + SYS_CONTINUEWORKUNIT = 0x4B3 // 1203 + SYS_CONNECTW = 0x4B4 // 1204 + SYS_CONNECTWORKMGR = 0x4B4 // 1204 + SYS_CONNECTS = 0x4B5 // 1205 + SYS_CONNECTSERVER = 0x4B5 // 1205 + SYS_DISCONNE = 0x4B6 // 1206 + SYS_DISCONNECTSERVER = 0x4B6 // 1206 + SYS_JOINWORK = 0x4B7 // 1207 + SYS_JOINWORKUNIT = 0x4B7 // 1207 + SYS_LEAVEWOR = 0x4B8 // 1208 + SYS_LEAVEWORKUNIT = 0x4B8 // 1208 + SYS_DELETEWO = 0x4B9 // 1209 + SYS_DELETEWORKUNIT = 0x4B9 // 1209 + SYS_QUERYMET = 0x4BA // 1210 + SYS_QUERYMETRICS = 0x4BA // 1210 + SYS_QUERYSCH = 0x4BB // 1211 + SYS_QUERYSCHENV = 0x4BB // 1211 + SYS_CHECKSCH = 0x4BC // 1212 + SYS_CHECKSCHENV = 0x4BC // 1212 + SYS___PID_AFFINITY = 0x4BD // 1213 + SYS___ASINH_B = 0x4BE // 1214 + SYS___ATAN_B = 0x4BF // 1215 + SYS___CBRT_B = 0x4C0 // 1216 + SYS___CEIL_B = 0x4C1 // 1217 + SYS_COPYSIGN = 0x4C2 // 1218 + SYS___COS_B = 0x4C3 // 1219 + SYS___ERF_B = 0x4C4 // 1220 + SYS___ERFC_B = 0x4C5 // 1221 + SYS___EXPM1_B = 0x4C6 // 1222 + SYS___FABS_B = 0x4C7 // 1223 + SYS_FINITE = 0x4C8 // 1224 + SYS___FLOOR_B = 0x4C9 // 1225 + SYS___FREXP_B = 0x4CA // 1226 + SYS___ILOGB_B = 0x4CB // 1227 + SYS___ISNAN_B = 0x4CC // 1228 + SYS___LDEXP_B = 0x4CD // 1229 + SYS___LOG1P_B = 0x4CE // 1230 + SYS___LOGB_B = 0x4CF // 1231 + SYS_MATHERR = 0x4D0 // 1232 + SYS___MODF_B = 0x4D1 // 1233 + SYS___NEXTAFTER_B = 0x4D2 // 1234 + SYS___RINT_B = 0x4D3 // 1235 + SYS_SCALBN = 0x4D4 // 1236 + SYS_SIGNIFIC = 0x4D5 // 1237 + SYS_SIGNIFICAND = 0x4D5 // 1237 + SYS___SIN_B = 0x4D6 // 1238 + SYS___TAN_B = 0x4D7 // 1239 + SYS___TANH_B = 0x4D8 // 1240 + SYS___ACOS_B = 0x4D9 // 1241 + SYS___ACOSH_B = 0x4DA // 1242 + SYS___ASIN_B = 0x4DB // 1243 + SYS___ATAN2_B = 0x4DC // 1244 + SYS___ATANH_B = 0x4DD // 1245 + SYS___COSH_B = 0x4DE // 1246 + SYS___EXP_B = 0x4DF // 1247 + SYS___FMOD_B = 0x4E0 // 1248 + SYS___GAMMA_B = 0x4E1 // 1249 + SYS_GAMMA_R = 0x4E2 // 1250 + SYS___HYPOT_B = 0x4E3 // 1251 + SYS___J0_B = 0x4E4 // 1252 + SYS___Y0_B = 0x4E5 // 1253 + SYS___J1_B = 0x4E6 // 1254 + SYS___Y1_B = 0x4E7 // 1255 + SYS___JN_B = 0x4E8 // 1256 + SYS___YN_B = 0x4E9 // 1257 + SYS___LGAMMA_B = 0x4EA // 1258 + SYS_LGAMMA_R = 0x4EB // 1259 + SYS___LOG_B = 0x4EC // 1260 + SYS___LOG10_B = 0x4ED // 1261 + SYS___POW_B = 0x4EE // 1262 + SYS___REMAINDER_B = 0x4EF // 1263 + SYS___SCALB_B = 0x4F0 // 1264 + SYS___SINH_B = 0x4F1 // 1265 + SYS___SQRT_B = 0x4F2 // 1266 + SYS___OPENDIR2 = 0x4F3 // 1267 + SYS___READDIR2 = 0x4F4 // 1268 + SYS___LOGIN = 0x4F5 // 1269 + SYS___OPEN_STAT = 0x4F6 // 1270 + SYS_ACCEPT_AND_RECV = 0x4F7 // 1271 + SYS___FP_SETMODE = 0x4F8 // 1272 + SYS___SIGACTIONSET = 0x4FB // 1275 + SYS___UCREATE = 0x4FC // 1276 + SYS___UMALLOC = 0x4FD // 1277 + SYS___UFREE = 0x4FE // 1278 + SYS___UHEAPREPORT = 0x4FF // 1279 + SYS___ISBFP = 0x500 // 1280 + SYS___FP_CAST = 0x501 // 1281 + SYS___CERTIFICATE = 0x502 // 1282 + SYS_SEND_FILE = 0x503 // 1283 + SYS_AIO_CANCEL = 0x504 // 1284 + SYS_AIO_ERROR = 0x505 // 1285 + SYS_AIO_READ = 0x506 // 1286 + SYS_AIO_RETURN = 0x507 // 1287 + SYS_AIO_SUSPEND = 0x508 // 1288 + SYS_AIO_WRITE = 0x509 // 1289 + SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A // 1290 + SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B // 1291 + SYS_PTHREAD_RWLOCK_DESTROY = 0x50C // 1292 + SYS_PTHREAD_RWLOCK_INIT = 0x50D // 1293 + SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E // 1294 + SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F // 1295 + SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510 // 1296 + SYS_PTHREAD_RWLOCK_UNLOCK = 0x511 // 1297 + SYS_PTHREAD_RWLOCK_WRLOCK = 0x512 // 1298 + SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513 // 1299 + SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514 // 1300 + SYS_PTHREAD_RWLOCKATTR_INIT = 0x515 // 1301 + SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516 // 1302 + SYS___CTTBL = 0x517 // 1303 + SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518 // 1304 + SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519 // 1305 + SYS___FP_CLR_FLAG = 0x51A // 1306 + SYS___FP_READ_FLAG = 0x51B // 1307 + SYS___FP_RAISE_XCP = 0x51C // 1308 + SYS___FP_CLASS = 0x51D // 1309 + SYS___FP_FINITE = 0x51E // 1310 + SYS___FP_ISNAN = 0x51F // 1311 + SYS___FP_UNORDERED = 0x520 // 1312 + SYS___FP_READ_RND = 0x521 // 1313 + SYS___FP_READ_RND_B = 0x522 // 1314 + SYS___FP_SWAP_RND = 0x523 // 1315 + SYS___FP_SWAP_RND_B = 0x524 // 1316 + SYS___FP_LEVEL = 0x525 // 1317 + SYS___FP_BTOH = 0x526 // 1318 + SYS___FP_HTOB = 0x527 // 1319 + SYS___FPC_RD = 0x528 // 1320 + SYS___FPC_WR = 0x529 // 1321 + SYS___FPC_RW = 0x52A // 1322 + SYS___FPC_SM = 0x52B // 1323 + SYS___FPC_RS = 0x52C // 1324 + SYS_SIGTIMEDWAIT = 0x52D // 1325 + SYS_SIGWAITINFO = 0x52E // 1326 + SYS___CHKBFP = 0x52F // 1327 + SYS___W_PIOCTL = 0x59E // 1438 + SYS___OSENV = 0x59F // 1439 + SYS_EXPORTWO = 0x5A1 // 1441 + SYS_EXPORTWORKUNIT = 0x5A1 // 1441 + SYS_UNDOEXPO = 0x5A2 // 1442 + SYS_UNDOEXPORTWORKUNIT = 0x5A2 // 1442 + SYS_IMPORTWO = 0x5A3 // 1443 + SYS_IMPORTWORKUNIT = 0x5A3 // 1443 + SYS_UNDOIMPO = 0x5A4 // 1444 + SYS_UNDOIMPORTWORKUNIT = 0x5A4 // 1444 + SYS_EXTRACTW = 0x5A5 // 1445 + SYS_EXTRACTWORKUNIT = 0x5A5 // 1445 + SYS___CPL = 0x5A6 // 1446 + SYS___MAP_INIT = 0x5A7 // 1447 + SYS___MAP_SERVICE = 0x5A8 // 1448 + SYS_SIGQUEUE = 0x5A9 // 1449 + SYS___MOUNT = 0x5AA // 1450 + SYS___GETUSERID = 0x5AB // 1451 + SYS___IPDOMAINNAME = 0x5AC // 1452 + SYS_QUERYENC = 0x5AD // 1453 + SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD // 1453 + SYS_CONNECTE = 0x5AE // 1454 + SYS_CONNECTEXPORTIMPORT = 0x5AE // 1454 + SYS___FP_SWAPMODE = 0x5AF // 1455 + SYS_STRTOLL = 0x5B0 // 1456 + SYS_STRTOULL = 0x5B1 // 1457 + SYS___DSA_PREV = 0x5B2 // 1458 + SYS___EP_FIND = 0x5B3 // 1459 + SYS___SERVER_THREADS_QUERY = 0x5B4 // 1460 + SYS___MSGRCV_TIMED = 0x5B7 // 1463 + SYS___SEMOP_TIMED = 0x5B8 // 1464 + SYS___GET_CPUID = 0x5B9 // 1465 + SYS___GET_SYSTEM_SETTINGS = 0x5BA // 1466 + SYS_FTELLO = 0x5C8 // 1480 + SYS_FSEEKO = 0x5C9 // 1481 + SYS_LLDIV = 0x5CB // 1483 + SYS_WCSTOLL = 0x5CC // 1484 + SYS_WCSTOULL = 0x5CD // 1485 + SYS_LLABS = 0x5CE // 1486 + SYS___CONSOLE2 = 0x5D2 // 1490 + SYS_INET_NTOP = 0x5D3 // 1491 + SYS_INET_PTON = 0x5D4 // 1492 + SYS___RES = 0x5D6 // 1494 + SYS_RES_MKQUERY = 0x5D7 // 1495 + SYS_RES_INIT = 0x5D8 // 1496 + SYS_RES_QUERY = 0x5D9 // 1497 + SYS_RES_SEARCH = 0x5DA // 1498 + SYS_RES_SEND = 0x5DB // 1499 + SYS_RES_QUERYDOMAIN = 0x5DC // 1500 + SYS_DN_EXPAND = 0x5DD // 1501 + SYS_DN_SKIPNAME = 0x5DE // 1502 + SYS_DN_COMP = 0x5DF // 1503 + SYS_ASCTIME_R = 0x5E0 // 1504 + SYS_CTIME_R = 0x5E1 // 1505 + SYS_GMTIME_R = 0x5E2 // 1506 + SYS_LOCALTIME_R = 0x5E3 // 1507 + SYS_RAND_R = 0x5E4 // 1508 + SYS_STRTOK_R = 0x5E5 // 1509 + SYS_READDIR_R = 0x5E6 // 1510 + SYS_GETGRGID_R = 0x5E7 // 1511 + SYS_GETGRNAM_R = 0x5E8 // 1512 + SYS_GETLOGIN_R = 0x5E9 // 1513 + SYS_GETPWNAM_R = 0x5EA // 1514 + SYS_GETPWUID_R = 0x5EB // 1515 + SYS_TTYNAME_R = 0x5EC // 1516 + SYS_PTHREAD_ATFORK = 0x5ED // 1517 + SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE // 1518 + SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF // 1519 + SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0 // 1520 + SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1 // 1521 + SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2 // 1522 + SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3 // 1523 + SYS_PTHREAD_GETCONCURRENCY = 0x5F4 // 1524 + SYS_PTHREAD_KEY_DELETE = 0x5F5 // 1525 + SYS_PTHREAD_SETCONCURRENCY = 0x5F6 // 1526 + SYS_PTHREAD_SIGMASK = 0x5F7 // 1527 + SYS___DISCARDDATA = 0x5F8 // 1528 + SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9 // 1529 + SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA // 1530 + SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB // 1531 + SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC // 1532 + SYS_PTHREAD_DETACH_U98 = 0x5FD // 1533 + SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE // 1534 + SYS_PTHREAD_SETCANCELSTATE = 0x5FF // 1535 + SYS_PTHREAD_SETCANCELTYPE = 0x600 // 1536 + SYS_PTHREAD_TESTCANCEL = 0x601 // 1537 + SYS___ATANF_B = 0x602 // 1538 + SYS___ATANL_B = 0x603 // 1539 + SYS___CEILF_B = 0x604 // 1540 + SYS___CEILL_B = 0x605 // 1541 + SYS___COSF_B = 0x606 // 1542 + SYS___COSL_B = 0x607 // 1543 + SYS___FABSF_B = 0x608 // 1544 + SYS___FABSL_B = 0x609 // 1545 + SYS___FLOORF_B = 0x60A // 1546 + SYS___FLOORL_B = 0x60B // 1547 + SYS___FREXPF_B = 0x60C // 1548 + SYS___FREXPL_B = 0x60D // 1549 + SYS___LDEXPF_B = 0x60E // 1550 + SYS___LDEXPL_B = 0x60F // 1551 + SYS___SINF_B = 0x610 // 1552 + SYS___SINL_B = 0x611 // 1553 + SYS___TANF_B = 0x612 // 1554 + SYS___TANL_B = 0x613 // 1555 + SYS___TANHF_B = 0x614 // 1556 + SYS___TANHL_B = 0x615 // 1557 + SYS___ACOSF_B = 0x616 // 1558 + SYS___ACOSL_B = 0x617 // 1559 + SYS___ASINF_B = 0x618 // 1560 + SYS___ASINL_B = 0x619 // 1561 + SYS___ATAN2F_B = 0x61A // 1562 + SYS___ATAN2L_B = 0x61B // 1563 + SYS___COSHF_B = 0x61C // 1564 + SYS___COSHL_B = 0x61D // 1565 + SYS___EXPF_B = 0x61E // 1566 + SYS___EXPL_B = 0x61F // 1567 + SYS___LOGF_B = 0x620 // 1568 + SYS___LOGL_B = 0x621 // 1569 + SYS___LOG10F_B = 0x622 // 1570 + SYS___LOG10L_B = 0x623 // 1571 + SYS___POWF_B = 0x624 // 1572 + SYS___POWL_B = 0x625 // 1573 + SYS___SINHF_B = 0x626 // 1574 + SYS___SINHL_B = 0x627 // 1575 + SYS___SQRTF_B = 0x628 // 1576 + SYS___SQRTL_B = 0x629 // 1577 + SYS___ABSF_B = 0x62A // 1578 + SYS___ABS_B = 0x62B // 1579 + SYS___ABSL_B = 0x62C // 1580 + SYS___FMODF_B = 0x62D // 1581 + SYS___FMODL_B = 0x62E // 1582 + SYS___MODFF_B = 0x62F // 1583 + SYS___MODFL_B = 0x630 // 1584 + SYS_ABSF = 0x631 // 1585 + SYS_ABSL = 0x632 // 1586 + SYS_ACOSF = 0x633 // 1587 + SYS_ACOSL = 0x634 // 1588 + SYS_ASINF = 0x635 // 1589 + SYS_ASINL = 0x636 // 1590 + SYS_ATAN2F = 0x637 // 1591 + SYS_ATAN2L = 0x638 // 1592 + SYS_ATANF = 0x639 // 1593 + SYS_ATANL = 0x63A // 1594 + SYS_CEILF = 0x63B // 1595 + SYS_CEILL = 0x63C // 1596 + SYS_COSF = 0x63D // 1597 + SYS_COSL = 0x63E // 1598 + SYS_COSHF = 0x63F // 1599 + SYS_COSHL = 0x640 // 1600 + SYS_EXPF = 0x641 // 1601 + SYS_EXPL = 0x642 // 1602 + SYS_TANHF = 0x643 // 1603 + SYS_TANHL = 0x644 // 1604 + SYS_LOG10F = 0x645 // 1605 + SYS_LOG10L = 0x646 // 1606 + SYS_LOGF = 0x647 // 1607 + SYS_LOGL = 0x648 // 1608 + SYS_POWF = 0x649 // 1609 + SYS_POWL = 0x64A // 1610 + SYS_SINF = 0x64B // 1611 + SYS_SINL = 0x64C // 1612 + SYS_SQRTF = 0x64D // 1613 + SYS_SQRTL = 0x64E // 1614 + SYS_SINHF = 0x64F // 1615 + SYS_SINHL = 0x650 // 1616 + SYS_TANF = 0x651 // 1617 + SYS_TANL = 0x652 // 1618 + SYS_FABSF = 0x653 // 1619 + SYS_FABSL = 0x654 // 1620 + SYS_FLOORF = 0x655 // 1621 + SYS_FLOORL = 0x656 // 1622 + SYS_FMODF = 0x657 // 1623 + SYS_FMODL = 0x658 // 1624 + SYS_FREXPF = 0x659 // 1625 + SYS_FREXPL = 0x65A // 1626 + SYS_LDEXPF = 0x65B // 1627 + SYS_LDEXPL = 0x65C // 1628 + SYS_MODFF = 0x65D // 1629 + SYS_MODFL = 0x65E // 1630 + SYS_BTOWC = 0x65F // 1631 + SYS___CHATTR = 0x660 // 1632 + SYS___FCHATTR = 0x661 // 1633 + SYS___TOCCSID = 0x662 // 1634 + SYS___CSNAMETYPE = 0x663 // 1635 + SYS___TOCSNAME = 0x664 // 1636 + SYS___CCSIDTYPE = 0x665 // 1637 + SYS___AE_CORRESTBL_QUERY = 0x666 // 1638 + SYS___AE_AUTOCONVERT_STATE = 0x667 // 1639 + SYS_DN_FIND = 0x668 // 1640 + SYS___GETHOSTBYADDR_A = 0x669 // 1641 + SYS___GETHOSTBYNAME_A = 0x66A // 1642 + SYS___RES_INIT_A = 0x66B // 1643 + SYS___GETHOSTBYADDR_R_A = 0x66C // 1644 + SYS___GETHOSTBYNAME_R_A = 0x66D // 1645 + SYS___CHARMAP_INIT_A = 0x66E // 1646 + SYS___MBLEN_A = 0x66F // 1647 + SYS___MBLEN_SB_A = 0x670 // 1648 + SYS___MBLEN_STD_A = 0x671 // 1649 + SYS___MBLEN_UTF = 0x672 // 1650 + SYS___MBSTOWCS_A = 0x673 // 1651 + SYS___MBSTOWCS_STD_A = 0x674 // 1652 + SYS___MBTOWC_A = 0x675 // 1653 + SYS___MBTOWC_ISO1 = 0x676 // 1654 + SYS___MBTOWC_SBCS = 0x677 // 1655 + SYS___MBTOWC_MBCS = 0x678 // 1656 + SYS___MBTOWC_UTF = 0x679 // 1657 + SYS___WCSTOMBS_A = 0x67A // 1658 + SYS___WCSTOMBS_STD_A = 0x67B // 1659 + SYS___WCSWIDTH_A = 0x67C // 1660 + SYS___GETGRGID_R_A = 0x67D // 1661 + SYS___WCSWIDTH_STD_A = 0x67E // 1662 + SYS___WCSWIDTH_ASIA = 0x67F // 1663 + SYS___CSID_A = 0x680 // 1664 + SYS___CSID_STD_A = 0x681 // 1665 + SYS___WCSID_A = 0x682 // 1666 + SYS___WCSID_STD_A = 0x683 // 1667 + SYS___WCTOMB_A = 0x684 // 1668 + SYS___WCTOMB_ISO1 = 0x685 // 1669 + SYS___WCTOMB_STD_A = 0x686 // 1670 + SYS___WCTOMB_UTF = 0x687 // 1671 + SYS___WCWIDTH_A = 0x688 // 1672 + SYS___GETGRNAM_R_A = 0x689 // 1673 + SYS___WCWIDTH_STD_A = 0x68A // 1674 + SYS___WCWIDTH_ASIA = 0x68B // 1675 + SYS___GETPWNAM_R_A = 0x68C // 1676 + SYS___GETPWUID_R_A = 0x68D // 1677 + SYS___GETLOGIN_R_A = 0x68E // 1678 + SYS___TTYNAME_R_A = 0x68F // 1679 + SYS___READDIR_R_A = 0x690 // 1680 + SYS___E2A_S = 0x691 // 1681 + SYS___FNMATCH_A = 0x692 // 1682 + SYS___FNMATCH_C_A = 0x693 // 1683 + SYS___EXECL_A = 0x694 // 1684 + SYS___FNMATCH_STD_A = 0x695 // 1685 + SYS___REGCOMP_A = 0x696 // 1686 + SYS___REGCOMP_STD_A = 0x697 // 1687 + SYS___REGERROR_A = 0x698 // 1688 + SYS___REGERROR_STD_A = 0x699 // 1689 + SYS___REGEXEC_A = 0x69A // 1690 + SYS___REGEXEC_STD_A = 0x69B // 1691 + SYS___REGFREE_A = 0x69C // 1692 + SYS___REGFREE_STD_A = 0x69D // 1693 + SYS___STRCOLL_A = 0x69E // 1694 + SYS___STRCOLL_C_A = 0x69F // 1695 + SYS___EXECLE_A = 0x6A0 // 1696 + SYS___STRCOLL_STD_A = 0x6A1 // 1697 + SYS___STRXFRM_A = 0x6A2 // 1698 + SYS___STRXFRM_C_A = 0x6A3 // 1699 + SYS___EXECLP_A = 0x6A4 // 1700 + SYS___STRXFRM_STD_A = 0x6A5 // 1701 + SYS___WCSCOLL_A = 0x6A6 // 1702 + SYS___WCSCOLL_C_A = 0x6A7 // 1703 + SYS___WCSCOLL_STD_A = 0x6A8 // 1704 + SYS___WCSXFRM_A = 0x6A9 // 1705 + SYS___WCSXFRM_C_A = 0x6AA // 1706 + SYS___WCSXFRM_STD_A = 0x6AB // 1707 + SYS___COLLATE_INIT_A = 0x6AC // 1708 + SYS___WCTYPE_A = 0x6AD // 1709 + SYS___GET_WCTYPE_STD_A = 0x6AE // 1710 + SYS___CTYPE_INIT_A = 0x6AF // 1711 + SYS___ISWCTYPE_A = 0x6B0 // 1712 + SYS___EXECV_A = 0x6B1 // 1713 + SYS___IS_WCTYPE_STD_A = 0x6B2 // 1714 + SYS___TOWLOWER_A = 0x6B3 // 1715 + SYS___TOWLOWER_STD_A = 0x6B4 // 1716 + SYS___TOWUPPER_A = 0x6B5 // 1717 + SYS___TOWUPPER_STD_A = 0x6B6 // 1718 + SYS___LOCALE_INIT_A = 0x6B7 // 1719 + SYS___LOCALECONV_A = 0x6B8 // 1720 + SYS___LOCALECONV_STD_A = 0x6B9 // 1721 + SYS___NL_LANGINFO_A = 0x6BA // 1722 + SYS___NL_LNAGINFO_STD_A = 0x6BB // 1723 + SYS___MONETARY_INIT_A = 0x6BC // 1724 + SYS___STRFMON_A = 0x6BD // 1725 + SYS___STRFMON_STD_A = 0x6BE // 1726 + SYS___GETADDRINFO_A = 0x6BF // 1727 + SYS___CATGETS_A = 0x6C0 // 1728 + SYS___EXECVE_A = 0x6C1 // 1729 + SYS___EXECVP_A = 0x6C2 // 1730 + SYS___SPAWN_A = 0x6C3 // 1731 + SYS___GETNAMEINFO_A = 0x6C4 // 1732 + SYS___SPAWNP_A = 0x6C5 // 1733 + SYS___NUMERIC_INIT_A = 0x6C6 // 1734 + SYS___RESP_INIT_A = 0x6C7 // 1735 + SYS___RPMATCH_A = 0x6C8 // 1736 + SYS___RPMATCH_C_A = 0x6C9 // 1737 + SYS___RPMATCH_STD_A = 0x6CA // 1738 + SYS___TIME_INIT_A = 0x6CB // 1739 + SYS___STRFTIME_A = 0x6CC // 1740 + SYS___STRFTIME_STD_A = 0x6CD // 1741 + SYS___STRPTIME_A = 0x6CE // 1742 + SYS___STRPTIME_STD_A = 0x6CF // 1743 + SYS___WCSFTIME_A = 0x6D0 // 1744 + SYS___WCSFTIME_STD_A = 0x6D1 // 1745 + SYS_____SPAWN2_A = 0x6D2 // 1746 + SYS_____SPAWNP2_A = 0x6D3 // 1747 + SYS___SYNTAX_INIT_A = 0x6D4 // 1748 + SYS___TOD_INIT_A = 0x6D5 // 1749 + SYS___NL_CSINFO_A = 0x6D6 // 1750 + SYS___NL_MONINFO_A = 0x6D7 // 1751 + SYS___NL_NUMINFO_A = 0x6D8 // 1752 + SYS___NL_RESPINFO_A = 0x6D9 // 1753 + SYS___NL_TIMINFO_A = 0x6DA // 1754 + SYS___IF_NAMETOINDEX_A = 0x6DB // 1755 + SYS___IF_INDEXTONAME_A = 0x6DC // 1756 + SYS___PRINTF_A = 0x6DD // 1757 + SYS___ICONV_OPEN_A = 0x6DE // 1758 + SYS___DLLLOAD_A = 0x6DF // 1759 + SYS___DLLQUERYFN_A = 0x6E0 // 1760 + SYS___DLLQUERYVAR_A = 0x6E1 // 1761 + SYS_____CHATTR_A = 0x6E2 // 1762 + SYS___E2A_L = 0x6E3 // 1763 + SYS_____TOCCSID_A = 0x6E4 // 1764 + SYS_____TOCSNAME_A = 0x6E5 // 1765 + SYS_____CCSIDTYPE_A = 0x6E6 // 1766 + SYS_____CSNAMETYPE_A = 0x6E7 // 1767 + SYS___CHMOD_A = 0x6E8 // 1768 + SYS___MKDIR_A = 0x6E9 // 1769 + SYS___STAT_A = 0x6EA // 1770 + SYS___STAT_O_A = 0x6EB // 1771 + SYS___MKFIFO_A = 0x6EC // 1772 + SYS_____OPEN_STAT_A = 0x6ED // 1773 + SYS___LSTAT_A = 0x6EE // 1774 + SYS___LSTAT_O_A = 0x6EF // 1775 + SYS___MKNOD_A = 0x6F0 // 1776 + SYS___MOUNT_A = 0x6F1 // 1777 + SYS___UMOUNT_A = 0x6F2 // 1778 + SYS___CHAUDIT_A = 0x6F4 // 1780 + SYS___W_GETMNTENT_A = 0x6F5 // 1781 + SYS___CREAT_A = 0x6F6 // 1782 + SYS___OPEN_A = 0x6F7 // 1783 + SYS___SETLOCALE_A = 0x6F9 // 1785 + SYS___FPRINTF_A = 0x6FA // 1786 + SYS___SPRINTF_A = 0x6FB // 1787 + SYS___VFPRINTF_A = 0x6FC // 1788 + SYS___VPRINTF_A = 0x6FD // 1789 + SYS___VSPRINTF_A = 0x6FE // 1790 + SYS___VSWPRINTF_A = 0x6FF // 1791 + SYS___SWPRINTF_A = 0x700 // 1792 + SYS___FSCANF_A = 0x701 // 1793 + SYS___SCANF_A = 0x702 // 1794 + SYS___SSCANF_A = 0x703 // 1795 + SYS___SWSCANF_A = 0x704 // 1796 + SYS___ATOF_A = 0x705 // 1797 + SYS___ATOI_A = 0x706 // 1798 + SYS___ATOL_A = 0x707 // 1799 + SYS___STRTOD_A = 0x708 // 1800 + SYS___STRTOL_A = 0x709 // 1801 + SYS___STRTOUL_A = 0x70A // 1802 + SYS_____AE_CORRESTBL_QUERY_A = 0x70B // 1803 + SYS___A64L_A = 0x70C // 1804 + SYS___ECVT_A = 0x70D // 1805 + SYS___FCVT_A = 0x70E // 1806 + SYS___GCVT_A = 0x70F // 1807 + SYS___L64A_A = 0x710 // 1808 + SYS___STRERROR_A = 0x711 // 1809 + SYS___PERROR_A = 0x712 // 1810 + SYS___FETCH_A = 0x713 // 1811 + SYS___GETENV_A = 0x714 // 1812 + SYS___MKSTEMP_A = 0x717 // 1815 + SYS___PTSNAME_A = 0x718 // 1816 + SYS___PUTENV_A = 0x719 // 1817 + SYS___REALPATH_A = 0x71A // 1818 + SYS___SETENV_A = 0x71B // 1819 + SYS___SYSTEM_A = 0x71C // 1820 + SYS___GETOPT_A = 0x71D // 1821 + SYS___CATOPEN_A = 0x71E // 1822 + SYS___ACCESS_A = 0x71F // 1823 + SYS___CHDIR_A = 0x720 // 1824 + SYS___CHOWN_A = 0x721 // 1825 + SYS___CHROOT_A = 0x722 // 1826 + SYS___GETCWD_A = 0x723 // 1827 + SYS___GETWD_A = 0x724 // 1828 + SYS___LCHOWN_A = 0x725 // 1829 + SYS___LINK_A = 0x726 // 1830 + SYS___PATHCONF_A = 0x727 // 1831 + SYS___IF_NAMEINDEX_A = 0x728 // 1832 + SYS___READLINK_A = 0x729 // 1833 + SYS___RMDIR_A = 0x72A // 1834 + SYS___STATVFS_A = 0x72B // 1835 + SYS___SYMLINK_A = 0x72C // 1836 + SYS___TRUNCATE_A = 0x72D // 1837 + SYS___UNLINK_A = 0x72E // 1838 + SYS___GAI_STRERROR_A = 0x72F // 1839 + SYS___EXTLINK_NP_A = 0x730 // 1840 + SYS___ISALNUM_A = 0x731 // 1841 + SYS___ISALPHA_A = 0x732 // 1842 + SYS___A2E_S = 0x733 // 1843 + SYS___ISCNTRL_A = 0x734 // 1844 + SYS___ISDIGIT_A = 0x735 // 1845 + SYS___ISGRAPH_A = 0x736 // 1846 + SYS___ISLOWER_A = 0x737 // 1847 + SYS___ISPRINT_A = 0x738 // 1848 + SYS___ISPUNCT_A = 0x739 // 1849 + SYS___ISSPACE_A = 0x73A // 1850 + SYS___ISUPPER_A = 0x73B // 1851 + SYS___ISXDIGIT_A = 0x73C // 1852 + SYS___TOLOWER_A = 0x73D // 1853 + SYS___TOUPPER_A = 0x73E // 1854 + SYS___ISWALNUM_A = 0x73F // 1855 + SYS___ISWALPHA_A = 0x740 // 1856 + SYS___A2E_L = 0x741 // 1857 + SYS___ISWCNTRL_A = 0x742 // 1858 + SYS___ISWDIGIT_A = 0x743 // 1859 + SYS___ISWGRAPH_A = 0x744 // 1860 + SYS___ISWLOWER_A = 0x745 // 1861 + SYS___ISWPRINT_A = 0x746 // 1862 + SYS___ISWPUNCT_A = 0x747 // 1863 + SYS___ISWSPACE_A = 0x748 // 1864 + SYS___ISWUPPER_A = 0x749 // 1865 + SYS___ISWXDIGIT_A = 0x74A // 1866 + SYS___CONFSTR_A = 0x74B // 1867 + SYS___FTOK_A = 0x74C // 1868 + SYS___MKTEMP_A = 0x74D // 1869 + SYS___FDOPEN_A = 0x74E // 1870 + SYS___FLDATA_A = 0x74F // 1871 + SYS___REMOVE_A = 0x750 // 1872 + SYS___RENAME_A = 0x751 // 1873 + SYS___TMPNAM_A = 0x752 // 1874 + SYS___FOPEN_A = 0x753 // 1875 + SYS___FREOPEN_A = 0x754 // 1876 + SYS___CUSERID_A = 0x755 // 1877 + SYS___POPEN_A = 0x756 // 1878 + SYS___TEMPNAM_A = 0x757 // 1879 + SYS___FTW_A = 0x758 // 1880 + SYS___GETGRENT_A = 0x759 // 1881 + SYS___GETGRGID_A = 0x75A // 1882 + SYS___GETGRNAM_A = 0x75B // 1883 + SYS___GETGROUPSBYNAME_A = 0x75C // 1884 + SYS___GETHOSTENT_A = 0x75D // 1885 + SYS___GETHOSTNAME_A = 0x75E // 1886 + SYS___GETLOGIN_A = 0x75F // 1887 + SYS___INET_NTOP_A = 0x760 // 1888 + SYS___GETPASS_A = 0x761 // 1889 + SYS___GETPWENT_A = 0x762 // 1890 + SYS___GETPWNAM_A = 0x763 // 1891 + SYS___GETPWUID_A = 0x764 // 1892 + SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765 // 1893 + SYS___CHECKSCHENV_A = 0x766 // 1894 + SYS___CONNECTSERVER_A = 0x767 // 1895 + SYS___CONNECTWORKMGR_A = 0x768 // 1896 + SYS_____CONSOLE_A = 0x769 // 1897 + SYS___CREATEWORKUNIT_A = 0x76A // 1898 + SYS___CTERMID_A = 0x76B // 1899 + SYS___FMTMSG_A = 0x76C // 1900 + SYS___INITGROUPS_A = 0x76D // 1901 + SYS_____LOGIN_A = 0x76E // 1902 + SYS___MSGRCV_A = 0x76F // 1903 + SYS___MSGSND_A = 0x770 // 1904 + SYS___MSGXRCV_A = 0x771 // 1905 + SYS___NFTW_A = 0x772 // 1906 + SYS_____PASSWD_A = 0x773 // 1907 + SYS___PTHREAD_SECURITY_NP_A = 0x774 // 1908 + SYS___QUERYMETRICS_A = 0x775 // 1909 + SYS___QUERYSCHENV = 0x776 // 1910 + SYS___READV_A = 0x777 // 1911 + SYS_____SERVER_CLASSIFY_A = 0x778 // 1912 + SYS_____SERVER_INIT_A = 0x779 // 1913 + SYS_____SERVER_PWU_A = 0x77A // 1914 + SYS___STRCASECMP_A = 0x77B // 1915 + SYS___STRNCASECMP_A = 0x77C // 1916 + SYS___TTYNAME_A = 0x77D // 1917 + SYS___UNAME_A = 0x77E // 1918 + SYS___UTIMES_A = 0x77F // 1919 + SYS___W_GETPSENT_A = 0x780 // 1920 + SYS___WRITEV_A = 0x781 // 1921 + SYS___W_STATFS_A = 0x782 // 1922 + SYS___W_STATVFS_A = 0x783 // 1923 + SYS___FPUTC_A = 0x784 // 1924 + SYS___PUTCHAR_A = 0x785 // 1925 + SYS___PUTS_A = 0x786 // 1926 + SYS___FGETS_A = 0x787 // 1927 + SYS___GETS_A = 0x788 // 1928 + SYS___FPUTS_A = 0x789 // 1929 + SYS___FREAD_A = 0x78A // 1930 + SYS___FWRITE_A = 0x78B // 1931 + SYS___OPEN_O_A = 0x78C // 1932 + SYS___ISASCII = 0x78D // 1933 + SYS___CREAT_O_A = 0x78E // 1934 + SYS___ENVNA = 0x78F // 1935 + SYS___PUTC_A = 0x790 // 1936 + SYS___AE_THREAD_SETMODE = 0x791 // 1937 + SYS___AE_THREAD_SWAPMODE = 0x792 // 1938 + SYS___GETNETBYADDR_A = 0x793 // 1939 + SYS___GETNETBYNAME_A = 0x794 // 1940 + SYS___GETNETENT_A = 0x795 // 1941 + SYS___GETPROTOBYNAME_A = 0x796 // 1942 + SYS___GETPROTOBYNUMBER_A = 0x797 // 1943 + SYS___GETPROTOENT_A = 0x798 // 1944 + SYS___GETSERVBYNAME_A = 0x799 // 1945 + SYS___GETSERVBYPORT_A = 0x79A // 1946 + SYS___GETSERVENT_A = 0x79B // 1947 + SYS___ASCTIME_A = 0x79C // 1948 + SYS___CTIME_A = 0x79D // 1949 + SYS___GETDATE_A = 0x79E // 1950 + SYS___TZSET_A = 0x79F // 1951 + SYS___UTIME_A = 0x7A0 // 1952 + SYS___ASCTIME_R_A = 0x7A1 // 1953 + SYS___CTIME_R_A = 0x7A2 // 1954 + SYS___STRTOLL_A = 0x7A3 // 1955 + SYS___STRTOULL_A = 0x7A4 // 1956 + SYS___FPUTWC_A = 0x7A5 // 1957 + SYS___PUTWC_A = 0x7A6 // 1958 + SYS___PUTWCHAR_A = 0x7A7 // 1959 + SYS___FPUTWS_A = 0x7A8 // 1960 + SYS___UNGETWC_A = 0x7A9 // 1961 + SYS___FGETWC_A = 0x7AA // 1962 + SYS___GETWC_A = 0x7AB // 1963 + SYS___GETWCHAR_A = 0x7AC // 1964 + SYS___FGETWS_A = 0x7AD // 1965 + SYS___GETTIMEOFDAY_A = 0x7AE // 1966 + SYS___GMTIME_A = 0x7AF // 1967 + SYS___GMTIME_R_A = 0x7B0 // 1968 + SYS___LOCALTIME_A = 0x7B1 // 1969 + SYS___LOCALTIME_R_A = 0x7B2 // 1970 + SYS___MKTIME_A = 0x7B3 // 1971 + SYS___TZZNA = 0x7B4 // 1972 + SYS_UNATEXIT = 0x7B5 // 1973 + SYS___CEE3DMP_A = 0x7B6 // 1974 + SYS___CDUMP_A = 0x7B7 // 1975 + SYS___CSNAP_A = 0x7B8 // 1976 + SYS___CTEST_A = 0x7B9 // 1977 + SYS___CTRACE_A = 0x7BA // 1978 + SYS___VSWPRNTF2_A = 0x7BB // 1979 + SYS___INET_PTON_A = 0x7BC // 1980 + SYS___SYSLOG_A = 0x7BD // 1981 + SYS___CRYPT_A = 0x7BE // 1982 + SYS_____OPENDIR2_A = 0x7BF // 1983 + SYS_____READDIR2_A = 0x7C0 // 1984 + SYS___OPENDIR_A = 0x7C2 // 1986 + SYS___READDIR_A = 0x7C3 // 1987 + SYS_PREAD = 0x7C7 // 1991 + SYS_PWRITE = 0x7C8 // 1992 + SYS_M_CREATE_LAYOUT = 0x7C9 // 1993 + SYS_M_DESTROY_LAYOUT = 0x7CA // 1994 + SYS_M_GETVALUES_LAYOUT = 0x7CB // 1995 + SYS_M_SETVALUES_LAYOUT = 0x7CC // 1996 + SYS_M_TRANSFORM_LAYOUT = 0x7CD // 1997 + SYS_M_WTRANSFORM_LAYOUT = 0x7CE // 1998 + SYS_FWPRINTF = 0x7D1 // 2001 + SYS_WPRINTF = 0x7D2 // 2002 + SYS_VFWPRINT = 0x7D3 // 2003 + SYS_VFWPRINTF = 0x7D3 // 2003 + SYS_VWPRINTF = 0x7D4 // 2004 + SYS_FWSCANF = 0x7D5 // 2005 + SYS_WSCANF = 0x7D6 // 2006 + SYS_WCTRANS = 0x7D7 // 2007 + SYS_TOWCTRAN = 0x7D8 // 2008 + SYS_TOWCTRANS = 0x7D8 // 2008 + SYS___WCSTOD_A = 0x7D9 // 2009 + SYS___WCSTOL_A = 0x7DA // 2010 + SYS___WCSTOUL_A = 0x7DB // 2011 + SYS___BASENAME_A = 0x7DC // 2012 + SYS___DIRNAME_A = 0x7DD // 2013 + SYS___GLOB_A = 0x7DE // 2014 + SYS_FWIDE = 0x7DF // 2015 + SYS___OSNAME = 0x7E0 // 2016 + SYS_____OSNAME_A = 0x7E1 // 2017 + SYS___BTOWC_A = 0x7E4 // 2020 + SYS___WCTOB_A = 0x7E5 // 2021 + SYS___DBM_OPEN_A = 0x7E6 // 2022 + SYS___VFPRINTF2_A = 0x7E7 // 2023 + SYS___VPRINTF2_A = 0x7E8 // 2024 + SYS___VSPRINTF2_A = 0x7E9 // 2025 + SYS___CEIL_H = 0x7EA // 2026 + SYS___FLOOR_H = 0x7EB // 2027 + SYS___MODF_H = 0x7EC // 2028 + SYS___FABS_H = 0x7ED // 2029 + SYS___J0_H = 0x7EE // 2030 + SYS___J1_H = 0x7EF // 2031 + SYS___JN_H = 0x7F0 // 2032 + SYS___Y0_H = 0x7F1 // 2033 + SYS___Y1_H = 0x7F2 // 2034 + SYS___YN_H = 0x7F3 // 2035 + SYS___CEILF_H = 0x7F4 // 2036 + SYS___CEILL_H = 0x7F5 // 2037 + SYS___FLOORF_H = 0x7F6 // 2038 + SYS___FLOORL_H = 0x7F7 // 2039 + SYS___MODFF_H = 0x7F8 // 2040 + SYS___MODFL_H = 0x7F9 // 2041 + SYS___FABSF_H = 0x7FA // 2042 + SYS___FABSL_H = 0x7FB // 2043 + SYS___MALLOC24 = 0x7FC // 2044 + SYS___MALLOC31 = 0x7FD // 2045 + SYS_ACL_INIT = 0x7FE // 2046 + SYS_ACL_FREE = 0x7FF // 2047 + SYS_ACL_FIRST_ENTRY = 0x800 // 2048 + SYS_ACL_GET_ENTRY = 0x801 // 2049 + SYS_ACL_VALID = 0x802 // 2050 + SYS_ACL_CREATE_ENTRY = 0x803 // 2051 + SYS_ACL_DELETE_ENTRY = 0x804 // 2052 + SYS_ACL_UPDATE_ENTRY = 0x805 // 2053 + SYS_ACL_DELETE_FD = 0x806 // 2054 + SYS_ACL_DELETE_FILE = 0x807 // 2055 + SYS_ACL_GET_FD = 0x808 // 2056 + SYS_ACL_GET_FILE = 0x809 // 2057 + SYS_ACL_SET_FD = 0x80A // 2058 + SYS_ACL_SET_FILE = 0x80B // 2059 + SYS_ACL_FROM_TEXT = 0x80C // 2060 + SYS_ACL_TO_TEXT = 0x80D // 2061 + SYS_ACL_SORT = 0x80E // 2062 + SYS___SHUTDOWN_REGISTRATION = 0x80F // 2063 + SYS___ERFL_B = 0x810 // 2064 + SYS___ERFCL_B = 0x811 // 2065 + SYS___LGAMMAL_B = 0x812 // 2066 + SYS___SETHOOKEVENTS = 0x813 // 2067 + SYS_IF_NAMETOINDEX = 0x814 // 2068 + SYS_IF_INDEXTONAME = 0x815 // 2069 + SYS_IF_NAMEINDEX = 0x816 // 2070 + SYS_IF_FREENAMEINDEX = 0x817 // 2071 + SYS_GETADDRINFO = 0x818 // 2072 + SYS_GETNAMEINFO = 0x819 // 2073 + SYS_FREEADDRINFO = 0x81A // 2074 + SYS_GAI_STRERROR = 0x81B // 2075 + SYS_REXEC_AF = 0x81C // 2076 + SYS___POE = 0x81D // 2077 + SYS___DYNALLOC_A = 0x81F // 2079 + SYS___DYNFREE_A = 0x820 // 2080 + SYS___RES_QUERY_A = 0x821 // 2081 + SYS___RES_SEARCH_A = 0x822 // 2082 + SYS___RES_QUERYDOMAIN_A = 0x823 // 2083 + SYS___RES_MKQUERY_A = 0x824 // 2084 + SYS___RES_SEND_A = 0x825 // 2085 + SYS___DN_EXPAND_A = 0x826 // 2086 + SYS___DN_SKIPNAME_A = 0x827 // 2087 + SYS___DN_COMP_A = 0x828 // 2088 + SYS___DN_FIND_A = 0x829 // 2089 + SYS___NLIST_A = 0x82A // 2090 + SYS_____TCGETCP_A = 0x82B // 2091 + SYS_____TCSETCP_A = 0x82C // 2092 + SYS_____W_PIOCTL_A = 0x82E // 2094 + SYS___INET_ADDR_A = 0x82F // 2095 + SYS___INET_NTOA_A = 0x830 // 2096 + SYS___INET_NETWORK_A = 0x831 // 2097 + SYS___ACCEPT_A = 0x832 // 2098 + SYS___ACCEPT_AND_RECV_A = 0x833 // 2099 + SYS___BIND_A = 0x834 // 2100 + SYS___CONNECT_A = 0x835 // 2101 + SYS___GETPEERNAME_A = 0x836 // 2102 + SYS___GETSOCKNAME_A = 0x837 // 2103 + SYS___RECVFROM_A = 0x838 // 2104 + SYS___SENDTO_A = 0x839 // 2105 + SYS___SENDMSG_A = 0x83A // 2106 + SYS___RECVMSG_A = 0x83B // 2107 + SYS_____LCHATTR_A = 0x83C // 2108 + SYS___CABEND = 0x83D // 2109 + SYS___LE_CIB_GET = 0x83E // 2110 + SYS___SET_LAA_FOR_JIT = 0x83F // 2111 + SYS___LCHATTR = 0x840 // 2112 + SYS___WRITEDOWN = 0x841 // 2113 + SYS_PTHREAD_MUTEX_INIT2 = 0x842 // 2114 + SYS___ACOSHF_B = 0x843 // 2115 + SYS___ACOSHL_B = 0x844 // 2116 + SYS___ASINHF_B = 0x845 // 2117 + SYS___ASINHL_B = 0x846 // 2118 + SYS___ATANHF_B = 0x847 // 2119 + SYS___ATANHL_B = 0x848 // 2120 + SYS___CBRTF_B = 0x849 // 2121 + SYS___CBRTL_B = 0x84A // 2122 + SYS___COPYSIGNF_B = 0x84B // 2123 + SYS___COPYSIGNL_B = 0x84C // 2124 + SYS___COTANF_B = 0x84D // 2125 + SYS___COTAN_B = 0x84E // 2126 + SYS___COTANL_B = 0x84F // 2127 + SYS___EXP2F_B = 0x850 // 2128 + SYS___EXP2L_B = 0x851 // 2129 + SYS___EXPM1F_B = 0x852 // 2130 + SYS___EXPM1L_B = 0x853 // 2131 + SYS___FDIMF_B = 0x854 // 2132 + SYS___FDIM_B = 0x855 // 2133 + SYS___FDIML_B = 0x856 // 2134 + SYS___HYPOTF_B = 0x857 // 2135 + SYS___HYPOTL_B = 0x858 // 2136 + SYS___LOG1PF_B = 0x859 // 2137 + SYS___LOG1PL_B = 0x85A // 2138 + SYS___LOG2F_B = 0x85B // 2139 + SYS___LOG2_B = 0x85C // 2140 + SYS___LOG2L_B = 0x85D // 2141 + SYS___REMAINDERF_B = 0x85E // 2142 + SYS___REMAINDERL_B = 0x85F // 2143 + SYS___REMQUOF_B = 0x860 // 2144 + SYS___REMQUO_B = 0x861 // 2145 + SYS___REMQUOL_B = 0x862 // 2146 + SYS___TGAMMAF_B = 0x863 // 2147 + SYS___TGAMMA_B = 0x864 // 2148 + SYS___TGAMMAL_B = 0x865 // 2149 + SYS___TRUNCF_B = 0x866 // 2150 + SYS___TRUNC_B = 0x867 // 2151 + SYS___TRUNCL_B = 0x868 // 2152 + SYS___LGAMMAF_B = 0x869 // 2153 + SYS___LROUNDF_B = 0x86A // 2154 + SYS___LROUND_B = 0x86B // 2155 + SYS___ERFF_B = 0x86C // 2156 + SYS___ERFCF_B = 0x86D // 2157 + SYS_ACOSHF = 0x86E // 2158 + SYS_ACOSHL = 0x86F // 2159 + SYS_ASINHF = 0x870 // 2160 + SYS_ASINHL = 0x871 // 2161 + SYS_ATANHF = 0x872 // 2162 + SYS_ATANHL = 0x873 // 2163 + SYS_CBRTF = 0x874 // 2164 + SYS_CBRTL = 0x875 // 2165 + SYS_COPYSIGNF = 0x876 // 2166 + SYS_CPYSIGNF = 0x876 // 2166 + SYS_COPYSIGNL = 0x877 // 2167 + SYS_CPYSIGNL = 0x877 // 2167 + SYS_COTANF = 0x878 // 2168 + SYS___COTANF = 0x878 // 2168 + SYS_COTAN = 0x879 // 2169 + SYS___COTAN = 0x879 // 2169 + SYS_COTANL = 0x87A // 2170 + SYS___COTANL = 0x87A // 2170 + SYS_EXP2F = 0x87B // 2171 + SYS_EXP2L = 0x87C // 2172 + SYS_EXPM1F = 0x87D // 2173 + SYS_EXPM1L = 0x87E // 2174 + SYS_FDIMF = 0x87F // 2175 + SYS_FDIM = 0x881 // 2177 + SYS_FDIML = 0x882 // 2178 + SYS_HYPOTF = 0x883 // 2179 + SYS_HYPOTL = 0x884 // 2180 + SYS_LOG1PF = 0x885 // 2181 + SYS_LOG1PL = 0x886 // 2182 + SYS_LOG2F = 0x887 // 2183 + SYS_LOG2 = 0x888 // 2184 + SYS_LOG2L = 0x889 // 2185 + SYS_REMAINDERF = 0x88A // 2186 + SYS_REMAINDF = 0x88A // 2186 + SYS_REMAINDERL = 0x88B // 2187 + SYS_REMAINDL = 0x88B // 2187 + SYS_REMQUOF = 0x88C // 2188 + SYS_REMQUO = 0x88D // 2189 + SYS_REMQUOL = 0x88E // 2190 + SYS_TGAMMAF = 0x88F // 2191 + SYS_TGAMMA = 0x890 // 2192 + SYS_TGAMMAL = 0x891 // 2193 + SYS_TRUNCF = 0x892 // 2194 + SYS_TRUNC = 0x893 // 2195 + SYS_TRUNCL = 0x894 // 2196 + SYS_LGAMMAF = 0x895 // 2197 + SYS_LGAMMAL = 0x896 // 2198 + SYS_LROUNDF = 0x897 // 2199 + SYS_LROUND = 0x898 // 2200 + SYS_ERFF = 0x899 // 2201 + SYS_ERFL = 0x89A // 2202 + SYS_ERFCF = 0x89B // 2203 + SYS_ERFCL = 0x89C // 2204 + SYS___EXP2_B = 0x89D // 2205 + SYS_EXP2 = 0x89E // 2206 + SYS___FAR_JUMP = 0x89F // 2207 + SYS___TCGETATTR_A = 0x8A1 // 2209 + SYS___TCSETATTR_A = 0x8A2 // 2210 + SYS___SUPERKILL = 0x8A4 // 2212 + SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5 // 2213 + SYS___LE_MSG_ADD_INSERT = 0x8A6 // 2214 + SYS___LE_MSG_GET = 0x8A7 // 2215 + SYS___LE_MSG_GET_AND_WRITE = 0x8A8 // 2216 + SYS___LE_MSG_WRITE = 0x8A9 // 2217 + SYS___ITOA = 0x8AA // 2218 + SYS___UTOA = 0x8AB // 2219 + SYS___LTOA = 0x8AC // 2220 + SYS___ULTOA = 0x8AD // 2221 + SYS___LLTOA = 0x8AE // 2222 + SYS___ULLTOA = 0x8AF // 2223 + SYS___ITOA_A = 0x8B0 // 2224 + SYS___UTOA_A = 0x8B1 // 2225 + SYS___LTOA_A = 0x8B2 // 2226 + SYS___ULTOA_A = 0x8B3 // 2227 + SYS___LLTOA_A = 0x8B4 // 2228 + SYS___ULLTOA_A = 0x8B5 // 2229 + SYS_____GETENV_A = 0x8C3 // 2243 + SYS___REXEC_A = 0x8C4 // 2244 + SYS___REXEC_AF_A = 0x8C5 // 2245 + SYS___GETUTXENT_A = 0x8C6 // 2246 + SYS___GETUTXID_A = 0x8C7 // 2247 + SYS___GETUTXLINE_A = 0x8C8 // 2248 + SYS___PUTUTXLINE_A = 0x8C9 // 2249 + SYS_____UTMPXNAME_A = 0x8CA // 2250 + SYS___PUTC_UNLOCKED_A = 0x8CB // 2251 + SYS___PUTCHAR_UNLOCKED_A = 0x8CC // 2252 + SYS___SNPRINTF_A = 0x8CD // 2253 + SYS___VSNPRINTF_A = 0x8CE // 2254 + SYS___DLOPEN_A = 0x8D0 // 2256 + SYS___DLSYM_A = 0x8D1 // 2257 + SYS___DLERROR_A = 0x8D2 // 2258 + SYS_FLOCKFILE = 0x8D3 // 2259 + SYS_FTRYLOCKFILE = 0x8D4 // 2260 + SYS_FUNLOCKFILE = 0x8D5 // 2261 + SYS_GETC_UNLOCKED = 0x8D6 // 2262 + SYS_GETCHAR_UNLOCKED = 0x8D7 // 2263 + SYS_PUTC_UNLOCKED = 0x8D8 // 2264 + SYS_PUTCHAR_UNLOCKED = 0x8D9 // 2265 + SYS_SNPRINTF = 0x8DA // 2266 + SYS_VSNPRINTF = 0x8DB // 2267 + SYS_DLOPEN = 0x8DD // 2269 + SYS_DLSYM = 0x8DE // 2270 + SYS_DLCLOSE = 0x8DF // 2271 + SYS_DLERROR = 0x8E0 // 2272 + SYS___SET_EXCEPTION_HANDLER = 0x8E2 // 2274 + SYS___RESET_EXCEPTION_HANDLER = 0x8E3 // 2275 + SYS___VHM_EVENT = 0x8E4 // 2276 + SYS___ABS_H = 0x8E6 // 2278 + SYS___ABSF_H = 0x8E7 // 2279 + SYS___ABSL_H = 0x8E8 // 2280 + SYS___ACOS_H = 0x8E9 // 2281 + SYS___ACOSF_H = 0x8EA // 2282 + SYS___ACOSL_H = 0x8EB // 2283 + SYS___ACOSH_H = 0x8EC // 2284 + SYS___ASIN_H = 0x8ED // 2285 + SYS___ASINF_H = 0x8EE // 2286 + SYS___ASINL_H = 0x8EF // 2287 + SYS___ASINH_H = 0x8F0 // 2288 + SYS___ATAN_H = 0x8F1 // 2289 + SYS___ATANF_H = 0x8F2 // 2290 + SYS___ATANL_H = 0x8F3 // 2291 + SYS___ATANH_H = 0x8F4 // 2292 + SYS___ATANHF_H = 0x8F5 // 2293 + SYS___ATANHL_H = 0x8F6 // 2294 + SYS___ATAN2_H = 0x8F7 // 2295 + SYS___ATAN2F_H = 0x8F8 // 2296 + SYS___ATAN2L_H = 0x8F9 // 2297 + SYS___CBRT_H = 0x8FA // 2298 + SYS___COPYSIGNF_H = 0x8FB // 2299 + SYS___COPYSIGNL_H = 0x8FC // 2300 + SYS___COS_H = 0x8FD // 2301 + SYS___COSF_H = 0x8FE // 2302 + SYS___COSL_H = 0x8FF // 2303 + SYS___COSHF_H = 0x900 // 2304 + SYS___COSHL_H = 0x901 // 2305 + SYS___COTAN_H = 0x902 // 2306 + SYS___COTANF_H = 0x903 // 2307 + SYS___COTANL_H = 0x904 // 2308 + SYS___ERF_H = 0x905 // 2309 + SYS___ERFF_H = 0x906 // 2310 + SYS___ERFL_H = 0x907 // 2311 + SYS___ERFC_H = 0x908 // 2312 + SYS___ERFCF_H = 0x909 // 2313 + SYS___ERFCL_H = 0x90A // 2314 + SYS___EXP_H = 0x90B // 2315 + SYS___EXPF_H = 0x90C // 2316 + SYS___EXPL_H = 0x90D // 2317 + SYS___EXPM1_H = 0x90E // 2318 + SYS___FDIM_H = 0x90F // 2319 + SYS___FDIMF_H = 0x910 // 2320 + SYS___FDIML_H = 0x911 // 2321 + SYS___FMOD_H = 0x912 // 2322 + SYS___FMODF_H = 0x913 // 2323 + SYS___FMODL_H = 0x914 // 2324 + SYS___GAMMA_H = 0x915 // 2325 + SYS___HYPOT_H = 0x916 // 2326 + SYS___ILOGB_H = 0x917 // 2327 + SYS___LGAMMA_H = 0x918 // 2328 + SYS___LGAMMAF_H = 0x919 // 2329 + SYS___LOG_H = 0x91A // 2330 + SYS___LOGF_H = 0x91B // 2331 + SYS___LOGL_H = 0x91C // 2332 + SYS___LOGB_H = 0x91D // 2333 + SYS___LOG2_H = 0x91E // 2334 + SYS___LOG2F_H = 0x91F // 2335 + SYS___LOG2L_H = 0x920 // 2336 + SYS___LOG1P_H = 0x921 // 2337 + SYS___LOG10_H = 0x922 // 2338 + SYS___LOG10F_H = 0x923 // 2339 + SYS___LOG10L_H = 0x924 // 2340 + SYS___LROUND_H = 0x925 // 2341 + SYS___LROUNDF_H = 0x926 // 2342 + SYS___NEXTAFTER_H = 0x927 // 2343 + SYS___POW_H = 0x928 // 2344 + SYS___POWF_H = 0x929 // 2345 + SYS___POWL_H = 0x92A // 2346 + SYS___REMAINDER_H = 0x92B // 2347 + SYS___RINT_H = 0x92C // 2348 + SYS___SCALB_H = 0x92D // 2349 + SYS___SIN_H = 0x92E // 2350 + SYS___SINF_H = 0x92F // 2351 + SYS___SINL_H = 0x930 // 2352 + SYS___SINH_H = 0x931 // 2353 + SYS___SINHF_H = 0x932 // 2354 + SYS___SINHL_H = 0x933 // 2355 + SYS___SQRT_H = 0x934 // 2356 + SYS___SQRTF_H = 0x935 // 2357 + SYS___SQRTL_H = 0x936 // 2358 + SYS___TAN_H = 0x937 // 2359 + SYS___TANF_H = 0x938 // 2360 + SYS___TANL_H = 0x939 // 2361 + SYS___TANH_H = 0x93A // 2362 + SYS___TANHF_H = 0x93B // 2363 + SYS___TANHL_H = 0x93C // 2364 + SYS___TGAMMA_H = 0x93D // 2365 + SYS___TGAMMAF_H = 0x93E // 2366 + SYS___TRUNC_H = 0x93F // 2367 + SYS___TRUNCF_H = 0x940 // 2368 + SYS___TRUNCL_H = 0x941 // 2369 + SYS___COSH_H = 0x942 // 2370 + SYS___LE_DEBUG_SET_RESUME_MCH = 0x943 // 2371 + SYS_VFSCANF = 0x944 // 2372 + SYS_VSCANF = 0x946 // 2374 + SYS_VSSCANF = 0x948 // 2376 + SYS_VFWSCANF = 0x94A // 2378 + SYS_VWSCANF = 0x94C // 2380 + SYS_VSWSCANF = 0x94E // 2382 + SYS_IMAXABS = 0x950 // 2384 + SYS_IMAXDIV = 0x951 // 2385 + SYS_STRTOIMAX = 0x952 // 2386 + SYS_STRTOUMAX = 0x953 // 2387 + SYS_WCSTOIMAX = 0x954 // 2388 + SYS_WCSTOUMAX = 0x955 // 2389 + SYS_ATOLL = 0x956 // 2390 + SYS_STRTOF = 0x957 // 2391 + SYS_STRTOLD = 0x958 // 2392 + SYS_WCSTOF = 0x959 // 2393 + SYS_WCSTOLD = 0x95A // 2394 + SYS_INET6_RTH_SPACE = 0x95B // 2395 + SYS_INET6_RTH_INIT = 0x95C // 2396 + SYS_INET6_RTH_ADD = 0x95D // 2397 + SYS_INET6_RTH_REVERSE = 0x95E // 2398 + SYS_INET6_RTH_SEGMENTS = 0x95F // 2399 + SYS_INET6_RTH_GETADDR = 0x960 // 2400 + SYS_INET6_OPT_INIT = 0x961 // 2401 + SYS_INET6_OPT_APPEND = 0x962 // 2402 + SYS_INET6_OPT_FINISH = 0x963 // 2403 + SYS_INET6_OPT_SET_VAL = 0x964 // 2404 + SYS_INET6_OPT_NEXT = 0x965 // 2405 + SYS_INET6_OPT_FIND = 0x966 // 2406 + SYS_INET6_OPT_GET_VAL = 0x967 // 2407 + SYS___POW_I = 0x987 // 2439 + SYS___POW_I_B = 0x988 // 2440 + SYS___POW_I_H = 0x989 // 2441 + SYS___POW_II = 0x98A // 2442 + SYS___POW_II_B = 0x98B // 2443 + SYS___POW_II_H = 0x98C // 2444 + SYS_CABS = 0x98E // 2446 + SYS___CABS_B = 0x98F // 2447 + SYS___CABS_H = 0x990 // 2448 + SYS_CABSF = 0x991 // 2449 + SYS___CABSF_B = 0x992 // 2450 + SYS___CABSF_H = 0x993 // 2451 + SYS_CABSL = 0x994 // 2452 + SYS___CABSL_B = 0x995 // 2453 + SYS___CABSL_H = 0x996 // 2454 + SYS_CACOS = 0x997 // 2455 + SYS___CACOS_B = 0x998 // 2456 + SYS___CACOS_H = 0x999 // 2457 + SYS_CACOSF = 0x99A // 2458 + SYS___CACOSF_B = 0x99B // 2459 + SYS___CACOSF_H = 0x99C // 2460 + SYS_CACOSL = 0x99D // 2461 + SYS___CACOSL_B = 0x99E // 2462 + SYS___CACOSL_H = 0x99F // 2463 + SYS_CACOSH = 0x9A0 // 2464 + SYS___CACOSH_B = 0x9A1 // 2465 + SYS___CACOSH_H = 0x9A2 // 2466 + SYS_CACOSHF = 0x9A3 // 2467 + SYS___CACOSHF_B = 0x9A4 // 2468 + SYS___CACOSHF_H = 0x9A5 // 2469 + SYS_CACOSHL = 0x9A6 // 2470 + SYS___CACOSHL_B = 0x9A7 // 2471 + SYS___CACOSHL_H = 0x9A8 // 2472 + SYS_CARG = 0x9A9 // 2473 + SYS___CARG_B = 0x9AA // 2474 + SYS___CARG_H = 0x9AB // 2475 + SYS_CARGF = 0x9AC // 2476 + SYS___CARGF_B = 0x9AD // 2477 + SYS___CARGF_H = 0x9AE // 2478 + SYS_CARGL = 0x9AF // 2479 + SYS___CARGL_B = 0x9B0 // 2480 + SYS___CARGL_H = 0x9B1 // 2481 + SYS_CASIN = 0x9B2 // 2482 + SYS___CASIN_B = 0x9B3 // 2483 + SYS___CASIN_H = 0x9B4 // 2484 + SYS_CASINF = 0x9B5 // 2485 + SYS___CASINF_B = 0x9B6 // 2486 + SYS___CASINF_H = 0x9B7 // 2487 + SYS_CASINL = 0x9B8 // 2488 + SYS___CASINL_B = 0x9B9 // 2489 + SYS___CASINL_H = 0x9BA // 2490 + SYS_CASINH = 0x9BB // 2491 + SYS___CASINH_B = 0x9BC // 2492 + SYS___CASINH_H = 0x9BD // 2493 + SYS_CASINHF = 0x9BE // 2494 + SYS___CASINHF_B = 0x9BF // 2495 + SYS___CASINHF_H = 0x9C0 // 2496 + SYS_CASINHL = 0x9C1 // 2497 + SYS___CASINHL_B = 0x9C2 // 2498 + SYS___CASINHL_H = 0x9C3 // 2499 + SYS_CATAN = 0x9C4 // 2500 + SYS___CATAN_B = 0x9C5 // 2501 + SYS___CATAN_H = 0x9C6 // 2502 + SYS_CATANF = 0x9C7 // 2503 + SYS___CATANF_B = 0x9C8 // 2504 + SYS___CATANF_H = 0x9C9 // 2505 + SYS_CATANL = 0x9CA // 2506 + SYS___CATANL_B = 0x9CB // 2507 + SYS___CATANL_H = 0x9CC // 2508 + SYS_CATANH = 0x9CD // 2509 + SYS___CATANH_B = 0x9CE // 2510 + SYS___CATANH_H = 0x9CF // 2511 + SYS_CATANHF = 0x9D0 // 2512 + SYS___CATANHF_B = 0x9D1 // 2513 + SYS___CATANHF_H = 0x9D2 // 2514 + SYS_CATANHL = 0x9D3 // 2515 + SYS___CATANHL_B = 0x9D4 // 2516 + SYS___CATANHL_H = 0x9D5 // 2517 + SYS_CCOS = 0x9D6 // 2518 + SYS___CCOS_B = 0x9D7 // 2519 + SYS___CCOS_H = 0x9D8 // 2520 + SYS_CCOSF = 0x9D9 // 2521 + SYS___CCOSF_B = 0x9DA // 2522 + SYS___CCOSF_H = 0x9DB // 2523 + SYS_CCOSL = 0x9DC // 2524 + SYS___CCOSL_B = 0x9DD // 2525 + SYS___CCOSL_H = 0x9DE // 2526 + SYS_CCOSH = 0x9DF // 2527 + SYS___CCOSH_B = 0x9E0 // 2528 + SYS___CCOSH_H = 0x9E1 // 2529 + SYS_CCOSHF = 0x9E2 // 2530 + SYS___CCOSHF_B = 0x9E3 // 2531 + SYS___CCOSHF_H = 0x9E4 // 2532 + SYS_CCOSHL = 0x9E5 // 2533 + SYS___CCOSHL_B = 0x9E6 // 2534 + SYS___CCOSHL_H = 0x9E7 // 2535 + SYS_CEXP = 0x9E8 // 2536 + SYS___CEXP_B = 0x9E9 // 2537 + SYS___CEXP_H = 0x9EA // 2538 + SYS_CEXPF = 0x9EB // 2539 + SYS___CEXPF_B = 0x9EC // 2540 + SYS___CEXPF_H = 0x9ED // 2541 + SYS_CEXPL = 0x9EE // 2542 + SYS___CEXPL_B = 0x9EF // 2543 + SYS___CEXPL_H = 0x9F0 // 2544 + SYS_CIMAG = 0x9F1 // 2545 + SYS___CIMAG_B = 0x9F2 // 2546 + SYS___CIMAG_H = 0x9F3 // 2547 + SYS_CIMAGF = 0x9F4 // 2548 + SYS___CIMAGF_B = 0x9F5 // 2549 + SYS___CIMAGF_H = 0x9F6 // 2550 + SYS_CIMAGL = 0x9F7 // 2551 + SYS___CIMAGL_B = 0x9F8 // 2552 + SYS___CIMAGL_H = 0x9F9 // 2553 + SYS___CLOG = 0x9FA // 2554 + SYS___CLOG_B = 0x9FB // 2555 + SYS___CLOG_H = 0x9FC // 2556 + SYS_CLOGF = 0x9FD // 2557 + SYS___CLOGF_B = 0x9FE // 2558 + SYS___CLOGF_H = 0x9FF // 2559 + SYS_CLOGL = 0xA00 // 2560 + SYS___CLOGL_B = 0xA01 // 2561 + SYS___CLOGL_H = 0xA02 // 2562 + SYS_CONJ = 0xA03 // 2563 + SYS___CONJ_B = 0xA04 // 2564 + SYS___CONJ_H = 0xA05 // 2565 + SYS_CONJF = 0xA06 // 2566 + SYS___CONJF_B = 0xA07 // 2567 + SYS___CONJF_H = 0xA08 // 2568 + SYS_CONJL = 0xA09 // 2569 + SYS___CONJL_B = 0xA0A // 2570 + SYS___CONJL_H = 0xA0B // 2571 + SYS_CPOW = 0xA0C // 2572 + SYS___CPOW_B = 0xA0D // 2573 + SYS___CPOW_H = 0xA0E // 2574 + SYS_CPOWF = 0xA0F // 2575 + SYS___CPOWF_B = 0xA10 // 2576 + SYS___CPOWF_H = 0xA11 // 2577 + SYS_CPOWL = 0xA12 // 2578 + SYS___CPOWL_B = 0xA13 // 2579 + SYS___CPOWL_H = 0xA14 // 2580 + SYS_CPROJ = 0xA15 // 2581 + SYS___CPROJ_B = 0xA16 // 2582 + SYS___CPROJ_H = 0xA17 // 2583 + SYS_CPROJF = 0xA18 // 2584 + SYS___CPROJF_B = 0xA19 // 2585 + SYS___CPROJF_H = 0xA1A // 2586 + SYS_CPROJL = 0xA1B // 2587 + SYS___CPROJL_B = 0xA1C // 2588 + SYS___CPROJL_H = 0xA1D // 2589 + SYS_CREAL = 0xA1E // 2590 + SYS___CREAL_B = 0xA1F // 2591 + SYS___CREAL_H = 0xA20 // 2592 + SYS_CREALF = 0xA21 // 2593 + SYS___CREALF_B = 0xA22 // 2594 + SYS___CREALF_H = 0xA23 // 2595 + SYS_CREALL = 0xA24 // 2596 + SYS___CREALL_B = 0xA25 // 2597 + SYS___CREALL_H = 0xA26 // 2598 + SYS_CSIN = 0xA27 // 2599 + SYS___CSIN_B = 0xA28 // 2600 + SYS___CSIN_H = 0xA29 // 2601 + SYS_CSINF = 0xA2A // 2602 + SYS___CSINF_B = 0xA2B // 2603 + SYS___CSINF_H = 0xA2C // 2604 + SYS_CSINL = 0xA2D // 2605 + SYS___CSINL_B = 0xA2E // 2606 + SYS___CSINL_H = 0xA2F // 2607 + SYS_CSINH = 0xA30 // 2608 + SYS___CSINH_B = 0xA31 // 2609 + SYS___CSINH_H = 0xA32 // 2610 + SYS_CSINHF = 0xA33 // 2611 + SYS___CSINHF_B = 0xA34 // 2612 + SYS___CSINHF_H = 0xA35 // 2613 + SYS_CSINHL = 0xA36 // 2614 + SYS___CSINHL_B = 0xA37 // 2615 + SYS___CSINHL_H = 0xA38 // 2616 + SYS_CSQRT = 0xA39 // 2617 + SYS___CSQRT_B = 0xA3A // 2618 + SYS___CSQRT_H = 0xA3B // 2619 + SYS_CSQRTF = 0xA3C // 2620 + SYS___CSQRTF_B = 0xA3D // 2621 + SYS___CSQRTF_H = 0xA3E // 2622 + SYS_CSQRTL = 0xA3F // 2623 + SYS___CSQRTL_B = 0xA40 // 2624 + SYS___CSQRTL_H = 0xA41 // 2625 + SYS_CTAN = 0xA42 // 2626 + SYS___CTAN_B = 0xA43 // 2627 + SYS___CTAN_H = 0xA44 // 2628 + SYS_CTANF = 0xA45 // 2629 + SYS___CTANF_B = 0xA46 // 2630 + SYS___CTANF_H = 0xA47 // 2631 + SYS_CTANL = 0xA48 // 2632 + SYS___CTANL_B = 0xA49 // 2633 + SYS___CTANL_H = 0xA4A // 2634 + SYS_CTANH = 0xA4B // 2635 + SYS___CTANH_B = 0xA4C // 2636 + SYS___CTANH_H = 0xA4D // 2637 + SYS_CTANHF = 0xA4E // 2638 + SYS___CTANHF_B = 0xA4F // 2639 + SYS___CTANHF_H = 0xA50 // 2640 + SYS_CTANHL = 0xA51 // 2641 + SYS___CTANHL_B = 0xA52 // 2642 + SYS___CTANHL_H = 0xA53 // 2643 + SYS___ACOSHF_H = 0xA54 // 2644 + SYS___ACOSHL_H = 0xA55 // 2645 + SYS___ASINHF_H = 0xA56 // 2646 + SYS___ASINHL_H = 0xA57 // 2647 + SYS___CBRTF_H = 0xA58 // 2648 + SYS___CBRTL_H = 0xA59 // 2649 + SYS___COPYSIGN_B = 0xA5A // 2650 + SYS___EXPM1F_H = 0xA5B // 2651 + SYS___EXPM1L_H = 0xA5C // 2652 + SYS___EXP2_H = 0xA5D // 2653 + SYS___EXP2F_H = 0xA5E // 2654 + SYS___EXP2L_H = 0xA5F // 2655 + SYS___LOG1PF_H = 0xA60 // 2656 + SYS___LOG1PL_H = 0xA61 // 2657 + SYS___LGAMMAL_H = 0xA62 // 2658 + SYS_FMA = 0xA63 // 2659 + SYS___FMA_B = 0xA64 // 2660 + SYS___FMA_H = 0xA65 // 2661 + SYS_FMAF = 0xA66 // 2662 + SYS___FMAF_B = 0xA67 // 2663 + SYS___FMAF_H = 0xA68 // 2664 + SYS_FMAL = 0xA69 // 2665 + SYS___FMAL_B = 0xA6A // 2666 + SYS___FMAL_H = 0xA6B // 2667 + SYS_FMAX = 0xA6C // 2668 + SYS___FMAX_B = 0xA6D // 2669 + SYS___FMAX_H = 0xA6E // 2670 + SYS_FMAXF = 0xA6F // 2671 + SYS___FMAXF_B = 0xA70 // 2672 + SYS___FMAXF_H = 0xA71 // 2673 + SYS_FMAXL = 0xA72 // 2674 + SYS___FMAXL_B = 0xA73 // 2675 + SYS___FMAXL_H = 0xA74 // 2676 + SYS_FMIN = 0xA75 // 2677 + SYS___FMIN_B = 0xA76 // 2678 + SYS___FMIN_H = 0xA77 // 2679 + SYS_FMINF = 0xA78 // 2680 + SYS___FMINF_B = 0xA79 // 2681 + SYS___FMINF_H = 0xA7A // 2682 + SYS_FMINL = 0xA7B // 2683 + SYS___FMINL_B = 0xA7C // 2684 + SYS___FMINL_H = 0xA7D // 2685 + SYS_ILOGBF = 0xA7E // 2686 + SYS___ILOGBF_B = 0xA7F // 2687 + SYS___ILOGBF_H = 0xA80 // 2688 + SYS_ILOGBL = 0xA81 // 2689 + SYS___ILOGBL_B = 0xA82 // 2690 + SYS___ILOGBL_H = 0xA83 // 2691 + SYS_LLRINT = 0xA84 // 2692 + SYS___LLRINT_B = 0xA85 // 2693 + SYS___LLRINT_H = 0xA86 // 2694 + SYS_LLRINTF = 0xA87 // 2695 + SYS___LLRINTF_B = 0xA88 // 2696 + SYS___LLRINTF_H = 0xA89 // 2697 + SYS_LLRINTL = 0xA8A // 2698 + SYS___LLRINTL_B = 0xA8B // 2699 + SYS___LLRINTL_H = 0xA8C // 2700 + SYS_LLROUND = 0xA8D // 2701 + SYS___LLROUND_B = 0xA8E // 2702 + SYS___LLROUND_H = 0xA8F // 2703 + SYS_LLROUNDF = 0xA90 // 2704 + SYS___LLROUNDF_B = 0xA91 // 2705 + SYS___LLROUNDF_H = 0xA92 // 2706 + SYS_LLROUNDL = 0xA93 // 2707 + SYS___LLROUNDL_B = 0xA94 // 2708 + SYS___LLROUNDL_H = 0xA95 // 2709 + SYS_LOGBF = 0xA96 // 2710 + SYS___LOGBF_B = 0xA97 // 2711 + SYS___LOGBF_H = 0xA98 // 2712 + SYS_LOGBL = 0xA99 // 2713 + SYS___LOGBL_B = 0xA9A // 2714 + SYS___LOGBL_H = 0xA9B // 2715 + SYS_LRINT = 0xA9C // 2716 + SYS___LRINT_B = 0xA9D // 2717 + SYS___LRINT_H = 0xA9E // 2718 + SYS_LRINTF = 0xA9F // 2719 + SYS___LRINTF_B = 0xAA0 // 2720 + SYS___LRINTF_H = 0xAA1 // 2721 + SYS_LRINTL = 0xAA2 // 2722 + SYS___LRINTL_B = 0xAA3 // 2723 + SYS___LRINTL_H = 0xAA4 // 2724 + SYS_LROUNDL = 0xAA5 // 2725 + SYS___LROUNDL_B = 0xAA6 // 2726 + SYS___LROUNDL_H = 0xAA7 // 2727 + SYS_NAN = 0xAA8 // 2728 + SYS___NAN_B = 0xAA9 // 2729 + SYS_NANF = 0xAAA // 2730 + SYS___NANF_B = 0xAAB // 2731 + SYS_NANL = 0xAAC // 2732 + SYS___NANL_B = 0xAAD // 2733 + SYS_NEARBYINT = 0xAAE // 2734 + SYS___NEARBYINT_B = 0xAAF // 2735 + SYS___NEARBYINT_H = 0xAB0 // 2736 + SYS_NEARBYINTF = 0xAB1 // 2737 + SYS___NEARBYINTF_B = 0xAB2 // 2738 + SYS___NEARBYINTF_H = 0xAB3 // 2739 + SYS_NEARBYINTL = 0xAB4 // 2740 + SYS___NEARBYINTL_B = 0xAB5 // 2741 + SYS___NEARBYINTL_H = 0xAB6 // 2742 + SYS_NEXTAFTERF = 0xAB7 // 2743 + SYS___NEXTAFTERF_B = 0xAB8 // 2744 + SYS___NEXTAFTERF_H = 0xAB9 // 2745 + SYS_NEXTAFTERL = 0xABA // 2746 + SYS___NEXTAFTERL_B = 0xABB // 2747 + SYS___NEXTAFTERL_H = 0xABC // 2748 + SYS_NEXTTOWARD = 0xABD // 2749 + SYS___NEXTTOWARD_B = 0xABE // 2750 + SYS___NEXTTOWARD_H = 0xABF // 2751 + SYS_NEXTTOWARDF = 0xAC0 // 2752 + SYS___NEXTTOWARDF_B = 0xAC1 // 2753 + SYS___NEXTTOWARDF_H = 0xAC2 // 2754 + SYS_NEXTTOWARDL = 0xAC3 // 2755 + SYS___NEXTTOWARDL_B = 0xAC4 // 2756 + SYS___NEXTTOWARDL_H = 0xAC5 // 2757 + SYS___REMAINDERF_H = 0xAC6 // 2758 + SYS___REMAINDERL_H = 0xAC7 // 2759 + SYS___REMQUO_H = 0xAC8 // 2760 + SYS___REMQUOF_H = 0xAC9 // 2761 + SYS___REMQUOL_H = 0xACA // 2762 + SYS_RINTF = 0xACB // 2763 + SYS___RINTF_B = 0xACC // 2764 + SYS_RINTL = 0xACD // 2765 + SYS___RINTL_B = 0xACE // 2766 + SYS_ROUND = 0xACF // 2767 + SYS___ROUND_B = 0xAD0 // 2768 + SYS___ROUND_H = 0xAD1 // 2769 + SYS_ROUNDF = 0xAD2 // 2770 + SYS___ROUNDF_B = 0xAD3 // 2771 + SYS___ROUNDF_H = 0xAD4 // 2772 + SYS_ROUNDL = 0xAD5 // 2773 + SYS___ROUNDL_B = 0xAD6 // 2774 + SYS___ROUNDL_H = 0xAD7 // 2775 + SYS_SCALBLN = 0xAD8 // 2776 + SYS___SCALBLN_B = 0xAD9 // 2777 + SYS___SCALBLN_H = 0xADA // 2778 + SYS_SCALBLNF = 0xADB // 2779 + SYS___SCALBLNF_B = 0xADC // 2780 + SYS___SCALBLNF_H = 0xADD // 2781 + SYS_SCALBLNL = 0xADE // 2782 + SYS___SCALBLNL_B = 0xADF // 2783 + SYS___SCALBLNL_H = 0xAE0 // 2784 + SYS___SCALBN_B = 0xAE1 // 2785 + SYS___SCALBN_H = 0xAE2 // 2786 + SYS_SCALBNF = 0xAE3 // 2787 + SYS___SCALBNF_B = 0xAE4 // 2788 + SYS___SCALBNF_H = 0xAE5 // 2789 + SYS_SCALBNL = 0xAE6 // 2790 + SYS___SCALBNL_B = 0xAE7 // 2791 + SYS___SCALBNL_H = 0xAE8 // 2792 + SYS___TGAMMAL_H = 0xAE9 // 2793 + SYS_FECLEAREXCEPT = 0xAEA // 2794 + SYS_FEGETENV = 0xAEB // 2795 + SYS_FEGETEXCEPTFLAG = 0xAEC // 2796 + SYS_FEGETROUND = 0xAED // 2797 + SYS_FEHOLDEXCEPT = 0xAEE // 2798 + SYS_FERAISEEXCEPT = 0xAEF // 2799 + SYS_FESETENV = 0xAF0 // 2800 + SYS_FESETEXCEPTFLAG = 0xAF1 // 2801 + SYS_FESETROUND = 0xAF2 // 2802 + SYS_FETESTEXCEPT = 0xAF3 // 2803 + SYS_FEUPDATEENV = 0xAF4 // 2804 + SYS___COPYSIGN_H = 0xAF5 // 2805 + SYS___HYPOTF_H = 0xAF6 // 2806 + SYS___HYPOTL_H = 0xAF7 // 2807 + SYS___CLASS = 0xAFA // 2810 + SYS___CLASS_B = 0xAFB // 2811 + SYS___CLASS_H = 0xAFC // 2812 + SYS___ISBLANK_A = 0xB2E // 2862 + SYS___ISWBLANK_A = 0xB2F // 2863 + SYS___LROUND_FIXUP = 0xB30 // 2864 + SYS___LROUNDF_FIXUP = 0xB31 // 2865 + SYS_SCHED_YIELD = 0xB32 // 2866 + SYS_STRERROR_R = 0xB33 // 2867 + SYS_UNSETENV = 0xB34 // 2868 + SYS___LGAMMA_H_C99 = 0xB38 // 2872 + SYS___LGAMMA_B_C99 = 0xB39 // 2873 + SYS___LGAMMA_R_C99 = 0xB3A // 2874 + SYS___FTELL2 = 0xB3B // 2875 + SYS___FSEEK2 = 0xB3C // 2876 + SYS___STATIC_REINIT = 0xB3D // 2877 + SYS_PTHREAD_ATTR_GETSTACK = 0xB3E // 2878 + SYS_PTHREAD_ATTR_SETSTACK = 0xB3F // 2879 + SYS___TGAMMA_H_C99 = 0xB78 // 2936 + SYS___TGAMMAF_H_C99 = 0xB79 // 2937 + SYS___LE_TRACEBACK = 0xB7A // 2938 + SYS___MUST_STAY_CLEAN = 0xB7C // 2940 + SYS___O_ENV = 0xB7D // 2941 + SYS_ACOSD32 = 0xB7E // 2942 + SYS_ACOSD64 = 0xB7F // 2943 + SYS_ACOSD128 = 0xB80 // 2944 + SYS_ACOSHD32 = 0xB81 // 2945 + SYS_ACOSHD64 = 0xB82 // 2946 + SYS_ACOSHD128 = 0xB83 // 2947 + SYS_ASIND32 = 0xB84 // 2948 + SYS_ASIND64 = 0xB85 // 2949 + SYS_ASIND128 = 0xB86 // 2950 + SYS_ASINHD32 = 0xB87 // 2951 + SYS_ASINHD64 = 0xB88 // 2952 + SYS_ASINHD128 = 0xB89 // 2953 + SYS_ATAND32 = 0xB8A // 2954 + SYS_ATAND64 = 0xB8B // 2955 + SYS_ATAND128 = 0xB8C // 2956 + SYS_ATAN2D32 = 0xB8D // 2957 + SYS_ATAN2D64 = 0xB8E // 2958 + SYS_ATAN2D128 = 0xB8F // 2959 + SYS_ATANHD32 = 0xB90 // 2960 + SYS_ATANHD64 = 0xB91 // 2961 + SYS_ATANHD128 = 0xB92 // 2962 + SYS_CBRTD32 = 0xB93 // 2963 + SYS_CBRTD64 = 0xB94 // 2964 + SYS_CBRTD128 = 0xB95 // 2965 + SYS_CEILD32 = 0xB96 // 2966 + SYS_CEILD64 = 0xB97 // 2967 + SYS_CEILD128 = 0xB98 // 2968 + SYS___CLASS2 = 0xB99 // 2969 + SYS___CLASS2_B = 0xB9A // 2970 + SYS___CLASS2_H = 0xB9B // 2971 + SYS_COPYSIGND32 = 0xB9C // 2972 + SYS_COPYSIGND64 = 0xB9D // 2973 + SYS_COPYSIGND128 = 0xB9E // 2974 + SYS_COSD32 = 0xB9F // 2975 + SYS_COSD64 = 0xBA0 // 2976 + SYS_COSD128 = 0xBA1 // 2977 + SYS_COSHD32 = 0xBA2 // 2978 + SYS_COSHD64 = 0xBA3 // 2979 + SYS_COSHD128 = 0xBA4 // 2980 + SYS_ERFD32 = 0xBA5 // 2981 + SYS_ERFD64 = 0xBA6 // 2982 + SYS_ERFD128 = 0xBA7 // 2983 + SYS_ERFCD32 = 0xBA8 // 2984 + SYS_ERFCD64 = 0xBA9 // 2985 + SYS_ERFCD128 = 0xBAA // 2986 + SYS_EXPD32 = 0xBAB // 2987 + SYS_EXPD64 = 0xBAC // 2988 + SYS_EXPD128 = 0xBAD // 2989 + SYS_EXP2D32 = 0xBAE // 2990 + SYS_EXP2D64 = 0xBAF // 2991 + SYS_EXP2D128 = 0xBB0 // 2992 + SYS_EXPM1D32 = 0xBB1 // 2993 + SYS_EXPM1D64 = 0xBB2 // 2994 + SYS_EXPM1D128 = 0xBB3 // 2995 + SYS_FABSD32 = 0xBB4 // 2996 + SYS_FABSD64 = 0xBB5 // 2997 + SYS_FABSD128 = 0xBB6 // 2998 + SYS_FDIMD32 = 0xBB7 // 2999 + SYS_FDIMD64 = 0xBB8 // 3000 + SYS_FDIMD128 = 0xBB9 // 3001 + SYS_FE_DEC_GETROUND = 0xBBA // 3002 + SYS_FE_DEC_SETROUND = 0xBBB // 3003 + SYS_FLOORD32 = 0xBBC // 3004 + SYS_FLOORD64 = 0xBBD // 3005 + SYS_FLOORD128 = 0xBBE // 3006 + SYS_FMAD32 = 0xBBF // 3007 + SYS_FMAD64 = 0xBC0 // 3008 + SYS_FMAD128 = 0xBC1 // 3009 + SYS_FMAXD32 = 0xBC2 // 3010 + SYS_FMAXD64 = 0xBC3 // 3011 + SYS_FMAXD128 = 0xBC4 // 3012 + SYS_FMIND32 = 0xBC5 // 3013 + SYS_FMIND64 = 0xBC6 // 3014 + SYS_FMIND128 = 0xBC7 // 3015 + SYS_FMODD32 = 0xBC8 // 3016 + SYS_FMODD64 = 0xBC9 // 3017 + SYS_FMODD128 = 0xBCA // 3018 + SYS___FP_CAST_D = 0xBCB // 3019 + SYS_FREXPD32 = 0xBCC // 3020 + SYS_FREXPD64 = 0xBCD // 3021 + SYS_FREXPD128 = 0xBCE // 3022 + SYS_HYPOTD32 = 0xBCF // 3023 + SYS_HYPOTD64 = 0xBD0 // 3024 + SYS_HYPOTD128 = 0xBD1 // 3025 + SYS_ILOGBD32 = 0xBD2 // 3026 + SYS_ILOGBD64 = 0xBD3 // 3027 + SYS_ILOGBD128 = 0xBD4 // 3028 + SYS_LDEXPD32 = 0xBD5 // 3029 + SYS_LDEXPD64 = 0xBD6 // 3030 + SYS_LDEXPD128 = 0xBD7 // 3031 + SYS_LGAMMAD32 = 0xBD8 // 3032 + SYS_LGAMMAD64 = 0xBD9 // 3033 + SYS_LGAMMAD128 = 0xBDA // 3034 + SYS_LLRINTD32 = 0xBDB // 3035 + SYS_LLRINTD64 = 0xBDC // 3036 + SYS_LLRINTD128 = 0xBDD // 3037 + SYS_LLROUNDD32 = 0xBDE // 3038 + SYS_LLROUNDD64 = 0xBDF // 3039 + SYS_LLROUNDD128 = 0xBE0 // 3040 + SYS_LOGD32 = 0xBE1 // 3041 + SYS_LOGD64 = 0xBE2 // 3042 + SYS_LOGD128 = 0xBE3 // 3043 + SYS_LOG10D32 = 0xBE4 // 3044 + SYS_LOG10D64 = 0xBE5 // 3045 + SYS_LOG10D128 = 0xBE6 // 3046 + SYS_LOG1PD32 = 0xBE7 // 3047 + SYS_LOG1PD64 = 0xBE8 // 3048 + SYS_LOG1PD128 = 0xBE9 // 3049 + SYS_LOG2D32 = 0xBEA // 3050 + SYS_LOG2D64 = 0xBEB // 3051 + SYS_LOG2D128 = 0xBEC // 3052 + SYS_LOGBD32 = 0xBED // 3053 + SYS_LOGBD64 = 0xBEE // 3054 + SYS_LOGBD128 = 0xBEF // 3055 + SYS_LRINTD32 = 0xBF0 // 3056 + SYS_LRINTD64 = 0xBF1 // 3057 + SYS_LRINTD128 = 0xBF2 // 3058 + SYS_LROUNDD32 = 0xBF3 // 3059 + SYS_LROUNDD64 = 0xBF4 // 3060 + SYS_LROUNDD128 = 0xBF5 // 3061 + SYS_MODFD32 = 0xBF6 // 3062 + SYS_MODFD64 = 0xBF7 // 3063 + SYS_MODFD128 = 0xBF8 // 3064 + SYS_NAND32 = 0xBF9 // 3065 + SYS_NAND64 = 0xBFA // 3066 + SYS_NAND128 = 0xBFB // 3067 + SYS_NEARBYINTD32 = 0xBFC // 3068 + SYS_NEARBYINTD64 = 0xBFD // 3069 + SYS_NEARBYINTD128 = 0xBFE // 3070 + SYS_NEXTAFTERD32 = 0xBFF // 3071 + SYS_NEXTAFTERD64 = 0xC00 // 3072 + SYS_NEXTAFTERD128 = 0xC01 // 3073 + SYS_NEXTTOWARDD32 = 0xC02 // 3074 + SYS_NEXTTOWARDD64 = 0xC03 // 3075 + SYS_NEXTTOWARDD128 = 0xC04 // 3076 + SYS_POWD32 = 0xC05 // 3077 + SYS_POWD64 = 0xC06 // 3078 + SYS_POWD128 = 0xC07 // 3079 + SYS_QUANTIZED32 = 0xC08 // 3080 + SYS_QUANTIZED64 = 0xC09 // 3081 + SYS_QUANTIZED128 = 0xC0A // 3082 + SYS_REMAINDERD32 = 0xC0B // 3083 + SYS_REMAINDERD64 = 0xC0C // 3084 + SYS_REMAINDERD128 = 0xC0D // 3085 + SYS___REMQUOD32 = 0xC0E // 3086 + SYS___REMQUOD64 = 0xC0F // 3087 + SYS___REMQUOD128 = 0xC10 // 3088 + SYS_RINTD32 = 0xC11 // 3089 + SYS_RINTD64 = 0xC12 // 3090 + SYS_RINTD128 = 0xC13 // 3091 + SYS_ROUNDD32 = 0xC14 // 3092 + SYS_ROUNDD64 = 0xC15 // 3093 + SYS_ROUNDD128 = 0xC16 // 3094 + SYS_SAMEQUANTUMD32 = 0xC17 // 3095 + SYS_SAMEQUANTUMD64 = 0xC18 // 3096 + SYS_SAMEQUANTUMD128 = 0xC19 // 3097 + SYS_SCALBLND32 = 0xC1A // 3098 + SYS_SCALBLND64 = 0xC1B // 3099 + SYS_SCALBLND128 = 0xC1C // 3100 + SYS_SCALBND32 = 0xC1D // 3101 + SYS_SCALBND64 = 0xC1E // 3102 + SYS_SCALBND128 = 0xC1F // 3103 + SYS_SIND32 = 0xC20 // 3104 + SYS_SIND64 = 0xC21 // 3105 + SYS_SIND128 = 0xC22 // 3106 + SYS_SINHD32 = 0xC23 // 3107 + SYS_SINHD64 = 0xC24 // 3108 + SYS_SINHD128 = 0xC25 // 3109 + SYS_SQRTD32 = 0xC26 // 3110 + SYS_SQRTD64 = 0xC27 // 3111 + SYS_SQRTD128 = 0xC28 // 3112 + SYS_STRTOD32 = 0xC29 // 3113 + SYS_STRTOD64 = 0xC2A // 3114 + SYS_STRTOD128 = 0xC2B // 3115 + SYS_TAND32 = 0xC2C // 3116 + SYS_TAND64 = 0xC2D // 3117 + SYS_TAND128 = 0xC2E // 3118 + SYS_TANHD32 = 0xC2F // 3119 + SYS_TANHD64 = 0xC30 // 3120 + SYS_TANHD128 = 0xC31 // 3121 + SYS_TGAMMAD32 = 0xC32 // 3122 + SYS_TGAMMAD64 = 0xC33 // 3123 + SYS_TGAMMAD128 = 0xC34 // 3124 + SYS_TRUNCD32 = 0xC3E // 3134 + SYS_TRUNCD64 = 0xC3F // 3135 + SYS_TRUNCD128 = 0xC40 // 3136 + SYS_WCSTOD32 = 0xC41 // 3137 + SYS_WCSTOD64 = 0xC42 // 3138 + SYS_WCSTOD128 = 0xC43 // 3139 + SYS___CODEPAGE_INFO = 0xC64 // 3172 + SYS_POSIX_OPENPT = 0xC66 // 3174 + SYS_PSELECT = 0xC67 // 3175 + SYS_SOCKATMARK = 0xC68 // 3176 + SYS_AIO_FSYNC = 0xC69 // 3177 + SYS_LIO_LISTIO = 0xC6A // 3178 + SYS___ATANPID32 = 0xC6B // 3179 + SYS___ATANPID64 = 0xC6C // 3180 + SYS___ATANPID128 = 0xC6D // 3181 + SYS___COSPID32 = 0xC6E // 3182 + SYS___COSPID64 = 0xC6F // 3183 + SYS___COSPID128 = 0xC70 // 3184 + SYS___SINPID32 = 0xC71 // 3185 + SYS___SINPID64 = 0xC72 // 3186 + SYS___SINPID128 = 0xC73 // 3187 + SYS_SETIPV4SOURCEFILTER = 0xC76 // 3190 + SYS_GETIPV4SOURCEFILTER = 0xC77 // 3191 + SYS_SETSOURCEFILTER = 0xC78 // 3192 + SYS_GETSOURCEFILTER = 0xC79 // 3193 + SYS_FWRITE_UNLOCKED = 0xC7A // 3194 + SYS_FREAD_UNLOCKED = 0xC7B // 3195 + SYS_FGETS_UNLOCKED = 0xC7C // 3196 + SYS_GETS_UNLOCKED = 0xC7D // 3197 + SYS_FPUTS_UNLOCKED = 0xC7E // 3198 + SYS_PUTS_UNLOCKED = 0xC7F // 3199 + SYS_FGETC_UNLOCKED = 0xC80 // 3200 + SYS_FPUTC_UNLOCKED = 0xC81 // 3201 + SYS_DLADDR = 0xC82 // 3202 + SYS_SHM_OPEN = 0xC8C // 3212 + SYS_SHM_UNLINK = 0xC8D // 3213 + SYS___CLASS2F = 0xC91 // 3217 + SYS___CLASS2L = 0xC92 // 3218 + SYS___CLASS2F_B = 0xC93 // 3219 + SYS___CLASS2F_H = 0xC94 // 3220 + SYS___CLASS2L_B = 0xC95 // 3221 + SYS___CLASS2L_H = 0xC96 // 3222 + SYS___CLASS2D32 = 0xC97 // 3223 + SYS___CLASS2D64 = 0xC98 // 3224 + SYS___CLASS2D128 = 0xC99 // 3225 + SYS___TOCSNAME2 = 0xC9A // 3226 + SYS___D1TOP = 0xC9B // 3227 + SYS___D2TOP = 0xC9C // 3228 + SYS___D4TOP = 0xC9D // 3229 + SYS___PTOD1 = 0xC9E // 3230 + SYS___PTOD2 = 0xC9F // 3231 + SYS___PTOD4 = 0xCA0 // 3232 + SYS_CLEARERR_UNLOCKED = 0xCA1 // 3233 + SYS_FDELREC_UNLOCKED = 0xCA2 // 3234 + SYS_FEOF_UNLOCKED = 0xCA3 // 3235 + SYS_FERROR_UNLOCKED = 0xCA4 // 3236 + SYS_FFLUSH_UNLOCKED = 0xCA5 // 3237 + SYS_FGETPOS_UNLOCKED = 0xCA6 // 3238 + SYS_FGETWC_UNLOCKED = 0xCA7 // 3239 + SYS_FGETWS_UNLOCKED = 0xCA8 // 3240 + SYS_FILENO_UNLOCKED = 0xCA9 // 3241 + SYS_FLDATA_UNLOCKED = 0xCAA // 3242 + SYS_FLOCATE_UNLOCKED = 0xCAB // 3243 + SYS_FPRINTF_UNLOCKED = 0xCAC // 3244 + SYS_FPUTWC_UNLOCKED = 0xCAD // 3245 + SYS_FPUTWS_UNLOCKED = 0xCAE // 3246 + SYS_FSCANF_UNLOCKED = 0xCAF // 3247 + SYS_FSEEK_UNLOCKED = 0xCB0 // 3248 + SYS_FSEEKO_UNLOCKED = 0xCB1 // 3249 + SYS_FSETPOS_UNLOCKED = 0xCB3 // 3251 + SYS_FTELL_UNLOCKED = 0xCB4 // 3252 + SYS_FTELLO_UNLOCKED = 0xCB5 // 3253 + SYS_FUPDATE_UNLOCKED = 0xCB7 // 3255 + SYS_FWIDE_UNLOCKED = 0xCB8 // 3256 + SYS_FWPRINTF_UNLOCKED = 0xCB9 // 3257 + SYS_FWSCANF_UNLOCKED = 0xCBA // 3258 + SYS_GETWC_UNLOCKED = 0xCBB // 3259 + SYS_GETWCHAR_UNLOCKED = 0xCBC // 3260 + SYS_PERROR_UNLOCKED = 0xCBD // 3261 + SYS_PRINTF_UNLOCKED = 0xCBE // 3262 + SYS_PUTWC_UNLOCKED = 0xCBF // 3263 + SYS_PUTWCHAR_UNLOCKED = 0xCC0 // 3264 + SYS_REWIND_UNLOCKED = 0xCC1 // 3265 + SYS_SCANF_UNLOCKED = 0xCC2 // 3266 + SYS_UNGETC_UNLOCKED = 0xCC3 // 3267 + SYS_UNGETWC_UNLOCKED = 0xCC4 // 3268 + SYS_VFPRINTF_UNLOCKED = 0xCC5 // 3269 + SYS_VFSCANF_UNLOCKED = 0xCC7 // 3271 + SYS_VFWPRINTF_UNLOCKED = 0xCC9 // 3273 + SYS_VFWSCANF_UNLOCKED = 0xCCB // 3275 + SYS_VPRINTF_UNLOCKED = 0xCCD // 3277 + SYS_VSCANF_UNLOCKED = 0xCCF // 3279 + SYS_VWPRINTF_UNLOCKED = 0xCD1 // 3281 + SYS_VWSCANF_UNLOCKED = 0xCD3 // 3283 + SYS_WPRINTF_UNLOCKED = 0xCD5 // 3285 + SYS_WSCANF_UNLOCKED = 0xCD6 // 3286 + SYS_ASCTIME64 = 0xCD7 // 3287 + SYS_ASCTIME64_R = 0xCD8 // 3288 + SYS_CTIME64 = 0xCD9 // 3289 + SYS_CTIME64_R = 0xCDA // 3290 + SYS_DIFFTIME64 = 0xCDB // 3291 + SYS_GMTIME64 = 0xCDC // 3292 + SYS_GMTIME64_R = 0xCDD // 3293 + SYS_LOCALTIME64 = 0xCDE // 3294 + SYS_LOCALTIME64_R = 0xCDF // 3295 + SYS_MKTIME64 = 0xCE0 // 3296 + SYS_TIME64 = 0xCE1 // 3297 + SYS___LOGIN_APPLID = 0xCE2 // 3298 + SYS___PASSWD_APPLID = 0xCE3 // 3299 + SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4 // 3300 + SYS___GETTHENT = 0xCE5 // 3301 + SYS_FREEIFADDRS = 0xCE6 // 3302 + SYS_GETIFADDRS = 0xCE7 // 3303 + SYS_POSIX_FALLOCATE = 0xCE8 // 3304 + SYS_POSIX_MEMALIGN = 0xCE9 // 3305 + SYS_SIZEOF_ALLOC = 0xCEA // 3306 + SYS_RESIZE_ALLOC = 0xCEB // 3307 + SYS_FREAD_NOUPDATE = 0xCEC // 3308 + SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED // 3309 + SYS_FGETPOS64 = 0xCEE // 3310 + SYS_FSEEK64 = 0xCEF // 3311 + SYS_FSEEKO64 = 0xCF0 // 3312 + SYS_FSETPOS64 = 0xCF1 // 3313 + SYS_FTELL64 = 0xCF2 // 3314 + SYS_FTELLO64 = 0xCF3 // 3315 + SYS_FGETPOS64_UNLOCKED = 0xCF4 // 3316 + SYS_FSEEK64_UNLOCKED = 0xCF5 // 3317 + SYS_FSEEKO64_UNLOCKED = 0xCF6 // 3318 + SYS_FSETPOS64_UNLOCKED = 0xCF7 // 3319 + SYS_FTELL64_UNLOCKED = 0xCF8 // 3320 + SYS_FTELLO64_UNLOCKED = 0xCF9 // 3321 + SYS_FOPEN_UNLOCKED = 0xCFA // 3322 + SYS_FREOPEN_UNLOCKED = 0xCFB // 3323 + SYS_FDOPEN_UNLOCKED = 0xCFC // 3324 + SYS_TMPFILE_UNLOCKED = 0xCFD // 3325 + SYS___MOSERVICES = 0xD3D // 3389 + SYS___GETTOD = 0xD3E // 3390 + SYS_C16RTOMB = 0xD40 // 3392 + SYS_C32RTOMB = 0xD41 // 3393 + SYS_MBRTOC16 = 0xD42 // 3394 + SYS_MBRTOC32 = 0xD43 // 3395 + SYS_QUANTEXPD32 = 0xD44 // 3396 + SYS_QUANTEXPD64 = 0xD45 // 3397 + SYS_QUANTEXPD128 = 0xD46 // 3398 + SYS___LOCALE_CTL = 0xD47 // 3399 + SYS___SMF_RECORD2 = 0xD48 // 3400 + SYS_FOPEN64 = 0xD49 // 3401 + SYS_FOPEN64_UNLOCKED = 0xD4A // 3402 + SYS_FREOPEN64 = 0xD4B // 3403 + SYS_FREOPEN64_UNLOCKED = 0xD4C // 3404 + SYS_TMPFILE64 = 0xD4D // 3405 + SYS_TMPFILE64_UNLOCKED = 0xD4E // 3406 + SYS_GETDATE64 = 0xD4F // 3407 + SYS_GETTIMEOFDAY64 = 0xD50 // 3408 + SYS_BIND2ADDRSEL = 0xD59 // 3417 + SYS_INET6_IS_SRCADDR = 0xD5A // 3418 + SYS___GETGRGID1 = 0xD5B // 3419 + SYS___GETGRNAM1 = 0xD5C // 3420 + SYS___FBUFSIZE = 0xD60 // 3424 + SYS___FPENDING = 0xD61 // 3425 + SYS___FLBF = 0xD62 // 3426 + SYS___FREADABLE = 0xD63 // 3427 + SYS___FWRITABLE = 0xD64 // 3428 + SYS___FREADING = 0xD65 // 3429 + SYS___FWRITING = 0xD66 // 3430 + SYS___FSETLOCKING = 0xD67 // 3431 + SYS__FLUSHLBF = 0xD68 // 3432 + SYS___FPURGE = 0xD69 // 3433 + SYS___FREADAHEAD = 0xD6A // 3434 + SYS___FSETERR = 0xD6B // 3435 + SYS___FPENDING_UNLOCKED = 0xD6C // 3436 + SYS___FREADING_UNLOCKED = 0xD6D // 3437 + SYS___FWRITING_UNLOCKED = 0xD6E // 3438 + SYS__FLUSHLBF_UNLOCKED = 0xD6F // 3439 + SYS___FPURGE_UNLOCKED = 0xD70 // 3440 + SYS___FREADAHEAD_UNLOCKED = 0xD71 // 3441 + SYS___LE_CEEGTJS = 0xD72 // 3442 + SYS___LE_RECORD_DUMP = 0xD73 // 3443 + SYS_FSTAT64 = 0xD74 // 3444 + SYS_LSTAT64 = 0xD75 // 3445 + SYS_STAT64 = 0xD76 // 3446 + SYS___READDIR2_64 = 0xD77 // 3447 + SYS___OPEN_STAT64 = 0xD78 // 3448 + SYS_FTW64 = 0xD79 // 3449 + SYS_NFTW64 = 0xD7A // 3450 + SYS_UTIME64 = 0xD7B // 3451 + SYS_UTIMES64 = 0xD7C // 3452 + SYS___GETIPC64 = 0xD7D // 3453 + SYS_MSGCTL64 = 0xD7E // 3454 + SYS_SEMCTL64 = 0xD7F // 3455 + SYS_SHMCTL64 = 0xD80 // 3456 + SYS_MSGXRCV64 = 0xD81 // 3457 + SYS___MGXR64 = 0xD81 // 3457 + SYS_W_GETPSENT64 = 0xD82 // 3458 + SYS_PTHREAD_COND_TIMEDWAIT64 = 0xD83 // 3459 + SYS_FTIME64 = 0xD85 // 3461 + SYS_GETUTXENT64 = 0xD86 // 3462 + SYS_GETUTXID64 = 0xD87 // 3463 + SYS_GETUTXLINE64 = 0xD88 // 3464 + SYS_PUTUTXLINE64 = 0xD89 // 3465 + SYS_NEWLOCALE = 0xD8A // 3466 + SYS_FREELOCALE = 0xD8B // 3467 + SYS_USELOCALE = 0xD8C // 3468 + SYS_DUPLOCALE = 0xD8D // 3469 + SYS___CHATTR64 = 0xD9C // 3484 + SYS___LCHATTR64 = 0xD9D // 3485 + SYS___FCHATTR64 = 0xD9E // 3486 + SYS_____CHATTR64_A = 0xD9F // 3487 + SYS_____LCHATTR64_A = 0xDA0 // 3488 + SYS___LE_CEEUSGD = 0xDA1 // 3489 + SYS___LE_IFAM_CON = 0xDA2 // 3490 + SYS___LE_IFAM_DSC = 0xDA3 // 3491 + SYS___LE_IFAM_GET = 0xDA4 // 3492 + SYS___LE_IFAM_QRY = 0xDA5 // 3493 + SYS_ALIGNED_ALLOC = 0xDA6 // 3494 + SYS_ACCEPT4 = 0xDA7 // 3495 + SYS___ACCEPT4_A = 0xDA8 // 3496 + SYS_COPYFILERANGE = 0xDA9 // 3497 + SYS_GETLINE = 0xDAA // 3498 + SYS___GETLINE_A = 0xDAB // 3499 + SYS_DIRFD = 0xDAC // 3500 + SYS_CLOCK_GETTIME = 0xDAD // 3501 + SYS_DUP3 = 0xDAE // 3502 + SYS_EPOLL_CREATE = 0xDAF // 3503 + SYS_EPOLL_CREATE1 = 0xDB0 // 3504 + SYS_EPOLL_CTL = 0xDB1 // 3505 + SYS_EPOLL_WAIT = 0xDB2 // 3506 + SYS_EPOLL_PWAIT = 0xDB3 // 3507 + SYS_EVENTFD = 0xDB4 // 3508 + SYS_STATFS = 0xDB5 // 3509 + SYS___STATFS_A = 0xDB6 // 3510 + SYS_FSTATFS = 0xDB7 // 3511 + SYS_INOTIFY_INIT = 0xDB8 // 3512 + SYS_INOTIFY_INIT1 = 0xDB9 // 3513 + SYS_INOTIFY_ADD_WATCH = 0xDBA // 3514 + SYS___INOTIFY_ADD_WATCH_A = 0xDBB // 3515 + SYS_INOTIFY_RM_WATCH = 0xDBC // 3516 + SYS_PIPE2 = 0xDBD // 3517 + SYS_PIVOT_ROOT = 0xDBE // 3518 + SYS___PIVOT_ROOT_A = 0xDBF // 3519 + SYS_PRCTL = 0xDC0 // 3520 + SYS_PRLIMIT = 0xDC1 // 3521 + SYS_SETHOSTNAME = 0xDC2 // 3522 + SYS___SETHOSTNAME_A = 0xDC3 // 3523 + SYS_SETRESUID = 0xDC4 // 3524 + SYS_SETRESGID = 0xDC5 // 3525 + SYS_PTHREAD_CONDATTR_GETCLOCK = 0xDC6 // 3526 + SYS_FLOCK = 0xDC7 // 3527 + SYS_FGETXATTR = 0xDC8 // 3528 + SYS___FGETXATTR_A = 0xDC9 // 3529 + SYS_FLISTXATTR = 0xDCA // 3530 + SYS___FLISTXATTR_A = 0xDCB // 3531 + SYS_FREMOVEXATTR = 0xDCC // 3532 + SYS___FREMOVEXATTR_A = 0xDCD // 3533 + SYS_FSETXATTR = 0xDCE // 3534 + SYS___FSETXATTR_A = 0xDCF // 3535 + SYS_GETXATTR = 0xDD0 // 3536 + SYS___GETXATTR_A = 0xDD1 // 3537 + SYS_LGETXATTR = 0xDD2 // 3538 + SYS___LGETXATTR_A = 0xDD3 // 3539 + SYS_LISTXATTR = 0xDD4 // 3540 + SYS___LISTXATTR_A = 0xDD5 // 3541 + SYS_LLISTXATTR = 0xDD6 // 3542 + SYS___LLISTXATTR_A = 0xDD7 // 3543 + SYS_LREMOVEXATTR = 0xDD8 // 3544 + SYS___LREMOVEXATTR_A = 0xDD9 // 3545 + SYS_LSETXATTR = 0xDDA // 3546 + SYS___LSETXATTR_A = 0xDDB // 3547 + SYS_REMOVEXATTR = 0xDDC // 3548 + SYS___REMOVEXATTR_A = 0xDDD // 3549 + SYS_SETXATTR = 0xDDE // 3550 + SYS___SETXATTR_A = 0xDDF // 3551 + SYS_FDATASYNC = 0xDE0 // 3552 + SYS_SYNCFS = 0xDE1 // 3553 + SYS_FUTIMES = 0xDE2 // 3554 + SYS_FUTIMESAT = 0xDE3 // 3555 + SYS___FUTIMESAT_A = 0xDE4 // 3556 + SYS_LUTIMES = 0xDE5 // 3557 + SYS___LUTIMES_A = 0xDE6 // 3558 + SYS_INET_ATON = 0xDE7 // 3559 + SYS_GETRANDOM = 0xDE8 // 3560 + SYS_GETTID = 0xDE9 // 3561 + SYS_MEMFD_CREATE = 0xDEA // 3562 + SYS___MEMFD_CREATE_A = 0xDEB // 3563 + SYS_FACCESSAT = 0xDEC // 3564 + SYS___FACCESSAT_A = 0xDED // 3565 + SYS_FCHMODAT = 0xDEE // 3566 + SYS___FCHMODAT_A = 0xDEF // 3567 + SYS_FCHOWNAT = 0xDF0 // 3568 + SYS___FCHOWNAT_A = 0xDF1 // 3569 + SYS_FSTATAT = 0xDF2 // 3570 + SYS___FSTATAT_A = 0xDF3 // 3571 + SYS_LINKAT = 0xDF4 // 3572 + SYS___LINKAT_A = 0xDF5 // 3573 + SYS_MKDIRAT = 0xDF6 // 3574 + SYS___MKDIRAT_A = 0xDF7 // 3575 + SYS_MKFIFOAT = 0xDF8 // 3576 + SYS___MKFIFOAT_A = 0xDF9 // 3577 + SYS_MKNODAT = 0xDFA // 3578 + SYS___MKNODAT_A = 0xDFB // 3579 + SYS_OPENAT = 0xDFC // 3580 + SYS___OPENAT_A = 0xDFD // 3581 + SYS_READLINKAT = 0xDFE // 3582 + SYS___READLINKAT_A = 0xDFF // 3583 + SYS_RENAMEAT = 0xE00 // 3584 + SYS___RENAMEAT_A = 0xE01 // 3585 + SYS_RENAMEAT2 = 0xE02 // 3586 + SYS___RENAMEAT2_A = 0xE03 // 3587 + SYS_SYMLINKAT = 0xE04 // 3588 + SYS___SYMLINKAT_A = 0xE05 // 3589 + SYS_UNLINKAT = 0xE06 // 3590 + SYS___UNLINKAT_A = 0xE07 // 3591 + SYS_SYSINFO = 0xE08 // 3592 + SYS_WAIT4 = 0xE0A // 3594 + SYS_CLONE = 0xE0B // 3595 + SYS_UNSHARE = 0xE0C // 3596 + SYS_SETNS = 0xE0D // 3597 + SYS_CAPGET = 0xE0E // 3598 + SYS_CAPSET = 0xE0F // 3599 + SYS_STRCHRNUL = 0xE10 // 3600 + SYS_PTHREAD_CONDATTR_SETCLOCK = 0xE12 // 3602 + SYS_OPEN_BY_HANDLE_AT = 0xE13 // 3603 + SYS___OPEN_BY_HANDLE_AT_A = 0xE14 // 3604 + SYS___INET_ATON_A = 0xE15 // 3605 + SYS_MOUNT1 = 0xE16 // 3606 + SYS___MOUNT1_A = 0xE17 // 3607 + SYS_UMOUNT1 = 0xE18 // 3608 + SYS___UMOUNT1_A = 0xE19 // 3609 + SYS_UMOUNT2 = 0xE1A // 3610 + SYS___UMOUNT2_A = 0xE1B // 3611 + SYS___PRCTL_A = 0xE1C // 3612 + SYS_LOCALTIME_R2 = 0xE1D // 3613 + SYS___LOCALTIME_R2_A = 0xE1E // 3614 + SYS_OPENAT2 = 0xE1F // 3615 + SYS___OPENAT2_A = 0xE20 // 3616 + SYS___LE_CEEMICT = 0xE21 // 3617 + SYS_GETENTROPY = 0xE22 // 3618 + SYS_NANOSLEEP = 0xE23 // 3619 + SYS_UTIMENSAT = 0xE24 // 3620 + SYS___UTIMENSAT_A = 0xE25 // 3621 + SYS_ASPRINTF = 0xE26 // 3622 + SYS___ASPRINTF_A = 0xE27 // 3623 + SYS_VASPRINTF = 0xE28 // 3624 + SYS___VASPRINTF_A = 0xE29 // 3625 + SYS_DPRINTF = 0xE2A // 3626 + SYS___DPRINTF_A = 0xE2B // 3627 + SYS_GETOPT_LONG = 0xE2C // 3628 + SYS___GETOPT_LONG_A = 0xE2D // 3629 + SYS_PSIGNAL = 0xE2E // 3630 + SYS___PSIGNAL_A = 0xE2F // 3631 + SYS_PSIGNAL_UNLOCKED = 0xE30 // 3632 + SYS___PSIGNAL_UNLOCKED_A = 0xE31 // 3633 + SYS_FSTATAT_O = 0xE32 // 3634 + SYS___FSTATAT_O_A = 0xE33 // 3635 + SYS_FSTATAT64 = 0xE34 // 3636 + SYS___FSTATAT64_A = 0xE35 // 3637 + SYS___CHATTRAT = 0xE36 // 3638 + SYS_____CHATTRAT_A = 0xE37 // 3639 + SYS___CHATTRAT64 = 0xE38 // 3640 + SYS_____CHATTRAT64_A = 0xE39 // 3641 + SYS_MADVISE = 0xE3A // 3642 + SYS___AUTHENTICATE = 0xE3B // 3643 + +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go index 2c1f815..3e6d57c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go @@ -1,7 +1,7 @@ // cgo -godefs types_aix.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc,aix +//go:build ppc && aix package unix @@ -219,6 +219,7 @@ const ( SizeofSockaddrUnix = 0x401 SizeofSockaddrDatalink = 0x80 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofIPv6MTUInfo = 0x20 diff --git a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go index b4a069e..3a219bd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go @@ -1,7 +1,7 @@ // cgo -godefs types_aix.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64,aix +//go:build ppc64 && aix package unix @@ -223,6 +223,7 @@ const ( SizeofSockaddrUnix = 0x401 SizeofSockaddrDatalink = 0x80 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofIPv6MTUInfo = 0x20 diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go deleted file mode 100644 index 9f47b87..0000000 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go +++ /dev/null @@ -1,499 +0,0 @@ -// cgo -godefs types_darwin.go | go run mkpost.go -// Code generated by the command above; see README.md. DO NOT EDIT. - -// +build 386,darwin - -package unix - -const ( - SizeofPtr = 0x4 - SizeofShort = 0x2 - SizeofInt = 0x4 - SizeofLong = 0x4 - SizeofLongLong = 0x8 -) - -type ( - _C_short int16 - _C_int int32 - _C_long int32 - _C_long_long int64 -) - -type Timespec struct { - Sec int32 - Nsec int32 -} - -type Timeval struct { - Sec int32 - Usec int32 -} - -type Timeval32 struct{} - -type Rusage struct { - Utime Timeval - Stime Timeval - Maxrss int32 - Ixrss int32 - Idrss int32 - Isrss int32 - Minflt int32 - Majflt int32 - Nswap int32 - Inblock int32 - Oublock int32 - Msgsnd int32 - Msgrcv int32 - Nsignals int32 - Nvcsw int32 - Nivcsw int32 -} - -type Rlimit struct { - Cur uint64 - Max uint64 -} - -type _Gid_t uint32 - -type Stat_t struct { - Dev int32 - Mode uint16 - Nlink uint16 - Ino uint64 - Uid uint32 - Gid uint32 - Rdev int32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Btim Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Qspare [2]int64 -} - -type Statfs_t struct { - Bsize uint32 - Iosize int32 - Blocks uint64 - Bfree uint64 - Bavail uint64 - Files uint64 - Ffree uint64 - Fsid Fsid - Owner uint32 - Type uint32 - Flags uint32 - Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 - Reserved [8]uint32 -} - -type Flock_t struct { - Start int64 - Len int64 - Pid int32 - Type int16 - Whence int16 -} - -type Fstore_t struct { - Flags uint32 - Posmode int32 - Offset int64 - Length int64 - Bytesalloc int64 -} - -type Radvisory_t struct { - Offset int64 - Count int32 -} - -type Fbootstraptransfer_t struct { - Offset int64 - Length uint32 - Buffer *byte -} - -type Log2phys_t struct { - Flags uint32 - Contigbytes int64 - Devoffset int64 -} - -type Fsid struct { - Val [2]int32 -} - -type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - _ [3]byte -} - -type RawSockaddrInet4 struct { - Len uint8 - Family uint8 - Port uint16 - Addr [4]byte /* in_addr */ - Zero [8]int8 -} - -type RawSockaddrInet6 struct { - Len uint8 - Family uint8 - Port uint16 - Flowinfo uint32 - Addr [16]byte /* in6_addr */ - Scope_id uint32 -} - -type RawSockaddrUnix struct { - Len uint8 - Family uint8 - Path [104]int8 -} - -type RawSockaddrDatalink struct { - Len uint8 - Family uint8 - Index uint16 - Type uint8 - Nlen uint8 - Alen uint8 - Slen uint8 - Data [12]int8 -} - -type RawSockaddr struct { - Len uint8 - Family uint8 - Data [14]int8 -} - -type RawSockaddrAny struct { - Addr RawSockaddr - Pad [92]int8 -} - -type _Socklen uint32 - -type Linger struct { - Onoff int32 - Linger int32 -} - -type Iovec struct { - Base *byte - Len uint32 -} - -type IPMreq struct { - Multiaddr [4]byte /* in_addr */ - Interface [4]byte /* in_addr */ -} - -type IPv6Mreq struct { - Multiaddr [16]byte /* in6_addr */ - Interface uint32 -} - -type Msghdr struct { - Name *byte - Namelen uint32 - Iov *Iovec - Iovlen int32 - Control *byte - Controllen uint32 - Flags int32 -} - -type Cmsghdr struct { - Len uint32 - Level int32 - Type int32 -} - -type Inet4Pktinfo struct { - Ifindex uint32 - Spec_dst [4]byte /* in_addr */ - Addr [4]byte /* in_addr */ -} - -type Inet6Pktinfo struct { - Addr [16]byte /* in6_addr */ - Ifindex uint32 -} - -type IPv6MTUInfo struct { - Addr RawSockaddrInet6 - Mtu uint32 -} - -type ICMPv6Filter struct { - Filt [8]uint32 -} - -const ( - SizeofSockaddrInet4 = 0x10 - SizeofSockaddrInet6 = 0x1c - SizeofSockaddrAny = 0x6c - SizeofSockaddrUnix = 0x6a - SizeofSockaddrDatalink = 0x14 - SizeofLinger = 0x8 - SizeofIPMreq = 0x8 - SizeofIPv6Mreq = 0x14 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc - SizeofInet4Pktinfo = 0xc - SizeofInet6Pktinfo = 0x14 - SizeofIPv6MTUInfo = 0x20 - SizeofICMPv6Filter = 0x20 -) - -const ( - PTRACE_TRACEME = 0x0 - PTRACE_CONT = 0x7 - PTRACE_KILL = 0x8 -) - -type Kevent_t struct { - Ident uint32 - Filter int16 - Flags uint16 - Fflags uint32 - Data int32 - Udata *byte -} - -type FdSet struct { - Bits [32]int32 -} - -const ( - SizeofIfMsghdr = 0x70 - SizeofIfData = 0x60 - SizeofIfaMsghdr = 0x14 - SizeofIfmaMsghdr = 0x10 - SizeofIfmaMsghdr2 = 0x14 - SizeofRtMsghdr = 0x5c - SizeofRtMetrics = 0x38 -) - -type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Data IfData -} - -type IfData struct { - Type uint8 - Typelen uint8 - Physical uint8 - Addrlen uint8 - Hdrlen uint8 - Recvquota uint8 - Xmitquota uint8 - Unused1 uint8 - Mtu uint32 - Metric uint32 - Baudrate uint32 - Ipackets uint32 - Ierrors uint32 - Opackets uint32 - Oerrors uint32 - Collisions uint32 - Ibytes uint32 - Obytes uint32 - Imcasts uint32 - Omcasts uint32 - Iqdrops uint32 - Noproto uint32 - Recvtiming uint32 - Xmittiming uint32 - Lastchange Timeval - Unused2 uint32 - Hwassist uint32 - Reserved1 uint32 - Reserved2 uint32 -} - -type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Metric int32 -} - -type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte -} - -type IfmaMsghdr2 struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Refcount int32 -} - -type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - _ [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics -} - -type RtMetrics struct { - Locks uint32 - Mtu uint32 - Hopcount uint32 - Expire int32 - Recvpipe uint32 - Sendpipe uint32 - Ssthresh uint32 - Rtt uint32 - Rttvar uint32 - Pksent uint32 - Filler [4]uint32 -} - -const ( - SizeofBpfVersion = 0x4 - SizeofBpfStat = 0x8 - SizeofBpfProgram = 0x8 - SizeofBpfInsn = 0x8 - SizeofBpfHdr = 0x14 -) - -type BpfVersion struct { - Major uint16 - Minor uint16 -} - -type BpfStat struct { - Recv uint32 - Drop uint32 -} - -type BpfProgram struct { - Len uint32 - Insns *BpfInsn -} - -type BpfInsn struct { - Code uint16 - Jt uint8 - Jf uint8 - K uint32 -} - -type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - _ [2]byte -} - -type Termios struct { - Iflag uint32 - Oflag uint32 - Cflag uint32 - Lflag uint32 - Cc [20]uint8 - Ispeed uint32 - Ospeed uint32 -} - -type Winsize struct { - Row uint16 - Col uint16 - Xpixel uint16 - Ypixel uint16 -} - -const ( - AT_FDCWD = -0x2 - AT_REMOVEDIR = 0x80 - AT_SYMLINK_FOLLOW = 0x40 - AT_SYMLINK_NOFOLLOW = 0x20 -) - -type PollFd struct { - Fd int32 - Events int16 - Revents int16 -} - -const ( - POLLERR = 0x8 - POLLHUP = 0x10 - POLLIN = 0x1 - POLLNVAL = 0x20 - POLLOUT = 0x4 - POLLPRI = 0x2 - POLLRDBAND = 0x80 - POLLRDNORM = 0x40 - POLLWRBAND = 0x100 - POLLWRNORM = 0x4 -) - -type Utsname struct { - Sysname [256]byte - Nodename [256]byte - Release [256]byte - Version [256]byte - Machine [256]byte -} - -const SizeofClockinfo = 0x14 - -type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 -} diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 966798a..17c53bd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -1,7 +1,7 @@ // cgo -godefs types_darwin.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,darwin +//go:build amd64 && darwin package unix @@ -70,7 +70,6 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev int32 - _ [4]byte Atim Timespec Mtim Timespec Ctim Timespec @@ -97,10 +96,11 @@ type Statfs_t struct { Type uint32 Flags uint32 Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 - Reserved [8]uint32 + Fstypename [16]byte + Mntonname [1024]byte + Mntfromname [1024]byte + Flags_ext uint32 + Reserved [7]uint32 } type Flock_t struct { @@ -133,8 +133,7 @@ type Fbootstraptransfer_t struct { type Log2phys_t struct { Flags uint32 - _ [8]byte - _ [8]byte + _ [16]byte } type Fsid struct { @@ -151,6 +150,20 @@ type Dirent struct { _ [3]byte } +type Attrlist struct { + Bitmapcount uint16 + Reserved uint16 + Commonattr uint32 + Volattr uint32 + Dirattr uint32 + Fileattr uint32 + Forkattr uint32 +} + +const ( + PathMax = 0x400 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 @@ -196,8 +209,123 @@ type RawSockaddrAny struct { Pad [92]int8 } +type RawSockaddrCtl struct { + Sc_len uint8 + Sc_family uint8 + Ss_sysaddr uint16 + Sc_id uint32 + Sc_unit uint32 + Sc_reserved [5]uint32 +} + +type RawSockaddrVM struct { + Len uint8 + Family uint8 + Reserved1 uint16 + Port uint32 + Cid uint32 +} + +type XVSockPCB struct { + Xv_len uint32 + Xv_vsockpp uint64 + Xvp_local_cid uint32 + Xvp_local_port uint32 + Xvp_remote_cid uint32 + Xvp_remote_port uint32 + Xvp_rxcnt uint32 + Xvp_txcnt uint32 + Xvp_peer_rxhiwat uint32 + Xvp_peer_rxcnt uint32 + Xvp_last_pid int32 + Xvp_gencnt uint64 + Xv_socket XSocket + _ [4]byte +} + +type XSocket struct { + Xso_len uint32 + Xso_so uint32 + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + So_pcb uint32 + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSocket64 struct { + Xso_len uint32 + _ [8]byte + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + _ [8]byte + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSockbuf struct { + Cc uint32 + Hiwat uint32 + Mbcnt uint32 + Mbmax uint32 + Lowat int32 + Flags int16 + Timeo int16 +} + +type XVSockPgen struct { + Len uint32 + Count uint64 + Gen uint64 + Sogen uint64 +} + type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 +} + type Linger struct { Onoff int32 Linger int32 @@ -213,6 +341,12 @@ type IPMreq struct { Interface [4]byte /* in_addr */ } +type IPMreqn struct { + Multiaddr [4]byte /* in_addr */ + Address [4]byte /* in_addr */ + Ifindex int32 +} + type IPv6Mreq struct { Multiaddr [16]byte /* in6_addr */ Interface uint32 @@ -221,10 +355,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -256,21 +388,57 @@ type ICMPv6Filter struct { Filt [8]uint32 } +type TCPConnectionInfo struct { + State uint8 + Snd_wscale uint8 + Rcv_wscale uint8 + _ uint8 + Options uint32 + Flags uint32 + Rto uint32 + Maxseg uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Snd_wnd uint32 + Snd_sbbytes uint32 + Rcv_wnd uint32 + Rttcur uint32 + Srtt uint32 + Rttvar uint32 + Txpackets uint64 + Txbytes uint64 + Txretransmitbytes uint64 + Rxpackets uint64 + Rxbytes uint64 + Rxoutoforderbytes uint64 + Txretransmitpackets uint64 +} + const ( - SizeofSockaddrInet4 = 0x10 - SizeofSockaddrInet6 = 0x1c - SizeofSockaddrAny = 0x6c - SizeofSockaddrUnix = 0x6a - SizeofSockaddrDatalink = 0x14 - SizeofLinger = 0x8 - SizeofIPMreq = 0x8 - SizeofIPv6Mreq = 0x14 - SizeofMsghdr = 0x30 - SizeofCmsghdr = 0xc - SizeofInet4Pktinfo = 0xc - SizeofInet6Pktinfo = 0x14 - SizeofIPv6MTUInfo = 0x20 - SizeofICMPv6Filter = 0x20 + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x14 + SizeofSockaddrCtl = 0x20 + SizeofSockaddrVM = 0xc + SizeofXvsockpcb = 0xa8 + SizeofXSocket = 0x64 + SizeofXSockbuf = 0x18 + SizeofXVSockPgen = 0x20 + SizeofXucred = 0x4c + SizeofLinger = 0x8 + SizeofIovec = 0x10 + SizeofIPMreq = 0x8 + SizeofIPMreqn = 0xc + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet4Pktinfo = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 + SizeofTCPConnectionInfo = 0x70 ) const ( @@ -294,11 +462,14 @@ type FdSet struct { const ( SizeofIfMsghdr = 0x70 + SizeofIfMsghdr2 = 0xa0 SizeofIfData = 0x60 + SizeofIfData64 = 0x80 SizeofIfaMsghdr = 0x14 SizeofIfmaMsghdr = 0x10 SizeofIfmaMsghdr2 = 0x14 SizeofRtMsghdr = 0x5c + SizeofRtMsghdr2 = 0x5c SizeofRtMetrics = 0x38 ) @@ -309,10 +480,23 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } +type IfMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + Snd_len int32 + Snd_maxlen int32 + Snd_drops int32 + Timer int32 + Data IfData64 +} + type IfData struct { Type uint8 Typelen uint8 @@ -345,6 +529,34 @@ type IfData struct { Reserved2 uint32 } +type IfData64 struct { + Type uint8 + Typelen uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Recvquota uint8 + Xmitquota uint8 + Unused1 uint8 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Noproto uint64 + Recvtiming uint32 + Xmittiming uint32 + Lastchange Timeval32 +} + type IfaMsghdr struct { Msglen uint16 Version uint8 @@ -352,7 +564,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -373,7 +584,6 @@ type IfmaMsghdr2 struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Refcount int32 } @@ -382,7 +592,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -393,6 +602,21 @@ type RtMsghdr struct { Rmx RtMetrics } +type RtMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Flags int32 + Addrs int32 + Refcnt int32 + Parentflags int32 + Reserved int32 + Use int32 + Inits uint32 + Rmx RtMetrics +} + type RtMetrics struct { Locks uint32 Mtu uint32 @@ -404,7 +628,8 @@ type RtMetrics struct { Rtt uint32 Rttvar uint32 Pksent uint32 - Filler [4]uint32 + State uint32 + Filler [3]uint32 } const ( @@ -427,7 +652,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -452,7 +676,6 @@ type Termios struct { Cflag uint64 Lflag uint64 Cc [20]uint8 - _ [4]byte Ispeed uint64 Ospeed uint64 } @@ -469,6 +692,7 @@ const ( AT_REMOVEDIR = 0x80 AT_SYMLINK_FOLLOW = 0x40 AT_SYMLINK_NOFOLLOW = 0x20 + AT_EACCESS = 0x10 ) type PollFd struct { @@ -507,3 +731,148 @@ type Clockinfo struct { Stathz int32 Profhz int32 } + +type CtlInfo struct { + Id uint32 + Name [96]byte +} + +const SizeofKinfoProc = 0x288 + +type Eproc struct { + Paddr uintptr + Sess uintptr + Pcred Pcred + Ucred Ucred + Vm Vmspace + Ppid int32 + Pgid int32 + Jobc int16 + Tdev int32 + Tpgid int32 + Tsess uintptr + Wmesg [8]byte + Xsize int32 + Xrssize int16 + Xccount int16 + Xswrss int16 + Flag int32 + Login [12]byte + Spare [4]int32 + _ [4]byte +} + +type ExternProc struct { + P_starttime Timeval + P_vmspace *Vmspace + P_sigacts uintptr + P_flag int32 + P_stat int8 + P_pid int32 + P_oppid int32 + P_dupfd int32 + User_stack *int8 + Exit_thread *byte + P_debugger int32 + Sigwait int32 + P_estcpu uint32 + P_cpticks int32 + P_pctcpu uint32 + P_wchan *byte + P_wmesg *int8 + P_swtime uint32 + P_slptime uint32 + P_realtimer Itimerval + P_rtime Timeval + P_uticks uint64 + P_sticks uint64 + P_iticks uint64 + P_traceflag int32 + P_tracep uintptr + P_siglist int32 + P_textvp uintptr + P_holdcnt int32 + P_sigmask uint32 + P_sigignore uint32 + P_sigcatch uint32 + P_priority uint8 + P_usrpri uint8 + P_nice int8 + P_comm [17]byte + P_pgrp uintptr + P_addr uintptr + P_xstat uint16 + P_acflag uint16 + P_ru *Rusage +} + +type Itimerval struct { + Interval Timeval + Value Timeval +} + +type KinfoProc struct { + Proc ExternProc + Eproc Eproc +} + +type Vmspace struct { + Dummy int32 + Dummy2 *int8 + Dummy3 [5]int32 + Dummy4 [3]*int8 +} + +type Pcred struct { + Pc_lock [72]int8 + Pc_ucred uintptr + P_ruid uint32 + P_svuid uint32 + P_rgid uint32 + P_svgid uint32 + P_refcnt int32 + _ [4]byte +} + +type Ucred struct { + Ref int32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 +} + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ uint16 + _ int32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Lpid int32 + Cpid int32 + Nattch uint16 + _ [34]byte +} + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go deleted file mode 100644 index 4fe4c9c..0000000 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go +++ /dev/null @@ -1,500 +0,0 @@ -// NOTE: cgo can't generate struct Stat_t and struct Statfs_t yet -// Created by cgo -godefs - DO NOT EDIT -// cgo -godefs types_darwin.go - -// +build arm,darwin - -package unix - -const ( - SizeofPtr = 0x4 - SizeofShort = 0x2 - SizeofInt = 0x4 - SizeofLong = 0x4 - SizeofLongLong = 0x8 -) - -type ( - _C_short int16 - _C_int int32 - _C_long int32 - _C_long_long int64 -) - -type Timespec struct { - Sec int32 - Nsec int32 -} - -type Timeval struct { - Sec int32 - Usec int32 -} - -type Timeval32 [0]byte - -type Rusage struct { - Utime Timeval - Stime Timeval - Maxrss int32 - Ixrss int32 - Idrss int32 - Isrss int32 - Minflt int32 - Majflt int32 - Nswap int32 - Inblock int32 - Oublock int32 - Msgsnd int32 - Msgrcv int32 - Nsignals int32 - Nvcsw int32 - Nivcsw int32 -} - -type Rlimit struct { - Cur uint64 - Max uint64 -} - -type _Gid_t uint32 - -type Stat_t struct { - Dev int32 - Mode uint16 - Nlink uint16 - Ino uint64 - Uid uint32 - Gid uint32 - Rdev int32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Btim Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Qspare [2]int64 -} - -type Statfs_t struct { - Bsize uint32 - Iosize int32 - Blocks uint64 - Bfree uint64 - Bavail uint64 - Files uint64 - Ffree uint64 - Fsid Fsid - Owner uint32 - Type uint32 - Flags uint32 - Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 - Reserved [8]uint32 -} - -type Flock_t struct { - Start int64 - Len int64 - Pid int32 - Type int16 - Whence int16 -} - -type Fstore_t struct { - Flags uint32 - Posmode int32 - Offset int64 - Length int64 - Bytesalloc int64 -} - -type Radvisory_t struct { - Offset int64 - Count int32 -} - -type Fbootstraptransfer_t struct { - Offset int64 - Length uint32 - Buffer *byte -} - -type Log2phys_t struct { - Flags uint32 - Contigbytes int64 - Devoffset int64 -} - -type Fsid struct { - Val [2]int32 -} - -type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - _ [3]byte -} - -type RawSockaddrInet4 struct { - Len uint8 - Family uint8 - Port uint16 - Addr [4]byte /* in_addr */ - Zero [8]int8 -} - -type RawSockaddrInet6 struct { - Len uint8 - Family uint8 - Port uint16 - Flowinfo uint32 - Addr [16]byte /* in6_addr */ - Scope_id uint32 -} - -type RawSockaddrUnix struct { - Len uint8 - Family uint8 - Path [104]int8 -} - -type RawSockaddrDatalink struct { - Len uint8 - Family uint8 - Index uint16 - Type uint8 - Nlen uint8 - Alen uint8 - Slen uint8 - Data [12]int8 -} - -type RawSockaddr struct { - Len uint8 - Family uint8 - Data [14]int8 -} - -type RawSockaddrAny struct { - Addr RawSockaddr - Pad [92]int8 -} - -type _Socklen uint32 - -type Linger struct { - Onoff int32 - Linger int32 -} - -type Iovec struct { - Base *byte - Len uint32 -} - -type IPMreq struct { - Multiaddr [4]byte /* in_addr */ - Interface [4]byte /* in_addr */ -} - -type IPv6Mreq struct { - Multiaddr [16]byte /* in6_addr */ - Interface uint32 -} - -type Msghdr struct { - Name *byte - Namelen uint32 - Iov *Iovec - Iovlen int32 - Control *byte - Controllen uint32 - Flags int32 -} - -type Cmsghdr struct { - Len uint32 - Level int32 - Type int32 -} - -type Inet4Pktinfo struct { - Ifindex uint32 - Spec_dst [4]byte /* in_addr */ - Addr [4]byte /* in_addr */ -} - -type Inet6Pktinfo struct { - Addr [16]byte /* in6_addr */ - Ifindex uint32 -} - -type IPv6MTUInfo struct { - Addr RawSockaddrInet6 - Mtu uint32 -} - -type ICMPv6Filter struct { - Filt [8]uint32 -} - -const ( - SizeofSockaddrInet4 = 0x10 - SizeofSockaddrInet6 = 0x1c - SizeofSockaddrAny = 0x6c - SizeofSockaddrUnix = 0x6a - SizeofSockaddrDatalink = 0x14 - SizeofLinger = 0x8 - SizeofIPMreq = 0x8 - SizeofIPv6Mreq = 0x14 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc - SizeofInet4Pktinfo = 0xc - SizeofInet6Pktinfo = 0x14 - SizeofIPv6MTUInfo = 0x20 - SizeofICMPv6Filter = 0x20 -) - -const ( - PTRACE_TRACEME = 0x0 - PTRACE_CONT = 0x7 - PTRACE_KILL = 0x8 -) - -type Kevent_t struct { - Ident uint32 - Filter int16 - Flags uint16 - Fflags uint32 - Data int32 - Udata *byte -} - -type FdSet struct { - Bits [32]int32 -} - -const ( - SizeofIfMsghdr = 0x70 - SizeofIfData = 0x60 - SizeofIfaMsghdr = 0x14 - SizeofIfmaMsghdr = 0x10 - SizeofIfmaMsghdr2 = 0x14 - SizeofRtMsghdr = 0x5c - SizeofRtMetrics = 0x38 -) - -type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Data IfData -} - -type IfData struct { - Type uint8 - Typelen uint8 - Physical uint8 - Addrlen uint8 - Hdrlen uint8 - Recvquota uint8 - Xmitquota uint8 - Unused1 uint8 - Mtu uint32 - Metric uint32 - Baudrate uint32 - Ipackets uint32 - Ierrors uint32 - Opackets uint32 - Oerrors uint32 - Collisions uint32 - Ibytes uint32 - Obytes uint32 - Imcasts uint32 - Omcasts uint32 - Iqdrops uint32 - Noproto uint32 - Recvtiming uint32 - Xmittiming uint32 - Lastchange Timeval - Unused2 uint32 - Hwassist uint32 - Reserved1 uint32 - Reserved2 uint32 -} - -type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Metric int32 -} - -type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte -} - -type IfmaMsghdr2 struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Refcount int32 -} - -type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - _ [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics -} - -type RtMetrics struct { - Locks uint32 - Mtu uint32 - Hopcount uint32 - Expire int32 - Recvpipe uint32 - Sendpipe uint32 - Ssthresh uint32 - Rtt uint32 - Rttvar uint32 - Pksent uint32 - Filler [4]uint32 -} - -const ( - SizeofBpfVersion = 0x4 - SizeofBpfStat = 0x8 - SizeofBpfProgram = 0x8 - SizeofBpfInsn = 0x8 - SizeofBpfHdr = 0x14 -) - -type BpfVersion struct { - Major uint16 - Minor uint16 -} - -type BpfStat struct { - Recv uint32 - Drop uint32 -} - -type BpfProgram struct { - Len uint32 - Insns *BpfInsn -} - -type BpfInsn struct { - Code uint16 - Jt uint8 - Jf uint8 - K uint32 -} - -type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - _ [2]byte -} - -type Termios struct { - Iflag uint32 - Oflag uint32 - Cflag uint32 - Lflag uint32 - Cc [20]uint8 - Ispeed uint32 - Ospeed uint32 -} - -type Winsize struct { - Row uint16 - Col uint16 - Xpixel uint16 - Ypixel uint16 -} - -const ( - AT_FDCWD = -0x2 - AT_REMOVEDIR = 0x80 - AT_SYMLINK_FOLLOW = 0x40 - AT_SYMLINK_NOFOLLOW = 0x20 -) - -type PollFd struct { - Fd int32 - Events int16 - Revents int16 -} - -const ( - POLLERR = 0x8 - POLLHUP = 0x10 - POLLIN = 0x1 - POLLNVAL = 0x20 - POLLOUT = 0x4 - POLLPRI = 0x2 - POLLRDBAND = 0x80 - POLLRDNORM = 0x40 - POLLWRBAND = 0x100 - POLLWRNORM = 0x4 -) - -type Utsname struct { - Sysname [256]byte - Nodename [256]byte - Release [256]byte - Version [256]byte - Machine [256]byte -} - -const SizeofClockinfo = 0x14 - -type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 -} diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 21999e4..2392226 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -1,7 +1,7 @@ // cgo -godefs types_darwin.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,darwin +//go:build arm64 && darwin package unix @@ -70,7 +70,6 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev int32 - _ [4]byte Atim Timespec Mtim Timespec Ctim Timespec @@ -97,10 +96,11 @@ type Statfs_t struct { Type uint32 Flags uint32 Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 - Reserved [8]uint32 + Fstypename [16]byte + Mntonname [1024]byte + Mntfromname [1024]byte + Flags_ext uint32 + Reserved [7]uint32 } type Flock_t struct { @@ -133,8 +133,7 @@ type Fbootstraptransfer_t struct { type Log2phys_t struct { Flags uint32 - _ [8]byte - _ [8]byte + _ [16]byte } type Fsid struct { @@ -151,6 +150,20 @@ type Dirent struct { _ [3]byte } +type Attrlist struct { + Bitmapcount uint16 + Reserved uint16 + Commonattr uint32 + Volattr uint32 + Dirattr uint32 + Fileattr uint32 + Forkattr uint32 +} + +const ( + PathMax = 0x400 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 @@ -196,8 +209,123 @@ type RawSockaddrAny struct { Pad [92]int8 } +type RawSockaddrCtl struct { + Sc_len uint8 + Sc_family uint8 + Ss_sysaddr uint16 + Sc_id uint32 + Sc_unit uint32 + Sc_reserved [5]uint32 +} + +type RawSockaddrVM struct { + Len uint8 + Family uint8 + Reserved1 uint16 + Port uint32 + Cid uint32 +} + +type XVSockPCB struct { + Xv_len uint32 + Xv_vsockpp uint64 + Xvp_local_cid uint32 + Xvp_local_port uint32 + Xvp_remote_cid uint32 + Xvp_remote_port uint32 + Xvp_rxcnt uint32 + Xvp_txcnt uint32 + Xvp_peer_rxhiwat uint32 + Xvp_peer_rxcnt uint32 + Xvp_last_pid int32 + Xvp_gencnt uint64 + Xv_socket XSocket + _ [4]byte +} + +type XSocket struct { + Xso_len uint32 + Xso_so uint32 + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + So_pcb uint32 + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSocket64 struct { + Xso_len uint32 + _ [8]byte + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + _ [8]byte + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSockbuf struct { + Cc uint32 + Hiwat uint32 + Mbcnt uint32 + Mbmax uint32 + Lowat int32 + Flags int16 + Timeo int16 +} + +type XVSockPgen struct { + Len uint32 + Count uint64 + Gen uint64 + Sogen uint64 +} + type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 +} + type Linger struct { Onoff int32 Linger int32 @@ -213,6 +341,12 @@ type IPMreq struct { Interface [4]byte /* in_addr */ } +type IPMreqn struct { + Multiaddr [4]byte /* in_addr */ + Address [4]byte /* in_addr */ + Ifindex int32 +} + type IPv6Mreq struct { Multiaddr [16]byte /* in6_addr */ Interface uint32 @@ -221,10 +355,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -256,21 +388,57 @@ type ICMPv6Filter struct { Filt [8]uint32 } +type TCPConnectionInfo struct { + State uint8 + Snd_wscale uint8 + Rcv_wscale uint8 + _ uint8 + Options uint32 + Flags uint32 + Rto uint32 + Maxseg uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Snd_wnd uint32 + Snd_sbbytes uint32 + Rcv_wnd uint32 + Rttcur uint32 + Srtt uint32 + Rttvar uint32 + Txpackets uint64 + Txbytes uint64 + Txretransmitbytes uint64 + Rxpackets uint64 + Rxbytes uint64 + Rxoutoforderbytes uint64 + Txretransmitpackets uint64 +} + const ( - SizeofSockaddrInet4 = 0x10 - SizeofSockaddrInet6 = 0x1c - SizeofSockaddrAny = 0x6c - SizeofSockaddrUnix = 0x6a - SizeofSockaddrDatalink = 0x14 - SizeofLinger = 0x8 - SizeofIPMreq = 0x8 - SizeofIPv6Mreq = 0x14 - SizeofMsghdr = 0x30 - SizeofCmsghdr = 0xc - SizeofInet4Pktinfo = 0xc - SizeofInet6Pktinfo = 0x14 - SizeofIPv6MTUInfo = 0x20 - SizeofICMPv6Filter = 0x20 + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x14 + SizeofSockaddrCtl = 0x20 + SizeofSockaddrVM = 0xc + SizeofXvsockpcb = 0xa8 + SizeofXSocket = 0x64 + SizeofXSockbuf = 0x18 + SizeofXVSockPgen = 0x20 + SizeofXucred = 0x4c + SizeofLinger = 0x8 + SizeofIovec = 0x10 + SizeofIPMreq = 0x8 + SizeofIPMreqn = 0xc + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet4Pktinfo = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 + SizeofTCPConnectionInfo = 0x70 ) const ( @@ -294,11 +462,14 @@ type FdSet struct { const ( SizeofIfMsghdr = 0x70 + SizeofIfMsghdr2 = 0xa0 SizeofIfData = 0x60 + SizeofIfData64 = 0x80 SizeofIfaMsghdr = 0x14 SizeofIfmaMsghdr = 0x10 SizeofIfmaMsghdr2 = 0x14 SizeofRtMsghdr = 0x5c + SizeofRtMsghdr2 = 0x5c SizeofRtMetrics = 0x38 ) @@ -309,10 +480,23 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } +type IfMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + Snd_len int32 + Snd_maxlen int32 + Snd_drops int32 + Timer int32 + Data IfData64 +} + type IfData struct { Type uint8 Typelen uint8 @@ -345,6 +529,34 @@ type IfData struct { Reserved2 uint32 } +type IfData64 struct { + Type uint8 + Typelen uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Recvquota uint8 + Xmitquota uint8 + Unused1 uint8 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Noproto uint64 + Recvtiming uint32 + Xmittiming uint32 + Lastchange Timeval32 +} + type IfaMsghdr struct { Msglen uint16 Version uint8 @@ -352,7 +564,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -373,7 +584,6 @@ type IfmaMsghdr2 struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Refcount int32 } @@ -382,7 +592,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -393,6 +602,21 @@ type RtMsghdr struct { Rmx RtMetrics } +type RtMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Flags int32 + Addrs int32 + Refcnt int32 + Parentflags int32 + Reserved int32 + Use int32 + Inits uint32 + Rmx RtMetrics +} + type RtMetrics struct { Locks uint32 Mtu uint32 @@ -404,7 +628,8 @@ type RtMetrics struct { Rtt uint32 Rttvar uint32 Pksent uint32 - Filler [4]uint32 + State uint32 + Filler [3]uint32 } const ( @@ -427,7 +652,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -452,7 +676,6 @@ type Termios struct { Cflag uint64 Lflag uint64 Cc [20]uint8 - _ [4]byte Ispeed uint64 Ospeed uint64 } @@ -469,6 +692,7 @@ const ( AT_REMOVEDIR = 0x80 AT_SYMLINK_FOLLOW = 0x40 AT_SYMLINK_NOFOLLOW = 0x20 + AT_EACCESS = 0x10 ) type PollFd struct { @@ -507,3 +731,148 @@ type Clockinfo struct { Stathz int32 Profhz int32 } + +type CtlInfo struct { + Id uint32 + Name [96]byte +} + +const SizeofKinfoProc = 0x288 + +type Eproc struct { + Paddr uintptr + Sess uintptr + Pcred Pcred + Ucred Ucred + Vm Vmspace + Ppid int32 + Pgid int32 + Jobc int16 + Tdev int32 + Tpgid int32 + Tsess uintptr + Wmesg [8]byte + Xsize int32 + Xrssize int16 + Xccount int16 + Xswrss int16 + Flag int32 + Login [12]byte + Spare [4]int32 + _ [4]byte +} + +type ExternProc struct { + P_starttime Timeval + P_vmspace *Vmspace + P_sigacts uintptr + P_flag int32 + P_stat int8 + P_pid int32 + P_oppid int32 + P_dupfd int32 + User_stack *int8 + Exit_thread *byte + P_debugger int32 + Sigwait int32 + P_estcpu uint32 + P_cpticks int32 + P_pctcpu uint32 + P_wchan *byte + P_wmesg *int8 + P_swtime uint32 + P_slptime uint32 + P_realtimer Itimerval + P_rtime Timeval + P_uticks uint64 + P_sticks uint64 + P_iticks uint64 + P_traceflag int32 + P_tracep uintptr + P_siglist int32 + P_textvp uintptr + P_holdcnt int32 + P_sigmask uint32 + P_sigignore uint32 + P_sigcatch uint32 + P_priority uint8 + P_usrpri uint8 + P_nice int8 + P_comm [17]byte + P_pgrp uintptr + P_addr uintptr + P_xstat uint16 + P_acflag uint16 + P_ru *Rusage +} + +type Itimerval struct { + Interval Timeval + Value Timeval +} + +type KinfoProc struct { + Proc ExternProc + Eproc Eproc +} + +type Vmspace struct { + Dummy int32 + Dummy2 *int8 + Dummy3 [5]int32 + Dummy4 [3]*int8 +} + +type Pcred struct { + Pc_lock [72]int8 + Pc_ucred uintptr + P_ruid uint32 + P_svuid uint32 + P_rgid uint32 + P_svgid uint32 + P_refcnt int32 + _ [4]byte +} + +type Ucred struct { + Ref int32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 +} + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ uint16 + _ int32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Lpid int32 + Cpid int32 + Nattch uint16 + _ [34]byte +} + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index 71ea1d6..30e405b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go @@ -1,7 +1,7 @@ // cgo -godefs types_dragonfly.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,dragonfly +//go:build amd64 && dragonfly package unix @@ -70,11 +70,11 @@ type Stat_t struct { Ctim Timespec Size int64 Blocks int64 - Blksize uint32 + _ uint32 Flags uint32 Gen uint32 Lspare int32 - Qspare1 int64 + Blksize int64 Qspare2 int64 } @@ -91,17 +91,15 @@ type Statfs_t struct { Owner uint32 Type int32 Flags int32 - _ [4]byte Syncwrites int64 Asyncwrites int64 - Fstypename [16]int8 - Mntonname [80]int8 + Fstypename [16]byte + Mntonname [80]byte Syncreads int64 Asyncreads int64 Spares1 int16 - Mntfromname [80]int8 + Mntfromname [80]byte Spares2 int16 - _ [4]byte Spare [2]int64 } @@ -202,10 +200,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -238,6 +234,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 @@ -269,7 +266,7 @@ type FdSet struct { const ( SizeofIfMsghdr = 0xb0 SizeofIfData = 0xa0 - SizeofIfaMsghdr = 0x14 + SizeofIfaMsghdr = 0x18 SizeofIfmaMsghdr = 0x10 SizeofIfAnnounceMsghdr = 0x18 SizeofRtMsghdr = 0x98 @@ -280,10 +277,9 @@ type IfMsghdr struct { Msglen uint16 Version uint8 Type uint8 - Addrs int32 - Flags int32 Index uint16 - _ [2]byte + Flags int32 + Addrs int32 Data IfData } @@ -294,7 +290,6 @@ type IfData struct { Hdrlen uint8 Recvquota uint8 Xmitquota uint8 - _ [2]byte Mtu uint64 Metric uint64 Link_state uint64 @@ -316,24 +311,23 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Flags int32 + Addrs int32 + Addrflags int32 + Metric int32 } type IfmaMsghdr struct { Msglen uint16 Version uint8 Type uint8 - Addrs int32 - Flags int32 Index uint16 - _ [2]byte + Flags int32 + Addrs int32 } type IfAnnounceMsghdr struct { @@ -350,7 +344,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -374,7 +367,6 @@ type RtMetrics struct { Hopcount uint64 Mssopt uint16 Pad uint16 - _ [4]byte Msl uint64 Iwmaxsegs uint64 Iwcapsegs uint64 @@ -400,7 +392,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -439,6 +430,9 @@ type Winsize struct { const ( AT_FDCWD = 0xfffafdcd AT_SYMLINK_NOFOLLOW = 0x1 + AT_REMOVEDIR = 0x2 + AT_EACCESS = 0x4 + AT_SYMLINK_FOLLOW = 0x8 ) type PollFd struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 2a3ec61..51e13eb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -1,7 +1,7 @@ // cgo -godefs types_freebsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,freebsd +//go:build 386 && freebsd package unix @@ -30,6 +30,8 @@ type Timeval struct { Usec int32 } +type Time_t int32 + type Rusage struct { Utime Timeval Stime Timeval @@ -87,27 +89,6 @@ type Stat_t struct { Spare [10]uint64 } -type stat_freebsd11_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Btim Timespec - _ [8]byte -} - type Statfs_t struct { Version uint32 Type uint32 @@ -133,31 +114,6 @@ type Statfs_t struct { Mntonname [1024]byte } -type statfs_freebsd11_t struct { - Version uint32 - Type uint32 - Flags uint64 - Bsize uint64 - Iosize uint64 - Blocks uint64 - Bfree uint64 - Bavail int64 - Files uint64 - Ffree int64 - Syncwrites uint64 - Asyncwrites uint64 - Syncreads uint64 - Asyncreads uint64 - Spare [10]uint64 - Namemax uint32 - Owner uint32 - Fsid Fsid - Charspare [80]int8 - Fstypename [16]byte - Mntfromname [88]byte - Mntonname [88]byte -} - type Flock_t struct { Start int64 Len int64 @@ -178,14 +134,6 @@ type Dirent struct { Name [256]int8 } -type dirent_freebsd11 struct { - Fileno uint32 - Reclen uint16 - Type uint8 - Namlen uint8 - Name [256]int8 -} - type Fsid struct { Val [2]int32 } @@ -250,6 +198,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -312,7 +268,9 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x50 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc SizeofIPv6Mreq = 0x14 @@ -324,41 +282,9 @@ const ( ) const ( - PTRACE_ATTACH = 0xa - PTRACE_CONT = 0x7 - PTRACE_DETACH = 0xb - PTRACE_GETFPREGS = 0x23 - PTRACE_GETFSBASE = 0x47 - PTRACE_GETLWPLIST = 0xf - PTRACE_GETNUMLWPS = 0xe - PTRACE_GETREGS = 0x21 - PTRACE_GETXSTATE = 0x45 - PTRACE_IO = 0xc - PTRACE_KILL = 0x8 - PTRACE_LWPEVENTS = 0x18 - PTRACE_LWPINFO = 0xd - PTRACE_SETFPREGS = 0x24 - PTRACE_SETREGS = 0x22 - PTRACE_SINGLESTEP = 0x9 - PTRACE_TRACEME = 0x0 -) - -const ( - PIOD_READ_D = 0x1 - PIOD_WRITE_D = 0x2 - PIOD_READ_I = 0x3 - PIOD_WRITE_I = 0x4 -) - -const ( - PL_FLAG_BORN = 0x100 - PL_FLAG_EXITED = 0x200 - PL_FLAG_SI = 0x20 -) - -const ( - TRAP_BRKPT = 0x1 - TRAP_TRACE = 0x2 + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 ) type PtraceLwpInfoStruct struct { @@ -367,7 +293,7 @@ type PtraceLwpInfoStruct struct { Flags int32 Sigmask Sigset_t Siglist Sigset_t - Siginfo __Siginfo + Siginfo __PtraceSiginfo Tdname [20]int8 Child_pid int32 Syscall_code uint32 @@ -385,6 +311,17 @@ type __Siginfo struct { Value [4]byte _ [32]byte } +type __PtraceSiginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr uintptr + Value [4]byte + _ [32]byte +} type Sigset_t struct { Val [4]uint32 @@ -419,9 +356,11 @@ type FpReg struct { Pad [64]uint8 } +type FpExtendedPrecision struct{} + type PtraceIoDesc struct { Op int32 - Offs *byte + Offs uintptr Addr *byte Len uint32 } @@ -431,8 +370,9 @@ type Kevent_t struct { Filter int16 Flags uint16 Fflags uint32 - Data int32 + Data int64 Udata *byte + Ext [4]uint64 } type FdSet struct { @@ -661,9 +601,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -684,6 +625,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index e11e954..d002d8e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -1,7 +1,7 @@ // cgo -godefs types_freebsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,freebsd +//go:build amd64 && freebsd package unix @@ -30,6 +30,8 @@ type Timeval struct { Usec int64 } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval @@ -83,26 +85,6 @@ type Stat_t struct { Spare [10]uint64 } -type stat_freebsd11_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Btim Timespec -} - type Statfs_t struct { Version uint32 Type uint32 @@ -128,31 +110,6 @@ type Statfs_t struct { Mntonname [1024]byte } -type statfs_freebsd11_t struct { - Version uint32 - Type uint32 - Flags uint64 - Bsize uint64 - Iosize uint64 - Blocks uint64 - Bfree uint64 - Bavail int64 - Files uint64 - Ffree int64 - Syncwrites uint64 - Asyncwrites uint64 - Syncreads uint64 - Asyncreads uint64 - Spare [10]uint64 - Namemax uint32 - Owner uint32 - Fsid Fsid - Charspare [80]int8 - Fstypename [16]byte - Mntfromname [88]byte - Mntonname [88]byte -} - type Flock_t struct { Start int64 Len int64 @@ -174,14 +131,6 @@ type Dirent struct { Name [256]int8 } -type dirent_freebsd11 struct { - Fileno uint32 - Reclen uint16 - Type uint8 - Namlen uint8 - Name [256]int8 -} - type Fsid struct { Val [2]int32 } @@ -246,6 +195,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -308,7 +265,9 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x58 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc SizeofIPv6Mreq = 0x14 @@ -320,41 +279,9 @@ const ( ) const ( - PTRACE_ATTACH = 0xa - PTRACE_CONT = 0x7 - PTRACE_DETACH = 0xb - PTRACE_GETFPREGS = 0x23 - PTRACE_GETFSBASE = 0x47 - PTRACE_GETLWPLIST = 0xf - PTRACE_GETNUMLWPS = 0xe - PTRACE_GETREGS = 0x21 - PTRACE_GETXSTATE = 0x45 - PTRACE_IO = 0xc - PTRACE_KILL = 0x8 - PTRACE_LWPEVENTS = 0x18 - PTRACE_LWPINFO = 0xd - PTRACE_SETFPREGS = 0x24 - PTRACE_SETREGS = 0x22 - PTRACE_SINGLESTEP = 0x9 - PTRACE_TRACEME = 0x0 -) - -const ( - PIOD_READ_D = 0x1 - PIOD_WRITE_D = 0x2 - PIOD_READ_I = 0x3 - PIOD_WRITE_I = 0x4 -) - -const ( - PL_FLAG_BORN = 0x100 - PL_FLAG_EXITED = 0x200 - PL_FLAG_SI = 0x20 -) - -const ( - TRAP_BRKPT = 0x1 - TRAP_TRACE = 0x2 + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 ) type PtraceLwpInfoStruct struct { @@ -363,7 +290,7 @@ type PtraceLwpInfoStruct struct { Flags int32 Sigmask Sigset_t Siglist Sigset_t - Siginfo __Siginfo + Siginfo __PtraceSiginfo Tdname [20]int8 Child_pid int32 Syscall_code uint32 @@ -382,6 +309,18 @@ type __Siginfo struct { _ [40]byte } +type __PtraceSiginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr uintptr + Value [8]byte + _ [40]byte +} + type Sigset_t struct { Val [4]uint32 } @@ -422,9 +361,11 @@ type FpReg struct { Spare [12]uint64 } +type FpExtendedPrecision struct{} + type PtraceIoDesc struct { Op int32 - Offs *byte + Offs uintptr Addr *byte Len uint64 } @@ -436,6 +377,7 @@ type Kevent_t struct { Fflags uint32 Data int64 Udata *byte + Ext [4]uint64 } type FdSet struct { @@ -664,9 +606,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -687,6 +630,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index 6f79227..3f863d8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -1,7 +1,7 @@ // cgo -godefs -- -fsigned-char types_freebsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,freebsd +//go:build arm && freebsd package unix @@ -32,6 +32,8 @@ type Timeval struct { _ [4]byte } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval @@ -85,26 +87,6 @@ type Stat_t struct { Spare [10]uint64 } -type stat_freebsd11_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Btim Timespec -} - type Statfs_t struct { Version uint32 Type uint32 @@ -125,34 +107,9 @@ type Statfs_t struct { Owner uint32 Fsid Fsid Charspare [80]int8 - Fstypename [16]int8 - Mntfromname [1024]int8 - Mntonname [1024]int8 -} - -type statfs_freebsd11_t struct { - Version uint32 - Type uint32 - Flags uint64 - Bsize uint64 - Iosize uint64 - Blocks uint64 - Bfree uint64 - Bavail int64 - Files uint64 - Ffree int64 - Syncwrites uint64 - Asyncwrites uint64 - Syncreads uint64 - Asyncreads uint64 - Spare [10]uint64 - Namemax uint32 - Owner uint32 - Fsid Fsid - Charspare [80]int8 - Fstypename [16]int8 - Mntfromname [88]int8 - Mntonname [88]int8 + Fstypename [16]byte + Mntfromname [1024]byte + Mntonname [1024]byte } type Flock_t struct { @@ -176,14 +133,6 @@ type Dirent struct { Name [256]int8 } -type dirent_freebsd11 struct { - Fileno uint32 - Reclen uint16 - Type uint8 - Namlen uint8 - Name [256]int8 -} - type Fsid struct { Val [2]int32 } @@ -248,6 +197,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -310,7 +267,9 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x50 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc SizeofIPv6Mreq = 0x14 @@ -322,41 +281,9 @@ const ( ) const ( - PTRACE_ATTACH = 0xa - PTRACE_CONT = 0x7 - PTRACE_DETACH = 0xb - PTRACE_GETFPREGS = 0x23 - PTRACE_GETFSBASE = 0x47 - PTRACE_GETLWPLIST = 0xf - PTRACE_GETNUMLWPS = 0xe - PTRACE_GETREGS = 0x21 - PTRACE_GETXSTATE = 0x45 - PTRACE_IO = 0xc - PTRACE_KILL = 0x8 - PTRACE_LWPEVENTS = 0x18 - PTRACE_LWPINFO = 0xd - PTRACE_SETFPREGS = 0x24 - PTRACE_SETREGS = 0x22 - PTRACE_SINGLESTEP = 0x9 - PTRACE_TRACEME = 0x0 -) - -const ( - PIOD_READ_D = 0x1 - PIOD_WRITE_D = 0x2 - PIOD_READ_I = 0x3 - PIOD_WRITE_I = 0x4 -) - -const ( - PL_FLAG_BORN = 0x100 - PL_FLAG_EXITED = 0x200 - PL_FLAG_SI = 0x20 -) - -const ( - TRAP_BRKPT = 0x1 - TRAP_TRACE = 0x2 + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 ) type PtraceLwpInfoStruct struct { @@ -365,7 +292,7 @@ type PtraceLwpInfoStruct struct { Flags int32 Sigmask Sigset_t Siglist Sigset_t - Siginfo __Siginfo + Siginfo __PtraceSiginfo Tdname [20]int8 Child_pid int32 Syscall_code uint32 @@ -373,15 +300,27 @@ type PtraceLwpInfoStruct struct { } type __Siginfo struct { - Signo int32 - Errno int32 - Code int32 - Pid int32 - Uid uint32 - Status int32 - Addr *byte - Value [4]byte - X_reason [32]byte + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr *byte + Value [4]byte + _ [32]byte +} + +type __PtraceSiginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr uintptr + Value [4]byte + _ [32]byte } type Sigset_t struct { @@ -389,21 +328,27 @@ type Sigset_t struct { } type Reg struct { - R [13]uint32 - R_sp uint32 - R_lr uint32 - R_pc uint32 - R_cpsr uint32 + R [13]uint32 + Sp uint32 + Lr uint32 + Pc uint32 + Cpsr uint32 } type FpReg struct { - Fpr_fpsr uint32 - Fpr [8][3]uint32 + Fpsr uint32 + Fpr [8]FpExtendedPrecision +} + +type FpExtendedPrecision struct { + Exponent uint32 + Mantissa_hi uint32 + Mantissa_lo uint32 } type PtraceIoDesc struct { Op int32 - Offs *byte + Offs uintptr Addr *byte Len uint32 } @@ -413,8 +358,11 @@ type Kevent_t struct { Filter int16 Flags uint16 Fflags uint32 - Data int32 + _ [4]byte + Data int64 Udata *byte + _ [4]byte + Ext [4]uint64 } type FdSet struct { @@ -440,7 +388,7 @@ type ifMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte + _ uint16 Data ifData } @@ -451,7 +399,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -519,7 +466,7 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte + _ uint16 Metric int32 } @@ -530,7 +477,7 @@ type IfmaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte + _ uint16 } type IfAnnounceMsghdr struct { @@ -547,7 +494,7 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte + _ uint16 Flags int32 Addrs int32 Pid int32 @@ -645,9 +592,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -668,6 +616,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index c6fe1d0..61c7293 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -1,7 +1,7 @@ // cgo -godefs -- -fsigned-char types_freebsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,freebsd +//go:build arm64 && freebsd package unix @@ -30,6 +30,8 @@ type Timeval struct { Usec int64 } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval @@ -83,26 +85,6 @@ type Stat_t struct { Spare [10]uint64 } -type stat_freebsd11_t struct { - Dev uint32 - Ino uint32 - Mode uint16 - Nlink uint16 - Uid uint32 - Gid uint32 - Rdev uint32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Btim Timespec -} - type Statfs_t struct { Version uint32 Type uint32 @@ -128,31 +110,6 @@ type Statfs_t struct { Mntonname [1024]byte } -type statfs_freebsd11_t struct { - Version uint32 - Type uint32 - Flags uint64 - Bsize uint64 - Iosize uint64 - Blocks uint64 - Bfree uint64 - Bavail int64 - Files uint64 - Ffree int64 - Syncwrites uint64 - Asyncwrites uint64 - Syncreads uint64 - Asyncreads uint64 - Spare [10]uint64 - Namemax uint32 - Owner uint32 - Fsid Fsid - Charspare [80]int8 - Fstypename [16]byte - Mntfromname [88]byte - Mntonname [88]byte -} - type Flock_t struct { Start int64 Len int64 @@ -174,14 +131,6 @@ type Dirent struct { Name [256]int8 } -type dirent_freebsd11 struct { - Fileno uint32 - Reclen uint16 - Type uint8 - Namlen uint8 - Name [256]int8 -} - type Fsid struct { Val [2]int32 } @@ -246,6 +195,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -308,7 +265,9 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x58 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc SizeofIPv6Mreq = 0x14 @@ -320,39 +279,9 @@ const ( ) const ( - PTRACE_ATTACH = 0xa - PTRACE_CONT = 0x7 - PTRACE_DETACH = 0xb - PTRACE_GETFPREGS = 0x23 - PTRACE_GETLWPLIST = 0xf - PTRACE_GETNUMLWPS = 0xe - PTRACE_GETREGS = 0x21 - PTRACE_IO = 0xc - PTRACE_KILL = 0x8 - PTRACE_LWPEVENTS = 0x18 - PTRACE_LWPINFO = 0xd - PTRACE_SETFPREGS = 0x24 - PTRACE_SETREGS = 0x22 - PTRACE_SINGLESTEP = 0x9 - PTRACE_TRACEME = 0x0 -) - -const ( - PIOD_READ_D = 0x1 - PIOD_WRITE_D = 0x2 - PIOD_READ_I = 0x3 - PIOD_WRITE_I = 0x4 -) - -const ( - PL_FLAG_BORN = 0x100 - PL_FLAG_EXITED = 0x200 - PL_FLAG_SI = 0x20 -) - -const ( - TRAP_BRKPT = 0x1 - TRAP_TRACE = 0x2 + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 ) type PtraceLwpInfoStruct struct { @@ -361,7 +290,7 @@ type PtraceLwpInfoStruct struct { Flags int32 Sigmask Sigset_t Siglist Sigset_t - Siginfo __Siginfo + Siginfo __PtraceSiginfo Tdname [20]int8 Child_pid int32 Syscall_code uint32 @@ -380,6 +309,18 @@ type __Siginfo struct { _ [40]byte } +type __PtraceSiginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr uintptr + Value [8]byte + _ [40]byte +} + type Sigset_t struct { Val [4]uint32 } @@ -400,9 +341,11 @@ type FpReg struct { _ [8]byte } +type FpExtendedPrecision struct{} + type PtraceIoDesc struct { Op int32 - Offs *byte + Offs uintptr Addr *byte Len uint64 } @@ -414,6 +357,7 @@ type Kevent_t struct { Fflags uint32 Data int64 Udata *byte + Ext [4]uint64 } type FdSet struct { @@ -642,9 +586,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -665,6 +610,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go new file mode 100644 index 0000000..b5d1741 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go @@ -0,0 +1,638 @@ +// cgo -godefs -- -fsigned-char types_freebsd.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build riscv64 && freebsd + +package unix + +const ( + SizeofPtr = 0x8 + SizeofShort = 0x2 + SizeofInt = 0x4 + SizeofLong = 0x8 + SizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +type Time_t int64 + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Rlimit struct { + Cur int64 + Max int64 +} + +type _Gid_t uint32 + +const ( + _statfsVersion = 0x20140518 + _dirblksiz = 0x400 +) + +type Stat_t struct { + Dev uint64 + Ino uint64 + Nlink uint64 + Mode uint16 + _0 int16 + Uid uint32 + Gid uint32 + _1 int32 + Rdev uint64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Btim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint64 + Spare [10]uint64 +} + +type Statfs_t struct { + Version uint32 + Type uint32 + Flags uint64 + Bsize uint64 + Iosize uint64 + Blocks uint64 + Bfree uint64 + Bavail int64 + Files uint64 + Ffree int64 + Syncwrites uint64 + Asyncwrites uint64 + Syncreads uint64 + Asyncreads uint64 + Spare [10]uint64 + Namemax uint32 + Owner uint32 + Fsid Fsid + Charspare [80]int8 + Fstypename [16]byte + Mntfromname [1024]byte + Mntonname [1024]byte +} + +type Flock_t struct { + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 + Sysid int32 + _ [4]byte +} + +type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Pad0 uint8 + Namlen uint16 + Pad1 uint16 + Name [256]int8 +} + +type Fsid struct { + Val [2]int32 +} + +const ( + PathMax = 0x400 +) + +const ( + FADV_NORMAL = 0x0 + FADV_RANDOM = 0x1 + FADV_SEQUENTIAL = 0x2 + FADV_WILLNEED = 0x3 + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + +type RawSockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]int8 +} + +type RawSockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddrUnix struct { + Len uint8 + Family uint8 + Path [104]int8 +} + +type RawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [46]int8 +} + +type RawSockaddr struct { + Len uint8 + Family uint8 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [92]int8 +} + +type _Socklen uint32 + +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + +type Linger struct { + Onoff int32 + Linger int32 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPMreqn struct { + Multiaddr [4]byte /* in_addr */ + Address [4]byte /* in_addr */ + Ifindex int32 +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Iov *Iovec + Iovlen int32 + Control *byte + Controllen uint32 + Flags int32 +} + +type Cmsghdr struct { + Len uint32 + Level int32 + Type int32 +} + +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type IPv6MTUInfo struct { + Addr RawSockaddrInet6 + Mtu uint32 +} + +type ICMPv6Filter struct { + Filt [8]uint32 +} + +const ( + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x58 + SizeofLinger = 0x8 + SizeofIovec = 0x10 + SizeofIPMreq = 0x8 + SizeofIPMreqn = 0xc + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 +) + +const ( + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 +) + +type PtraceLwpInfoStruct struct { + Lwpid int32 + Event int32 + Flags int32 + Sigmask Sigset_t + Siglist Sigset_t + Siginfo __PtraceSiginfo + Tdname [20]int8 + Child_pid int32 + Syscall_code uint32 + Syscall_narg uint32 +} + +type __Siginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr *byte + Value [8]byte + _ [40]byte +} + +type __PtraceSiginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + Status int32 + Addr uintptr + Value [8]byte + _ [40]byte +} + +type Sigset_t struct { + Val [4]uint32 +} + +type Reg struct { + Ra uint64 + Sp uint64 + Gp uint64 + Tp uint64 + T [7]uint64 + S [12]uint64 + A [8]uint64 + Sepc uint64 + Sstatus uint64 +} + +type FpReg struct { + X [32][2]uint64 + Fcsr uint64 +} + +type FpExtendedPrecision struct{} + +type PtraceIoDesc struct { + Op int32 + Offs uintptr + Addr *byte + Len uint64 +} + +type Kevent_t struct { + Ident uint64 + Filter int16 + Flags uint16 + Fflags uint32 + Data int64 + Udata *byte + Ext [4]uint64 +} + +type FdSet struct { + Bits [16]uint64 +} + +const ( + sizeofIfMsghdr = 0xa8 + SizeofIfMsghdr = 0xa8 + sizeofIfData = 0x98 + SizeofIfData = 0x98 + SizeofIfaMsghdr = 0x14 + SizeofIfmaMsghdr = 0x10 + SizeofIfAnnounceMsghdr = 0x18 + SizeofRtMsghdr = 0x98 + SizeofRtMetrics = 0x70 +) + +type ifMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ uint16 + Data ifData +} + +type IfMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + Data IfData +} + +type ifData struct { + Type uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Vhid uint8 + Datalen uint16 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Hwassist uint64 + _ [8]byte + _ [16]byte +} + +type IfData struct { + Type uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Spare_char1 uint8 + Spare_char2 uint8 + Datalen uint8 + Mtu uint64 + Metric uint64 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Noproto uint64 + Hwassist uint64 + Epoch int64 + Lastchange Timeval +} + +type IfaMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ uint16 + Metric int32 +} + +type IfmaMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ uint16 +} + +type IfAnnounceMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Name [16]int8 + What uint16 +} + +type RtMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ uint16 + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Fmask int32 + Inits uint64 + Rmx RtMetrics +} + +type RtMetrics struct { + Locks uint64 + Mtu uint64 + Hopcount uint64 + Expire uint64 + Recvpipe uint64 + Sendpipe uint64 + Ssthresh uint64 + Rtt uint64 + Rttvar uint64 + Pksent uint64 + Weight uint64 + Nhidx uint64 + Filler [2]uint64 +} + +const ( + SizeofBpfVersion = 0x4 + SizeofBpfStat = 0x8 + SizeofBpfZbuf = 0x18 + SizeofBpfProgram = 0x10 + SizeofBpfInsn = 0x8 + SizeofBpfHdr = 0x20 + SizeofBpfZbufHeader = 0x20 +) + +type BpfVersion struct { + Major uint16 + Minor uint16 +} + +type BpfStat struct { + Recv uint32 + Drop uint32 +} + +type BpfZbuf struct { + Bufa *byte + Bufb *byte + Buflen uint64 +} + +type BpfProgram struct { + Len uint32 + Insns *BpfInsn +} + +type BpfInsn struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} + +type BpfHdr struct { + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [6]byte +} + +type BpfZbufHeader struct { + Kernel_gen uint32 + Kernel_len uint32 + User_gen uint32 + _ [5]uint32 +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]uint8 + Ispeed uint32 + Ospeed uint32 +} + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +const ( + AT_FDCWD = -0x64 + AT_EACCESS = 0x100 + AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 +) + +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLERR = 0x8 + POLLHUP = 0x10 + POLLIN = 0x1 + POLLINIGNEOF = 0x2000 + POLLNVAL = 0x20 + POLLOUT = 0x4 + POLLPRI = 0x2 + POLLRDBAND = 0x80 + POLLRDNORM = 0x40 + POLLWRBAND = 0x100 + POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 +) + +type CapRights struct { + Rights [2]uint64 +} + +type Utsname struct { + Sysname [256]byte + Nodename [256]byte + Release [256]byte + Version [256]byte + Machine [256]byte +} + +const SizeofClockinfo = 0x14 + +type Clockinfo struct { + Hz int32 + Tick int32 + Spare int32 + Stathz int32 + Profhz int32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index cb5e06c..c1a4670 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -1,6 +1,6 @@ -// Code generated by mkmerge.go; DO NOT EDIT. +// Code generated by mkmerge; DO NOT EDIT. -// +build linux +//go:build linux package unix @@ -18,6 +18,51 @@ type ( _C_long_long int64 ) +type ItimerSpec struct { + Interval Timespec + Value Timespec +} + +type Itimerval struct { + Interval Timeval + Value Timeval +} + +const ( + ADJ_OFFSET = 0x1 + ADJ_FREQUENCY = 0x2 + ADJ_MAXERROR = 0x4 + ADJ_ESTERROR = 0x8 + ADJ_STATUS = 0x10 + ADJ_TIMECONST = 0x20 + ADJ_TAI = 0x80 + ADJ_SETOFFSET = 0x100 + ADJ_MICRO = 0x1000 + ADJ_NANO = 0x2000 + ADJ_TICK = 0x4000 + ADJ_OFFSET_SINGLESHOT = 0x8001 + ADJ_OFFSET_SS_READ = 0xa001 +) + +const ( + STA_PLL = 0x1 + STA_PPSFREQ = 0x2 + STA_PPSTIME = 0x4 + STA_FLL = 0x8 + STA_INS = 0x10 + STA_DEL = 0x20 + STA_UNSYNC = 0x40 + STA_FREQHOLD = 0x80 + STA_PPSSIGNAL = 0x100 + STA_PPSJITTER = 0x200 + STA_PPSWANDER = 0x400 + STA_PPSERROR = 0x800 + STA_CLOCKERR = 0x1000 + STA_NANO = 0x2000 + STA_MODE = 0x4000 + STA_CLK = 0x8000 +) + const ( TIME_OK = 0x0 TIME_INS = 0x1 @@ -42,33 +87,73 @@ type StatxTimestamp struct { } type Statx_t struct { - Mask uint32 - Blksize uint32 - Attributes uint64 - Nlink uint32 - Uid uint32 - Gid uint32 - Mode uint16 - _ [1]uint16 - Ino uint64 - Size uint64 - Blocks uint64 - Attributes_mask uint64 - Atime StatxTimestamp - Btime StatxTimestamp - Ctime StatxTimestamp - Mtime StatxTimestamp - Rdev_major uint32 - Rdev_minor uint32 - Dev_major uint32 - Dev_minor uint32 - _ [14]uint64 + Mask uint32 + Blksize uint32 + Attributes uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Mode uint16 + _ [1]uint16 + Ino uint64 + Size uint64 + Blocks uint64 + Attributes_mask uint64 + Atime StatxTimestamp + Btime StatxTimestamp + Ctime StatxTimestamp + Mtime StatxTimestamp + Rdev_major uint32 + Rdev_minor uint32 + Dev_major uint32 + Dev_minor uint32 + Mnt_id uint64 + Dio_mem_align uint32 + Dio_offset_align uint32 + Subvol uint64 + Atomic_write_unit_min uint32 + Atomic_write_unit_max uint32 + Atomic_write_segments_max uint32 + Dio_read_offset_align uint32 + Atomic_write_unit_max_opt uint32 + _ [1]uint32 + _ [8]uint64 } type Fsid struct { Val [2]int32 } +type FileCloneRange struct { + Src_fd int64 + Src_offset uint64 + Src_length uint64 + Dest_offset uint64 +} + +type RawFileDedupeRange struct { + Src_offset uint64 + Src_length uint64 + Dest_count uint16 + Reserved1 uint16 + Reserved2 uint32 +} + +type RawFileDedupeRangeInfo struct { + Dest_fd int64 + Dest_offset uint64 + Bytes_deduped uint64 + Status int32 + Reserved uint32 +} + +const ( + SizeofRawFileDedupeRange = 0x18 + SizeofRawFileDedupeRangeInfo = 0x20 + FILE_DEDUPE_RANGE_SAME = 0x0 + FILE_DEDUPE_RANGE_DIFFERS = 0x1 +) + type FscryptPolicy struct { Version uint8 Contents_encryption_mode uint8 @@ -96,7 +181,8 @@ type FscryptPolicyV2 struct { Contents_encryption_mode uint8 Filenames_encryption_mode uint8 Flags uint8 - _ [4]uint8 + Log2_data_unit_size uint8 + _ [3]uint8 Master_key_identifier [16]uint8 } @@ -114,7 +200,9 @@ type FscryptKeySpecifier struct { type FscryptAddKeyArg struct { Key_spec FscryptKeySpecifier Raw_size uint32 - _ [9]uint32 + Key_id uint32 + Flags uint32 + _ [7]uint32 } type FscryptRemoveKeyArg struct { @@ -132,6 +220,48 @@ type FscryptGetKeyStatusArg struct { _ [13]uint32 } +type DmIoctl struct { + Version [3]uint32 + Data_size uint32 + Data_start uint32 + Target_count uint32 + Open_count int32 + Flags uint32 + Event_nr uint32 + _ uint32 + Dev uint64 + Name [128]byte + Uuid [129]byte + Data [7]byte +} + +type DmTargetSpec struct { + Sector_start uint64 + Length uint64 + Status int32 + Next uint32 + Target_type [16]byte +} + +type DmTargetDeps struct { + Count uint32 + _ uint32 +} + +type DmTargetVersions struct { + Next uint32 + Version [3]uint32 +} + +type DmTargetMsg struct { + Sector uint64 +} + +const ( + SizeofDmIoctl = 0x138 + SizeofDmTargetSpec = 0x28 +) + type KeyctlDHParams struct { Private int32 Prime int32 @@ -223,7 +353,8 @@ type RawSockaddrVM struct { Reserved1 uint16 Port uint32 Cid uint32 - Zero [4]uint8 + Flags uint8 + Zero [3]uint8 } type RawSockaddrXDP struct { @@ -260,6 +391,22 @@ type RawSockaddrL2TPIP6 struct { Conn_id uint32 } +type RawSockaddrIUCV struct { + Family uint16 + Port uint16 + Addr uint32 + Nodeid [8]int8 + User_id [8]int8 + Name [8]int8 +} + +type RawSockaddrNFC struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 +} + type _Socklen uint32 type Linger struct { @@ -317,36 +464,86 @@ type Ucred struct { } type TCPInfo struct { - State uint8 - Ca_state uint8 - Retransmits uint8 - Probes uint8 - Backoff uint8 - Options uint8 - Rto uint32 - Ato uint32 - Snd_mss uint32 - Rcv_mss uint32 - Unacked uint32 - Sacked uint32 - Lost uint32 - Retrans uint32 - Fackets uint32 - Last_data_sent uint32 - Last_ack_sent uint32 - Last_data_recv uint32 - Last_ack_recv uint32 - Pmtu uint32 - Rcv_ssthresh uint32 - Rtt uint32 - Rttvar uint32 - Snd_ssthresh uint32 - Snd_cwnd uint32 - Advmss uint32 - Reordering uint32 - Rcv_rtt uint32 - Rcv_space uint32 - Total_retrans uint32 + State uint8 + Ca_state uint8 + Retransmits uint8 + Probes uint8 + Backoff uint8 + Options uint8 + Rto uint32 + Ato uint32 + Snd_mss uint32 + Rcv_mss uint32 + Unacked uint32 + Sacked uint32 + Lost uint32 + Retrans uint32 + Fackets uint32 + Last_data_sent uint32 + Last_ack_sent uint32 + Last_data_recv uint32 + Last_ack_recv uint32 + Pmtu uint32 + Rcv_ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Advmss uint32 + Reordering uint32 + Rcv_rtt uint32 + Rcv_space uint32 + Total_retrans uint32 + Pacing_rate uint64 + Max_pacing_rate uint64 + Bytes_acked uint64 + Bytes_received uint64 + Segs_out uint32 + Segs_in uint32 + Notsent_bytes uint32 + Min_rtt uint32 + Data_segs_in uint32 + Data_segs_out uint32 + Delivery_rate uint64 + Busy_time uint64 + Rwnd_limited uint64 + Sndbuf_limited uint64 + Delivered uint32 + Delivered_ce uint32 + Bytes_sent uint64 + Bytes_retrans uint64 + Dsack_dups uint32 + Reord_seen uint32 + Rcv_ooopack uint32 + Snd_wnd uint32 + Rcv_wnd uint32 + Rehash uint32 + Total_rto uint16 + Total_rto_recoveries uint16 + Total_rto_time uint32 +} + +type TCPVegasInfo struct { + Enabled uint32 + Rttcnt uint32 + Rtt uint32 + Minrtt uint32 +} + +type TCPDCTCPInfo struct { + Enabled uint16 + Ce_state uint16 + Alpha uint32 + Ab_ecn uint32 + Ab_tot uint32 +} + +type TCPBBRInfo struct { + Bw_lo uint32 + Bw_hi uint32 + Min_rtt uint32 + Pacing_gain uint32 + Cwnd_gain uint32 } type CanFilter struct { @@ -354,6 +551,11 @@ type CanFilter struct { Mask uint32 } +type TCPRepairOpt struct { + Code uint32 + Val uint32 +} + const ( SizeofSockaddrInet4 = 0x10 SizeofSockaddrInet6 = 0x1c @@ -372,6 +574,8 @@ const ( SizeofSockaddrTIPC = 0x10 SizeofSockaddrL2TPIP = 0x10 SizeofSockaddrL2TPIP6 = 0x20 + SizeofSockaddrIUCV = 0x20 + SizeofSockaddrNFC = 0x10 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc @@ -382,171 +586,117 @@ const ( SizeofIPv6MTUInfo = 0x20 SizeofICMPv6Filter = 0x20 SizeofUcred = 0xc - SizeofTCPInfo = 0x68 + SizeofTCPInfo = 0xf8 + SizeofTCPCCInfo = 0x14 SizeofCanFilter = 0x8 + SizeofTCPRepairOpt = 0x8 ) const ( - NDA_UNSPEC = 0x0 - NDA_DST = 0x1 - NDA_LLADDR = 0x2 - NDA_CACHEINFO = 0x3 - NDA_PROBES = 0x4 - NDA_VLAN = 0x5 - NDA_PORT = 0x6 - NDA_VNI = 0x7 - NDA_IFINDEX = 0x8 - NDA_MASTER = 0x9 - NDA_LINK_NETNSID = 0xa - NDA_SRC_VNI = 0xb - NTF_USE = 0x1 - NTF_SELF = 0x2 - NTF_MASTER = 0x4 - NTF_PROXY = 0x8 - NTF_EXT_LEARNED = 0x10 - NTF_OFFLOADED = 0x20 - NTF_ROUTER = 0x80 - NUD_INCOMPLETE = 0x1 - NUD_REACHABLE = 0x2 - NUD_STALE = 0x4 - NUD_DELAY = 0x8 - NUD_PROBE = 0x10 - NUD_FAILED = 0x20 - NUD_NOARP = 0x40 - NUD_PERMANENT = 0x80 - NUD_NONE = 0x0 - IFA_UNSPEC = 0x0 - IFA_ADDRESS = 0x1 - IFA_LOCAL = 0x2 - IFA_LABEL = 0x3 - IFA_BROADCAST = 0x4 - IFA_ANYCAST = 0x5 - IFA_CACHEINFO = 0x6 - IFA_MULTICAST = 0x7 - IFA_FLAGS = 0x8 - IFA_RT_PRIORITY = 0x9 - IFA_TARGET_NETNSID = 0xa - IFLA_UNSPEC = 0x0 - IFLA_ADDRESS = 0x1 - IFLA_BROADCAST = 0x2 - IFLA_IFNAME = 0x3 - IFLA_MTU = 0x4 - IFLA_LINK = 0x5 - IFLA_QDISC = 0x6 - IFLA_STATS = 0x7 - IFLA_COST = 0x8 - IFLA_PRIORITY = 0x9 - IFLA_MASTER = 0xa - IFLA_WIRELESS = 0xb - IFLA_PROTINFO = 0xc - IFLA_TXQLEN = 0xd - IFLA_MAP = 0xe - IFLA_WEIGHT = 0xf - IFLA_OPERSTATE = 0x10 - IFLA_LINKMODE = 0x11 - IFLA_LINKINFO = 0x12 - IFLA_NET_NS_PID = 0x13 - IFLA_IFALIAS = 0x14 - IFLA_NUM_VF = 0x15 - IFLA_VFINFO_LIST = 0x16 - IFLA_STATS64 = 0x17 - IFLA_VF_PORTS = 0x18 - IFLA_PORT_SELF = 0x19 - IFLA_AF_SPEC = 0x1a - IFLA_GROUP = 0x1b - IFLA_NET_NS_FD = 0x1c - IFLA_EXT_MASK = 0x1d - IFLA_PROMISCUITY = 0x1e - IFLA_NUM_TX_QUEUES = 0x1f - IFLA_NUM_RX_QUEUES = 0x20 - IFLA_CARRIER = 0x21 - IFLA_PHYS_PORT_ID = 0x22 - IFLA_CARRIER_CHANGES = 0x23 - IFLA_PHYS_SWITCH_ID = 0x24 - IFLA_LINK_NETNSID = 0x25 - IFLA_PHYS_PORT_NAME = 0x26 - IFLA_PROTO_DOWN = 0x27 - IFLA_GSO_MAX_SEGS = 0x28 - IFLA_GSO_MAX_SIZE = 0x29 - IFLA_PAD = 0x2a - IFLA_XDP = 0x2b - IFLA_EVENT = 0x2c - IFLA_NEW_NETNSID = 0x2d - IFLA_IF_NETNSID = 0x2e - IFLA_TARGET_NETNSID = 0x2e - IFLA_CARRIER_UP_COUNT = 0x2f - IFLA_CARRIER_DOWN_COUNT = 0x30 - IFLA_NEW_IFINDEX = 0x31 - IFLA_MIN_MTU = 0x32 - IFLA_MAX_MTU = 0x33 - IFLA_MAX = 0x35 - IFLA_INFO_KIND = 0x1 - IFLA_INFO_DATA = 0x2 - IFLA_INFO_XSTATS = 0x3 - IFLA_INFO_SLAVE_KIND = 0x4 - IFLA_INFO_SLAVE_DATA = 0x5 - RT_SCOPE_UNIVERSE = 0x0 - RT_SCOPE_SITE = 0xc8 - RT_SCOPE_LINK = 0xfd - RT_SCOPE_HOST = 0xfe - RT_SCOPE_NOWHERE = 0xff - RT_TABLE_UNSPEC = 0x0 - RT_TABLE_COMPAT = 0xfc - RT_TABLE_DEFAULT = 0xfd - RT_TABLE_MAIN = 0xfe - RT_TABLE_LOCAL = 0xff - RT_TABLE_MAX = 0xffffffff - RTA_UNSPEC = 0x0 - RTA_DST = 0x1 - RTA_SRC = 0x2 - RTA_IIF = 0x3 - RTA_OIF = 0x4 - RTA_GATEWAY = 0x5 - RTA_PRIORITY = 0x6 - RTA_PREFSRC = 0x7 - RTA_METRICS = 0x8 - RTA_MULTIPATH = 0x9 - RTA_FLOW = 0xb - RTA_CACHEINFO = 0xc - RTA_TABLE = 0xf - RTA_MARK = 0x10 - RTA_MFC_STATS = 0x11 - RTA_VIA = 0x12 - RTA_NEWDST = 0x13 - RTA_PREF = 0x14 - RTA_ENCAP_TYPE = 0x15 - RTA_ENCAP = 0x16 - RTA_EXPIRES = 0x17 - RTA_PAD = 0x18 - RTA_UID = 0x19 - RTA_TTL_PROPAGATE = 0x1a - RTA_IP_PROTO = 0x1b - RTA_SPORT = 0x1c - RTA_DPORT = 0x1d - RTN_UNSPEC = 0x0 - RTN_UNICAST = 0x1 - RTN_LOCAL = 0x2 - RTN_BROADCAST = 0x3 - RTN_ANYCAST = 0x4 - RTN_MULTICAST = 0x5 - RTN_BLACKHOLE = 0x6 - RTN_UNREACHABLE = 0x7 - RTN_PROHIBIT = 0x8 - RTN_THROW = 0x9 - RTN_NAT = 0xa - RTN_XRESOLVE = 0xb - SizeofNlMsghdr = 0x10 - SizeofNlMsgerr = 0x14 - SizeofRtGenmsg = 0x1 - SizeofNlAttr = 0x4 - SizeofRtAttr = 0x4 - SizeofIfInfomsg = 0x10 - SizeofIfAddrmsg = 0x8 - SizeofIfaCacheinfo = 0x10 - SizeofRtMsg = 0xc - SizeofRtNexthop = 0x8 - SizeofNdUseroptmsg = 0x10 - SizeofNdMsg = 0xc + NDA_UNSPEC = 0x0 + NDA_DST = 0x1 + NDA_LLADDR = 0x2 + NDA_CACHEINFO = 0x3 + NDA_PROBES = 0x4 + NDA_VLAN = 0x5 + NDA_PORT = 0x6 + NDA_VNI = 0x7 + NDA_IFINDEX = 0x8 + NDA_MASTER = 0x9 + NDA_LINK_NETNSID = 0xa + NDA_SRC_VNI = 0xb + NTF_USE = 0x1 + NTF_SELF = 0x2 + NTF_MASTER = 0x4 + NTF_PROXY = 0x8 + NTF_EXT_LEARNED = 0x10 + NTF_OFFLOADED = 0x20 + NTF_ROUTER = 0x80 + NUD_INCOMPLETE = 0x1 + NUD_REACHABLE = 0x2 + NUD_STALE = 0x4 + NUD_DELAY = 0x8 + NUD_PROBE = 0x10 + NUD_FAILED = 0x20 + NUD_NOARP = 0x40 + NUD_PERMANENT = 0x80 + NUD_NONE = 0x0 + IFA_UNSPEC = 0x0 + IFA_ADDRESS = 0x1 + IFA_LOCAL = 0x2 + IFA_LABEL = 0x3 + IFA_BROADCAST = 0x4 + IFA_ANYCAST = 0x5 + IFA_CACHEINFO = 0x6 + IFA_MULTICAST = 0x7 + IFA_FLAGS = 0x8 + IFA_RT_PRIORITY = 0x9 + IFA_TARGET_NETNSID = 0xa + IFAL_LABEL = 0x2 + IFAL_ADDRESS = 0x1 + RT_SCOPE_UNIVERSE = 0x0 + RT_SCOPE_SITE = 0xc8 + RT_SCOPE_LINK = 0xfd + RT_SCOPE_HOST = 0xfe + RT_SCOPE_NOWHERE = 0xff + RT_TABLE_UNSPEC = 0x0 + RT_TABLE_COMPAT = 0xfc + RT_TABLE_DEFAULT = 0xfd + RT_TABLE_MAIN = 0xfe + RT_TABLE_LOCAL = 0xff + RT_TABLE_MAX = 0xffffffff + RTA_UNSPEC = 0x0 + RTA_DST = 0x1 + RTA_SRC = 0x2 + RTA_IIF = 0x3 + RTA_OIF = 0x4 + RTA_GATEWAY = 0x5 + RTA_PRIORITY = 0x6 + RTA_PREFSRC = 0x7 + RTA_METRICS = 0x8 + RTA_MULTIPATH = 0x9 + RTA_FLOW = 0xb + RTA_CACHEINFO = 0xc + RTA_TABLE = 0xf + RTA_MARK = 0x10 + RTA_MFC_STATS = 0x11 + RTA_VIA = 0x12 + RTA_NEWDST = 0x13 + RTA_PREF = 0x14 + RTA_ENCAP_TYPE = 0x15 + RTA_ENCAP = 0x16 + RTA_EXPIRES = 0x17 + RTA_PAD = 0x18 + RTA_UID = 0x19 + RTA_TTL_PROPAGATE = 0x1a + RTA_IP_PROTO = 0x1b + RTA_SPORT = 0x1c + RTA_DPORT = 0x1d + RTN_UNSPEC = 0x0 + RTN_UNICAST = 0x1 + RTN_LOCAL = 0x2 + RTN_BROADCAST = 0x3 + RTN_ANYCAST = 0x4 + RTN_MULTICAST = 0x5 + RTN_BLACKHOLE = 0x6 + RTN_UNREACHABLE = 0x7 + RTN_PROHIBIT = 0x8 + RTN_THROW = 0x9 + RTN_NAT = 0xa + RTN_XRESOLVE = 0xb + SizeofNlMsghdr = 0x10 + SizeofNlMsgerr = 0x14 + SizeofRtGenmsg = 0x1 + SizeofNlAttr = 0x4 + SizeofRtAttr = 0x4 + SizeofIfInfomsg = 0x10 + SizeofIfAddrmsg = 0x8 + SizeofIfAddrlblmsg = 0xc + SizeofIfaCacheinfo = 0x10 + SizeofRtMsg = 0xc + SizeofRtNexthop = 0x8 + SizeofNdUseroptmsg = 0x10 + SizeofNdMsg = 0xc ) type NlMsghdr struct { @@ -593,6 +743,15 @@ type IfAddrmsg struct { Index uint32 } +type IfAddrlblmsg struct { + Family uint8 + _ uint8 + Prefixlen uint8 + Flags uint8 + Index uint32 + Seq uint32 +} + type IfaCacheinfo struct { Prefered uint32 Valid uint32 @@ -640,6 +799,16 @@ type NdMsg struct { Type uint8 } +const ( + ICMP_FILTER = 0x1 + + ICMPV6_FILTER = 0x1 + ICMPV6_FILTER_BLOCK = 0x1 + ICMPV6_FILTER_BLOCKOTHERS = 0x3 + ICMPV6_FILTER_PASS = 0x2 + ICMPV6_FILTER_PASSONLY = 0x4 +) + const ( SizeofSockFilter = 0x8 ) @@ -665,6 +834,8 @@ type InotifyEvent struct { const SizeofInotifyEvent = 0x10 +const SI_LOAD_SHIFT = 0x10 + type Utsname struct { Sysname [65]byte Nodename [65]byte @@ -684,10 +855,56 @@ const ( AT_STATX_FORCE_SYNC = 0x2000 AT_STATX_DONT_SYNC = 0x4000 + AT_RECURSIVE = 0x8000 + AT_SYMLINK_FOLLOW = 0x400 AT_SYMLINK_NOFOLLOW = 0x100 AT_EACCESS = 0x200 + + OPEN_TREE_CLONE = 0x1 + + MOVE_MOUNT_F_SYMLINKS = 0x1 + MOVE_MOUNT_F_AUTOMOUNTS = 0x2 + MOVE_MOUNT_F_EMPTY_PATH = 0x4 + MOVE_MOUNT_T_SYMLINKS = 0x10 + MOVE_MOUNT_T_AUTOMOUNTS = 0x20 + MOVE_MOUNT_T_EMPTY_PATH = 0x40 + MOVE_MOUNT_SET_GROUP = 0x100 + + FSOPEN_CLOEXEC = 0x1 + + FSPICK_CLOEXEC = 0x1 + FSPICK_SYMLINK_NOFOLLOW = 0x2 + FSPICK_NO_AUTOMOUNT = 0x4 + FSPICK_EMPTY_PATH = 0x8 + + FSMOUNT_CLOEXEC = 0x1 + + FSCONFIG_SET_FLAG = 0x0 + FSCONFIG_SET_STRING = 0x1 + FSCONFIG_SET_BINARY = 0x2 + FSCONFIG_SET_PATH = 0x3 + FSCONFIG_SET_PATH_EMPTY = 0x4 + FSCONFIG_SET_FD = 0x5 + FSCONFIG_CMD_CREATE = 0x6 + FSCONFIG_CMD_RECONFIGURE = 0x7 +) + +type OpenHow struct { + Flags uint64 + Mode uint64 + Resolve uint64 +} + +const SizeofOpenHow = 0x18 + +const ( + RESOLVE_BENEATH = 0x8 + RESOLVE_IN_ROOT = 0x10 + RESOLVE_NO_MAGICLINKS = 0x2 + RESOLVE_NO_SYMLINKS = 0x4 + RESOLVE_NO_XDEV = 0x1 ) type PollFd struct { @@ -705,6 +922,11 @@ const ( POLLNVAL = 0x20 ) +type sigset_argpack struct { + ss *Sigset_t + ssLen uintptr +} + type SignalfdSiginfo struct { Signo uint32 Errno int32 @@ -730,8 +952,6 @@ type SignalfdSiginfo struct { _ [28]uint8 } -const PERF_IOC_FLAG_GROUP = 0x1 - type Winsize struct { Row uint16 Col uint16 @@ -792,6 +1012,7 @@ const ( CTRL_CMD_NEWMCAST_GRP = 0x7 CTRL_CMD_DELMCAST_GRP = 0x8 CTRL_CMD_GETMCAST_GRP = 0x9 + CTRL_CMD_GETPOLICY = 0xa CTRL_ATTR_UNSPEC = 0x0 CTRL_ATTR_FAMILY_ID = 0x1 CTRL_ATTR_FAMILY_NAME = 0x2 @@ -800,12 +1021,19 @@ const ( CTRL_ATTR_MAXATTR = 0x5 CTRL_ATTR_OPS = 0x6 CTRL_ATTR_MCAST_GROUPS = 0x7 + CTRL_ATTR_POLICY = 0x8 + CTRL_ATTR_OP_POLICY = 0x9 + CTRL_ATTR_OP = 0xa CTRL_ATTR_OP_UNSPEC = 0x0 CTRL_ATTR_OP_ID = 0x1 CTRL_ATTR_OP_FLAGS = 0x2 CTRL_ATTR_MCAST_GRP_UNSPEC = 0x0 CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_ID = 0x2 + CTRL_ATTR_POLICY_UNSPEC = 0x0 + CTRL_ATTR_POLICY_DO = 0x1 + CTRL_ATTR_POLICY_DUMP = 0x2 + CTRL_ATTR_POLICY_DUMP_MAX = 0x2 ) const ( @@ -838,6 +1066,9 @@ type PerfEventAttr struct { Aux_watermark uint32 Sample_max_stack uint16 _ uint16 + Aux_sample_size uint32 + _ uint32 + Sig_data uint64 } type PerfEventMmapPage struct { @@ -855,7 +1086,10 @@ type PerfEventMmapPage struct { Time_offset uint64 Time_zero uint64 Size uint32 - _ [948]uint8 + _ uint32 + Time_cycles uint64 + Time_mask uint64 + _ [928]uint8 Data_head uint64 Data_tail uint64 Data_offset uint64 @@ -894,16 +1128,17 @@ const ( PerfBitCommExec = CBitFieldMaskBit24 PerfBitUseClockID = CBitFieldMaskBit25 PerfBitContextSwitch = CBitFieldMaskBit26 + PerfBitWriteBackward = CBitFieldMaskBit27 ) const ( - PERF_TYPE_HARDWARE = 0x0 - PERF_TYPE_SOFTWARE = 0x1 - PERF_TYPE_TRACEPOINT = 0x2 - PERF_TYPE_HW_CACHE = 0x3 - PERF_TYPE_RAW = 0x4 - PERF_TYPE_BREAKPOINT = 0x5 - + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + PERF_TYPE_MAX = 0x6 PERF_COUNT_HW_CPU_CYCLES = 0x0 PERF_COUNT_HW_INSTRUCTIONS = 0x1 PERF_COUNT_HW_CACHE_REFERENCES = 0x2 @@ -914,99 +1149,176 @@ const ( PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 - - PERF_COUNT_HW_CACHE_L1D = 0x0 - PERF_COUNT_HW_CACHE_L1I = 0x1 - PERF_COUNT_HW_CACHE_LL = 0x2 - PERF_COUNT_HW_CACHE_DTLB = 0x3 - PERF_COUNT_HW_CACHE_ITLB = 0x4 - PERF_COUNT_HW_CACHE_BPU = 0x5 - PERF_COUNT_HW_CACHE_NODE = 0x6 - - PERF_COUNT_HW_CACHE_OP_READ = 0x0 - PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 - PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 - - PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 - PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 - - PERF_COUNT_SW_CPU_CLOCK = 0x0 - PERF_COUNT_SW_TASK_CLOCK = 0x1 - PERF_COUNT_SW_PAGE_FAULTS = 0x2 - PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 - PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 - PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 - PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 - PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 - PERF_COUNT_SW_EMULATION_FAULTS = 0x8 - PERF_COUNT_SW_DUMMY = 0x9 - PERF_COUNT_SW_BPF_OUTPUT = 0xa - - PERF_SAMPLE_IP = 0x1 - PERF_SAMPLE_TID = 0x2 - PERF_SAMPLE_TIME = 0x4 - PERF_SAMPLE_ADDR = 0x8 - PERF_SAMPLE_READ = 0x10 - PERF_SAMPLE_CALLCHAIN = 0x20 - PERF_SAMPLE_ID = 0x40 - PERF_SAMPLE_CPU = 0x80 - PERF_SAMPLE_PERIOD = 0x100 - PERF_SAMPLE_STREAM_ID = 0x200 - PERF_SAMPLE_RAW = 0x400 - PERF_SAMPLE_BRANCH_STACK = 0x800 - - PERF_SAMPLE_BRANCH_USER = 0x1 - PERF_SAMPLE_BRANCH_KERNEL = 0x2 - PERF_SAMPLE_BRANCH_HV = 0x4 - PERF_SAMPLE_BRANCH_ANY = 0x8 - PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 - PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 - PERF_SAMPLE_BRANCH_IND_CALL = 0x40 - PERF_SAMPLE_BRANCH_ABORT_TX = 0x80 - PERF_SAMPLE_BRANCH_IN_TX = 0x100 - PERF_SAMPLE_BRANCH_NO_TX = 0x200 - PERF_SAMPLE_BRANCH_COND = 0x400 - PERF_SAMPLE_BRANCH_CALL_STACK = 0x800 - PERF_SAMPLE_BRANCH_IND_JUMP = 0x1000 - PERF_SAMPLE_BRANCH_CALL = 0x2000 - PERF_SAMPLE_BRANCH_NO_FLAGS = 0x4000 - PERF_SAMPLE_BRANCH_NO_CYCLES = 0x8000 - PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 - - PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 - PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 - PERF_FORMAT_ID = 0x4 - PERF_FORMAT_GROUP = 0x8 - - PERF_RECORD_MMAP = 0x1 - PERF_RECORD_LOST = 0x2 - PERF_RECORD_COMM = 0x3 - PERF_RECORD_EXIT = 0x4 - PERF_RECORD_THROTTLE = 0x5 - PERF_RECORD_UNTHROTTLE = 0x6 - PERF_RECORD_FORK = 0x7 - PERF_RECORD_READ = 0x8 - PERF_RECORD_SAMPLE = 0x9 - PERF_RECORD_MMAP2 = 0xa - PERF_RECORD_AUX = 0xb - PERF_RECORD_ITRACE_START = 0xc - PERF_RECORD_LOST_SAMPLES = 0xd - PERF_RECORD_SWITCH = 0xe - PERF_RECORD_SWITCH_CPU_WIDE = 0xf - PERF_RECORD_NAMESPACES = 0x10 - - PERF_CONTEXT_HV = -0x20 - PERF_CONTEXT_KERNEL = -0x80 - PERF_CONTEXT_USER = -0x200 - - PERF_CONTEXT_GUEST = -0x800 - PERF_CONTEXT_GUEST_KERNEL = -0x880 - PERF_CONTEXT_GUEST_USER = -0xa00 - - PERF_FLAG_FD_NO_GROUP = 0x1 - PERF_FLAG_FD_OUTPUT = 0x2 - PERF_FLAG_PID_CGROUP = 0x4 - PERF_FLAG_FD_CLOEXEC = 0x8 + PERF_COUNT_HW_MAX = 0xa + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + PERF_COUNT_HW_CACHE_MAX = 0x7 + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + PERF_COUNT_HW_CACHE_OP_MAX = 0x3 + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + PERF_COUNT_HW_CACHE_RESULT_MAX = 0x2 + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + PERF_COUNT_SW_BPF_OUTPUT = 0xa + PERF_COUNT_SW_MAX = 0xc + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + PERF_SAMPLE_REGS_USER = 0x1000 + PERF_SAMPLE_STACK_USER = 0x2000 + PERF_SAMPLE_WEIGHT = 0x4000 + PERF_SAMPLE_DATA_SRC = 0x8000 + PERF_SAMPLE_IDENTIFIER = 0x10000 + PERF_SAMPLE_TRANSACTION = 0x20000 + PERF_SAMPLE_REGS_INTR = 0x40000 + PERF_SAMPLE_PHYS_ADDR = 0x80000 + PERF_SAMPLE_AUX = 0x100000 + PERF_SAMPLE_CGROUP = 0x200000 + PERF_SAMPLE_DATA_PAGE_SIZE = 0x400000 + PERF_SAMPLE_CODE_PAGE_SIZE = 0x800000 + PERF_SAMPLE_WEIGHT_STRUCT = 0x1000000 + PERF_SAMPLE_MAX = 0x2000000 + PERF_SAMPLE_BRANCH_USER_SHIFT = 0x0 + PERF_SAMPLE_BRANCH_KERNEL_SHIFT = 0x1 + PERF_SAMPLE_BRANCH_HV_SHIFT = 0x2 + PERF_SAMPLE_BRANCH_ANY_SHIFT = 0x3 + PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT = 0x4 + PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT = 0x5 + PERF_SAMPLE_BRANCH_IND_CALL_SHIFT = 0x6 + PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT = 0x7 + PERF_SAMPLE_BRANCH_IN_TX_SHIFT = 0x8 + PERF_SAMPLE_BRANCH_NO_TX_SHIFT = 0x9 + PERF_SAMPLE_BRANCH_COND_SHIFT = 0xa + PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT = 0xb + PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 0xc + PERF_SAMPLE_BRANCH_CALL_SHIFT = 0xd + PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 0xe + PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 0xf + PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10 + PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11 + PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 0x12 + PERF_SAMPLE_BRANCH_COUNTERS = 0x80000 + PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x14 + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + PERF_SAMPLE_BRANCH_ABORT_TX = 0x80 + PERF_SAMPLE_BRANCH_IN_TX = 0x100 + PERF_SAMPLE_BRANCH_NO_TX = 0x200 + PERF_SAMPLE_BRANCH_COND = 0x400 + PERF_SAMPLE_BRANCH_CALL_STACK = 0x800 + PERF_SAMPLE_BRANCH_IND_JUMP = 0x1000 + PERF_SAMPLE_BRANCH_CALL = 0x2000 + PERF_SAMPLE_BRANCH_NO_FLAGS = 0x4000 + PERF_SAMPLE_BRANCH_NO_CYCLES = 0x8000 + PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 + PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000 + PERF_SAMPLE_BRANCH_PRIV_SAVE = 0x40000 + PERF_SAMPLE_BRANCH_MAX = 0x100000 + PERF_BR_UNKNOWN = 0x0 + PERF_BR_COND = 0x1 + PERF_BR_UNCOND = 0x2 + PERF_BR_IND = 0x3 + PERF_BR_CALL = 0x4 + PERF_BR_IND_CALL = 0x5 + PERF_BR_RET = 0x6 + PERF_BR_SYSCALL = 0x7 + PERF_BR_SYSRET = 0x8 + PERF_BR_COND_CALL = 0x9 + PERF_BR_COND_RET = 0xa + PERF_BR_ERET = 0xb + PERF_BR_IRQ = 0xc + PERF_BR_SERROR = 0xd + PERF_BR_NO_TX = 0xe + PERF_BR_EXTEND_ABI = 0xf + PERF_BR_MAX = 0x10 + PERF_SAMPLE_REGS_ABI_NONE = 0x0 + PERF_SAMPLE_REGS_ABI_32 = 0x1 + PERF_SAMPLE_REGS_ABI_64 = 0x2 + PERF_TXN_ELISION = 0x1 + PERF_TXN_TRANSACTION = 0x2 + PERF_TXN_SYNC = 0x4 + PERF_TXN_ASYNC = 0x8 + PERF_TXN_RETRY = 0x10 + PERF_TXN_CONFLICT = 0x20 + PERF_TXN_CAPACITY_WRITE = 0x40 + PERF_TXN_CAPACITY_READ = 0x80 + PERF_TXN_MAX = 0x100 + PERF_TXN_ABORT_MASK = -0x100000000 + PERF_TXN_ABORT_SHIFT = 0x20 + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + PERF_FORMAT_LOST = 0x10 + PERF_FORMAT_MAX = 0x20 + PERF_IOC_FLAG_GROUP = 0x1 + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + PERF_RECORD_MMAP2 = 0xa + PERF_RECORD_AUX = 0xb + PERF_RECORD_ITRACE_START = 0xc + PERF_RECORD_LOST_SAMPLES = 0xd + PERF_RECORD_SWITCH = 0xe + PERF_RECORD_SWITCH_CPU_WIDE = 0xf + PERF_RECORD_NAMESPACES = 0x10 + PERF_RECORD_KSYMBOL = 0x11 + PERF_RECORD_BPF_EVENT = 0x12 + PERF_RECORD_CGROUP = 0x13 + PERF_RECORD_TEXT_POKE = 0x14 + PERF_RECORD_AUX_OUTPUT_HW_ID = 0x15 + PERF_RECORD_MAX = 0x16 + PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0x0 + PERF_RECORD_KSYMBOL_TYPE_BPF = 0x1 + PERF_RECORD_KSYMBOL_TYPE_OOL = 0x2 + PERF_RECORD_KSYMBOL_TYPE_MAX = 0x3 + PERF_BPF_EVENT_UNKNOWN = 0x0 + PERF_BPF_EVENT_PROG_LOAD = 0x1 + PERF_BPF_EVENT_PROG_UNLOAD = 0x2 + PERF_BPF_EVENT_MAX = 0x3 + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + PERF_CONTEXT_MAX = -0xfff ) type TCPMD5Sig struct { @@ -1014,7 +1326,7 @@ type TCPMD5Sig struct { Flags uint8 Prefixlen uint8 Keylen uint16 - _ uint32 + Ifindex int32 Key [80]uint8 } @@ -1225,6 +1537,469 @@ const ( SizeofTpacketStatsV3 = 0xc ) +const ( + IFLA_UNSPEC = 0x0 + IFLA_ADDRESS = 0x1 + IFLA_BROADCAST = 0x2 + IFLA_IFNAME = 0x3 + IFLA_MTU = 0x4 + IFLA_LINK = 0x5 + IFLA_QDISC = 0x6 + IFLA_STATS = 0x7 + IFLA_COST = 0x8 + IFLA_PRIORITY = 0x9 + IFLA_MASTER = 0xa + IFLA_WIRELESS = 0xb + IFLA_PROTINFO = 0xc + IFLA_TXQLEN = 0xd + IFLA_MAP = 0xe + IFLA_WEIGHT = 0xf + IFLA_OPERSTATE = 0x10 + IFLA_LINKMODE = 0x11 + IFLA_LINKINFO = 0x12 + IFLA_NET_NS_PID = 0x13 + IFLA_IFALIAS = 0x14 + IFLA_NUM_VF = 0x15 + IFLA_VFINFO_LIST = 0x16 + IFLA_STATS64 = 0x17 + IFLA_VF_PORTS = 0x18 + IFLA_PORT_SELF = 0x19 + IFLA_AF_SPEC = 0x1a + IFLA_GROUP = 0x1b + IFLA_NET_NS_FD = 0x1c + IFLA_EXT_MASK = 0x1d + IFLA_PROMISCUITY = 0x1e + IFLA_NUM_TX_QUEUES = 0x1f + IFLA_NUM_RX_QUEUES = 0x20 + IFLA_CARRIER = 0x21 + IFLA_PHYS_PORT_ID = 0x22 + IFLA_CARRIER_CHANGES = 0x23 + IFLA_PHYS_SWITCH_ID = 0x24 + IFLA_LINK_NETNSID = 0x25 + IFLA_PHYS_PORT_NAME = 0x26 + IFLA_PROTO_DOWN = 0x27 + IFLA_GSO_MAX_SEGS = 0x28 + IFLA_GSO_MAX_SIZE = 0x29 + IFLA_PAD = 0x2a + IFLA_XDP = 0x2b + IFLA_EVENT = 0x2c + IFLA_NEW_NETNSID = 0x2d + IFLA_IF_NETNSID = 0x2e + IFLA_TARGET_NETNSID = 0x2e + IFLA_CARRIER_UP_COUNT = 0x2f + IFLA_CARRIER_DOWN_COUNT = 0x30 + IFLA_NEW_IFINDEX = 0x31 + IFLA_MIN_MTU = 0x32 + IFLA_MAX_MTU = 0x33 + IFLA_PROP_LIST = 0x34 + IFLA_ALT_IFNAME = 0x35 + IFLA_PERM_ADDRESS = 0x36 + IFLA_PROTO_DOWN_REASON = 0x37 + IFLA_PARENT_DEV_NAME = 0x38 + IFLA_PARENT_DEV_BUS_NAME = 0x39 + IFLA_GRO_MAX_SIZE = 0x3a + IFLA_TSO_MAX_SIZE = 0x3b + IFLA_TSO_MAX_SEGS = 0x3c + IFLA_ALLMULTI = 0x3d + IFLA_DEVLINK_PORT = 0x3e + IFLA_GSO_IPV4_MAX_SIZE = 0x3f + IFLA_GRO_IPV4_MAX_SIZE = 0x40 + IFLA_DPLL_PIN = 0x41 + IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0 + IFLA_PROTO_DOWN_REASON_MASK = 0x1 + IFLA_PROTO_DOWN_REASON_VALUE = 0x2 + IFLA_PROTO_DOWN_REASON_MAX = 0x2 + IFLA_INET_UNSPEC = 0x0 + IFLA_INET_CONF = 0x1 + IFLA_INET6_UNSPEC = 0x0 + IFLA_INET6_FLAGS = 0x1 + IFLA_INET6_CONF = 0x2 + IFLA_INET6_STATS = 0x3 + IFLA_INET6_MCAST = 0x4 + IFLA_INET6_CACHEINFO = 0x5 + IFLA_INET6_ICMP6STATS = 0x6 + IFLA_INET6_TOKEN = 0x7 + IFLA_INET6_ADDR_GEN_MODE = 0x8 + IFLA_INET6_RA_MTU = 0x9 + IFLA_BR_UNSPEC = 0x0 + IFLA_BR_FORWARD_DELAY = 0x1 + IFLA_BR_HELLO_TIME = 0x2 + IFLA_BR_MAX_AGE = 0x3 + IFLA_BR_AGEING_TIME = 0x4 + IFLA_BR_STP_STATE = 0x5 + IFLA_BR_PRIORITY = 0x6 + IFLA_BR_VLAN_FILTERING = 0x7 + IFLA_BR_VLAN_PROTOCOL = 0x8 + IFLA_BR_GROUP_FWD_MASK = 0x9 + IFLA_BR_ROOT_ID = 0xa + IFLA_BR_BRIDGE_ID = 0xb + IFLA_BR_ROOT_PORT = 0xc + IFLA_BR_ROOT_PATH_COST = 0xd + IFLA_BR_TOPOLOGY_CHANGE = 0xe + IFLA_BR_TOPOLOGY_CHANGE_DETECTED = 0xf + IFLA_BR_HELLO_TIMER = 0x10 + IFLA_BR_TCN_TIMER = 0x11 + IFLA_BR_TOPOLOGY_CHANGE_TIMER = 0x12 + IFLA_BR_GC_TIMER = 0x13 + IFLA_BR_GROUP_ADDR = 0x14 + IFLA_BR_FDB_FLUSH = 0x15 + IFLA_BR_MCAST_ROUTER = 0x16 + IFLA_BR_MCAST_SNOOPING = 0x17 + IFLA_BR_MCAST_QUERY_USE_IFADDR = 0x18 + IFLA_BR_MCAST_QUERIER = 0x19 + IFLA_BR_MCAST_HASH_ELASTICITY = 0x1a + IFLA_BR_MCAST_HASH_MAX = 0x1b + IFLA_BR_MCAST_LAST_MEMBER_CNT = 0x1c + IFLA_BR_MCAST_STARTUP_QUERY_CNT = 0x1d + IFLA_BR_MCAST_LAST_MEMBER_INTVL = 0x1e + IFLA_BR_MCAST_MEMBERSHIP_INTVL = 0x1f + IFLA_BR_MCAST_QUERIER_INTVL = 0x20 + IFLA_BR_MCAST_QUERY_INTVL = 0x21 + IFLA_BR_MCAST_QUERY_RESPONSE_INTVL = 0x22 + IFLA_BR_MCAST_STARTUP_QUERY_INTVL = 0x23 + IFLA_BR_NF_CALL_IPTABLES = 0x24 + IFLA_BR_NF_CALL_IP6TABLES = 0x25 + IFLA_BR_NF_CALL_ARPTABLES = 0x26 + IFLA_BR_VLAN_DEFAULT_PVID = 0x27 + IFLA_BR_PAD = 0x28 + IFLA_BR_VLAN_STATS_ENABLED = 0x29 + IFLA_BR_MCAST_STATS_ENABLED = 0x2a + IFLA_BR_MCAST_IGMP_VERSION = 0x2b + IFLA_BR_MCAST_MLD_VERSION = 0x2c + IFLA_BR_VLAN_STATS_PER_PORT = 0x2d + IFLA_BR_MULTI_BOOLOPT = 0x2e + IFLA_BR_MCAST_QUERIER_STATE = 0x2f + IFLA_BR_FDB_N_LEARNED = 0x30 + IFLA_BR_FDB_MAX_LEARNED = 0x31 + IFLA_BRPORT_UNSPEC = 0x0 + IFLA_BRPORT_STATE = 0x1 + IFLA_BRPORT_PRIORITY = 0x2 + IFLA_BRPORT_COST = 0x3 + IFLA_BRPORT_MODE = 0x4 + IFLA_BRPORT_GUARD = 0x5 + IFLA_BRPORT_PROTECT = 0x6 + IFLA_BRPORT_FAST_LEAVE = 0x7 + IFLA_BRPORT_LEARNING = 0x8 + IFLA_BRPORT_UNICAST_FLOOD = 0x9 + IFLA_BRPORT_PROXYARP = 0xa + IFLA_BRPORT_LEARNING_SYNC = 0xb + IFLA_BRPORT_PROXYARP_WIFI = 0xc + IFLA_BRPORT_ROOT_ID = 0xd + IFLA_BRPORT_BRIDGE_ID = 0xe + IFLA_BRPORT_DESIGNATED_PORT = 0xf + IFLA_BRPORT_DESIGNATED_COST = 0x10 + IFLA_BRPORT_ID = 0x11 + IFLA_BRPORT_NO = 0x12 + IFLA_BRPORT_TOPOLOGY_CHANGE_ACK = 0x13 + IFLA_BRPORT_CONFIG_PENDING = 0x14 + IFLA_BRPORT_MESSAGE_AGE_TIMER = 0x15 + IFLA_BRPORT_FORWARD_DELAY_TIMER = 0x16 + IFLA_BRPORT_HOLD_TIMER = 0x17 + IFLA_BRPORT_FLUSH = 0x18 + IFLA_BRPORT_MULTICAST_ROUTER = 0x19 + IFLA_BRPORT_PAD = 0x1a + IFLA_BRPORT_MCAST_FLOOD = 0x1b + IFLA_BRPORT_MCAST_TO_UCAST = 0x1c + IFLA_BRPORT_VLAN_TUNNEL = 0x1d + IFLA_BRPORT_BCAST_FLOOD = 0x1e + IFLA_BRPORT_GROUP_FWD_MASK = 0x1f + IFLA_BRPORT_NEIGH_SUPPRESS = 0x20 + IFLA_BRPORT_ISOLATED = 0x21 + IFLA_BRPORT_BACKUP_PORT = 0x22 + IFLA_BRPORT_MRP_RING_OPEN = 0x23 + IFLA_BRPORT_MRP_IN_OPEN = 0x24 + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT = 0x25 + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT = 0x26 + IFLA_BRPORT_LOCKED = 0x27 + IFLA_BRPORT_MAB = 0x28 + IFLA_BRPORT_MCAST_N_GROUPS = 0x29 + IFLA_BRPORT_MCAST_MAX_GROUPS = 0x2a + IFLA_BRPORT_NEIGH_VLAN_SUPPRESS = 0x2b + IFLA_BRPORT_BACKUP_NHID = 0x2c + IFLA_INFO_UNSPEC = 0x0 + IFLA_INFO_KIND = 0x1 + IFLA_INFO_DATA = 0x2 + IFLA_INFO_XSTATS = 0x3 + IFLA_INFO_SLAVE_KIND = 0x4 + IFLA_INFO_SLAVE_DATA = 0x5 + IFLA_VLAN_UNSPEC = 0x0 + IFLA_VLAN_ID = 0x1 + IFLA_VLAN_FLAGS = 0x2 + IFLA_VLAN_EGRESS_QOS = 0x3 + IFLA_VLAN_INGRESS_QOS = 0x4 + IFLA_VLAN_PROTOCOL = 0x5 + IFLA_VLAN_QOS_UNSPEC = 0x0 + IFLA_VLAN_QOS_MAPPING = 0x1 + IFLA_MACVLAN_UNSPEC = 0x0 + IFLA_MACVLAN_MODE = 0x1 + IFLA_MACVLAN_FLAGS = 0x2 + IFLA_MACVLAN_MACADDR_MODE = 0x3 + IFLA_MACVLAN_MACADDR = 0x4 + IFLA_MACVLAN_MACADDR_DATA = 0x5 + IFLA_MACVLAN_MACADDR_COUNT = 0x6 + IFLA_MACVLAN_BC_QUEUE_LEN = 0x7 + IFLA_MACVLAN_BC_QUEUE_LEN_USED = 0x8 + IFLA_MACVLAN_BC_CUTOFF = 0x9 + IFLA_VRF_UNSPEC = 0x0 + IFLA_VRF_TABLE = 0x1 + IFLA_VRF_PORT_UNSPEC = 0x0 + IFLA_VRF_PORT_TABLE = 0x1 + IFLA_MACSEC_UNSPEC = 0x0 + IFLA_MACSEC_SCI = 0x1 + IFLA_MACSEC_PORT = 0x2 + IFLA_MACSEC_ICV_LEN = 0x3 + IFLA_MACSEC_CIPHER_SUITE = 0x4 + IFLA_MACSEC_WINDOW = 0x5 + IFLA_MACSEC_ENCODING_SA = 0x6 + IFLA_MACSEC_ENCRYPT = 0x7 + IFLA_MACSEC_PROTECT = 0x8 + IFLA_MACSEC_INC_SCI = 0x9 + IFLA_MACSEC_ES = 0xa + IFLA_MACSEC_SCB = 0xb + IFLA_MACSEC_REPLAY_PROTECT = 0xc + IFLA_MACSEC_VALIDATION = 0xd + IFLA_MACSEC_PAD = 0xe + IFLA_MACSEC_OFFLOAD = 0xf + IFLA_XFRM_UNSPEC = 0x0 + IFLA_XFRM_LINK = 0x1 + IFLA_XFRM_IF_ID = 0x2 + IFLA_XFRM_COLLECT_METADATA = 0x3 + IFLA_IPVLAN_UNSPEC = 0x0 + IFLA_IPVLAN_MODE = 0x1 + IFLA_IPVLAN_FLAGS = 0x2 + IFLA_NETKIT_UNSPEC = 0x0 + IFLA_NETKIT_PEER_INFO = 0x1 + IFLA_NETKIT_PRIMARY = 0x2 + IFLA_NETKIT_POLICY = 0x3 + IFLA_NETKIT_PEER_POLICY = 0x4 + IFLA_NETKIT_MODE = 0x5 + IFLA_VXLAN_UNSPEC = 0x0 + IFLA_VXLAN_ID = 0x1 + IFLA_VXLAN_GROUP = 0x2 + IFLA_VXLAN_LINK = 0x3 + IFLA_VXLAN_LOCAL = 0x4 + IFLA_VXLAN_TTL = 0x5 + IFLA_VXLAN_TOS = 0x6 + IFLA_VXLAN_LEARNING = 0x7 + IFLA_VXLAN_AGEING = 0x8 + IFLA_VXLAN_LIMIT = 0x9 + IFLA_VXLAN_PORT_RANGE = 0xa + IFLA_VXLAN_PROXY = 0xb + IFLA_VXLAN_RSC = 0xc + IFLA_VXLAN_L2MISS = 0xd + IFLA_VXLAN_L3MISS = 0xe + IFLA_VXLAN_PORT = 0xf + IFLA_VXLAN_GROUP6 = 0x10 + IFLA_VXLAN_LOCAL6 = 0x11 + IFLA_VXLAN_UDP_CSUM = 0x12 + IFLA_VXLAN_UDP_ZERO_CSUM6_TX = 0x13 + IFLA_VXLAN_UDP_ZERO_CSUM6_RX = 0x14 + IFLA_VXLAN_REMCSUM_TX = 0x15 + IFLA_VXLAN_REMCSUM_RX = 0x16 + IFLA_VXLAN_GBP = 0x17 + IFLA_VXLAN_REMCSUM_NOPARTIAL = 0x18 + IFLA_VXLAN_COLLECT_METADATA = 0x19 + IFLA_VXLAN_LABEL = 0x1a + IFLA_VXLAN_GPE = 0x1b + IFLA_VXLAN_TTL_INHERIT = 0x1c + IFLA_VXLAN_DF = 0x1d + IFLA_VXLAN_VNIFILTER = 0x1e + IFLA_VXLAN_LOCALBYPASS = 0x1f + IFLA_VXLAN_LABEL_POLICY = 0x20 + IFLA_GENEVE_UNSPEC = 0x0 + IFLA_GENEVE_ID = 0x1 + IFLA_GENEVE_REMOTE = 0x2 + IFLA_GENEVE_TTL = 0x3 + IFLA_GENEVE_TOS = 0x4 + IFLA_GENEVE_PORT = 0x5 + IFLA_GENEVE_COLLECT_METADATA = 0x6 + IFLA_GENEVE_REMOTE6 = 0x7 + IFLA_GENEVE_UDP_CSUM = 0x8 + IFLA_GENEVE_UDP_ZERO_CSUM6_TX = 0x9 + IFLA_GENEVE_UDP_ZERO_CSUM6_RX = 0xa + IFLA_GENEVE_LABEL = 0xb + IFLA_GENEVE_TTL_INHERIT = 0xc + IFLA_GENEVE_DF = 0xd + IFLA_GENEVE_INNER_PROTO_INHERIT = 0xe + IFLA_BAREUDP_UNSPEC = 0x0 + IFLA_BAREUDP_PORT = 0x1 + IFLA_BAREUDP_ETHERTYPE = 0x2 + IFLA_BAREUDP_SRCPORT_MIN = 0x3 + IFLA_BAREUDP_MULTIPROTO_MODE = 0x4 + IFLA_PPP_UNSPEC = 0x0 + IFLA_PPP_DEV_FD = 0x1 + IFLA_GTP_UNSPEC = 0x0 + IFLA_GTP_FD0 = 0x1 + IFLA_GTP_FD1 = 0x2 + IFLA_GTP_PDP_HASHSIZE = 0x3 + IFLA_GTP_ROLE = 0x4 + IFLA_GTP_CREATE_SOCKETS = 0x5 + IFLA_GTP_RESTART_COUNT = 0x6 + IFLA_GTP_LOCAL = 0x7 + IFLA_GTP_LOCAL6 = 0x8 + IFLA_BOND_UNSPEC = 0x0 + IFLA_BOND_MODE = 0x1 + IFLA_BOND_ACTIVE_SLAVE = 0x2 + IFLA_BOND_MIIMON = 0x3 + IFLA_BOND_UPDELAY = 0x4 + IFLA_BOND_DOWNDELAY = 0x5 + IFLA_BOND_USE_CARRIER = 0x6 + IFLA_BOND_ARP_INTERVAL = 0x7 + IFLA_BOND_ARP_IP_TARGET = 0x8 + IFLA_BOND_ARP_VALIDATE = 0x9 + IFLA_BOND_ARP_ALL_TARGETS = 0xa + IFLA_BOND_PRIMARY = 0xb + IFLA_BOND_PRIMARY_RESELECT = 0xc + IFLA_BOND_FAIL_OVER_MAC = 0xd + IFLA_BOND_XMIT_HASH_POLICY = 0xe + IFLA_BOND_RESEND_IGMP = 0xf + IFLA_BOND_NUM_PEER_NOTIF = 0x10 + IFLA_BOND_ALL_SLAVES_ACTIVE = 0x11 + IFLA_BOND_MIN_LINKS = 0x12 + IFLA_BOND_LP_INTERVAL = 0x13 + IFLA_BOND_PACKETS_PER_SLAVE = 0x14 + IFLA_BOND_AD_LACP_RATE = 0x15 + IFLA_BOND_AD_SELECT = 0x16 + IFLA_BOND_AD_INFO = 0x17 + IFLA_BOND_AD_ACTOR_SYS_PRIO = 0x18 + IFLA_BOND_AD_USER_PORT_KEY = 0x19 + IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a + IFLA_BOND_TLB_DYNAMIC_LB = 0x1b + IFLA_BOND_PEER_NOTIF_DELAY = 0x1c + IFLA_BOND_AD_LACP_ACTIVE = 0x1d + IFLA_BOND_MISSED_MAX = 0x1e + IFLA_BOND_NS_IP6_TARGET = 0x1f + IFLA_BOND_COUPLED_CONTROL = 0x20 + IFLA_BOND_AD_INFO_UNSPEC = 0x0 + IFLA_BOND_AD_INFO_AGGREGATOR = 0x1 + IFLA_BOND_AD_INFO_NUM_PORTS = 0x2 + IFLA_BOND_AD_INFO_ACTOR_KEY = 0x3 + IFLA_BOND_AD_INFO_PARTNER_KEY = 0x4 + IFLA_BOND_AD_INFO_PARTNER_MAC = 0x5 + IFLA_BOND_SLAVE_UNSPEC = 0x0 + IFLA_BOND_SLAVE_STATE = 0x1 + IFLA_BOND_SLAVE_MII_STATUS = 0x2 + IFLA_BOND_SLAVE_LINK_FAILURE_COUNT = 0x3 + IFLA_BOND_SLAVE_PERM_HWADDR = 0x4 + IFLA_BOND_SLAVE_QUEUE_ID = 0x5 + IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6 + IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7 + IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8 + IFLA_BOND_SLAVE_PRIO = 0x9 + IFLA_VF_INFO_UNSPEC = 0x0 + IFLA_VF_INFO = 0x1 + IFLA_VF_UNSPEC = 0x0 + IFLA_VF_MAC = 0x1 + IFLA_VF_VLAN = 0x2 + IFLA_VF_TX_RATE = 0x3 + IFLA_VF_SPOOFCHK = 0x4 + IFLA_VF_LINK_STATE = 0x5 + IFLA_VF_RATE = 0x6 + IFLA_VF_RSS_QUERY_EN = 0x7 + IFLA_VF_STATS = 0x8 + IFLA_VF_TRUST = 0x9 + IFLA_VF_IB_NODE_GUID = 0xa + IFLA_VF_IB_PORT_GUID = 0xb + IFLA_VF_VLAN_LIST = 0xc + IFLA_VF_BROADCAST = 0xd + IFLA_VF_VLAN_INFO_UNSPEC = 0x0 + IFLA_VF_VLAN_INFO = 0x1 + IFLA_VF_LINK_STATE_AUTO = 0x0 + IFLA_VF_LINK_STATE_ENABLE = 0x1 + IFLA_VF_LINK_STATE_DISABLE = 0x2 + IFLA_VF_STATS_RX_PACKETS = 0x0 + IFLA_VF_STATS_TX_PACKETS = 0x1 + IFLA_VF_STATS_RX_BYTES = 0x2 + IFLA_VF_STATS_TX_BYTES = 0x3 + IFLA_VF_STATS_BROADCAST = 0x4 + IFLA_VF_STATS_MULTICAST = 0x5 + IFLA_VF_STATS_PAD = 0x6 + IFLA_VF_STATS_RX_DROPPED = 0x7 + IFLA_VF_STATS_TX_DROPPED = 0x8 + IFLA_VF_PORT_UNSPEC = 0x0 + IFLA_VF_PORT = 0x1 + IFLA_PORT_UNSPEC = 0x0 + IFLA_PORT_VF = 0x1 + IFLA_PORT_PROFILE = 0x2 + IFLA_PORT_VSI_TYPE = 0x3 + IFLA_PORT_INSTANCE_UUID = 0x4 + IFLA_PORT_HOST_UUID = 0x5 + IFLA_PORT_REQUEST = 0x6 + IFLA_PORT_RESPONSE = 0x7 + IFLA_IPOIB_UNSPEC = 0x0 + IFLA_IPOIB_PKEY = 0x1 + IFLA_IPOIB_MODE = 0x2 + IFLA_IPOIB_UMCAST = 0x3 + IFLA_HSR_UNSPEC = 0x0 + IFLA_HSR_SLAVE1 = 0x1 + IFLA_HSR_SLAVE2 = 0x2 + IFLA_HSR_MULTICAST_SPEC = 0x3 + IFLA_HSR_SUPERVISION_ADDR = 0x4 + IFLA_HSR_SEQ_NR = 0x5 + IFLA_HSR_VERSION = 0x6 + IFLA_HSR_PROTOCOL = 0x7 + IFLA_HSR_INTERLINK = 0x8 + IFLA_STATS_UNSPEC = 0x0 + IFLA_STATS_LINK_64 = 0x1 + IFLA_STATS_LINK_XSTATS = 0x2 + IFLA_STATS_LINK_XSTATS_SLAVE = 0x3 + IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4 + IFLA_STATS_AF_SPEC = 0x5 + IFLA_STATS_GETSET_UNSPEC = 0x0 + IFLA_STATS_GET_FILTERS = 0x1 + IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS = 0x2 + IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0 + IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1 + IFLA_OFFLOAD_XSTATS_HW_S_INFO = 0x2 + IFLA_OFFLOAD_XSTATS_L3_STATS = 0x3 + IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC = 0x0 + IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST = 0x1 + IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED = 0x2 + IFLA_XDP_UNSPEC = 0x0 + IFLA_XDP_FD = 0x1 + IFLA_XDP_ATTACHED = 0x2 + IFLA_XDP_FLAGS = 0x3 + IFLA_XDP_PROG_ID = 0x4 + IFLA_XDP_DRV_PROG_ID = 0x5 + IFLA_XDP_SKB_PROG_ID = 0x6 + IFLA_XDP_HW_PROG_ID = 0x7 + IFLA_XDP_EXPECTED_FD = 0x8 + IFLA_EVENT_NONE = 0x0 + IFLA_EVENT_REBOOT = 0x1 + IFLA_EVENT_FEATURES = 0x2 + IFLA_EVENT_BONDING_FAILOVER = 0x3 + IFLA_EVENT_NOTIFY_PEERS = 0x4 + IFLA_EVENT_IGMP_RESEND = 0x5 + IFLA_EVENT_BONDING_OPTIONS = 0x6 + IFLA_TUN_UNSPEC = 0x0 + IFLA_TUN_OWNER = 0x1 + IFLA_TUN_GROUP = 0x2 + IFLA_TUN_TYPE = 0x3 + IFLA_TUN_PI = 0x4 + IFLA_TUN_VNET_HDR = 0x5 + IFLA_TUN_PERSIST = 0x6 + IFLA_TUN_MULTI_QUEUE = 0x7 + IFLA_TUN_NUM_QUEUES = 0x8 + IFLA_TUN_NUM_DISABLED_QUEUES = 0x9 + IFLA_RMNET_UNSPEC = 0x0 + IFLA_RMNET_MUX_ID = 0x1 + IFLA_RMNET_FLAGS = 0x2 + IFLA_MCTP_UNSPEC = 0x0 + IFLA_MCTP_NET = 0x1 + IFLA_DSA_UNSPEC = 0x0 + IFLA_DSA_CONDUIT = 0x1 + IFLA_DSA_MASTER = 0x1 +) + +const ( + NETKIT_NEXT = -0x1 + NETKIT_PASS = 0x0 + NETKIT_DROP = 0x2 + NETKIT_REDIRECT = 0x7 + NETKIT_L2 = 0x0 + NETKIT_L3 = 0x1 +) + const ( NF_INET_PRE_ROUTING = 0x0 NF_INET_LOCAL_IN = 0x1 @@ -1236,7 +2011,8 @@ const ( const ( NF_NETDEV_INGRESS = 0x0 - NF_NETDEV_NUMHOOKS = 0x1 + NF_NETDEV_EGRESS = 0x1 + NF_NETDEV_NUMHOOKS = 0x2 ) const ( @@ -1251,6 +2027,8 @@ const ( NFPROTO_NUMPROTO = 0xd ) +const SO_ORIGINAL_DST = 0x50 + type Nfgenmsg struct { Nfgen_family uint8 Version uint8 @@ -1311,8 +2089,12 @@ const ( NFT_MSG_GETOBJ = 0x13 NFT_MSG_DELOBJ = 0x14 NFT_MSG_GETOBJ_RESET = 0x15 - NFT_MSG_MAX = 0x19 - NFTA_LIST_UNPEC = 0x0 + NFT_MSG_NEWFLOWTABLE = 0x16 + NFT_MSG_GETFLOWTABLE = 0x17 + NFT_MSG_DELFLOWTABLE = 0x18 + NFT_MSG_GETRULE_RESET = 0x19 + NFT_MSG_MAX = 0x22 + NFTA_LIST_UNSPEC = 0x0 NFTA_LIST_ELEM = 0x1 NFTA_HOOK_UNSPEC = 0x0 NFTA_HOOK_HOOKNUM = 0x1 @@ -1459,8 +2241,11 @@ const ( NFT_PAYLOAD_LL_HEADER = 0x0 NFT_PAYLOAD_NETWORK_HEADER = 0x1 NFT_PAYLOAD_TRANSPORT_HEADER = 0x2 + NFT_PAYLOAD_INNER_HEADER = 0x3 + NFT_PAYLOAD_TUN_HEADER = 0x4 NFT_PAYLOAD_CSUM_NONE = 0x0 NFT_PAYLOAD_CSUM_INET = 0x1 + NFT_PAYLOAD_CSUM_SCTP = 0x2 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1 NFTA_PAYLOAD_UNSPEC = 0x0 NFTA_PAYLOAD_DREG = 0x1 @@ -1547,6 +2332,11 @@ const ( NFT_CT_AVGPKT = 0x10 NFT_CT_ZONE = 0x11 NFT_CT_EVENTMASK = 0x12 + NFT_CT_SRC_IP = 0x13 + NFT_CT_DST_IP = 0x14 + NFT_CT_SRC_IP6 = 0x15 + NFT_CT_DST_IP6 = 0x16 + NFT_CT_ID = 0x17 NFTA_CT_UNSPEC = 0x0 NFTA_CT_DREG = 0x1 NFTA_CT_KEY = 0x2 @@ -1683,6 +2473,21 @@ const ( NFT_NG_RANDOM = 0x1 ) +const ( + NFTA_TARGET_UNSPEC = 0x0 + NFTA_TARGET_NAME = 0x1 + NFTA_TARGET_REV = 0x2 + NFTA_TARGET_INFO = 0x3 + NFTA_MATCH_UNSPEC = 0x0 + NFTA_MATCH_NAME = 0x1 + NFTA_MATCH_REV = 0x2 + NFTA_MATCH_INFO = 0x3 + NFTA_COMPAT_UNSPEC = 0x0 + NFTA_COMPAT_NAME = 0x1 + NFTA_COMPAT_REV = 0x2 + NFTA_COMPAT_TYPE = 0x3 +) + type RTCTime struct { Sec int32 Min int32 @@ -1715,10 +2520,12 @@ const ( ) const ( - NETNSA_NONE = 0x0 - NETNSA_NSID = 0x1 - NETNSA_PID = 0x2 - NETNSA_FD = 0x3 + NETNSA_NONE = 0x0 + NETNSA_NSID = 0x1 + NETNSA_PID = 0x2 + NETNSA_FD = 0x3 + NETNSA_TARGET_NSID = 0x4 + NETNSA_CURRENT_NSID = 0x5 ) type XDPRingOffset struct { @@ -1735,10 +2542,22 @@ type XDPMmapOffsets struct { Cr XDPRingOffset } +type XDPUmemReg struct { + Addr uint64 + Len uint64 + Size uint32 + Headroom uint32 + Flags uint32 + Tx_metadata_len uint32 +} + type XDPStatistics struct { - Rx_dropped uint64 - Rx_invalid_descs uint64 - Tx_invalid_descs uint64 + Rx_dropped uint64 + Rx_invalid_descs uint64 + Tx_invalid_descs uint64 + Rx_ring_full uint64 + Rx_fill_ring_empty_descs uint64 + Tx_ring_empty_descs uint64 } type XDPDesc struct { @@ -1795,9 +2614,11 @@ const ( SOF_TIMESTAMPING_OPT_STATS = 0x1000 SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 + SOF_TIMESTAMPING_BIND_PHC = 0x8000 + SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x4000 - SOF_TIMESTAMPING_MASK = 0x7fff + SOF_TIMESTAMPING_LAST = 0x40000 + SOF_TIMESTAMPING_MASK = 0x7ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -1865,178 +2686,401 @@ const ( ) const ( - BPF_REG_0 = 0x0 - BPF_REG_1 = 0x1 - BPF_REG_2 = 0x2 - BPF_REG_3 = 0x3 - BPF_REG_4 = 0x4 - BPF_REG_5 = 0x5 - BPF_REG_6 = 0x6 - BPF_REG_7 = 0x7 - BPF_REG_8 = 0x8 - BPF_REG_9 = 0x9 - BPF_REG_10 = 0xa - BPF_MAP_CREATE = 0x0 - BPF_MAP_LOOKUP_ELEM = 0x1 - BPF_MAP_UPDATE_ELEM = 0x2 - BPF_MAP_DELETE_ELEM = 0x3 - BPF_MAP_GET_NEXT_KEY = 0x4 - BPF_PROG_LOAD = 0x5 - BPF_OBJ_PIN = 0x6 - BPF_OBJ_GET = 0x7 - BPF_PROG_ATTACH = 0x8 - BPF_PROG_DETACH = 0x9 - BPF_PROG_TEST_RUN = 0xa - BPF_PROG_GET_NEXT_ID = 0xb - BPF_MAP_GET_NEXT_ID = 0xc - BPF_PROG_GET_FD_BY_ID = 0xd - BPF_MAP_GET_FD_BY_ID = 0xe - BPF_OBJ_GET_INFO_BY_FD = 0xf - BPF_PROG_QUERY = 0x10 - BPF_RAW_TRACEPOINT_OPEN = 0x11 - BPF_BTF_LOAD = 0x12 - BPF_BTF_GET_FD_BY_ID = 0x13 - BPF_TASK_FD_QUERY = 0x14 - BPF_MAP_LOOKUP_AND_DELETE_ELEM = 0x15 - BPF_MAP_FREEZE = 0x16 - BPF_BTF_GET_NEXT_ID = 0x17 - BPF_MAP_TYPE_UNSPEC = 0x0 - BPF_MAP_TYPE_HASH = 0x1 - BPF_MAP_TYPE_ARRAY = 0x2 - BPF_MAP_TYPE_PROG_ARRAY = 0x3 - BPF_MAP_TYPE_PERF_EVENT_ARRAY = 0x4 - BPF_MAP_TYPE_PERCPU_HASH = 0x5 - BPF_MAP_TYPE_PERCPU_ARRAY = 0x6 - BPF_MAP_TYPE_STACK_TRACE = 0x7 - BPF_MAP_TYPE_CGROUP_ARRAY = 0x8 - BPF_MAP_TYPE_LRU_HASH = 0x9 - BPF_MAP_TYPE_LRU_PERCPU_HASH = 0xa - BPF_MAP_TYPE_LPM_TRIE = 0xb - BPF_MAP_TYPE_ARRAY_OF_MAPS = 0xc - BPF_MAP_TYPE_HASH_OF_MAPS = 0xd - BPF_MAP_TYPE_DEVMAP = 0xe - BPF_MAP_TYPE_SOCKMAP = 0xf - BPF_MAP_TYPE_CPUMAP = 0x10 - BPF_MAP_TYPE_XSKMAP = 0x11 - BPF_MAP_TYPE_SOCKHASH = 0x12 - BPF_MAP_TYPE_CGROUP_STORAGE = 0x13 - BPF_MAP_TYPE_REUSEPORT_SOCKARRAY = 0x14 - BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE = 0x15 - BPF_MAP_TYPE_QUEUE = 0x16 - BPF_MAP_TYPE_STACK = 0x17 - BPF_MAP_TYPE_SK_STORAGE = 0x18 - BPF_MAP_TYPE_DEVMAP_HASH = 0x19 - BPF_PROG_TYPE_UNSPEC = 0x0 - BPF_PROG_TYPE_SOCKET_FILTER = 0x1 - BPF_PROG_TYPE_KPROBE = 0x2 - BPF_PROG_TYPE_SCHED_CLS = 0x3 - BPF_PROG_TYPE_SCHED_ACT = 0x4 - BPF_PROG_TYPE_TRACEPOINT = 0x5 - BPF_PROG_TYPE_XDP = 0x6 - BPF_PROG_TYPE_PERF_EVENT = 0x7 - BPF_PROG_TYPE_CGROUP_SKB = 0x8 - BPF_PROG_TYPE_CGROUP_SOCK = 0x9 - BPF_PROG_TYPE_LWT_IN = 0xa - BPF_PROG_TYPE_LWT_OUT = 0xb - BPF_PROG_TYPE_LWT_XMIT = 0xc - BPF_PROG_TYPE_SOCK_OPS = 0xd - BPF_PROG_TYPE_SK_SKB = 0xe - BPF_PROG_TYPE_CGROUP_DEVICE = 0xf - BPF_PROG_TYPE_SK_MSG = 0x10 - BPF_PROG_TYPE_RAW_TRACEPOINT = 0x11 - BPF_PROG_TYPE_CGROUP_SOCK_ADDR = 0x12 - BPF_PROG_TYPE_LWT_SEG6LOCAL = 0x13 - BPF_PROG_TYPE_LIRC_MODE2 = 0x14 - BPF_PROG_TYPE_SK_REUSEPORT = 0x15 - BPF_PROG_TYPE_FLOW_DISSECTOR = 0x16 - BPF_PROG_TYPE_CGROUP_SYSCTL = 0x17 - BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE = 0x18 - BPF_PROG_TYPE_CGROUP_SOCKOPT = 0x19 - BPF_PROG_TYPE_TRACING = 0x1a - BPF_CGROUP_INET_INGRESS = 0x0 - BPF_CGROUP_INET_EGRESS = 0x1 - BPF_CGROUP_INET_SOCK_CREATE = 0x2 - BPF_CGROUP_SOCK_OPS = 0x3 - BPF_SK_SKB_STREAM_PARSER = 0x4 - BPF_SK_SKB_STREAM_VERDICT = 0x5 - BPF_CGROUP_DEVICE = 0x6 - BPF_SK_MSG_VERDICT = 0x7 - BPF_CGROUP_INET4_BIND = 0x8 - BPF_CGROUP_INET6_BIND = 0x9 - BPF_CGROUP_INET4_CONNECT = 0xa - BPF_CGROUP_INET6_CONNECT = 0xb - BPF_CGROUP_INET4_POST_BIND = 0xc - BPF_CGROUP_INET6_POST_BIND = 0xd - BPF_CGROUP_UDP4_SENDMSG = 0xe - BPF_CGROUP_UDP6_SENDMSG = 0xf - BPF_LIRC_MODE2 = 0x10 - BPF_FLOW_DISSECTOR = 0x11 - BPF_CGROUP_SYSCTL = 0x12 - BPF_CGROUP_UDP4_RECVMSG = 0x13 - BPF_CGROUP_UDP6_RECVMSG = 0x14 - BPF_CGROUP_GETSOCKOPT = 0x15 - BPF_CGROUP_SETSOCKOPT = 0x16 - BPF_TRACE_RAW_TP = 0x17 - BPF_TRACE_FENTRY = 0x18 - BPF_TRACE_FEXIT = 0x19 - BPF_STACK_BUILD_ID_EMPTY = 0x0 - BPF_STACK_BUILD_ID_VALID = 0x1 - BPF_STACK_BUILD_ID_IP = 0x2 - BPF_ADJ_ROOM_NET = 0x0 - BPF_ADJ_ROOM_MAC = 0x1 - BPF_HDR_START_MAC = 0x0 - BPF_HDR_START_NET = 0x1 - BPF_LWT_ENCAP_SEG6 = 0x0 - BPF_LWT_ENCAP_SEG6_INLINE = 0x1 - BPF_LWT_ENCAP_IP = 0x2 - BPF_OK = 0x0 - BPF_DROP = 0x2 - BPF_REDIRECT = 0x7 - BPF_LWT_REROUTE = 0x80 - BPF_SOCK_OPS_VOID = 0x0 - BPF_SOCK_OPS_TIMEOUT_INIT = 0x1 - BPF_SOCK_OPS_RWND_INIT = 0x2 - BPF_SOCK_OPS_TCP_CONNECT_CB = 0x3 - BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB = 0x4 - BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB = 0x5 - BPF_SOCK_OPS_NEEDS_ECN = 0x6 - BPF_SOCK_OPS_BASE_RTT = 0x7 - BPF_SOCK_OPS_RTO_CB = 0x8 - BPF_SOCK_OPS_RETRANS_CB = 0x9 - BPF_SOCK_OPS_STATE_CB = 0xa - BPF_SOCK_OPS_TCP_LISTEN_CB = 0xb - BPF_SOCK_OPS_RTT_CB = 0xc - BPF_TCP_ESTABLISHED = 0x1 - BPF_TCP_SYN_SENT = 0x2 - BPF_TCP_SYN_RECV = 0x3 - BPF_TCP_FIN_WAIT1 = 0x4 - BPF_TCP_FIN_WAIT2 = 0x5 - BPF_TCP_TIME_WAIT = 0x6 - BPF_TCP_CLOSE = 0x7 - BPF_TCP_CLOSE_WAIT = 0x8 - BPF_TCP_LAST_ACK = 0x9 - BPF_TCP_LISTEN = 0xa - BPF_TCP_CLOSING = 0xb - BPF_TCP_NEW_SYN_RECV = 0xc - BPF_TCP_MAX_STATES = 0xd - BPF_FIB_LKUP_RET_SUCCESS = 0x0 - BPF_FIB_LKUP_RET_BLACKHOLE = 0x1 - BPF_FIB_LKUP_RET_UNREACHABLE = 0x2 - BPF_FIB_LKUP_RET_PROHIBIT = 0x3 - BPF_FIB_LKUP_RET_NOT_FWDED = 0x4 - BPF_FIB_LKUP_RET_FWD_DISABLED = 0x5 - BPF_FIB_LKUP_RET_UNSUPP_LWT = 0x6 - BPF_FIB_LKUP_RET_NO_NEIGH = 0x7 - BPF_FIB_LKUP_RET_FRAG_NEEDED = 0x8 - BPF_FD_TYPE_RAW_TRACEPOINT = 0x0 - BPF_FD_TYPE_TRACEPOINT = 0x1 - BPF_FD_TYPE_KPROBE = 0x2 - BPF_FD_TYPE_KRETPROBE = 0x3 - BPF_FD_TYPE_UPROBE = 0x4 - BPF_FD_TYPE_URETPROBE = 0x5 + BPF_REG_0 = 0x0 + BPF_REG_1 = 0x1 + BPF_REG_2 = 0x2 + BPF_REG_3 = 0x3 + BPF_REG_4 = 0x4 + BPF_REG_5 = 0x5 + BPF_REG_6 = 0x6 + BPF_REG_7 = 0x7 + BPF_REG_8 = 0x8 + BPF_REG_9 = 0x9 + BPF_REG_10 = 0xa + BPF_CGROUP_ITER_ORDER_UNSPEC = 0x0 + BPF_CGROUP_ITER_SELF_ONLY = 0x1 + BPF_CGROUP_ITER_DESCENDANTS_PRE = 0x2 + BPF_CGROUP_ITER_DESCENDANTS_POST = 0x3 + BPF_CGROUP_ITER_ANCESTORS_UP = 0x4 + BPF_MAP_CREATE = 0x0 + BPF_MAP_LOOKUP_ELEM = 0x1 + BPF_MAP_UPDATE_ELEM = 0x2 + BPF_MAP_DELETE_ELEM = 0x3 + BPF_MAP_GET_NEXT_KEY = 0x4 + BPF_PROG_LOAD = 0x5 + BPF_OBJ_PIN = 0x6 + BPF_OBJ_GET = 0x7 + BPF_PROG_ATTACH = 0x8 + BPF_PROG_DETACH = 0x9 + BPF_PROG_TEST_RUN = 0xa + BPF_PROG_RUN = 0xa + BPF_PROG_GET_NEXT_ID = 0xb + BPF_MAP_GET_NEXT_ID = 0xc + BPF_PROG_GET_FD_BY_ID = 0xd + BPF_MAP_GET_FD_BY_ID = 0xe + BPF_OBJ_GET_INFO_BY_FD = 0xf + BPF_PROG_QUERY = 0x10 + BPF_RAW_TRACEPOINT_OPEN = 0x11 + BPF_BTF_LOAD = 0x12 + BPF_BTF_GET_FD_BY_ID = 0x13 + BPF_TASK_FD_QUERY = 0x14 + BPF_MAP_LOOKUP_AND_DELETE_ELEM = 0x15 + BPF_MAP_FREEZE = 0x16 + BPF_BTF_GET_NEXT_ID = 0x17 + BPF_MAP_LOOKUP_BATCH = 0x18 + BPF_MAP_LOOKUP_AND_DELETE_BATCH = 0x19 + BPF_MAP_UPDATE_BATCH = 0x1a + BPF_MAP_DELETE_BATCH = 0x1b + BPF_LINK_CREATE = 0x1c + BPF_LINK_UPDATE = 0x1d + BPF_LINK_GET_FD_BY_ID = 0x1e + BPF_LINK_GET_NEXT_ID = 0x1f + BPF_ENABLE_STATS = 0x20 + BPF_ITER_CREATE = 0x21 + BPF_LINK_DETACH = 0x22 + BPF_PROG_BIND_MAP = 0x23 + BPF_MAP_TYPE_UNSPEC = 0x0 + BPF_MAP_TYPE_HASH = 0x1 + BPF_MAP_TYPE_ARRAY = 0x2 + BPF_MAP_TYPE_PROG_ARRAY = 0x3 + BPF_MAP_TYPE_PERF_EVENT_ARRAY = 0x4 + BPF_MAP_TYPE_PERCPU_HASH = 0x5 + BPF_MAP_TYPE_PERCPU_ARRAY = 0x6 + BPF_MAP_TYPE_STACK_TRACE = 0x7 + BPF_MAP_TYPE_CGROUP_ARRAY = 0x8 + BPF_MAP_TYPE_LRU_HASH = 0x9 + BPF_MAP_TYPE_LRU_PERCPU_HASH = 0xa + BPF_MAP_TYPE_LPM_TRIE = 0xb + BPF_MAP_TYPE_ARRAY_OF_MAPS = 0xc + BPF_MAP_TYPE_HASH_OF_MAPS = 0xd + BPF_MAP_TYPE_DEVMAP = 0xe + BPF_MAP_TYPE_SOCKMAP = 0xf + BPF_MAP_TYPE_CPUMAP = 0x10 + BPF_MAP_TYPE_XSKMAP = 0x11 + BPF_MAP_TYPE_SOCKHASH = 0x12 + BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED = 0x13 + BPF_MAP_TYPE_CGROUP_STORAGE = 0x13 + BPF_MAP_TYPE_REUSEPORT_SOCKARRAY = 0x14 + BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE = 0x15 + BPF_MAP_TYPE_QUEUE = 0x16 + BPF_MAP_TYPE_STACK = 0x17 + BPF_MAP_TYPE_SK_STORAGE = 0x18 + BPF_MAP_TYPE_DEVMAP_HASH = 0x19 + BPF_MAP_TYPE_STRUCT_OPS = 0x1a + BPF_MAP_TYPE_RINGBUF = 0x1b + BPF_MAP_TYPE_INODE_STORAGE = 0x1c + BPF_MAP_TYPE_TASK_STORAGE = 0x1d + BPF_MAP_TYPE_BLOOM_FILTER = 0x1e + BPF_MAP_TYPE_USER_RINGBUF = 0x1f + BPF_MAP_TYPE_CGRP_STORAGE = 0x20 + BPF_PROG_TYPE_UNSPEC = 0x0 + BPF_PROG_TYPE_SOCKET_FILTER = 0x1 + BPF_PROG_TYPE_KPROBE = 0x2 + BPF_PROG_TYPE_SCHED_CLS = 0x3 + BPF_PROG_TYPE_SCHED_ACT = 0x4 + BPF_PROG_TYPE_TRACEPOINT = 0x5 + BPF_PROG_TYPE_XDP = 0x6 + BPF_PROG_TYPE_PERF_EVENT = 0x7 + BPF_PROG_TYPE_CGROUP_SKB = 0x8 + BPF_PROG_TYPE_CGROUP_SOCK = 0x9 + BPF_PROG_TYPE_LWT_IN = 0xa + BPF_PROG_TYPE_LWT_OUT = 0xb + BPF_PROG_TYPE_LWT_XMIT = 0xc + BPF_PROG_TYPE_SOCK_OPS = 0xd + BPF_PROG_TYPE_SK_SKB = 0xe + BPF_PROG_TYPE_CGROUP_DEVICE = 0xf + BPF_PROG_TYPE_SK_MSG = 0x10 + BPF_PROG_TYPE_RAW_TRACEPOINT = 0x11 + BPF_PROG_TYPE_CGROUP_SOCK_ADDR = 0x12 + BPF_PROG_TYPE_LWT_SEG6LOCAL = 0x13 + BPF_PROG_TYPE_LIRC_MODE2 = 0x14 + BPF_PROG_TYPE_SK_REUSEPORT = 0x15 + BPF_PROG_TYPE_FLOW_DISSECTOR = 0x16 + BPF_PROG_TYPE_CGROUP_SYSCTL = 0x17 + BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE = 0x18 + BPF_PROG_TYPE_CGROUP_SOCKOPT = 0x19 + BPF_PROG_TYPE_TRACING = 0x1a + BPF_PROG_TYPE_STRUCT_OPS = 0x1b + BPF_PROG_TYPE_EXT = 0x1c + BPF_PROG_TYPE_LSM = 0x1d + BPF_PROG_TYPE_SK_LOOKUP = 0x1e + BPF_PROG_TYPE_SYSCALL = 0x1f + BPF_PROG_TYPE_NETFILTER = 0x20 + BPF_CGROUP_INET_INGRESS = 0x0 + BPF_CGROUP_INET_EGRESS = 0x1 + BPF_CGROUP_INET_SOCK_CREATE = 0x2 + BPF_CGROUP_SOCK_OPS = 0x3 + BPF_SK_SKB_STREAM_PARSER = 0x4 + BPF_SK_SKB_STREAM_VERDICT = 0x5 + BPF_CGROUP_DEVICE = 0x6 + BPF_SK_MSG_VERDICT = 0x7 + BPF_CGROUP_INET4_BIND = 0x8 + BPF_CGROUP_INET6_BIND = 0x9 + BPF_CGROUP_INET4_CONNECT = 0xa + BPF_CGROUP_INET6_CONNECT = 0xb + BPF_CGROUP_INET4_POST_BIND = 0xc + BPF_CGROUP_INET6_POST_BIND = 0xd + BPF_CGROUP_UDP4_SENDMSG = 0xe + BPF_CGROUP_UDP6_SENDMSG = 0xf + BPF_LIRC_MODE2 = 0x10 + BPF_FLOW_DISSECTOR = 0x11 + BPF_CGROUP_SYSCTL = 0x12 + BPF_CGROUP_UDP4_RECVMSG = 0x13 + BPF_CGROUP_UDP6_RECVMSG = 0x14 + BPF_CGROUP_GETSOCKOPT = 0x15 + BPF_CGROUP_SETSOCKOPT = 0x16 + BPF_TRACE_RAW_TP = 0x17 + BPF_TRACE_FENTRY = 0x18 + BPF_TRACE_FEXIT = 0x19 + BPF_MODIFY_RETURN = 0x1a + BPF_LSM_MAC = 0x1b + BPF_TRACE_ITER = 0x1c + BPF_CGROUP_INET4_GETPEERNAME = 0x1d + BPF_CGROUP_INET6_GETPEERNAME = 0x1e + BPF_CGROUP_INET4_GETSOCKNAME = 0x1f + BPF_CGROUP_INET6_GETSOCKNAME = 0x20 + BPF_XDP_DEVMAP = 0x21 + BPF_CGROUP_INET_SOCK_RELEASE = 0x22 + BPF_XDP_CPUMAP = 0x23 + BPF_SK_LOOKUP = 0x24 + BPF_XDP = 0x25 + BPF_SK_SKB_VERDICT = 0x26 + BPF_SK_REUSEPORT_SELECT = 0x27 + BPF_SK_REUSEPORT_SELECT_OR_MIGRATE = 0x28 + BPF_PERF_EVENT = 0x29 + BPF_TRACE_KPROBE_MULTI = 0x2a + BPF_LSM_CGROUP = 0x2b + BPF_STRUCT_OPS = 0x2c + BPF_NETFILTER = 0x2d + BPF_TCX_INGRESS = 0x2e + BPF_TCX_EGRESS = 0x2f + BPF_TRACE_UPROBE_MULTI = 0x30 + BPF_LINK_TYPE_UNSPEC = 0x0 + BPF_LINK_TYPE_RAW_TRACEPOINT = 0x1 + BPF_LINK_TYPE_TRACING = 0x2 + BPF_LINK_TYPE_CGROUP = 0x3 + BPF_LINK_TYPE_ITER = 0x4 + BPF_LINK_TYPE_NETNS = 0x5 + BPF_LINK_TYPE_XDP = 0x6 + BPF_LINK_TYPE_PERF_EVENT = 0x7 + BPF_LINK_TYPE_KPROBE_MULTI = 0x8 + BPF_LINK_TYPE_STRUCT_OPS = 0x9 + BPF_LINK_TYPE_NETFILTER = 0xa + BPF_LINK_TYPE_TCX = 0xb + BPF_LINK_TYPE_UPROBE_MULTI = 0xc + BPF_PERF_EVENT_UNSPEC = 0x0 + BPF_PERF_EVENT_UPROBE = 0x1 + BPF_PERF_EVENT_URETPROBE = 0x2 + BPF_PERF_EVENT_KPROBE = 0x3 + BPF_PERF_EVENT_KRETPROBE = 0x4 + BPF_PERF_EVENT_TRACEPOINT = 0x5 + BPF_PERF_EVENT_EVENT = 0x6 + BPF_F_KPROBE_MULTI_RETURN = 0x1 + BPF_F_UPROBE_MULTI_RETURN = 0x1 + BPF_ANY = 0x0 + BPF_NOEXIST = 0x1 + BPF_EXIST = 0x2 + BPF_F_LOCK = 0x4 + BPF_F_NO_PREALLOC = 0x1 + BPF_F_NO_COMMON_LRU = 0x2 + BPF_F_NUMA_NODE = 0x4 + BPF_F_RDONLY = 0x8 + BPF_F_WRONLY = 0x10 + BPF_F_STACK_BUILD_ID = 0x20 + BPF_F_ZERO_SEED = 0x40 + BPF_F_RDONLY_PROG = 0x80 + BPF_F_WRONLY_PROG = 0x100 + BPF_F_CLONE = 0x200 + BPF_F_MMAPABLE = 0x400 + BPF_F_PRESERVE_ELEMS = 0x800 + BPF_F_INNER_MAP = 0x1000 + BPF_F_LINK = 0x2000 + BPF_F_PATH_FD = 0x4000 + BPF_STATS_RUN_TIME = 0x0 + BPF_STACK_BUILD_ID_EMPTY = 0x0 + BPF_STACK_BUILD_ID_VALID = 0x1 + BPF_STACK_BUILD_ID_IP = 0x2 + BPF_F_RECOMPUTE_CSUM = 0x1 + BPF_F_INVALIDATE_HASH = 0x2 + BPF_F_HDR_FIELD_MASK = 0xf + BPF_F_PSEUDO_HDR = 0x10 + BPF_F_MARK_MANGLED_0 = 0x20 + BPF_F_MARK_ENFORCE = 0x40 + BPF_F_INGRESS = 0x1 + BPF_F_TUNINFO_IPV6 = 0x1 + BPF_F_SKIP_FIELD_MASK = 0xff + BPF_F_USER_STACK = 0x100 + BPF_F_FAST_STACK_CMP = 0x200 + BPF_F_REUSE_STACKID = 0x400 + BPF_F_USER_BUILD_ID = 0x800 + BPF_F_ZERO_CSUM_TX = 0x2 + BPF_F_DONT_FRAGMENT = 0x4 + BPF_F_SEQ_NUMBER = 0x8 + BPF_F_NO_TUNNEL_KEY = 0x10 + BPF_F_TUNINFO_FLAGS = 0x10 + BPF_F_INDEX_MASK = 0xffffffff + BPF_F_CURRENT_CPU = 0xffffffff + BPF_F_CTXLEN_MASK = 0xfffff00000000 + BPF_F_CURRENT_NETNS = -0x1 + BPF_CSUM_LEVEL_QUERY = 0x0 + BPF_CSUM_LEVEL_INC = 0x1 + BPF_CSUM_LEVEL_DEC = 0x2 + BPF_CSUM_LEVEL_RESET = 0x3 + BPF_F_ADJ_ROOM_FIXED_GSO = 0x1 + BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = 0x2 + BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = 0x4 + BPF_F_ADJ_ROOM_ENCAP_L4_GRE = 0x8 + BPF_F_ADJ_ROOM_ENCAP_L4_UDP = 0x10 + BPF_F_ADJ_ROOM_NO_CSUM_RESET = 0x20 + BPF_F_ADJ_ROOM_ENCAP_L2_ETH = 0x40 + BPF_F_ADJ_ROOM_DECAP_L3_IPV4 = 0x80 + BPF_F_ADJ_ROOM_DECAP_L3_IPV6 = 0x100 + BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff + BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 0x38 + BPF_F_SYSCTL_BASE_NAME = 0x1 + BPF_LOCAL_STORAGE_GET_F_CREATE = 0x1 + BPF_SK_STORAGE_GET_F_CREATE = 0x1 + BPF_F_GET_BRANCH_RECORDS_SIZE = 0x1 + BPF_RB_NO_WAKEUP = 0x1 + BPF_RB_FORCE_WAKEUP = 0x2 + BPF_RB_AVAIL_DATA = 0x0 + BPF_RB_RING_SIZE = 0x1 + BPF_RB_CONS_POS = 0x2 + BPF_RB_PROD_POS = 0x3 + BPF_RINGBUF_BUSY_BIT = 0x80000000 + BPF_RINGBUF_DISCARD_BIT = 0x40000000 + BPF_RINGBUF_HDR_SZ = 0x8 + BPF_SK_LOOKUP_F_REPLACE = 0x1 + BPF_SK_LOOKUP_F_NO_REUSEPORT = 0x2 + BPF_ADJ_ROOM_NET = 0x0 + BPF_ADJ_ROOM_MAC = 0x1 + BPF_HDR_START_MAC = 0x0 + BPF_HDR_START_NET = 0x1 + BPF_LWT_ENCAP_SEG6 = 0x0 + BPF_LWT_ENCAP_SEG6_INLINE = 0x1 + BPF_LWT_ENCAP_IP = 0x2 + BPF_F_BPRM_SECUREEXEC = 0x1 + BPF_F_BROADCAST = 0x8 + BPF_F_EXCLUDE_INGRESS = 0x10 + BPF_SKB_TSTAMP_UNSPEC = 0x0 + BPF_SKB_TSTAMP_DELIVERY_MONO = 0x1 + BPF_OK = 0x0 + BPF_DROP = 0x2 + BPF_REDIRECT = 0x7 + BPF_LWT_REROUTE = 0x80 + BPF_FLOW_DISSECTOR_CONTINUE = 0x81 + BPF_SOCK_OPS_RTO_CB_FLAG = 0x1 + BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2 + BPF_SOCK_OPS_STATE_CB_FLAG = 0x4 + BPF_SOCK_OPS_RTT_CB_FLAG = 0x8 + BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG = 0x10 + BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG = 0x20 + BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG = 0x40 + BPF_SOCK_OPS_ALL_CB_FLAGS = 0x7f + BPF_SOCK_OPS_VOID = 0x0 + BPF_SOCK_OPS_TIMEOUT_INIT = 0x1 + BPF_SOCK_OPS_RWND_INIT = 0x2 + BPF_SOCK_OPS_TCP_CONNECT_CB = 0x3 + BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB = 0x4 + BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB = 0x5 + BPF_SOCK_OPS_NEEDS_ECN = 0x6 + BPF_SOCK_OPS_BASE_RTT = 0x7 + BPF_SOCK_OPS_RTO_CB = 0x8 + BPF_SOCK_OPS_RETRANS_CB = 0x9 + BPF_SOCK_OPS_STATE_CB = 0xa + BPF_SOCK_OPS_TCP_LISTEN_CB = 0xb + BPF_SOCK_OPS_RTT_CB = 0xc + BPF_SOCK_OPS_PARSE_HDR_OPT_CB = 0xd + BPF_SOCK_OPS_HDR_OPT_LEN_CB = 0xe + BPF_SOCK_OPS_WRITE_HDR_OPT_CB = 0xf + BPF_TCP_ESTABLISHED = 0x1 + BPF_TCP_SYN_SENT = 0x2 + BPF_TCP_SYN_RECV = 0x3 + BPF_TCP_FIN_WAIT1 = 0x4 + BPF_TCP_FIN_WAIT2 = 0x5 + BPF_TCP_TIME_WAIT = 0x6 + BPF_TCP_CLOSE = 0x7 + BPF_TCP_CLOSE_WAIT = 0x8 + BPF_TCP_LAST_ACK = 0x9 + BPF_TCP_LISTEN = 0xa + BPF_TCP_CLOSING = 0xb + BPF_TCP_NEW_SYN_RECV = 0xc + BPF_TCP_MAX_STATES = 0xe + TCP_BPF_IW = 0x3e9 + TCP_BPF_SNDCWND_CLAMP = 0x3ea + TCP_BPF_DELACK_MAX = 0x3eb + TCP_BPF_RTO_MIN = 0x3ec + TCP_BPF_SYN = 0x3ed + TCP_BPF_SYN_IP = 0x3ee + TCP_BPF_SYN_MAC = 0x3ef + BPF_LOAD_HDR_OPT_TCP_SYN = 0x1 + BPF_WRITE_HDR_TCP_CURRENT_MSS = 0x1 + BPF_WRITE_HDR_TCP_SYNACK_COOKIE = 0x2 + BPF_DEVCG_ACC_MKNOD = 0x1 + BPF_DEVCG_ACC_READ = 0x2 + BPF_DEVCG_ACC_WRITE = 0x4 + BPF_DEVCG_DEV_BLOCK = 0x1 + BPF_DEVCG_DEV_CHAR = 0x2 + BPF_FIB_LOOKUP_DIRECT = 0x1 + BPF_FIB_LOOKUP_OUTPUT = 0x2 + BPF_FIB_LOOKUP_SKIP_NEIGH = 0x4 + BPF_FIB_LOOKUP_TBID = 0x8 + BPF_FIB_LKUP_RET_SUCCESS = 0x0 + BPF_FIB_LKUP_RET_BLACKHOLE = 0x1 + BPF_FIB_LKUP_RET_UNREACHABLE = 0x2 + BPF_FIB_LKUP_RET_PROHIBIT = 0x3 + BPF_FIB_LKUP_RET_NOT_FWDED = 0x4 + BPF_FIB_LKUP_RET_FWD_DISABLED = 0x5 + BPF_FIB_LKUP_RET_UNSUPP_LWT = 0x6 + BPF_FIB_LKUP_RET_NO_NEIGH = 0x7 + BPF_FIB_LKUP_RET_FRAG_NEEDED = 0x8 + BPF_MTU_CHK_SEGS = 0x1 + BPF_MTU_CHK_RET_SUCCESS = 0x0 + BPF_MTU_CHK_RET_FRAG_NEEDED = 0x1 + BPF_MTU_CHK_RET_SEGS_TOOBIG = 0x2 + BPF_FD_TYPE_RAW_TRACEPOINT = 0x0 + BPF_FD_TYPE_TRACEPOINT = 0x1 + BPF_FD_TYPE_KPROBE = 0x2 + BPF_FD_TYPE_KRETPROBE = 0x3 + BPF_FD_TYPE_UPROBE = 0x4 + BPF_FD_TYPE_URETPROBE = 0x5 + BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG = 0x1 + BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL = 0x2 + BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP = 0x4 + BPF_CORE_FIELD_BYTE_OFFSET = 0x0 + BPF_CORE_FIELD_BYTE_SIZE = 0x1 + BPF_CORE_FIELD_EXISTS = 0x2 + BPF_CORE_FIELD_SIGNED = 0x3 + BPF_CORE_FIELD_LSHIFT_U64 = 0x4 + BPF_CORE_FIELD_RSHIFT_U64 = 0x5 + BPF_CORE_TYPE_ID_LOCAL = 0x6 + BPF_CORE_TYPE_ID_TARGET = 0x7 + BPF_CORE_TYPE_EXISTS = 0x8 + BPF_CORE_TYPE_SIZE = 0x9 + BPF_CORE_ENUMVAL_EXISTS = 0xa + BPF_CORE_ENUMVAL_VALUE = 0xb + BPF_CORE_TYPE_MATCHES = 0xc + BPF_F_TIMER_ABS = 0x1 ) const ( + TCA_UNSPEC = 0x0 + TCA_KIND = 0x1 + TCA_OPTIONS = 0x2 + TCA_STATS = 0x3 + TCA_XSTATS = 0x4 + TCA_RATE = 0x5 + TCA_FCNT = 0x6 + TCA_STATS2 = 0x7 + TCA_STAB = 0x8 + TCA_PAD = 0x9 + TCA_DUMP_INVISIBLE = 0xa + TCA_CHAIN = 0xb + TCA_HW_OFFLOAD = 0xc + TCA_INGRESS_BLOCK = 0xd + TCA_EGRESS_BLOCK = 0xe + TCA_DUMP_FLAGS = 0xf + TCA_EXT_WARN_MSG = 0x10 RTNLGRP_NONE = 0x0 RTNLGRP_LINK = 0x1 RTNLGRP_NOTIFY = 0x2 @@ -2070,6 +3114,19 @@ const ( RTNLGRP_IPV4_MROUTE_R = 0x1e RTNLGRP_IPV6_MROUTE_R = 0x1f RTNLGRP_NEXTHOP = 0x20 + RTNLGRP_BRVLAN = 0x21 + RTNLGRP_MCTP_IFADDR = 0x22 + RTNLGRP_TUNNEL = 0x23 + RTNLGRP_STATS = 0x24 + RTNLGRP_IPV4_MCADDR = 0x25 + RTNLGRP_IPV6_MCADDR = 0x26 + RTNLGRP_IPV6_ACADDR = 0x27 + TCA_ROOT_UNSPEC = 0x0 + TCA_ROOT_TAB = 0x1 + TCA_ROOT_FLAGS = 0x2 + TCA_ROOT_COUNT = 0x3 + TCA_ROOT_TIME_DELTA = 0x4 + TCA_ROOT_EXT_WARN_MSG = 0x5 ) type CapUserHeader struct { @@ -2111,6 +3168,12 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } +type LoopConfig struct { + Fd uint32 + Size uint32 + Info LoopInfo64 + _ [8]uint64 +} type TIPCSocketAddr struct { Ref uint32 @@ -2164,130 +3227,3139 @@ const ( ) const ( - DEVLINK_CMD_UNSPEC = 0x0 - DEVLINK_CMD_GET = 0x1 - DEVLINK_CMD_SET = 0x2 - DEVLINK_CMD_NEW = 0x3 - DEVLINK_CMD_DEL = 0x4 - DEVLINK_CMD_PORT_GET = 0x5 - DEVLINK_CMD_PORT_SET = 0x6 - DEVLINK_CMD_PORT_NEW = 0x7 - DEVLINK_CMD_PORT_DEL = 0x8 - DEVLINK_CMD_PORT_SPLIT = 0x9 - DEVLINK_CMD_PORT_UNSPLIT = 0xa - DEVLINK_CMD_SB_GET = 0xb - DEVLINK_CMD_SB_SET = 0xc - DEVLINK_CMD_SB_NEW = 0xd - DEVLINK_CMD_SB_DEL = 0xe - DEVLINK_CMD_SB_POOL_GET = 0xf - DEVLINK_CMD_SB_POOL_SET = 0x10 - DEVLINK_CMD_SB_POOL_NEW = 0x11 - DEVLINK_CMD_SB_POOL_DEL = 0x12 - DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 - DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 - DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 - DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 - DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 - DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 - DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 - DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a - DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b - DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c - DEVLINK_CMD_ESWITCH_GET = 0x1d - DEVLINK_CMD_ESWITCH_SET = 0x1e - DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f - DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 - DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 - DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 - DEVLINK_CMD_MAX = 0x44 - DEVLINK_PORT_TYPE_NOTSET = 0x0 - DEVLINK_PORT_TYPE_AUTO = 0x1 - DEVLINK_PORT_TYPE_ETH = 0x2 - DEVLINK_PORT_TYPE_IB = 0x3 - DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 - DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 - DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 - DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 - DEVLINK_ESWITCH_MODE_LEGACY = 0x0 - DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 - DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 - DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 - DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 - DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 - DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 - DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 - DEVLINK_ATTR_UNSPEC = 0x0 - DEVLINK_ATTR_BUS_NAME = 0x1 - DEVLINK_ATTR_DEV_NAME = 0x2 - DEVLINK_ATTR_PORT_INDEX = 0x3 - DEVLINK_ATTR_PORT_TYPE = 0x4 - DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 - DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 - DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 - DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 - DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 - DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa - DEVLINK_ATTR_SB_INDEX = 0xb - DEVLINK_ATTR_SB_SIZE = 0xc - DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd - DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe - DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf - DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 - DEVLINK_ATTR_SB_POOL_INDEX = 0x11 - DEVLINK_ATTR_SB_POOL_TYPE = 0x12 - DEVLINK_ATTR_SB_POOL_SIZE = 0x13 - DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 - DEVLINK_ATTR_SB_THRESHOLD = 0x15 - DEVLINK_ATTR_SB_TC_INDEX = 0x16 - DEVLINK_ATTR_SB_OCC_CUR = 0x17 - DEVLINK_ATTR_SB_OCC_MAX = 0x18 - DEVLINK_ATTR_ESWITCH_MODE = 0x19 - DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a - DEVLINK_ATTR_DPIPE_TABLES = 0x1b - DEVLINK_ATTR_DPIPE_TABLE = 0x1c - DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d - DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e - DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f - DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 - DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 - DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 - DEVLINK_ATTR_DPIPE_ENTRY = 0x23 - DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 - DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 - DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 - DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 - DEVLINK_ATTR_DPIPE_MATCH = 0x28 - DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 - DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a - DEVLINK_ATTR_DPIPE_ACTION = 0x2b - DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c - DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d - DEVLINK_ATTR_DPIPE_VALUE = 0x2e - DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f - DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 - DEVLINK_ATTR_DPIPE_HEADERS = 0x31 - DEVLINK_ATTR_DPIPE_HEADER = 0x32 - DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 - DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 - DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 - DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 - DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 - DEVLINK_ATTR_DPIPE_FIELD = 0x38 - DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 - DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a - DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b - DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c - DEVLINK_ATTR_PAD = 0x3d - DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e - DEVLINK_ATTR_MAX = 0x8c - DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 - DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 - DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 - DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 - DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 - DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 - DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 - DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 - DEVLINK_DPIPE_HEADER_IPV4 = 0x1 - DEVLINK_DPIPE_HEADER_IPV6 = 0x2 + DEVLINK_CMD_UNSPEC = 0x0 + DEVLINK_CMD_GET = 0x1 + DEVLINK_CMD_SET = 0x2 + DEVLINK_CMD_NEW = 0x3 + DEVLINK_CMD_DEL = 0x4 + DEVLINK_CMD_PORT_GET = 0x5 + DEVLINK_CMD_PORT_SET = 0x6 + DEVLINK_CMD_PORT_NEW = 0x7 + DEVLINK_CMD_PORT_DEL = 0x8 + DEVLINK_CMD_PORT_SPLIT = 0x9 + DEVLINK_CMD_PORT_UNSPLIT = 0xa + DEVLINK_CMD_SB_GET = 0xb + DEVLINK_CMD_SB_SET = 0xc + DEVLINK_CMD_SB_NEW = 0xd + DEVLINK_CMD_SB_DEL = 0xe + DEVLINK_CMD_SB_POOL_GET = 0xf + DEVLINK_CMD_SB_POOL_SET = 0x10 + DEVLINK_CMD_SB_POOL_NEW = 0x11 + DEVLINK_CMD_SB_POOL_DEL = 0x12 + DEVLINK_CMD_SB_PORT_POOL_GET = 0x13 + DEVLINK_CMD_SB_PORT_POOL_SET = 0x14 + DEVLINK_CMD_SB_PORT_POOL_NEW = 0x15 + DEVLINK_CMD_SB_PORT_POOL_DEL = 0x16 + DEVLINK_CMD_SB_TC_POOL_BIND_GET = 0x17 + DEVLINK_CMD_SB_TC_POOL_BIND_SET = 0x18 + DEVLINK_CMD_SB_TC_POOL_BIND_NEW = 0x19 + DEVLINK_CMD_SB_TC_POOL_BIND_DEL = 0x1a + DEVLINK_CMD_SB_OCC_SNAPSHOT = 0x1b + DEVLINK_CMD_SB_OCC_MAX_CLEAR = 0x1c + DEVLINK_CMD_ESWITCH_GET = 0x1d + DEVLINK_CMD_ESWITCH_SET = 0x1e + DEVLINK_CMD_DPIPE_TABLE_GET = 0x1f + DEVLINK_CMD_DPIPE_ENTRIES_GET = 0x20 + DEVLINK_CMD_DPIPE_HEADERS_GET = 0x21 + DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET = 0x22 + DEVLINK_CMD_RESOURCE_SET = 0x23 + DEVLINK_CMD_RESOURCE_DUMP = 0x24 + DEVLINK_CMD_RELOAD = 0x25 + DEVLINK_CMD_PARAM_GET = 0x26 + DEVLINK_CMD_PARAM_SET = 0x27 + DEVLINK_CMD_PARAM_NEW = 0x28 + DEVLINK_CMD_PARAM_DEL = 0x29 + DEVLINK_CMD_REGION_GET = 0x2a + DEVLINK_CMD_REGION_SET = 0x2b + DEVLINK_CMD_REGION_NEW = 0x2c + DEVLINK_CMD_REGION_DEL = 0x2d + DEVLINK_CMD_REGION_READ = 0x2e + DEVLINK_CMD_PORT_PARAM_GET = 0x2f + DEVLINK_CMD_PORT_PARAM_SET = 0x30 + DEVLINK_CMD_PORT_PARAM_NEW = 0x31 + DEVLINK_CMD_PORT_PARAM_DEL = 0x32 + DEVLINK_CMD_INFO_GET = 0x33 + DEVLINK_CMD_HEALTH_REPORTER_GET = 0x34 + DEVLINK_CMD_HEALTH_REPORTER_SET = 0x35 + DEVLINK_CMD_HEALTH_REPORTER_RECOVER = 0x36 + DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE = 0x37 + DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET = 0x38 + DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR = 0x39 + DEVLINK_CMD_FLASH_UPDATE = 0x3a + DEVLINK_CMD_FLASH_UPDATE_END = 0x3b + DEVLINK_CMD_FLASH_UPDATE_STATUS = 0x3c + DEVLINK_CMD_TRAP_GET = 0x3d + DEVLINK_CMD_TRAP_SET = 0x3e + DEVLINK_CMD_TRAP_NEW = 0x3f + DEVLINK_CMD_TRAP_DEL = 0x40 + DEVLINK_CMD_TRAP_GROUP_GET = 0x41 + DEVLINK_CMD_TRAP_GROUP_SET = 0x42 + DEVLINK_CMD_TRAP_GROUP_NEW = 0x43 + DEVLINK_CMD_TRAP_GROUP_DEL = 0x44 + DEVLINK_CMD_TRAP_POLICER_GET = 0x45 + DEVLINK_CMD_TRAP_POLICER_SET = 0x46 + DEVLINK_CMD_TRAP_POLICER_NEW = 0x47 + DEVLINK_CMD_TRAP_POLICER_DEL = 0x48 + DEVLINK_CMD_HEALTH_REPORTER_TEST = 0x49 + DEVLINK_CMD_RATE_GET = 0x4a + DEVLINK_CMD_RATE_SET = 0x4b + DEVLINK_CMD_RATE_NEW = 0x4c + DEVLINK_CMD_RATE_DEL = 0x4d + DEVLINK_CMD_LINECARD_GET = 0x4e + DEVLINK_CMD_LINECARD_SET = 0x4f + DEVLINK_CMD_LINECARD_NEW = 0x50 + DEVLINK_CMD_LINECARD_DEL = 0x51 + DEVLINK_CMD_SELFTESTS_GET = 0x52 + DEVLINK_CMD_MAX = 0x54 + DEVLINK_PORT_TYPE_NOTSET = 0x0 + DEVLINK_PORT_TYPE_AUTO = 0x1 + DEVLINK_PORT_TYPE_ETH = 0x2 + DEVLINK_PORT_TYPE_IB = 0x3 + DEVLINK_SB_POOL_TYPE_INGRESS = 0x0 + DEVLINK_SB_POOL_TYPE_EGRESS = 0x1 + DEVLINK_SB_THRESHOLD_TYPE_STATIC = 0x0 + DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC = 0x1 + DEVLINK_ESWITCH_MODE_LEGACY = 0x0 + DEVLINK_ESWITCH_MODE_SWITCHDEV = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NONE = 0x0 + DEVLINK_ESWITCH_INLINE_MODE_LINK = 0x1 + DEVLINK_ESWITCH_INLINE_MODE_NETWORK = 0x2 + DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT = 0x3 + DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0x0 + DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 0x1 + DEVLINK_PORT_FLAVOUR_PHYSICAL = 0x0 + DEVLINK_PORT_FLAVOUR_CPU = 0x1 + DEVLINK_PORT_FLAVOUR_DSA = 0x2 + DEVLINK_PORT_FLAVOUR_PCI_PF = 0x3 + DEVLINK_PORT_FLAVOUR_PCI_VF = 0x4 + DEVLINK_PORT_FLAVOUR_VIRTUAL = 0x5 + DEVLINK_PORT_FLAVOUR_UNUSED = 0x6 + DEVLINK_PARAM_CMODE_RUNTIME = 0x0 + DEVLINK_PARAM_CMODE_DRIVERINIT = 0x1 + DEVLINK_PARAM_CMODE_PERMANENT = 0x2 + DEVLINK_PARAM_CMODE_MAX = 0x2 + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER = 0x0 + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH = 0x1 + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK = 0x2 + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_UNKNOWN = 0x3 + DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN = 0x0 + DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS = 0x1 + DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER = 0x2 + DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK = 0x3 + DEVLINK_ATTR_STATS_RX_PACKETS = 0x0 + DEVLINK_ATTR_STATS_RX_BYTES = 0x1 + DEVLINK_ATTR_STATS_RX_DROPPED = 0x2 + DEVLINK_ATTR_STATS_MAX = 0x2 + DEVLINK_FLASH_OVERWRITE_SETTINGS_BIT = 0x0 + DEVLINK_FLASH_OVERWRITE_IDENTIFIERS_BIT = 0x1 + DEVLINK_FLASH_OVERWRITE_MAX_BIT = 0x1 + DEVLINK_TRAP_ACTION_DROP = 0x0 + DEVLINK_TRAP_ACTION_TRAP = 0x1 + DEVLINK_TRAP_ACTION_MIRROR = 0x2 + DEVLINK_TRAP_TYPE_DROP = 0x0 + DEVLINK_TRAP_TYPE_EXCEPTION = 0x1 + DEVLINK_TRAP_TYPE_CONTROL = 0x2 + DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT = 0x0 + DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE = 0x1 + DEVLINK_RELOAD_ACTION_UNSPEC = 0x0 + DEVLINK_RELOAD_ACTION_DRIVER_REINIT = 0x1 + DEVLINK_RELOAD_ACTION_FW_ACTIVATE = 0x2 + DEVLINK_RELOAD_ACTION_MAX = 0x2 + DEVLINK_RELOAD_LIMIT_UNSPEC = 0x0 + DEVLINK_RELOAD_LIMIT_NO_RESET = 0x1 + DEVLINK_RELOAD_LIMIT_MAX = 0x1 + DEVLINK_ATTR_UNSPEC = 0x0 + DEVLINK_ATTR_BUS_NAME = 0x1 + DEVLINK_ATTR_DEV_NAME = 0x2 + DEVLINK_ATTR_PORT_INDEX = 0x3 + DEVLINK_ATTR_PORT_TYPE = 0x4 + DEVLINK_ATTR_PORT_DESIRED_TYPE = 0x5 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 0x6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 0x7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 0x8 + DEVLINK_ATTR_PORT_SPLIT_COUNT = 0x9 + DEVLINK_ATTR_PORT_SPLIT_GROUP = 0xa + DEVLINK_ATTR_SB_INDEX = 0xb + DEVLINK_ATTR_SB_SIZE = 0xc + DEVLINK_ATTR_SB_INGRESS_POOL_COUNT = 0xd + DEVLINK_ATTR_SB_EGRESS_POOL_COUNT = 0xe + DEVLINK_ATTR_SB_INGRESS_TC_COUNT = 0xf + DEVLINK_ATTR_SB_EGRESS_TC_COUNT = 0x10 + DEVLINK_ATTR_SB_POOL_INDEX = 0x11 + DEVLINK_ATTR_SB_POOL_TYPE = 0x12 + DEVLINK_ATTR_SB_POOL_SIZE = 0x13 + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE = 0x14 + DEVLINK_ATTR_SB_THRESHOLD = 0x15 + DEVLINK_ATTR_SB_TC_INDEX = 0x16 + DEVLINK_ATTR_SB_OCC_CUR = 0x17 + DEVLINK_ATTR_SB_OCC_MAX = 0x18 + DEVLINK_ATTR_ESWITCH_MODE = 0x19 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 0x1a + DEVLINK_ATTR_DPIPE_TABLES = 0x1b + DEVLINK_ATTR_DPIPE_TABLE = 0x1c + DEVLINK_ATTR_DPIPE_TABLE_NAME = 0x1d + DEVLINK_ATTR_DPIPE_TABLE_SIZE = 0x1e + DEVLINK_ATTR_DPIPE_TABLE_MATCHES = 0x1f + DEVLINK_ATTR_DPIPE_TABLE_ACTIONS = 0x20 + DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED = 0x21 + DEVLINK_ATTR_DPIPE_ENTRIES = 0x22 + DEVLINK_ATTR_DPIPE_ENTRY = 0x23 + DEVLINK_ATTR_DPIPE_ENTRY_INDEX = 0x24 + DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES = 0x25 + DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES = 0x26 + DEVLINK_ATTR_DPIPE_ENTRY_COUNTER = 0x27 + DEVLINK_ATTR_DPIPE_MATCH = 0x28 + DEVLINK_ATTR_DPIPE_MATCH_VALUE = 0x29 + DEVLINK_ATTR_DPIPE_MATCH_TYPE = 0x2a + DEVLINK_ATTR_DPIPE_ACTION = 0x2b + DEVLINK_ATTR_DPIPE_ACTION_VALUE = 0x2c + DEVLINK_ATTR_DPIPE_ACTION_TYPE = 0x2d + DEVLINK_ATTR_DPIPE_VALUE = 0x2e + DEVLINK_ATTR_DPIPE_VALUE_MASK = 0x2f + DEVLINK_ATTR_DPIPE_VALUE_MAPPING = 0x30 + DEVLINK_ATTR_DPIPE_HEADERS = 0x31 + DEVLINK_ATTR_DPIPE_HEADER = 0x32 + DEVLINK_ATTR_DPIPE_HEADER_NAME = 0x33 + DEVLINK_ATTR_DPIPE_HEADER_ID = 0x34 + DEVLINK_ATTR_DPIPE_HEADER_FIELDS = 0x35 + DEVLINK_ATTR_DPIPE_HEADER_GLOBAL = 0x36 + DEVLINK_ATTR_DPIPE_HEADER_INDEX = 0x37 + DEVLINK_ATTR_DPIPE_FIELD = 0x38 + DEVLINK_ATTR_DPIPE_FIELD_NAME = 0x39 + DEVLINK_ATTR_DPIPE_FIELD_ID = 0x3a + DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH = 0x3b + DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c + DEVLINK_ATTR_PAD = 0x3d + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e + DEVLINK_ATTR_RESOURCE_LIST = 0x3f + DEVLINK_ATTR_RESOURCE = 0x40 + DEVLINK_ATTR_RESOURCE_NAME = 0x41 + DEVLINK_ATTR_RESOURCE_ID = 0x42 + DEVLINK_ATTR_RESOURCE_SIZE = 0x43 + DEVLINK_ATTR_RESOURCE_SIZE_NEW = 0x44 + DEVLINK_ATTR_RESOURCE_SIZE_VALID = 0x45 + DEVLINK_ATTR_RESOURCE_SIZE_MIN = 0x46 + DEVLINK_ATTR_RESOURCE_SIZE_MAX = 0x47 + DEVLINK_ATTR_RESOURCE_SIZE_GRAN = 0x48 + DEVLINK_ATTR_RESOURCE_UNIT = 0x49 + DEVLINK_ATTR_RESOURCE_OCC = 0x4a + DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID = 0x4b + DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS = 0x4c + DEVLINK_ATTR_PORT_FLAVOUR = 0x4d + DEVLINK_ATTR_PORT_NUMBER = 0x4e + DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER = 0x4f + DEVLINK_ATTR_PARAM = 0x50 + DEVLINK_ATTR_PARAM_NAME = 0x51 + DEVLINK_ATTR_PARAM_GENERIC = 0x52 + DEVLINK_ATTR_PARAM_TYPE = 0x53 + DEVLINK_ATTR_PARAM_VALUES_LIST = 0x54 + DEVLINK_ATTR_PARAM_VALUE = 0x55 + DEVLINK_ATTR_PARAM_VALUE_DATA = 0x56 + DEVLINK_ATTR_PARAM_VALUE_CMODE = 0x57 + DEVLINK_ATTR_REGION_NAME = 0x58 + DEVLINK_ATTR_REGION_SIZE = 0x59 + DEVLINK_ATTR_REGION_SNAPSHOTS = 0x5a + DEVLINK_ATTR_REGION_SNAPSHOT = 0x5b + DEVLINK_ATTR_REGION_SNAPSHOT_ID = 0x5c + DEVLINK_ATTR_REGION_CHUNKS = 0x5d + DEVLINK_ATTR_REGION_CHUNK = 0x5e + DEVLINK_ATTR_REGION_CHUNK_DATA = 0x5f + DEVLINK_ATTR_REGION_CHUNK_ADDR = 0x60 + DEVLINK_ATTR_REGION_CHUNK_LEN = 0x61 + DEVLINK_ATTR_INFO_DRIVER_NAME = 0x62 + DEVLINK_ATTR_INFO_SERIAL_NUMBER = 0x63 + DEVLINK_ATTR_INFO_VERSION_FIXED = 0x64 + DEVLINK_ATTR_INFO_VERSION_RUNNING = 0x65 + DEVLINK_ATTR_INFO_VERSION_STORED = 0x66 + DEVLINK_ATTR_INFO_VERSION_NAME = 0x67 + DEVLINK_ATTR_INFO_VERSION_VALUE = 0x68 + DEVLINK_ATTR_SB_POOL_CELL_SIZE = 0x69 + DEVLINK_ATTR_FMSG = 0x6a + DEVLINK_ATTR_FMSG_OBJ_NEST_START = 0x6b + DEVLINK_ATTR_FMSG_PAIR_NEST_START = 0x6c + DEVLINK_ATTR_FMSG_ARR_NEST_START = 0x6d + DEVLINK_ATTR_FMSG_NEST_END = 0x6e + DEVLINK_ATTR_FMSG_OBJ_NAME = 0x6f + DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE = 0x70 + DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA = 0x71 + DEVLINK_ATTR_HEALTH_REPORTER = 0x72 + DEVLINK_ATTR_HEALTH_REPORTER_NAME = 0x73 + DEVLINK_ATTR_HEALTH_REPORTER_STATE = 0x74 + DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT = 0x75 + DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT = 0x76 + DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS = 0x77 + DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD = 0x78 + DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER = 0x79 + DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME = 0x7a + DEVLINK_ATTR_FLASH_UPDATE_COMPONENT = 0x7b + DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG = 0x7c + DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE = 0x7d + DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL = 0x7e + DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 0x7f + DEVLINK_ATTR_PORT_PCI_VF_NUMBER = 0x80 + DEVLINK_ATTR_STATS = 0x81 + DEVLINK_ATTR_TRAP_NAME = 0x82 + DEVLINK_ATTR_TRAP_ACTION = 0x83 + DEVLINK_ATTR_TRAP_TYPE = 0x84 + DEVLINK_ATTR_TRAP_GENERIC = 0x85 + DEVLINK_ATTR_TRAP_METADATA = 0x86 + DEVLINK_ATTR_TRAP_GROUP_NAME = 0x87 + DEVLINK_ATTR_RELOAD_FAILED = 0x88 + DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS = 0x89 + DEVLINK_ATTR_NETNS_FD = 0x8a + DEVLINK_ATTR_NETNS_PID = 0x8b + DEVLINK_ATTR_NETNS_ID = 0x8c + DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP = 0x8d + DEVLINK_ATTR_TRAP_POLICER_ID = 0x8e + DEVLINK_ATTR_TRAP_POLICER_RATE = 0x8f + DEVLINK_ATTR_TRAP_POLICER_BURST = 0x90 + DEVLINK_ATTR_PORT_FUNCTION = 0x91 + DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER = 0x92 + DEVLINK_ATTR_PORT_LANES = 0x93 + DEVLINK_ATTR_PORT_SPLITTABLE = 0x94 + DEVLINK_ATTR_PORT_EXTERNAL = 0x95 + DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 0x96 + DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT = 0x97 + DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK = 0x98 + DEVLINK_ATTR_RELOAD_ACTION = 0x99 + DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED = 0x9a + DEVLINK_ATTR_RELOAD_LIMITS = 0x9b + DEVLINK_ATTR_DEV_STATS = 0x9c + DEVLINK_ATTR_RELOAD_STATS = 0x9d + DEVLINK_ATTR_RELOAD_STATS_ENTRY = 0x9e + DEVLINK_ATTR_RELOAD_STATS_LIMIT = 0x9f + DEVLINK_ATTR_RELOAD_STATS_VALUE = 0xa0 + DEVLINK_ATTR_REMOTE_RELOAD_STATS = 0xa1 + DEVLINK_ATTR_RELOAD_ACTION_INFO = 0xa2 + DEVLINK_ATTR_RELOAD_ACTION_STATS = 0xa3 + DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 0xa4 + DEVLINK_ATTR_RATE_TYPE = 0xa5 + DEVLINK_ATTR_RATE_TX_SHARE = 0xa6 + DEVLINK_ATTR_RATE_TX_MAX = 0xa7 + DEVLINK_ATTR_RATE_NODE_NAME = 0xa8 + DEVLINK_ATTR_RATE_PARENT_NODE_NAME = 0xa9 + DEVLINK_ATTR_REGION_MAX_SNAPSHOTS = 0xaa + DEVLINK_ATTR_LINECARD_INDEX = 0xab + DEVLINK_ATTR_LINECARD_STATE = 0xac + DEVLINK_ATTR_LINECARD_TYPE = 0xad + DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES = 0xae + DEVLINK_ATTR_NESTED_DEVLINK = 0xaf + DEVLINK_ATTR_SELFTESTS = 0xb0 + DEVLINK_ATTR_MAX = 0xb3 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 + DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 + DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 + DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY = 0x0 + DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC = 0x0 + DEVLINK_DPIPE_FIELD_IPV4_DST_IP = 0x0 + DEVLINK_DPIPE_FIELD_IPV6_DST_IP = 0x0 + DEVLINK_DPIPE_HEADER_ETHERNET = 0x0 + DEVLINK_DPIPE_HEADER_IPV4 = 0x1 + DEVLINK_DPIPE_HEADER_IPV6 = 0x2 + DEVLINK_RESOURCE_UNIT_ENTRY = 0x0 + DEVLINK_PORT_FUNCTION_ATTR_UNSPEC = 0x0 + DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR = 0x1 + DEVLINK_PORT_FN_ATTR_STATE = 0x2 + DEVLINK_PORT_FN_ATTR_OPSTATE = 0x3 + DEVLINK_PORT_FN_ATTR_CAPS = 0x4 + DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x6 +) + +type FsverityDigest struct { + Algorithm uint16 + Size uint16 +} + +type FsverityEnableArg struct { + Version uint32 + Hash_algorithm uint32 + Block_size uint32 + Salt_size uint32 + Salt_ptr uint64 + Sig_size uint32 + _ uint32 + Sig_ptr uint64 + _ [11]uint64 +} + +type Nhmsg struct { + Family uint8 + Scope uint8 + Protocol uint8 + Resvd uint8 + Flags uint32 +} + +const SizeofNhmsg = 0x8 + +type NexthopGrp struct { + Id uint32 + Weight uint8 + High uint8 + Resvd2 uint16 +} + +const SizeofNexthopGrp = 0x8 + +const ( + NHA_UNSPEC = 0x0 + NHA_ID = 0x1 + NHA_GROUP = 0x2 + NHA_GROUP_TYPE = 0x3 + NHA_BLACKHOLE = 0x4 + NHA_OIF = 0x5 + NHA_GATEWAY = 0x6 + NHA_ENCAP_TYPE = 0x7 + NHA_ENCAP = 0x8 + NHA_GROUPS = 0x9 + NHA_MASTER = 0xa +) + +const ( + CAN_RAW_FILTER = 0x1 + CAN_RAW_ERR_FILTER = 0x2 + CAN_RAW_LOOPBACK = 0x3 + CAN_RAW_RECV_OWN_MSGS = 0x4 + CAN_RAW_FD_FRAMES = 0x5 + CAN_RAW_JOIN_FILTERS = 0x6 +) + +type WatchdogInfo struct { + Options uint32 + Version uint32 + Identity [32]uint8 +} + +type PPSFData struct { + Info PPSKInfo + Timeout PPSKTime +} + +type PPSKParams struct { + Api_version int32 + Mode int32 + Assert_off_tu PPSKTime + Clear_off_tu PPSKTime +} + +type PPSKTime struct { + Sec int64 + Nsec int32 + Flags uint32 +} + +const ( + LWTUNNEL_ENCAP_NONE = 0x0 + LWTUNNEL_ENCAP_MPLS = 0x1 + LWTUNNEL_ENCAP_IP = 0x2 + LWTUNNEL_ENCAP_ILA = 0x3 + LWTUNNEL_ENCAP_IP6 = 0x4 + LWTUNNEL_ENCAP_SEG6 = 0x5 + LWTUNNEL_ENCAP_BPF = 0x6 + LWTUNNEL_ENCAP_SEG6_LOCAL = 0x7 + LWTUNNEL_ENCAP_RPL = 0x8 + LWTUNNEL_ENCAP_IOAM6 = 0x9 + LWTUNNEL_ENCAP_XFRM = 0xa + LWTUNNEL_ENCAP_MAX = 0xa + + MPLS_IPTUNNEL_UNSPEC = 0x0 + MPLS_IPTUNNEL_DST = 0x1 + MPLS_IPTUNNEL_TTL = 0x2 + MPLS_IPTUNNEL_MAX = 0x2 +) + +const ( + ETHTOOL_ID_UNSPEC = 0x0 + ETHTOOL_RX_COPYBREAK = 0x1 + ETHTOOL_TX_COPYBREAK = 0x2 + ETHTOOL_PFC_PREVENTION_TOUT = 0x3 + ETHTOOL_TUNABLE_UNSPEC = 0x0 + ETHTOOL_TUNABLE_U8 = 0x1 + ETHTOOL_TUNABLE_U16 = 0x2 + ETHTOOL_TUNABLE_U32 = 0x3 + ETHTOOL_TUNABLE_U64 = 0x4 + ETHTOOL_TUNABLE_STRING = 0x5 + ETHTOOL_TUNABLE_S8 = 0x6 + ETHTOOL_TUNABLE_S16 = 0x7 + ETHTOOL_TUNABLE_S32 = 0x8 + ETHTOOL_TUNABLE_S64 = 0x9 + ETHTOOL_PHY_ID_UNSPEC = 0x0 + ETHTOOL_PHY_DOWNSHIFT = 0x1 + ETHTOOL_PHY_FAST_LINK_DOWN = 0x2 + ETHTOOL_PHY_EDPD = 0x3 + ETHTOOL_LINK_EXT_STATE_AUTONEG = 0x0 + ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE = 0x1 + ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH = 0x2 + ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY = 0x3 + ETHTOOL_LINK_EXT_STATE_NO_CABLE = 0x4 + ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE = 0x5 + ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE = 0x6 + ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE = 0x7 + ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED = 0x8 + ETHTOOL_LINK_EXT_STATE_OVERHEAT = 0x9 + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 0x1 + ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED = 0x2 + ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED = 0x3 + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE = 0x4 + ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE = 0x5 + ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD = 0x6 + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 0x1 + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT = 0x2 + ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY = 0x3 + ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT = 0x4 + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 0x1 + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK = 0x2 + ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS = 0x3 + ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED = 0x4 + ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED = 0x5 + ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 0x1 + ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE = 0x2 + ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 0x1 + ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE = 0x2 + ETHTOOL_FLASH_ALL_REGIONS = 0x0 + ETHTOOL_F_UNSUPPORTED__BIT = 0x0 + ETHTOOL_F_WISH__BIT = 0x1 + ETHTOOL_F_COMPAT__BIT = 0x2 + ETHTOOL_FEC_NONE_BIT = 0x0 + ETHTOOL_FEC_AUTO_BIT = 0x1 + ETHTOOL_FEC_OFF_BIT = 0x2 + ETHTOOL_FEC_RS_BIT = 0x3 + ETHTOOL_FEC_BASER_BIT = 0x4 + ETHTOOL_FEC_LLRS_BIT = 0x5 + ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0x0 + ETHTOOL_LINK_MODE_10baseT_Full_BIT = 0x1 + ETHTOOL_LINK_MODE_100baseT_Half_BIT = 0x2 + ETHTOOL_LINK_MODE_100baseT_Full_BIT = 0x3 + ETHTOOL_LINK_MODE_1000baseT_Half_BIT = 0x4 + ETHTOOL_LINK_MODE_1000baseT_Full_BIT = 0x5 + ETHTOOL_LINK_MODE_Autoneg_BIT = 0x6 + ETHTOOL_LINK_MODE_TP_BIT = 0x7 + ETHTOOL_LINK_MODE_AUI_BIT = 0x8 + ETHTOOL_LINK_MODE_MII_BIT = 0x9 + ETHTOOL_LINK_MODE_FIBRE_BIT = 0xa + ETHTOOL_LINK_MODE_BNC_BIT = 0xb + ETHTOOL_LINK_MODE_10000baseT_Full_BIT = 0xc + ETHTOOL_LINK_MODE_Pause_BIT = 0xd + ETHTOOL_LINK_MODE_Asym_Pause_BIT = 0xe + ETHTOOL_LINK_MODE_2500baseX_Full_BIT = 0xf + ETHTOOL_LINK_MODE_Backplane_BIT = 0x10 + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT = 0x11 + ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT = 0x12 + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT = 0x13 + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT = 0x14 + ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 0x15 + ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT = 0x16 + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT = 0x17 + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT = 0x18 + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT = 0x19 + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT = 0x1a + ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT = 0x1b + ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 0x1c + ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 0x1d + ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 0x1e + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT = 0x1f + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT = 0x20 + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT = 0x21 + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 0x22 + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 0x23 + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT = 0x24 + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT = 0x25 + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT = 0x26 + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 0x27 + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 0x28 + ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 0x29 + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 0x2a + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 0x2b + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 0x2c + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 0x2d + ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 0x2e + ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 0x2f + ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 0x30 + ETHTOOL_LINK_MODE_FEC_NONE_BIT = 0x31 + ETHTOOL_LINK_MODE_FEC_RS_BIT = 0x32 + ETHTOOL_LINK_MODE_FEC_BASER_BIT = 0x33 + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT = 0x34 + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT = 0x35 + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT = 0x36 + ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT = 0x37 + ETHTOOL_LINK_MODE_50000baseDR_Full_BIT = 0x38 + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT = 0x39 + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT = 0x3a + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT = 0x3b + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT = 0x3c + ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT = 0x3d + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT = 0x3e + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT = 0x3f + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 0x40 + ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT = 0x41 + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT = 0x42 + ETHTOOL_LINK_MODE_100baseT1_Full_BIT = 0x43 + ETHTOOL_LINK_MODE_1000baseT1_Full_BIT = 0x44 + ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT = 0x45 + ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT = 0x46 + ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 0x47 + ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 0x48 + ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 0x49 + ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 0x4a + ETHTOOL_LINK_MODE_100000baseKR_Full_BIT = 0x4b + ETHTOOL_LINK_MODE_100000baseSR_Full_BIT = 0x4c + ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT = 0x4d + ETHTOOL_LINK_MODE_100000baseCR_Full_BIT = 0x4e + ETHTOOL_LINK_MODE_100000baseDR_Full_BIT = 0x4f + ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT = 0x50 + ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT = 0x51 + ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 0x52 + ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT = 0x53 + ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT = 0x54 + ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT = 0x55 + ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT = 0x56 + ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 0x57 + ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT = 0x58 + ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 0x59 + ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 0x5a + ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 0x5b + + ETHTOOL_MSG_USER_NONE = 0x0 + ETHTOOL_MSG_STRSET_GET = 0x1 + ETHTOOL_MSG_LINKINFO_GET = 0x2 + ETHTOOL_MSG_LINKINFO_SET = 0x3 + ETHTOOL_MSG_LINKMODES_GET = 0x4 + ETHTOOL_MSG_LINKMODES_SET = 0x5 + ETHTOOL_MSG_LINKSTATE_GET = 0x6 + ETHTOOL_MSG_DEBUG_GET = 0x7 + ETHTOOL_MSG_DEBUG_SET = 0x8 + ETHTOOL_MSG_WOL_GET = 0x9 + ETHTOOL_MSG_WOL_SET = 0xa + ETHTOOL_MSG_FEATURES_GET = 0xb + ETHTOOL_MSG_FEATURES_SET = 0xc + ETHTOOL_MSG_PRIVFLAGS_GET = 0xd + ETHTOOL_MSG_PRIVFLAGS_SET = 0xe + ETHTOOL_MSG_RINGS_GET = 0xf + ETHTOOL_MSG_RINGS_SET = 0x10 + ETHTOOL_MSG_CHANNELS_GET = 0x11 + ETHTOOL_MSG_CHANNELS_SET = 0x12 + ETHTOOL_MSG_COALESCE_GET = 0x13 + ETHTOOL_MSG_COALESCE_SET = 0x14 + ETHTOOL_MSG_PAUSE_GET = 0x15 + ETHTOOL_MSG_PAUSE_SET = 0x16 + ETHTOOL_MSG_EEE_GET = 0x17 + ETHTOOL_MSG_EEE_SET = 0x18 + ETHTOOL_MSG_TSINFO_GET = 0x19 + ETHTOOL_MSG_CABLE_TEST_ACT = 0x1a + ETHTOOL_MSG_CABLE_TEST_TDR_ACT = 0x1b + ETHTOOL_MSG_TUNNEL_INFO_GET = 0x1c + ETHTOOL_MSG_FEC_GET = 0x1d + ETHTOOL_MSG_FEC_SET = 0x1e + ETHTOOL_MSG_MODULE_EEPROM_GET = 0x1f + ETHTOOL_MSG_STATS_GET = 0x20 + ETHTOOL_MSG_PHC_VCLOCKS_GET = 0x21 + ETHTOOL_MSG_MODULE_GET = 0x22 + ETHTOOL_MSG_MODULE_SET = 0x23 + ETHTOOL_MSG_PSE_GET = 0x24 + ETHTOOL_MSG_PSE_SET = 0x25 + ETHTOOL_MSG_RSS_GET = 0x26 + ETHTOOL_MSG_PLCA_GET_CFG = 0x27 + ETHTOOL_MSG_PLCA_SET_CFG = 0x28 + ETHTOOL_MSG_PLCA_GET_STATUS = 0x29 + ETHTOOL_MSG_MM_GET = 0x2a + ETHTOOL_MSG_MM_SET = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c + ETHTOOL_MSG_PHY_GET = 0x2d + ETHTOOL_MSG_TSCONFIG_GET = 0x2e + ETHTOOL_MSG_TSCONFIG_SET = 0x2f + ETHTOOL_MSG_USER_MAX = 0x2f + ETHTOOL_MSG_KERNEL_NONE = 0x0 + ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 + ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 + ETHTOOL_MSG_LINKINFO_NTF = 0x3 + ETHTOOL_MSG_LINKMODES_GET_REPLY = 0x4 + ETHTOOL_MSG_LINKMODES_NTF = 0x5 + ETHTOOL_MSG_LINKSTATE_GET_REPLY = 0x6 + ETHTOOL_MSG_DEBUG_GET_REPLY = 0x7 + ETHTOOL_MSG_DEBUG_NTF = 0x8 + ETHTOOL_MSG_WOL_GET_REPLY = 0x9 + ETHTOOL_MSG_WOL_NTF = 0xa + ETHTOOL_MSG_FEATURES_GET_REPLY = 0xb + ETHTOOL_MSG_FEATURES_SET_REPLY = 0xc + ETHTOOL_MSG_FEATURES_NTF = 0xd + ETHTOOL_MSG_PRIVFLAGS_GET_REPLY = 0xe + ETHTOOL_MSG_PRIVFLAGS_NTF = 0xf + ETHTOOL_MSG_RINGS_GET_REPLY = 0x10 + ETHTOOL_MSG_RINGS_NTF = 0x11 + ETHTOOL_MSG_CHANNELS_GET_REPLY = 0x12 + ETHTOOL_MSG_CHANNELS_NTF = 0x13 + ETHTOOL_MSG_COALESCE_GET_REPLY = 0x14 + ETHTOOL_MSG_COALESCE_NTF = 0x15 + ETHTOOL_MSG_PAUSE_GET_REPLY = 0x16 + ETHTOOL_MSG_PAUSE_NTF = 0x17 + ETHTOOL_MSG_EEE_GET_REPLY = 0x18 + ETHTOOL_MSG_EEE_NTF = 0x19 + ETHTOOL_MSG_TSINFO_GET_REPLY = 0x1a + ETHTOOL_MSG_CABLE_TEST_NTF = 0x1b + ETHTOOL_MSG_CABLE_TEST_TDR_NTF = 0x1c + ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY = 0x1d + ETHTOOL_MSG_FEC_GET_REPLY = 0x1e + ETHTOOL_MSG_FEC_NTF = 0x1f + ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY = 0x20 + ETHTOOL_MSG_STATS_GET_REPLY = 0x21 + ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY = 0x22 + ETHTOOL_MSG_MODULE_GET_REPLY = 0x23 + ETHTOOL_MSG_MODULE_NTF = 0x24 + ETHTOOL_MSG_PSE_GET_REPLY = 0x25 + ETHTOOL_MSG_RSS_GET_REPLY = 0x26 + ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27 + ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28 + ETHTOOL_MSG_PLCA_NTF = 0x29 + ETHTOOL_MSG_MM_GET_REPLY = 0x2a + ETHTOOL_MSG_MM_NTF = 0x2b + ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c + ETHTOOL_MSG_PHY_GET_REPLY = 0x2d + ETHTOOL_MSG_PHY_NTF = 0x2e + ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f + ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 + ETHTOOL_MSG_KERNEL_MAX = 0x30 + ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 + ETHTOOL_FLAG_OMIT_REPLY = 0x2 + ETHTOOL_FLAG_STATS = 0x4 + ETHTOOL_A_HEADER_UNSPEC = 0x0 + ETHTOOL_A_HEADER_DEV_INDEX = 0x1 + ETHTOOL_A_HEADER_DEV_NAME = 0x2 + ETHTOOL_A_HEADER_FLAGS = 0x3 + ETHTOOL_A_HEADER_MAX = 0x4 + ETHTOOL_A_BITSET_BIT_UNSPEC = 0x0 + ETHTOOL_A_BITSET_BIT_INDEX = 0x1 + ETHTOOL_A_BITSET_BIT_NAME = 0x2 + ETHTOOL_A_BITSET_BIT_VALUE = 0x3 + ETHTOOL_A_BITSET_BIT_MAX = 0x3 + ETHTOOL_A_BITSET_BITS_UNSPEC = 0x0 + ETHTOOL_A_BITSET_BITS_BIT = 0x1 + ETHTOOL_A_BITSET_BITS_MAX = 0x1 + ETHTOOL_A_BITSET_UNSPEC = 0x0 + ETHTOOL_A_BITSET_NOMASK = 0x1 + ETHTOOL_A_BITSET_SIZE = 0x2 + ETHTOOL_A_BITSET_BITS = 0x3 + ETHTOOL_A_BITSET_VALUE = 0x4 + ETHTOOL_A_BITSET_MASK = 0x5 + ETHTOOL_A_BITSET_MAX = 0x5 + ETHTOOL_A_STRING_UNSPEC = 0x0 + ETHTOOL_A_STRING_INDEX = 0x1 + ETHTOOL_A_STRING_VALUE = 0x2 + ETHTOOL_A_STRING_MAX = 0x2 + ETHTOOL_A_STRINGS_UNSPEC = 0x0 + ETHTOOL_A_STRINGS_STRING = 0x1 + ETHTOOL_A_STRINGS_MAX = 0x1 + ETHTOOL_A_STRINGSET_UNSPEC = 0x0 + ETHTOOL_A_STRINGSET_ID = 0x1 + ETHTOOL_A_STRINGSET_COUNT = 0x2 + ETHTOOL_A_STRINGSET_STRINGS = 0x3 + ETHTOOL_A_STRINGSET_MAX = 0x3 + ETHTOOL_A_STRINGSETS_UNSPEC = 0x0 + ETHTOOL_A_STRINGSETS_STRINGSET = 0x1 + ETHTOOL_A_STRINGSETS_MAX = 0x1 + ETHTOOL_A_STRSET_UNSPEC = 0x0 + ETHTOOL_A_STRSET_HEADER = 0x1 + ETHTOOL_A_STRSET_STRINGSETS = 0x2 + ETHTOOL_A_STRSET_COUNTS_ONLY = 0x3 + ETHTOOL_A_STRSET_MAX = 0x3 + ETHTOOL_A_LINKINFO_UNSPEC = 0x0 + ETHTOOL_A_LINKINFO_HEADER = 0x1 + ETHTOOL_A_LINKINFO_PORT = 0x2 + ETHTOOL_A_LINKINFO_PHYADDR = 0x3 + ETHTOOL_A_LINKINFO_TP_MDIX = 0x4 + ETHTOOL_A_LINKINFO_TP_MDIX_CTRL = 0x5 + ETHTOOL_A_LINKINFO_TRANSCEIVER = 0x6 + ETHTOOL_A_LINKINFO_MAX = 0x6 + ETHTOOL_A_LINKMODES_UNSPEC = 0x0 + ETHTOOL_A_LINKMODES_HEADER = 0x1 + ETHTOOL_A_LINKMODES_AUTONEG = 0x2 + ETHTOOL_A_LINKMODES_OURS = 0x3 + ETHTOOL_A_LINKMODES_PEER = 0x4 + ETHTOOL_A_LINKMODES_SPEED = 0x5 + ETHTOOL_A_LINKMODES_DUPLEX = 0x6 + ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG = 0x7 + ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE = 0x8 + ETHTOOL_A_LINKMODES_LANES = 0x9 + ETHTOOL_A_LINKMODES_RATE_MATCHING = 0xa + ETHTOOL_A_LINKMODES_MAX = 0xa + ETHTOOL_A_LINKSTATE_UNSPEC = 0x0 + ETHTOOL_A_LINKSTATE_HEADER = 0x1 + ETHTOOL_A_LINKSTATE_LINK = 0x2 + ETHTOOL_A_LINKSTATE_SQI = 0x3 + ETHTOOL_A_LINKSTATE_SQI_MAX = 0x4 + ETHTOOL_A_LINKSTATE_EXT_STATE = 0x5 + ETHTOOL_A_LINKSTATE_EXT_SUBSTATE = 0x6 + ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT = 0x7 + ETHTOOL_A_LINKSTATE_MAX = 0x7 + ETHTOOL_A_DEBUG_UNSPEC = 0x0 + ETHTOOL_A_DEBUG_HEADER = 0x1 + ETHTOOL_A_DEBUG_MSGMASK = 0x2 + ETHTOOL_A_DEBUG_MAX = 0x2 + ETHTOOL_A_WOL_UNSPEC = 0x0 + ETHTOOL_A_WOL_HEADER = 0x1 + ETHTOOL_A_WOL_MODES = 0x2 + ETHTOOL_A_WOL_SOPASS = 0x3 + ETHTOOL_A_WOL_MAX = 0x3 + ETHTOOL_A_FEATURES_UNSPEC = 0x0 + ETHTOOL_A_FEATURES_HEADER = 0x1 + ETHTOOL_A_FEATURES_HW = 0x2 + ETHTOOL_A_FEATURES_WANTED = 0x3 + ETHTOOL_A_FEATURES_ACTIVE = 0x4 + ETHTOOL_A_FEATURES_NOCHANGE = 0x5 + ETHTOOL_A_FEATURES_MAX = 0x5 + ETHTOOL_A_PRIVFLAGS_UNSPEC = 0x0 + ETHTOOL_A_PRIVFLAGS_HEADER = 0x1 + ETHTOOL_A_PRIVFLAGS_FLAGS = 0x2 + ETHTOOL_A_PRIVFLAGS_MAX = 0x2 + ETHTOOL_A_RINGS_UNSPEC = 0x0 + ETHTOOL_A_RINGS_HEADER = 0x1 + ETHTOOL_A_RINGS_RX_MAX = 0x2 + ETHTOOL_A_RINGS_RX_MINI_MAX = 0x3 + ETHTOOL_A_RINGS_RX_JUMBO_MAX = 0x4 + ETHTOOL_A_RINGS_TX_MAX = 0x5 + ETHTOOL_A_RINGS_RX = 0x6 + ETHTOOL_A_RINGS_RX_MINI = 0x7 + ETHTOOL_A_RINGS_RX_JUMBO = 0x8 + ETHTOOL_A_RINGS_TX = 0x9 + ETHTOOL_A_RINGS_RX_BUF_LEN = 0xa + ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb + ETHTOOL_A_RINGS_CQE_SIZE = 0xc + ETHTOOL_A_RINGS_TX_PUSH = 0xd + ETHTOOL_A_RINGS_RX_PUSH = 0xe + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf + ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10 + ETHTOOL_A_RINGS_HDS_THRESH = 0x11 + ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12 + ETHTOOL_A_RINGS_MAX = 0x12 + ETHTOOL_A_CHANNELS_UNSPEC = 0x0 + ETHTOOL_A_CHANNELS_HEADER = 0x1 + ETHTOOL_A_CHANNELS_RX_MAX = 0x2 + ETHTOOL_A_CHANNELS_TX_MAX = 0x3 + ETHTOOL_A_CHANNELS_OTHER_MAX = 0x4 + ETHTOOL_A_CHANNELS_COMBINED_MAX = 0x5 + ETHTOOL_A_CHANNELS_RX_COUNT = 0x6 + ETHTOOL_A_CHANNELS_TX_COUNT = 0x7 + ETHTOOL_A_CHANNELS_OTHER_COUNT = 0x8 + ETHTOOL_A_CHANNELS_COMBINED_COUNT = 0x9 + ETHTOOL_A_CHANNELS_MAX = 0x9 + ETHTOOL_A_COALESCE_UNSPEC = 0x0 + ETHTOOL_A_COALESCE_HEADER = 0x1 + ETHTOOL_A_COALESCE_RX_USECS = 0x2 + ETHTOOL_A_COALESCE_RX_MAX_FRAMES = 0x3 + ETHTOOL_A_COALESCE_RX_USECS_IRQ = 0x4 + ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ = 0x5 + ETHTOOL_A_COALESCE_TX_USECS = 0x6 + ETHTOOL_A_COALESCE_TX_MAX_FRAMES = 0x7 + ETHTOOL_A_COALESCE_TX_USECS_IRQ = 0x8 + ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ = 0x9 + ETHTOOL_A_COALESCE_STATS_BLOCK_USECS = 0xa + ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX = 0xb + ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX = 0xc + ETHTOOL_A_COALESCE_PKT_RATE_LOW = 0xd + ETHTOOL_A_COALESCE_RX_USECS_LOW = 0xe + ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW = 0xf + ETHTOOL_A_COALESCE_TX_USECS_LOW = 0x10 + ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW = 0x11 + ETHTOOL_A_COALESCE_PKT_RATE_HIGH = 0x12 + ETHTOOL_A_COALESCE_RX_USECS_HIGH = 0x13 + ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH = 0x14 + ETHTOOL_A_COALESCE_TX_USECS_HIGH = 0x15 + ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH = 0x16 + ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17 + ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18 + ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19 + ETHTOOL_A_COALESCE_MAX = 0x1e + ETHTOOL_A_PAUSE_UNSPEC = 0x0 + ETHTOOL_A_PAUSE_HEADER = 0x1 + ETHTOOL_A_PAUSE_AUTONEG = 0x2 + ETHTOOL_A_PAUSE_RX = 0x3 + ETHTOOL_A_PAUSE_TX = 0x4 + ETHTOOL_A_PAUSE_STATS = 0x5 + ETHTOOL_A_PAUSE_MAX = 0x6 + ETHTOOL_A_PAUSE_STAT_UNSPEC = 0x0 + ETHTOOL_A_PAUSE_STAT_PAD = 0x1 + ETHTOOL_A_PAUSE_STAT_TX_FRAMES = 0x2 + ETHTOOL_A_PAUSE_STAT_RX_FRAMES = 0x3 + ETHTOOL_A_PAUSE_STAT_MAX = 0x3 + ETHTOOL_A_EEE_UNSPEC = 0x0 + ETHTOOL_A_EEE_HEADER = 0x1 + ETHTOOL_A_EEE_MODES_OURS = 0x2 + ETHTOOL_A_EEE_MODES_PEER = 0x3 + ETHTOOL_A_EEE_ACTIVE = 0x4 + ETHTOOL_A_EEE_ENABLED = 0x5 + ETHTOOL_A_EEE_TX_LPI_ENABLED = 0x6 + ETHTOOL_A_EEE_TX_LPI_TIMER = 0x7 + ETHTOOL_A_EEE_MAX = 0x7 + ETHTOOL_A_TSINFO_UNSPEC = 0x0 + ETHTOOL_A_TSINFO_HEADER = 0x1 + ETHTOOL_A_TSINFO_TIMESTAMPING = 0x2 + ETHTOOL_A_TSINFO_TX_TYPES = 0x3 + ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 + ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 + ETHTOOL_A_TSINFO_STATS = 0x6 + ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7 + ETHTOOL_A_TSINFO_MAX = 0x9 + ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TEST_HEADER = 0x1 + ETHTOOL_A_CABLE_TEST_MAX = 0x1 + ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC = 0x0 + ETHTOOL_A_CABLE_RESULT_CODE_OK = 0x1 + ETHTOOL_A_CABLE_RESULT_CODE_OPEN = 0x2 + ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT = 0x3 + ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT = 0x4 + ETHTOOL_A_CABLE_PAIR_A = 0x0 + ETHTOOL_A_CABLE_PAIR_B = 0x1 + ETHTOOL_A_CABLE_PAIR_C = 0x2 + ETHTOOL_A_CABLE_PAIR_D = 0x3 + ETHTOOL_A_CABLE_RESULT_UNSPEC = 0x0 + ETHTOOL_A_CABLE_RESULT_PAIR = 0x1 + ETHTOOL_A_CABLE_RESULT_CODE = 0x2 + ETHTOOL_A_CABLE_RESULT_MAX = 0x3 + ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC = 0x0 + ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR = 0x1 + ETHTOOL_A_CABLE_FAULT_LENGTH_CM = 0x2 + ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = 0x3 + ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED = 0x1 + ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED = 0x2 + ETHTOOL_A_CABLE_NEST_UNSPEC = 0x0 + ETHTOOL_A_CABLE_NEST_RESULT = 0x1 + ETHTOOL_A_CABLE_NEST_FAULT_LENGTH = 0x2 + ETHTOOL_A_CABLE_NEST_MAX = 0x2 + ETHTOOL_A_CABLE_TEST_NTF_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TEST_NTF_HEADER = 0x1 + ETHTOOL_A_CABLE_TEST_NTF_STATUS = 0x2 + ETHTOOL_A_CABLE_TEST_NTF_NEST = 0x3 + ETHTOOL_A_CABLE_TEST_NTF_MAX = 0x3 + ETHTOOL_A_CABLE_TEST_TDR_CFG_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST = 0x1 + ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST = 0x2 + ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP = 0x3 + ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR = 0x4 + ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX = 0x4 + ETHTOOL_A_CABLE_TEST_TDR_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TEST_TDR_HEADER = 0x1 + ETHTOOL_A_CABLE_TEST_TDR_CFG = 0x2 + ETHTOOL_A_CABLE_TEST_TDR_MAX = 0x2 + ETHTOOL_A_CABLE_AMPLITUDE_UNSPEC = 0x0 + ETHTOOL_A_CABLE_AMPLITUDE_PAIR = 0x1 + ETHTOOL_A_CABLE_AMPLITUDE_mV = 0x2 + ETHTOOL_A_CABLE_AMPLITUDE_MAX = 0x2 + ETHTOOL_A_CABLE_PULSE_UNSPEC = 0x0 + ETHTOOL_A_CABLE_PULSE_mV = 0x1 + ETHTOOL_A_CABLE_PULSE_MAX = 0x1 + ETHTOOL_A_CABLE_STEP_UNSPEC = 0x0 + ETHTOOL_A_CABLE_STEP_FIRST_DISTANCE = 0x1 + ETHTOOL_A_CABLE_STEP_LAST_DISTANCE = 0x2 + ETHTOOL_A_CABLE_STEP_STEP_DISTANCE = 0x3 + ETHTOOL_A_CABLE_STEP_MAX = 0x3 + ETHTOOL_A_CABLE_TDR_NEST_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TDR_NEST_STEP = 0x1 + ETHTOOL_A_CABLE_TDR_NEST_AMPLITUDE = 0x2 + ETHTOOL_A_CABLE_TDR_NEST_PULSE = 0x3 + ETHTOOL_A_CABLE_TDR_NEST_MAX = 0x3 + ETHTOOL_A_CABLE_TEST_TDR_NTF_UNSPEC = 0x0 + ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER = 0x1 + ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS = 0x2 + ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST = 0x3 + ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX = 0x3 + ETHTOOL_UDP_TUNNEL_TYPE_VXLAN = 0x0 + ETHTOOL_UDP_TUNNEL_TYPE_GENEVE = 0x1 + ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE = 0x2 + ETHTOOL_A_TUNNEL_UDP_ENTRY_UNSPEC = 0x0 + ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT = 0x1 + ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE = 0x2 + ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX = 0x2 + ETHTOOL_A_TUNNEL_UDP_TABLE_UNSPEC = 0x0 + ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE = 0x1 + ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES = 0x2 + ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY = 0x3 + ETHTOOL_A_TUNNEL_UDP_TABLE_MAX = 0x3 + ETHTOOL_A_TUNNEL_UDP_UNSPEC = 0x0 + ETHTOOL_A_TUNNEL_UDP_TABLE = 0x1 + ETHTOOL_A_TUNNEL_UDP_MAX = 0x1 + ETHTOOL_A_TUNNEL_INFO_UNSPEC = 0x0 + ETHTOOL_A_TUNNEL_INFO_HEADER = 0x1 + ETHTOOL_A_TUNNEL_INFO_UDP_PORTS = 0x2 + ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 +) + +const ( + TCP_V4_FLOW = 0x1 + UDP_V4_FLOW = 0x2 + TCP_V6_FLOW = 0x5 + UDP_V6_FLOW = 0x6 + ESP_V4_FLOW = 0xa + ESP_V6_FLOW = 0xc + IP_USER_FLOW = 0xd + IPV6_USER_FLOW = 0xe + IPV6_FLOW = 0x11 + ETHER_FLOW = 0x12 +) + +const SPEED_UNKNOWN = -0x1 + +type EthtoolDrvinfo struct { + Cmd uint32 + Driver [32]byte + Version [32]byte + Fw_version [32]byte + Bus_info [32]byte + Erom_version [32]byte + Reserved2 [12]byte + N_priv_flags uint32 + N_stats uint32 + Testinfo_len uint32 + Eedump_len uint32 + Regdump_len uint32 +} + +type EthtoolTsInfo struct { + Cmd uint32 + So_timestamping uint32 + Phc_index int32 + Tx_types uint32 + Tx_reserved [3]uint32 + Rx_filters uint32 + Rx_reserved [3]uint32 +} + +type HwTstampConfig struct { + Flags int32 + Tx_type int32 + Rx_filter int32 +} + +const ( + HWTSTAMP_FILTER_NONE = 0x0 + HWTSTAMP_FILTER_ALL = 0x1 + HWTSTAMP_FILTER_SOME = 0x2 + HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3 + HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6 + HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9 + HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc +) + +const ( + HWTSTAMP_TX_OFF = 0x0 + HWTSTAMP_TX_ON = 0x1 + HWTSTAMP_TX_ONESTEP_SYNC = 0x2 +) + +type ( + PtpClockCaps struct { + Max_adj int32 + N_alarm int32 + N_ext_ts int32 + N_per_out int32 + Pps int32 + N_pins int32 + Cross_timestamping int32 + Adjust_phase int32 + Max_phase_adj int32 + Rsv [11]int32 + } + PtpClockTime struct { + Sec int64 + Nsec uint32 + Reserved uint32 + } + PtpExttsEvent struct { + T PtpClockTime + Index uint32 + Flags uint32 + Rsv [2]uint32 + } + PtpExttsRequest struct { + Index uint32 + Flags uint32 + Rsv [2]uint32 + } + PtpPeroutRequest struct { + StartOrPhase PtpClockTime + Period PtpClockTime + Index uint32 + Flags uint32 + On PtpClockTime + } + PtpPinDesc struct { + Name [64]byte + Index uint32 + Func uint32 + Chan uint32 + Rsv [5]uint32 + } + PtpSysOffset struct { + Samples uint32 + Rsv [3]uint32 + Ts [51]PtpClockTime + } + PtpSysOffsetExtended struct { + Samples uint32 + Clockid int32 + Rsv [2]uint32 + Ts [25][3]PtpClockTime + } + PtpSysOffsetPrecise struct { + Device PtpClockTime + Realtime PtpClockTime + Monoraw PtpClockTime + Rsv [4]uint32 + } +) + +const ( + PTP_PF_NONE = 0x0 + PTP_PF_EXTTS = 0x1 + PTP_PF_PEROUT = 0x2 + PTP_PF_PHYSYNC = 0x3 +) + +type ( + HIDRawReportDescriptor struct { + Size uint32 + Value [4096]uint8 + } + HIDRawDevInfo struct { + Bustype uint32 + Vendor int16 + Product int16 + } +) + +const ( + CLOSE_RANGE_UNSHARE = 0x2 + CLOSE_RANGE_CLOEXEC = 0x4 +) + +const ( + NLMSGERR_ATTR_MSG = 0x1 + NLMSGERR_ATTR_OFFS = 0x2 + NLMSGERR_ATTR_COOKIE = 0x3 +) + +type ( + EraseInfo struct { + Start uint32 + Length uint32 + } + EraseInfo64 struct { + Start uint64 + Length uint64 + } + MtdOobBuf struct { + Start uint32 + Length uint32 + Ptr *uint8 + } + MtdOobBuf64 struct { + Start uint64 + Pad uint32 + Length uint32 + Ptr uint64 + } + MtdWriteReq struct { + Start uint64 + Len uint64 + Ooblen uint64 + Data uint64 + Oob uint64 + Mode uint8 + _ [7]uint8 + } + MtdInfo struct { + Type uint8 + Flags uint32 + Size uint32 + Erasesize uint32 + Writesize uint32 + Oobsize uint32 + _ uint64 + } + RegionInfo struct { + Offset uint32 + Erasesize uint32 + Numblocks uint32 + Regionindex uint32 + } + OtpInfo struct { + Start uint32 + Length uint32 + Locked uint32 + } + NandOobinfo struct { + Useecc uint32 + Eccbytes uint32 + Oobfree [8][2]uint32 + Eccpos [32]uint32 + } + NandOobfree struct { + Offset uint32 + Length uint32 + } + NandEcclayout struct { + Eccbytes uint32 + Eccpos [64]uint32 + Oobavail uint32 + Oobfree [8]NandOobfree + } + MtdEccStats struct { + Corrected uint32 + Failed uint32 + Badblocks uint32 + Bbtblocks uint32 + } +) + +const ( + MTD_OPS_PLACE_OOB = 0x0 + MTD_OPS_AUTO_OOB = 0x1 + MTD_OPS_RAW = 0x2 +) + +const ( + MTD_FILE_MODE_NORMAL = 0x0 + MTD_FILE_MODE_OTP_FACTORY = 0x1 + MTD_FILE_MODE_OTP_USER = 0x2 + MTD_FILE_MODE_RAW = 0x3 +) + +const ( + NFC_CMD_UNSPEC = 0x0 + NFC_CMD_GET_DEVICE = 0x1 + NFC_CMD_DEV_UP = 0x2 + NFC_CMD_DEV_DOWN = 0x3 + NFC_CMD_DEP_LINK_UP = 0x4 + NFC_CMD_DEP_LINK_DOWN = 0x5 + NFC_CMD_START_POLL = 0x6 + NFC_CMD_STOP_POLL = 0x7 + NFC_CMD_GET_TARGET = 0x8 + NFC_EVENT_TARGETS_FOUND = 0x9 + NFC_EVENT_DEVICE_ADDED = 0xa + NFC_EVENT_DEVICE_REMOVED = 0xb + NFC_EVENT_TARGET_LOST = 0xc + NFC_EVENT_TM_ACTIVATED = 0xd + NFC_EVENT_TM_DEACTIVATED = 0xe + NFC_CMD_LLC_GET_PARAMS = 0xf + NFC_CMD_LLC_SET_PARAMS = 0x10 + NFC_CMD_ENABLE_SE = 0x11 + NFC_CMD_DISABLE_SE = 0x12 + NFC_CMD_LLC_SDREQ = 0x13 + NFC_EVENT_LLC_SDRES = 0x14 + NFC_CMD_FW_DOWNLOAD = 0x15 + NFC_EVENT_SE_ADDED = 0x16 + NFC_EVENT_SE_REMOVED = 0x17 + NFC_EVENT_SE_CONNECTIVITY = 0x18 + NFC_EVENT_SE_TRANSACTION = 0x19 + NFC_CMD_GET_SE = 0x1a + NFC_CMD_SE_IO = 0x1b + NFC_CMD_ACTIVATE_TARGET = 0x1c + NFC_CMD_VENDOR = 0x1d + NFC_CMD_DEACTIVATE_TARGET = 0x1e + NFC_ATTR_UNSPEC = 0x0 + NFC_ATTR_DEVICE_INDEX = 0x1 + NFC_ATTR_DEVICE_NAME = 0x2 + NFC_ATTR_PROTOCOLS = 0x3 + NFC_ATTR_TARGET_INDEX = 0x4 + NFC_ATTR_TARGET_SENS_RES = 0x5 + NFC_ATTR_TARGET_SEL_RES = 0x6 + NFC_ATTR_TARGET_NFCID1 = 0x7 + NFC_ATTR_TARGET_SENSB_RES = 0x8 + NFC_ATTR_TARGET_SENSF_RES = 0x9 + NFC_ATTR_COMM_MODE = 0xa + NFC_ATTR_RF_MODE = 0xb + NFC_ATTR_DEVICE_POWERED = 0xc + NFC_ATTR_IM_PROTOCOLS = 0xd + NFC_ATTR_TM_PROTOCOLS = 0xe + NFC_ATTR_LLC_PARAM_LTO = 0xf + NFC_ATTR_LLC_PARAM_RW = 0x10 + NFC_ATTR_LLC_PARAM_MIUX = 0x11 + NFC_ATTR_SE = 0x12 + NFC_ATTR_LLC_SDP = 0x13 + NFC_ATTR_FIRMWARE_NAME = 0x14 + NFC_ATTR_SE_INDEX = 0x15 + NFC_ATTR_SE_TYPE = 0x16 + NFC_ATTR_SE_AID = 0x17 + NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS = 0x18 + NFC_ATTR_SE_APDU = 0x19 + NFC_ATTR_TARGET_ISO15693_DSFID = 0x1a + NFC_ATTR_TARGET_ISO15693_UID = 0x1b + NFC_ATTR_SE_PARAMS = 0x1c + NFC_ATTR_VENDOR_ID = 0x1d + NFC_ATTR_VENDOR_SUBCMD = 0x1e + NFC_ATTR_VENDOR_DATA = 0x1f + NFC_SDP_ATTR_UNSPEC = 0x0 + NFC_SDP_ATTR_URI = 0x1 + NFC_SDP_ATTR_SAP = 0x2 +) + +type LandlockRulesetAttr struct { + Access_fs uint64 + Access_net uint64 + Scoped uint64 +} + +type LandlockPathBeneathAttr struct { + Allowed_access uint64 + Parent_fd int32 +} + +const ( + LANDLOCK_RULE_PATH_BENEATH = 0x1 +) + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 + + ipc_64 = 0x100 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) + +type MountAttr struct { + Attr_set uint64 + Attr_clr uint64 + Propagation uint64 + Userns_fd uint64 +} + +const ( + WG_CMD_GET_DEVICE = 0x0 + WG_CMD_SET_DEVICE = 0x1 + WGDEVICE_F_REPLACE_PEERS = 0x1 + WGDEVICE_A_UNSPEC = 0x0 + WGDEVICE_A_IFINDEX = 0x1 + WGDEVICE_A_IFNAME = 0x2 + WGDEVICE_A_PRIVATE_KEY = 0x3 + WGDEVICE_A_PUBLIC_KEY = 0x4 + WGDEVICE_A_FLAGS = 0x5 + WGDEVICE_A_LISTEN_PORT = 0x6 + WGDEVICE_A_FWMARK = 0x7 + WGDEVICE_A_PEERS = 0x8 + WGPEER_F_REMOVE_ME = 0x1 + WGPEER_F_REPLACE_ALLOWEDIPS = 0x2 + WGPEER_F_UPDATE_ONLY = 0x4 + WGPEER_A_UNSPEC = 0x0 + WGPEER_A_PUBLIC_KEY = 0x1 + WGPEER_A_PRESHARED_KEY = 0x2 + WGPEER_A_FLAGS = 0x3 + WGPEER_A_ENDPOINT = 0x4 + WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL = 0x5 + WGPEER_A_LAST_HANDSHAKE_TIME = 0x6 + WGPEER_A_RX_BYTES = 0x7 + WGPEER_A_TX_BYTES = 0x8 + WGPEER_A_ALLOWEDIPS = 0x9 + WGPEER_A_PROTOCOL_VERSION = 0xa + WGALLOWEDIP_A_UNSPEC = 0x0 + WGALLOWEDIP_A_FAMILY = 0x1 + WGALLOWEDIP_A_IPADDR = 0x2 + WGALLOWEDIP_A_CIDR_MASK = 0x3 +) + +const ( + NL_ATTR_TYPE_INVALID = 0x0 + NL_ATTR_TYPE_FLAG = 0x1 + NL_ATTR_TYPE_U8 = 0x2 + NL_ATTR_TYPE_U16 = 0x3 + NL_ATTR_TYPE_U32 = 0x4 + NL_ATTR_TYPE_U64 = 0x5 + NL_ATTR_TYPE_S8 = 0x6 + NL_ATTR_TYPE_S16 = 0x7 + NL_ATTR_TYPE_S32 = 0x8 + NL_ATTR_TYPE_S64 = 0x9 + NL_ATTR_TYPE_BINARY = 0xa + NL_ATTR_TYPE_STRING = 0xb + NL_ATTR_TYPE_NUL_STRING = 0xc + NL_ATTR_TYPE_NESTED = 0xd + NL_ATTR_TYPE_NESTED_ARRAY = 0xe + NL_ATTR_TYPE_BITFIELD32 = 0xf + + NL_POLICY_TYPE_ATTR_UNSPEC = 0x0 + NL_POLICY_TYPE_ATTR_TYPE = 0x1 + NL_POLICY_TYPE_ATTR_MIN_VALUE_S = 0x2 + NL_POLICY_TYPE_ATTR_MAX_VALUE_S = 0x3 + NL_POLICY_TYPE_ATTR_MIN_VALUE_U = 0x4 + NL_POLICY_TYPE_ATTR_MAX_VALUE_U = 0x5 + NL_POLICY_TYPE_ATTR_MIN_LENGTH = 0x6 + NL_POLICY_TYPE_ATTR_MAX_LENGTH = 0x7 + NL_POLICY_TYPE_ATTR_POLICY_IDX = 0x8 + NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE = 0x9 + NL_POLICY_TYPE_ATTR_BITFIELD32_MASK = 0xa + NL_POLICY_TYPE_ATTR_PAD = 0xb + NL_POLICY_TYPE_ATTR_MASK = 0xc + NL_POLICY_TYPE_ATTR_MAX = 0xc +) + +type CANBitTiming struct { + Bitrate uint32 + Sample_point uint32 + Tq uint32 + Prop_seg uint32 + Phase_seg1 uint32 + Phase_seg2 uint32 + Sjw uint32 + Brp uint32 +} + +type CANBitTimingConst struct { + Name [16]uint8 + Tseg1_min uint32 + Tseg1_max uint32 + Tseg2_min uint32 + Tseg2_max uint32 + Sjw_max uint32 + Brp_min uint32 + Brp_max uint32 + Brp_inc uint32 +} + +type CANClock struct { + Freq uint32 +} + +type CANBusErrorCounters struct { + Txerr uint16 + Rxerr uint16 +} + +type CANCtrlMode struct { + Mask uint32 + Flags uint32 +} + +type CANDeviceStats struct { + Bus_error uint32 + Error_warning uint32 + Error_passive uint32 + Bus_off uint32 + Arbitration_lost uint32 + Restarts uint32 +} + +const ( + CAN_STATE_ERROR_ACTIVE = 0x0 + CAN_STATE_ERROR_WARNING = 0x1 + CAN_STATE_ERROR_PASSIVE = 0x2 + CAN_STATE_BUS_OFF = 0x3 + CAN_STATE_STOPPED = 0x4 + CAN_STATE_SLEEPING = 0x5 + CAN_STATE_MAX = 0x6 +) + +const ( + IFLA_CAN_UNSPEC = 0x0 + IFLA_CAN_BITTIMING = 0x1 + IFLA_CAN_BITTIMING_CONST = 0x2 + IFLA_CAN_CLOCK = 0x3 + IFLA_CAN_STATE = 0x4 + IFLA_CAN_CTRLMODE = 0x5 + IFLA_CAN_RESTART_MS = 0x6 + IFLA_CAN_RESTART = 0x7 + IFLA_CAN_BERR_COUNTER = 0x8 + IFLA_CAN_DATA_BITTIMING = 0x9 + IFLA_CAN_DATA_BITTIMING_CONST = 0xa + IFLA_CAN_TERMINATION = 0xb + IFLA_CAN_TERMINATION_CONST = 0xc + IFLA_CAN_BITRATE_CONST = 0xd + IFLA_CAN_DATA_BITRATE_CONST = 0xe + IFLA_CAN_BITRATE_MAX = 0xf +) + +type KCMAttach struct { + Fd int32 + Bpf_fd int32 +} + +type KCMUnattach struct { + Fd int32 +} + +type KCMClone struct { + Fd int32 +} + +const ( + NL80211_AC_BE = 0x2 + NL80211_AC_BK = 0x3 + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED = 0x0 + NL80211_ACL_POLICY_DENY_UNLESS_LISTED = 0x1 + NL80211_AC_VI = 0x1 + NL80211_AC_VO = 0x0 + NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = 0x1 + NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 0x2 + NL80211_AP_SME_SA_QUERY_OFFLOAD = 0x1 + NL80211_ATTR_4ADDR = 0x53 + NL80211_ATTR_ACK = 0x5c + NL80211_ATTR_ACK_SIGNAL = 0x107 + NL80211_ATTR_ACL_POLICY = 0xa5 + NL80211_ATTR_ADMITTED_TIME = 0xd4 + NL80211_ATTR_AIRTIME_WEIGHT = 0x112 + NL80211_ATTR_AKM_SUITES = 0x4c + NL80211_ATTR_AP_ISOLATE = 0x60 + NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135 + NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a + NL80211_ATTR_AUTH_DATA = 0x9c + NL80211_ATTR_AUTH_TYPE = 0x35 + NL80211_ATTR_BANDS = 0xef + NL80211_ATTR_BEACON_HEAD = 0xe + NL80211_ATTR_BEACON_INTERVAL = 0xc + NL80211_ATTR_BEACON_TAIL = 0xf + NL80211_ATTR_BG_SCAN_PERIOD = 0x98 + NL80211_ATTR_BSS_BASIC_RATES = 0x24 + NL80211_ATTR_BSS = 0x2f + NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147 + NL80211_ATTR_BSS_HT_OPMODE = 0x6d + NL80211_ATTR_BSSID = 0xf5 + NL80211_ATTR_BSS_SELECT = 0xe3 + NL80211_ATTR_BSS_SHORT_PREAMBLE = 0x1d + NL80211_ATTR_BSS_SHORT_SLOT_TIME = 0x1e + NL80211_ATTR_CENTER_FREQ1 = 0xa0 + NL80211_ATTR_CENTER_FREQ1_OFFSET = 0x123 + NL80211_ATTR_CENTER_FREQ2 = 0xa1 + NL80211_ATTR_CHANNEL_WIDTH = 0x9f + NL80211_ATTR_CH_SWITCH_BLOCK_TX = 0xb8 + NL80211_ATTR_CH_SWITCH_COUNT = 0xb7 + NL80211_ATTR_CIPHER_SUITE_GROUP = 0x4a + NL80211_ATTR_CIPHER_SUITES = 0x39 + NL80211_ATTR_CIPHER_SUITES_PAIRWISE = 0x49 + NL80211_ATTR_CNTDWN_OFFS_BEACON = 0xba + NL80211_ATTR_CNTDWN_OFFS_PRESP = 0xbb + NL80211_ATTR_COALESCE_RULE = 0xb6 + NL80211_ATTR_COALESCE_RULE_CONDITION = 0x2 + NL80211_ATTR_COALESCE_RULE_DELAY = 0x1 + NL80211_ATTR_COALESCE_RULE_MAX = 0x3 + NL80211_ATTR_COALESCE_RULE_PKT_PATTERN = 0x3 + NL80211_ATTR_COLOR_CHANGE_COLOR = 0x130 + NL80211_ATTR_COLOR_CHANGE_COUNT = 0x12f + NL80211_ATTR_COLOR_CHANGE_ELEMS = 0x131 + NL80211_ATTR_CONN_FAILED_REASON = 0x9b + NL80211_ATTR_CONTROL_PORT = 0x44 + NL80211_ATTR_CONTROL_PORT_ETHERTYPE = 0x66 + NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT = 0x67 + NL80211_ATTR_CONTROL_PORT_NO_PREAUTH = 0x11e + NL80211_ATTR_CONTROL_PORT_OVER_NL80211 = 0x108 + NL80211_ATTR_COOKIE = 0x58 + NL80211_ATTR_CQM_BEACON_LOSS_EVENT = 0x8 + NL80211_ATTR_CQM = 0x5e + NL80211_ATTR_CQM_MAX = 0x9 + NL80211_ATTR_CQM_PKT_LOSS_EVENT = 0x4 + NL80211_ATTR_CQM_RSSI_HYST = 0x2 + NL80211_ATTR_CQM_RSSI_LEVEL = 0x9 + NL80211_ATTR_CQM_RSSI_THOLD = 0x1 + NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT = 0x3 + NL80211_ATTR_CQM_TXE_INTVL = 0x7 + NL80211_ATTR_CQM_TXE_PKTS = 0x6 + NL80211_ATTR_CQM_TXE_RATE = 0x5 + NL80211_ATTR_CRIT_PROT_ID = 0xb3 + NL80211_ATTR_CSA_C_OFF_BEACON = 0xba + NL80211_ATTR_CSA_C_OFF_PRESP = 0xbb + NL80211_ATTR_CSA_C_OFFSETS_TX = 0xcd + NL80211_ATTR_CSA_IES = 0xb9 + NL80211_ATTR_DEVICE_AP_SME = 0x8d + NL80211_ATTR_DFS_CAC_TIME = 0x7 + NL80211_ATTR_DFS_REGION = 0x92 + NL80211_ATTR_DISABLE_EHT = 0x137 + NL80211_ATTR_DISABLE_HE = 0x12d + NL80211_ATTR_DISABLE_HT = 0x93 + NL80211_ATTR_DISABLE_VHT = 0xaf + NL80211_ATTR_DISCONNECTED_BY_AP = 0x47 + NL80211_ATTR_DONT_WAIT_FOR_ACK = 0x8e + NL80211_ATTR_DTIM_PERIOD = 0xd + NL80211_ATTR_DURATION = 0x57 + NL80211_ATTR_EHT_CAPABILITY = 0x136 + NL80211_ATTR_EMA_RNR_ELEMS = 0x145 + NL80211_ATTR_EML_CAPABILITY = 0x13d + NL80211_ATTR_EXT_CAPA = 0xa9 + NL80211_ATTR_EXT_CAPA_MASK = 0xaa + NL80211_ATTR_EXTERNAL_AUTH_ACTION = 0x104 + NL80211_ATTR_EXTERNAL_AUTH_SUPPORT = 0x105 + NL80211_ATTR_EXT_FEATURES = 0xd9 + NL80211_ATTR_FEATURE_FLAGS = 0x8f + NL80211_ATTR_FILS_CACHE_ID = 0xfd + NL80211_ATTR_FILS_DISCOVERY = 0x126 + NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM = 0xfb + NL80211_ATTR_FILS_ERP_REALM = 0xfa + NL80211_ATTR_FILS_ERP_RRK = 0xfc + NL80211_ATTR_FILS_ERP_USERNAME = 0xf9 + NL80211_ATTR_FILS_KEK = 0xf2 + NL80211_ATTR_FILS_NONCES = 0xf3 + NL80211_ATTR_FRAME = 0x33 + NL80211_ATTR_FRAME_MATCH = 0x5b + NL80211_ATTR_FRAME_TYPE = 0x65 + NL80211_ATTR_FREQ_AFTER = 0x3b + NL80211_ATTR_FREQ_BEFORE = 0x3a + NL80211_ATTR_FREQ_FIXED = 0x3c + NL80211_ATTR_FREQ_RANGE_END = 0x3 + NL80211_ATTR_FREQ_RANGE_MAX_BW = 0x4 + NL80211_ATTR_FREQ_RANGE_START = 0x2 + NL80211_ATTR_FTM_RESPONDER = 0x10e + NL80211_ATTR_FTM_RESPONDER_STATS = 0x10f + NL80211_ATTR_GENERATION = 0x2e + NL80211_ATTR_HANDLE_DFS = 0xbf + NL80211_ATTR_HE_6GHZ_CAPABILITY = 0x125 + NL80211_ATTR_HE_BSS_COLOR = 0x11b + NL80211_ATTR_HE_CAPABILITY = 0x10d + NL80211_ATTR_HE_OBSS_PD = 0x117 + NL80211_ATTR_HIDDEN_SSID = 0x7e + NL80211_ATTR_HT_CAPABILITY = 0x1f + NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144 + NL80211_ATTR_IE_ASSOC_RESP = 0x80 + NL80211_ATTR_IE = 0x2a + NL80211_ATTR_IE_PROBE_RESP = 0x7f + NL80211_ATTR_IE_RIC = 0xb2 + NL80211_ATTR_IFACE_SOCKET_OWNER = 0xcc + NL80211_ATTR_IFINDEX = 0x3 + NL80211_ATTR_IFNAME = 0x4 + NL80211_ATTR_IFTYPE_AKM_SUITES = 0x11c + NL80211_ATTR_IFTYPE = 0x5 + NL80211_ATTR_IFTYPE_EXT_CAPA = 0xe6 + NL80211_ATTR_INACTIVITY_TIMEOUT = 0x96 + NL80211_ATTR_INTERFACE_COMBINATIONS = 0x78 + NL80211_ATTR_KEY_CIPHER = 0x9 + NL80211_ATTR_KEY = 0x50 + NL80211_ATTR_KEY_DATA = 0x7 + NL80211_ATTR_KEY_DEFAULT = 0xb + NL80211_ATTR_KEY_DEFAULT_MGMT = 0x28 + NL80211_ATTR_KEY_DEFAULT_TYPES = 0x6e + NL80211_ATTR_KEY_IDX = 0x8 + NL80211_ATTR_KEYS = 0x51 + NL80211_ATTR_KEY_SEQ = 0xa + NL80211_ATTR_KEY_TYPE = 0x37 + NL80211_ATTR_LOCAL_MESH_POWER_MODE = 0xa4 + NL80211_ATTR_LOCAL_STATE_CHANGE = 0x5f + NL80211_ATTR_MAC_ACL_MAX = 0xa7 + NL80211_ATTR_MAC_ADDRS = 0xa6 + NL80211_ATTR_MAC = 0x6 + NL80211_ATTR_MAC_HINT = 0xc8 + NL80211_ATTR_MAC_MASK = 0xd7 + NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca + NL80211_ATTR_MAX = 0x151 + NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 + NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 + NL80211_ATTR_MAX_MATCH_SETS = 0x85 + NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c + NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 + NL80211_ATTR_MAX_NUM_SCAN_SSIDS = 0x2b + NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS = 0xde + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS = 0x7b + NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION = 0x6f + NL80211_ATTR_MAX_SCAN_IE_LEN = 0x38 + NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL = 0xdf + NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS = 0xe0 + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN = 0x7c + NL80211_ATTR_MBSSID_CONFIG = 0x132 + NL80211_ATTR_MBSSID_ELEMS = 0x133 + NL80211_ATTR_MCAST_RATE = 0x6b + NL80211_ATTR_MDID = 0xb1 + NL80211_ATTR_MEASUREMENT_DURATION = 0xeb + NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY = 0xec + NL80211_ATTR_MESH_CONFIG = 0x23 + NL80211_ATTR_MESH_ID = 0x18 + NL80211_ATTR_MESH_PEER_AID = 0xed + NL80211_ATTR_MESH_SETUP = 0x70 + NL80211_ATTR_MGMT_SUBTYPE = 0x29 + NL80211_ATTR_MLD_ADDR = 0x13a + NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e + NL80211_ATTR_MLO_LINK_DISABLED = 0x146 + NL80211_ATTR_MLO_LINK_ID = 0x139 + NL80211_ATTR_MLO_LINKS = 0x138 + NL80211_ATTR_MLO_SUPPORT = 0x13b + NL80211_ATTR_MLO_TTLM_DLINK = 0x148 + NL80211_ATTR_MLO_TTLM_ULINK = 0x149 + NL80211_ATTR_MNTR_FLAGS = 0x17 + NL80211_ATTR_MPATH_INFO = 0x1b + NL80211_ATTR_MPATH_NEXT_HOP = 0x1a + NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED = 0xf4 + NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR = 0xe8 + NL80211_ATTR_MU_MIMO_GROUP_DATA = 0xe7 + NL80211_ATTR_NAN_FUNC = 0xf0 + NL80211_ATTR_NAN_MASTER_PREF = 0xee + NL80211_ATTR_NAN_MATCH = 0xf1 + NL80211_ATTR_NETNS_FD = 0xdb + NL80211_ATTR_NOACK_MAP = 0x95 + NL80211_ATTR_NSS = 0x106 + NL80211_ATTR_OBSS_COLOR_BITMAP = 0x12e + NL80211_ATTR_OFFCHANNEL_TX_OK = 0x6c + NL80211_ATTR_OPER_CLASS = 0xd6 + NL80211_ATTR_OPMODE_NOTIF = 0xc2 + NL80211_ATTR_P2P_CTWINDOW = 0xa2 + NL80211_ATTR_P2P_OPPPS = 0xa3 + NL80211_ATTR_PAD = 0xe5 + NL80211_ATTR_PBSS = 0xe2 + NL80211_ATTR_PEER_AID = 0xb5 + NL80211_ATTR_PEER_MEASUREMENTS = 0x111 + NL80211_ATTR_PID = 0x52 + NL80211_ATTR_PMK = 0xfe + NL80211_ATTR_PMKID = 0x55 + NL80211_ATTR_PMK_LIFETIME = 0x11f + NL80211_ATTR_PMKR0_NAME = 0x102 + NL80211_ATTR_PMK_REAUTH_THRESHOLD = 0x120 + NL80211_ATTR_PMKSA_CANDIDATE = 0x86 + NL80211_ATTR_PORT_AUTHORIZED = 0x103 + NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 + NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_POWER_RULE_PSD = 0x8 + NL80211_ATTR_PREV_BSSID = 0x4f + NL80211_ATTR_PRIVACY = 0x46 + NL80211_ATTR_PROBE_RESP = 0x91 + NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 + NL80211_ATTR_PROTOCOL_FEATURES = 0xad + NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_PUNCT_BITMAP = 0x142 + NL80211_ATTR_QOS_MAP = 0xc7 + NL80211_ATTR_RADAR_BACKGROUND = 0x134 + NL80211_ATTR_RADAR_EVENT = 0xa8 + NL80211_ATTR_REASON_CODE = 0x36 + NL80211_ATTR_RECEIVE_MULTICAST = 0x121 + NL80211_ATTR_RECONNECT_REQUESTED = 0x12b + NL80211_ATTR_REG_ALPHA2 = 0x21 + NL80211_ATTR_REG_INDOOR = 0xdd + NL80211_ATTR_REG_INITIATOR = 0x30 + NL80211_ATTR_REG_RULE_FLAGS = 0x1 + NL80211_ATTR_REG_RULES = 0x22 + NL80211_ATTR_REG_TYPE = 0x31 + NL80211_ATTR_REKEY_DATA = 0x7a + NL80211_ATTR_REQ_IE = 0x4d + NL80211_ATTR_RESP_IE = 0x4e + NL80211_ATTR_ROAM_SUPPORT = 0x83 + NL80211_ATTR_RX_FRAME_TYPES = 0x64 + NL80211_ATTR_RX_HW_TIMESTAMP = 0x140 + NL80211_ATTR_RXMGMT_FLAGS = 0xbc + NL80211_ATTR_RX_SIGNAL_DBM = 0x97 + NL80211_ATTR_S1G_CAPABILITY = 0x128 + NL80211_ATTR_S1G_CAPABILITY_MASK = 0x129 + NL80211_ATTR_SAE_DATA = 0x9c + NL80211_ATTR_SAE_PASSWORD = 0x115 + NL80211_ATTR_SAE_PWE = 0x12a + NL80211_ATTR_SAR_SPEC = 0x12c + NL80211_ATTR_SCAN_FLAGS = 0x9e + NL80211_ATTR_SCAN_FREQ_KHZ = 0x124 + NL80211_ATTR_SCAN_FREQUENCIES = 0x2c + NL80211_ATTR_SCAN_GENERATION = 0x2e + NL80211_ATTR_SCAN_SSIDS = 0x2d + NL80211_ATTR_SCAN_START_TIME_TSF_BSSID = 0xea + NL80211_ATTR_SCAN_START_TIME_TSF = 0xe9 + NL80211_ATTR_SCAN_SUPP_RATES = 0x7d + NL80211_ATTR_SCHED_SCAN_DELAY = 0xdc + NL80211_ATTR_SCHED_SCAN_INTERVAL = 0x77 + NL80211_ATTR_SCHED_SCAN_MATCH = 0x84 + NL80211_ATTR_SCHED_SCAN_MATCH_SSID = 0x1 + NL80211_ATTR_SCHED_SCAN_MAX_REQS = 0x100 + NL80211_ATTR_SCHED_SCAN_MULTI = 0xff + NL80211_ATTR_SCHED_SCAN_PLANS = 0xe1 + NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI = 0xf6 + NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST = 0xf7 + NL80211_ATTR_SMPS_MODE = 0xd5 + NL80211_ATTR_SOCKET_OWNER = 0xcc + NL80211_ATTR_SOFTWARE_IFTYPES = 0x79 + NL80211_ATTR_SPLIT_WIPHY_DUMP = 0xae + NL80211_ATTR_SSID = 0x34 + NL80211_ATTR_STA_AID = 0x10 + NL80211_ATTR_STA_CAPABILITY = 0xab + NL80211_ATTR_STA_EXT_CAPABILITY = 0xac + NL80211_ATTR_STA_FLAGS2 = 0x43 + NL80211_ATTR_STA_FLAGS = 0x11 + NL80211_ATTR_STA_INFO = 0x15 + NL80211_ATTR_STA_LISTEN_INTERVAL = 0x12 + NL80211_ATTR_STA_PLINK_ACTION = 0x19 + NL80211_ATTR_STA_PLINK_STATE = 0x74 + NL80211_ATTR_STA_SUPPORTED_CHANNELS = 0xbd + NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES = 0xbe + NL80211_ATTR_STA_SUPPORTED_RATES = 0x13 + NL80211_ATTR_STA_SUPPORT_P2P_PS = 0xe4 + NL80211_ATTR_STATUS_CODE = 0x48 + NL80211_ATTR_STA_TX_POWER = 0x114 + NL80211_ATTR_STA_TX_POWER_SETTING = 0x113 + NL80211_ATTR_STA_VLAN = 0x14 + NL80211_ATTR_STA_WME = 0x81 + NL80211_ATTR_SUPPORT_10_MHZ = 0xc1 + NL80211_ATTR_SUPPORT_5_MHZ = 0xc0 + NL80211_ATTR_SUPPORT_AP_UAPSD = 0x82 + NL80211_ATTR_SUPPORTED_COMMANDS = 0x32 + NL80211_ATTR_SUPPORTED_IFTYPES = 0x20 + NL80211_ATTR_SUPPORT_IBSS_RSN = 0x68 + NL80211_ATTR_SUPPORT_MESH_AUTH = 0x73 + NL80211_ATTR_SURVEY_INFO = 0x54 + NL80211_ATTR_SURVEY_RADIO_STATS = 0xda + NL80211_ATTR_TD_BITMAP = 0x141 + NL80211_ATTR_TDLS_ACTION = 0x88 + NL80211_ATTR_TDLS_DIALOG_TOKEN = 0x89 + NL80211_ATTR_TDLS_EXTERNAL_SETUP = 0x8c + NL80211_ATTR_TDLS_INITIATOR = 0xcf + NL80211_ATTR_TDLS_OPERATION = 0x8a + NL80211_ATTR_TDLS_PEER_CAPABILITY = 0xcb + NL80211_ATTR_TDLS_SUPPORT = 0x8b + NL80211_ATTR_TESTDATA = 0x45 + NL80211_ATTR_TID_CONFIG = 0x11d + NL80211_ATTR_TIMED_OUT = 0x41 + NL80211_ATTR_TIMEOUT = 0x110 + NL80211_ATTR_TIMEOUT_REASON = 0xf8 + NL80211_ATTR_TSID = 0xd2 + NL80211_ATTR_TWT_RESPONDER = 0x116 + NL80211_ATTR_TX_FRAME_TYPES = 0x63 + NL80211_ATTR_TX_HW_TIMESTAMP = 0x13f + NL80211_ATTR_TX_NO_CCK_RATE = 0x87 + NL80211_ATTR_TXQ_LIMIT = 0x10a + NL80211_ATTR_TXQ_MEMORY_LIMIT = 0x10b + NL80211_ATTR_TXQ_QUANTUM = 0x10c + NL80211_ATTR_TXQ_STATS = 0x109 + NL80211_ATTR_TX_RATES = 0x5a + NL80211_ATTR_UNSOL_BCAST_PROBE_RESP = 0x127 + NL80211_ATTR_UNSPEC = 0x0 + NL80211_ATTR_USE_MFP = 0x42 + NL80211_ATTR_USER_PRIO = 0xd3 + NL80211_ATTR_USER_REG_HINT_TYPE = 0x9a + NL80211_ATTR_USE_RRM = 0xd0 + NL80211_ATTR_VENDOR_DATA = 0xc5 + NL80211_ATTR_VENDOR_EVENTS = 0xc6 + NL80211_ATTR_VENDOR_ID = 0xc3 + NL80211_ATTR_VENDOR_SUBCMD = 0xc4 + NL80211_ATTR_VHT_CAPABILITY = 0x9d + NL80211_ATTR_VHT_CAPABILITY_MASK = 0xb0 + NL80211_ATTR_VLAN_ID = 0x11a + NL80211_ATTR_WANT_1X_4WAY_HS = 0x101 + NL80211_ATTR_WDEV = 0x99 + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX = 0x72 + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX = 0x71 + NL80211_ATTR_WIPHY_ANTENNA_RX = 0x6a + NL80211_ATTR_WIPHY_ANTENNA_TX = 0x69 + NL80211_ATTR_WIPHY_BANDS = 0x16 + NL80211_ATTR_WIPHY_CHANNEL_TYPE = 0x27 + NL80211_ATTR_WIPHY = 0x1 + NL80211_ATTR_WIPHY_COVERAGE_CLASS = 0x59 + NL80211_ATTR_WIPHY_DYN_ACK = 0xd1 + NL80211_ATTR_WIPHY_EDMG_BW_CONFIG = 0x119 + NL80211_ATTR_WIPHY_EDMG_CHANNELS = 0x118 + NL80211_ATTR_WIPHY_FRAG_THRESHOLD = 0x3f + NL80211_ATTR_WIPHY_FREQ = 0x26 + NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 + NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c + NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RADIOS = 0x14b + NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e + NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d + NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 + NL80211_ATTR_WIPHY_SELF_MANAGED_REG = 0xd8 + NL80211_ATTR_WIPHY_TX_POWER_LEVEL = 0x62 + NL80211_ATTR_WIPHY_TX_POWER_SETTING = 0x61 + NL80211_ATTR_WIPHY_TXQ_PARAMS = 0x25 + NL80211_ATTR_WOWLAN_TRIGGERS = 0x75 + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED = 0x76 + NL80211_ATTR_WPA_VERSIONS = 0x4b + NL80211_AUTHTYPE_AUTOMATIC = 0x8 + NL80211_AUTHTYPE_FILS_PK = 0x7 + NL80211_AUTHTYPE_FILS_SK = 0x5 + NL80211_AUTHTYPE_FILS_SK_PFS = 0x6 + NL80211_AUTHTYPE_FT = 0x2 + NL80211_AUTHTYPE_MAX = 0x7 + NL80211_AUTHTYPE_NETWORK_EAP = 0x3 + NL80211_AUTHTYPE_OPEN_SYSTEM = 0x0 + NL80211_AUTHTYPE_SAE = 0x4 + NL80211_AUTHTYPE_SHARED_KEY = 0x1 + NL80211_BAND_2GHZ = 0x0 + NL80211_BAND_5GHZ = 0x1 + NL80211_BAND_60GHZ = 0x2 + NL80211_BAND_6GHZ = 0x3 + NL80211_BAND_ATTR_EDMG_BW_CONFIG = 0xb + NL80211_BAND_ATTR_EDMG_CHANNELS = 0xa + NL80211_BAND_ATTR_FREQS = 0x1 + NL80211_BAND_ATTR_HT_AMPDU_DENSITY = 0x6 + NL80211_BAND_ATTR_HT_AMPDU_FACTOR = 0x5 + NL80211_BAND_ATTR_HT_CAPA = 0x4 + NL80211_BAND_ATTR_HT_MCS_SET = 0x3 + NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 + NL80211_BAND_ATTR_MAX = 0xd + NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_S1G_CAPA = 0xd + NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc + NL80211_BAND_ATTR_VHT_CAPA = 0x8 + NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8 + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET = 0xa + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY = 0x9 + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE = 0xb + NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA = 0x6 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC = 0x2 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET = 0x4 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY = 0x3 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE = 0x5 + NL80211_BAND_IFTYPE_ATTR_IFTYPES = 0x1 + NL80211_BAND_IFTYPE_ATTR_MAX = 0xb + NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS = 0x7 + NL80211_BAND_LC = 0x5 + NL80211_BAND_S1GHZ = 0x4 + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE = 0x2 + NL80211_BITRATE_ATTR_MAX = 0x2 + NL80211_BITRATE_ATTR_RATE = 0x1 + NL80211_BSS_BEACON_IES = 0xb + NL80211_BSS_BEACON_INTERVAL = 0x4 + NL80211_BSS_BEACON_TSF = 0xd + NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2 + NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1 + NL80211_BSS_CANNOT_USE_REASONS = 0x18 + NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2 + NL80211_BSS_CAPABILITY = 0x5 + NL80211_BSS_CHAIN_SIGNAL = 0x13 + NL80211_BSS_CHAN_WIDTH_10 = 0x1 + NL80211_BSS_CHAN_WIDTH_1 = 0x3 + NL80211_BSS_CHAN_WIDTH_20 = 0x0 + NL80211_BSS_CHAN_WIDTH_2 = 0x4 + NL80211_BSS_CHAN_WIDTH_5 = 0x2 + NL80211_BSS_CHAN_WIDTH = 0xc + NL80211_BSS_FREQUENCY = 0x2 + NL80211_BSS_FREQUENCY_OFFSET = 0x14 + NL80211_BSS_INFORMATION_ELEMENTS = 0x6 + NL80211_BSS_LAST_SEEN_BOOTTIME = 0xf + NL80211_BSS_MAX = 0x18 + NL80211_BSS_MLD_ADDR = 0x16 + NL80211_BSS_MLO_LINK_ID = 0x15 + NL80211_BSS_PAD = 0x10 + NL80211_BSS_PARENT_BSSID = 0x12 + NL80211_BSS_PARENT_TSF = 0x11 + NL80211_BSS_PRESP_DATA = 0xe + NL80211_BSS_SEEN_MS_AGO = 0xa + NL80211_BSS_SELECT_ATTR_BAND_PREF = 0x2 + NL80211_BSS_SELECT_ATTR_MAX = 0x3 + NL80211_BSS_SELECT_ATTR_RSSI_ADJUST = 0x3 + NL80211_BSS_SELECT_ATTR_RSSI = 0x1 + NL80211_BSS_SIGNAL_MBM = 0x7 + NL80211_BSS_SIGNAL_UNSPEC = 0x8 + NL80211_BSS_STATUS_ASSOCIATED = 0x1 + NL80211_BSS_STATUS_AUTHENTICATED = 0x0 + NL80211_BSS_STATUS = 0x9 + NL80211_BSS_STATUS_IBSS_JOINED = 0x2 + NL80211_BSS_TSF = 0x3 + NL80211_BSS_USE_FOR = 0x17 + NL80211_BSS_USE_FOR_MLD_LINK = 0x2 + NL80211_BSS_USE_FOR_NORMAL = 0x1 + NL80211_CHAN_HT20 = 0x1 + NL80211_CHAN_HT40MINUS = 0x2 + NL80211_CHAN_HT40PLUS = 0x3 + NL80211_CHAN_NO_HT = 0x0 + NL80211_CHAN_WIDTH_10 = 0x7 + NL80211_CHAN_WIDTH_160 = 0x5 + NL80211_CHAN_WIDTH_16 = 0xc + NL80211_CHAN_WIDTH_1 = 0x8 + NL80211_CHAN_WIDTH_20 = 0x1 + NL80211_CHAN_WIDTH_20_NOHT = 0x0 + NL80211_CHAN_WIDTH_2 = 0x9 + NL80211_CHAN_WIDTH_320 = 0xd + NL80211_CHAN_WIDTH_40 = 0x2 + NL80211_CHAN_WIDTH_4 = 0xa + NL80211_CHAN_WIDTH_5 = 0x6 + NL80211_CHAN_WIDTH_80 = 0x3 + NL80211_CHAN_WIDTH_80P80 = 0x4 + NL80211_CHAN_WIDTH_8 = 0xb + NL80211_CMD_ABORT_SCAN = 0x72 + NL80211_CMD_ACTION = 0x3b + NL80211_CMD_ACTION_TX_STATUS = 0x3c + NL80211_CMD_ADD_LINK = 0x94 + NL80211_CMD_ADD_LINK_STA = 0x96 + NL80211_CMD_ADD_NAN_FUNCTION = 0x75 + NL80211_CMD_ADD_TX_TS = 0x69 + NL80211_CMD_ASSOC_COMEBACK = 0x93 + NL80211_CMD_ASSOCIATE = 0x26 + NL80211_CMD_AUTHENTICATE = 0x25 + NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL = 0x38 + NL80211_CMD_CHANGE_NAN_CONFIG = 0x77 + NL80211_CMD_CHANNEL_SWITCH = 0x66 + NL80211_CMD_CH_SWITCH_NOTIFY = 0x58 + NL80211_CMD_CH_SWITCH_STARTED_NOTIFY = 0x6e + NL80211_CMD_COLOR_CHANGE_ABORTED = 0x90 + NL80211_CMD_COLOR_CHANGE_COMPLETED = 0x91 + NL80211_CMD_COLOR_CHANGE_REQUEST = 0x8e + NL80211_CMD_COLOR_CHANGE_STARTED = 0x8f + NL80211_CMD_CONNECT = 0x2e + NL80211_CMD_CONN_FAILED = 0x5b + NL80211_CMD_CONTROL_PORT_FRAME = 0x81 + NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS = 0x8b + NL80211_CMD_CRIT_PROTOCOL_START = 0x62 + NL80211_CMD_CRIT_PROTOCOL_STOP = 0x63 + NL80211_CMD_DEAUTHENTICATE = 0x27 + NL80211_CMD_DEL_BEACON = 0x10 + NL80211_CMD_DEL_INTERFACE = 0x8 + NL80211_CMD_DEL_KEY = 0xc + NL80211_CMD_DEL_MPATH = 0x18 + NL80211_CMD_DEL_NAN_FUNCTION = 0x76 + NL80211_CMD_DEL_PMK = 0x7c + NL80211_CMD_DEL_PMKSA = 0x35 + NL80211_CMD_DEL_STATION = 0x14 + NL80211_CMD_DEL_TX_TS = 0x6a + NL80211_CMD_DEL_WIPHY = 0x4 + NL80211_CMD_DISASSOCIATE = 0x28 + NL80211_CMD_DISCONNECT = 0x30 + NL80211_CMD_EXTERNAL_AUTH = 0x7f + NL80211_CMD_FLUSH_PMKSA = 0x36 + NL80211_CMD_FRAME = 0x3b + NL80211_CMD_FRAME_TX_STATUS = 0x3c + NL80211_CMD_FRAME_WAIT_CANCEL = 0x43 + NL80211_CMD_FT_EVENT = 0x61 + NL80211_CMD_GET_BEACON = 0xd + NL80211_CMD_GET_COALESCE = 0x64 + NL80211_CMD_GET_FTM_RESPONDER_STATS = 0x82 + NL80211_CMD_GET_INTERFACE = 0x5 + NL80211_CMD_GET_KEY = 0x9 + NL80211_CMD_GET_MESH_CONFIG = 0x1c + NL80211_CMD_GET_MESH_PARAMS = 0x1c + NL80211_CMD_GET_MPATH = 0x15 + NL80211_CMD_GET_MPP = 0x6b + NL80211_CMD_GET_POWER_SAVE = 0x3e + NL80211_CMD_GET_PROTOCOL_FEATURES = 0x5f + NL80211_CMD_GET_REG = 0x1f + NL80211_CMD_GET_SCAN = 0x20 + NL80211_CMD_GET_STATION = 0x11 + NL80211_CMD_GET_SURVEY = 0x32 + NL80211_CMD_GET_WIPHY = 0x1 + NL80211_CMD_GET_WOWLAN = 0x49 + NL80211_CMD_JOIN_IBSS = 0x2b + NL80211_CMD_JOIN_MESH = 0x44 + NL80211_CMD_JOIN_OCB = 0x6c + NL80211_CMD_LEAVE_IBSS = 0x2c + NL80211_CMD_LEAVE_MESH = 0x45 + NL80211_CMD_LEAVE_OCB = 0x6d + NL80211_CMD_LINKS_REMOVED = 0x9a + NL80211_CMD_MAX = 0x9d + NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 + NL80211_CMD_MODIFY_LINK_STA = 0x97 + NL80211_CMD_NAN_MATCH = 0x78 + NL80211_CMD_NEW_BEACON = 0xf + NL80211_CMD_NEW_INTERFACE = 0x7 + NL80211_CMD_NEW_KEY = 0xb + NL80211_CMD_NEW_MPATH = 0x17 + NL80211_CMD_NEW_PEER_CANDIDATE = 0x48 + NL80211_CMD_NEW_SCAN_RESULTS = 0x22 + NL80211_CMD_NEW_STATION = 0x13 + NL80211_CMD_NEW_SURVEY_RESULTS = 0x33 + NL80211_CMD_NEW_WIPHY = 0x3 + NL80211_CMD_NOTIFY_CQM = 0x40 + NL80211_CMD_NOTIFY_RADAR = 0x86 + NL80211_CMD_OBSS_COLOR_COLLISION = 0x8d + NL80211_CMD_PEER_MEASUREMENT_COMPLETE = 0x85 + NL80211_CMD_PEER_MEASUREMENT_RESULT = 0x84 + NL80211_CMD_PEER_MEASUREMENT_START = 0x83 + NL80211_CMD_PMKSA_CANDIDATE = 0x50 + NL80211_CMD_PORT_AUTHORIZED = 0x7d + NL80211_CMD_PROBE_CLIENT = 0x54 + NL80211_CMD_PROBE_MESH_LINK = 0x88 + NL80211_CMD_RADAR_DETECT = 0x5e + NL80211_CMD_REG_BEACON_HINT = 0x2a + NL80211_CMD_REG_CHANGE = 0x24 + NL80211_CMD_REGISTER_ACTION = 0x3a + NL80211_CMD_REGISTER_BEACONS = 0x55 + NL80211_CMD_REGISTER_FRAME = 0x3a + NL80211_CMD_RELOAD_REGDB = 0x7e + NL80211_CMD_REMAIN_ON_CHANNEL = 0x37 + NL80211_CMD_REMOVE_LINK = 0x95 + NL80211_CMD_REMOVE_LINK_STA = 0x98 + NL80211_CMD_REQ_SET_REG = 0x1b + NL80211_CMD_ROAM = 0x2f + NL80211_CMD_SCAN_ABORTED = 0x23 + NL80211_CMD_SCHED_SCAN_RESULTS = 0x4d + NL80211_CMD_SCHED_SCAN_STOPPED = 0x4e + NL80211_CMD_SET_BEACON = 0xe + NL80211_CMD_SET_BSS = 0x19 + NL80211_CMD_SET_CHANNEL = 0x41 + NL80211_CMD_SET_COALESCE = 0x65 + NL80211_CMD_SET_CQM = 0x3f + NL80211_CMD_SET_FILS_AAD = 0x92 + NL80211_CMD_SET_HW_TIMESTAMP = 0x99 + NL80211_CMD_SET_INTERFACE = 0x6 + NL80211_CMD_SET_KEY = 0xa + NL80211_CMD_SET_MAC_ACL = 0x5d + NL80211_CMD_SET_MCAST_RATE = 0x5c + NL80211_CMD_SET_MESH_CONFIG = 0x1d + NL80211_CMD_SET_MESH_PARAMS = 0x1d + NL80211_CMD_SET_MGMT_EXTRA_IE = 0x1e + NL80211_CMD_SET_MPATH = 0x16 + NL80211_CMD_SET_MULTICAST_TO_UNICAST = 0x79 + NL80211_CMD_SET_NOACK_MAP = 0x57 + NL80211_CMD_SET_PMK = 0x7b + NL80211_CMD_SET_PMKSA = 0x34 + NL80211_CMD_SET_POWER_SAVE = 0x3d + NL80211_CMD_SET_QOS_MAP = 0x68 + NL80211_CMD_SET_REG = 0x1a + NL80211_CMD_SET_REKEY_OFFLOAD = 0x4f + NL80211_CMD_SET_SAR_SPECS = 0x8c + NL80211_CMD_SET_STATION = 0x12 + NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b + NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 + NL80211_CMD_SET_WDS_PEER = 0x42 + NL80211_CMD_SET_WIPHY = 0x2 + NL80211_CMD_SET_WIPHY_NETNS = 0x31 + NL80211_CMD_SET_WOWLAN = 0x4a + NL80211_CMD_STA_OPMODE_CHANGED = 0x80 + NL80211_CMD_START_AP = 0xf + NL80211_CMD_START_NAN = 0x73 + NL80211_CMD_START_P2P_DEVICE = 0x59 + NL80211_CMD_START_SCHED_SCAN = 0x4b + NL80211_CMD_STOP_AP = 0x10 + NL80211_CMD_STOP_NAN = 0x74 + NL80211_CMD_STOP_P2P_DEVICE = 0x5a + NL80211_CMD_STOP_SCHED_SCAN = 0x4c + NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH = 0x70 + NL80211_CMD_TDLS_CHANNEL_SWITCH = 0x6f + NL80211_CMD_TDLS_MGMT = 0x52 + NL80211_CMD_TDLS_OPER = 0x51 + NL80211_CMD_TESTMODE = 0x2d + NL80211_CMD_TRIGGER_SCAN = 0x21 + NL80211_CMD_UNEXPECTED_4ADDR_FRAME = 0x56 + NL80211_CMD_UNEXPECTED_FRAME = 0x53 + NL80211_CMD_UNPROT_BEACON = 0x8a + NL80211_CMD_UNPROT_DEAUTHENTICATE = 0x46 + NL80211_CMD_UNPROT_DISASSOCIATE = 0x47 + NL80211_CMD_UNSPEC = 0x0 + NL80211_CMD_UPDATE_CONNECT_PARAMS = 0x7a + NL80211_CMD_UPDATE_FT_IES = 0x60 + NL80211_CMD_UPDATE_OWE_INFO = 0x87 + NL80211_CMD_VENDOR = 0x67 + NL80211_CMD_WIPHY_REG_CHANGE = 0x71 + NL80211_COALESCE_CONDITION_MATCH = 0x0 + NL80211_COALESCE_CONDITION_NO_MATCH = 0x1 + NL80211_CONN_FAIL_BLOCKED_CLIENT = 0x1 + NL80211_CONN_FAIL_MAX_CLIENTS = 0x0 + NL80211_CQM_RSSI_BEACON_LOSS_EVENT = 0x2 + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH = 0x1 + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW = 0x0 + NL80211_CQM_TXE_MAX_INTVL = 0x708 + NL80211_CRIT_PROTO_APIPA = 0x3 + NL80211_CRIT_PROTO_DHCP = 0x1 + NL80211_CRIT_PROTO_EAPOL = 0x2 + NL80211_CRIT_PROTO_MAX_DURATION = 0x1388 + NL80211_CRIT_PROTO_UNSPEC = 0x0 + NL80211_DFS_AVAILABLE = 0x2 + NL80211_DFS_ETSI = 0x2 + NL80211_DFS_FCC = 0x1 + NL80211_DFS_JP = 0x3 + NL80211_DFS_UNAVAILABLE = 0x1 + NL80211_DFS_UNSET = 0x0 + NL80211_DFS_USABLE = 0x0 + NL80211_EDMG_BW_CONFIG_MAX = 0xf + NL80211_EDMG_BW_CONFIG_MIN = 0x4 + NL80211_EDMG_CHANNELS_MAX = 0x3c + NL80211_EDMG_CHANNELS_MIN = 0x1 + NL80211_EHT_MAX_CAPABILITY_LEN = 0x33 + NL80211_EHT_MIN_CAPABILITY_LEN = 0xd + NL80211_EXTERNAL_AUTH_ABORT = 0x1 + NL80211_EXTERNAL_AUTH_START = 0x0 + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK = 0x32 + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X = 0x10 + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK = 0xf + NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP = 0x12 + NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT = 0x1b + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 + NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 + NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40 + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e + NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 + NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 + NL80211_EXT_FEATURE_BEACON_RATE_HT = 0x7 + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY = 0x6 + NL80211_EXT_FEATURE_BEACON_RATE_VHT = 0x8 + NL80211_EXT_FEATURE_BSS_COLOR = 0x3a + NL80211_EXT_FEATURE_BSS_PARENT_TSF = 0x4 + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 = 0x1f + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH = 0x2a + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211 = 0x1a + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS = 0x30 + NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd + NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b + NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43 + NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 + NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 + NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD = 0x3b + NL80211_EXT_FEATURE_FILS_DISCOVERY = 0x34 + NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME = 0x11 + NL80211_EXT_FEATURE_FILS_SK_OFFLOAD = 0xe + NL80211_EXT_FEATURE_FILS_STA = 0x9 + NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN = 0x18 + NL80211_EXT_FEATURE_LOW_POWER_SCAN = 0x17 + NL80211_EXT_FEATURE_LOW_SPAN_SCAN = 0x16 + NL80211_EXT_FEATURE_MFP_OPTIONAL = 0x15 + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA = 0xa + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED = 0xb + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS = 0x2d + NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER = 0x2 + NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 + NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 + NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42 + NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41 + NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d + NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_PUNCT = 0x3e + NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c + NL80211_EXT_FEATURE_RRM = 0x1 + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 + NL80211_EXT_FEATURE_SAE_OFFLOAD = 0x26 + NL80211_EXT_FEATURE_SCAN_FREQ_KHZ = 0x2f + NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT = 0x1e + NL80211_EXT_FEATURE_SCAN_RANDOM_SN = 0x1d + NL80211_EXT_FEATURE_SCAN_START_TIME = 0x3 + NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 + NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc + NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_NAN = 0x3f + NL80211_EXT_FEATURE_SECURE_RTT = 0x38 + NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44 + NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 + NL80211_EXT_FEATURE_TXQS = 0x1c + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 + NL80211_EXT_FEATURE_VHT_IBSS = 0x0 + NL80211_EXT_FEATURE_VLAN_OFFLOAD = 0x27 + NL80211_FEATURE_ACKTO_ESTIMATION = 0x800000 + NL80211_FEATURE_ACTIVE_MONITOR = 0x20000 + NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 0x4000 + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = 0x40000 + NL80211_FEATURE_AP_SCAN = 0x100 + NL80211_FEATURE_CELL_BASE_REG_HINTS = 0x8 + NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = 0x80000 + NL80211_FEATURE_DYNAMIC_SMPS = 0x2000000 + NL80211_FEATURE_FULL_AP_CLIENT_STATE = 0x8000 + NL80211_FEATURE_HT_IBSS = 0x2 + NL80211_FEATURE_INACTIVITY_TIMER = 0x4 + NL80211_FEATURE_LOW_PRIORITY_SCAN = 0x40 + NL80211_FEATURE_MAC_ON_CREATE = 0x8000000 + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 0x80000000 + NL80211_FEATURE_NEED_OBSS_SCAN = 0x400 + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 0x10 + NL80211_FEATURE_P2P_GO_CTWIN = 0x800 + NL80211_FEATURE_P2P_GO_OPPPS = 0x1000 + NL80211_FEATURE_QUIET = 0x200000 + NL80211_FEATURE_SAE = 0x20 + NL80211_FEATURE_SCAN_FLUSH = 0x80 + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 0x20000000 + NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 0x40000000 + NL80211_FEATURE_SK_TX_STATUS = 0x1 + NL80211_FEATURE_STATIC_SMPS = 0x1000000 + NL80211_FEATURE_SUPPORTS_WMM_ADMISSION = 0x4000000 + NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 0x10000000 + NL80211_FEATURE_TX_POWER_INSERTION = 0x400000 + NL80211_FEATURE_USERSPACE_MPM = 0x10000 + NL80211_FEATURE_VIF_TXPOWER = 0x200 + NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = 0x100000 + NL80211_FILS_DISCOVERY_ATTR_INT_MAX = 0x2 + NL80211_FILS_DISCOVERY_ATTR_INT_MIN = 0x1 + NL80211_FILS_DISCOVERY_ATTR_MAX = 0x3 + NL80211_FILS_DISCOVERY_ATTR_TMPL = 0x3 + NL80211_FILS_DISCOVERY_TMPL_MIN_LEN = 0x2a + NL80211_FREQUENCY_ATTR_16MHZ = 0x19 + NL80211_FREQUENCY_ATTR_1MHZ = 0x15 + NL80211_FREQUENCY_ATTR_2MHZ = 0x16 + NL80211_FREQUENCY_ATTR_4MHZ = 0x17 + NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21 + NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20 + NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d + NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 + NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 + NL80211_FREQUENCY_ATTR_DISABLED = 0x2 + NL80211_FREQUENCY_ATTR_FREQ = 0x1 + NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf + NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe + NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf + NL80211_FREQUENCY_ATTR_MAX = 0x22 + NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 + NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 + NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc + NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 + NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e + NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb + NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b + NL80211_FREQUENCY_ATTR_NO_HE = 0x13 + NL80211_FREQUENCY_ATTR_NO_HT40_MINUS = 0x9 + NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa + NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 + NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f + NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e + NL80211_FREQUENCY_ATTR_OFFSET = 0x14 + NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_PSD = 0x1c + NL80211_FREQUENCY_ATTR_RADAR = 0x5 + NL80211_FREQUENCY_ATTR_WMM = 0x12 + NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 + NL80211_FTM_RESP_ATTR_ENABLED = 0x1 + NL80211_FTM_RESP_ATTR_LCI = 0x2 + NL80211_FTM_RESP_ATTR_MAX = 0x3 + NL80211_FTM_STATS_ASAP_NUM = 0x4 + NL80211_FTM_STATS_FAILED_NUM = 0x3 + NL80211_FTM_STATS_MAX = 0xa + NL80211_FTM_STATS_NON_ASAP_NUM = 0x5 + NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM = 0x9 + NL80211_FTM_STATS_PAD = 0xa + NL80211_FTM_STATS_PARTIAL_NUM = 0x2 + NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM = 0x8 + NL80211_FTM_STATS_SUCCESS_NUM = 0x1 + NL80211_FTM_STATS_TOTAL_DURATION_MSEC = 0x6 + NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM = 0x7 + NL80211_GENL_NAME = "nl80211" + NL80211_HE_BSS_COLOR_ATTR_COLOR = 0x1 + NL80211_HE_BSS_COLOR_ATTR_DISABLED = 0x2 + NL80211_HE_BSS_COLOR_ATTR_MAX = 0x3 + NL80211_HE_BSS_COLOR_ATTR_PARTIAL = 0x3 + NL80211_HE_MAX_CAPABILITY_LEN = 0x36 + NL80211_HE_MIN_CAPABILITY_LEN = 0x10 + NL80211_HE_NSS_MAX = 0x8 + NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP = 0x4 + NL80211_HE_OBSS_PD_ATTR_MAX = 0x6 + NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET = 0x2 + NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET = 0x1 + NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET = 0x3 + NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP = 0x5 + NL80211_HE_OBSS_PD_ATTR_SR_CTRL = 0x6 + NL80211_HIDDEN_SSID_NOT_IN_USE = 0x0 + NL80211_HIDDEN_SSID_ZERO_CONTENTS = 0x2 + NL80211_HIDDEN_SSID_ZERO_LEN = 0x1 + NL80211_HT_CAPABILITY_LEN = 0x1a + NL80211_IFACE_COMB_BI_MIN_GCD = 0x7 + NL80211_IFACE_COMB_LIMITS = 0x1 + NL80211_IFACE_COMB_MAXNUM = 0x2 + NL80211_IFACE_COMB_NUM_CHANNELS = 0x4 + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS = 0x6 + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS = 0x5 + NL80211_IFACE_COMB_STA_AP_BI_MATCH = 0x3 + NL80211_IFACE_COMB_UNSPEC = 0x0 + NL80211_IFACE_LIMIT_MAX = 0x1 + NL80211_IFACE_LIMIT_TYPES = 0x2 + NL80211_IFACE_LIMIT_UNSPEC = 0x0 + NL80211_IFTYPE_ADHOC = 0x1 + NL80211_IFTYPE_AKM_ATTR_IFTYPES = 0x1 + NL80211_IFTYPE_AKM_ATTR_MAX = 0x2 + NL80211_IFTYPE_AKM_ATTR_SUITES = 0x2 + NL80211_IFTYPE_AP = 0x3 + NL80211_IFTYPE_AP_VLAN = 0x4 + NL80211_IFTYPE_MAX = 0xc + NL80211_IFTYPE_MESH_POINT = 0x7 + NL80211_IFTYPE_MONITOR = 0x6 + NL80211_IFTYPE_NAN = 0xc + NL80211_IFTYPE_OCB = 0xb + NL80211_IFTYPE_P2P_CLIENT = 0x8 + NL80211_IFTYPE_P2P_DEVICE = 0xa + NL80211_IFTYPE_P2P_GO = 0x9 + NL80211_IFTYPE_STATION = 0x2 + NL80211_IFTYPE_UNSPECIFIED = 0x0 + NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN_32 = 0x20 + NL80211_KCK_EXT_LEN = 0x18 + NL80211_KCK_LEN = 0x10 + NL80211_KEK_EXT_LEN = 0x20 + NL80211_KEK_LEN = 0x10 + NL80211_KEY_CIPHER = 0x3 + NL80211_KEY_DATA = 0x1 + NL80211_KEY_DEFAULT_BEACON = 0xa + NL80211_KEY_DEFAULT = 0x5 + NL80211_KEY_DEFAULT_MGMT = 0x6 + NL80211_KEY_DEFAULT_TYPE_MULTICAST = 0x2 + NL80211_KEY_DEFAULT_TYPES = 0x8 + NL80211_KEY_DEFAULT_TYPE_UNICAST = 0x1 + NL80211_KEY_IDX = 0x2 + NL80211_KEY_MAX = 0xa + NL80211_KEY_MODE = 0x9 + NL80211_KEY_NO_TX = 0x1 + NL80211_KEY_RX_TX = 0x0 + NL80211_KEY_SEQ = 0x4 + NL80211_KEY_SET_TX = 0x2 + NL80211_KEY_TYPE = 0x7 + NL80211_KEYTYPE_GROUP = 0x0 + NL80211_KEYTYPE_PAIRWISE = 0x1 + NL80211_KEYTYPE_PEERKEY = 0x2 + NL80211_MAX_NR_AKM_SUITES = 0x2 + NL80211_MAX_NR_CIPHER_SUITES = 0x5 + NL80211_MAX_SUPP_HT_RATES = 0x4d + NL80211_MAX_SUPP_RATES = 0x20 + NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MAX_SUPP_SELECTORS = 0x80 + NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5 + NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3 + NL80211_MBSSID_CONFIG_ATTR_MAX = 0x6 + NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY = 0x2 + NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES = 0x1 + NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX = 0x4 + NL80211_MESHCONF_ATTR_MAX = 0x1f + NL80211_MESHCONF_AUTO_OPEN_PLINKS = 0x7 + NL80211_MESHCONF_AWAKE_WINDOW = 0x1b + NL80211_MESHCONF_CONFIRM_TIMEOUT = 0x2 + NL80211_MESHCONF_CONNECTED_TO_AS = 0x1f + NL80211_MESHCONF_CONNECTED_TO_GATE = 0x1d + NL80211_MESHCONF_ELEMENT_TTL = 0xf + NL80211_MESHCONF_FORWARDING = 0x13 + NL80211_MESHCONF_GATE_ANNOUNCEMENTS = 0x11 + NL80211_MESHCONF_HOLDING_TIMEOUT = 0x3 + NL80211_MESHCONF_HT_OPMODE = 0x16 + NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT = 0xb + NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL = 0x19 + NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES = 0x8 + NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME = 0xd + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT = 0x17 + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL = 0x12 + NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL = 0xc + NL80211_MESHCONF_HWMP_RANN_INTERVAL = 0x10 + NL80211_MESHCONF_HWMP_ROOT_INTERVAL = 0x18 + NL80211_MESHCONF_HWMP_ROOTMODE = 0xe + NL80211_MESHCONF_MAX_PEER_LINKS = 0x4 + NL80211_MESHCONF_MAX_RETRIES = 0x5 + NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT = 0xa + NL80211_MESHCONF_NOLEARN = 0x1e + NL80211_MESHCONF_PATH_REFRESH_TIME = 0x9 + NL80211_MESHCONF_PLINK_TIMEOUT = 0x1c + NL80211_MESHCONF_POWER_MODE = 0x1a + NL80211_MESHCONF_RETRY_TIMEOUT = 0x1 + NL80211_MESHCONF_RSSI_THRESHOLD = 0x14 + NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR = 0x15 + NL80211_MESHCONF_TTL = 0x6 + NL80211_MESH_POWER_ACTIVE = 0x1 + NL80211_MESH_POWER_DEEP_SLEEP = 0x3 + NL80211_MESH_POWER_LIGHT_SLEEP = 0x2 + NL80211_MESH_POWER_MAX = 0x3 + NL80211_MESH_POWER_UNKNOWN = 0x0 + NL80211_MESH_SETUP_ATTR_MAX = 0x8 + NL80211_MESH_SETUP_AUTH_PROTOCOL = 0x8 + NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC = 0x2 + NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL = 0x1 + NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC = 0x6 + NL80211_MESH_SETUP_IE = 0x3 + NL80211_MESH_SETUP_USERSPACE_AMPE = 0x5 + NL80211_MESH_SETUP_USERSPACE_AUTH = 0x4 + NL80211_MESH_SETUP_USERSPACE_MPM = 0x7 + NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE = 0x3 + NL80211_MFP_NO = 0x0 + NL80211_MFP_OPTIONAL = 0x2 + NL80211_MFP_REQUIRED = 0x1 + NL80211_MIN_REMAIN_ON_CHANNEL_TIME = 0xa + NL80211_MNTR_FLAG_ACTIVE = 0x6 + NL80211_MNTR_FLAG_CONTROL = 0x3 + NL80211_MNTR_FLAG_COOK_FRAMES = 0x5 + NL80211_MNTR_FLAG_FCSFAIL = 0x1 + NL80211_MNTR_FLAG_MAX = 0x7 + NL80211_MNTR_FLAG_OTHER_BSS = 0x4 + NL80211_MNTR_FLAG_PLCPFAIL = 0x2 + NL80211_MPATH_FLAG_ACTIVE = 0x1 + NL80211_MPATH_FLAG_FIXED = 0x8 + NL80211_MPATH_FLAG_RESOLVED = 0x10 + NL80211_MPATH_FLAG_RESOLVING = 0x2 + NL80211_MPATH_FLAG_SN_VALID = 0x4 + NL80211_MPATH_INFO_DISCOVERY_RETRIES = 0x7 + NL80211_MPATH_INFO_DISCOVERY_TIMEOUT = 0x6 + NL80211_MPATH_INFO_EXPTIME = 0x4 + NL80211_MPATH_INFO_FLAGS = 0x5 + NL80211_MPATH_INFO_FRAME_QLEN = 0x1 + NL80211_MPATH_INFO_HOP_COUNT = 0x8 + NL80211_MPATH_INFO_MAX = 0x9 + NL80211_MPATH_INFO_METRIC = 0x3 + NL80211_MPATH_INFO_PATH_CHANGE = 0x9 + NL80211_MPATH_INFO_SN = 0x2 + NL80211_MULTICAST_GROUP_CONFIG = "config" + NL80211_MULTICAST_GROUP_MLME = "mlme" + NL80211_MULTICAST_GROUP_NAN = "nan" + NL80211_MULTICAST_GROUP_REG = "regulatory" + NL80211_MULTICAST_GROUP_SCAN = "scan" + NL80211_MULTICAST_GROUP_TESTMODE = "testmode" + NL80211_MULTICAST_GROUP_VENDOR = "vendor" + NL80211_NAN_FUNC_ATTR_MAX = 0x10 + NL80211_NAN_FUNC_CLOSE_RANGE = 0x9 + NL80211_NAN_FUNC_FOLLOW_UP = 0x2 + NL80211_NAN_FUNC_FOLLOW_UP_DEST = 0x8 + NL80211_NAN_FUNC_FOLLOW_UP_ID = 0x6 + NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID = 0x7 + NL80211_NAN_FUNC_INSTANCE_ID = 0xf + NL80211_NAN_FUNC_MAX_TYPE = 0x2 + NL80211_NAN_FUNC_PUBLISH_BCAST = 0x4 + NL80211_NAN_FUNC_PUBLISH = 0x0 + NL80211_NAN_FUNC_PUBLISH_TYPE = 0x3 + NL80211_NAN_FUNC_RX_MATCH_FILTER = 0xd + NL80211_NAN_FUNC_SERVICE_ID = 0x2 + NL80211_NAN_FUNC_SERVICE_ID_LEN = 0x6 + NL80211_NAN_FUNC_SERVICE_INFO = 0xb + NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN = 0xff + NL80211_NAN_FUNC_SRF = 0xc + NL80211_NAN_FUNC_SRF_MAX_LEN = 0xff + NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE = 0x5 + NL80211_NAN_FUNC_SUBSCRIBE = 0x1 + NL80211_NAN_FUNC_TERM_REASON = 0x10 + NL80211_NAN_FUNC_TERM_REASON_ERROR = 0x2 + NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED = 0x1 + NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST = 0x0 + NL80211_NAN_FUNC_TTL = 0xa + NL80211_NAN_FUNC_TX_MATCH_FILTER = 0xe + NL80211_NAN_FUNC_TYPE = 0x1 + NL80211_NAN_MATCH_ATTR_MAX = 0x2 + NL80211_NAN_MATCH_FUNC_LOCAL = 0x1 + NL80211_NAN_MATCH_FUNC_PEER = 0x2 + NL80211_NAN_SOLICITED_PUBLISH = 0x1 + NL80211_NAN_SRF_ATTR_MAX = 0x4 + NL80211_NAN_SRF_BF = 0x2 + NL80211_NAN_SRF_BF_IDX = 0x3 + NL80211_NAN_SRF_INCLUDE = 0x1 + NL80211_NAN_SRF_MAC_ADDRS = 0x4 + NL80211_NAN_UNSOLICITED_PUBLISH = 0x2 + NL80211_NUM_ACS = 0x4 + NL80211_P2P_PS_SUPPORTED = 0x1 + NL80211_P2P_PS_UNSUPPORTED = 0x0 + NL80211_PKTPAT_MASK = 0x1 + NL80211_PKTPAT_OFFSET = 0x3 + NL80211_PKTPAT_PATTERN = 0x2 + NL80211_PLINK_ACTION_BLOCK = 0x2 + NL80211_PLINK_ACTION_NO_ACTION = 0x0 + NL80211_PLINK_ACTION_OPEN = 0x1 + NL80211_PLINK_BLOCKED = 0x6 + NL80211_PLINK_CNF_RCVD = 0x3 + NL80211_PLINK_ESTAB = 0x4 + NL80211_PLINK_HOLDING = 0x5 + NL80211_PLINK_LISTEN = 0x0 + NL80211_PLINK_OPN_RCVD = 0x2 + NL80211_PLINK_OPN_SNT = 0x1 + NL80211_PMKSA_CANDIDATE_BSSID = 0x2 + NL80211_PMKSA_CANDIDATE_INDEX = 0x1 + NL80211_PMKSA_CANDIDATE_PREAUTH = 0x3 + NL80211_PMSR_ATTR_MAX = 0x5 + NL80211_PMSR_ATTR_MAX_PEERS = 0x1 + NL80211_PMSR_ATTR_PEERS = 0x5 + NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR = 0x3 + NL80211_PMSR_ATTR_REPORT_AP_TSF = 0x2 + NL80211_PMSR_ATTR_TYPE_CAPA = 0x4 + NL80211_PMSR_FTM_CAPA_ATTR_ASAP = 0x1 + NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS = 0x6 + NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT = 0x7 + NL80211_PMSR_FTM_CAPA_ATTR_MAX = 0xa + NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST = 0x8 + NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP = 0x2 + NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED = 0xa + NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES = 0x5 + NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC = 0x4 + NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI = 0x3 + NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED = 0x9 + NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS = 0x7 + NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP = 0x5 + NL80211_PMSR_FTM_FAILURE_NO_RESPONSE = 0x1 + NL80211_PMSR_FTM_FAILURE_PEER_BUSY = 0x6 + NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE = 0x4 + NL80211_PMSR_FTM_FAILURE_REJECTED = 0x2 + NL80211_PMSR_FTM_FAILURE_UNSPECIFIED = 0x0 + NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL = 0x3 + NL80211_PMSR_FTM_REQ_ATTR_ASAP = 0x1 + NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR = 0xd + NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION = 0x5 + NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD = 0x4 + NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST = 0x6 + NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK = 0xc + NL80211_PMSR_FTM_REQ_ATTR_MAX = 0xd + NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED = 0xb + NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP = 0x3 + NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES = 0x7 + NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE = 0x2 + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC = 0x9 + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI = 0x8 + NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED = 0xa + NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION = 0x7 + NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX = 0x2 + NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME = 0x5 + NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC = 0x14 + NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG = 0x10 + NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD = 0x12 + NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE = 0x11 + NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON = 0x1 + NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST = 0x8 + NL80211_PMSR_FTM_RESP_ATTR_LCI = 0x13 + NL80211_PMSR_FTM_RESP_ATTR_MAX = 0x15 + NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP = 0x6 + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS = 0x3 + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES = 0x4 + NL80211_PMSR_FTM_RESP_ATTR_PAD = 0x15 + NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG = 0x9 + NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD = 0xa + NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG = 0xd + NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD = 0xf + NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE = 0xe + NL80211_PMSR_FTM_RESP_ATTR_RX_RATE = 0xc + NL80211_PMSR_FTM_RESP_ATTR_TX_RATE = 0xb + NL80211_PMSR_PEER_ATTR_ADDR = 0x1 + NL80211_PMSR_PEER_ATTR_CHAN = 0x2 + NL80211_PMSR_PEER_ATTR_MAX = 0x4 + NL80211_PMSR_PEER_ATTR_REQ = 0x3 + NL80211_PMSR_PEER_ATTR_RESP = 0x4 + NL80211_PMSR_REQ_ATTR_DATA = 0x1 + NL80211_PMSR_REQ_ATTR_GET_AP_TSF = 0x2 + NL80211_PMSR_REQ_ATTR_MAX = 0x2 + NL80211_PMSR_RESP_ATTR_AP_TSF = 0x4 + NL80211_PMSR_RESP_ATTR_DATA = 0x1 + NL80211_PMSR_RESP_ATTR_FINAL = 0x5 + NL80211_PMSR_RESP_ATTR_HOST_TIME = 0x3 + NL80211_PMSR_RESP_ATTR_MAX = 0x6 + NL80211_PMSR_RESP_ATTR_PAD = 0x6 + NL80211_PMSR_RESP_ATTR_STATUS = 0x2 + NL80211_PMSR_STATUS_FAILURE = 0x3 + NL80211_PMSR_STATUS_REFUSED = 0x1 + NL80211_PMSR_STATUS_SUCCESS = 0x0 + NL80211_PMSR_STATUS_TIMEOUT = 0x2 + NL80211_PMSR_TYPE_FTM = 0x1 + NL80211_PMSR_TYPE_INVALID = 0x0 + NL80211_PMSR_TYPE_MAX = 0x1 + NL80211_PREAMBLE_DMG = 0x3 + NL80211_PREAMBLE_HE = 0x4 + NL80211_PREAMBLE_HT = 0x1 + NL80211_PREAMBLE_LEGACY = 0x0 + NL80211_PREAMBLE_VHT = 0x2 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 0x8 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 0x4 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 0x2 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 0x1 + NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 0x1 + NL80211_PS_DISABLED = 0x0 + NL80211_PS_ENABLED = 0x1 + NL80211_RADAR_CAC_ABORTED = 0x2 + NL80211_RADAR_CAC_FINISHED = 0x1 + NL80211_RADAR_CAC_STARTED = 0x5 + NL80211_RADAR_DETECTED = 0x0 + NL80211_RADAR_NOP_FINISHED = 0x3 + NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 + NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb + NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d + NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19 + NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a + NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12 + NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b + NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc + NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 + NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c + NL80211_RATE_INFO_BITRATE32 = 0x5 + NL80211_RATE_INFO_BITRATE = 0x1 + NL80211_RATE_INFO_EHT_GI_0_8 = 0x0 + NL80211_RATE_INFO_EHT_GI_1_6 = 0x1 + NL80211_RATE_INFO_EHT_GI_3_2 = 0x2 + NL80211_RATE_INFO_EHT_GI = 0x15 + NL80211_RATE_INFO_EHT_MCS = 0x13 + NL80211_RATE_INFO_EHT_NSS = 0x14 + NL80211_RATE_INFO_EHT_RU_ALLOC_106 = 0x3 + NL80211_RATE_INFO_EHT_RU_ALLOC_106P26 = 0x4 + NL80211_RATE_INFO_EHT_RU_ALLOC_242 = 0x5 + NL80211_RATE_INFO_EHT_RU_ALLOC_26 = 0x0 + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996 = 0xb + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484 = 0xc + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996 = 0xd + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484 = 0xe + NL80211_RATE_INFO_EHT_RU_ALLOC_484 = 0x6 + NL80211_RATE_INFO_EHT_RU_ALLOC_484P242 = 0x7 + NL80211_RATE_INFO_EHT_RU_ALLOC_4x996 = 0xf + NL80211_RATE_INFO_EHT_RU_ALLOC_52 = 0x1 + NL80211_RATE_INFO_EHT_RU_ALLOC_52P26 = 0x2 + NL80211_RATE_INFO_EHT_RU_ALLOC_996 = 0x8 + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484 = 0x9 + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242 = 0xa + NL80211_RATE_INFO_EHT_RU_ALLOC = 0x16 + NL80211_RATE_INFO_HE_1XLTF = 0x0 + NL80211_RATE_INFO_HE_2XLTF = 0x1 + NL80211_RATE_INFO_HE_4XLTF = 0x2 + NL80211_RATE_INFO_HE_DCM = 0x10 + NL80211_RATE_INFO_HE_GI_0_8 = 0x0 + NL80211_RATE_INFO_HE_GI_1_6 = 0x1 + NL80211_RATE_INFO_HE_GI_3_2 = 0x2 + NL80211_RATE_INFO_HE_GI = 0xf + NL80211_RATE_INFO_HE_MCS = 0xd + NL80211_RATE_INFO_HE_NSS = 0xe + NL80211_RATE_INFO_HE_RU_ALLOC_106 = 0x2 + NL80211_RATE_INFO_HE_RU_ALLOC_242 = 0x3 + NL80211_RATE_INFO_HE_RU_ALLOC_26 = 0x0 + NL80211_RATE_INFO_HE_RU_ALLOC_2x996 = 0x6 + NL80211_RATE_INFO_HE_RU_ALLOC_484 = 0x4 + NL80211_RATE_INFO_HE_RU_ALLOC_52 = 0x1 + NL80211_RATE_INFO_HE_RU_ALLOC_996 = 0x5 + NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 + NL80211_RATE_INFO_MAX = 0x1d + NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_S1G_MCS = 0x17 + NL80211_RATE_INFO_S1G_NSS = 0x18 + NL80211_RATE_INFO_SHORT_GI = 0x4 + NL80211_RATE_INFO_VHT_MCS = 0x6 + NL80211_RATE_INFO_VHT_NSS = 0x7 + NL80211_REGDOM_SET_BY_CORE = 0x0 + NL80211_REGDOM_SET_BY_COUNTRY_IE = 0x3 + NL80211_REGDOM_SET_BY_DRIVER = 0x2 + NL80211_REGDOM_SET_BY_USER = 0x1 + NL80211_REGDOM_TYPE_COUNTRY = 0x0 + NL80211_REGDOM_TYPE_CUSTOM_WORLD = 0x2 + NL80211_REGDOM_TYPE_INTERSECTION = 0x3 + NL80211_REGDOM_TYPE_WORLD = 0x1 + NL80211_REG_RULE_ATTR_MAX = 0x8 + NL80211_REKEY_DATA_AKM = 0x4 + NL80211_REKEY_DATA_KCK = 0x2 + NL80211_REKEY_DATA_KEK = 0x1 + NL80211_REKEY_DATA_REPLAY_CTR = 0x3 + NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000 + NL80211_RRF_AUTO_BW = 0x800 + NL80211_RRF_DFS = 0x10 + NL80211_RRF_DFS_CONCURRENT = 0x200000 + NL80211_RRF_GO_CONCURRENT = 0x1000 + NL80211_RRF_IR_CONCURRENT = 0x1000 + NL80211_RRF_NO_160MHZ = 0x10000 + NL80211_RRF_NO_320MHZ = 0x40000 + NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000 + NL80211_RRF_NO_80MHZ = 0x8000 + NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_EHT = 0x80000 + NL80211_RRF_NO_HE = 0x20000 + NL80211_RRF_NO_HT40 = 0x6000 + NL80211_RRF_NO_HT40MINUS = 0x2000 + NL80211_RRF_NO_HT40PLUS = 0x4000 + NL80211_RRF_NO_IBSS = 0x80 + NL80211_RRF_NO_INDOOR = 0x4 + NL80211_RRF_NO_IR_ALL = 0x180 + NL80211_RRF_NO_IR = 0x80 + NL80211_RRF_NO_OFDM = 0x1 + NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000 + NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000 + NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PSD = 0x100000 + NL80211_RRF_PTMP_ONLY = 0x40 + NL80211_RRF_PTP_ONLY = 0x20 + NL80211_RXMGMT_FLAG_ANSWERED = 0x1 + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 0x2 + NL80211_SAE_PWE_BOTH = 0x3 + NL80211_SAE_PWE_HASH_TO_ELEMENT = 0x2 + NL80211_SAE_PWE_HUNT_AND_PECK = 0x1 + NL80211_SAE_PWE_UNSPECIFIED = 0x0 + NL80211_SAR_ATTR_MAX = 0x2 + NL80211_SAR_ATTR_SPECS = 0x2 + NL80211_SAR_ATTR_SPECS_END_FREQ = 0x4 + NL80211_SAR_ATTR_SPECS_MAX = 0x4 + NL80211_SAR_ATTR_SPECS_POWER = 0x1 + NL80211_SAR_ATTR_SPECS_RANGE_INDEX = 0x2 + NL80211_SAR_ATTR_SPECS_START_FREQ = 0x3 + NL80211_SAR_ATTR_TYPE = 0x1 + NL80211_SAR_TYPE_POWER = 0x0 + NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = 0x20 + NL80211_SCAN_FLAG_AP = 0x4 + NL80211_SCAN_FLAG_COLOCATED_6GHZ = 0x4000 + NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = 0x10 + NL80211_SCAN_FLAG_FLUSH = 0x2 + NL80211_SCAN_FLAG_FREQ_KHZ = 0x2000 + NL80211_SCAN_FLAG_HIGH_ACCURACY = 0x400 + NL80211_SCAN_FLAG_LOW_POWER = 0x200 + NL80211_SCAN_FLAG_LOW_PRIORITY = 0x1 + NL80211_SCAN_FLAG_LOW_SPAN = 0x100 + NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 0x1000 + NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x80 + NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = 0x40 + NL80211_SCAN_FLAG_RANDOM_ADDR = 0x8 + NL80211_SCAN_FLAG_RANDOM_SN = 0x800 + NL80211_SCAN_RSSI_THOLD_OFF = -0x12c + NL80211_SCHED_SCAN_MATCH_ATTR_BSSID = 0x5 + NL80211_SCHED_SCAN_MATCH_ATTR_MAX = 0x6 + NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI = 0x3 + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST = 0x4 + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI = 0x2 + NL80211_SCHED_SCAN_MATCH_ATTR_SSID = 0x1 + NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI = 0x6 + NL80211_SCHED_SCAN_PLAN_INTERVAL = 0x1 + NL80211_SCHED_SCAN_PLAN_ITERATIONS = 0x2 + NL80211_SCHED_SCAN_PLAN_MAX = 0x2 + NL80211_SMPS_DYNAMIC = 0x2 + NL80211_SMPS_MAX = 0x2 + NL80211_SMPS_OFF = 0x0 + NL80211_SMPS_STATIC = 0x1 + NL80211_STA_BSS_PARAM_BEACON_INTERVAL = 0x5 + NL80211_STA_BSS_PARAM_CTS_PROT = 0x1 + NL80211_STA_BSS_PARAM_DTIM_PERIOD = 0x4 + NL80211_STA_BSS_PARAM_MAX = 0x5 + NL80211_STA_BSS_PARAM_SHORT_PREAMBLE = 0x2 + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME = 0x3 + NL80211_STA_FLAG_ASSOCIATED = 0x7 + NL80211_STA_FLAG_AUTHENTICATED = 0x5 + NL80211_STA_FLAG_AUTHORIZED = 0x1 + NL80211_STA_FLAG_MAX = 0x8 + NL80211_STA_FLAG_MAX_OLD_API = 0x6 + NL80211_STA_FLAG_MFP = 0x4 + NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_SPP_AMSDU = 0x8 + NL80211_STA_FLAG_TDLS_PEER = 0x6 + NL80211_STA_FLAG_WME = 0x3 + NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 + NL80211_STA_INFO_ACK_SIGNAL = 0x22 + NL80211_STA_INFO_AIRTIME_LINK_METRIC = 0x29 + NL80211_STA_INFO_AIRTIME_WEIGHT = 0x28 + NL80211_STA_INFO_ASSOC_AT_BOOTTIME = 0x2a + NL80211_STA_INFO_BEACON_LOSS = 0x12 + NL80211_STA_INFO_BEACON_RX = 0x1d + NL80211_STA_INFO_BEACON_SIGNAL_AVG = 0x1e + NL80211_STA_INFO_BSS_PARAM = 0xf + NL80211_STA_INFO_CHAIN_SIGNAL_AVG = 0x1a + NL80211_STA_INFO_CHAIN_SIGNAL = 0x19 + NL80211_STA_INFO_CONNECTED_TIME = 0x10 + NL80211_STA_INFO_CONNECTED_TO_AS = 0x2b + NL80211_STA_INFO_CONNECTED_TO_GATE = 0x26 + NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG = 0x23 + NL80211_STA_INFO_EXPECTED_THROUGHPUT = 0x1b + NL80211_STA_INFO_FCS_ERROR_COUNT = 0x25 + NL80211_STA_INFO_INACTIVE_TIME = 0x1 + NL80211_STA_INFO_LLID = 0x4 + NL80211_STA_INFO_LOCAL_PM = 0x14 + NL80211_STA_INFO_MAX = 0x2b + NL80211_STA_INFO_NONPEER_PM = 0x16 + NL80211_STA_INFO_PAD = 0x21 + NL80211_STA_INFO_PEER_PM = 0x15 + NL80211_STA_INFO_PLID = 0x5 + NL80211_STA_INFO_PLINK_STATE = 0x6 + NL80211_STA_INFO_RX_BITRATE = 0xe + NL80211_STA_INFO_RX_BYTES64 = 0x17 + NL80211_STA_INFO_RX_BYTES = 0x2 + NL80211_STA_INFO_RX_DROP_MISC = 0x1c + NL80211_STA_INFO_RX_DURATION = 0x20 + NL80211_STA_INFO_RX_MPDUS = 0x24 + NL80211_STA_INFO_RX_PACKETS = 0x9 + NL80211_STA_INFO_SIGNAL_AVG = 0xd + NL80211_STA_INFO_SIGNAL = 0x7 + NL80211_STA_INFO_STA_FLAGS = 0x11 + NL80211_STA_INFO_TID_STATS = 0x1f + NL80211_STA_INFO_T_OFFSET = 0x13 + NL80211_STA_INFO_TX_BITRATE = 0x8 + NL80211_STA_INFO_TX_BYTES64 = 0x18 + NL80211_STA_INFO_TX_BYTES = 0x3 + NL80211_STA_INFO_TX_DURATION = 0x27 + NL80211_STA_INFO_TX_FAILED = 0xc + NL80211_STA_INFO_TX_PACKETS = 0xa + NL80211_STA_INFO_TX_RETRIES = 0xb + NL80211_STA_WME_MAX = 0x2 + NL80211_STA_WME_MAX_SP = 0x2 + NL80211_STA_WME_UAPSD_QUEUES = 0x1 + NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY = 0x5 + NL80211_SURVEY_INFO_CHANNEL_TIME = 0x4 + NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 0x6 + NL80211_SURVEY_INFO_CHANNEL_TIME_RX = 0x7 + NL80211_SURVEY_INFO_CHANNEL_TIME_TX = 0x8 + NL80211_SURVEY_INFO_FREQUENCY = 0x1 + NL80211_SURVEY_INFO_FREQUENCY_OFFSET = 0xc + NL80211_SURVEY_INFO_IN_USE = 0x3 + NL80211_SURVEY_INFO_MAX = 0xc + NL80211_SURVEY_INFO_NOISE = 0x2 + NL80211_SURVEY_INFO_PAD = 0xa + NL80211_SURVEY_INFO_TIME_BSS_RX = 0xb + NL80211_SURVEY_INFO_TIME_BUSY = 0x5 + NL80211_SURVEY_INFO_TIME = 0x4 + NL80211_SURVEY_INFO_TIME_EXT_BUSY = 0x6 + NL80211_SURVEY_INFO_TIME_RX = 0x7 + NL80211_SURVEY_INFO_TIME_SCAN = 0x9 + NL80211_SURVEY_INFO_TIME_TX = 0x8 + NL80211_TDLS_DISABLE_LINK = 0x4 + NL80211_TDLS_DISCOVERY_REQ = 0x0 + NL80211_TDLS_ENABLE_LINK = 0x3 + NL80211_TDLS_PEER_HE = 0x8 + NL80211_TDLS_PEER_HT = 0x1 + NL80211_TDLS_PEER_VHT = 0x2 + NL80211_TDLS_PEER_WMM = 0x4 + NL80211_TDLS_SETUP = 0x1 + NL80211_TDLS_TEARDOWN = 0x2 + NL80211_TID_CONFIG_ATTR_AMPDU_CTRL = 0x9 + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL = 0xb + NL80211_TID_CONFIG_ATTR_MAX = 0xd + NL80211_TID_CONFIG_ATTR_NOACK = 0x6 + NL80211_TID_CONFIG_ATTR_OVERRIDE = 0x4 + NL80211_TID_CONFIG_ATTR_PAD = 0x1 + NL80211_TID_CONFIG_ATTR_PEER_SUPP = 0x3 + NL80211_TID_CONFIG_ATTR_RETRY_LONG = 0x8 + NL80211_TID_CONFIG_ATTR_RETRY_SHORT = 0x7 + NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL = 0xa + NL80211_TID_CONFIG_ATTR_TIDS = 0x5 + NL80211_TID_CONFIG_ATTR_TX_RATE = 0xd + NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE = 0xc + NL80211_TID_CONFIG_ATTR_VIF_SUPP = 0x2 + NL80211_TID_CONFIG_DISABLE = 0x1 + NL80211_TID_CONFIG_ENABLE = 0x0 + NL80211_TID_STATS_MAX = 0x6 + NL80211_TID_STATS_PAD = 0x5 + NL80211_TID_STATS_RX_MSDU = 0x1 + NL80211_TID_STATS_TX_MSDU = 0x2 + NL80211_TID_STATS_TX_MSDU_FAILED = 0x4 + NL80211_TID_STATS_TX_MSDU_RETRIES = 0x3 + NL80211_TID_STATS_TXQ_STATS = 0x6 + NL80211_TIMEOUT_ASSOC = 0x3 + NL80211_TIMEOUT_AUTH = 0x2 + NL80211_TIMEOUT_SCAN = 0x1 + NL80211_TIMEOUT_UNSPECIFIED = 0x0 + NL80211_TKIP_DATA_OFFSET_ENCR_KEY = 0x0 + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY = 0x18 + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY = 0x10 + NL80211_TX_POWER_AUTOMATIC = 0x0 + NL80211_TX_POWER_FIXED = 0x2 + NL80211_TX_POWER_LIMITED = 0x1 + NL80211_TXQ_ATTR_AC = 0x1 + NL80211_TXQ_ATTR_AIFS = 0x5 + NL80211_TXQ_ATTR_CWMAX = 0x4 + NL80211_TXQ_ATTR_CWMIN = 0x3 + NL80211_TXQ_ATTR_MAX = 0x5 + NL80211_TXQ_ATTR_QUEUE = 0x1 + NL80211_TXQ_ATTR_TXOP = 0x2 + NL80211_TXQ_Q_BE = 0x2 + NL80211_TXQ_Q_BK = 0x3 + NL80211_TXQ_Q_VI = 0x1 + NL80211_TXQ_Q_VO = 0x0 + NL80211_TXQ_STATS_BACKLOG_BYTES = 0x1 + NL80211_TXQ_STATS_BACKLOG_PACKETS = 0x2 + NL80211_TXQ_STATS_COLLISIONS = 0x8 + NL80211_TXQ_STATS_DROPS = 0x4 + NL80211_TXQ_STATS_ECN_MARKS = 0x5 + NL80211_TXQ_STATS_FLOWS = 0x3 + NL80211_TXQ_STATS_MAX = 0xb + NL80211_TXQ_STATS_MAX_FLOWS = 0xb + NL80211_TXQ_STATS_OVERLIMIT = 0x6 + NL80211_TXQ_STATS_OVERMEMORY = 0x7 + NL80211_TXQ_STATS_TX_BYTES = 0x9 + NL80211_TXQ_STATS_TX_PACKETS = 0xa + NL80211_TX_RATE_AUTOMATIC = 0x0 + NL80211_TXRATE_DEFAULT_GI = 0x0 + NL80211_TX_RATE_FIXED = 0x2 + NL80211_TXRATE_FORCE_LGI = 0x2 + NL80211_TXRATE_FORCE_SGI = 0x1 + NL80211_TXRATE_GI = 0x4 + NL80211_TXRATE_HE = 0x5 + NL80211_TXRATE_HE_GI = 0x6 + NL80211_TXRATE_HE_LTF = 0x7 + NL80211_TXRATE_HT = 0x2 + NL80211_TXRATE_LEGACY = 0x1 + NL80211_TX_RATE_LIMITED = 0x1 + NL80211_TXRATE_MAX = 0x7 + NL80211_TXRATE_MCS = 0x2 + NL80211_TXRATE_VHT = 0x3 + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT = 0x1 + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX = 0x2 + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL = 0x2 + NL80211_USER_REG_HINT_CELL_BASE = 0x1 + NL80211_USER_REG_HINT_INDOOR = 0x2 + NL80211_USER_REG_HINT_USER = 0x0 + NL80211_VENDOR_ID_IS_LINUX = 0x80000000 + NL80211_VHT_CAPABILITY_LEN = 0xc + NL80211_VHT_NSS_MAX = 0x8 + NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 + NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 + NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 + NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 + NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 + NL80211_WMMR_AIFSN = 0x3 + NL80211_WMMR_CW_MAX = 0x2 + NL80211_WMMR_CW_MIN = 0x1 + NL80211_WMMR_MAX = 0x4 + NL80211_WMMR_TXOP = 0x4 + NL80211_WOWLAN_PKTPAT_MASK = 0x1 + NL80211_WOWLAN_PKTPAT_OFFSET = 0x3 + NL80211_WOWLAN_PKTPAT_PATTERN = 0x2 + NL80211_WOWLAN_TCP_DATA_INTERVAL = 0x9 + NL80211_WOWLAN_TCP_DATA_PAYLOAD = 0x6 + NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ = 0x7 + NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN = 0x8 + NL80211_WOWLAN_TCP_DST_IPV4 = 0x2 + NL80211_WOWLAN_TCP_DST_MAC = 0x3 + NL80211_WOWLAN_TCP_DST_PORT = 0x5 + NL80211_WOWLAN_TCP_SRC_IPV4 = 0x1 + NL80211_WOWLAN_TCP_SRC_PORT = 0x4 + NL80211_WOWLAN_TCP_WAKE_MASK = 0xb + NL80211_WOWLAN_TCP_WAKE_PAYLOAD = 0xa + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE = 0x8 + NL80211_WOWLAN_TRIG_ANY = 0x1 + NL80211_WOWLAN_TRIG_DISCONNECT = 0x2 + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST = 0x7 + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE = 0x6 + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED = 0x5 + NL80211_WOWLAN_TRIG_MAGIC_PKT = 0x3 + NL80211_WOWLAN_TRIG_NET_DETECT = 0x12 + NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS = 0x13 + NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 + NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 + NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14 + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN = 0xd + NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST = 0x10 + NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH = 0xf + NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS = 0x11 + NL80211_WPA_VERSION_1 = 0x1 + NL80211_WPA_VERSION_2 = 0x2 + NL80211_WPA_VERSION_3 = 0x4 +) + +const ( + FRA_UNSPEC = 0x0 + FRA_DST = 0x1 + FRA_SRC = 0x2 + FRA_IIFNAME = 0x3 + FRA_GOTO = 0x4 + FRA_UNUSED2 = 0x5 + FRA_PRIORITY = 0x6 + FRA_UNUSED3 = 0x7 + FRA_UNUSED4 = 0x8 + FRA_UNUSED5 = 0x9 + FRA_FWMARK = 0xa + FRA_FLOW = 0xb + FRA_TUN_ID = 0xc + FRA_SUPPRESS_IFGROUP = 0xd + FRA_SUPPRESS_PREFIXLEN = 0xe + FRA_TABLE = 0xf + FRA_FWMASK = 0x10 + FRA_OIFNAME = 0x11 + FRA_PAD = 0x12 + FRA_L3MDEV = 0x13 + FRA_UID_RANGE = 0x14 + FRA_PROTOCOL = 0x15 + FRA_IP_PROTO = 0x16 + FRA_SPORT_RANGE = 0x17 + FRA_DPORT_RANGE = 0x18 + FR_ACT_UNSPEC = 0x0 + FR_ACT_TO_TBL = 0x1 + FR_ACT_GOTO = 0x2 + FR_ACT_NOP = 0x3 + FR_ACT_RES3 = 0x4 + FR_ACT_RES4 = 0x5 + FR_ACT_BLACKHOLE = 0x6 + FR_ACT_UNREACHABLE = 0x7 + FR_ACT_PROHIBIT = 0x8 +) + +const ( + AUDIT_NLGRP_NONE = 0x0 + AUDIT_NLGRP_READLOG = 0x1 +) + +const ( + TUN_F_CSUM = 0x1 + TUN_F_TSO4 = 0x2 + TUN_F_TSO6 = 0x4 + TUN_F_TSO_ECN = 0x8 + TUN_F_UFO = 0x10 + TUN_F_USO4 = 0x20 + TUN_F_USO6 = 0x40 +) + +const ( + VIRTIO_NET_HDR_F_NEEDS_CSUM = 0x1 + VIRTIO_NET_HDR_F_DATA_VALID = 0x2 + VIRTIO_NET_HDR_F_RSC_INFO = 0x4 +) + +const ( + VIRTIO_NET_HDR_GSO_NONE = 0x0 + VIRTIO_NET_HDR_GSO_TCPV4 = 0x1 + VIRTIO_NET_HDR_GSO_UDP = 0x3 + VIRTIO_NET_HDR_GSO_TCPV6 = 0x4 + VIRTIO_NET_HDR_GSO_UDP_L4 = 0x5 + VIRTIO_NET_HDR_GSO_ECN = 0x80 +) + +type SchedAttr struct { + Size uint32 + Policy uint32 + Flags uint64 + Nice int32 + Priority uint32 + Runtime uint64 + Deadline uint64 + Period uint64 + Util_min uint32 + Util_max uint32 +} + +const SizeofSchedAttr = 0x38 + +type Cachestat_t struct { + Cache uint64 + Dirty uint64 + Writeback uint64 + Evicted uint64 + Recently_evicted uint64 +} +type CachestatRange struct { + Off uint64 + Len uint64 +} + +const ( + SK_MEMINFO_RMEM_ALLOC = 0x0 + SK_MEMINFO_RCVBUF = 0x1 + SK_MEMINFO_WMEM_ALLOC = 0x2 + SK_MEMINFO_SNDBUF = 0x3 + SK_MEMINFO_FWD_ALLOC = 0x4 + SK_MEMINFO_WMEM_QUEUED = 0x5 + SK_MEMINFO_OPTMEM = 0x6 + SK_MEMINFO_BACKLOG = 0x7 + SK_MEMINFO_DROPS = 0x8 + SK_MEMINFO_VARS = 0x9 + SKNLGRP_NONE = 0x0 + SKNLGRP_INET_TCP_DESTROY = 0x1 + SKNLGRP_INET_UDP_DESTROY = 0x2 + SKNLGRP_INET6_TCP_DESTROY = 0x3 + SKNLGRP_INET6_UDP_DESTROY = 0x4 + SK_DIAG_BPF_STORAGE_REQ_NONE = 0x0 + SK_DIAG_BPF_STORAGE_REQ_MAP_FD = 0x1 + SK_DIAG_BPF_STORAGE_REP_NONE = 0x0 + SK_DIAG_BPF_STORAGE = 0x1 + SK_DIAG_BPF_STORAGE_NONE = 0x0 + SK_DIAG_BPF_STORAGE_PAD = 0x1 + SK_DIAG_BPF_STORAGE_MAP_ID = 0x2 + SK_DIAG_BPF_STORAGE_MAP_VALUE = 0x3 +) + +type SockDiagReq struct { + Family uint8 + Protocol uint8 +} + +const RTM_NEWNVLAN = 0x70 + +const ( + MPOL_BIND = 0x2 + MPOL_DEFAULT = 0x0 + MPOL_F_ADDR = 0x2 + MPOL_F_MEMS_ALLOWED = 0x4 + MPOL_F_MOF = 0x8 + MPOL_F_MORON = 0x10 + MPOL_F_NODE = 0x1 + MPOL_F_NUMA_BALANCING = 0x2000 + MPOL_F_RELATIVE_NODES = 0x4000 + MPOL_F_SHARED = 0x1 + MPOL_F_STATIC_NODES = 0x8000 + MPOL_INTERLEAVE = 0x3 + MPOL_LOCAL = 0x4 + MPOL_MAX = 0x7 + MPOL_MF_INTERNAL = 0x10 + MPOL_MF_LAZY = 0x8 + MPOL_MF_MOVE_ALL = 0x4 + MPOL_MF_MOVE = 0x2 + MPOL_MF_STRICT = 0x1 + MPOL_MF_VALID = 0x7 + MPOL_MODE_FLAGS = 0xe000 + MPOL_PREFERRED = 0x1 + MPOL_PREFERRED_MANY = 0x5 + MPOL_WEIGHTED_INTERLEAVE = 0x6 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fc6b3fb..485f2d3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/386/cgo -- -Wall -Werror -static -I/tmp/386/include -m32 linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,linux +//go:build 386 && linux package unix @@ -117,11 +117,27 @@ type Flock_t struct { Pid int32 } +type DmNameList struct { + Dev uint64 + Next uint32 +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -153,10 +169,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( @@ -217,6 +239,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -227,6 +253,19 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -243,7 +282,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -287,6 +326,34 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + _ [4]byte + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 @@ -364,7 +431,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [122]int8 + Data [122]byte _ uint32 } @@ -426,14 +493,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -596,3 +655,51 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 +} + +const ( + PPS_GETPARAMS = 0x800470a1 + PPS_SETPARAMS = 0x400470a2 + PPS_GETCAP = 0x800470a3 + PPS_FETCH = 0xc00470a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ [2]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Atime_high uint32 + Dtime uint32 + Dtime_high uint32 + Ctime uint32 + Ctime_high uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 26c30b8..ecbd1ad 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/amd64/cgo -- -Wall -Werror -static -I/tmp/amd64/include -m64 linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,linux +//go:build amd64 && linux package unix @@ -117,11 +117,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -154,10 +172,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -230,6 +254,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -240,6 +268,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -298,6 +340,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -375,7 +444,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]int8 + Data [118]byte _ uint64 } @@ -439,15 +508,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -611,3 +671,49 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 814d42d..02f0463 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/arm/cgo -- -Wall -Werror -static -I/tmp/arm/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,linux +//go:build arm && linux package unix @@ -91,7 +91,7 @@ type Stat_t struct { Gid uint32 Rdev uint64 _ uint16 - _ [4]byte + _ [6]byte Size int64 Blksize int32 _ [4]byte @@ -121,11 +121,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -157,10 +175,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( @@ -206,6 +230,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -216,6 +244,19 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -232,7 +273,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -276,6 +317,34 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + _ [4]byte + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 @@ -353,7 +422,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [122]uint8 + Data [122]byte _ uint32 } @@ -417,15 +486,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 @@ -588,3 +648,52 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800470a1 + PPS_SETPARAMS = 0x400470a2 + PPS_GETCAP = 0x800470a3 + PPS_FETCH = 0xc00470a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ [2]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Atime_high uint32 + Dtime uint32 + Dtime_high uint32 + Ctime uint32 + Ctime_high uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index d9664c7..6f4d400 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/arm64/cgo -- -Wall -Werror -static -I/tmp/arm64/include -fsigned-char linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,linux +//go:build arm64 && linux package unix @@ -118,11 +118,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -155,10 +173,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -209,6 +233,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -219,6 +247,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -277,6 +319,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -354,7 +423,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]int8 + Data [118]byte _ uint64 } @@ -418,15 +487,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -590,3 +650,49 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go new file mode 100644 index 0000000..cd532cf --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -0,0 +1,699 @@ +// cgo -godefs -objdir=/tmp/loong64/cgo -- -Wall -Werror -static -I/tmp/loong64/include linux/types.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build loong64 && linux + +package unix + +const ( + SizeofPtr = 0x8 + SizeofLong = 0x8 +) + +type ( + _C_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +type Timex struct { + Modes uint32 + Offset int64 + Freq int64 + Maxerror int64 + Esterror int64 + Status int32 + Constant int64 + Precision int64 + Tolerance int64 + Time Timeval + Tick int64 + Ppsfreq int64 + Jitter int64 + Shift int32 + Stabil int64 + Jitcnt int64 + Calcnt int64 + Errcnt int64 + Stbcnt int64 + Tai int32 + _ [44]byte +} + +type Time_t int64 + +type Tms struct { + Utime int64 + Stime int64 + Cutime int64 + Cstime int64 +} + +type Utimbuf struct { + Actime int64 + Modtime int64 +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Stat_t struct { + Dev uint64 + Ino uint64 + Mode uint32 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev uint64 + _ uint64 + Size int64 + Blksize int32 + _ int32 + Blocks int64 + Atim Timespec + Mtim Timespec + Ctim Timespec + _ [2]int32 +} + +type Dirent struct { + Ino uint64 + Off int64 + Reclen uint16 + Type uint8 + Name [256]int8 + _ [5]byte +} + +type Flock_t struct { + Type int16 + Whence int16 + Start int64 + Len int64 + Pid int32 + _ [4]byte +} + +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + +const ( + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + +type RawSockaddr struct { + Family uint16 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [96]int8 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Iov *Iovec + Iovlen uint64 + Control *byte + Controllen uint64 + Flags int32 + _ [4]byte +} + +type Cmsghdr struct { + Len uint64 + Level int32 + Type int32 +} + +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + +const ( + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 +) + +const ( + SizeofSockFprog = 0x10 +) + +type PtraceRegs struct { + Regs [32]uint64 + Orig_a0 uint64 + Era uint64 + Badv uint64 + Reserved [10]uint64 +} + +type FdSet struct { + Bits [16]int64 +} + +type Sysinfo_t struct { + Uptime int64 + Loads [3]uint64 + Totalram uint64 + Freeram uint64 + Sharedram uint64 + Bufferram uint64 + Totalswap uint64 + Freeswap uint64 + Procs uint16 + Pad uint16 + Totalhigh uint64 + Freehigh uint64 + Unit uint32 + _ [0]int8 + _ [4]byte +} + +type Ustat_t struct { + Tfree int32 + Tinode uint64 + Fname [6]int8 + Fpack [6]int8 + _ [4]byte +} + +type EpollEvent struct { + Events uint32 + _ int32 + Fd int32 + Pad int32 +} + +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + +const ( + POLLRDHUP = 0x2000 +) + +type Sigset_t struct { + Val [16]uint64 +} + +const _C__NSIG = 0x41 + +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Line uint8 + Cc [19]uint8 + Ispeed uint32 + Ospeed uint32 +} + +type Taskstats struct { + Version uint16 + Ac_exitcode uint32 + Ac_flag uint8 + Ac_nice uint8 + Cpu_count uint64 + Cpu_delay_total uint64 + Blkio_count uint64 + Blkio_delay_total uint64 + Swapin_count uint64 + Swapin_delay_total uint64 + Cpu_run_real_total uint64 + Cpu_run_virtual_total uint64 + Ac_comm [32]int8 + Ac_sched uint8 + Ac_pad [3]uint8 + _ [4]byte + Ac_uid uint32 + Ac_gid uint32 + Ac_pid uint32 + Ac_ppid uint32 + Ac_btime uint32 + Ac_etime uint64 + Ac_utime uint64 + Ac_stime uint64 + Ac_minflt uint64 + Ac_majflt uint64 + Coremem uint64 + Virtmem uint64 + Hiwater_rss uint64 + Hiwater_vm uint64 + Read_char uint64 + Write_char uint64 + Read_syscalls uint64 + Write_syscalls uint64 + Read_bytes uint64 + Write_bytes uint64 + Cancelled_write_bytes uint64 + Nvcsw uint64 + Nivcsw uint64 + Ac_utimescaled uint64 + Ac_stimescaled uint64 + Cpu_scaled_run_real_total uint64 + Freepages_count uint64 + Freepages_delay_total uint64 + Thrashing_count uint64 + Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 +} + +type cpuMask uint64 + +const ( + _NCPUBITS = 0x40 +) + +const ( + CBitFieldMaskBit0 = 0x1 + CBitFieldMaskBit1 = 0x2 + CBitFieldMaskBit2 = 0x4 + CBitFieldMaskBit3 = 0x8 + CBitFieldMaskBit4 = 0x10 + CBitFieldMaskBit5 = 0x20 + CBitFieldMaskBit6 = 0x40 + CBitFieldMaskBit7 = 0x80 + CBitFieldMaskBit8 = 0x100 + CBitFieldMaskBit9 = 0x200 + CBitFieldMaskBit10 = 0x400 + CBitFieldMaskBit11 = 0x800 + CBitFieldMaskBit12 = 0x1000 + CBitFieldMaskBit13 = 0x2000 + CBitFieldMaskBit14 = 0x4000 + CBitFieldMaskBit15 = 0x8000 + CBitFieldMaskBit16 = 0x10000 + CBitFieldMaskBit17 = 0x20000 + CBitFieldMaskBit18 = 0x40000 + CBitFieldMaskBit19 = 0x80000 + CBitFieldMaskBit20 = 0x100000 + CBitFieldMaskBit21 = 0x200000 + CBitFieldMaskBit22 = 0x400000 + CBitFieldMaskBit23 = 0x800000 + CBitFieldMaskBit24 = 0x1000000 + CBitFieldMaskBit25 = 0x2000000 + CBitFieldMaskBit26 = 0x4000000 + CBitFieldMaskBit27 = 0x8000000 + CBitFieldMaskBit28 = 0x10000000 + CBitFieldMaskBit29 = 0x20000000 + CBitFieldMaskBit30 = 0x40000000 + CBitFieldMaskBit31 = 0x80000000 + CBitFieldMaskBit32 = 0x100000000 + CBitFieldMaskBit33 = 0x200000000 + CBitFieldMaskBit34 = 0x400000000 + CBitFieldMaskBit35 = 0x800000000 + CBitFieldMaskBit36 = 0x1000000000 + CBitFieldMaskBit37 = 0x2000000000 + CBitFieldMaskBit38 = 0x4000000000 + CBitFieldMaskBit39 = 0x8000000000 + CBitFieldMaskBit40 = 0x10000000000 + CBitFieldMaskBit41 = 0x20000000000 + CBitFieldMaskBit42 = 0x40000000000 + CBitFieldMaskBit43 = 0x80000000000 + CBitFieldMaskBit44 = 0x100000000000 + CBitFieldMaskBit45 = 0x200000000000 + CBitFieldMaskBit46 = 0x400000000000 + CBitFieldMaskBit47 = 0x800000000000 + CBitFieldMaskBit48 = 0x1000000000000 + CBitFieldMaskBit49 = 0x2000000000000 + CBitFieldMaskBit50 = 0x4000000000000 + CBitFieldMaskBit51 = 0x8000000000000 + CBitFieldMaskBit52 = 0x10000000000000 + CBitFieldMaskBit53 = 0x20000000000000 + CBitFieldMaskBit54 = 0x40000000000000 + CBitFieldMaskBit55 = 0x80000000000000 + CBitFieldMaskBit56 = 0x100000000000000 + CBitFieldMaskBit57 = 0x200000000000000 + CBitFieldMaskBit58 = 0x400000000000000 + CBitFieldMaskBit59 = 0x800000000000000 + CBitFieldMaskBit60 = 0x1000000000000000 + CBitFieldMaskBit61 = 0x2000000000000000 + CBitFieldMaskBit62 = 0x4000000000000000 + CBitFieldMaskBit63 = 0x8000000000000000 +) + +type SockaddrStorage struct { + Family uint16 + Data [118]byte + _ uint64 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + Start uint64 +} + +type Statfs_t struct { + Type int64 + Bsize int64 + Blocks uint64 + Bfree uint64 + Bavail uint64 + Files uint64 + Ffree uint64 + Fsid Fsid + Namelen int64 + Frsize int64 + Flags int64 + Spare [4]int64 +} + +type TpacketHdr struct { + Status uint64 + Len uint32 + Snaplen uint32 + Mac uint16 + Net uint16 + Sec uint32 + Usec uint32 + _ [4]byte +} + +const ( + SizeofTpacketHdr = 0x20 +) + +type RTCPLLInfo struct { + Ctrl int32 + Value int32 + Max int32 + Min int32 + Posmult int32 + Negmult int32 + Clock int64 +} + +type BlkpgPartition struct { + Start int64 + Length int64 + Pno int32 + Devname [64]uint8 + Volname [64]uint8 + _ [4]byte +} + +const ( + BLKPG = 0x1269 +) + +type CryptoUserAlg struct { + Name [64]int8 + Driver_name [64]int8 + Module_name [64]int8 + Type uint32 + Mask uint32 + Refcnt uint32 + Flags uint32 +} + +type CryptoStatAEAD struct { + Type [64]int8 + Encrypt_cnt uint64 + Encrypt_tlen uint64 + Decrypt_cnt uint64 + Decrypt_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatAKCipher struct { + Type [64]int8 + Encrypt_cnt uint64 + Encrypt_tlen uint64 + Decrypt_cnt uint64 + Decrypt_tlen uint64 + Verify_cnt uint64 + Sign_cnt uint64 + Err_cnt uint64 +} + +type CryptoStatCipher struct { + Type [64]int8 + Encrypt_cnt uint64 + Encrypt_tlen uint64 + Decrypt_cnt uint64 + Decrypt_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatCompress struct { + Type [64]int8 + Compress_cnt uint64 + Compress_tlen uint64 + Decompress_cnt uint64 + Decompress_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatHash struct { + Type [64]int8 + Hash_cnt uint64 + Hash_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatKPP struct { + Type [64]int8 + Setsecret_cnt uint64 + Generate_public_key_cnt uint64 + Compute_shared_secret_cnt uint64 + Err_cnt uint64 +} + +type CryptoStatRNG struct { + Type [64]int8 + Generate_cnt uint64 + Generate_tlen uint64 + Seed_cnt uint64 + Err_cnt uint64 +} + +type CryptoStatLarval struct { + Type [64]int8 +} + +type CryptoReportLarval struct { + Type [64]int8 +} + +type CryptoReportHash struct { + Type [64]int8 + Blocksize uint32 + Digestsize uint32 +} + +type CryptoReportCipher struct { + Type [64]int8 + Blocksize uint32 + Min_keysize uint32 + Max_keysize uint32 +} + +type CryptoReportBlkCipher struct { + Type [64]int8 + Geniv [64]int8 + Blocksize uint32 + Min_keysize uint32 + Max_keysize uint32 + Ivsize uint32 +} + +type CryptoReportAEAD struct { + Type [64]int8 + Geniv [64]int8 + Blocksize uint32 + Maxauthsize uint32 + Ivsize uint32 +} + +type CryptoReportComp struct { + Type [64]int8 +} + +type CryptoReportRNG struct { + Type [64]int8 + Seedsize uint32 +} + +type CryptoReportAKCipher struct { + Type [64]int8 +} + +type CryptoReportKPP struct { + Type [64]int8 +} + +type CryptoReportAcomp struct { + Type [64]int8 +} + +type LoopInfo struct { + Number int32 + Device uint32 + Inode uint64 + Rdevice uint32 + Offset int32 + Encrypt_type int32 + Encrypt_key_size int32 + Flags int32 + Name [64]int8 + Encrypt_key [32]uint8 + Init [2]uint64 + Reserved [4]int8 + _ [4]byte +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]int8 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]int8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]int8 +} + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 0d72145..4133620 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/mips/cgo -- -Wall -Werror -static -I/tmp/mips/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips,linux +//go:build mips && linux package unix @@ -120,11 +120,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -156,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( @@ -211,6 +235,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -221,6 +249,19 @@ type Sigset_t struct { const _C__NSIG = 0x80 +const ( + SIG_BLOCK = 0x1 + SIG_UNBLOCK = 0x2 + SIG_SETMASK = 0x3 +) + +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -237,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -281,6 +322,34 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + _ [4]byte + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 @@ -358,7 +427,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [122]int8 + Data [122]byte _ uint32 } @@ -423,15 +492,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -594,3 +654,51 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400470a1 + PPS_SETPARAMS = 0x800470a2 + PPS_GETCAP = 0x400470a3 + PPS_FETCH = 0xc00470a4 +) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Dtime uint32 + Ctime uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + Atime_high uint16 + Dtime_high uint16 + Ctime_high uint16 + _ uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index ef69768..eaa37eb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/mips64/cgo -- -Wall -Werror -static -I/tmp/mips64/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips64,linux +//go:build mips64 && linux package unix @@ -118,11 +118,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -155,10 +173,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -212,6 +236,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -222,6 +250,20 @@ type Sigset_t struct { const _C__NSIG = 0x80 +const ( + SIG_BLOCK = 0x1 + SIG_UNBLOCK = 0x2 + SIG_SETMASK = 0x3 +) + +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -280,6 +322,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -357,7 +426,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]int8 + Data [118]byte _ uint64 } @@ -421,15 +490,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -593,3 +653,49 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 485fda7..98ae6a1 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/mips64le/cgo -- -Wall -Werror -static -I/tmp/mips64le/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mips64le,linux +//go:build mips64le && linux package unix @@ -118,11 +118,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -155,10 +173,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -212,6 +236,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -222,6 +250,20 @@ type Sigset_t struct { const _C__NSIG = 0x80 +const ( + SIG_BLOCK = 0x1 + SIG_UNBLOCK = 0x2 + SIG_SETMASK = 0x3 +) + +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -280,6 +322,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -357,7 +426,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]int8 + Data [118]byte _ uint64 } @@ -421,15 +490,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -593,3 +653,49 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 569477e..cae1961 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/mipsle/cgo -- -Wall -Werror -static -I/tmp/mipsle/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build mipsle,linux +//go:build mipsle && linux package unix @@ -120,11 +120,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -156,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( @@ -211,6 +235,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -221,6 +249,19 @@ type Sigset_t struct { const _C__NSIG = 0x80 +const ( + SIG_BLOCK = 0x1 + SIG_UNBLOCK = 0x2 + SIG_SETMASK = 0x3 +) + +type Siginfo struct { + Signo int32 + Code int32 + Errno int32 + _ [116]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -237,7 +278,7 @@ type Taskstats struct { Ac_exitcode uint32 Ac_flag uint8 Ac_nice uint8 - _ [4]byte + _ [6]byte Cpu_count uint64 Cpu_delay_total uint64 Blkio_count uint64 @@ -281,6 +322,34 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + _ [4]byte + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint32 @@ -358,7 +427,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [122]int8 + Data [122]byte _ uint32 } @@ -423,15 +492,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -594,3 +654,51 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400470a1 + PPS_SETPARAMS = 0x800470a2 + PPS_GETCAP = 0x400470a3 + PPS_FETCH = 0xc00470a4 +) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Dtime uint32 + Ctime uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + Atime_high uint16 + Dtime_high uint16 + Ctime_high uint16 + _ uint16 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go new file mode 100644 index 0000000..6ce3b4e --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -0,0 +1,712 @@ +// cgo -godefs -objdir=/tmp/ppc/cgo -- -Wall -Werror -static -I/tmp/ppc/include linux/types.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build ppc && linux + +package unix + +const ( + SizeofPtr = 0x4 + SizeofLong = 0x4 +) + +type ( + _C_long int32 +) + +type Timespec struct { + Sec int32 + Nsec int32 +} + +type Timeval struct { + Sec int32 + Usec int32 +} + +type Timex struct { + Modes uint32 + Offset int32 + Freq int32 + Maxerror int32 + Esterror int32 + Status int32 + Constant int32 + Precision int32 + Tolerance int32 + Time Timeval + Tick int32 + Ppsfreq int32 + Jitter int32 + Shift int32 + Stabil int32 + Jitcnt int32 + Calcnt int32 + Errcnt int32 + Stbcnt int32 + Tai int32 + _ [44]byte +} + +type Time_t int32 + +type Tms struct { + Utime int32 + Stime int32 + Cutime int32 + Cstime int32 +} + +type Utimbuf struct { + Actime int32 + Modtime int32 +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int32 + Ixrss int32 + Idrss int32 + Isrss int32 + Minflt int32 + Majflt int32 + Nswap int32 + Inblock int32 + Oublock int32 + Msgsnd int32 + Msgrcv int32 + Nsignals int32 + Nvcsw int32 + Nivcsw int32 +} + +type Stat_t struct { + Dev uint64 + Ino uint64 + Mode uint32 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev uint64 + _ uint16 + _ [6]byte + Size int64 + Blksize int32 + _ [4]byte + Blocks int64 + Atim Timespec + Mtim Timespec + Ctim Timespec + _ uint32 + _ uint32 +} + +type Dirent struct { + Ino uint64 + Off int64 + Reclen uint16 + Type uint8 + Name [256]uint8 + _ [5]byte +} + +type Flock_t struct { + Type int16 + Whence int16 + _ [4]byte + Start int64 + Len int64 + Pid int32 + _ [4]byte +} + +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + +const ( + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + +type RawSockaddr struct { + Family uint16 + Data [14]uint8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [96]uint8 +} + +type Iovec struct { + Base *byte + Len uint32 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Iov *Iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 +} + +type Cmsghdr struct { + Len uint32 + Level int32 + Type int32 +} + +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + +const ( + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc +) + +const ( + SizeofSockFprog = 0x8 +) + +type PtraceRegs struct { + Gpr [32]uint32 + Nip uint32 + Msr uint32 + Orig_gpr3 uint32 + Ctr uint32 + Link uint32 + Xer uint32 + Ccr uint32 + Mq uint32 + Trap uint32 + Dar uint32 + Dsisr uint32 + Result uint32 +} + +type FdSet struct { + Bits [32]int32 +} + +type Sysinfo_t struct { + Uptime int32 + Loads [3]uint32 + Totalram uint32 + Freeram uint32 + Sharedram uint32 + Bufferram uint32 + Totalswap uint32 + Freeswap uint32 + Procs uint16 + Pad uint16 + Totalhigh uint32 + Freehigh uint32 + Unit uint32 + _ [8]uint8 +} + +type Ustat_t struct { + Tfree int32 + Tinode uint32 + Fname [6]uint8 + Fpack [6]uint8 +} + +type EpollEvent struct { + Events uint32 + _ int32 + Fd int32 + Pad int32 +} + +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + +const ( + POLLRDHUP = 0x2000 +) + +type Sigset_t struct { + Val [32]uint32 +} + +const _C__NSIG = 0x41 + +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ [116]byte +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [19]uint8 + Line uint8 + Ispeed uint32 + Ospeed uint32 +} + +type Taskstats struct { + Version uint16 + Ac_exitcode uint32 + Ac_flag uint8 + Ac_nice uint8 + _ [6]byte + Cpu_count uint64 + Cpu_delay_total uint64 + Blkio_count uint64 + Blkio_delay_total uint64 + Swapin_count uint64 + Swapin_delay_total uint64 + Cpu_run_real_total uint64 + Cpu_run_virtual_total uint64 + Ac_comm [32]uint8 + Ac_sched uint8 + Ac_pad [3]uint8 + _ [4]byte + Ac_uid uint32 + Ac_gid uint32 + Ac_pid uint32 + Ac_ppid uint32 + Ac_btime uint32 + _ [4]byte + Ac_etime uint64 + Ac_utime uint64 + Ac_stime uint64 + Ac_minflt uint64 + Ac_majflt uint64 + Coremem uint64 + Virtmem uint64 + Hiwater_rss uint64 + Hiwater_vm uint64 + Read_char uint64 + Write_char uint64 + Read_syscalls uint64 + Write_syscalls uint64 + Read_bytes uint64 + Write_bytes uint64 + Cancelled_write_bytes uint64 + Nvcsw uint64 + Nivcsw uint64 + Ac_utimescaled uint64 + Ac_stimescaled uint64 + Cpu_scaled_run_real_total uint64 + Freepages_count uint64 + Freepages_delay_total uint64 + Thrashing_count uint64 + Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + _ [4]byte + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 +} + +type cpuMask uint32 + +const ( + _NCPUBITS = 0x20 +) + +const ( + CBitFieldMaskBit0 = 0x8000000000000000 + CBitFieldMaskBit1 = 0x4000000000000000 + CBitFieldMaskBit2 = 0x2000000000000000 + CBitFieldMaskBit3 = 0x1000000000000000 + CBitFieldMaskBit4 = 0x800000000000000 + CBitFieldMaskBit5 = 0x400000000000000 + CBitFieldMaskBit6 = 0x200000000000000 + CBitFieldMaskBit7 = 0x100000000000000 + CBitFieldMaskBit8 = 0x80000000000000 + CBitFieldMaskBit9 = 0x40000000000000 + CBitFieldMaskBit10 = 0x20000000000000 + CBitFieldMaskBit11 = 0x10000000000000 + CBitFieldMaskBit12 = 0x8000000000000 + CBitFieldMaskBit13 = 0x4000000000000 + CBitFieldMaskBit14 = 0x2000000000000 + CBitFieldMaskBit15 = 0x1000000000000 + CBitFieldMaskBit16 = 0x800000000000 + CBitFieldMaskBit17 = 0x400000000000 + CBitFieldMaskBit18 = 0x200000000000 + CBitFieldMaskBit19 = 0x100000000000 + CBitFieldMaskBit20 = 0x80000000000 + CBitFieldMaskBit21 = 0x40000000000 + CBitFieldMaskBit22 = 0x20000000000 + CBitFieldMaskBit23 = 0x10000000000 + CBitFieldMaskBit24 = 0x8000000000 + CBitFieldMaskBit25 = 0x4000000000 + CBitFieldMaskBit26 = 0x2000000000 + CBitFieldMaskBit27 = 0x1000000000 + CBitFieldMaskBit28 = 0x800000000 + CBitFieldMaskBit29 = 0x400000000 + CBitFieldMaskBit30 = 0x200000000 + CBitFieldMaskBit31 = 0x100000000 + CBitFieldMaskBit32 = 0x80000000 + CBitFieldMaskBit33 = 0x40000000 + CBitFieldMaskBit34 = 0x20000000 + CBitFieldMaskBit35 = 0x10000000 + CBitFieldMaskBit36 = 0x8000000 + CBitFieldMaskBit37 = 0x4000000 + CBitFieldMaskBit38 = 0x2000000 + CBitFieldMaskBit39 = 0x1000000 + CBitFieldMaskBit40 = 0x800000 + CBitFieldMaskBit41 = 0x400000 + CBitFieldMaskBit42 = 0x200000 + CBitFieldMaskBit43 = 0x100000 + CBitFieldMaskBit44 = 0x80000 + CBitFieldMaskBit45 = 0x40000 + CBitFieldMaskBit46 = 0x20000 + CBitFieldMaskBit47 = 0x10000 + CBitFieldMaskBit48 = 0x8000 + CBitFieldMaskBit49 = 0x4000 + CBitFieldMaskBit50 = 0x2000 + CBitFieldMaskBit51 = 0x1000 + CBitFieldMaskBit52 = 0x800 + CBitFieldMaskBit53 = 0x400 + CBitFieldMaskBit54 = 0x200 + CBitFieldMaskBit55 = 0x100 + CBitFieldMaskBit56 = 0x80 + CBitFieldMaskBit57 = 0x40 + CBitFieldMaskBit58 = 0x20 + CBitFieldMaskBit59 = 0x10 + CBitFieldMaskBit60 = 0x8 + CBitFieldMaskBit61 = 0x4 + CBitFieldMaskBit62 = 0x2 + CBitFieldMaskBit63 = 0x1 +) + +type SockaddrStorage struct { + Family uint16 + Data [122]byte + _ uint32 +} + +type HDGeometry struct { + Heads uint8 + Sectors uint8 + Cylinders uint16 + Start uint32 +} + +type Statfs_t struct { + Type int32 + Bsize int32 + Blocks uint64 + Bfree uint64 + Bavail uint64 + Files uint64 + Ffree uint64 + Fsid Fsid + Namelen int32 + Frsize int32 + Flags int32 + Spare [4]int32 + _ [4]byte +} + +type TpacketHdr struct { + Status uint32 + Len uint32 + Snaplen uint32 + Mac uint16 + Net uint16 + Sec uint32 + Usec uint32 +} + +const ( + SizeofTpacketHdr = 0x18 +) + +type RTCPLLInfo struct { + Ctrl int32 + Value int32 + Max int32 + Min int32 + Posmult int32 + Negmult int32 + Clock int32 +} + +type BlkpgPartition struct { + Start int64 + Length int64 + Pno int32 + Devname [64]uint8 + Volname [64]uint8 + _ [4]byte +} + +const ( + BLKPG = 0x20001269 +) + +type CryptoUserAlg struct { + Name [64]uint8 + Driver_name [64]uint8 + Module_name [64]uint8 + Type uint32 + Mask uint32 + Refcnt uint32 + Flags uint32 +} + +type CryptoStatAEAD struct { + Type [64]uint8 + Encrypt_cnt uint64 + Encrypt_tlen uint64 + Decrypt_cnt uint64 + Decrypt_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatAKCipher struct { + Type [64]uint8 + Encrypt_cnt uint64 + Encrypt_tlen uint64 + Decrypt_cnt uint64 + Decrypt_tlen uint64 + Verify_cnt uint64 + Sign_cnt uint64 + Err_cnt uint64 +} + +type CryptoStatCipher struct { + Type [64]uint8 + Encrypt_cnt uint64 + Encrypt_tlen uint64 + Decrypt_cnt uint64 + Decrypt_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatCompress struct { + Type [64]uint8 + Compress_cnt uint64 + Compress_tlen uint64 + Decompress_cnt uint64 + Decompress_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatHash struct { + Type [64]uint8 + Hash_cnt uint64 + Hash_tlen uint64 + Err_cnt uint64 +} + +type CryptoStatKPP struct { + Type [64]uint8 + Setsecret_cnt uint64 + Generate_public_key_cnt uint64 + Compute_shared_secret_cnt uint64 + Err_cnt uint64 +} + +type CryptoStatRNG struct { + Type [64]uint8 + Generate_cnt uint64 + Generate_tlen uint64 + Seed_cnt uint64 + Err_cnt uint64 +} + +type CryptoStatLarval struct { + Type [64]uint8 +} + +type CryptoReportLarval struct { + Type [64]uint8 +} + +type CryptoReportHash struct { + Type [64]uint8 + Blocksize uint32 + Digestsize uint32 +} + +type CryptoReportCipher struct { + Type [64]uint8 + Blocksize uint32 + Min_keysize uint32 + Max_keysize uint32 +} + +type CryptoReportBlkCipher struct { + Type [64]uint8 + Geniv [64]uint8 + Blocksize uint32 + Min_keysize uint32 + Max_keysize uint32 + Ivsize uint32 +} + +type CryptoReportAEAD struct { + Type [64]uint8 + Geniv [64]uint8 + Blocksize uint32 + Maxauthsize uint32 + Ivsize uint32 +} + +type CryptoReportComp struct { + Type [64]uint8 +} + +type CryptoReportRNG struct { + Type [64]uint8 + Seedsize uint32 +} + +type CryptoReportAKCipher struct { + Type [64]uint8 +} + +type CryptoReportKPP struct { + Type [64]uint8 +} + +type CryptoReportAcomp struct { + Type [64]uint8 +} + +type LoopInfo struct { + Number int32 + Device uint32 + Inode uint32 + Rdevice uint32 + Offset int32 + Encrypt_type int32 + Encrypt_key_size int32 + Flags int32 + Name [64]uint8 + Encrypt_key [32]uint8 + Init [2]uint32 + Reserved [4]uint8 +} + +type TIPCSubscr struct { + Seq TIPCServiceRange + Timeout uint32 + Filter uint32 + Handle [8]uint8 +} + +type TIPCSIOCLNReq struct { + Peer uint32 + Id uint32 + Linkname [68]uint8 +} + +type TIPCSIOCNodeIDReq struct { + Peer uint32 + Id [16]uint8 +} + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400470a1 + PPS_SETPARAMS = 0x800470a2 + PPS_GETCAP = 0x400470a3 + PPS_FETCH = 0xc00470a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime_high uint32 + Atime uint32 + Dtime_high uint32 + Dtime uint32 + Ctime_high uint32 + Ctime uint32 + _ uint32 + Segsz uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 + _ [4]byte +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 602d8b4..c7429c6 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/ppc64/cgo -- -Wall -Werror -static -I/tmp/ppc64/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64,linux +//go:build ppc64 && linux package unix @@ -119,11 +119,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -156,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -219,6 +243,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -229,6 +257,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -287,6 +329,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -364,7 +433,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]uint8 + Data [118]byte _ uint64 } @@ -428,15 +497,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 @@ -600,3 +660,48 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 6db9a7b..4bf4baf 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/ppc64le/cgo -- -Wall -Werror -static -I/tmp/ppc64le/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build ppc64le,linux +//go:build ppc64le && linux package unix @@ -119,11 +119,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -156,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -219,6 +243,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -229,6 +257,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -287,6 +329,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -364,7 +433,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]uint8 + Data [118]byte _ uint64 } @@ -428,15 +497,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 @@ -600,3 +660,48 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 52b5348..e9709d7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/riscv64/cgo -- -Wall -Werror -static -I/tmp/riscv64/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build riscv64,linux +//go:build riscv64 && linux package unix @@ -118,11 +118,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -155,10 +173,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -237,6 +261,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -247,6 +275,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -305,6 +347,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -382,7 +451,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]uint8 + Data [118]byte _ uint64 } @@ -446,15 +515,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 @@ -618,3 +678,109 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} + +type RISCVHWProbePairs struct { + Key int64 + Value uint64 +} + +const ( + RISCV_HWPROBE_KEY_MVENDORID = 0x0 + RISCV_HWPROBE_KEY_MARCHID = 0x1 + RISCV_HWPROBE_KEY_MIMPID = 0x2 + RISCV_HWPROBE_KEY_BASE_BEHAVIOR = 0x3 + RISCV_HWPROBE_BASE_BEHAVIOR_IMA = 0x1 + RISCV_HWPROBE_KEY_IMA_EXT_0 = 0x4 + RISCV_HWPROBE_IMA_FD = 0x1 + RISCV_HWPROBE_IMA_C = 0x2 + RISCV_HWPROBE_IMA_V = 0x4 + RISCV_HWPROBE_EXT_ZBA = 0x8 + RISCV_HWPROBE_EXT_ZBB = 0x10 + RISCV_HWPROBE_EXT_ZBS = 0x20 + RISCV_HWPROBE_EXT_ZICBOZ = 0x40 + RISCV_HWPROBE_EXT_ZBC = 0x80 + RISCV_HWPROBE_EXT_ZBKB = 0x100 + RISCV_HWPROBE_EXT_ZBKC = 0x200 + RISCV_HWPROBE_EXT_ZBKX = 0x400 + RISCV_HWPROBE_EXT_ZKND = 0x800 + RISCV_HWPROBE_EXT_ZKNE = 0x1000 + RISCV_HWPROBE_EXT_ZKNH = 0x2000 + RISCV_HWPROBE_EXT_ZKSED = 0x4000 + RISCV_HWPROBE_EXT_ZKSH = 0x8000 + RISCV_HWPROBE_EXT_ZKT = 0x10000 + RISCV_HWPROBE_EXT_ZVBB = 0x20000 + RISCV_HWPROBE_EXT_ZVBC = 0x40000 + RISCV_HWPROBE_EXT_ZVKB = 0x80000 + RISCV_HWPROBE_EXT_ZVKG = 0x100000 + RISCV_HWPROBE_EXT_ZVKNED = 0x200000 + RISCV_HWPROBE_EXT_ZVKNHA = 0x400000 + RISCV_HWPROBE_EXT_ZVKNHB = 0x800000 + RISCV_HWPROBE_EXT_ZVKSED = 0x1000000 + RISCV_HWPROBE_EXT_ZVKSH = 0x2000000 + RISCV_HWPROBE_EXT_ZVKT = 0x4000000 + RISCV_HWPROBE_EXT_ZFH = 0x8000000 + RISCV_HWPROBE_EXT_ZFHMIN = 0x10000000 + RISCV_HWPROBE_EXT_ZIHINTNTL = 0x20000000 + RISCV_HWPROBE_EXT_ZVFH = 0x40000000 + RISCV_HWPROBE_EXT_ZVFHMIN = 0x80000000 + RISCV_HWPROBE_EXT_ZFA = 0x100000000 + RISCV_HWPROBE_EXT_ZTSO = 0x200000000 + RISCV_HWPROBE_EXT_ZACAS = 0x400000000 + RISCV_HWPROBE_EXT_ZICOND = 0x800000000 + RISCV_HWPROBE_EXT_ZIHINTPAUSE = 0x1000000000 + RISCV_HWPROBE_KEY_CPUPERF_0 = 0x5 + RISCV_HWPROBE_MISALIGNED_UNKNOWN = 0x0 + RISCV_HWPROBE_MISALIGNED_EMULATED = 0x1 + RISCV_HWPROBE_MISALIGNED_SLOW = 0x2 + RISCV_HWPROBE_MISALIGNED_FAST = 0x3 + RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = 0x4 + RISCV_HWPROBE_MISALIGNED_MASK = 0x7 + RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = 0x6 + RISCV_HWPROBE_WHICH_CPUS = 0x1 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index a111387..fb44268 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/s390x/cgo -- -Wall -Werror -static -I/tmp/s390x/include -fsigned-char linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build s390x,linux +//go:build s390x && linux package unix @@ -117,11 +117,29 @@ type Flock_t struct { _ [4]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x6 FADV_NOREUSE = 0x7 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -154,10 +172,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -185,8 +209,8 @@ type PtraceFpregs struct { } type PtracePer struct { - _ [0]uint64 - _ [32]byte + Control_regs [3]uint64 + _ [8]byte Starting_addr uint64 Ending_addr uint64 Perc_atmid uint16 @@ -232,6 +256,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x80000 +) + const ( POLLRDHUP = 0x2000 ) @@ -242,6 +270,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x0 + SIG_UNBLOCK = 0x1 + SIG_SETMASK = 0x2 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -300,6 +342,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -377,7 +446,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]int8 + Data [118]byte _ uint64 } @@ -442,15 +511,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -614,3 +674,48 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ uint16 + Seq uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 8153af1..9c38265 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -1,7 +1,7 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go +// cgo -godefs -objdir=/tmp/sparc64/cgo -- -Wall -Werror -static -I/tmp/sparc64/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build sparc64,linux +//go:build sparc64 && linux package unix @@ -121,11 +121,29 @@ type Flock_t struct { _ [2]byte } +type DmNameList struct { + Dev uint64 + Next uint32 + Name [0]byte + _ [4]byte +} + const ( FADV_DONTNEED = 0x4 FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -158,10 +176,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( @@ -214,6 +238,10 @@ type EpollEvent struct { Pad int32 } +const ( + OPEN_TREE_CLOEXEC = 0x400000 +) + const ( POLLRDHUP = 0x800 ) @@ -224,6 +252,20 @@ type Sigset_t struct { const _C__NSIG = 0x41 +const ( + SIG_BLOCK = 0x1 + SIG_UNBLOCK = 0x2 + SIG_SETMASK = 0x4 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + _ int32 + _ [112]byte +} + type Termios struct { Iflag uint32 Oflag uint32 @@ -282,6 +324,33 @@ type Taskstats struct { Freepages_delay_total uint64 Thrashing_count uint64 Thrashing_delay_total uint64 + Ac_btime64 uint64 + Compact_count uint64 + Compact_delay_total uint64 + Ac_tgid uint32 + Ac_tgetime uint64 + Ac_exe_dev uint64 + Ac_exe_inode uint64 + Wpcopy_count uint64 + Wpcopy_delay_total uint64 + Irq_count uint64 + Irq_delay_total uint64 + Cpu_delay_max uint64 + Cpu_delay_min uint64 + Blkio_delay_max uint64 + Blkio_delay_min uint64 + Swapin_delay_max uint64 + Swapin_delay_min uint64 + Freepages_delay_max uint64 + Freepages_delay_min uint64 + Thrashing_delay_max uint64 + Thrashing_delay_min uint64 + Compact_delay_max uint64 + Compact_delay_min uint64 + Wpcopy_delay_max uint64 + Wpcopy_delay_min uint64 + Irq_delay_max uint64 + Irq_delay_min uint64 } type cpuMask uint64 @@ -359,7 +428,7 @@ const ( type SockaddrStorage struct { Family uint16 - _ [118]int8 + Data [118]byte _ uint64 } @@ -423,15 +492,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 @@ -595,3 +655,48 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) + +const ( + PIDFD_NONBLOCK = 0x4000 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ uint16 + Seq uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go index a89100c..f22e794 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go @@ -1,7 +1,7 @@ // cgo -godefs types_netbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,netbsd +//go:build 386 && netbsd package unix @@ -248,6 +248,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c @@ -443,8 +444,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -487,6 +490,90 @@ type Utsname struct { Machine [256]byte } +const SizeofUvmexp = 0x278 + +type Uvmexp struct { + Pagesize int64 + Pagemask int64 + Pageshift int64 + Npages int64 + Free int64 + Active int64 + Inactive int64 + Paging int64 + Wired int64 + Zeropages int64 + Reserve_pagedaemon int64 + Reserve_kernel int64 + Freemin int64 + Freetarg int64 + Inactarg int64 + Wiredmax int64 + Nswapdev int64 + Swpages int64 + Swpginuse int64 + Swpgonly int64 + Nswget int64 + Unused1 int64 + Cpuhit int64 + Cpumiss int64 + Faults int64 + Traps int64 + Intrs int64 + Swtch int64 + Softs int64 + Syscalls int64 + Pageins int64 + Swapins int64 + Swapouts int64 + Pgswapin int64 + Pgswapout int64 + Forks int64 + Forks_ppwait int64 + Forks_sharevm int64 + Pga_zerohit int64 + Pga_zeromiss int64 + Zeroaborts int64 + Fltnoram int64 + Fltnoanon int64 + Fltpgwait int64 + Fltpgrele int64 + Fltrelck int64 + Fltrelckok int64 + Fltanget int64 + Fltanretry int64 + Fltamcopy int64 + Fltnamap int64 + Fltnomap int64 + Fltlget int64 + Fltget int64 + Flt_anon int64 + Flt_acow int64 + Flt_obj int64 + Flt_prcopy int64 + Flt_przero int64 + Pdwoke int64 + Pdrevs int64 + Unused4 int64 + Pdfreed int64 + Pdscans int64 + Pdanscan int64 + Pdobscan int64 + Pdreact int64 + Pdbusy int64 + Pdpageouts int64 + Pdpending int64 + Pddeact int64 + Anonpages int64 + Filepages int64 + Execpages int64 + Colorhit int64 + Colormiss int64 + Ncolors int64 + Bootpages int64 + Poolpages int64 +} + const SizeofClockinfo = 0x14 type Clockinfo struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go index 289184e..066a7d8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go @@ -1,7 +1,7 @@ // cgo -godefs types_netbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,netbsd +//go:build amd64 && netbsd package unix @@ -255,6 +255,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 @@ -451,8 +452,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -495,6 +498,90 @@ type Utsname struct { Machine [256]byte } +const SizeofUvmexp = 0x278 + +type Uvmexp struct { + Pagesize int64 + Pagemask int64 + Pageshift int64 + Npages int64 + Free int64 + Active int64 + Inactive int64 + Paging int64 + Wired int64 + Zeropages int64 + Reserve_pagedaemon int64 + Reserve_kernel int64 + Freemin int64 + Freetarg int64 + Inactarg int64 + Wiredmax int64 + Nswapdev int64 + Swpages int64 + Swpginuse int64 + Swpgonly int64 + Nswget int64 + Unused1 int64 + Cpuhit int64 + Cpumiss int64 + Faults int64 + Traps int64 + Intrs int64 + Swtch int64 + Softs int64 + Syscalls int64 + Pageins int64 + Swapins int64 + Swapouts int64 + Pgswapin int64 + Pgswapout int64 + Forks int64 + Forks_ppwait int64 + Forks_sharevm int64 + Pga_zerohit int64 + Pga_zeromiss int64 + Zeroaborts int64 + Fltnoram int64 + Fltnoanon int64 + Fltpgwait int64 + Fltpgrele int64 + Fltrelck int64 + Fltrelckok int64 + Fltanget int64 + Fltanretry int64 + Fltamcopy int64 + Fltnamap int64 + Fltnomap int64 + Fltlget int64 + Fltget int64 + Flt_anon int64 + Flt_acow int64 + Flt_obj int64 + Flt_prcopy int64 + Flt_przero int64 + Pdwoke int64 + Pdrevs int64 + Unused4 int64 + Pdfreed int64 + Pdscans int64 + Pdanscan int64 + Pdobscan int64 + Pdreact int64 + Pdbusy int64 + Pdpageouts int64 + Pdpending int64 + Pddeact int64 + Anonpages int64 + Filepages int64 + Execpages int64 + Colorhit int64 + Colormiss int64 + Ncolors int64 + Bootpages int64 + Poolpages int64 +} + const SizeofClockinfo = 0x14 type Clockinfo struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go index 428c450..50e8e64 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go @@ -1,7 +1,7 @@ // cgo -godefs types_netbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,netbsd +//go:build arm && netbsd package unix @@ -104,7 +104,7 @@ type Statvfs_t struct { Fsid uint32 Namemax uint32 Owner uint32 - Spare [4]uint32 + Spare [4]uint64 Fstypename [32]byte Mntonname [1024]byte Mntfromname [1024]byte @@ -253,6 +253,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c @@ -448,8 +449,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -492,6 +495,90 @@ type Utsname struct { Machine [256]byte } +const SizeofUvmexp = 0x278 + +type Uvmexp struct { + Pagesize int64 + Pagemask int64 + Pageshift int64 + Npages int64 + Free int64 + Active int64 + Inactive int64 + Paging int64 + Wired int64 + Zeropages int64 + Reserve_pagedaemon int64 + Reserve_kernel int64 + Freemin int64 + Freetarg int64 + Inactarg int64 + Wiredmax int64 + Nswapdev int64 + Swpages int64 + Swpginuse int64 + Swpgonly int64 + Nswget int64 + Unused1 int64 + Cpuhit int64 + Cpumiss int64 + Faults int64 + Traps int64 + Intrs int64 + Swtch int64 + Softs int64 + Syscalls int64 + Pageins int64 + Swapins int64 + Swapouts int64 + Pgswapin int64 + Pgswapout int64 + Forks int64 + Forks_ppwait int64 + Forks_sharevm int64 + Pga_zerohit int64 + Pga_zeromiss int64 + Zeroaborts int64 + Fltnoram int64 + Fltnoanon int64 + Fltpgwait int64 + Fltpgrele int64 + Fltrelck int64 + Fltrelckok int64 + Fltanget int64 + Fltanretry int64 + Fltamcopy int64 + Fltnamap int64 + Fltnomap int64 + Fltlget int64 + Fltget int64 + Flt_anon int64 + Flt_acow int64 + Flt_obj int64 + Flt_prcopy int64 + Flt_przero int64 + Pdwoke int64 + Pdrevs int64 + Unused4 int64 + Pdfreed int64 + Pdscans int64 + Pdanscan int64 + Pdobscan int64 + Pdreact int64 + Pdbusy int64 + Pdpageouts int64 + Pdpending int64 + Pddeact int64 + Anonpages int64 + Filepages int64 + Execpages int64 + Colorhit int64 + Colormiss int64 + Ncolors int64 + Bootpages int64 + Poolpages int64 +} + const SizeofClockinfo = 0x14 type Clockinfo struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go index 6f1f284..16085d3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go @@ -1,7 +1,7 @@ // cgo -godefs types_netbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,netbsd +//go:build arm64 && netbsd package unix @@ -255,6 +255,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 @@ -451,8 +452,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { @@ -495,6 +498,90 @@ type Utsname struct { Machine [256]byte } +const SizeofUvmexp = 0x278 + +type Uvmexp struct { + Pagesize int64 + Pagemask int64 + Pageshift int64 + Npages int64 + Free int64 + Active int64 + Inactive int64 + Paging int64 + Wired int64 + Zeropages int64 + Reserve_pagedaemon int64 + Reserve_kernel int64 + Freemin int64 + Freetarg int64 + Inactarg int64 + Wiredmax int64 + Nswapdev int64 + Swpages int64 + Swpginuse int64 + Swpgonly int64 + Nswget int64 + Unused1 int64 + Cpuhit int64 + Cpumiss int64 + Faults int64 + Traps int64 + Intrs int64 + Swtch int64 + Softs int64 + Syscalls int64 + Pageins int64 + Swapins int64 + Swapouts int64 + Pgswapin int64 + Pgswapout int64 + Forks int64 + Forks_ppwait int64 + Forks_sharevm int64 + Pga_zerohit int64 + Pga_zeromiss int64 + Zeroaborts int64 + Fltnoram int64 + Fltnoanon int64 + Fltpgwait int64 + Fltpgrele int64 + Fltrelck int64 + Fltrelckok int64 + Fltanget int64 + Fltanretry int64 + Fltamcopy int64 + Fltnamap int64 + Fltnomap int64 + Fltlget int64 + Fltget int64 + Flt_anon int64 + Flt_acow int64 + Flt_obj int64 + Flt_prcopy int64 + Flt_przero int64 + Pdwoke int64 + Pdrevs int64 + Unused4 int64 + Pdfreed int64 + Pdscans int64 + Pdanscan int64 + Pdobscan int64 + Pdreact int64 + Pdbusy int64 + Pdpageouts int64 + Pdpending int64 + Pddeact int64 + Anonpages int64 + Filepages int64 + Execpages int64 + Colorhit int64 + Colormiss int64 + Ncolors int64 + Bootpages int64 + Poolpages int64 +} + const SizeofClockinfo = 0x14 type Clockinfo struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index 61ea001..afd13a3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -1,7 +1,7 @@ // cgo -godefs types_openbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build 386,openbsd +//go:build 386 && openbsd package unix @@ -57,22 +57,22 @@ type Rlimit struct { type _Gid_t uint32 type Stat_t struct { - Mode uint32 - Dev int32 - Ino uint64 - Nlink uint32 - Uid uint32 - Gid uint32 - Rdev int32 - Atim Timespec - Mtim Timespec - Ctim Timespec - Size int64 - Blocks int64 - Blksize uint32 - Flags uint32 - Gen uint32 - X__st_birthtim Timespec + Mode uint32 + Dev int32 + Ino uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev int32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + _ Timespec } type Statfs_t struct { @@ -93,11 +93,11 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 - Pad_cgo_0 [2]byte + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte + _ [2]byte Mount_info [160]byte } @@ -110,13 +110,13 @@ type Flock_t struct { } type Dirent struct { - Fileno uint64 - Off int64 - Reclen uint16 - Type uint8 - Namlen uint8 - X__d_padding [4]uint8 - Name [256]int8 + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Namlen uint8 + _ [4]uint8 + Name [256]int8 } type Fsid struct { @@ -231,6 +231,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c @@ -260,8 +261,8 @@ type FdSet struct { } const ( - SizeofIfMsghdr = 0xec - SizeofIfData = 0xd4 + SizeofIfMsghdr = 0xa0 + SizeofIfData = 0x88 SizeofIfaMsghdr = 0x18 SizeofIfAnnounceMsghdr = 0x1a SizeofRtMsghdr = 0x60 @@ -290,7 +291,7 @@ type IfData struct { Link_state uint8 Mtu uint32 Metric uint32 - Pad uint32 + Rdomain uint32 Baudrate uint64 Ipackets uint64 Ierrors uint64 @@ -302,10 +303,10 @@ type IfData struct { Imcasts uint64 Omcasts uint64 Iqdrops uint64 + Oqdrops uint64 Noproto uint64 Capabilities uint32 Lastchange Timeval - Mclpool [7]Mclpool } type IfaMsghdr struct { @@ -366,20 +367,12 @@ type RtMetrics struct { Pad uint32 } -type Mclpool struct { - Grown int32 - Alive uint16 - Hwm uint16 - Cwm uint16 - Lwm uint16 -} - const ( SizeofBpfVersion = 0x4 SizeofBpfStat = 0x8 SizeofBpfProgram = 0x8 SizeofBpfInsn = 0x8 - SizeofBpfHdr = 0x14 + SizeofBpfHdr = 0x18 ) type BpfVersion struct { @@ -405,11 +398,14 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp BpfTimeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp BpfTimeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 } type BpfTimeval struct { @@ -436,8 +432,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { @@ -484,7 +482,7 @@ type Uvmexp struct { Zeropages int32 Reserve_pagedaemon int32 Reserve_kernel int32 - Anonpages int32 + Unused01 int32 Vnodepages int32 Vtextpages int32 Freemin int32 @@ -503,8 +501,8 @@ type Uvmexp struct { Swpgonly int32 Nswget int32 Nanon int32 - Nanonneeded int32 - Nfreeanon int32 + Unused05 int32 + Unused06 int32 Faults int32 Traps int32 Intrs int32 @@ -512,8 +510,8 @@ type Uvmexp struct { Softs int32 Syscalls int32 Pageins int32 - Obsolete_swapins int32 - Obsolete_swapouts int32 + Unused07 int32 + Unused08 int32 Pgswapin int32 Pgswapout int32 Forks int32 @@ -521,7 +519,7 @@ type Uvmexp struct { Forks_sharevm int32 Pga_zerohit int32 Pga_zeromiss int32 - Zeroaborts int32 + Unused09 int32 Fltnoram int32 Fltnoanon int32 Fltnoamap int32 @@ -553,19 +551,18 @@ type Uvmexp struct { Pdpageouts int32 Pdpending int32 Pddeact int32 - Pdreanon int32 - Pdrevnode int32 - Pdrevtext int32 + Unused11 int32 + Unused12 int32 + Unused13 int32 Fpswtch int32 Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index 87a493f..5d97f1f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -1,7 +1,7 @@ // cgo -godefs types_openbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,openbsd +//go:build amd64 && openbsd package unix @@ -72,7 +72,6 @@ type Stat_t struct { Blksize int32 Flags uint32 Gen uint32 - _ [4]byte _ Timespec } @@ -80,7 +79,6 @@ type Statfs_t struct { F_flags uint32 F_bsize uint32 F_iosize uint32 - _ [4]byte F_blocks uint64 F_bfree uint64 F_bavail int64 @@ -95,10 +93,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } @@ -199,10 +197,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen uint32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -235,6 +231,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 @@ -309,7 +306,6 @@ type IfData struct { Oqdrops uint64 Noproto uint64 Capabilities uint32 - _ [4]byte Lastchange Timeval } @@ -371,14 +367,12 @@ type RtMetrics struct { Pad uint32 } -type Mclpool struct{} - const ( SizeofBpfVersion = 0x4 SizeofBpfStat = 0x8 SizeofBpfProgram = 0x10 SizeofBpfInsn = 0x8 - SizeofBpfHdr = 0x14 + SizeofBpfHdr = 0x18 ) type BpfVersion struct { @@ -393,7 +387,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -409,7 +402,10 @@ type BpfHdr struct { Caplen uint32 Datalen uint32 Hdrlen uint16 - _ [2]byte + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 } type BpfTimeval struct { @@ -436,8 +432,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { @@ -484,7 +482,7 @@ type Uvmexp struct { Zeropages int32 Reserve_pagedaemon int32 Reserve_kernel int32 - Anonpages int32 + Unused01 int32 Vnodepages int32 Vtextpages int32 Freemin int32 @@ -503,8 +501,8 @@ type Uvmexp struct { Swpgonly int32 Nswget int32 Nanon int32 - Nanonneeded int32 - Nfreeanon int32 + Unused05 int32 + Unused06 int32 Faults int32 Traps int32 Intrs int32 @@ -512,8 +510,8 @@ type Uvmexp struct { Softs int32 Syscalls int32 Pageins int32 - Obsolete_swapins int32 - Obsolete_swapouts int32 + Unused07 int32 + Unused08 int32 Pgswapin int32 Pgswapout int32 Forks int32 @@ -521,7 +519,7 @@ type Uvmexp struct { Forks_sharevm int32 Pga_zerohit int32 Pga_zeromiss int32 - Zeroaborts int32 + Unused09 int32 Fltnoram int32 Fltnoanon int32 Fltnoamap int32 @@ -553,19 +551,18 @@ type Uvmexp struct { Pdpageouts int32 Pdpending int32 Pddeact int32 - Pdreanon int32 - Pdrevnode int32 - Pdrevtext int32 + Unused11 int32 + Unused12 int32 + Unused13 int32 Fpswtch int32 Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index d80836e..34871cd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -1,7 +1,7 @@ // cgo -godefs -- -fsigned-char types_openbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm,openbsd +//go:build arm && openbsd package unix @@ -97,10 +97,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } @@ -235,6 +235,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c @@ -373,14 +374,12 @@ type RtMetrics struct { Pad uint32 } -type Mclpool struct{} - const ( SizeofBpfVersion = 0x4 SizeofBpfStat = 0x8 SizeofBpfProgram = 0x8 SizeofBpfInsn = 0x8 - SizeofBpfHdr = 0x14 + SizeofBpfHdr = 0x18 ) type BpfVersion struct { @@ -410,7 +409,10 @@ type BpfHdr struct { Caplen uint32 Datalen uint32 Hdrlen uint16 - _ [2]byte + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 } type BpfTimeval struct { @@ -437,8 +439,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { @@ -561,12 +565,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index 4e15874..5911bce 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -1,7 +1,7 @@ // cgo -godefs -- -fsigned-char types_openbsd.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build arm64,openbsd +//go:build arm64 && openbsd package unix @@ -93,10 +93,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } @@ -231,6 +231,7 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x20 SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 @@ -366,14 +367,12 @@ type RtMetrics struct { Pad uint32 } -type Mclpool struct{} - const ( SizeofBpfVersion = 0x4 SizeofBpfStat = 0x8 SizeofBpfProgram = 0x10 SizeofBpfInsn = 0x8 - SizeofBpfHdr = 0x14 + SizeofBpfHdr = 0x18 ) type BpfVersion struct { @@ -403,7 +402,10 @@ type BpfHdr struct { Caplen uint32 Datalen uint32 Hdrlen uint16 - _ [2]byte + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 } type BpfTimeval struct { @@ -430,8 +432,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { @@ -554,12 +558,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go new file mode 100644 index 0000000..e4f24f3 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -0,0 +1,568 @@ +// cgo -godefs -- -fsigned-char types_openbsd.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build mips64 && openbsd + +package unix + +const ( + SizeofPtr = 0x8 + SizeofShort = 0x2 + SizeofInt = 0x4 + SizeofLong = 0x8 + SizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Rlimit struct { + Cur uint64 + Max uint64 +} + +type _Gid_t uint32 + +type Stat_t struct { + Mode uint32 + Dev int32 + Ino uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev int32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + _ Timespec +} + +type Statfs_t struct { + F_flags uint32 + F_bsize uint32 + F_iosize uint32 + F_blocks uint64 + F_bfree uint64 + F_bavail int64 + F_files uint64 + F_ffree uint64 + F_favail int64 + F_syncwrites uint64 + F_syncreads uint64 + F_asyncwrites uint64 + F_asyncreads uint64 + F_fsid Fsid + F_namemax uint32 + F_owner uint32 + F_ctime uint64 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte + _ [2]byte + Mount_info [160]byte +} + +type Flock_t struct { + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 +} + +type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Namlen uint8 + _ [4]uint8 + Name [256]int8 +} + +type Fsid struct { + Val [2]int32 +} + +const ( + PathMax = 0x400 +) + +type RawSockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]int8 +} + +type RawSockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddrUnix struct { + Len uint8 + Family uint8 + Path [104]int8 +} + +type RawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [24]int8 +} + +type RawSockaddr struct { + Len uint8 + Family uint8 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [92]int8 +} + +type _Socklen uint32 + +type Linger struct { + Onoff int32 + Linger int32 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Iov *Iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 +} + +type Cmsghdr struct { + Len uint32 + Level int32 + Type int32 +} + +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type IPv6MTUInfo struct { + Addr RawSockaddrInet6 + Mtu uint32 +} + +type ICMPv6Filter struct { + Filt [8]uint32 +} + +const ( + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x20 + SizeofLinger = 0x8 + SizeofIovec = 0x10 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 +) + +const ( + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 +) + +type Kevent_t struct { + Ident uint64 + Filter int16 + Flags uint16 + Fflags uint32 + Data int64 + Udata *byte +} + +type FdSet struct { + Bits [32]uint32 +} + +const ( + SizeofIfMsghdr = 0xa8 + SizeofIfData = 0x90 + SizeofIfaMsghdr = 0x18 + SizeofIfAnnounceMsghdr = 0x1a + SizeofRtMsghdr = 0x60 + SizeofRtMetrics = 0x38 +) + +type IfMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Pad1 uint8 + Pad2 uint8 + Addrs int32 + Flags int32 + Xflags int32 + Data IfData +} + +type IfData struct { + Type uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Mtu uint32 + Metric uint32 + Rdomain uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Capabilities uint32 + Lastchange Timeval +} + +type IfaMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Pad1 uint8 + Pad2 uint8 + Addrs int32 + Flags int32 + Metric int32 +} + +type IfAnnounceMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + What uint16 + Name [16]int8 +} + +type RtMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Priority uint8 + Mpls uint8 + Addrs int32 + Flags int32 + Fmask int32 + Pid int32 + Seq int32 + Errno int32 + Inits uint32 + Rmx RtMetrics +} + +type RtMetrics struct { + Pksent uint64 + Expire int64 + Locks uint32 + Mtu uint32 + Refcnt uint32 + Hopcount uint32 + Recvpipe uint32 + Sendpipe uint32 + Ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Pad uint32 +} + +const ( + SizeofBpfVersion = 0x4 + SizeofBpfStat = 0x8 + SizeofBpfProgram = 0x10 + SizeofBpfInsn = 0x8 + SizeofBpfHdr = 0x18 +) + +type BpfVersion struct { + Major uint16 + Minor uint16 +} + +type BpfStat struct { + Recv uint32 + Drop uint32 +} + +type BpfProgram struct { + Len uint32 + Insns *BpfInsn +} + +type BpfInsn struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} + +type BpfHdr struct { + Tstamp BpfTimeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 +} + +type BpfTimeval struct { + Sec uint32 + Usec uint32 +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]uint8 + Ispeed int32 + Ospeed int32 +} + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +const ( + AT_FDCWD = -0x64 + AT_EACCESS = 0x1 + AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 +) + +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLERR = 0x8 + POLLHUP = 0x10 + POLLIN = 0x1 + POLLNVAL = 0x20 + POLLOUT = 0x4 + POLLPRI = 0x2 + POLLRDBAND = 0x80 + POLLRDNORM = 0x40 + POLLWRBAND = 0x100 + POLLWRNORM = 0x4 +) + +type Sigset_t uint32 + +type Utsname struct { + Sysname [256]byte + Nodename [256]byte + Release [256]byte + Version [256]byte + Machine [256]byte +} + +const SizeofUvmexp = 0x158 + +type Uvmexp struct { + Pagesize int32 + Pagemask int32 + Pageshift int32 + Npages int32 + Free int32 + Active int32 + Inactive int32 + Paging int32 + Wired int32 + Zeropages int32 + Reserve_pagedaemon int32 + Reserve_kernel int32 + Unused01 int32 + Vnodepages int32 + Vtextpages int32 + Freemin int32 + Freetarg int32 + Inactarg int32 + Wiredmax int32 + Anonmin int32 + Vtextmin int32 + Vnodemin int32 + Anonminpct int32 + Vtextminpct int32 + Vnodeminpct int32 + Nswapdev int32 + Swpages int32 + Swpginuse int32 + Swpgonly int32 + Nswget int32 + Nanon int32 + Unused05 int32 + Unused06 int32 + Faults int32 + Traps int32 + Intrs int32 + Swtch int32 + Softs int32 + Syscalls int32 + Pageins int32 + Unused07 int32 + Unused08 int32 + Pgswapin int32 + Pgswapout int32 + Forks int32 + Forks_ppwait int32 + Forks_sharevm int32 + Pga_zerohit int32 + Pga_zeromiss int32 + Unused09 int32 + Fltnoram int32 + Fltnoanon int32 + Fltnoamap int32 + Fltpgwait int32 + Fltpgrele int32 + Fltrelck int32 + Fltrelckok int32 + Fltanget int32 + Fltanretry int32 + Fltamcopy int32 + Fltnamap int32 + Fltnomap int32 + Fltlget int32 + Fltget int32 + Flt_anon int32 + Flt_acow int32 + Flt_obj int32 + Flt_prcopy int32 + Flt_przero int32 + Pdwoke int32 + Pdrevs int32 + Pdswout int32 + Pdfreed int32 + Pdscans int32 + Pdanscan int32 + Pdobscan int32 + Pdreact int32 + Pdbusy int32 + Pdpageouts int32 + Pdpending int32 + Pddeact int32 + Unused11 int32 + Unused12 int32 + Unused13 int32 + Fpswtch int32 + Kmapent int32 +} + +const SizeofClockinfo = 0x10 + +type Clockinfo struct { + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go new file mode 100644 index 0000000..ca50a79 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go @@ -0,0 +1,570 @@ +// cgo -godefs -- -fsigned-char types_openbsd.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build ppc64 && openbsd + +package unix + +const ( + SizeofPtr = 0x8 + SizeofShort = 0x2 + SizeofInt = 0x4 + SizeofLong = 0x8 + SizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Rlimit struct { + Cur uint64 + Max uint64 +} + +type _Gid_t uint32 + +type Stat_t struct { + Mode uint32 + Dev int32 + Ino uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev int32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + _ Timespec +} + +type Statfs_t struct { + F_flags uint32 + F_bsize uint32 + F_iosize uint32 + F_blocks uint64 + F_bfree uint64 + F_bavail int64 + F_files uint64 + F_ffree uint64 + F_favail int64 + F_syncwrites uint64 + F_syncreads uint64 + F_asyncwrites uint64 + F_asyncreads uint64 + F_fsid Fsid + F_namemax uint32 + F_owner uint32 + F_ctime uint64 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte + _ [2]byte + Mount_info [160]byte +} + +type Flock_t struct { + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 +} + +type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Namlen uint8 + _ [4]uint8 + Name [256]int8 +} + +type Fsid struct { + Val [2]int32 +} + +const ( + PathMax = 0x400 +) + +type RawSockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]int8 +} + +type RawSockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddrUnix struct { + Len uint8 + Family uint8 + Path [104]int8 +} + +type RawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [24]int8 +} + +type RawSockaddr struct { + Len uint8 + Family uint8 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [92]int8 +} + +type _Socklen uint32 + +type Linger struct { + Onoff int32 + Linger int32 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Iov *Iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 +} + +type Cmsghdr struct { + Len uint32 + Level int32 + Type int32 +} + +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type IPv6MTUInfo struct { + Addr RawSockaddrInet6 + Mtu uint32 +} + +type ICMPv6Filter struct { + Filt [8]uint32 +} + +const ( + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x20 + SizeofLinger = 0x8 + SizeofIovec = 0x10 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 +) + +const ( + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 +) + +type Kevent_t struct { + Ident uint64 + Filter int16 + Flags uint16 + Fflags uint32 + Data int64 + Udata *byte +} + +type FdSet struct { + Bits [32]uint32 +} + +const ( + SizeofIfMsghdr = 0xa8 + SizeofIfData = 0x90 + SizeofIfaMsghdr = 0x18 + SizeofIfAnnounceMsghdr = 0x1a + SizeofRtMsghdr = 0x60 + SizeofRtMetrics = 0x38 +) + +type IfMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Pad1 uint8 + Pad2 uint8 + Addrs int32 + Flags int32 + Xflags int32 + Data IfData +} + +type IfData struct { + Type uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Mtu uint32 + Metric uint32 + Rdomain uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Capabilities uint32 + Lastchange Timeval +} + +type IfaMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Pad1 uint8 + Pad2 uint8 + Addrs int32 + Flags int32 + Metric int32 +} + +type IfAnnounceMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + What uint16 + Name [16]int8 +} + +type RtMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Priority uint8 + Mpls uint8 + Addrs int32 + Flags int32 + Fmask int32 + Pid int32 + Seq int32 + Errno int32 + Inits uint32 + Rmx RtMetrics +} + +type RtMetrics struct { + Pksent uint64 + Expire int64 + Locks uint32 + Mtu uint32 + Refcnt uint32 + Hopcount uint32 + Recvpipe uint32 + Sendpipe uint32 + Ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Pad uint32 +} + +type Mclpool struct{} + +const ( + SizeofBpfVersion = 0x4 + SizeofBpfStat = 0x8 + SizeofBpfProgram = 0x10 + SizeofBpfInsn = 0x8 + SizeofBpfHdr = 0x18 +) + +type BpfVersion struct { + Major uint16 + Minor uint16 +} + +type BpfStat struct { + Recv uint32 + Drop uint32 +} + +type BpfProgram struct { + Len uint32 + Insns *BpfInsn +} + +type BpfInsn struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} + +type BpfHdr struct { + Tstamp BpfTimeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 +} + +type BpfTimeval struct { + Sec uint32 + Usec uint32 +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]uint8 + Ispeed int32 + Ospeed int32 +} + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +const ( + AT_FDCWD = -0x64 + AT_EACCESS = 0x1 + AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 +) + +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLERR = 0x8 + POLLHUP = 0x10 + POLLIN = 0x1 + POLLNVAL = 0x20 + POLLOUT = 0x4 + POLLPRI = 0x2 + POLLRDBAND = 0x80 + POLLRDNORM = 0x40 + POLLWRBAND = 0x100 + POLLWRNORM = 0x4 +) + +type Sigset_t uint32 + +type Utsname struct { + Sysname [256]byte + Nodename [256]byte + Release [256]byte + Version [256]byte + Machine [256]byte +} + +const SizeofUvmexp = 0x158 + +type Uvmexp struct { + Pagesize int32 + Pagemask int32 + Pageshift int32 + Npages int32 + Free int32 + Active int32 + Inactive int32 + Paging int32 + Wired int32 + Zeropages int32 + Reserve_pagedaemon int32 + Reserve_kernel int32 + Unused01 int32 + Vnodepages int32 + Vtextpages int32 + Freemin int32 + Freetarg int32 + Inactarg int32 + Wiredmax int32 + Anonmin int32 + Vtextmin int32 + Vnodemin int32 + Anonminpct int32 + Vtextminpct int32 + Vnodeminpct int32 + Nswapdev int32 + Swpages int32 + Swpginuse int32 + Swpgonly int32 + Nswget int32 + Nanon int32 + Unused05 int32 + Unused06 int32 + Faults int32 + Traps int32 + Intrs int32 + Swtch int32 + Softs int32 + Syscalls int32 + Pageins int32 + Unused07 int32 + Unused08 int32 + Pgswapin int32 + Pgswapout int32 + Forks int32 + Forks_ppwait int32 + Forks_sharevm int32 + Pga_zerohit int32 + Pga_zeromiss int32 + Unused09 int32 + Fltnoram int32 + Fltnoanon int32 + Fltnoamap int32 + Fltpgwait int32 + Fltpgrele int32 + Fltrelck int32 + Fltrelckok int32 + Fltanget int32 + Fltanretry int32 + Fltamcopy int32 + Fltnamap int32 + Fltnomap int32 + Fltlget int32 + Fltget int32 + Flt_anon int32 + Flt_acow int32 + Flt_obj int32 + Flt_prcopy int32 + Flt_przero int32 + Pdwoke int32 + Pdrevs int32 + Pdswout int32 + Pdfreed int32 + Pdscans int32 + Pdanscan int32 + Pdobscan int32 + Pdreact int32 + Pdbusy int32 + Pdpageouts int32 + Pdpending int32 + Pddeact int32 + Unused11 int32 + Unused12 int32 + Unused13 int32 + Fpswtch int32 + Kmapent int32 +} + +const SizeofClockinfo = 0x10 + +type Clockinfo struct { + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go new file mode 100644 index 0000000..d7d7f79 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go @@ -0,0 +1,570 @@ +// cgo -godefs -- -fsigned-char types_openbsd.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build riscv64 && openbsd + +package unix + +const ( + SizeofPtr = 0x8 + SizeofShort = 0x2 + SizeofInt = 0x4 + SizeofLong = 0x8 + SizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Rlimit struct { + Cur uint64 + Max uint64 +} + +type _Gid_t uint32 + +type Stat_t struct { + Mode uint32 + Dev int32 + Ino uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev int32 + Atim Timespec + Mtim Timespec + Ctim Timespec + Size int64 + Blocks int64 + Blksize int32 + Flags uint32 + Gen uint32 + _ Timespec +} + +type Statfs_t struct { + F_flags uint32 + F_bsize uint32 + F_iosize uint32 + F_blocks uint64 + F_bfree uint64 + F_bavail int64 + F_files uint64 + F_ffree uint64 + F_favail int64 + F_syncwrites uint64 + F_syncreads uint64 + F_asyncwrites uint64 + F_asyncreads uint64 + F_fsid Fsid + F_namemax uint32 + F_owner uint32 + F_ctime uint64 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte + _ [2]byte + Mount_info [160]byte +} + +type Flock_t struct { + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 +} + +type Dirent struct { + Fileno uint64 + Off int64 + Reclen uint16 + Type uint8 + Namlen uint8 + _ [4]uint8 + Name [256]int8 +} + +type Fsid struct { + Val [2]int32 +} + +const ( + PathMax = 0x400 +) + +type RawSockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]int8 +} + +type RawSockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddrUnix struct { + Len uint8 + Family uint8 + Path [104]int8 +} + +type RawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [24]int8 +} + +type RawSockaddr struct { + Len uint8 + Family uint8 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [92]int8 +} + +type _Socklen uint32 + +type Linger struct { + Onoff int32 + Linger int32 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Iov *Iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 +} + +type Cmsghdr struct { + Len uint32 + Level int32 + Type int32 +} + +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type IPv6MTUInfo struct { + Addr RawSockaddrInet6 + Mtu uint32 +} + +type ICMPv6Filter struct { + Filt [8]uint32 +} + +const ( + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x20 + SizeofLinger = 0x8 + SizeofIovec = 0x10 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 +) + +const ( + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 +) + +type Kevent_t struct { + Ident uint64 + Filter int16 + Flags uint16 + Fflags uint32 + Data int64 + Udata *byte +} + +type FdSet struct { + Bits [32]uint32 +} + +const ( + SizeofIfMsghdr = 0xa8 + SizeofIfData = 0x90 + SizeofIfaMsghdr = 0x18 + SizeofIfAnnounceMsghdr = 0x1a + SizeofRtMsghdr = 0x60 + SizeofRtMetrics = 0x38 +) + +type IfMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Pad1 uint8 + Pad2 uint8 + Addrs int32 + Flags int32 + Xflags int32 + Data IfData +} + +type IfData struct { + Type uint8 + Addrlen uint8 + Hdrlen uint8 + Link_state uint8 + Mtu uint32 + Metric uint32 + Rdomain uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Oqdrops uint64 + Noproto uint64 + Capabilities uint32 + Lastchange Timeval +} + +type IfaMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Pad1 uint8 + Pad2 uint8 + Addrs int32 + Flags int32 + Metric int32 +} + +type IfAnnounceMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + What uint16 + Name [16]int8 +} + +type RtMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Hdrlen uint16 + Index uint16 + Tableid uint16 + Priority uint8 + Mpls uint8 + Addrs int32 + Flags int32 + Fmask int32 + Pid int32 + Seq int32 + Errno int32 + Inits uint32 + Rmx RtMetrics +} + +type RtMetrics struct { + Pksent uint64 + Expire int64 + Locks uint32 + Mtu uint32 + Refcnt uint32 + Hopcount uint32 + Recvpipe uint32 + Sendpipe uint32 + Ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Pad uint32 +} + +type Mclpool struct{} + +const ( + SizeofBpfVersion = 0x4 + SizeofBpfStat = 0x8 + SizeofBpfProgram = 0x10 + SizeofBpfInsn = 0x8 + SizeofBpfHdr = 0x18 +) + +type BpfVersion struct { + Major uint16 + Minor uint16 +} + +type BpfStat struct { + Recv uint32 + Drop uint32 +} + +type BpfProgram struct { + Len uint32 + Insns *BpfInsn +} + +type BpfInsn struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} + +type BpfHdr struct { + Tstamp BpfTimeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + Ifidx uint16 + Flowid uint16 + Flags uint8 + Drops uint8 +} + +type BpfTimeval struct { + Sec uint32 + Usec uint32 +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]uint8 + Ispeed int32 + Ospeed int32 +} + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +const ( + AT_FDCWD = -0x64 + AT_EACCESS = 0x1 + AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 +) + +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLERR = 0x8 + POLLHUP = 0x10 + POLLIN = 0x1 + POLLNVAL = 0x20 + POLLOUT = 0x4 + POLLPRI = 0x2 + POLLRDBAND = 0x80 + POLLRDNORM = 0x40 + POLLWRBAND = 0x100 + POLLWRNORM = 0x4 +) + +type Sigset_t uint32 + +type Utsname struct { + Sysname [256]byte + Nodename [256]byte + Release [256]byte + Version [256]byte + Machine [256]byte +} + +const SizeofUvmexp = 0x158 + +type Uvmexp struct { + Pagesize int32 + Pagemask int32 + Pageshift int32 + Npages int32 + Free int32 + Active int32 + Inactive int32 + Paging int32 + Wired int32 + Zeropages int32 + Reserve_pagedaemon int32 + Reserve_kernel int32 + Unused01 int32 + Vnodepages int32 + Vtextpages int32 + Freemin int32 + Freetarg int32 + Inactarg int32 + Wiredmax int32 + Anonmin int32 + Vtextmin int32 + Vnodemin int32 + Anonminpct int32 + Vtextminpct int32 + Vnodeminpct int32 + Nswapdev int32 + Swpages int32 + Swpginuse int32 + Swpgonly int32 + Nswget int32 + Nanon int32 + Unused05 int32 + Unused06 int32 + Faults int32 + Traps int32 + Intrs int32 + Swtch int32 + Softs int32 + Syscalls int32 + Pageins int32 + Unused07 int32 + Unused08 int32 + Pgswapin int32 + Pgswapout int32 + Forks int32 + Forks_ppwait int32 + Forks_sharevm int32 + Pga_zerohit int32 + Pga_zeromiss int32 + Unused09 int32 + Fltnoram int32 + Fltnoanon int32 + Fltnoamap int32 + Fltpgwait int32 + Fltpgrele int32 + Fltrelck int32 + Fltrelckok int32 + Fltanget int32 + Fltanretry int32 + Fltamcopy int32 + Fltnamap int32 + Fltnomap int32 + Fltlget int32 + Fltget int32 + Flt_anon int32 + Flt_acow int32 + Flt_obj int32 + Flt_prcopy int32 + Flt_przero int32 + Pdwoke int32 + Pdrevs int32 + Pdswout int32 + Pdfreed int32 + Pdscans int32 + Pdanscan int32 + Pdobscan int32 + Pdreact int32 + Pdbusy int32 + Pdpageouts int32 + Pdpending int32 + Pddeact int32 + Unused11 int32 + Unused12 int32 + Unused13 int32 + Fpswtch int32 + Kmapent int32 +} + +const SizeofClockinfo = 0x10 + +type Clockinfo struct { + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index 23ed9fe..1416057 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -1,7 +1,7 @@ // cgo -godefs types_solaris.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. -// +build amd64,solaris +//go:build amd64 && solaris package unix @@ -88,7 +88,6 @@ type Stat_t struct { Mtim Timespec Ctim Timespec Blksize int32 - _ [4]byte Blocks int64 Fstype [16]int8 } @@ -96,7 +95,6 @@ type Stat_t struct { type Flock_t struct { Type int16 Whence int16 - _ [4]byte Start int64 Len int64 Sysid int32 @@ -138,12 +136,12 @@ type RawSockaddrInet4 struct { } type RawSockaddrInet6 struct { - Family uint16 - Port uint16 - Flowinfo uint32 - Addr [16]byte /* in6_addr */ - Scope_id uint32 - X__sin6_src_id uint32 + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 + _ uint32 } type RawSockaddrUnix struct { @@ -179,7 +177,7 @@ type Linger struct { } type Iovec struct { - Base *int8 + Base *byte Len uint64 } @@ -196,10 +194,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Accrights *int8 Accrightslen int32 _ [4]byte @@ -228,7 +224,7 @@ type IPv6MTUInfo struct { } type ICMPv6Filter struct { - X__icmp6_filt [8]uint32 + Filt [8]uint32 } const ( @@ -238,6 +234,7 @@ const ( SizeofSockaddrUnix = 0x6e SizeofSockaddrDatalink = 0xfc SizeofLinger = 0x8 + SizeofIovec = 0x10 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 @@ -291,7 +288,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -299,7 +295,6 @@ type IfData struct { Type uint8 Addrlen uint8 Hdrlen uint8 - _ [1]byte Mtu uint32 Metric uint32 Baudrate uint32 @@ -324,7 +319,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -333,7 +327,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -371,15 +364,14 @@ type BpfVersion struct { } type BpfStat struct { - Recv uint64 - Drop uint64 - Capt uint64 - Padding [13]uint64 + Recv uint64 + Drop uint64 + Capt uint64 + _ [13]uint64 } type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -447,3 +439,78 @@ const ( POLLWRBAND = 0x100 POLLWRNORM = 0x4 ) + +type fileObj struct { + Atim Timespec + Mtim Timespec + Ctim Timespec + Pad [3]uint64 + Name *int8 +} + +type portEvent struct { + Events int32 + Source uint16 + Pad uint16 + Object uint64 + User *byte +} + +const ( + PORT_SOURCE_AIO = 0x1 + PORT_SOURCE_TIMER = 0x2 + PORT_SOURCE_USER = 0x3 + PORT_SOURCE_FD = 0x4 + PORT_SOURCE_ALERT = 0x5 + PORT_SOURCE_MQ = 0x6 + PORT_SOURCE_FILE = 0x7 + PORT_ALERT_SET = 0x1 + PORT_ALERT_UPDATE = 0x2 + PORT_ALERT_INVALID = 0x3 + FILE_ACCESS = 0x1 + FILE_MODIFIED = 0x2 + FILE_ATTRIB = 0x4 + FILE_TRUNC = 0x100000 + FILE_NOFOLLOW = 0x10000000 + FILE_DELETE = 0x10 + FILE_RENAME_TO = 0x20 + FILE_RENAME_FROM = 0x40 + UNMOUNTED = 0x20000000 + MOUNTEDOVER = 0x40000000 + FILE_EXCEPTION = 0x60000070 +) + +const ( + TUNNEWPPA = 0x540001 + TUNSETPPA = 0x540002 + + I_STR = 0x5308 + I_POP = 0x5303 + I_PUSH = 0x5302 + I_LINK = 0x530c + I_UNLINK = 0x530d + I_PLINK = 0x5316 + I_PUNLINK = 0x5317 + + IF_UNITSEL = -0x7ffb8cca +) + +type strbuf struct { + Maxlen int32 + Len int32 + Buf *int8 +} + +type Strioctl struct { + Cmd int32 + Timout int32 + Len int32 + Dp *int8 +} + +type Lifreq struct { + Name [32]int8 + Lifru1 [4]byte + Type uint32 + Lifru [336]byte +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go new file mode 100644 index 0000000..2e5d5a4 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go @@ -0,0 +1,552 @@ +// 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 + +// Hand edited based on ztypes_linux_s390x.go +// TODO: auto-generate. + +package unix + +const ( + SizeofPtr = 0x8 + SizeofShort = 0x2 + SizeofInt = 0x4 + SizeofLong = 0x8 + SizeofLongLong = 0x8 + PathMax = 0x1000 +) + +const ( + SizeofSockaddrAny = 128 + SizeofCmsghdr = 12 + SizeofIPMreq = 8 + SizeofIPv6Mreq = 20 + SizeofICMPv6Filter = 32 + SizeofIPv6MTUInfo = 32 + SizeofInet4Pktinfo = 8 + SizeofInet6Pktinfo = 20 + SizeofLinger = 8 + SizeofSockaddrInet4 = 16 + SizeofSockaddrInet6 = 28 + SizeofTCPInfo = 0x68 + SizeofUcred = 12 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int64 +} + +type timeval_zos struct { //correct (with padding and all) + Sec int64 + _ [4]byte // pad + Usec int32 +} + +type Tms struct { //clock_t is 4-byte unsigned int in zos + Utime uint32 + Stime uint32 + Cutime uint32 + Cstime uint32 +} + +type Time_t int64 + +type Utimbuf struct { + Actime int64 + Modtime int64 +} + +type Utsname struct { + Sysname [16]byte + Nodename [32]byte + Release [8]byte + Version [8]byte + Machine [16]byte +} + +type Ucred struct { + Pid int32 + Uid uint32 + Gid uint32 +} + +type RawSockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]uint8 +} + +type RawSockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddrUnix struct { + Len uint8 + Family uint8 + Path [108]int8 +} + +type RawSockaddr struct { + Len uint8 + Family uint8 + Data [14]uint8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + _ [112]uint8 // pad +} + +type _Socklen uint32 + +type Linger struct { + Onoff int32 + Linger int32 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type Msghdr struct { + Name *byte + Iov *Iovec + Control *byte + Flags int32 + Namelen int32 + Iovlen int32 + Controllen int32 +} + +type Cmsghdr struct { + Len int32 + Level int32 + Type int32 +} + +type Inet4Pktinfo struct { + Addr [4]byte /* in_addr */ + Ifindex uint32 +} + +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type IPv6MTUInfo struct { + Addr RawSockaddrInet6 + Mtu uint32 +} + +type ICMPv6Filter struct { + Data [8]uint32 +} + +type TCPInfo struct { + State uint8 + Ca_state uint8 + Retransmits uint8 + Probes uint8 + Backoff uint8 + Options uint8 + Rto uint32 + Ato uint32 + Snd_mss uint32 + Rcv_mss uint32 + Unacked uint32 + Sacked uint32 + Lost uint32 + Retrans uint32 + Fackets uint32 + Last_data_sent uint32 + Last_ack_sent uint32 + Last_data_recv uint32 + Last_ack_recv uint32 + Pmtu uint32 + Rcv_ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Advmss uint32 + Reordering uint32 + Rcv_rtt uint32 + Rcv_space uint32 + Total_retrans uint32 +} + +type _Gid_t uint32 + +type rusage_zos struct { + Utime timeval_zos + Stime timeval_zos +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Rlimit struct { + Cur uint64 + Max uint64 +} + +// { int, short, short } in poll.h +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +type Stat_t struct { //Linux Definition + Dev uint64 + Ino uint64 + Nlink uint64 + Mode uint32 + Uid uint32 + Gid uint32 + _ int32 + Rdev uint64 + Size int64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Blksize int64 + Blocks int64 + _ [3]int64 +} + +type Stat_LE_t struct { + _ [4]byte // eye catcher + Length uint16 + Version uint16 + Mode int32 + Ino uint32 + Dev uint32 + Nlink int32 + Uid int32 + Gid int32 + Size int64 + Atim31 [4]byte + Mtim31 [4]byte + Ctim31 [4]byte + Rdev uint32 + Auditoraudit uint32 + Useraudit uint32 + Blksize int32 + Creatim31 [4]byte + AuditID [16]byte + _ [4]byte // rsrvd1 + File_tag struct { + Ccsid uint16 + Txtflag uint16 // aggregating Txflag:1 deferred:1 rsvflags:14 + } + CharsetID [8]byte + Blocks int64 + Genvalue uint32 + Reftim31 [4]byte + Fid [8]byte + Filefmt byte + Fspflag2 byte + _ [2]byte // rsrvd2 + Ctimemsec int32 + Seclabel [8]byte + _ [4]byte // rsrvd3 + _ [4]byte // rsrvd4 + Atim Time_t + Mtim Time_t + Ctim Time_t + Creatim Time_t + Reftim Time_t + _ [24]byte // rsrvd5 +} + +type Statvfs_t struct { + ID [4]byte + Len int32 + Bsize uint64 + Blocks uint64 + Usedspace uint64 + Bavail uint64 + Flag uint64 + Maxfilesize int64 + _ [16]byte + Frsize uint64 + Bfree uint64 + Files uint32 + Ffree uint32 + Favail uint32 + Namemax31 uint32 + Invarsec uint32 + _ [4]byte + Fsid uint64 + Namemax uint64 +} + +type Statfs_t struct { + Type uint64 + Bsize uint64 + Blocks uint64 + Bfree uint64 + Bavail uint64 + Files uint32 + Ffree uint32 + Fsid uint64 + Namelen uint64 + Frsize uint64 + Flags uint64 + _ [4]uint64 +} + +type direntLE struct { + Reclen uint16 + Namlen uint16 + Ino uint32 + Extra uintptr + Name [256]byte +} + +type Dirent struct { + Ino uint64 + Off int64 + Reclen uint16 + Type uint8 + Name [256]uint8 + _ [5]byte +} + +type FdSet struct { + Bits [64]int32 +} + +// This struct is packed on z/OS so it can't be used directly. +type Flock_t struct { + Type int16 + Whence int16 + Start int64 + Len int64 + Pid int32 +} + +type F_cnvrt struct { + Cvtcmd int32 + Pccsid int16 + Fccsid int16 +} + +type Termios struct { + Cflag uint32 + Iflag uint32 + Lflag uint32 + Oflag uint32 + Cc [11]uint8 +} + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +type W_Mnth struct { + Hid [4]byte + Size int32 + Cur1 int32 //32bit pointer + Cur2 int32 //^ + Devno uint32 + _ [4]byte +} + +type W_Mntent struct { + Fstype uint32 + Mode uint32 + Dev uint32 + Parentdev uint32 + Rootino uint32 + Status byte + Ddname [9]byte + Fstname [9]byte + Fsname [45]byte + Pathlen uint32 + Mountpoint [1024]byte + Jobname [8]byte + PID int32 + Parmoffset int32 + Parmlen int16 + Owner [8]byte + Quiesceowner [8]byte + _ [38]byte +} + +type EpollEvent struct { + Events uint32 + _ int32 + Fd int32 + Pad int32 +} + +type InotifyEvent struct { + Wd int32 + Mask uint32 + Cookie uint32 + Len uint32 + Name string +} + +const ( + SizeofInotifyEvent = 0x10 +) + +type ConsMsg2 struct { + Cm2Format uint16 + Cm2R1 uint16 + Cm2Msglength uint32 + Cm2Msg *byte + Cm2R2 [4]byte + Cm2R3 [4]byte + Cm2Routcde *uint32 + Cm2Descr *uint32 + Cm2Msgflag uint32 + Cm2Token uint32 + Cm2Msgid *uint32 + Cm2R4 [4]byte + Cm2DomToken uint32 + Cm2DomMsgid *uint32 + Cm2ModCartptr *byte + Cm2ModConsidptr *byte + Cm2MsgCart [8]byte + Cm2MsgConsid [4]byte + Cm2R5 [12]byte +} + +const ( + CC_modify = 1 + CC_stop = 2 + CONSOLE_FORMAT_2 = 2 + CONSOLE_FORMAT_3 = 3 + CONSOLE_HRDCPY = 0x80000000 +) + +type OpenHow struct { + Flags uint64 + Mode uint64 + Resolve uint64 +} + +const SizeofOpenHow = 0x18 + +const ( + RESOLVE_CACHED = 0x20 + RESOLVE_BENEATH = 0x8 + RESOLVE_IN_ROOT = 0x10 + RESOLVE_NO_MAGICLINKS = 0x2 + RESOLVE_NO_SYMLINKS = 0x4 + RESOLVE_NO_XDEV = 0x1 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + _ [44]byte +} + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode int32 +} + +type SysvShmDesc struct { + Perm SysvIpcPerm + _ [4]byte + Lpid int32 + Cpid int32 + Nattch uint32 + _ [4]byte + _ [4]byte + _ [4]byte + _ int32 + _ uint8 + _ uint8 + _ uint16 + _ *byte + Segsz uint64 + Atime Time_t + Dtime Time_t + Ctime Time_t +} + +type SysvShmDesc64 struct { + Perm SysvIpcPerm + _ [4]byte + Lpid int32 + Cpid int32 + Nattch uint32 + _ [4]byte + _ [4]byte + _ [4]byte + _ int32 + _ byte + _ uint8 + _ uint16 + _ *byte + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 +} diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go index af3af60..16f9056 100644 --- a/vendor/golang.org/x/sys/windows/aliases.go +++ b/vendor/golang.org/x/sys/windows/aliases.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows -// +build go1.9 +//go:build windows package windows diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go index d777113..3ca814f 100644 --- a/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -32,6 +32,8 @@ type DLLError struct { func (e *DLLError) Error() string { return e.Msg } +func (e *DLLError) Unwrap() error { return e.Err } + // A DLL implements access to a single DLL. type DLL struct { Name string @@ -41,8 +43,8 @@ type DLL struct { // LoadDLL loads DLL file into memory. // // Warning: using LoadDLL without an absolute path name is subject to -// DLL preloading attacks. To safely load a system DLL, use LazyDLL -// with System set to true, or use LoadLibraryEx directly. +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL], +// or use [LoadLibraryEx] directly. func LoadDLL(name string) (dll *DLL, err error) { namep, err := UTF16PtrFromString(name) if err != nil { @@ -63,7 +65,7 @@ func LoadDLL(name string) (dll *DLL, err error) { return d, nil } -// MustLoadDLL is like LoadDLL but panics if load operation failes. +// MustLoadDLL is like LoadDLL but panics if load operation fails. func MustLoadDLL(name string) *DLL { d, e := LoadDLL(name) if e != nil { @@ -104,6 +106,35 @@ func (d *DLL) MustFindProc(name string) *Proc { return p } +// FindProcByOrdinal searches DLL d for procedure by ordinal and returns *Proc +// if found. It returns an error if search fails. +func (d *DLL) FindProcByOrdinal(ordinal uintptr) (proc *Proc, err error) { + a, e := GetProcAddressByOrdinal(d.Handle, ordinal) + name := "#" + itoa(int(ordinal)) + if e != nil { + return nil, &DLLError{ + Err: e, + ObjName: name, + Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(), + } + } + p := &Proc{ + Dll: d, + Name: name, + addr: a, + } + return p, nil +} + +// MustFindProcByOrdinal is like FindProcByOrdinal but panics if search fails. +func (d *DLL) MustFindProcByOrdinal(ordinal uintptr) *Proc { + p, e := d.FindProcByOrdinal(ordinal) + if e != nil { + panic(e) + } + return p +} + // Release unloads DLL d from memory. func (d *DLL) Release() (err error) { return FreeLibrary(d.Handle) @@ -240,6 +271,9 @@ func (d *LazyDLL) NewProc(name string) *LazyProc { } // NewLazyDLL creates new LazyDLL associated with DLL file. +// +// Warning: using NewLazyDLL without an absolute path name is subject to +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL]. func NewLazyDLL(name string) *LazyDLL { return &LazyDLL{Name: name} } @@ -360,7 +394,6 @@ func loadLibraryEx(name string, system bool) (*DLL, error) { var flags uintptr if system { if canDoSearchSystem32() { - const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 flags = LOAD_LIBRARY_SEARCH_SYSTEM32 } else if isBaseName(name) { // WindowsXP or unpatched Windows machine @@ -380,7 +413,3 @@ func loadLibraryEx(name string, system bool) (*DLL, error) { } return &DLL{Name: name, Handle: h}, nil } - -type errString string - -func (s errString) Error() string { return string(s) } diff --git a/vendor/golang.org/x/sys/windows/empty.s b/vendor/golang.org/x/sys/windows/empty.s deleted file mode 100644 index 69309e4..0000000 --- a/vendor/golang.org/x/sys/windows/empty.s +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.12 - -// This file is here to allow bodyless functions with go:linkname for Go 1.11 -// and earlier (see https://golang.org/issue/23311). diff --git a/vendor/golang.org/x/sys/windows/env_windows.go b/vendor/golang.org/x/sys/windows/env_windows.go index f482a9f..d4577a4 100644 --- a/vendor/golang.org/x/sys/windows/env_windows.go +++ b/vendor/golang.org/x/sys/windows/env_windows.go @@ -8,7 +8,6 @@ package windows import ( "syscall" - "unicode/utf16" "unsafe" ) @@ -38,20 +37,17 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) { return nil, err } defer DestroyEnvironmentBlock(block) - blockp := uintptr(unsafe.Pointer(block)) - for { - entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:] - for i, v := range entry { - if v == 0 { - entry = entry[:i] - break - } + size := unsafe.Sizeof(*block) + for *block != 0 { + // find NUL terminator + end := unsafe.Pointer(block) + for *(*uint16)(end) != 0 { + end = unsafe.Add(end, size) } - if len(entry) == 0 { - break - } - env = append(env, string(utf16.Decode(entry))) - blockp += 2 * (uintptr(len(entry)) + 1) + + entry := unsafe.Slice(block, (uintptr(end)-uintptr(unsafe.Pointer(block)))/size) + env = append(env, UTF16ToString(entry)) + block = (*uint16)(unsafe.Add(end, size)) } return env, nil } diff --git a/vendor/golang.org/x/sys/windows/eventlog.go b/vendor/golang.org/x/sys/windows/eventlog.go index 40af946..6c36695 100644 --- a/vendor/golang.org/x/sys/windows/eventlog.go +++ b/vendor/golang.org/x/sys/windows/eventlog.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package windows diff --git a/vendor/golang.org/x/sys/windows/exec_windows.go b/vendor/golang.org/x/sys/windows/exec_windows.go index 3606c3a..9cabbb6 100644 --- a/vendor/golang.org/x/sys/windows/exec_windows.go +++ b/vendor/golang.org/x/sys/windows/exec_windows.go @@ -6,18 +6,23 @@ package windows +import ( + errorspkg "errors" + "unsafe" +) + // EscapeArg rewrites command line argument s as prescribed // in http://msdn.microsoft.com/en-us/library/ms880421. // This function returns "" (2 double quotes) if s is empty. // Alternatively, these transformations are done: -// - every back slash (\) is doubled, but only if immediately -// followed by double quote ("); -// - every double quote (") is escaped by back slash (\); -// - finally, s is wrapped with double quotes (arg -> "arg"), -// but only if there is space or tab inside s. +// - every back slash (\) is doubled, but only if immediately +// followed by double quote ("); +// - every double quote (") is escaped by back slash (\); +// - finally, s is wrapped with double quotes (arg -> "arg"), +// but only if there is space or tab inside s. func EscapeArg(s string) string { if len(s) == 0 { - return "\"\"" + return `""` } n := len(s) hasSpace := false @@ -30,7 +35,7 @@ func EscapeArg(s string) string { } } if hasSpace { - n += 2 + n += 2 // Reserve space for quotes. } if n == len(s) { return s @@ -73,6 +78,110 @@ func EscapeArg(s string) string { return string(qs[:j]) } +// ComposeCommandLine escapes and joins the given arguments suitable for use as a Windows command line, +// in CreateProcess's CommandLine argument, CreateService/ChangeServiceConfig's BinaryPathName argument, +// or any program that uses CommandLineToArgv. +func ComposeCommandLine(args []string) string { + if len(args) == 0 { + return "" + } + + // Per https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw: + // “This function accepts command lines that contain a program name; the + // program name can be enclosed in quotation marks or not.” + // + // Unfortunately, it provides no means of escaping interior quotation marks + // within that program name, and we have no way to report them here. + prog := args[0] + mustQuote := len(prog) == 0 + for i := 0; i < len(prog); i++ { + c := prog[i] + if c <= ' ' || (c == '"' && i == 0) { + // Force quotes for not only the ASCII space and tab as described in the + // MSDN article, but also ASCII control characters. + // The documentation for CommandLineToArgvW doesn't say what happens when + // the first argument is not a valid program name, but it empirically + // seems to drop unquoted control characters. + mustQuote = true + break + } + } + var commandLine []byte + if mustQuote { + commandLine = make([]byte, 0, len(prog)+2) + commandLine = append(commandLine, '"') + for i := 0; i < len(prog); i++ { + c := prog[i] + if c == '"' { + // This quote would interfere with our surrounding quotes. + // We have no way to report an error, so just strip out + // the offending character instead. + continue + } + commandLine = append(commandLine, c) + } + commandLine = append(commandLine, '"') + } else { + if len(args) == 1 { + // args[0] is a valid command line representing itself. + // No need to allocate a new slice or string for it. + return prog + } + commandLine = []byte(prog) + } + + for _, arg := range args[1:] { + commandLine = append(commandLine, ' ') + // TODO(bcmills): since we're already appending to a slice, it would be nice + // to avoid the intermediate allocations of EscapeArg. + // Perhaps we can factor out an appendEscapedArg function. + commandLine = append(commandLine, EscapeArg(arg)...) + } + return string(commandLine) +} + +// DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv, +// as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that +// command lines are passed around. +// DecomposeCommandLine returns an error if commandLine contains NUL. +func DecomposeCommandLine(commandLine string) ([]string, error) { + if len(commandLine) == 0 { + return []string{}, nil + } + utf16CommandLine, err := UTF16FromString(commandLine) + if err != nil { + return nil, errorspkg.New("string with NUL passed to DecomposeCommandLine") + } + var argc int32 + argv, err := commandLineToArgv(&utf16CommandLine[0], &argc) + if err != nil { + return nil, err + } + defer LocalFree(Handle(unsafe.Pointer(argv))) + + var args []string + for _, p := range unsafe.Slice(argv, argc) { + args = append(args, UTF16PtrToString(p)) + } + return args, nil +} + +// CommandLineToArgv parses a Unicode command line string and sets +// argc to the number of parsed arguments. +// +// The returned memory should be freed using a single call to LocalFree. +// +// Note that although the return type of CommandLineToArgv indicates 8192 +// entries of up to 8192 characters each, the actual count of parsed arguments +// may exceed 8192, and the documentation for CommandLineToArgvW does not mention +// any bound on the lengths of the individual argument strings. +// (See https://go.dev/issue/63236.) +func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { + argp, err := commandLineToArgv(cmd, argc) + argv = (*[8192]*[8192]uint16)(unsafe.Pointer(argp)) + return argv, err +} + func CloseOnExec(fd Handle) { SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0) } @@ -95,3 +204,45 @@ func FullPath(name string) (path string, err error) { } } } + +// NewProcThreadAttributeList allocates a new ProcThreadAttributeListContainer, with the requested maximum number of attributes. +func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) { + var size uintptr + err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size) + if err != ERROR_INSUFFICIENT_BUFFER { + if err == nil { + return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList") + } + return nil, err + } + alloc, err := LocalAlloc(LMEM_FIXED, uint32(size)) + if err != nil { + return nil, err + } + // size is guaranteed to be ≥1 by InitializeProcThreadAttributeList. + al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(alloc))} + err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size) + if err != nil { + return nil, err + } + return al, err +} + +// Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute. +func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error { + al.pointers = append(al.pointers, value) + return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil) +} + +// Delete frees ProcThreadAttributeList's resources. +func (al *ProcThreadAttributeListContainer) Delete() { + deleteProcThreadAttributeList(al.data) + LocalFree(Handle(unsafe.Pointer(al.data))) + al.data = nil + al.pointers = nil +} + +// List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx. +func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList { + return al.data +} diff --git a/vendor/golang.org/x/sys/windows/memory_windows.go b/vendor/golang.org/x/sys/windows/memory_windows.go index f80a420..6dc0920 100644 --- a/vendor/golang.org/x/sys/windows/memory_windows.go +++ b/vendor/golang.org/x/sys/windows/memory_windows.go @@ -16,11 +16,33 @@ const ( MEM_RESET_UNDO = 0x01000000 MEM_LARGE_PAGES = 0x20000000 - PAGE_NOACCESS = 0x01 - PAGE_READONLY = 0x02 - PAGE_READWRITE = 0x04 - PAGE_WRITECOPY = 0x08 - PAGE_EXECUTE_READ = 0x20 - PAGE_EXECUTE_READWRITE = 0x40 - PAGE_EXECUTE_WRITECOPY = 0x80 + PAGE_NOACCESS = 0x00000001 + PAGE_READONLY = 0x00000002 + PAGE_READWRITE = 0x00000004 + PAGE_WRITECOPY = 0x00000008 + PAGE_EXECUTE = 0x00000010 + PAGE_EXECUTE_READ = 0x00000020 + PAGE_EXECUTE_READWRITE = 0x00000040 + PAGE_EXECUTE_WRITECOPY = 0x00000080 + PAGE_GUARD = 0x00000100 + PAGE_NOCACHE = 0x00000200 + PAGE_WRITECOMBINE = 0x00000400 + PAGE_TARGETS_INVALID = 0x40000000 + PAGE_TARGETS_NO_UPDATE = 0x40000000 + + QUOTA_LIMITS_HARDWS_MIN_DISABLE = 0x00000002 + QUOTA_LIMITS_HARDWS_MIN_ENABLE = 0x00000001 + QUOTA_LIMITS_HARDWS_MAX_DISABLE = 0x00000008 + QUOTA_LIMITS_HARDWS_MAX_ENABLE = 0x00000004 ) + +type MemoryBasicInformation struct { + BaseAddress uintptr + AllocationBase uintptr + AllocationProtect uint32 + PartitionId uint16 + RegionSize uintptr + State uint32 + Protect uint32 + Type uint32 +} diff --git a/vendor/golang.org/x/sys/windows/mkerrors.bash b/vendor/golang.org/x/sys/windows/mkerrors.bash index 2163843..58e0188 100644 --- a/vendor/golang.org/x/sys/windows/mkerrors.bash +++ b/vendor/golang.org/x/sys/windows/mkerrors.bash @@ -9,6 +9,8 @@ shopt -s nullglob winerror="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/winerror.h | sort -Vr | head -n 1)" [[ -n $winerror ]] || { echo "Unable to find winerror.h" >&2; exit 1; } +ntstatus="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/ntstatus.h | sort -Vr | head -n 1)" +[[ -n $ntstatus ]] || { echo "Unable to find ntstatus.h" >&2; exit 1; } declare -A errors @@ -59,5 +61,10 @@ declare -A errors echo "$key $vtype = $value" done < "$winerror" + while read -r line; do + [[ $line =~ ^#define\ (STATUS_[^\s]+)\ +\(\(NTSTATUS\)((0x)?[0-9a-fA-F]+)L?\) ]] || continue + echo "${BASH_REMATCH[1]} NTStatus = ${BASH_REMATCH[2]}" + done < "$ntstatus" + echo ")" } | gofmt > "zerrors_windows.go" diff --git a/vendor/golang.org/x/sys/windows/mksyscall.go b/vendor/golang.org/x/sys/windows/mksyscall.go index 328e3b2..dbcdb09 100644 --- a/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/vendor/golang.org/x/sys/windows/mksyscall.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build generate +//go:build generate package windows -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go setupapi_windows.go diff --git a/vendor/golang.org/x/sys/windows/race.go b/vendor/golang.org/x/sys/windows/race.go index a74e3e2..0f1bdc3 100644 --- a/vendor/golang.org/x/sys/windows/race.go +++ b/vendor/golang.org/x/sys/windows/race.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows,race +//go:build windows && race package windows diff --git a/vendor/golang.org/x/sys/windows/race0.go b/vendor/golang.org/x/sys/windows/race0.go index e44a3cb..0c78da7 100644 --- a/vendor/golang.org/x/sys/windows/race0.go +++ b/vendor/golang.org/x/sys/windows/race0.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows,!race +//go:build windows && !race package windows diff --git a/vendor/golang.org/x/sys/windows/registry/key.go b/vendor/golang.org/x/sys/windows/registry/key.go index c256483..39aeeb6 100644 --- a/vendor/golang.org/x/sys/windows/registry/key.go +++ b/vendor/golang.org/x/sys/windows/registry/key.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows // Package registry provides access to the Windows registry. // @@ -19,11 +19,11 @@ // log.Fatal(err) // } // fmt.Printf("Windows system root is %q\n", s) -// package registry import ( "io" + "runtime" "syscall" "time" ) @@ -113,6 +113,13 @@ func OpenRemoteKey(pcname string, k Key) (Key, error) { // The parameter n controls the number of returned names, // analogous to the way os.File.Readdirnames works. func (k Key) ReadSubKeyNames(n int) ([]string, error) { + // RegEnumKeyEx must be called repeatedly and to completion. + // During this time, this goroutine cannot migrate away from + // its current thread. See https://golang.org/issue/49320 and + // https://golang.org/issue/49466. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + names := make([]string, 0) // Registry key size limit is 255 bytes and described there: // https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx @@ -157,7 +164,12 @@ loopItems: func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool, err error) { var h syscall.Handle var d uint32 - err = regCreateKeyEx(syscall.Handle(k), syscall.StringToUTF16Ptr(path), + var pathPointer *uint16 + pathPointer, err = syscall.UTF16PtrFromString(path) + if err != nil { + return 0, false, err + } + err = regCreateKeyEx(syscall.Handle(k), pathPointer, 0, nil, _REG_OPTION_NON_VOLATILE, access, nil, &h, &d) if err != nil { return 0, false, err @@ -167,7 +179,11 @@ func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool // DeleteKey deletes the subkey path of key k and its values. func DeleteKey(k Key, path string) error { - return regDeleteKey(syscall.Handle(k), syscall.StringToUTF16Ptr(path)) + pathPointer, err := syscall.UTF16PtrFromString(path) + if err != nil { + return err + } + return regDeleteKey(syscall.Handle(k), pathPointer) } // A KeyInfo describes the statistics of a key. It is returned by Stat. diff --git a/vendor/golang.org/x/sys/windows/registry/mksyscall.go b/vendor/golang.org/x/sys/windows/registry/mksyscall.go index 50c32a3..bbf86cc 100644 --- a/vendor/golang.org/x/sys/windows/registry/mksyscall.go +++ b/vendor/golang.org/x/sys/windows/registry/mksyscall.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build generate +//go:build generate package registry diff --git a/vendor/golang.org/x/sys/windows/registry/syscall.go b/vendor/golang.org/x/sys/windows/registry/syscall.go index e66643c..f533091 100644 --- a/vendor/golang.org/x/sys/windows/registry/syscall.go +++ b/vendor/golang.org/x/sys/windows/registry/syscall.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package registry diff --git a/vendor/golang.org/x/sys/windows/registry/value.go b/vendor/golang.org/x/sys/windows/registry/value.go index f25e7e9..a1bcbb2 100644 --- a/vendor/golang.org/x/sys/windows/registry/value.go +++ b/vendor/golang.org/x/sys/windows/registry/value.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package registry @@ -340,7 +340,11 @@ func (k Key) SetBinaryValue(name string, value []byte) error { // DeleteValue removes a named value from the key k. func (k Key) DeleteValue(name string) error { - return regDeleteValue(syscall.Handle(k), syscall.StringToUTF16Ptr(name)) + namePointer, err := syscall.UTF16PtrFromString(name) + if err != nil { + return err + } + return regDeleteValue(syscall.Handle(k), namePointer) } // ReadValueNames returns the value names of key k. diff --git a/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go index 3778075..bc1ce43 100644 --- a/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go @@ -19,6 +19,7 @@ const ( var ( errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL ) // errnoErr returns common boxed Errno values, to prevent @@ -26,7 +27,7 @@ var ( func errnoErr(e syscall.Errno) error { switch e { case 0: - return nil + return errERROR_EINVAL case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } @@ -40,50 +41,50 @@ var ( modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW") procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW") procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW") - procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW") - procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW") + procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW") - procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW") + procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW") procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW") ) -func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition))) +func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) { + r0, _, _ := syscall.SyscallN(procRegConnectRegistryW.Addr(), uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result))) if r0 != 0 { regerrno = syscall.Errno(r0) } return } -func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) { - r0, _, _ := syscall.Syscall(procRegDeleteKeyW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(subkey)), 0) +func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) { + r0, _, _ := syscall.SyscallN(procRegCreateKeyExW.Addr(), uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition))) if r0 != 0 { regerrno = syscall.Errno(r0) } return } -func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize)) +func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) { + r0, _, _ := syscall.SyscallN(procRegDeleteKeyW.Addr(), uintptr(key), uintptr(unsafe.Pointer(subkey))) if r0 != 0 { regerrno = syscall.Errno(r0) } return } -func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)), 0) +func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) { + r0, _, _ := syscall.SyscallN(procRegDeleteValueW.Addr(), uintptr(key), uintptr(unsafe.Pointer(name))) if r0 != 0 { regerrno = syscall.Errno(r0) } return } -func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) { - r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0) +func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { + r0, _, _ := syscall.SyscallN(procRegEnumValueW.Addr(), uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -91,15 +92,15 @@ func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) { } func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0) + r0, _, _ := syscall.SyscallN(procRegLoadMUIStringW.Addr(), uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir))) if r0 != 0 { regerrno = syscall.Errno(r0) } return } -func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) { - r0, _, _ := syscall.Syscall(procRegConnectRegistryW.Addr(), 3, uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result))) +func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) { + r0, _, _ := syscall.SyscallN(procRegSetValueExW.Addr(), uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize)) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -107,14 +108,10 @@ func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall } func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) + r0, _, e1 := syscall.SyscallN(procExpandEnvironmentStringsW.Addr(), uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) n = uint32(r0) if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index 4b6eff1..a8b0364 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -68,6 +68,7 @@ type UserInfo10 struct { //sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo //sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation //sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree +//sys NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum const ( // do not reorder @@ -622,6 +623,7 @@ func (tml *Tokenmandatorylabel) Size() uint32 { // Authorization Functions //sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership +//sys isTokenRestricted(tokenHandle Token) (ret bool, err error) [!failretval] = advapi32.IsTokenRestricted //sys OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken //sys OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken //sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf @@ -835,6 +837,16 @@ func (t Token) IsMember(sid *SID) (bool, error) { return b != 0, nil } +// IsRestricted reports whether the access token t is a restricted token. +func (t Token) IsRestricted() (isRestricted bool, err error) { + isRestricted, err = isTokenRestricted(t) + if !isRestricted && err == syscall.EINVAL { + // If err is EINVAL, this returned ERROR_SUCCESS indicating a non-restricted token. + err = nil + } + return +} + const ( WTS_CONSOLE_CONNECT = 0x1 WTS_CONSOLE_DISCONNECT = 0x2 @@ -876,12 +888,13 @@ type WTS_SESSION_INFO struct { //sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken //sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW //sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory +//sys WTSGetActiveConsoleSessionId() (sessionID uint32) type ACL struct { aclRevision byte sbz1 byte aclSize uint16 - aceCount uint16 + AceCount uint16 sbz2 uint16 } @@ -895,6 +908,19 @@ type SECURITY_DESCRIPTOR struct { dacl *ACL } +type SECURITY_QUALITY_OF_SERVICE struct { + Length uint32 + ImpersonationLevel uint32 + ContextTrackingMode byte + EffectiveOnly byte +} + +// Constants for the ContextTrackingMode field of SECURITY_QUALITY_OF_SERVICE. +const ( + SECURITY_STATIC_TRACKING = 0 + SECURITY_DYNAMIC_TRACKING = 1 +) + type SecurityAttributes struct { Length uint32 SecurityDescriptor *SECURITY_DESCRIPTOR @@ -1061,6 +1087,27 @@ type EXPLICIT_ACCESS struct { Trustee TRUSTEE } +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header +type ACE_HEADER struct { + AceType uint8 + AceFlags uint8 + AceSize uint16 +} + +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace +type ACCESS_ALLOWED_ACE struct { + Header ACE_HEADER + Mask ACCESS_MASK + SidStart uint32 +} + +const ( + // Constants for AceType + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header + ACCESS_ALLOWED_ACE_TYPE = 0 + ACCESS_DENIED_ACE_TYPE = 1 +) + // This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. type TrusteeValue uintptr @@ -1101,9 +1148,10 @@ type OBJECTS_AND_NAME struct { } //sys getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo -//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo +//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetSecurityInfo //sys getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW //sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW +//sys SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) = advapi32.SetKernelObjectSecurity //sys buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW //sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor @@ -1131,6 +1179,7 @@ type OBJECTS_AND_NAME struct { //sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD //sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW +//sys GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) = advapi32.GetAce // Control returns the security descriptor control bits. func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { @@ -1229,7 +1278,7 @@ func (sd *SECURITY_DESCRIPTOR) String() string { return "" } defer LocalFree(Handle(unsafe.Pointer(sddl))) - return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:]) + return UTF16PtrToString(sddl) } // ToAbsolute converts a self-relative security descriptor into an absolute one. @@ -1254,7 +1303,10 @@ func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DE return nil, err } if absoluteSDSize > 0 { - absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0])) + absoluteSD = new(SECURITY_DESCRIPTOR) + if unsafe.Sizeof(*absoluteSD) < uintptr(absoluteSDSize) { + panic("sizeof(SECURITY_DESCRIPTOR) too small") + } } var ( dacl *ACL @@ -1263,19 +1315,55 @@ func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DE group *SID ) if daclSize > 0 { - dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0])) + dacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, daclSize)))) } if saclSize > 0 { - sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0])) + sacl = (*ACL)(unsafe.Pointer(unsafe.SliceData(make([]byte, saclSize)))) } if ownerSize > 0 { - owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0])) + owner = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, ownerSize)))) } if groupSize > 0 { - group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0])) + group = (*SID)(unsafe.Pointer(unsafe.SliceData(make([]byte, groupSize)))) } + // We call into Windows via makeAbsoluteSD, which sets up + // pointers within absoluteSD that point to other chunks of memory + // we pass into makeAbsoluteSD, and that happens outside the view of the GC. + // We therefore take some care here to then verify the pointers are as we expect + // and set them explicitly in view of the GC. See https://go.dev/issue/73199. + // TODO: consider weak pointers once Go 1.24 is appropriate. See suggestion in https://go.dev/cl/663575. err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize, dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize) + if err != nil { + // Don't return absoluteSD, which might be partially initialized. + return nil, err + } + // Before using any fields, verify absoluteSD is in the format we expect according to Windows. + // See https://learn.microsoft.com/en-us/windows/win32/secauthz/absolute-and-self-relative-security-descriptors + absControl, _, err := absoluteSD.Control() + if err != nil { + panic("absoluteSD: " + err.Error()) + } + if absControl&SE_SELF_RELATIVE != 0 { + panic("absoluteSD not in absolute format") + } + if absoluteSD.dacl != dacl { + panic("dacl pointer mismatch") + } + if absoluteSD.sacl != sacl { + panic("sacl pointer mismatch") + } + if absoluteSD.owner != owner { + panic("owner pointer mismatch") + } + if absoluteSD.group != group { + panic("group pointer mismatch") + } + absoluteSD.dacl = dacl + absoluteSD.sacl = sacl + absoluteSD.owner = owner + absoluteSD.group = group + return } @@ -1307,9 +1395,22 @@ func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURIT } func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR { - sdBytes := make([]byte, selfRelativeSD.Length()) - copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)]) - return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0])) + sdLen := int(selfRelativeSD.Length()) + const min = int(unsafe.Sizeof(SECURITY_DESCRIPTOR{})) + if sdLen < min { + sdLen = min + } + + src := unsafe.Slice((*byte)(unsafe.Pointer(selfRelativeSD)), sdLen) + // SECURITY_DESCRIPTOR has pointers in it, which means checkptr expects for it to + // be aligned properly. When we're copying a Windows-allocated struct to a + // Go-allocated one, make sure that the Go allocation is aligned to the + // pointer size. + const psize = int(unsafe.Sizeof(uintptr(0))) + alloc := make([]uintptr, (sdLen+psize-1)/psize) + dst := unsafe.Slice((*byte)(unsafe.Pointer(&alloc[0])), sdLen) + copy(dst, src) + return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0])) } // SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a @@ -1391,6 +1492,6 @@ func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL } defer LocalFree(Handle(unsafe.Pointer(winHeapACL))) aclBytes := make([]byte, winHeapACL.aclSize) - copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)]) + copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes):len(aclBytes)]) return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil } diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index 847e00b..a9dc630 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package windows @@ -16,8 +16,6 @@ const ( SC_MANAGER_ALL_ACCESS = 0xf003f ) -//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW - const ( SERVICE_KERNEL_DRIVER = 1 SERVICE_FILE_SYSTEM_DRIVER = 2 @@ -65,6 +63,7 @@ const ( SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 32 SERVICE_ACCEPT_POWEREVENT = 64 SERVICE_ACCEPT_SESSIONCHANGE = 128 + SERVICE_ACCEPT_PRESHUTDOWN = 256 SERVICE_CONTROL_STOP = 1 SERVICE_CONTROL_PAUSE = 2 @@ -80,6 +79,7 @@ const ( SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12 SERVICE_CONTROL_POWEREVENT = 13 SERVICE_CONTROL_SESSIONCHANGE = 14 + SERVICE_CONTROL_PRESHUTDOWN = 15 SERVICE_ACTIVE = 1 SERVICE_INACTIVE = 2 @@ -126,8 +126,26 @@ const ( SERVICE_NOTIFY_CREATED = 0x00000080 SERVICE_NOTIFY_DELETED = 0x00000100 SERVICE_NOTIFY_DELETE_PENDING = 0x00000200 + + SC_EVENT_DATABASE_CHANGE = 0 + SC_EVENT_PROPERTY_CHANGE = 1 + SC_EVENT_STATUS_CHANGE = 2 + + SERVICE_START_REASON_DEMAND = 0x00000001 + SERVICE_START_REASON_AUTO = 0x00000002 + SERVICE_START_REASON_TRIGGER = 0x00000004 + SERVICE_START_REASON_RESTART_ON_FAILURE = 0x00000008 + SERVICE_START_REASON_DELAYEDAUTO = 0x00000010 + + SERVICE_DYNAMIC_INFORMATION_LEVEL_START_REASON = 1 ) +type ENUM_SERVICE_STATUS struct { + ServiceName *uint16 + DisplayName *uint16 + ServiceStatus SERVICE_STATUS +} + type SERVICE_STATUS struct { ServiceType uint32 CurrentState uint32 @@ -199,6 +217,10 @@ type SERVICE_FAILURE_ACTIONS struct { Actions *SC_ACTION } +type SERVICE_FAILURE_ACTIONS_FLAG struct { + FailureActionsOnNonCrashFailures int32 +} + type SC_ACTION struct { Type uint32 Delay uint32 @@ -210,6 +232,7 @@ type QUERY_SERVICE_LOCK_STATUS struct { LockDuration uint32 } +//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW //sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle //sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW //sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW @@ -227,3 +250,8 @@ type QUERY_SERVICE_LOCK_STATUS struct { //sys EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) = advapi32.EnumServicesStatusExW //sys QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) = advapi32.QueryServiceStatusEx //sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW +//sys SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) = sechost.SubscribeServiceChangeNotifications? +//sys UnsubscribeServiceChangeNotifications(subscription uintptr) = sechost.UnsubscribeServiceChangeNotifications? +//sys RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) = advapi32.RegisterServiceCtrlHandlerExW +//sys QueryServiceDynamicInformation(service Handle, infoLevel uint32, dynamicInfo unsafe.Pointer) (err error) = advapi32.QueryServiceDynamicInformation? +//sys EnumDependentServices(service Handle, activityState uint32, services *ENUM_SERVICE_STATUS, buffSize uint32, bytesNeeded *uint32, servicesReturned *uint32) (err error) = advapi32.EnumDependentServicesW diff --git a/vendor/golang.org/x/sys/windows/setupapi_windows.go b/vendor/golang.org/x/sys/windows/setupapi_windows.go new file mode 100644 index 0000000..f812648 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/setupapi_windows.go @@ -0,0 +1,1425 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package windows + +import ( + "encoding/binary" + "errors" + "fmt" + "runtime" + "strings" + "syscall" + "unsafe" +) + +// This file contains functions that wrap SetupAPI.dll and CfgMgr32.dll, +// core system functions for managing hardware devices, drivers, and the PnP tree. +// Information about these APIs can be found at: +// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi +// https://docs.microsoft.com/en-us/windows/win32/devinst/cfgmgr32- + +const ( + ERROR_EXPECTED_SECTION_NAME Errno = 0x20000000 | 0xC0000000 | 0 + ERROR_BAD_SECTION_NAME_LINE Errno = 0x20000000 | 0xC0000000 | 1 + ERROR_SECTION_NAME_TOO_LONG Errno = 0x20000000 | 0xC0000000 | 2 + ERROR_GENERAL_SYNTAX Errno = 0x20000000 | 0xC0000000 | 3 + ERROR_WRONG_INF_STYLE Errno = 0x20000000 | 0xC0000000 | 0x100 + ERROR_SECTION_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x101 + ERROR_LINE_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x102 + ERROR_NO_BACKUP Errno = 0x20000000 | 0xC0000000 | 0x103 + ERROR_NO_ASSOCIATED_CLASS Errno = 0x20000000 | 0xC0000000 | 0x200 + ERROR_CLASS_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x201 + ERROR_DUPLICATE_FOUND Errno = 0x20000000 | 0xC0000000 | 0x202 + ERROR_NO_DRIVER_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x203 + ERROR_KEY_DOES_NOT_EXIST Errno = 0x20000000 | 0xC0000000 | 0x204 + ERROR_INVALID_DEVINST_NAME Errno = 0x20000000 | 0xC0000000 | 0x205 + ERROR_INVALID_CLASS Errno = 0x20000000 | 0xC0000000 | 0x206 + ERROR_DEVINST_ALREADY_EXISTS Errno = 0x20000000 | 0xC0000000 | 0x207 + ERROR_DEVINFO_NOT_REGISTERED Errno = 0x20000000 | 0xC0000000 | 0x208 + ERROR_INVALID_REG_PROPERTY Errno = 0x20000000 | 0xC0000000 | 0x209 + ERROR_NO_INF Errno = 0x20000000 | 0xC0000000 | 0x20A + ERROR_NO_SUCH_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x20B + ERROR_CANT_LOAD_CLASS_ICON Errno = 0x20000000 | 0xC0000000 | 0x20C + ERROR_INVALID_CLASS_INSTALLER Errno = 0x20000000 | 0xC0000000 | 0x20D + ERROR_DI_DO_DEFAULT Errno = 0x20000000 | 0xC0000000 | 0x20E + ERROR_DI_NOFILECOPY Errno = 0x20000000 | 0xC0000000 | 0x20F + ERROR_INVALID_HWPROFILE Errno = 0x20000000 | 0xC0000000 | 0x210 + ERROR_NO_DEVICE_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x211 + ERROR_DEVINFO_LIST_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x212 + ERROR_DEVINFO_DATA_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x213 + ERROR_DI_BAD_PATH Errno = 0x20000000 | 0xC0000000 | 0x214 + ERROR_NO_CLASSINSTALL_PARAMS Errno = 0x20000000 | 0xC0000000 | 0x215 + ERROR_FILEQUEUE_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x216 + ERROR_BAD_SERVICE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x217 + ERROR_NO_CLASS_DRIVER_LIST Errno = 0x20000000 | 0xC0000000 | 0x218 + ERROR_NO_ASSOCIATED_SERVICE Errno = 0x20000000 | 0xC0000000 | 0x219 + ERROR_NO_DEFAULT_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x21A + ERROR_DEVICE_INTERFACE_ACTIVE Errno = 0x20000000 | 0xC0000000 | 0x21B + ERROR_DEVICE_INTERFACE_REMOVED Errno = 0x20000000 | 0xC0000000 | 0x21C + ERROR_BAD_INTERFACE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x21D + ERROR_NO_SUCH_INTERFACE_CLASS Errno = 0x20000000 | 0xC0000000 | 0x21E + ERROR_INVALID_REFERENCE_STRING Errno = 0x20000000 | 0xC0000000 | 0x21F + ERROR_INVALID_MACHINENAME Errno = 0x20000000 | 0xC0000000 | 0x220 + ERROR_REMOTE_COMM_FAILURE Errno = 0x20000000 | 0xC0000000 | 0x221 + ERROR_MACHINE_UNAVAILABLE Errno = 0x20000000 | 0xC0000000 | 0x222 + ERROR_NO_CONFIGMGR_SERVICES Errno = 0x20000000 | 0xC0000000 | 0x223 + ERROR_INVALID_PROPPAGE_PROVIDER Errno = 0x20000000 | 0xC0000000 | 0x224 + ERROR_NO_SUCH_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x225 + ERROR_DI_POSTPROCESSING_REQUIRED Errno = 0x20000000 | 0xC0000000 | 0x226 + ERROR_INVALID_COINSTALLER Errno = 0x20000000 | 0xC0000000 | 0x227 + ERROR_NO_COMPAT_DRIVERS Errno = 0x20000000 | 0xC0000000 | 0x228 + ERROR_NO_DEVICE_ICON Errno = 0x20000000 | 0xC0000000 | 0x229 + ERROR_INVALID_INF_LOGCONFIG Errno = 0x20000000 | 0xC0000000 | 0x22A + ERROR_DI_DONT_INSTALL Errno = 0x20000000 | 0xC0000000 | 0x22B + ERROR_INVALID_FILTER_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22C + ERROR_NON_WINDOWS_NT_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22D + ERROR_NON_WINDOWS_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22E + ERROR_NO_CATALOG_FOR_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x22F + ERROR_DEVINSTALL_QUEUE_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x230 + ERROR_NOT_DISABLEABLE Errno = 0x20000000 | 0xC0000000 | 0x231 + ERROR_CANT_REMOVE_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x232 + ERROR_INVALID_TARGET Errno = 0x20000000 | 0xC0000000 | 0x233 + ERROR_DRIVER_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x234 + ERROR_IN_WOW64 Errno = 0x20000000 | 0xC0000000 | 0x235 + ERROR_SET_SYSTEM_RESTORE_POINT Errno = 0x20000000 | 0xC0000000 | 0x236 + ERROR_SCE_DISABLED Errno = 0x20000000 | 0xC0000000 | 0x238 + ERROR_UNKNOWN_EXCEPTION Errno = 0x20000000 | 0xC0000000 | 0x239 + ERROR_PNP_REGISTRY_ERROR Errno = 0x20000000 | 0xC0000000 | 0x23A + ERROR_REMOTE_REQUEST_UNSUPPORTED Errno = 0x20000000 | 0xC0000000 | 0x23B + ERROR_NOT_AN_INSTALLED_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x23C + ERROR_INF_IN_USE_BY_DEVICES Errno = 0x20000000 | 0xC0000000 | 0x23D + ERROR_DI_FUNCTION_OBSOLETE Errno = 0x20000000 | 0xC0000000 | 0x23E + ERROR_NO_AUTHENTICODE_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x23F + ERROR_AUTHENTICODE_DISALLOWED Errno = 0x20000000 | 0xC0000000 | 0x240 + ERROR_AUTHENTICODE_TRUSTED_PUBLISHER Errno = 0x20000000 | 0xC0000000 | 0x241 + ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED Errno = 0x20000000 | 0xC0000000 | 0x242 + ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED Errno = 0x20000000 | 0xC0000000 | 0x243 + ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x244 + ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE Errno = 0x20000000 | 0xC0000000 | 0x245 + ERROR_DEVICE_INSTALLER_NOT_READY Errno = 0x20000000 | 0xC0000000 | 0x246 + ERROR_DRIVER_STORE_ADD_FAILED Errno = 0x20000000 | 0xC0000000 | 0x247 + ERROR_DEVICE_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x248 + ERROR_DRIVER_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x249 + ERROR_WRONG_INF_TYPE Errno = 0x20000000 | 0xC0000000 | 0x24A + ERROR_FILE_HASH_NOT_IN_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x24B + ERROR_DRIVER_STORE_DELETE_FAILED Errno = 0x20000000 | 0xC0000000 | 0x24C + ERROR_UNRECOVERABLE_STACK_OVERFLOW Errno = 0x20000000 | 0xC0000000 | 0x300 + EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW + ERROR_NO_DEFAULT_INTERFACE_DEVICE Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE + ERROR_INTERFACE_DEVICE_ACTIVE Errno = ERROR_DEVICE_INTERFACE_ACTIVE + ERROR_INTERFACE_DEVICE_REMOVED Errno = ERROR_DEVICE_INTERFACE_REMOVED + ERROR_NO_SUCH_INTERFACE_DEVICE Errno = ERROR_NO_SUCH_DEVICE_INTERFACE +) + +const ( + MAX_DEVICE_ID_LEN = 200 + MAX_DEVNODE_ID_LEN = MAX_DEVICE_ID_LEN + MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null + MAX_CLASS_NAME_LEN = 32 + MAX_PROFILE_LEN = 80 + MAX_CONFIG_VALUE = 9999 + MAX_INSTANCE_VALUE = 9999 + CONFIGMG_VERSION = 0x0400 +) + +// Maximum string length constants +const ( + LINE_LEN = 256 // Windows 9x-compatible maximum for displayable strings coming from a device INF. + MAX_INF_STRING_LENGTH = 4096 // Actual maximum size of an INF string (including string substitutions). + MAX_INF_SECTION_NAME_LENGTH = 255 // For Windows 9x compatibility, INF section names should be constrained to 32 characters. + MAX_TITLE_LEN = 60 + MAX_INSTRUCTION_LEN = 256 + MAX_LABEL_LEN = 30 + MAX_SERVICE_NAME_LEN = 256 + MAX_SUBTITLE_LEN = 256 +) + +const ( + // SP_MAX_MACHINENAME_LENGTH defines maximum length of a machine name in the format expected by ConfigMgr32 CM_Connect_Machine (i.e., "\\\\MachineName\0"). + SP_MAX_MACHINENAME_LENGTH = MAX_PATH + 3 +) + +// HSPFILEQ is type for setup file queue +type HSPFILEQ uintptr + +// DevInfo holds reference to device information set +type DevInfo Handle + +// DEVINST is a handle usually recognized by cfgmgr32 APIs +type DEVINST uint32 + +// DevInfoData is a device information structure (references a device instance that is a member of a device information set) +type DevInfoData struct { + size uint32 + ClassGUID GUID + DevInst DEVINST + _ uintptr +} + +// DevInfoListDetailData is a structure for detailed information on a device information set (used for SetupDiGetDeviceInfoListDetail which supersedes the functionality of SetupDiGetDeviceInfoListClass). +type DevInfoListDetailData struct { + size uint32 // Use unsafeSizeOf method + ClassGUID GUID + RemoteMachineHandle Handle + remoteMachineName [SP_MAX_MACHINENAME_LENGTH]uint16 +} + +func (*DevInfoListDetailData) unsafeSizeOf() uint32 { + if unsafe.Sizeof(uintptr(0)) == 4 { + // Windows declares this with pshpack1.h + return uint32(unsafe.Offsetof(DevInfoListDetailData{}.remoteMachineName) + unsafe.Sizeof(DevInfoListDetailData{}.remoteMachineName)) + } + return uint32(unsafe.Sizeof(DevInfoListDetailData{})) +} + +func (data *DevInfoListDetailData) RemoteMachineName() string { + return UTF16ToString(data.remoteMachineName[:]) +} + +func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error { + str, err := UTF16FromString(remoteMachineName) + if err != nil { + return err + } + copy(data.remoteMachineName[:], str) + return nil +} + +// DI_FUNCTION is function type for device installer +type DI_FUNCTION uint32 + +const ( + DIF_SELECTDEVICE DI_FUNCTION = 0x00000001 + DIF_INSTALLDEVICE DI_FUNCTION = 0x00000002 + DIF_ASSIGNRESOURCES DI_FUNCTION = 0x00000003 + DIF_PROPERTIES DI_FUNCTION = 0x00000004 + DIF_REMOVE DI_FUNCTION = 0x00000005 + DIF_FIRSTTIMESETUP DI_FUNCTION = 0x00000006 + DIF_FOUNDDEVICE DI_FUNCTION = 0x00000007 + DIF_SELECTCLASSDRIVERS DI_FUNCTION = 0x00000008 + DIF_VALIDATECLASSDRIVERS DI_FUNCTION = 0x00000009 + DIF_INSTALLCLASSDRIVERS DI_FUNCTION = 0x0000000A + DIF_CALCDISKSPACE DI_FUNCTION = 0x0000000B + DIF_DESTROYPRIVATEDATA DI_FUNCTION = 0x0000000C + DIF_VALIDATEDRIVER DI_FUNCTION = 0x0000000D + DIF_DETECT DI_FUNCTION = 0x0000000F + DIF_INSTALLWIZARD DI_FUNCTION = 0x00000010 + DIF_DESTROYWIZARDDATA DI_FUNCTION = 0x00000011 + DIF_PROPERTYCHANGE DI_FUNCTION = 0x00000012 + DIF_ENABLECLASS DI_FUNCTION = 0x00000013 + DIF_DETECTVERIFY DI_FUNCTION = 0x00000014 + DIF_INSTALLDEVICEFILES DI_FUNCTION = 0x00000015 + DIF_UNREMOVE DI_FUNCTION = 0x00000016 + DIF_SELECTBESTCOMPATDRV DI_FUNCTION = 0x00000017 + DIF_ALLOW_INSTALL DI_FUNCTION = 0x00000018 + DIF_REGISTERDEVICE DI_FUNCTION = 0x00000019 + DIF_NEWDEVICEWIZARD_PRESELECT DI_FUNCTION = 0x0000001A + DIF_NEWDEVICEWIZARD_SELECT DI_FUNCTION = 0x0000001B + DIF_NEWDEVICEWIZARD_PREANALYZE DI_FUNCTION = 0x0000001C + DIF_NEWDEVICEWIZARD_POSTANALYZE DI_FUNCTION = 0x0000001D + DIF_NEWDEVICEWIZARD_FINISHINSTALL DI_FUNCTION = 0x0000001E + DIF_INSTALLINTERFACES DI_FUNCTION = 0x00000020 + DIF_DETECTCANCEL DI_FUNCTION = 0x00000021 + DIF_REGISTER_COINSTALLERS DI_FUNCTION = 0x00000022 + DIF_ADDPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000023 + DIF_ADDPROPERTYPAGE_BASIC DI_FUNCTION = 0x00000024 + DIF_TROUBLESHOOTER DI_FUNCTION = 0x00000026 + DIF_POWERMESSAGEWAKE DI_FUNCTION = 0x00000027 + DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028 + DIF_UPDATEDRIVER_UI DI_FUNCTION = 0x00000029 + DIF_FINISHINSTALL_ACTION DI_FUNCTION = 0x0000002A +) + +// DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set) +type DevInstallParams struct { + size uint32 + Flags DI_FLAGS + FlagsEx DI_FLAGSEX + hwndParent uintptr + InstallMsgHandler uintptr + InstallMsgHandlerContext uintptr + FileQueue HSPFILEQ + _ uintptr + _ uint32 + driverPath [MAX_PATH]uint16 +} + +func (params *DevInstallParams) DriverPath() string { + return UTF16ToString(params.driverPath[:]) +} + +func (params *DevInstallParams) SetDriverPath(driverPath string) error { + str, err := UTF16FromString(driverPath) + if err != nil { + return err + } + copy(params.driverPath[:], str) + return nil +} + +// DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values +type DI_FLAGS uint32 + +const ( + // Flags for choosing a device + DI_SHOWOEM DI_FLAGS = 0x00000001 // support Other... button + DI_SHOWCOMPAT DI_FLAGS = 0x00000002 // show compatibility list + DI_SHOWCLASS DI_FLAGS = 0x00000004 // show class list + DI_SHOWALL DI_FLAGS = 0x00000007 // both class & compat list shown + DI_NOVCP DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue + DI_DIDCOMPAT DI_FLAGS = 0x00000010 // Searched for compatible devices + DI_DIDCLASS DI_FLAGS = 0x00000020 // Searched for class devices + DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible + + // Flags returned by DiInstallDevice to indicate need to reboot/restart + DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect + DI_NEEDREBOOT DI_FLAGS = 0x00000100 // "" + + // Flags for device installation + DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk + + // Flags set by DiBuildDriverInfoList + DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list + + // Flag indicates that device is disabled + DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled + + // Flags for Device/Class Properties + DI_GENERALPAGE_ADDED DI_FLAGS = 0x00001000 + DI_RESOURCEPAGE_ADDED DI_FLAGS = 0x00002000 + + // Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updated. + DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000 + + // Flag to indicate that the sorting from the INF file should be used. + DI_INF_IS_SORTED DI_FLAGS = 0x00008000 + + // Flag to indicate that only the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched. + DI_ENUMSINGLEINF DI_FLAGS = 0x00010000 + + // Flag that prevents ConfigMgr from removing/re-enumerating devices during device + // registration, installation, and deletion. + DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000 + + // The following flag can be used to install a device disabled + DI_INSTALLDISABLED DI_FLAGS = 0x00040000 + + // Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver + // list from its existing class driver list, instead of the normal INF search. + DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000 + + // This flag is set if the Class Install params should be used. + DI_CLASSINSTALLPARAMS DI_FLAGS = 0x00100000 + + // This flag is set if the caller of DiCallClassInstaller does NOT want the internal default action performed if the Class installer returns ERROR_DI_DO_DEFAULT. + DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000 + + // Flags for device installation + DI_QUIETINSTALL DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info + DI_NOFILECOPY DI_FLAGS = 0x01000000 // No file Copy necessary + DI_FORCECOPY DI_FLAGS = 0x02000000 // Force files to be copied from install path + DI_DRIVERPAGE_ADDED DI_FLAGS = 0x04000000 // Prop provider added Driver page. + DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg + DI_OVERRIDE_INFFLAGS DI_FLAGS = 0x10000000 // Override INF flags + DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props + + DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs + + DI_NOWRITE_IDS DI_FLAGS = 0x80000000 // Don't write HW & Compat IDs on install +) + +// DI_FLAGSEX is SP_DEVINSTALL_PARAMS.FlagsEx values +type DI_FLAGSEX uint32 + +const ( + DI_FLAGSEX_CI_FAILED DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer + DI_FLAGSEX_FINISHINSTALL_ACTION DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context. + DI_FLAGSEX_DIDINFOLIST DI_FLAGSEX = 0x00000010 // Did the Class Info List + DI_FLAGSEX_DIDCOMPATINFO DI_FLAGSEX = 0x00000020 // Did the Compat Info List + DI_FLAGSEX_FILTERCLASSES DI_FLAGSEX = 0x00000040 + DI_FLAGSEX_SETFAILEDINSTALL DI_FLAGSEX = 0x00000080 + DI_FLAGSEX_DEVICECHANGE DI_FLAGSEX = 0x00000100 + DI_FLAGSEX_ALWAYSWRITEIDS DI_FLAGSEX = 0x00000200 + DI_FLAGSEX_PROPCHANGE_PENDING DI_FLAGSEX = 0x00000400 // One or more device property sheets have had changes made to them, and need to have a DIF_PROPERTYCHANGE occur. + DI_FLAGSEX_ALLOWEXCLUDEDDRVS DI_FLAGSEX = 0x00000800 + DI_FLAGSEX_NOUIONQUERYREMOVE DI_FLAGSEX = 0x00001000 + DI_FLAGSEX_USECLASSFORCOMPAT DI_FLAGSEX = 0x00002000 // Use the device's class when building compat drv list. (Ignored if DI_COMPAT_FROM_CLASS flag is specified.) + DI_FLAGSEX_NO_DRVREG_MODIFY DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key. + DI_FLAGSEX_IN_SYSTEM_SETUP DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup. + DI_FLAGSEX_INET_DRIVER DI_FLAGSEX = 0x00020000 // Driver came from Windows Update + DI_FLAGSEX_APPENDDRIVERLIST DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list. + DI_FLAGSEX_PREINSTALLBACKUP DI_FLAGSEX = 0x00080000 // not used + DI_FLAGSEX_BACKUPONREPLACE DI_FLAGSEX = 0x00100000 // not used + DI_FLAGSEX_DRIVERLIST_FROM_URL DI_FLAGSEX = 0x00200000 // build driver list from INF(s) retrieved from URL specified in SP_DEVINSTALL_PARAMS.DriverPath (empty string means Windows Update website) + DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS DI_FLAGSEX = 0x00800000 // Don't include old Internet drivers when building a driver list. Ignored on Windows Vista and later. + DI_FLAGSEX_POWERPAGE_ADDED DI_FLAGSEX = 0x01000000 // class installer added their own power page + DI_FLAGSEX_FILTERSIMILARDRIVERS DI_FLAGSEX = 0x02000000 // only include similar drivers in class list + DI_FLAGSEX_INSTALLEDDRIVER DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list. Used in calls to SetupDiBuildDriverInfoList + DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list + DI_FLAGSEX_ALTPLATFORM_DRVSEARCH DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue + DI_FLAGSEX_RESTART_DEVICE_ONLY DI_FLAGSEX = 0x20000000 // only restart the device drivers are being installed on as opposed to restarting all devices using those drivers. + DI_FLAGSEX_RECURSIVESEARCH DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search + DI_FLAGSEX_SEARCH_PUBLISHED_INFS DI_FLAGSEX = 0x80000000 // Tell SetupDiBuildDriverInfoList to do a "published INF" search +) + +// ClassInstallHeader is the first member of any class install parameters structure. It contains the device installation request code that defines the format of the rest of the install parameters structure. +type ClassInstallHeader struct { + size uint32 + InstallFunction DI_FUNCTION +} + +func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader { + hdr := &ClassInstallHeader{InstallFunction: installFunction} + hdr.size = uint32(unsafe.Sizeof(*hdr)) + return hdr +} + +// DICS_STATE specifies values indicating a change in a device's state +type DICS_STATE uint32 + +const ( + DICS_ENABLE DICS_STATE = 0x00000001 // The device is being enabled. + DICS_DISABLE DICS_STATE = 0x00000002 // The device is being disabled. + DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed. + DICS_START DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile). + DICS_STOP DICS_STATE = 0x00000005 // The device is being stopped. The driver stack will be unloaded and the CSCONFIGFLAG_DO_NOT_START flag will be set for the device. +) + +// DICS_FLAG specifies the scope of a device property change +type DICS_FLAG uint32 + +const ( + DICS_FLAG_GLOBAL DICS_FLAG = 0x00000001 // make change in all hardware profiles + DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only + DICS_FLAG_CONFIGGENERAL DICS_FLAG = 0x00000004 // 1 or more hardware profile-specific changes to follow (obsolete) +) + +// PropChangeParams is a structure corresponding to a DIF_PROPERTYCHANGE install function. +type PropChangeParams struct { + ClassInstallHeader ClassInstallHeader + StateChange DICS_STATE + Scope DICS_FLAG + HwProfile uint32 +} + +// DI_REMOVEDEVICE specifies the scope of the device removal +type DI_REMOVEDEVICE uint32 + +const ( + DI_REMOVEDEVICE_GLOBAL DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry. + DI_REMOVEDEVICE_CONFIGSPECIFIC DI_REMOVEDEVICE = 0x00000002 // Make this change to only the hardware profile specified by HwProfile. this flag only applies to root-enumerated devices. When Windows removes the device from the last hardware profile in which it was configured, Windows performs a global removal. +) + +// RemoveDeviceParams is a structure corresponding to a DIF_REMOVE install function. +type RemoveDeviceParams struct { + ClassInstallHeader ClassInstallHeader + Scope DI_REMOVEDEVICE + HwProfile uint32 +} + +// DrvInfoData is driver information structure (member of a driver info list that may be associated with a particular device instance, or (globally) with a device information set) +type DrvInfoData struct { + size uint32 + DriverType uint32 + _ uintptr + description [LINE_LEN]uint16 + mfgName [LINE_LEN]uint16 + providerName [LINE_LEN]uint16 + DriverDate Filetime + DriverVersion uint64 +} + +func (data *DrvInfoData) Description() string { + return UTF16ToString(data.description[:]) +} + +func (data *DrvInfoData) SetDescription(description string) error { + str, err := UTF16FromString(description) + if err != nil { + return err + } + copy(data.description[:], str) + return nil +} + +func (data *DrvInfoData) MfgName() string { + return UTF16ToString(data.mfgName[:]) +} + +func (data *DrvInfoData) SetMfgName(mfgName string) error { + str, err := UTF16FromString(mfgName) + if err != nil { + return err + } + copy(data.mfgName[:], str) + return nil +} + +func (data *DrvInfoData) ProviderName() string { + return UTF16ToString(data.providerName[:]) +} + +func (data *DrvInfoData) SetProviderName(providerName string) error { + str, err := UTF16FromString(providerName) + if err != nil { + return err + } + copy(data.providerName[:], str) + return nil +} + +// IsNewer method returns true if DrvInfoData date and version is newer than supplied parameters. +func (data *DrvInfoData) IsNewer(driverDate Filetime, driverVersion uint64) bool { + if data.DriverDate.HighDateTime > driverDate.HighDateTime { + return true + } + if data.DriverDate.HighDateTime < driverDate.HighDateTime { + return false + } + + if data.DriverDate.LowDateTime > driverDate.LowDateTime { + return true + } + if data.DriverDate.LowDateTime < driverDate.LowDateTime { + return false + } + + if data.DriverVersion > driverVersion { + return true + } + if data.DriverVersion < driverVersion { + return false + } + + return false +} + +// DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure) +type DrvInfoDetailData struct { + size uint32 // Use unsafeSizeOf method + InfDate Filetime + compatIDsOffset uint32 + compatIDsLength uint32 + _ uintptr + sectionName [LINE_LEN]uint16 + infFileName [MAX_PATH]uint16 + drvDescription [LINE_LEN]uint16 + hardwareID [1]uint16 +} + +func (*DrvInfoDetailData) unsafeSizeOf() uint32 { + if unsafe.Sizeof(uintptr(0)) == 4 { + // Windows declares this with pshpack1.h + return uint32(unsafe.Offsetof(DrvInfoDetailData{}.hardwareID) + unsafe.Sizeof(DrvInfoDetailData{}.hardwareID)) + } + return uint32(unsafe.Sizeof(DrvInfoDetailData{})) +} + +func (data *DrvInfoDetailData) SectionName() string { + return UTF16ToString(data.sectionName[:]) +} + +func (data *DrvInfoDetailData) InfFileName() string { + return UTF16ToString(data.infFileName[:]) +} + +func (data *DrvInfoDetailData) DrvDescription() string { + return UTF16ToString(data.drvDescription[:]) +} + +func (data *DrvInfoDetailData) HardwareID() string { + if data.compatIDsOffset > 1 { + bufW := data.getBuf() + return UTF16ToString(bufW[:wcslen(bufW)]) + } + + return "" +} + +func (data *DrvInfoDetailData) CompatIDs() []string { + a := make([]string, 0) + + if data.compatIDsLength > 0 { + bufW := data.getBuf() + bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength] + for i := 0; i < len(bufW); { + j := i + wcslen(bufW[i:]) + if i < j { + a = append(a, UTF16ToString(bufW[i:j])) + } + i = j + 1 + } + } + + return a +} + +func (data *DrvInfoDetailData) getBuf() []uint16 { + len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2 + sl := struct { + addr *uint16 + len int + cap int + }{&data.hardwareID[0], int(len), int(len)} + return *(*[]uint16)(unsafe.Pointer(&sl)) +} + +// IsCompatible method tests if given hardware ID matches the driver or is listed on the compatible ID list. +func (data *DrvInfoDetailData) IsCompatible(hwid string) bool { + hwidLC := strings.ToLower(hwid) + if strings.ToLower(data.HardwareID()) == hwidLC { + return true + } + a := data.CompatIDs() + for i := range a { + if strings.ToLower(a[i]) == hwidLC { + return true + } + } + + return false +} + +// DICD flags control SetupDiCreateDeviceInfo +type DICD uint32 + +const ( + DICD_GENERATE_ID DICD = 0x00000001 + DICD_INHERIT_CLASSDRVS DICD = 0x00000002 +) + +// SUOI flags control SetupUninstallOEMInf +type SUOI uint32 + +const ( + SUOI_FORCEDELETE SUOI = 0x0001 +) + +// SPDIT flags to distinguish between class drivers and +// device drivers. (Passed in 'DriverType' parameter of +// driver information list APIs) +type SPDIT uint32 + +const ( + SPDIT_NODRIVER SPDIT = 0x00000000 + SPDIT_CLASSDRIVER SPDIT = 0x00000001 + SPDIT_COMPATDRIVER SPDIT = 0x00000002 +) + +// DIGCF flags control what is included in the device information set built by SetupDiGetClassDevs +type DIGCF uint32 + +const ( + DIGCF_DEFAULT DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE + DIGCF_PRESENT DIGCF = 0x00000002 + DIGCF_ALLCLASSES DIGCF = 0x00000004 + DIGCF_PROFILE DIGCF = 0x00000008 + DIGCF_DEVICEINTERFACE DIGCF = 0x00000010 +) + +// DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey. +type DIREG uint32 + +const ( + DIREG_DEV DIREG = 0x00000001 // Open/Create/Delete device key + DIREG_DRV DIREG = 0x00000002 // Open/Create/Delete driver key + DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key +) + +// SPDRP specifies device registry property codes +// (Codes marked as read-only (R) may only be used for +// SetupDiGetDeviceRegistryProperty) +// +// These values should cover the same set of registry properties +// as defined by the CM_DRP codes in cfgmgr32.h. +// +// Note that SPDRP codes are zero based while CM_DRP codes are one based! +type SPDRP uint32 + +const ( + SPDRP_DEVICEDESC SPDRP = 0x00000000 // DeviceDesc (R/W) + SPDRP_HARDWAREID SPDRP = 0x00000001 // HardwareID (R/W) + SPDRP_COMPATIBLEIDS SPDRP = 0x00000002 // CompatibleIDs (R/W) + SPDRP_SERVICE SPDRP = 0x00000004 // Service (R/W) + SPDRP_CLASS SPDRP = 0x00000007 // Class (R--tied to ClassGUID) + SPDRP_CLASSGUID SPDRP = 0x00000008 // ClassGUID (R/W) + SPDRP_DRIVER SPDRP = 0x00000009 // Driver (R/W) + SPDRP_CONFIGFLAGS SPDRP = 0x0000000A // ConfigFlags (R/W) + SPDRP_MFG SPDRP = 0x0000000B // Mfg (R/W) + SPDRP_FRIENDLYNAME SPDRP = 0x0000000C // FriendlyName (R/W) + SPDRP_LOCATION_INFORMATION SPDRP = 0x0000000D // LocationInformation (R/W) + SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R) + SPDRP_CAPABILITIES SPDRP = 0x0000000F // Capabilities (R) + SPDRP_UI_NUMBER SPDRP = 0x00000010 // UiNumber (R) + SPDRP_UPPERFILTERS SPDRP = 0x00000011 // UpperFilters (R/W) + SPDRP_LOWERFILTERS SPDRP = 0x00000012 // LowerFilters (R/W) + SPDRP_BUSTYPEGUID SPDRP = 0x00000013 // BusTypeGUID (R) + SPDRP_LEGACYBUSTYPE SPDRP = 0x00000014 // LegacyBusType (R) + SPDRP_BUSNUMBER SPDRP = 0x00000015 // BusNumber (R) + SPDRP_ENUMERATOR_NAME SPDRP = 0x00000016 // Enumerator Name (R) + SPDRP_SECURITY SPDRP = 0x00000017 // Security (R/W, binary form) + SPDRP_SECURITY_SDS SPDRP = 0x00000018 // Security (W, SDS form) + SPDRP_DEVTYPE SPDRP = 0x00000019 // Device Type (R/W) + SPDRP_EXCLUSIVE SPDRP = 0x0000001A // Device is exclusive-access (R/W) + SPDRP_CHARACTERISTICS SPDRP = 0x0000001B // Device Characteristics (R/W) + SPDRP_ADDRESS SPDRP = 0x0000001C // Device Address (R) + SPDRP_UI_NUMBER_DESC_FORMAT SPDRP = 0x0000001D // UiNumberDescFormat (R/W) + SPDRP_DEVICE_POWER_DATA SPDRP = 0x0000001E // Device Power Data (R) + SPDRP_REMOVAL_POLICY SPDRP = 0x0000001F // Removal Policy (R) + SPDRP_REMOVAL_POLICY_HW_DEFAULT SPDRP = 0x00000020 // Hardware Removal Policy (R) + SPDRP_REMOVAL_POLICY_OVERRIDE SPDRP = 0x00000021 // Removal Policy Override (RW) + SPDRP_INSTALL_STATE SPDRP = 0x00000022 // Device Install State (R) + SPDRP_LOCATION_PATHS SPDRP = 0x00000023 // Device Location Paths (R) + SPDRP_BASE_CONTAINERID SPDRP = 0x00000024 // Base ContainerID (R) + + SPDRP_MAXIMUM_PROPERTY SPDRP = 0x00000025 // Upper bound on ordinals +) + +// DEVPROPTYPE represents the property-data-type identifier that specifies the +// data type of a device property value in the unified device property model. +type DEVPROPTYPE uint32 + +const ( + DEVPROP_TYPEMOD_ARRAY DEVPROPTYPE = 0x00001000 + DEVPROP_TYPEMOD_LIST DEVPROPTYPE = 0x00002000 + + DEVPROP_TYPE_EMPTY DEVPROPTYPE = 0x00000000 + DEVPROP_TYPE_NULL DEVPROPTYPE = 0x00000001 + DEVPROP_TYPE_SBYTE DEVPROPTYPE = 0x00000002 + DEVPROP_TYPE_BYTE DEVPROPTYPE = 0x00000003 + DEVPROP_TYPE_INT16 DEVPROPTYPE = 0x00000004 + DEVPROP_TYPE_UINT16 DEVPROPTYPE = 0x00000005 + DEVPROP_TYPE_INT32 DEVPROPTYPE = 0x00000006 + DEVPROP_TYPE_UINT32 DEVPROPTYPE = 0x00000007 + DEVPROP_TYPE_INT64 DEVPROPTYPE = 0x00000008 + DEVPROP_TYPE_UINT64 DEVPROPTYPE = 0x00000009 + DEVPROP_TYPE_FLOAT DEVPROPTYPE = 0x0000000A + DEVPROP_TYPE_DOUBLE DEVPROPTYPE = 0x0000000B + DEVPROP_TYPE_DECIMAL DEVPROPTYPE = 0x0000000C + DEVPROP_TYPE_GUID DEVPROPTYPE = 0x0000000D + DEVPROP_TYPE_CURRENCY DEVPROPTYPE = 0x0000000E + DEVPROP_TYPE_DATE DEVPROPTYPE = 0x0000000F + DEVPROP_TYPE_FILETIME DEVPROPTYPE = 0x00000010 + DEVPROP_TYPE_BOOLEAN DEVPROPTYPE = 0x00000011 + DEVPROP_TYPE_STRING DEVPROPTYPE = 0x00000012 + DEVPROP_TYPE_STRING_LIST DEVPROPTYPE = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST + DEVPROP_TYPE_SECURITY_DESCRIPTOR DEVPROPTYPE = 0x00000013 + DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING DEVPROPTYPE = 0x00000014 + DEVPROP_TYPE_DEVPROPKEY DEVPROPTYPE = 0x00000015 + DEVPROP_TYPE_DEVPROPTYPE DEVPROPTYPE = 0x00000016 + DEVPROP_TYPE_BINARY DEVPROPTYPE = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY + DEVPROP_TYPE_ERROR DEVPROPTYPE = 0x00000017 + DEVPROP_TYPE_NTSTATUS DEVPROPTYPE = 0x00000018 + DEVPROP_TYPE_STRING_INDIRECT DEVPROPTYPE = 0x00000019 + + MAX_DEVPROP_TYPE DEVPROPTYPE = 0x00000019 + MAX_DEVPROP_TYPEMOD DEVPROPTYPE = 0x00002000 + + DEVPROP_MASK_TYPE DEVPROPTYPE = 0x00000FFF + DEVPROP_MASK_TYPEMOD DEVPROPTYPE = 0x0000F000 +) + +// DEVPROPGUID specifies a property category. +type DEVPROPGUID GUID + +// DEVPROPID uniquely identifies the property within the property category. +type DEVPROPID uint32 + +const DEVPROPID_FIRST_USABLE DEVPROPID = 2 + +// DEVPROPKEY represents a device property key for a device property in the +// unified device property model. +type DEVPROPKEY struct { + FmtID DEVPROPGUID + PID DEVPROPID +} + +// CONFIGRET is a return value or error code from cfgmgr32 APIs +type CONFIGRET uint32 + +func (ret CONFIGRET) Error() string { + if win32Error, ok := ret.Unwrap().(Errno); ok { + return fmt.Sprintf("%s (CfgMgr error: 0x%08x)", win32Error.Error(), uint32(ret)) + } + return fmt.Sprintf("CfgMgr error: 0x%08x", uint32(ret)) +} + +func (ret CONFIGRET) Win32Error(defaultError Errno) Errno { + return cm_MapCrToWin32Err(ret, defaultError) +} + +func (ret CONFIGRET) Unwrap() error { + const noMatch = Errno(^uintptr(0)) + win32Error := ret.Win32Error(noMatch) + if win32Error == noMatch { + return nil + } + return win32Error +} + +const ( + CR_SUCCESS CONFIGRET = 0x00000000 + CR_DEFAULT CONFIGRET = 0x00000001 + CR_OUT_OF_MEMORY CONFIGRET = 0x00000002 + CR_INVALID_POINTER CONFIGRET = 0x00000003 + CR_INVALID_FLAG CONFIGRET = 0x00000004 + CR_INVALID_DEVNODE CONFIGRET = 0x00000005 + CR_INVALID_DEVINST = CR_INVALID_DEVNODE + CR_INVALID_RES_DES CONFIGRET = 0x00000006 + CR_INVALID_LOG_CONF CONFIGRET = 0x00000007 + CR_INVALID_ARBITRATOR CONFIGRET = 0x00000008 + CR_INVALID_NODELIST CONFIGRET = 0x00000009 + CR_DEVNODE_HAS_REQS CONFIGRET = 0x0000000A + CR_DEVINST_HAS_REQS = CR_DEVNODE_HAS_REQS + CR_INVALID_RESOURCEID CONFIGRET = 0x0000000B + CR_DLVXD_NOT_FOUND CONFIGRET = 0x0000000C + CR_NO_SUCH_DEVNODE CONFIGRET = 0x0000000D + CR_NO_SUCH_DEVINST = CR_NO_SUCH_DEVNODE + CR_NO_MORE_LOG_CONF CONFIGRET = 0x0000000E + CR_NO_MORE_RES_DES CONFIGRET = 0x0000000F + CR_ALREADY_SUCH_DEVNODE CONFIGRET = 0x00000010 + CR_ALREADY_SUCH_DEVINST = CR_ALREADY_SUCH_DEVNODE + CR_INVALID_RANGE_LIST CONFIGRET = 0x00000011 + CR_INVALID_RANGE CONFIGRET = 0x00000012 + CR_FAILURE CONFIGRET = 0x00000013 + CR_NO_SUCH_LOGICAL_DEV CONFIGRET = 0x00000014 + CR_CREATE_BLOCKED CONFIGRET = 0x00000015 + CR_NOT_SYSTEM_VM CONFIGRET = 0x00000016 + CR_REMOVE_VETOED CONFIGRET = 0x00000017 + CR_APM_VETOED CONFIGRET = 0x00000018 + CR_INVALID_LOAD_TYPE CONFIGRET = 0x00000019 + CR_BUFFER_SMALL CONFIGRET = 0x0000001A + CR_NO_ARBITRATOR CONFIGRET = 0x0000001B + CR_NO_REGISTRY_HANDLE CONFIGRET = 0x0000001C + CR_REGISTRY_ERROR CONFIGRET = 0x0000001D + CR_INVALID_DEVICE_ID CONFIGRET = 0x0000001E + CR_INVALID_DATA CONFIGRET = 0x0000001F + CR_INVALID_API CONFIGRET = 0x00000020 + CR_DEVLOADER_NOT_READY CONFIGRET = 0x00000021 + CR_NEED_RESTART CONFIGRET = 0x00000022 + CR_NO_MORE_HW_PROFILES CONFIGRET = 0x00000023 + CR_DEVICE_NOT_THERE CONFIGRET = 0x00000024 + CR_NO_SUCH_VALUE CONFIGRET = 0x00000025 + CR_WRONG_TYPE CONFIGRET = 0x00000026 + CR_INVALID_PRIORITY CONFIGRET = 0x00000027 + CR_NOT_DISABLEABLE CONFIGRET = 0x00000028 + CR_FREE_RESOURCES CONFIGRET = 0x00000029 + CR_QUERY_VETOED CONFIGRET = 0x0000002A + CR_CANT_SHARE_IRQ CONFIGRET = 0x0000002B + CR_NO_DEPENDENT CONFIGRET = 0x0000002C + CR_SAME_RESOURCES CONFIGRET = 0x0000002D + CR_NO_SUCH_REGISTRY_KEY CONFIGRET = 0x0000002E + CR_INVALID_MACHINENAME CONFIGRET = 0x0000002F + CR_REMOTE_COMM_FAILURE CONFIGRET = 0x00000030 + CR_MACHINE_UNAVAILABLE CONFIGRET = 0x00000031 + CR_NO_CM_SERVICES CONFIGRET = 0x00000032 + CR_ACCESS_DENIED CONFIGRET = 0x00000033 + CR_CALL_NOT_IMPLEMENTED CONFIGRET = 0x00000034 + CR_INVALID_PROPERTY CONFIGRET = 0x00000035 + CR_DEVICE_INTERFACE_ACTIVE CONFIGRET = 0x00000036 + CR_NO_SUCH_DEVICE_INTERFACE CONFIGRET = 0x00000037 + CR_INVALID_REFERENCE_STRING CONFIGRET = 0x00000038 + CR_INVALID_CONFLICT_LIST CONFIGRET = 0x00000039 + CR_INVALID_INDEX CONFIGRET = 0x0000003A + CR_INVALID_STRUCTURE_SIZE CONFIGRET = 0x0000003B + NUM_CR_RESULTS CONFIGRET = 0x0000003C +) + +const ( + CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0 // only currently 'live' device interfaces + CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not +) + +const ( + DN_ROOT_ENUMERATED = 0x00000001 // Was enumerated by ROOT + DN_DRIVER_LOADED = 0x00000002 // Has Register_Device_Driver + DN_ENUM_LOADED = 0x00000004 // Has Register_Enumerator + DN_STARTED = 0x00000008 // Is currently configured + DN_MANUAL = 0x00000010 // Manually installed + DN_NEED_TO_ENUM = 0x00000020 // May need reenumeration + DN_NOT_FIRST_TIME = 0x00000040 // Has received a config + DN_HARDWARE_ENUM = 0x00000080 // Enum generates hardware ID + DN_LIAR = 0x00000100 // Lied about can reconfig once + DN_HAS_MARK = 0x00000200 // Not CM_Create_DevInst lately + DN_HAS_PROBLEM = 0x00000400 // Need device installer + DN_FILTERED = 0x00000800 // Is filtered + DN_MOVED = 0x00001000 // Has been moved + DN_DISABLEABLE = 0x00002000 // Can be disabled + DN_REMOVABLE = 0x00004000 // Can be removed + DN_PRIVATE_PROBLEM = 0x00008000 // Has a private problem + DN_MF_PARENT = 0x00010000 // Multi function parent + DN_MF_CHILD = 0x00020000 // Multi function child + DN_WILL_BE_REMOVED = 0x00040000 // DevInst is being removed + DN_NOT_FIRST_TIMEE = 0x00080000 // Has received a config enumerate + DN_STOP_FREE_RES = 0x00100000 // When child is stopped, free resources + DN_REBAL_CANDIDATE = 0x00200000 // Don't skip during rebalance + DN_BAD_PARTIAL = 0x00400000 // This devnode's log_confs do not have same resources + DN_NT_ENUMERATOR = 0x00800000 // This devnode's is an NT enumerator + DN_NT_DRIVER = 0x01000000 // This devnode's is an NT driver + DN_NEEDS_LOCKING = 0x02000000 // Devnode need lock resume processing + DN_ARM_WAKEUP = 0x04000000 // Devnode can be the wakeup device + DN_APM_ENUMERATOR = 0x08000000 // APM aware enumerator + DN_APM_DRIVER = 0x10000000 // APM aware driver + DN_SILENT_INSTALL = 0x20000000 // Silent install + DN_NO_SHOW_IN_DM = 0x40000000 // No show in device manager + DN_BOOT_LOG_PROB = 0x80000000 // Had a problem during preassignment of boot log conf + DN_NEED_RESTART = DN_LIAR // System needs to be restarted for this Devnode to work properly + DN_DRIVER_BLOCKED = DN_NOT_FIRST_TIME // One or more drivers are blocked from loading for this Devnode + DN_LEGACY_DRIVER = DN_MOVED // This device is using a legacy driver + DN_CHILD_WITH_INVALID_ID = DN_HAS_MARK // One or more children have invalid IDs + DN_DEVICE_DISCONNECTED = DN_NEEDS_LOCKING // The function driver for a device reported that the device is not connected. Typically this means a wireless device is out of range. + DN_QUERY_REMOVE_PENDING = DN_MF_PARENT // Device is part of a set of related devices collectively pending query-removal + DN_QUERY_REMOVE_ACTIVE = DN_MF_CHILD // Device is actively engaged in a query-remove IRP + DN_CHANGEABLE_FLAGS = DN_NOT_FIRST_TIME | DN_HARDWARE_ENUM | DN_HAS_MARK | DN_DISABLEABLE | DN_REMOVABLE | DN_MF_CHILD | DN_MF_PARENT | DN_NOT_FIRST_TIMEE | DN_STOP_FREE_RES | DN_REBAL_CANDIDATE | DN_NT_ENUMERATOR | DN_NT_DRIVER | DN_SILENT_INSTALL | DN_NO_SHOW_IN_DM +) + +//sys setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW + +// SetupDiCreateDeviceInfoListEx function creates an empty device information set on a remote or a local computer and optionally associates the set with a device setup class. +func SetupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName string) (deviceInfoSet DevInfo, err error) { + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return + } + } + return setupDiCreateDeviceInfoListEx(classGUID, hwndParent, machineNameUTF16, 0) +} + +//sys setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW + +// SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name. +func SetupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo) (deviceInfoSetDetailData *DevInfoListDetailData, err error) { + data := &DevInfoListDetailData{} + data.size = data.unsafeSizeOf() + + return data, setupDiGetDeviceInfoListDetail(deviceInfoSet, data) +} + +// DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name. +func (deviceInfoSet DevInfo) DeviceInfoListDetail() (*DevInfoListDetailData, error) { + return SetupDiGetDeviceInfoListDetail(deviceInfoSet) +} + +//sys setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW + +// SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set. +func SetupDiCreateDeviceInfo(deviceInfoSet DevInfo, deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (deviceInfoData *DevInfoData, err error) { + deviceNameUTF16, err := UTF16PtrFromString(deviceName) + if err != nil { + return + } + + var deviceDescriptionUTF16 *uint16 + if deviceDescription != "" { + deviceDescriptionUTF16, err = UTF16PtrFromString(deviceDescription) + if err != nil { + return + } + } + + data := &DevInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiCreateDeviceInfo(deviceInfoSet, deviceNameUTF16, classGUID, deviceDescriptionUTF16, hwndParent, creationFlags, data) +} + +// CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set. +func (deviceInfoSet DevInfo) CreateDeviceInfo(deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (*DevInfoData, error) { + return SetupDiCreateDeviceInfo(deviceInfoSet, deviceName, classGUID, deviceDescription, hwndParent, creationFlags) +} + +//sys setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo + +// SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set. +func SetupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex int) (*DevInfoData, error) { + data := &DevInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiEnumDeviceInfo(deviceInfoSet, uint32(memberIndex), data) +} + +// EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set. +func (deviceInfoSet DevInfo) EnumDeviceInfo(memberIndex int) (*DevInfoData, error) { + return SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex) +} + +// SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory. +//sys SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList + +// Close method deletes a device information set and frees all associated memory. +func (deviceInfoSet DevInfo) Close() error { + return SetupDiDestroyDeviceInfoList(deviceInfoSet) +} + +//sys SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList + +// BuildDriverInfoList method builds a list of drivers that is associated with a specific device or with the global class driver list for a device information set. +func (deviceInfoSet DevInfo) BuildDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error { + return SetupDiBuildDriverInfoList(deviceInfoSet, deviceInfoData, driverType) +} + +//sys SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch + +// CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread. +func (deviceInfoSet DevInfo) CancelDriverInfoSearch() error { + return SetupDiCancelDriverInfoSearch(deviceInfoSet) +} + +//sys setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW + +// SetupDiEnumDriverInfo function enumerates the members of a driver list. +func SetupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) { + data := &DrvInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, uint32(memberIndex), data) +} + +// EnumDriverInfo method enumerates the members of a driver list. +func (deviceInfoSet DevInfo) EnumDriverInfo(deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) { + return SetupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, memberIndex) +} + +//sys setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW + +// SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element. +func SetupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DrvInfoData, error) { + data := &DrvInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiGetSelectedDriver(deviceInfoSet, deviceInfoData, data) +} + +// SelectedDriver method retrieves the selected driver for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) SelectedDriver(deviceInfoData *DevInfoData) (*DrvInfoData, error) { + return SetupDiGetSelectedDriver(deviceInfoSet, deviceInfoData) +} + +//sys SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW + +// SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set. +func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) error { + return SetupDiSetSelectedDriver(deviceInfoSet, deviceInfoData, driverInfoData) +} + +//sys setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW + +// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set. +func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) { + reqSize := uint32(2048) + for { + buf := make([]byte, reqSize) + data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0])) + data.size = data.unsafeSizeOf() + err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return nil, err + } + data.size = reqSize + return data, nil + } +} + +// DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set. +func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) { + return SetupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData) +} + +//sys SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList + +// DestroyDriverInfoList method deletes a driver list. +func (deviceInfoSet DevInfo) DestroyDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error { + return SetupDiDestroyDriverInfoList(deviceInfoSet, deviceInfoData, driverType) +} + +//sys setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiGetClassDevsExW + +// SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer. +func SetupDiGetClassDevsEx(classGUID *GUID, enumerator string, hwndParent uintptr, flags DIGCF, deviceInfoSet DevInfo, machineName string) (handle DevInfo, err error) { + var enumeratorUTF16 *uint16 + if enumerator != "" { + enumeratorUTF16, err = UTF16PtrFromString(enumerator) + if err != nil { + return + } + } + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return + } + } + return setupDiGetClassDevsEx(classGUID, enumeratorUTF16, hwndParent, flags, deviceInfoSet, machineNameUTF16, 0) +} + +// SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code). +//sys SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller + +// CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code). +func (deviceInfoSet DevInfo) CallClassInstaller(installFunction DI_FUNCTION, deviceInfoData *DevInfoData) error { + return SetupDiCallClassInstaller(installFunction, deviceInfoSet, deviceInfoData) +} + +// SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information. +//sys SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) [failretval==InvalidHandle] = setupapi.SetupDiOpenDevRegKey + +// OpenDevRegKey method opens a registry key for device-specific configuration information. +func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (Handle, error) { + return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired) +} + +//sys setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) = setupapi.SetupDiGetDevicePropertyW + +// SetupDiGetDeviceProperty function retrieves a specified device instance property. +func SetupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY) (value interface{}, err error) { + reqSize := uint32(256) + for { + var dataType DEVPROPTYPE + buf := make([]byte, reqSize) + err = setupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, propertyKey, &dataType, &buf[0], uint32(len(buf)), &reqSize, 0) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return + } + switch dataType { + case DEVPROP_TYPE_STRING: + ret := UTF16ToString(bufToUTF16(buf)) + runtime.KeepAlive(buf) + return ret, nil + } + return nil, errors.New("unimplemented property type") + } +} + +//sys setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW + +// SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property. +func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) { + reqSize := uint32(256) + for { + var dataType uint32 + buf := make([]byte, reqSize) + err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return + } + return getRegistryValue(buf[:reqSize], dataType) + } +} + +func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) { + switch dataType { + case REG_SZ: + ret := UTF16ToString(bufToUTF16(buf)) + runtime.KeepAlive(buf) + return ret, nil + case REG_EXPAND_SZ: + value := UTF16ToString(bufToUTF16(buf)) + if value == "" { + return "", nil + } + p, err := syscall.UTF16PtrFromString(value) + if err != nil { + return "", err + } + ret := make([]uint16, 100) + for { + n, err := ExpandEnvironmentStrings(p, &ret[0], uint32(len(ret))) + if err != nil { + return "", err + } + if n <= uint32(len(ret)) { + return UTF16ToString(ret[:n]), nil + } + ret = make([]uint16, n) + } + case REG_BINARY: + return buf, nil + case REG_DWORD_LITTLE_ENDIAN: + return binary.LittleEndian.Uint32(buf), nil + case REG_DWORD_BIG_ENDIAN: + return binary.BigEndian.Uint32(buf), nil + case REG_MULTI_SZ: + bufW := bufToUTF16(buf) + a := []string{} + for i := 0; i < len(bufW); { + j := i + wcslen(bufW[i:]) + if i < j { + a = append(a, UTF16ToString(bufW[i:j])) + } + i = j + 1 + } + runtime.KeepAlive(buf) + return a, nil + case REG_QWORD_LITTLE_ENDIAN: + return binary.LittleEndian.Uint64(buf), nil + default: + return nil, fmt.Errorf("Unsupported registry value type: %v", dataType) + } +} + +// bufToUTF16 function reinterprets []byte buffer as []uint16 +func bufToUTF16(buf []byte) []uint16 { + sl := struct { + addr *uint16 + len int + cap int + }{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2} + return *(*[]uint16)(unsafe.Pointer(&sl)) +} + +// utf16ToBuf function reinterprets []uint16 as []byte +func utf16ToBuf(buf []uint16) []byte { + sl := struct { + addr *byte + len int + cap int + }{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2} + return *(*[]byte)(unsafe.Pointer(&sl)) +} + +func wcslen(str []uint16) int { + for i := 0; i < len(str); i++ { + if str[i] == 0 { + return i + } + } + return len(str) +} + +// DeviceRegistryProperty method retrieves a specified Plug and Play device property. +func (deviceInfoSet DevInfo) DeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP) (interface{}, error) { + return SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property) +} + +//sys setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW + +// SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device. +func SetupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error { + return setupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &propertyBuffers[0], uint32(len(propertyBuffers))) +} + +// SetDeviceRegistryProperty function sets a Plug and Play device property for a device. +func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error { + return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers) +} + +// SetDeviceRegistryPropertyString method sets a Plug and Play device property string for a device. +func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error { + str16, err := UTF16FromString(str) + if err != nil { + return err + } + err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0))) + runtime.KeepAlive(str16) + return err +} + +//sys setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW + +// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element. +func SetupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DevInstallParams, error) { + params := &DevInstallParams{} + params.size = uint32(unsafe.Sizeof(*params)) + + return params, setupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData, params) +} + +// DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) DeviceInstallParams(deviceInfoData *DevInfoData) (*DevInstallParams, error) { + return SetupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData) +} + +//sys setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceInstanceIdW + +// SetupDiGetDeviceInstanceId function retrieves the instance ID of the device. +func SetupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (string, error) { + reqSize := uint32(1024) + for { + buf := make([]uint16, reqSize) + err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return "", err + } + return UTF16ToString(buf), nil + } +} + +// DeviceInstanceID method retrieves the instance ID of the device. +func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) { + return SetupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData) +} + +// SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element. +//sys SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW + +// ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) ClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) error { + return SetupDiGetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize, requiredSize) +} + +//sys SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW + +// SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) SetDeviceInstallParams(deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) error { + return SetupDiSetDeviceInstallParams(deviceInfoSet, deviceInfoData, deviceInstallParams) +} + +// SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element. +//sys SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW + +// SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) SetClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) error { + return SetupDiSetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize) +} + +//sys setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW + +// SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer. +func SetupDiClassNameFromGuidEx(classGUID *GUID, machineName string) (className string, err error) { + var classNameUTF16 [MAX_CLASS_NAME_LEN]uint16 + + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return + } + } + + err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0) + if err != nil { + return + } + + className = UTF16ToString(classNameUTF16[:]) + return +} + +//sys setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW + +// SetupDiClassGuidsFromNameEx function retrieves the GUIDs associated with the specified class name. This resulting list contains the classes currently installed on a local or remote computer. +func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]GUID, error) { + classNameUTF16, err := UTF16PtrFromString(className) + if err != nil { + return nil, err + } + + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return nil, err + } + } + + reqSize := uint32(4) + for { + buf := make([]GUID, reqSize) + err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return nil, err + } + return buf[:reqSize], nil + } +} + +//sys setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice + +// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set. +func SetupDiGetSelectedDevice(deviceInfoSet DevInfo) (*DevInfoData, error) { + data := &DevInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiGetSelectedDevice(deviceInfoSet, data) +} + +// SelectedDevice method retrieves the selected device information element in a device information set. +func (deviceInfoSet DevInfo) SelectedDevice() (*DevInfoData, error) { + return SetupDiGetSelectedDevice(deviceInfoSet) +} + +// SetupDiSetSelectedDevice function sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard. +//sys SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice + +// SetSelectedDevice method sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard. +func (deviceInfoSet DevInfo) SetSelectedDevice(deviceInfoData *DevInfoData) error { + return SetupDiSetSelectedDevice(deviceInfoSet, deviceInfoData) +} + +//sys setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) = setupapi.SetupUninstallOEMInfW + +// SetupUninstallOEMInf uninstalls the specified driver. +func SetupUninstallOEMInf(infFileName string, flags SUOI) error { + infFileName16, err := UTF16PtrFromString(infFileName) + if err != nil { + return err + } + return setupUninstallOEMInf(infFileName16, flags, 0) +} + +//sys cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) = CfgMgr32.CM_MapCrToWin32Err + +//sys cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_List_SizeW +//sys cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_ListW + +func CM_Get_Device_Interface_List(deviceID string, interfaceClass *GUID, flags uint32) ([]string, error) { + deviceID16, err := UTF16PtrFromString(deviceID) + if err != nil { + return nil, err + } + var buf []uint16 + var buflen uint32 + for { + if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS { + return nil, ret + } + buf = make([]uint16, buflen) + if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS { + break + } else if ret != CR_BUFFER_SMALL { + return nil, ret + } + } + var interfaces []string + for i := 0; i < len(buf); { + j := i + wcslen(buf[i:]) + if i < j { + interfaces = append(interfaces, UTF16ToString(buf[i:j])) + } + i = j + 1 + } + if interfaces == nil { + return nil, ERROR_NO_SUCH_DEVICE_INTERFACE + } + return interfaces, nil +} + +//sys cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_DevNode_Status + +func CM_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) error { + ret := cm_Get_DevNode_Status(status, problemNumber, devInst, flags) + if ret == CR_SUCCESS { + return nil + } + return ret +} diff --git a/vendor/golang.org/x/sys/windows/str.go b/vendor/golang.org/x/sys/windows/str.go index 917cc2a..6a4f9ce 100644 --- a/vendor/golang.org/x/sys/windows/str.go +++ b/vendor/golang.org/x/sys/windows/str.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package windows diff --git a/vendor/golang.org/x/sys/windows/svc/event.go b/vendor/golang.org/x/sys/windows/svc/event.go deleted file mode 100644 index 0508e22..0000000 --- a/vendor/golang.org/x/sys/windows/svc/event.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -package svc - -import ( - "errors" - - "golang.org/x/sys/windows" -) - -// event represents auto-reset, initially non-signaled Windows event. -// It is used to communicate between go and asm parts of this package. -type event struct { - h windows.Handle -} - -func newEvent() (*event, error) { - h, err := windows.CreateEvent(nil, 0, 0, nil) - if err != nil { - return nil, err - } - return &event{h: h}, nil -} - -func (e *event) Close() error { - return windows.CloseHandle(e.h) -} - -func (e *event) Set() error { - return windows.SetEvent(e.h) -} - -func (e *event) Wait() error { - s, err := windows.WaitForSingleObject(e.h, windows.INFINITE) - switch s { - case windows.WAIT_OBJECT_0: - break - case windows.WAIT_FAILED: - return err - default: - return errors.New("unexpected result from WaitForSingleObject") - } - return nil -} diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/install.go b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go index c76a376..1179c38 100644 --- a/vendor/golang.org/x/sys/windows/svc/eventlog/install.go +++ b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package eventlog diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/log.go b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go index 46e5153..ad40c2f 100644 --- a/vendor/golang.org/x/sys/windows/svc/eventlog/log.go +++ b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows // Package eventlog implements access to Windows event log. -// package eventlog import ( @@ -30,11 +29,19 @@ func OpenRemote(host, source string) (*Log, error) { if source == "" { return nil, errors.New("Specify event log source") } - var s *uint16 + var hostPointer *uint16 if host != "" { - s = syscall.StringToUTF16Ptr(host) + var err error + hostPointer, err = syscall.UTF16PtrFromString(host) + if err != nil { + return nil, err + } } - h, err := windows.RegisterEventSource(s, syscall.StringToUTF16Ptr(source)) + sourcePointer, err := syscall.UTF16PtrFromString(source) + if err != nil { + return nil, err + } + h, err := windows.RegisterEventSource(hostPointer, sourcePointer) if err != nil { return nil, err } @@ -47,7 +54,11 @@ func (l *Log) Close() error { } func (l *Log) report(etype uint16, eid uint32, msg string) error { - ss := []*uint16{syscall.StringToUTF16Ptr(msg)} + msgPointer, err := syscall.UTF16PtrFromString(msg) + if err != nil { + return err + } + ss := []*uint16{msgPointer} return windows.ReportEvent(l.Handle, etype, 0, eid, 0, 1, 0, &ss[0], nil) } diff --git a/vendor/golang.org/x/sys/windows/svc/go12.c b/vendor/golang.org/x/sys/windows/svc/go12.c deleted file mode 100644 index 6f1be1f..0000000 --- a/vendor/golang.org/x/sys/windows/svc/go12.c +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows -// +build !go1.3 - -// copied from pkg/runtime -typedef unsigned int uint32; -typedef unsigned long long int uint64; -#ifdef _64BIT -typedef uint64 uintptr; -#else -typedef uint32 uintptr; -#endif - -// from sys_386.s or sys_amd64.s -void ·servicemain(void); - -void -·getServiceMain(uintptr *r) -{ - *r = (uintptr)·servicemain; -} diff --git a/vendor/golang.org/x/sys/windows/svc/go12.go b/vendor/golang.org/x/sys/windows/svc/go12.go deleted file mode 100644 index cd8b913..0000000 --- a/vendor/golang.org/x/sys/windows/svc/go12.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows -// +build !go1.3 - -package svc - -// from go12.c -func getServiceMain(r *uintptr) diff --git a/vendor/golang.org/x/sys/windows/svc/go13.go b/vendor/golang.org/x/sys/windows/svc/go13.go deleted file mode 100644 index 9d7f3ce..0000000 --- a/vendor/golang.org/x/sys/windows/svc/go13.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows -// +build go1.3 - -package svc - -import "unsafe" - -const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const - -// Should be a built-in for unsafe.Pointer? -func add(p unsafe.Pointer, x uintptr) unsafe.Pointer { - return unsafe.Pointer(uintptr(p) + x) -} - -// funcPC returns the entry PC of the function f. -// It assumes that f is a func value. Otherwise the behavior is undefined. -func funcPC(f interface{}) uintptr { - return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize)) -} - -// from sys_386.s and sys_amd64.s -func servicectlhandler(ctl uint32) uintptr -func servicemain(argc uint32, argv **uint16) - -func getServiceMain(r *uintptr) { - *r = funcPC(servicemain) -} diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/config.go b/vendor/golang.org/x/sys/windows/svc/mgr/config.go index 8431edb..ec01f96 100644 --- a/vendor/golang.org/x/sys/windows/svc/mgr/config.go +++ b/vendor/golang.org/x/sys/windows/svc/mgr/config.go @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package mgr import ( "syscall" - "unicode/utf16" "unsafe" "golang.org/x/sys/windows" @@ -46,32 +45,25 @@ type Config struct { DelayedAutoStart bool // the service is started after other auto-start services are started plus a short delay } -func toString(p *uint16) string { - if p == nil { - return "" - } - return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:]) -} - func toStringSlice(ps *uint16) []string { - if ps == nil { - return nil - } r := make([]string, 0) - for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(ps)); true; i++ { - if p[i] == 0 { - // empty string marks the end - if i <= from { - break - } - r = append(r, string(utf16.Decode(p[from:i]))) - from = i + 1 + p := unsafe.Pointer(ps) + + for { + s := windows.UTF16PtrToString((*uint16)(p)) + if len(s) == 0 { + break } + + r = append(r, s) + offset := unsafe.Sizeof(uint16(0)) * (uintptr)(len(s)+1) + p = unsafe.Pointer(uintptr(p) + offset) } + return r } -// Config retrieves service s configuration paramteres. +// Config retrieves service s configuration parameters. func (s *Service) Config() (Config, error) { var p *windows.QUERY_SERVICE_CONFIG n := uint32(1024) @@ -106,23 +98,34 @@ func (s *Service) Config() (Config, error) { delayedStart = true } + b, err = s.queryServiceConfig2(windows.SERVICE_CONFIG_SERVICE_SID_INFO) + if err != nil { + return Config{}, err + } + sidType := *(*uint32)(unsafe.Pointer(&b[0])) + return Config{ ServiceType: p.ServiceType, StartType: p.StartType, ErrorControl: p.ErrorControl, - BinaryPathName: toString(p.BinaryPathName), - LoadOrderGroup: toString(p.LoadOrderGroup), + BinaryPathName: windows.UTF16PtrToString(p.BinaryPathName), + LoadOrderGroup: windows.UTF16PtrToString(p.LoadOrderGroup), TagId: p.TagId, Dependencies: toStringSlice(p.Dependencies), - ServiceStartName: toString(p.ServiceStartName), - DisplayName: toString(p.DisplayName), - Description: toString(p2.Description), + ServiceStartName: windows.UTF16PtrToString(p.ServiceStartName), + DisplayName: windows.UTF16PtrToString(p.DisplayName), + Description: windows.UTF16PtrToString(p2.Description), DelayedAutoStart: delayedStart, + SidType: sidType, }, nil } func updateDescription(handle windows.Handle, desc string) error { - d := windows.SERVICE_DESCRIPTION{Description: toPtr(desc)} + descPointer, err := toPtr(desc) + if err != nil { + return err + } + d := windows.SERVICE_DESCRIPTION{Description: descPointer} return windows.ChangeServiceConfig2(handle, windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d))) } @@ -142,10 +145,30 @@ func updateStartUp(handle windows.Handle, isDelayed bool) error { // UpdateConfig updates service s configuration parameters. func (s *Service) UpdateConfig(c Config) error { - err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType, - c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup), - nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), - toPtr(c.Password), toPtr(c.DisplayName)) + binaryPathNamePointer, err := toPtr(c.BinaryPathName) + if err != nil { + return err + } + loadOrderGroupPointer, err := toPtr(c.LoadOrderGroup) + if err != nil { + return err + } + serviceStartNamePointer, err := toPtr(c.ServiceStartName) + if err != nil { + return err + } + passwordPointer, err := toPtr(c.Password) + if err != nil { + return err + } + displayNamePointer, err := toPtr(c.DisplayName) + if err != nil { + return err + } + err = windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType, + c.ErrorControl, binaryPathNamePointer, loadOrderGroupPointer, + nil, toStringBlock(c.Dependencies), serviceStartNamePointer, + passwordPointer, displayNamePointer) if err != nil { return err } diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go b/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go index 33944d0..7475594 100644 --- a/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go +++ b/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows // Package mgr can be used to manage Windows service programs. // It can be used to install and remove them. It can also start, // stop and pause them. The package can query / change current // service state and config parameters. -// package mgr import ( @@ -35,7 +34,11 @@ func Connect() (*Mgr, error) { func ConnectRemote(host string) (*Mgr, error) { var s *uint16 if host != "" { - s = syscall.StringToUTF16Ptr(host) + var err error + s, err = syscall.UTF16PtrFromString(host) + if err != nil { + return nil, err + } } h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS) if err != nil { @@ -73,17 +76,17 @@ func (m *Mgr) LockStatus() (*LockStatus, error) { status := &LockStatus{ IsLocked: lockStatus.IsLocked != 0, Age: time.Duration(lockStatus.LockDuration) * time.Second, - Owner: windows.UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(lockStatus.LockOwner))[:]), + Owner: windows.UTF16PtrToString(lockStatus.LockOwner), } return status, nil } } -func toPtr(s string) *uint16 { +func toPtr(s string) (*uint16, error) { if len(s) == 0 { - return nil + return nil, nil } - return syscall.StringToUTF16Ptr(s) + return syscall.UTF16PtrFromString(s) } // toStringBlock terminates strings in ss with 0, and then @@ -116,9 +119,6 @@ func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Se if c.StartType == 0 { c.StartType = StartManual } - if c.ErrorControl == 0 { - c.ErrorControl = ErrorNormal - } if c.ServiceType == 0 { c.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS } @@ -126,10 +126,34 @@ func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Se for _, v := range args { s += " " + syscall.EscapeArg(v) } - h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName), + namePointer, err := toPtr(name) + if err != nil { + return nil, err + } + displayNamePointer, err := toPtr(c.DisplayName) + if err != nil { + return nil, err + } + sPointer, err := toPtr(s) + if err != nil { + return nil, err + } + loadOrderGroupPointer, err := toPtr(c.LoadOrderGroup) + if err != nil { + return nil, err + } + serviceStartNamePointer, err := toPtr(c.ServiceStartName) + if err != nil { + return nil, err + } + passwordPointer, err := toPtr(c.Password) + if err != nil { + return nil, err + } + h, err := windows.CreateService(m.Handle, namePointer, displayNamePointer, windows.SERVICE_ALL_ACCESS, c.ServiceType, - c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup), - nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password)) + c.StartType, c.ErrorControl, sPointer, loadOrderGroupPointer, + nil, toStringBlock(c.Dependencies), serviceStartNamePointer, passwordPointer) if err != nil { return nil, err } @@ -163,7 +187,12 @@ func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Se // OpenService retrieves access to service name, so it can // be interrogated and controlled. func (m *Mgr) OpenService(name string) (*Service, error) { - h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS) + namePointer, err := syscall.UTF16PtrFromString(name) + if err != nil { + return nil, err + } + + h, err := windows.OpenService(m.Handle, namePointer, windows.SERVICE_ALL_ACCESS) if err != nil { return nil, err } @@ -201,10 +230,11 @@ func (m *Mgr) ListServices() ([]string, error) { if servicesReturned == 0 { return nil, nil } - services := (*[1 << 20]windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0]))[:servicesReturned] + services := unsafe.Slice((*windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0])), int(servicesReturned)) + var names []string for _, s := range services { - name := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(s.ServiceName))[:]) + name := windows.UTF16PtrToString(s.ServiceName) names = append(names, name) } return names, nil diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go index 71ce2b8..1a07374 100644 --- a/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go +++ b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package mgr @@ -68,8 +68,8 @@ func (s *Service) RecoveryActions() ([]RecoveryAction, error) { return nil, err } + actions := unsafe.Slice(p.Actions, int(p.ActionsCount)) var recoveryActions []RecoveryAction - actions := (*[1024]windows.SC_ACTION)(unsafe.Pointer(p.Actions))[:p.ActionsCount] for _, action := range actions { recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond}) } @@ -99,8 +99,13 @@ func (s *Service) ResetPeriod() (uint32, error) { // SetRebootMessage sets service s reboot message. // If msg is "", the reboot message is deleted and no message is broadcast. func (s *Service) SetRebootMessage(msg string) error { + msgPointer, err := syscall.UTF16PtrFromString(msg) + if err != nil { + return err + } + rActions := windows.SERVICE_FAILURE_ACTIONS{ - RebootMsg: syscall.StringToUTF16Ptr(msg), + RebootMsg: msgPointer, } return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) } @@ -112,14 +117,19 @@ func (s *Service) RebootMessage() (string, error) { return "", err } p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) - return toString(p.RebootMsg), nil + return windows.UTF16PtrToString(p.RebootMsg), nil } // SetRecoveryCommand sets the command line of the process to execute in response to the RunCommand service controller action. // If cmd is "", the command is deleted and no program is run when the service fails. func (s *Service) SetRecoveryCommand(cmd string) error { + cmdPointer, err := syscall.UTF16PtrFromString(cmd) + if err != nil { + return err + } + rActions := windows.SERVICE_FAILURE_ACTIONS{ - Command: syscall.StringToUTF16Ptr(cmd), + Command: cmdPointer, } return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) } @@ -131,5 +141,32 @@ func (s *Service) RecoveryCommand() (string, error) { return "", err } p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) - return toString(p.Command), nil + return windows.UTF16PtrToString(p.Command), nil +} + +// SetRecoveryActionsOnNonCrashFailures sets the failure actions flag. If the +// flag is set to false, recovery actions will only be performed if the service +// terminates without reporting a status of SERVICE_STOPPED. If the flag is set +// to true, recovery actions are also performed if the service stops with a +// nonzero exit code. +func (s *Service) SetRecoveryActionsOnNonCrashFailures(flag bool) error { + var setting windows.SERVICE_FAILURE_ACTIONS_FLAG + if flag { + setting.FailureActionsOnNonCrashFailures = 1 + } + return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, (*byte)(unsafe.Pointer(&setting))) +} + +// RecoveryActionsOnNonCrashFailures returns the current value of the failure +// actions flag. If the flag is set to false, recovery actions will only be +// performed if the service terminates without reporting a status of +// SERVICE_STOPPED. If the flag is set to true, recovery actions are also +// performed if the service stops with a nonzero exit code. +func (s *Service) RecoveryActionsOnNonCrashFailures() (bool, error) { + b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) + if err != nil { + return false, err + } + p := (*windows.SERVICE_FAILURE_ACTIONS_FLAG)(unsafe.Pointer(&b[0])) + return p.FailureActionsOnNonCrashFailures != 0, nil } diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/service.go b/vendor/golang.org/x/sys/windows/svc/mgr/service.go index ded1c7a..9f59eab 100644 --- a/vendor/golang.org/x/sys/windows/svc/mgr/service.go +++ b/vendor/golang.org/x/sys/windows/svc/mgr/service.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package mgr @@ -14,8 +14,6 @@ import ( "golang.org/x/sys/windows/svc" ) -// TODO(brainman): Use EnumDependentServices to enumerate dependent services. - // Service is used to access Windows service. type Service struct { Name string @@ -39,24 +37,36 @@ func (s *Service) Start(args ...string) error { if len(args) > 0 { vs := make([]*uint16, len(args)) for i := range vs { - vs[i] = syscall.StringToUTF16Ptr(args[i]) + argPointer, err := syscall.UTF16PtrFromString(args[i]) + if err != nil { + return err + } + vs[i] = argPointer } p = &vs[0] } return windows.StartService(s.Handle, uint32(len(args)), p) } -// Control sends state change request c to the servce s. +// Control sends state change request c to the service s. It returns the most +// recent status the service reported to the service control manager, and an +// error if the state change request was not accepted. +// Note that the returned service status is only set if the status change +// request succeeded, or if it failed with error ERROR_INVALID_SERVICE_CONTROL, +// ERROR_SERVICE_CANNOT_ACCEPT_CTRL, or ERROR_SERVICE_NOT_ACTIVE. func (s *Service) Control(c svc.Cmd) (svc.Status, error) { var t windows.SERVICE_STATUS err := windows.ControlService(s.Handle, uint32(c), &t) - if err != nil { + if err != nil && + err != windows.ERROR_INVALID_SERVICE_CONTROL && + err != windows.ERROR_SERVICE_CANNOT_ACCEPT_CTRL && + err != windows.ERROR_SERVICE_NOT_ACTIVE { return svc.Status{}, err } return svc.Status{ State: svc.State(t.CurrentState), Accepts: svc.Accepted(t.ControlsAccepted), - }, nil + }, err } // Query returns current status of service s. @@ -68,8 +78,51 @@ func (s *Service) Query() (svc.Status, error) { return svc.Status{}, err } return svc.Status{ - State: svc.State(t.CurrentState), - Accepts: svc.Accepted(t.ControlsAccepted), - ProcessId: t.ProcessId, + State: svc.State(t.CurrentState), + Accepts: svc.Accepted(t.ControlsAccepted), + ProcessId: t.ProcessId, + Win32ExitCode: t.Win32ExitCode, + ServiceSpecificExitCode: t.ServiceSpecificExitCode, }, nil } + +// ListDependentServices returns the names of the services dependent on service s, which match the given status. +func (s *Service) ListDependentServices(status svc.ActivityStatus) ([]string, error) { + var bytesNeeded, returnedServiceCount uint32 + var services []windows.ENUM_SERVICE_STATUS + for { + var servicesPtr *windows.ENUM_SERVICE_STATUS + if len(services) > 0 { + servicesPtr = &services[0] + } + allocatedBytes := uint32(len(services)) * uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) + err := windows.EnumDependentServices(s.Handle, uint32(status), servicesPtr, allocatedBytes, &bytesNeeded, + &returnedServiceCount) + if err == nil { + break + } + if err != syscall.ERROR_MORE_DATA { + return nil, err + } + if bytesNeeded <= allocatedBytes { + return nil, err + } + // ERROR_MORE_DATA indicates the provided buffer was too small, run the call again after resizing the buffer + requiredSliceLen := bytesNeeded / uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) + if bytesNeeded%uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) != 0 { + requiredSliceLen += 1 + } + services = make([]windows.ENUM_SERVICE_STATUS, requiredSliceLen) + } + if returnedServiceCount == 0 { + return nil, nil + } + + // The slice mutated by EnumDependentServices may have a length greater than returnedServiceCount, any elements + // past that should be ignored. + var dependents []string + for i := 0; i < int(returnedServiceCount); i++ { + dependents = append(dependents, windows.UTF16PtrToString(services[i].ServiceName)) + } + return dependents, nil +} diff --git a/vendor/golang.org/x/sys/windows/svc/security.go b/vendor/golang.org/x/sys/windows/svc/security.go index 6fbc923..6a1f3c6 100644 --- a/vendor/golang.org/x/sys/windows/svc/security.go +++ b/vendor/golang.org/x/sys/windows/svc/security.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows package svc import ( + "strings" "unsafe" "golang.org/x/sys/windows" @@ -25,6 +26,8 @@ func allocSid(subAuth0 uint32) (*windows.SID, error) { // IsAnInteractiveSession determines if calling process is running interactively. // It queries the process token for membership in the Interactive group. // http://stackoverflow.com/questions/2668851/how-do-i-detect-that-my-application-is-running-as-service-or-in-an-interactive-s +// +// Deprecated: Use IsWindowsService instead. func IsAnInteractiveSession() (bool, error) { interSid, err := allocSid(windows.SECURITY_INTERACTIVE_RID) if err != nil { @@ -48,9 +51,8 @@ func IsAnInteractiveSession() (bool, error) { if err != nil { return false, err } - p := unsafe.Pointer(&gs.Groups[0]) - groups := (*[2 << 20]windows.SIDAndAttributes)(p)[:gs.GroupCount] - for _, g := range groups { + + for _, g := range gs.AllGroups() { if windows.EqualSid(g.Sid, interSid) { return true, nil } @@ -60,3 +62,39 @@ func IsAnInteractiveSession() (bool, error) { } return false, nil } + +// IsWindowsService reports whether the process is currently executing +// as a Windows service. +func IsWindowsService() (bool, error) { + // The below technique looks a bit hairy, but it's actually + // exactly what the .NET framework does for the similarly named function: + // https://github.com/dotnet/extensions/blob/f4066026ca06984b07e90e61a6390ac38152ba93/src/Hosting/WindowsServices/src/WindowsServiceHelpers.cs#L26-L31 + // Specifically, it looks up whether the parent process has session ID zero + // and is called "services". + + var currentProcess windows.PROCESS_BASIC_INFORMATION + infoSize := uint32(unsafe.Sizeof(currentProcess)) + err := windows.NtQueryInformationProcess(windows.CurrentProcess(), windows.ProcessBasicInformation, unsafe.Pointer(¤tProcess), infoSize, &infoSize) + if err != nil { + return false, err + } + var parentProcess *windows.SYSTEM_PROCESS_INFORMATION + for infoSize = uint32((unsafe.Sizeof(*parentProcess) + unsafe.Sizeof(uintptr(0))) * 1024); ; { + parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(&make([]byte, infoSize)[0])) + err = windows.NtQuerySystemInformation(windows.SystemProcessInformation, unsafe.Pointer(parentProcess), infoSize, &infoSize) + if err == nil { + break + } else if err != windows.STATUS_INFO_LENGTH_MISMATCH { + return false, err + } + } + for ; ; parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(uintptr(unsafe.Pointer(parentProcess)) + uintptr(parentProcess.NextEntryOffset))) { + if parentProcess.UniqueProcessID == currentProcess.InheritedFromUniqueProcessId { + return parentProcess.SessionID == 0 && strings.EqualFold("services.exe", parentProcess.ImageName.String()), nil + } + if parentProcess.NextEntryOffset == 0 { + break + } + } + return false, nil +} diff --git a/vendor/golang.org/x/sys/windows/svc/service.go b/vendor/golang.org/x/sys/windows/svc/service.go index ee3d696..a9b1c19 100644 --- a/vendor/golang.org/x/sys/windows/svc/service.go +++ b/vendor/golang.org/x/sys/windows/svc/service.go @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows // Package svc provides everything required to build Windows service. -// package svc import ( "errors" - "runtime" - "syscall" + "sync" "unsafe" "golang.org/x/sys/windows" @@ -49,6 +47,7 @@ const ( HardwareProfileChange = Cmd(windows.SERVICE_CONTROL_HARDWAREPROFILECHANGE) PowerEvent = Cmd(windows.SERVICE_CONTROL_POWEREVENT) SessionChange = Cmd(windows.SERVICE_CONTROL_SESSIONCHANGE) + PreShutdown = Cmd(windows.SERVICE_CONTROL_PRESHUTDOWN) ) // Accepted is used to describe commands accepted by the service. @@ -64,17 +63,40 @@ const ( AcceptHardwareProfileChange = Accepted(windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE) AcceptPowerEvent = Accepted(windows.SERVICE_ACCEPT_POWEREVENT) AcceptSessionChange = Accepted(windows.SERVICE_ACCEPT_SESSIONCHANGE) + AcceptPreShutdown = Accepted(windows.SERVICE_ACCEPT_PRESHUTDOWN) +) + +// ActivityStatus allows for services to be selected based on active and inactive categories of service state. +type ActivityStatus uint32 + +const ( + Active = ActivityStatus(windows.SERVICE_ACTIVE) + Inactive = ActivityStatus(windows.SERVICE_INACTIVE) + AnyActivity = ActivityStatus(windows.SERVICE_STATE_ALL) ) // Status combines State and Accepted commands to fully describe running service. type Status struct { - State State - Accepts Accepted - CheckPoint uint32 // used to report progress during a lengthy operation - WaitHint uint32 // estimated time required for a pending operation, in milliseconds - ProcessId uint32 // if the service is running, the process identifier of it, and otherwise zero + State State + Accepts Accepted + CheckPoint uint32 // used to report progress during a lengthy operation + WaitHint uint32 // estimated time required for a pending operation, in milliseconds + ProcessId uint32 // if the service is running, the process identifier of it, and otherwise zero + Win32ExitCode uint32 // set if the service has exited with a win32 exit code + ServiceSpecificExitCode uint32 // set if the service has exited with a service-specific exit code } +// StartReason is the reason that the service was started. +type StartReason uint32 + +const ( + StartReasonDemand = StartReason(windows.SERVICE_START_REASON_DEMAND) + StartReasonAuto = StartReason(windows.SERVICE_START_REASON_AUTO) + StartReasonTrigger = StartReason(windows.SERVICE_START_REASON_TRIGGER) + StartReasonRestartOnFailure = StartReason(windows.SERVICE_START_REASON_RESTART_ON_FAILURE) + StartReasonDelayedAuto = StartReason(windows.SERVICE_START_REASON_DELAYEDAUTO) +) + // ChangeRequest is sent to the service Handler to request service status change. type ChangeRequest struct { Cmd Cmd @@ -86,7 +108,6 @@ type ChangeRequest struct { // Handler is the interface that must be implemented to build Windows service. type Handler interface { - // Execute will be called by the package code at the start of // the service, and the service will exit once Execute completes. // Inside Execute you must read service change requests from r and @@ -101,28 +122,6 @@ type Handler interface { Execute(args []string, r <-chan ChangeRequest, s chan<- Status) (svcSpecificEC bool, exitCode uint32) } -var ( - // These are used by asm code. - goWaitsH uintptr - cWaitsH uintptr - ssHandle uintptr - sName *uint16 - sArgc uintptr - sArgv **uint16 - ctlHandlerExProc uintptr - cSetEvent uintptr - cWaitForSingleObject uintptr - cRegisterServiceCtrlHandlerExW uintptr -) - -func init() { - k := windows.NewLazySystemDLL("kernel32.dll") - cSetEvent = k.NewProc("SetEvent").Addr() - cWaitForSingleObject = k.NewProc("WaitForSingleObject").Addr() - a := windows.NewLazySystemDLL("advapi32.dll") - cRegisterServiceCtrlHandlerExW = a.NewProc("RegisterServiceCtrlHandlerExW").Addr() -} - type ctlEvent struct { cmd Cmd eventType uint32 @@ -133,36 +132,10 @@ type ctlEvent struct { // service provides access to windows service api. type service struct { - name string - h windows.Handle - cWaits *event - goWaits *event - c chan ctlEvent - handler Handler -} - -func newService(name string, handler Handler) (*service, error) { - var s service - var err error - s.name = name - s.c = make(chan ctlEvent) - s.handler = handler - s.cWaits, err = newEvent() - if err != nil { - return nil, err - } - s.goWaits, err = newEvent() - if err != nil { - s.cWaits.Close() - return nil, err - } - return &s, nil -} - -func (s *service) close() error { - s.cWaits.Close() - s.goWaits.Close() - return nil + namePointer *uint16 + h windows.Handle + c chan ctlEvent + handler Handler } type exitCode struct { @@ -201,6 +174,9 @@ func (s *service) updateStatus(status *Status, ec *exitCode) error { if status.Accepts&AcceptSessionChange != 0 { t.ControlsAccepted |= windows.SERVICE_ACCEPT_SESSIONCHANGE } + if status.Accepts&AcceptPreShutdown != 0 { + t.ControlsAccepted |= windows.SERVICE_ACCEPT_PRESHUTDOWN + } if ec.errno == 0 { t.Win32ExitCode = windows.NO_ERROR t.ServiceSpecificExitCode = windows.NO_ERROR @@ -216,18 +192,38 @@ func (s *service) updateStatus(status *Status, ec *exitCode) error { return windows.SetServiceStatus(s.h, &t) } -const ( - sysErrSetServiceStatusFailed = uint32(syscall.APPLICATION_ERROR) + iota - sysErrNewThreadInCallback +var ( + initCallbacks sync.Once + ctlHandlerCallback uintptr + serviceMainCallback uintptr ) -func (s *service) run() { - s.goWaits.Wait() - s.h = windows.Handle(ssHandle) - argv := (*[100]*int16)(unsafe.Pointer(sArgv))[:sArgc] - args := make([]string, len(argv)) - for i, a := range argv { - args[i] = syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(a))[:]) +func ctlHandler(ctl, evtype, evdata, context uintptr) uintptr { + e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: 123456} // Set context to 123456 to test issue #25660. + theService.c <- e + return 0 +} + +var theService service // This is, unfortunately, a global, which means only one service per process. + +// serviceMain is the entry point called by the service manager, registered earlier by +// the call to StartServiceCtrlDispatcher. +func serviceMain(argc uint32, argv **uint16) uintptr { + handle, err := windows.RegisterServiceCtrlHandlerEx(theService.namePointer, ctlHandlerCallback, 0) + if sysErr, ok := err.(windows.Errno); ok { + return uintptr(sysErr) + } else if err != nil { + return uintptr(windows.ERROR_UNKNOWN_EXCEPTION) + } + theService.h = handle + defer func() { + theService.h = 0 + }() + args16 := unsafe.Slice(argv, int(argc)) + + args := make([]string, len(args16)) + for i, a := range args16 { + args[i] = windows.UTF16PtrToString(a) } cmdsToHandler := make(chan ChangeRequest) @@ -235,7 +231,7 @@ func (s *service) run() { exitFromHandler := make(chan exitCode) go func() { - ss, errno := s.handler.Execute(args, cmdsToHandler, changesFromHandler) + ss, errno := theService.handler.Execute(args, cmdsToHandler, changesFromHandler) exitFromHandler <- exitCode{ss, errno} }() @@ -244,7 +240,7 @@ func (s *service) run() { CurrentStatus: Status{State: Stopped}, } var outch chan ChangeRequest - inch := s.c + inch := theService.c loop: for { select { @@ -260,14 +256,13 @@ loop: outcr.EventData = r.eventData outcr.Context = r.context case outch <- outcr: - inch = s.c + inch = theService.c outch = nil case c := <-changesFromHandler: - err := s.updateStatus(&c, &ec) + err := theService.updateStatus(&c, &ec) if err != nil { - // best suitable error number - ec.errno = sysErrSetServiceStatusFailed - if err2, ok := err.(syscall.Errno); ok { + ec.errno = uint32(windows.ERROR_EXCEPTION_IN_SERVICE) + if err2, ok := err.(windows.Errno); ok { ec.errno = uint32(err2) } break loop @@ -278,87 +273,49 @@ loop: } } - s.updateStatus(&Status{State: Stopped}, &ec) - s.cWaits.Set() -} + theService.updateStatus(&Status{State: Stopped}, &ec) -func newCallback(fn interface{}) (cb uintptr, err error) { - defer func() { - r := recover() - if r == nil { - return - } - cb = 0 - switch v := r.(type) { - case string: - err = errors.New(v) - case error: - err = v - default: - err = errors.New("unexpected panic in syscall.NewCallback") - } - }() - return syscall.NewCallback(fn), nil + return windows.NO_ERROR } -// BUG(brainman): There is no mechanism to run multiple services -// inside one single executable. Perhaps, it can be overcome by -// using RegisterServiceCtrlHandlerEx Windows api. - // Run executes service name by calling appropriate handler function. func Run(name string, handler Handler) error { - runtime.LockOSThread() - - tid := windows.GetCurrentThreadId() - - s, err := newService(name, handler) + // Check to make sure that the service name is valid. + namePointer, err := windows.UTF16PtrFromString(name) if err != nil { return err } - ctlHandler := func(ctl, evtype, evdata, context uintptr) uintptr { - e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: context} - // We assume that this callback function is running on - // the same thread as Run. Nowhere in MS documentation - // I could find statement to guarantee that. So putting - // check here to verify, otherwise things will go bad - // quickly, if ignored. - i := windows.GetCurrentThreadId() - if i != tid { - e.errno = sysErrNewThreadInCallback - } - s.c <- e - // Always return NO_ERROR (0) for now. - return windows.NO_ERROR - } - - var svcmain uintptr - getServiceMain(&svcmain) + initCallbacks.Do(func() { + ctlHandlerCallback = windows.NewCallback(ctlHandler) + serviceMainCallback = windows.NewCallback(serviceMain) + }) + theService.namePointer = namePointer + theService.handler = handler + theService.c = make(chan ctlEvent) t := []windows.SERVICE_TABLE_ENTRY{ - {ServiceName: syscall.StringToUTF16Ptr(s.name), ServiceProc: svcmain}, + {ServiceName: namePointer, ServiceProc: serviceMainCallback}, {ServiceName: nil, ServiceProc: 0}, } - - goWaitsH = uintptr(s.goWaits.h) - cWaitsH = uintptr(s.cWaits.h) - sName = t[0].ServiceName - ctlHandlerExProc, err = newCallback(ctlHandler) - if err != nil { - return err - } - - go s.run() - - err = windows.StartServiceCtrlDispatcher(&t[0]) - if err != nil { - return err - } - return nil + return windows.StartServiceCtrlDispatcher(&t[0]) } // StatusHandle returns service status handle. It is safe to call this function // from inside the Handler.Execute because then it is guaranteed to be set. -// This code will have to change once multiple services are possible per process. func StatusHandle() windows.Handle { - return windows.Handle(ssHandle) + return theService.h +} + +// DynamicStartReason returns the reason why the service was started. It is safe +// to call this function from inside the Handler.Execute because then it is +// guaranteed to be set. +func DynamicStartReason() (StartReason, error) { + var allocReason *uint32 + err := windows.QueryServiceDynamicInformation(theService.h, windows.SERVICE_DYNAMIC_INFORMATION_LEVEL_START_REASON, unsafe.Pointer(&allocReason)) + if err != nil { + return 0, err + } + reason := StartReason(*allocReason) + windows.LocalFree(windows.Handle(unsafe.Pointer(allocReason))) + return reason, nil } diff --git a/vendor/golang.org/x/sys/windows/svc/sys_386.s b/vendor/golang.org/x/sys/windows/svc/sys_386.s deleted file mode 100644 index c8a583d..0000000 --- a/vendor/golang.org/x/sys/windows/svc/sys_386.s +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -// func servicemain(argc uint32, argv **uint16) -TEXT ·servicemain(SB),7,$0 - MOVL argc+0(FP), AX - MOVL AX, ·sArgc(SB) - MOVL argv+4(FP), AX - MOVL AX, ·sArgv(SB) - - PUSHL BP - PUSHL BX - PUSHL SI - PUSHL DI - - SUBL $12, SP - - MOVL ·sName(SB), AX - MOVL AX, (SP) - MOVL $·servicectlhandler(SB), AX - MOVL AX, 4(SP) - // Set context to 123456 to test issue #25660. - MOVL $123456, 8(SP) - MOVL ·cRegisterServiceCtrlHandlerExW(SB), AX - MOVL SP, BP - CALL AX - MOVL BP, SP - CMPL AX, $0 - JE exit - MOVL AX, ·ssHandle(SB) - - MOVL ·goWaitsH(SB), AX - MOVL AX, (SP) - MOVL ·cSetEvent(SB), AX - MOVL SP, BP - CALL AX - MOVL BP, SP - - MOVL ·cWaitsH(SB), AX - MOVL AX, (SP) - MOVL $-1, AX - MOVL AX, 4(SP) - MOVL ·cWaitForSingleObject(SB), AX - MOVL SP, BP - CALL AX - MOVL BP, SP - -exit: - ADDL $12, SP - - POPL DI - POPL SI - POPL BX - POPL BP - - MOVL 0(SP), CX - ADDL $12, SP - JMP CX - -// I do not know why, but this seems to be the only way to call -// ctlHandlerProc on Windows 7. - -// func servicectlhandler(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr { -TEXT ·servicectlhandler(SB),7,$0 - MOVL ·ctlHandlerExProc(SB), CX - JMP CX diff --git a/vendor/golang.org/x/sys/windows/svc/sys_amd64.s b/vendor/golang.org/x/sys/windows/svc/sys_amd64.s deleted file mode 100644 index 2f7609c..0000000 --- a/vendor/golang.org/x/sys/windows/svc/sys_amd64.s +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -// func servicemain(argc uint32, argv **uint16) -TEXT ·servicemain(SB),7,$0 - MOVL CX, ·sArgc(SB) - MOVQ DX, ·sArgv(SB) - - SUBQ $32, SP // stack for the first 4 syscall params - - MOVQ ·sName(SB), CX - MOVQ $·servicectlhandler(SB), DX - // BUG(pastarmovj): Figure out a way to pass in context in R8. - // Set context to 123456 to test issue #25660. - MOVQ $123456, R8 - MOVQ ·cRegisterServiceCtrlHandlerExW(SB), AX - CALL AX - CMPQ AX, $0 - JE exit - MOVQ AX, ·ssHandle(SB) - - MOVQ ·goWaitsH(SB), CX - MOVQ ·cSetEvent(SB), AX - CALL AX - - MOVQ ·cWaitsH(SB), CX - MOVQ $4294967295, DX - MOVQ ·cWaitForSingleObject(SB), AX - CALL AX - -exit: - ADDQ $32, SP - RET - -// I do not know why, but this seems to be the only way to call -// ctlHandlerProc on Windows 7. - -// func ·servicectlhandler(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr { -TEXT ·servicectlhandler(SB),7,$0 - MOVQ ·ctlHandlerExProc(SB), AX - JMP AX diff --git a/vendor/golang.org/x/sys/windows/svc/sys_arm.s b/vendor/golang.org/x/sys/windows/svc/sys_arm.s deleted file mode 100644 index 33c692a..0000000 --- a/vendor/golang.org/x/sys/windows/svc/sys_arm.s +++ /dev/null @@ -1,38 +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. - -// +build windows - -#include "textflag.h" - -// func servicemain(argc uint32, argv **uint16) -TEXT ·servicemain(SB),NOSPLIT|NOFRAME,$0 - MOVM.DB.W [R4, R14], (R13) // push {r4, lr} - MOVW R13, R4 - BIC $0x7, R13 // alignment for ABI - - MOVW R0, ·sArgc(SB) - MOVW R1, ·sArgv(SB) - - MOVW ·sName(SB), R0 - MOVW ·ctlHandlerExProc(SB), R1 - MOVW $0, R2 - MOVW ·cRegisterServiceCtrlHandlerExW(SB), R3 - BL (R3) - CMP $0, R0 - BEQ exit - MOVW R0, ·ssHandle(SB) - - MOVW ·goWaitsH(SB), R0 - MOVW ·cSetEvent(SB), R1 - BL (R1) - - MOVW ·cWaitsH(SB), R0 - MOVW $-1, R1 - MOVW ·cWaitForSingleObject(SB), R2 - BL (R2) - -exit: - MOVW R4, R13 // free extra stack space - MOVM.IA.W (R13), [R4, R15] // pop {r4, pc} diff --git a/vendor/golang.org/x/sys/windows/syscall.go b/vendor/golang.org/x/sys/windows/syscall.go index af828a9..e85ed6b 100644 --- a/vendor/golang.org/x/sys/windows/syscall.go +++ b/vendor/golang.org/x/sys/windows/syscall.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows +//go:build windows // Package windows contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and @@ -25,17 +25,18 @@ package windows // import "golang.org/x/sys/windows" import ( + "bytes" + "strings" "syscall" + "unsafe" ) // ByteSliceFromString returns a NUL-terminated slice of bytes // containing the text of s. If s contains a NUL byte at any // location, it returns (nil, syscall.EINVAL). func ByteSliceFromString(s string) ([]byte, error) { - for i := 0; i < len(s); i++ { - if s[i] == 0 { - return nil, syscall.EINVAL - } + if strings.IndexByte(s, 0) != -1 { + return nil, syscall.EINVAL } a := make([]byte, len(s)+1) copy(a, s) @@ -53,6 +54,35 @@ func BytePtrFromString(s string) (*byte, error) { return &a[0], nil } +// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any +// bytes after the NUL removed. +func ByteSliceToString(s []byte) string { + if i := bytes.IndexByte(s, 0); i != -1 { + s = s[:i] + } + return string(s) +} + +// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string. +// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated +// at a zero byte; if the zero byte is not present, the program may crash. +func BytePtrToString(p *byte) string { + if p == nil { + return "" + } + if *p == 0 { + return "" + } + + // Find NUL terminator. + n := 0 + for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + 1) + } + + return string(unsafe.Slice(p, n)) +} + // Single-word zero for use when we need a valid pointer to 0 bytes. // See mksyscall.pl. var _zero uintptr diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 053d664..69439df 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -8,6 +8,8 @@ package windows import ( errorspkg "errors" + "fmt" + "runtime" "sync" "syscall" "time" @@ -15,10 +17,14 @@ import ( "unsafe" ) -type Handle uintptr +type ( + Handle uintptr + HWND uintptr +) const ( InvalidHandle = ^Handle(0) + InvalidHWND = ^HWND(0) // Flags for DefineDosDevice. DDD_EXACT_MATCH_ON_REMOVE = 0x00000004 @@ -61,9 +67,8 @@ const ( LOCKFILE_FAIL_IMMEDIATELY = 0x00000001 LOCKFILE_EXCLUSIVE_LOCK = 0x00000002 - // Return values of SleepEx and other APC functions - STATUS_USER_APC = 0x000000C0 - WAIT_IO_COMPLETION = STATUS_USER_APC + // Return value of SleepEx and other APC functions + WAIT_IO_COMPLETION = 0x000000C0 ) // StringToUTF16 is deprecated. Use UTF16FromString instead. @@ -81,24 +86,13 @@ func StringToUTF16(s string) []uint16 { // s, with a terminating NUL added. If s contains a NUL byte at any // location, it returns (nil, syscall.EINVAL). func UTF16FromString(s string) ([]uint16, error) { - for i := 0; i < len(s); i++ { - if s[i] == 0 { - return nil, syscall.EINVAL - } - } - return utf16.Encode([]rune(s + "\x00")), nil + return syscall.UTF16FromString(s) } // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, -// with a terminating NUL removed. +// with a terminating NUL and any bytes after the NUL removed. func UTF16ToString(s []uint16) string { - for i, v := range s { - if v == 0 { - s = s[0:i] - break - } - } - return string(utf16.Decode(s)) + return syscall.UTF16ToString(s) } // StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead. @@ -117,18 +111,37 @@ func UTF16PtrFromString(s string) (*uint16, error) { return &a[0], nil } +// UTF16PtrToString takes a pointer to a UTF-16 sequence and returns the corresponding UTF-8 encoded string. +// If the pointer is nil, it returns the empty string. It assumes that the UTF-16 sequence is terminated +// at a zero word; if the zero word is not present, the program may crash. +func UTF16PtrToString(p *uint16) string { + if p == nil { + return "" + } + if *p == 0 { + return "" + } + + // Find NUL terminator. + n := 0 + for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p)) + } + return UTF16ToString(unsafe.Slice(p, n)) +} + func Getpagesize() int { return 4096 } // NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. // This is useful when interoperating with Windows code requiring callbacks. -// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. +// The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. func NewCallback(fn interface{}) uintptr { return syscall.NewCallback(fn) } // NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention. // This is useful when interoperating with Windows code requiring callbacks. -// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. +// The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. func NewCallbackCDecl(fn interface{}) uintptr { return syscall.NewCallbackCDecl(fn) } @@ -142,13 +155,26 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) //sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW //sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW +//sys SetDefaultDllDirectories(directoryFlags uint32) (err error) +//sys AddDllDirectory(path *uint16) (cookie uintptr, err error) = kernel32.AddDllDirectory +//sys RemoveDllDirectory(cookie uintptr) (err error) = kernel32.RemoveDllDirectory +//sys SetDllDirectory(path string) (err error) = kernel32.SetDllDirectoryW //sys GetVersion() (ver uint32, err error) //sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW //sys ExitProcess(exitcode uint32) //sys IsWow64Process(handle Handle, isWow64 *bool) (err error) = IsWow64Process +//sys IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint16) (err error) = IsWow64Process2? //sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW -//sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) -//sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) +//sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) [failretval==InvalidHandle] = CreateNamedPipeW +//sys ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error) +//sys DisconnectNamedPipe(pipe Handle) (err error) +//sys GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error) +//sys GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error) +//sys GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) +//sys GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW +//sys SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) = SetNamedPipeHandleState +//sys readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = ReadFile +//sys writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = WriteFile //sys GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) //sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff] //sys CloseHandle(handle Handle) (err error) @@ -159,6 +185,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys FindClose(handle Handle) (err error) //sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) //sys GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) +//sys SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error) //sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW //sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW //sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW @@ -171,21 +198,34 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW //sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW //sys SetEndOfFile(handle Handle) (err error) +//sys SetFileValidData(handle Handle, validDataLength int64) (err error) //sys GetSystemTimeAsFileTime(time *Filetime) //sys GetSystemTimePreciseAsFileTime(time *Filetime) //sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] -//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) -//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) -//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) +//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) +//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) +//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) //sys CancelIo(s Handle) (err error) //sys CancelIoEx(s Handle, o *Overlapped) (err error) //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW +//sys CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = advapi32.CreateProcessAsUserW +//sys initializeProcThreadAttributeList(attrlist *ProcThreadAttributeList, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList +//sys deleteProcThreadAttributeList(attrlist *ProcThreadAttributeList) = DeleteProcThreadAttributeList +//sys updateProcThreadAttribute(attrlist *ProcThreadAttributeList, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) //sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW +//sys GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId +//sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) [failretval==0] = user32.LoadKeyboardLayoutW +//sys UnloadKeyboardLayout(hkl Handle) (err error) = user32.UnloadKeyboardLayout +//sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout +//sys ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx +//sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow +//sys MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW +//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx //sys shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) = shell32.SHGetKnownFolderPath //sys TerminateProcess(handle Handle, exitcode uint32) (err error) //sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) -//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW +//sys getStartupInfo(startupInfo *StartupInfo) = GetStartupInfoW //sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) //sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) //sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] @@ -200,22 +240,26 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW //sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW //sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW +//sys ExpandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW //sys CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys getTickCount64() (ms uint64) = kernel32.GetTickCount64 +//sys GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) //sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) //sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW //sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW //sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW //sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW -//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW +//sys commandLineToArgv(cmd *uint16, argc *int32) (argv **uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW //sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0] +//sys LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error) //sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) //sys FlushFileBuffers(handle Handle) (err error) //sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW //sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW //sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW -//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW +//sys GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW +//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) [failretval == 0 || e1 == ERROR_ALREADY_EXISTS] = kernel32.CreateFileMappingW //sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) //sys UnmapViewOfFile(addr uintptr) (err error) //sys FlushViewOfFile(addr uintptr, length uintptr) (err error) @@ -224,30 +268,65 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) = kernel32.VirtualAlloc //sys VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) = kernel32.VirtualFree //sys VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) = kernel32.VirtualProtect +//sys VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) = kernel32.VirtualProtectEx +//sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery +//sys VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQueryEx +//sys ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) = kernel32.ReadProcessMemory +//sys WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) = kernel32.WriteProcessMemory //sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile //sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW +//sys FindFirstChangeNotification(path string, watchSubtree bool, notifyFilter uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.FindFirstChangeNotificationW +//sys FindNextChangeNotification(handle Handle) (err error) +//sys FindCloseChangeNotification(handle Handle) (err error) //sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW -//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore +//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore //sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore -//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore +//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore //sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore -//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain -//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain -//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext -//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext -//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy +//sys CertDeleteCertificateFromStore(certContext *CertContext) (err error) = crypt32.CertDeleteCertificateFromStore +//sys CertDuplicateCertificateContext(certContext *CertContext) (dupContext *CertContext) = crypt32.CertDuplicateCertificateContext +//sys PFXImportCertStore(pfx *CryptDataBlob, password *uint16, flags uint32) (store Handle, err error) = crypt32.PFXImportCertStore +//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain +//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain +//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext +//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext +//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy +//sys CertGetNameString(certContext *CertContext, nameType uint32, flags uint32, typePara unsafe.Pointer, name *uint16, size uint32) (chars uint32) = crypt32.CertGetNameStringW +//sys CertFindExtension(objId *byte, countExtensions uint32, extensions *CertExtension) (ret *CertExtension) = crypt32.CertFindExtension +//sys CertFindCertificateInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevCertContext *CertContext) (cert *CertContext, err error) [failretval==nil] = crypt32.CertFindCertificateInStore +//sys CertFindChainInStore(store Handle, certEncodingType uint32, findFlags uint32, findType uint32, findPara unsafe.Pointer, prevChainContext *CertChainContext) (certchain *CertChainContext, err error) [failretval==nil] = crypt32.CertFindChainInStore +//sys CryptAcquireCertificatePrivateKey(cert *CertContext, flags uint32, parameters unsafe.Pointer, cryptProvOrNCryptKey *Handle, keySpec *uint32, callerFreeProvOrNCryptKey *bool) (err error) = crypt32.CryptAcquireCertificatePrivateKey +//sys CryptQueryObject(objectType uint32, object unsafe.Pointer, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *Handle, msg *Handle, context *unsafe.Pointer) (err error) = crypt32.CryptQueryObject +//sys CryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) = crypt32.CryptDecodeObject +//sys CryptProtectData(dataIn *DataBlob, name *uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) = crypt32.CryptProtectData +//sys CryptUnprotectData(dataIn *DataBlob, name **uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) = crypt32.CryptUnprotectData +//sys WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) = wintrust.WinVerifyTrustEx //sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW //sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey //sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW //sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW //sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW +//sys RegNotifyChangeKeyValue(key Handle, watchSubtree bool, notifyFilter uint32, event Handle, asynchronous bool) (regerrno error) = advapi32.RegNotifyChangeKeyValue //sys GetCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId +//sys ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) = kernel32.ProcessIdToSessionId +//sys ClosePseudoConsole(console Handle) = kernel32.ClosePseudoConsole +//sys createPseudoConsole(size uint32, in Handle, out Handle, flags uint32, pconsole *Handle) (hr error) = kernel32.CreatePseudoConsole //sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode //sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode //sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo +//sys setConsoleCursorPosition(console Handle, position uint32) (err error) = kernel32.SetConsoleCursorPosition +//sys GetConsoleCP() (cp uint32, err error) = kernel32.GetConsoleCP +//sys GetConsoleOutputCP() (cp uint32, err error) = kernel32.GetConsoleOutputCP +//sys SetConsoleCP(cp uint32) (err error) = kernel32.SetConsoleCP +//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW +//sys GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) = kernel32.GetNumberOfConsoleInputEvents +//sys FlushConsoleInputBuffer(console Handle) (err error) = kernel32.FlushConsoleInputBuffer +//sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole //sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot +//sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW +//sys Module32Next(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32NextW //sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW //sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW //sys Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) @@ -257,14 +336,14 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW //sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW //sys GetCurrentThreadId() (id uint32) -//sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) = kernel32.CreateEventW -//sys CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateEventExW +//sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) [failretval == 0 || e1 == ERROR_ALREADY_EXISTS] = kernel32.CreateEventW +//sys CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) [failretval == 0 || e1 == ERROR_ALREADY_EXISTS] = kernel32.CreateEventExW //sys OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenEventW //sys SetEvent(event Handle) (err error) = kernel32.SetEvent //sys ResetEvent(event Handle) (err error) = kernel32.ResetEvent //sys PulseEvent(event Handle) (err error) = kernel32.PulseEvent -//sys CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) = kernel32.CreateMutexW -//sys CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateMutexExW +//sys CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) [failretval == 0 || e1 == ERROR_ALREADY_EXISTS] = kernel32.CreateMutexW +//sys CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) [failretval == 0 || e1 == ERROR_ALREADY_EXISTS] = kernel32.CreateMutexExW //sys OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenMutexW //sys ReleaseMutex(mutex Handle) (err error) = kernel32.ReleaseMutex //sys SleepEx(milliseconds uint32, alertable bool) (ret uint32) = kernel32.SleepEx @@ -275,11 +354,40 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys ResumeThread(thread Handle) (ret uint32, err error) [failretval==0xffffffff] = kernel32.ResumeThread //sys SetPriorityClass(process Handle, priorityClass uint32) (err error) = kernel32.SetPriorityClass //sys GetPriorityClass(process Handle) (ret uint32, err error) = kernel32.GetPriorityClass +//sys QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobObjectInformation uintptr, JobObjectInformationLength uint32, retlen *uint32) (err error) = kernel32.QueryInformationJobObject //sys SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) //sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) //sys GetProcessId(process Handle) (id uint32, err error) +//sys QueryFullProcessImageName(proc Handle, flags uint32, exeName *uint16, size *uint32) (err error) = kernel32.QueryFullProcessImageNameW //sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) //sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost +//sys GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) +//sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) +//sys ClearCommBreak(handle Handle) (err error) +//sys ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) +//sys EscapeCommFunction(handle Handle, dwFunc uint32) (err error) +//sys GetCommState(handle Handle, lpDCB *DCB) (err error) +//sys GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) +//sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) +//sys PurgeComm(handle Handle, dwFlags uint32) (err error) +//sys SetCommBreak(handle Handle) (err error) +//sys SetCommMask(handle Handle, dwEvtMask uint32) (err error) +//sys SetCommState(handle Handle, lpDCB *DCB) (err error) +//sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) +//sys SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) +//sys WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) +//sys GetActiveProcessorCount(groupNumber uint16) (ret uint32) +//sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32) +//sys EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) = user32.EnumWindows +//sys EnumChildWindows(hwnd HWND, enumFunc uintptr, param unsafe.Pointer) = user32.EnumChildWindows +//sys GetClassName(hwnd HWND, className *uint16, maxCount int32) (copied int32, err error) = user32.GetClassNameW +//sys GetDesktopWindow() (hwnd HWND) = user32.GetDesktopWindow +//sys GetForegroundWindow() (hwnd HWND) = user32.GetForegroundWindow +//sys IsWindow(hwnd HWND) (isWindow bool) = user32.IsWindow +//sys IsWindowUnicode(hwnd HWND) (isUnicode bool) = user32.IsWindowUnicode +//sys IsWindowVisible(hwnd HWND) (isVisible bool) = user32.IsWindowVisible +//sys GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) = user32.GetGUIThreadInfo +//sys GetLargePageMinimum() (size uintptr) // Volume Management Functions //sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW @@ -302,8 +410,6 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) [failretval==0] = QueryDosDeviceW //sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW //sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW -//sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW -//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx //sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW //sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters //sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters @@ -311,15 +417,59 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2 //sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid //sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree -//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion -//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers +//sys CoInitializeEx(reserved uintptr, coInit uint32) (ret error) = ole32.CoInitializeEx +//sys CoUninitialize() = ole32.CoUninitialize +//sys CoGetObject(name *uint16, bindOpts *BIND_OPTS3, guid *GUID, functionTable **uintptr) (ret error) = ole32.CoGetObject //sys getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetProcessPreferredUILanguages //sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages //sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages //sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages +//sys findResource(module Handle, name uintptr, resType uintptr) (resInfo Handle, err error) = kernel32.FindResourceW +//sys SizeofResource(module Handle, resInfo Handle) (size uint32, err error) = kernel32.SizeofResource +//sys LoadResource(module Handle, resInfo Handle) (resData Handle, err error) = kernel32.LoadResource +//sys LockResource(resData Handle) (addr uintptr, err error) = kernel32.LockResource + +// Version APIs +//sys GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32, err error) = version.GetFileVersionInfoSizeW +//sys GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) = version.GetFileVersionInfoW +//sys VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) = version.VerQueryValueW // Process Status API (PSAPI) -//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses +//sys enumProcesses(processIds *uint32, nSize uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses +//sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules +//sys EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) = psapi.EnumProcessModulesEx +//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation +//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW +//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW +//sys QueryWorkingSetEx(process Handle, pv uintptr, cb uint32) (err error) = psapi.QueryWorkingSetEx + +// NT Native APIs +//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb +//sys rtlGetVersion(info *OsVersionInfoEx) (ntstatus error) = ntdll.RtlGetVersion +//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers +//sys RtlGetCurrentPeb() (peb *PEB) = ntdll.RtlGetCurrentPeb +//sys RtlInitUnicodeString(destinationString *NTUnicodeString, sourceString *uint16) = ntdll.RtlInitUnicodeString +//sys RtlInitString(destinationString *NTString, sourceString *byte) = ntdll.RtlInitString +//sys NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile +//sys NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) = ntdll.NtCreateNamedPipeFile +//sys NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile +//sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus +//sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus +//sys RtlDefaultNpAcl(acl **ACL) (ntstatus error) = ntdll.RtlDefaultNpAcl +//sys NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQueryInformationProcess +//sys NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) = ntdll.NtSetInformationProcess +//sys NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQuerySystemInformation +//sys NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) = ntdll.NtSetSystemInformation +//sys RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) = ntdll.RtlAddFunctionTable +//sys RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) = ntdll.RtlDeleteFunctionTable + +// Desktop Window Manager API (Dwmapi) +//sys DwmGetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, size uint32) (ret error) = dwmapi.DwmGetWindowAttribute +//sys DwmSetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, size uint32) (ret error) = dwmapi.DwmSetWindowAttribute + +// Windows Multimedia API +//sys TimeBeginPeriod (period uint32) (err error) [failretval != 0] = winmm.timeBeginPeriod +//sys TimeEndPeriod (period uint32) (err error) [failretval != 0] = winmm.timeEndPeriod // syscall interface implementation for other packages @@ -357,11 +507,7 @@ func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0) proc = uintptr(r0) if proc == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -435,12 +581,6 @@ func Read(fd Handle, p []byte) (n int, err error) { } return 0, e } - if raceenabled { - if done > 0 { - raceWriteRange(unsafe.Pointer(&p[0]), int(done)) - } - raceAcquire(unsafe.Pointer(&ioSync)) - } return int(done), nil } @@ -453,12 +593,31 @@ func Write(fd Handle, p []byte) (n int, err error) { if e != nil { return 0, e } - if raceenabled && done > 0 { - raceReadRange(unsafe.Pointer(&p[0]), int(done)) - } return int(done), nil } +func ReadFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error { + err := readFile(fd, p, done, overlapped) + if raceenabled { + if *done > 0 { + raceWriteRange(unsafe.Pointer(&p[0]), int(*done)) + } + raceAcquire(unsafe.Pointer(&ioSync)) + } + return err +} + +func WriteFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + err := writeFile(fd, p, done, overlapped) + if raceenabled && *done > 0 { + raceReadRange(unsafe.Pointer(&p[0]), int(*done)) + } + return err +} + var ioSync int64 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) { @@ -497,7 +656,6 @@ var ( func getStdHandle(stdhandle uint32) (fd Handle) { r, _ := GetStdHandle(stdhandle) - CloseOnExec(r) return r } @@ -571,20 +729,12 @@ func DurationSinceBoot() time.Duration { } func Ftruncate(fd Handle, length int64) (err error) { - curoffset, e := Seek(fd, 0, 1) - if e != nil { - return e - } - defer Seek(fd, curoffset, 0) - _, e = Seek(fd, length, 0) - if e != nil { - return e + type _FILE_END_OF_FILE_INFO struct { + EndOfFile int64 } - e = SetEndOfFile(fd) - if e != nil { - return e - } - return nil + var info _FILE_END_OF_FILE_INFO + info.EndOfFile = length + return SetFileInformationByHandle(fd, FileEndOfFileInfo, (*byte)(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info))) } func Gettimeofday(tv *Timeval) (err error) { @@ -622,7 +772,7 @@ func Utimes(path string, tv []Timeval) (err error) { if e != nil { return e } - defer Close(h) + defer CloseHandle(h) a := NsecToFiletime(tv[0].Nanoseconds()) w := NsecToFiletime(tv[1].Nanoseconds()) return SetFileTime(h, nil, &a, &w) @@ -642,7 +792,7 @@ func UtimesNano(path string, ts []Timespec) (err error) { if e != nil { return e } - defer Close(h) + defer CloseHandle(h) a := NsecToFiletime(TimespecToNsec(ts[0])) w := NsecToFiletime(TimespecToNsec(ts[1])) return SetFileTime(h, nil, &a, &w) @@ -700,6 +850,9 @@ const socket_error = uintptr(^uint32(0)) //sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup //sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup //sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl +//sys WSALookupServiceBegin(querySet *WSAQUERYSET, flags uint32, handle *Handle) (err error) [failretval==socket_error] = ws2_32.WSALookupServiceBeginW +//sys WSALookupServiceNext(handle Handle, flags uint32, size *int32, querySet *WSAQUERYSET) (err error) [failretval==socket_error] = ws2_32.WSALookupServiceNextW +//sys WSALookupServiceEnd(handle Handle) (err error) [failretval==socket_error] = ws2_32.WSALookupServiceEnd //sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket //sys sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) [failretval==socket_error] = ws2_32.sendto //sys recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) [failretval==-1] = ws2_32.recvfrom @@ -718,6 +871,8 @@ const socket_error = uintptr(^uint32(0)) //sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend //sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom //sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo +//sys WSASocket(af int32, typ int32, protocol int32, protoInfo *WSAProtocolInfo, group uint32, flags uint32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.WSASocketW +//sys WSADuplicateSocket(s Handle, processID uint32, info *WSAProtocolInfo) (err error) [failretval!=0] = ws2_32.WSADuplicateSocketW //sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname //sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname //sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs @@ -731,9 +886,20 @@ const socket_error = uintptr(^uint32(0)) //sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo //sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes //sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW +//sys WSAGetOverlappedResult(h Handle, o *Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult //sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses //sys GetACP() (acp uint32) = kernel32.GetACP //sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar +//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx +//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex +//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2 +//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2 +//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry +//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable +//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange +//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2 +//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange +//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2 // For testing: clients can set this flag to force // creation of IPv6 sockets to return EAFNOSUPPORT. @@ -754,6 +920,17 @@ type RawSockaddrInet6 struct { Scope_id uint32 } +// RawSockaddrInet is a union that contains an IPv4, an IPv6 address, or an address family. See +// https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet. +// +// A [*RawSockaddrInet] may be converted to a [*RawSockaddrInet4] or [*RawSockaddrInet6] using +// unsafe, depending on the address family. +type RawSockaddrInet struct { + Family uint16 + Port uint16 + Data [6]uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -782,9 +959,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -804,9 +979,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -838,7 +1011,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { if n > 0 { sl += int32(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -847,6 +1021,32 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { return unsafe.Pointer(&sa.raw), sl, nil } +type RawSockaddrBth struct { + AddressFamily [2]byte + BtAddr [8]byte + ServiceClassId [16]byte + Port [4]byte +} + +type SockaddrBth struct { + BtAddr uint64 + ServiceClassId GUID + Port uint32 + + raw RawSockaddrBth +} + +func (sa *SockaddrBth) sockaddr() (unsafe.Pointer, int32, error) { + family := AF_BTH + sa.raw = RawSockaddrBth{ + AddressFamily: *(*[2]byte)(unsafe.Pointer(&family)), + BtAddr: *(*[8]byte)(unsafe.Pointer(&sa.BtAddr)), + Port: *(*[4]byte)(unsafe.Pointer(&sa.Port)), + ServiceClassId: *(*[16]byte)(unsafe.Pointer(&sa.ServiceClassId)), + } + return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil +} + func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { switch rsa.Addr.Family { case AF_UNIX: @@ -870,8 +1070,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { for n < len(pp.Path) && pp.Path[n] != 0 { n++ } - bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] - sa.Name = string(bytes) + sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) return sa, nil case AF_INET: @@ -879,9 +1078,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -890,9 +1087,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, syscall.EAFNOSUPPORT @@ -926,6 +1121,14 @@ func Connect(fd Handle, sa Sockaddr) (err error) { return connect(fd, ptr, n) } +func GetBestInterfaceEx(sa Sockaddr, pdwBestIfIndex *uint32) (err error) { + ptr, _, err := sa.sockaddr() + if err != nil { + return err + } + return getBestInterfaceEx(ptr, pdwBestIfIndex) +} + func Getsockname(fd Handle) (sa Sockaddr, err error) { var rsa RawSockaddrAny l := int32(unsafe.Sizeof(rsa)) @@ -953,9 +1156,13 @@ func Shutdown(fd Handle, how int) (err error) { } func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) { - rsa, l, err := to.sockaddr() - if err != nil { - return err + var rsa unsafe.Pointer + var l int32 + if to != nil { + rsa, l, err = to.sockaddr() + if err != nil { + return err + } } return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine) } @@ -1058,11 +1265,7 @@ func WSASendMsg(fd Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlap } r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.sendAddr, 6, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return err } @@ -1074,11 +1277,7 @@ func WSARecvMsg(fd Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *Overl } r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.recvAddr, 5, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(bytesReceived)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0) if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return err } @@ -1181,7 +1380,12 @@ type IPv6Mreq struct { Interface uint32 } -func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, syscall.EWINDOWS } +func GetsockoptInt(fd Handle, level, opt int) (int, error) { + v := int32(0) + l := int32(unsafe.Sizeof(v)) + err := Getsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), &l) + return int(v), err +} func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)} @@ -1191,13 +1395,26 @@ func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) } + func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) } + func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return syscall.EWINDOWS } +func EnumProcesses(processIds []uint32, bytesReturned *uint32) error { + // EnumProcesses syscall expects the size parameter to be in bytes, but the code generated with mksyscall uses + // the length of the processIds slice instead. Hence, this wrapper function is added to fix the discrepancy. + var p *uint32 + if len(processIds) > 0 { + p = &processIds[0] + } + size := uint32(len(processIds) * 4) + return enumProcesses(p, size, bytesReturned) +} + func Getpid() (pid int) { return int(GetCurrentProcessId()) } func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) { @@ -1378,7 +1595,7 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e return "", err } defer CoTaskMemFree(unsafe.Pointer(p)) - return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil + return UTF16PtrToString(p), nil } // RtlGetVersion returns the version of the underlying operating system, ignoring @@ -1452,3 +1669,283 @@ func getUILanguages(flags uint32, f func(flags uint32, numLanguages *uint32, buf return languages, nil } } + +func SetConsoleCursorPosition(console Handle, position Coord) error { + return setConsoleCursorPosition(console, *((*uint32)(unsafe.Pointer(&position)))) +} + +func GetStartupInfo(startupInfo *StartupInfo) error { + getStartupInfo(startupInfo) + return nil +} + +func (s NTStatus) Errno() syscall.Errno { + return rtlNtStatusToDosErrorNoTeb(s) +} + +func langID(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) } + +func (s NTStatus) Error() string { + b := make([]uint16, 300) + n, err := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ARGUMENT_ARRAY, modntdll.Handle(), uint32(s), langID(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil) + if err != nil { + return fmt.Sprintf("NTSTATUS 0x%08x", uint32(s)) + } + // trim terminating \r and \n + for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { + } + return string(utf16.Decode(b[:n])) +} + +// NewNTUnicodeString returns a new NTUnicodeString structure for use with native +// NT APIs that work over the NTUnicodeString type. Note that most Windows APIs +// do not use NTUnicodeString, and instead UTF16PtrFromString should be used for +// the more common *uint16 string type. +func NewNTUnicodeString(s string) (*NTUnicodeString, error) { + s16, err := UTF16FromString(s) + if err != nil { + return nil, err + } + n := uint16(len(s16) * 2) + return &NTUnicodeString{ + Length: n - 2, // subtract 2 bytes for the NULL terminator + MaximumLength: n, + Buffer: &s16[0], + }, nil +} + +// Slice returns a uint16 slice that aliases the data in the NTUnicodeString. +func (s *NTUnicodeString) Slice() []uint16 { + // Note: this rounds the length down, if it happens + // to (incorrectly) be odd. Probably safer than rounding up. + return unsafe.Slice(s.Buffer, s.MaximumLength/2)[:s.Length/2] +} + +func (s *NTUnicodeString) String() string { + return UTF16ToString(s.Slice()) +} + +// NewNTString returns a new NTString structure for use with native +// NT APIs that work over the NTString type. Note that most Windows APIs +// do not use NTString, and instead UTF16PtrFromString should be used for +// the more common *uint16 string type. +func NewNTString(s string) (*NTString, error) { + var nts NTString + s8, err := BytePtrFromString(s) + if err != nil { + return nil, err + } + RtlInitString(&nts, s8) + return &nts, nil +} + +// Slice returns a byte slice that aliases the data in the NTString. +func (s *NTString) Slice() []byte { + slice := unsafe.Slice(s.Buffer, s.MaximumLength) + return slice[:s.Length] +} + +func (s *NTString) String() string { + return ByteSliceToString(s.Slice()) +} + +// FindResource resolves a resource of the given name and resource type. +func FindResource(module Handle, name, resType ResourceIDOrString) (Handle, error) { + var namePtr, resTypePtr uintptr + var name16, resType16 *uint16 + var err error + resolvePtr := func(i interface{}, keep **uint16) (uintptr, error) { + switch v := i.(type) { + case string: + *keep, err = UTF16PtrFromString(v) + if err != nil { + return 0, err + } + return uintptr(unsafe.Pointer(*keep)), nil + case ResourceID: + return uintptr(v), nil + } + return 0, errorspkg.New("parameter must be a ResourceID or a string") + } + namePtr, err = resolvePtr(name, &name16) + if err != nil { + return 0, err + } + resTypePtr, err = resolvePtr(resType, &resType16) + if err != nil { + return 0, err + } + resInfo, err := findResource(module, namePtr, resTypePtr) + runtime.KeepAlive(name16) + runtime.KeepAlive(resType16) + return resInfo, err +} + +func LoadResourceData(module, resInfo Handle) (data []byte, err error) { + size, err := SizeofResource(module, resInfo) + if err != nil { + return + } + resData, err := LoadResource(module, resInfo) + if err != nil { + return + } + ptr, err := LockResource(resData) + if err != nil { + return + } + data = unsafe.Slice((*byte)(unsafe.Pointer(ptr)), size) + return +} + +// PSAPI_WORKING_SET_EX_BLOCK contains extended working set information for a page. +type PSAPI_WORKING_SET_EX_BLOCK uint64 + +// Valid returns the validity of this page. +// If this bit is 1, the subsequent members are valid; otherwise they should be ignored. +func (b PSAPI_WORKING_SET_EX_BLOCK) Valid() bool { + return (b & 1) == 1 +} + +// ShareCount is the number of processes that share this page. The maximum value of this member is 7. +func (b PSAPI_WORKING_SET_EX_BLOCK) ShareCount() uint64 { + return b.intField(1, 3) +} + +// Win32Protection is the memory protection attributes of the page. For a list of values, see +// https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants +func (b PSAPI_WORKING_SET_EX_BLOCK) Win32Protection() uint64 { + return b.intField(4, 11) +} + +// Shared returns the shared status of this page. +// If this bit is 1, the page can be shared. +func (b PSAPI_WORKING_SET_EX_BLOCK) Shared() bool { + return (b & (1 << 15)) == 1 +} + +// Node is the NUMA node. The maximum value of this member is 63. +func (b PSAPI_WORKING_SET_EX_BLOCK) Node() uint64 { + return b.intField(16, 6) +} + +// Locked returns the locked status of this page. +// If this bit is 1, the virtual page is locked in physical memory. +func (b PSAPI_WORKING_SET_EX_BLOCK) Locked() bool { + return (b & (1 << 22)) == 1 +} + +// LargePage returns the large page status of this page. +// If this bit is 1, the page is a large page. +func (b PSAPI_WORKING_SET_EX_BLOCK) LargePage() bool { + return (b & (1 << 23)) == 1 +} + +// Bad returns the bad status of this page. +// If this bit is 1, the page is has been reported as bad. +func (b PSAPI_WORKING_SET_EX_BLOCK) Bad() bool { + return (b & (1 << 31)) == 1 +} + +// intField extracts an integer field in the PSAPI_WORKING_SET_EX_BLOCK union. +func (b PSAPI_WORKING_SET_EX_BLOCK) intField(start, length int) uint64 { + var mask PSAPI_WORKING_SET_EX_BLOCK + for pos := start; pos < start+length; pos++ { + mask |= (1 << pos) + } + + masked := b & mask + return uint64(masked >> start) +} + +// PSAPI_WORKING_SET_EX_INFORMATION contains extended working set information for a process. +type PSAPI_WORKING_SET_EX_INFORMATION struct { + // The virtual address. + VirtualAddress Pointer + // A PSAPI_WORKING_SET_EX_BLOCK union that indicates the attributes of the page at VirtualAddress. + VirtualAttributes PSAPI_WORKING_SET_EX_BLOCK +} + +// CreatePseudoConsole creates a windows pseudo console. +func CreatePseudoConsole(size Coord, in Handle, out Handle, flags uint32, pconsole *Handle) error { + // We need this wrapper to manually cast Coord to uint32. The autogenerated wrappers only + // accept arguments that can be casted to uintptr, and Coord can't. + return createPseudoConsole(*((*uint32)(unsafe.Pointer(&size))), in, out, flags, pconsole) +} + +// ResizePseudoConsole resizes the internal buffers of the pseudo console to the width and height specified in `size`. +func ResizePseudoConsole(pconsole Handle, size Coord) error { + // We need this wrapper to manually cast Coord to uint32. The autogenerated wrappers only + // accept arguments that can be casted to uintptr, and Coord can't. + return resizePseudoConsole(pconsole, *((*uint32)(unsafe.Pointer(&size)))) +} + +// DCB constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb. +const ( + CBR_110 = 110 + CBR_300 = 300 + CBR_600 = 600 + CBR_1200 = 1200 + CBR_2400 = 2400 + CBR_4800 = 4800 + CBR_9600 = 9600 + CBR_14400 = 14400 + CBR_19200 = 19200 + CBR_38400 = 38400 + CBR_57600 = 57600 + CBR_115200 = 115200 + CBR_128000 = 128000 + CBR_256000 = 256000 + + DTR_CONTROL_DISABLE = 0x00000000 + DTR_CONTROL_ENABLE = 0x00000010 + DTR_CONTROL_HANDSHAKE = 0x00000020 + + RTS_CONTROL_DISABLE = 0x00000000 + RTS_CONTROL_ENABLE = 0x00001000 + RTS_CONTROL_HANDSHAKE = 0x00002000 + RTS_CONTROL_TOGGLE = 0x00003000 + + NOPARITY = 0 + ODDPARITY = 1 + EVENPARITY = 2 + MARKPARITY = 3 + SPACEPARITY = 4 + + ONESTOPBIT = 0 + ONE5STOPBITS = 1 + TWOSTOPBITS = 2 +) + +// EscapeCommFunction constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-escapecommfunction. +const ( + SETXOFF = 1 + SETXON = 2 + SETRTS = 3 + CLRRTS = 4 + SETDTR = 5 + CLRDTR = 6 + SETBREAK = 8 + CLRBREAK = 9 +) + +// PurgeComm constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-purgecomm. +const ( + PURGE_TXABORT = 0x0001 + PURGE_RXABORT = 0x0002 + PURGE_TXCLEAR = 0x0004 + PURGE_RXCLEAR = 0x0008 +) + +// SetCommMask constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommmask. +const ( + EV_RXCHAR = 0x0001 + EV_RXFLAG = 0x0002 + EV_TXEMPTY = 0x0004 + EV_CTS = 0x0008 + EV_DSR = 0x0010 + EV_RLSD = 0x0020 + EV_BREAK = 0x0040 + EV_ERR = 0x0080 + EV_RING = 0x0100 +) diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 809fff0..6e4f50e 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -10,6 +10,10 @@ import ( "unsafe" ) +// NTStatus corresponds with NTSTATUS, error values returned by ntdll.dll and +// other native functions. +type NTStatus uint32 + const ( // Invented values to support what package os expects. O_RDONLY = 0x00000 @@ -61,10 +65,38 @@ var signals = [...]string{ 15: "terminated", } +// File flags for [os.OpenFile]. The O_ prefix is used to indicate +// that these flags are specific to the OpenFile function. const ( - FILE_LIST_DIRECTORY = 0x00000001 - FILE_APPEND_DATA = 0x00000004 + O_FILE_FLAG_OPEN_NO_RECALL = FILE_FLAG_OPEN_NO_RECALL + O_FILE_FLAG_OPEN_REPARSE_POINT = FILE_FLAG_OPEN_REPARSE_POINT + O_FILE_FLAG_SESSION_AWARE = FILE_FLAG_SESSION_AWARE + O_FILE_FLAG_POSIX_SEMANTICS = FILE_FLAG_POSIX_SEMANTICS + O_FILE_FLAG_BACKUP_SEMANTICS = FILE_FLAG_BACKUP_SEMANTICS + O_FILE_FLAG_DELETE_ON_CLOSE = FILE_FLAG_DELETE_ON_CLOSE + O_FILE_FLAG_SEQUENTIAL_SCAN = FILE_FLAG_SEQUENTIAL_SCAN + O_FILE_FLAG_RANDOM_ACCESS = FILE_FLAG_RANDOM_ACCESS + O_FILE_FLAG_NO_BUFFERING = FILE_FLAG_NO_BUFFERING + O_FILE_FLAG_OVERLAPPED = FILE_FLAG_OVERLAPPED + O_FILE_FLAG_WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH +) + +const ( + FILE_READ_DATA = 0x00000001 + FILE_READ_ATTRIBUTES = 0x00000080 + FILE_READ_EA = 0x00000008 + FILE_WRITE_DATA = 0x00000002 FILE_WRITE_ATTRIBUTES = 0x00000100 + FILE_WRITE_EA = 0x00000010 + FILE_APPEND_DATA = 0x00000004 + FILE_EXECUTE = 0x00000020 + + FILE_GENERIC_READ = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE + FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE + FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE + + FILE_LIST_DIRECTORY = 0x00000001 + FILE_TRAVERSE = 0x00000020 FILE_SHARE_READ = 0x00000001 FILE_SHARE_WRITE = 0x00000002 @@ -140,8 +172,14 @@ const ( MAX_PATH = 260 MAX_LONG_PATH = 32768 + MAX_MODULE_NAME32 = 255 + MAX_COMPUTERNAME_LENGTH = 15 + MAX_DHCPV6_DUID_LENGTH = 130 + + MAX_DNS_SUFFIX_STRING_LENGTH = 256 + TIME_ZONE_ID_UNKNOWN = 0 TIME_ZONE_ID_STANDARD = 1 @@ -154,6 +192,7 @@ const ( WAIT_FAILED = 0xFFFFFFFF // Access rights for process. + PROCESS_ALL_ACCESS = 0xFFFF PROCESS_CREATE_PROCESS = 0x0080 PROCESS_CREATE_THREAD = 0x0002 PROCESS_DUP_HANDLE = 0x0040 @@ -215,6 +254,19 @@ const ( INHERIT_PARENT_AFFINITY = 0x00010000 ) +const ( + // attributes for ProcThreadAttributeList + PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000 + PROC_THREAD_ATTRIBUTE_HANDLE_LIST = 0x00020002 + PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY = 0x00030003 + PROC_THREAD_ATTRIBUTE_PREFERRED_NODE = 0x00020004 + PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR = 0x00030005 + PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = 0x00020007 + PROC_THREAD_ATTRIBUTE_UMS_THREAD = 0x00030006 + PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL = 0x0002000b + PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x00020016 +) + const ( // flags for CreateToolhelp32Snapshot TH32CS_SNAPHEAPLIST = 0x01 @@ -227,7 +279,15 @@ const ( ) const ( - // filters for ReadDirectoryChangesW + // flags for EnumProcessModulesEx + LIST_MODULES_32BIT = 0x01 + LIST_MODULES_64BIT = 0x02 + LIST_MODULES_ALL = 0x03 + LIST_MODULES_DEFAULT = 0x00 +) + +const ( + // filters for ReadDirectoryChangesW and FindFirstChangeNotificationW FILE_NOTIFY_CHANGE_FILE_NAME = 0x001 FILE_NOTIFY_CHANGE_DIR_NAME = 0x002 FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x004 @@ -249,24 +309,27 @@ const ( const ( // wincrypt.h - PROV_RSA_FULL = 1 - PROV_RSA_SIG = 2 - PROV_DSS = 3 - PROV_FORTEZZA = 4 - PROV_MS_EXCHANGE = 5 - PROV_SSL = 6 - PROV_RSA_SCHANNEL = 12 - PROV_DSS_DH = 13 - PROV_EC_ECDSA_SIG = 14 - PROV_EC_ECNRA_SIG = 15 - PROV_EC_ECDSA_FULL = 16 - PROV_EC_ECNRA_FULL = 17 - PROV_DH_SCHANNEL = 18 - PROV_SPYRUS_LYNKS = 20 - PROV_RNG = 21 - PROV_INTEL_SEC = 22 - PROV_REPLACE_OWF = 23 - PROV_RSA_AES = 24 + /* certenrolld_begin -- PROV_RSA_*/ + PROV_RSA_FULL = 1 + PROV_RSA_SIG = 2 + PROV_DSS = 3 + PROV_FORTEZZA = 4 + PROV_MS_EXCHANGE = 5 + PROV_SSL = 6 + PROV_RSA_SCHANNEL = 12 + PROV_DSS_DH = 13 + PROV_EC_ECDSA_SIG = 14 + PROV_EC_ECNRA_SIG = 15 + PROV_EC_ECDSA_FULL = 16 + PROV_EC_ECNRA_FULL = 17 + PROV_DH_SCHANNEL = 18 + PROV_SPYRUS_LYNKS = 20 + PROV_RNG = 21 + PROV_INTEL_SEC = 22 + PROV_REPLACE_OWF = 23 + PROV_RSA_AES = 24 + + /* dwFlags definitions for CryptAcquireContext */ CRYPT_VERIFYCONTEXT = 0xF0000000 CRYPT_NEWKEYSET = 0x00000008 CRYPT_DELETEKEYSET = 0x00000010 @@ -274,6 +337,34 @@ const ( CRYPT_SILENT = 0x00000040 CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x00000080 + /* Flags for PFXImportCertStore */ + CRYPT_EXPORTABLE = 0x00000001 + CRYPT_USER_PROTECTED = 0x00000002 + CRYPT_USER_KEYSET = 0x00001000 + PKCS12_PREFER_CNG_KSP = 0x00000100 + PKCS12_ALWAYS_CNG_KSP = 0x00000200 + PKCS12_ALLOW_OVERWRITE_KEY = 0x00004000 + PKCS12_NO_PERSIST_KEY = 0x00008000 + PKCS12_INCLUDE_EXTENDED_PROPERTIES = 0x00000010 + + /* Flags for CryptAcquireCertificatePrivateKey */ + CRYPT_ACQUIRE_CACHE_FLAG = 0x00000001 + CRYPT_ACQUIRE_USE_PROV_INFO_FLAG = 0x00000002 + CRYPT_ACQUIRE_COMPARE_KEY_FLAG = 0x00000004 + CRYPT_ACQUIRE_NO_HEALING = 0x00000008 + CRYPT_ACQUIRE_SILENT_FLAG = 0x00000040 + CRYPT_ACQUIRE_WINDOW_HANDLE_FLAG = 0x00000080 + CRYPT_ACQUIRE_NCRYPT_KEY_FLAGS_MASK = 0x00070000 + CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG = 0x00010000 + CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG = 0x00020000 + CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG = 0x00040000 + + /* pdwKeySpec for CryptAcquireCertificatePrivateKey */ + AT_KEYEXCHANGE = 1 + AT_SIGNATURE = 2 + CERT_NCRYPT_KEY_SPEC = 0xFFFFFFFF + + /* Default usage match type is AND with value zero */ USAGE_MATCH_TYPE_AND = 0 USAGE_MATCH_TYPE_OR = 1 @@ -398,6 +489,89 @@ const ( CERT_TRUST_IS_CA_TRUSTED = 0x00004000 CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000 + /* Certificate Information Flags */ + CERT_INFO_VERSION_FLAG = 1 + CERT_INFO_SERIAL_NUMBER_FLAG = 2 + CERT_INFO_SIGNATURE_ALGORITHM_FLAG = 3 + CERT_INFO_ISSUER_FLAG = 4 + CERT_INFO_NOT_BEFORE_FLAG = 5 + CERT_INFO_NOT_AFTER_FLAG = 6 + CERT_INFO_SUBJECT_FLAG = 7 + CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG = 8 + CERT_INFO_ISSUER_UNIQUE_ID_FLAG = 9 + CERT_INFO_SUBJECT_UNIQUE_ID_FLAG = 10 + CERT_INFO_EXTENSION_FLAG = 11 + + /* dwFindType for CertFindCertificateInStore */ + CERT_COMPARE_MASK = 0xFFFF + CERT_COMPARE_SHIFT = 16 + CERT_COMPARE_ANY = 0 + CERT_COMPARE_SHA1_HASH = 1 + CERT_COMPARE_NAME = 2 + CERT_COMPARE_ATTR = 3 + CERT_COMPARE_MD5_HASH = 4 + CERT_COMPARE_PROPERTY = 5 + CERT_COMPARE_PUBLIC_KEY = 6 + CERT_COMPARE_HASH = CERT_COMPARE_SHA1_HASH + CERT_COMPARE_NAME_STR_A = 7 + CERT_COMPARE_NAME_STR_W = 8 + CERT_COMPARE_KEY_SPEC = 9 + CERT_COMPARE_ENHKEY_USAGE = 10 + CERT_COMPARE_CTL_USAGE = CERT_COMPARE_ENHKEY_USAGE + CERT_COMPARE_SUBJECT_CERT = 11 + CERT_COMPARE_ISSUER_OF = 12 + CERT_COMPARE_EXISTING = 13 + CERT_COMPARE_SIGNATURE_HASH = 14 + CERT_COMPARE_KEY_IDENTIFIER = 15 + CERT_COMPARE_CERT_ID = 16 + CERT_COMPARE_CROSS_CERT_DIST_POINTS = 17 + CERT_COMPARE_PUBKEY_MD5_HASH = 18 + CERT_COMPARE_SUBJECT_INFO_ACCESS = 19 + CERT_COMPARE_HASH_STR = 20 + CERT_COMPARE_HAS_PRIVATE_KEY = 21 + CERT_FIND_ANY = (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT) + CERT_FIND_SHA1_HASH = (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT) + CERT_FIND_MD5_HASH = (CERT_COMPARE_MD5_HASH << CERT_COMPARE_SHIFT) + CERT_FIND_SIGNATURE_HASH = (CERT_COMPARE_SIGNATURE_HASH << CERT_COMPARE_SHIFT) + CERT_FIND_KEY_IDENTIFIER = (CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT) + CERT_FIND_HASH = CERT_FIND_SHA1_HASH + CERT_FIND_PROPERTY = (CERT_COMPARE_PROPERTY << CERT_COMPARE_SHIFT) + CERT_FIND_PUBLIC_KEY = (CERT_COMPARE_PUBLIC_KEY << CERT_COMPARE_SHIFT) + CERT_FIND_SUBJECT_NAME = (CERT_COMPARE_NAME< 0 { + _p0 = &buf[0] } - return _LoadLibraryEx(_p0, zero, flags) + r0, _, e1 := syscall.SyscallN(procFormatMessageW.Addr(), uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args))) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return } -func _LoadLibraryEx(libname *uint16, zero Handle, flags uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadLibraryExW.Addr(), 3, uintptr(unsafe.Pointer(libname)), uintptr(zero), uintptr(flags)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func FreeEnvironmentStrings(envs *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procFreeEnvironmentStringsW.Addr(), uintptr(unsafe.Pointer(envs))) + if r1 == 0 { + err = errnoErr(e1) } return } func FreeLibrary(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.SyscallN(procFreeLibrary.Addr(), uintptr(handle)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(procname) - if err != nil { - return +func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGenerateConsoleCtrlEvent.Addr(), uintptr(ctrlEvent), uintptr(processGroupID)) + if r1 == 0 { + err = errnoErr(e1) } - return _GetProcAddress(module, _p0) + return } -func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { - r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) - proc = uintptr(r0) - if proc == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetACP() (acp uint32) { + r0, _, _ := syscall.SyscallN(procGetACP.Addr()) + acp = uint32(r0) + return +} + +func GetActiveProcessorCount(groupNumber uint16) (ret uint32) { + r0, _, _ := syscall.SyscallN(procGetActiveProcessorCount.Addr(), uintptr(groupNumber)) + ret = uint32(r0) + return +} + +func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetCommModemStatus.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpModemStat))) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) +func GetCommState(handle Handle, lpDCB *DCB) (err error) { + r1, _, e1 := syscall.SyscallN(procGetCommState.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpDCB))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { + r1, _, e1 := syscall.SyscallN(procGetCommTimeouts.Addr(), uintptr(handle), uintptr(unsafe.Pointer(timeouts))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCommandLine() (cmd *uint16) { + r0, _, _ := syscall.SyscallN(procGetCommandLineW.Addr()) + cmd = (*uint16)(unsafe.Pointer(r0)) + return +} + +func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetComputerNameExW.Addr(), uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetComputerName(buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetComputerNameW.Addr(), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleCP() (cp uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetConsoleCP.Addr()) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleMode(console Handle, mode *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetConsoleMode.Addr(), uintptr(console), uintptr(unsafe.Pointer(mode))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleOutputCP() (cp uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetConsoleOutputCP.Addr()) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { + r1, _, e1 := syscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(console), uintptr(unsafe.Pointer(info))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetCurrentDirectoryW.Addr(), uintptr(buflen), uintptr(unsafe.Pointer(buf))) n = uint32(r0) if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) { - r1, _, e1 := syscall.Syscall(procGetModuleHandleExW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) +func GetCurrentProcessId() (pid uint32) { + r0, _, _ := syscall.SyscallN(procGetCurrentProcessId.Addr()) + pid = uint32(r0) + return +} + +func GetCurrentThreadId() (id uint32) { + r0, _, _ := syscall.SyscallN(procGetCurrentThreadId.Addr()) + id = uint32(r0) + return +} + +func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { + r1, _, e1 := syscall.SyscallN(procGetDiskFreeSpaceExW.Addr(), uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetVersion() (ver uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetVersion.Addr(), 0, 0, 0, 0) - ver = uint32(r0) - if ver == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetDriveType(rootPathName *uint16) (driveType uint32) { + r0, _, _ := syscall.SyscallN(procGetDriveTypeW.Addr(), uintptr(unsafe.Pointer(rootPathName))) + driveType = uint32(r0) + return +} + +func GetEnvironmentStrings() (envs *uint16, err error) { + r0, _, e1 := syscall.SyscallN(procGetEnvironmentStringsW.Addr()) + envs = (*uint16)(unsafe.Pointer(r0)) + if envs == nil { + err = errnoErr(e1) } return } -func FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { - var _p0 *uint16 - if len(buf) > 0 { - _p0 = &buf[0] - } - r0, _, e1 := syscall.Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) +func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetEnvironmentVariableW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) n = uint32(r0) if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ExitProcess(exitcode uint32) { - syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) +func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetExitCodeProcess.Addr(), uintptr(handle), uintptr(unsafe.Pointer(exitcode))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func IsWow64Process(handle Handle, isWow64 *bool) (err error) { - var _p0 uint32 - if *isWow64 { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(&_p0)), 0) - *isWow64 = _p0 != 0 +func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procGetFileAttributesExW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetFileAttributes(name *uint16) (attrs uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetFileAttributesW.Addr(), uintptr(unsafe.Pointer(name))) + attrs = uint32(r0) + if attrs == INVALID_FILE_ATTRIBUTES { + err = errnoErr(e1) } return } -func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := syscall.Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) +func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { + r1, _, e1 := syscall.SyscallN(procGetFileInformationByHandle.Addr(), uintptr(handle), uintptr(unsafe.Pointer(data))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := syscall.Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) +func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetFileInformationByHandleEx.Addr(), uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) { - var _p0 uint32 - if wait { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0), 0, 0) +func GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := syscall.SyscallN(procGetFileTime.Addr(), uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { - r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) - newlowoffset = uint32(r0) - if newlowoffset == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetFileType(filehandle Handle) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetFileType.Addr(), uintptr(filehandle)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func CloseHandle(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetFinalPathNameByHandleW.Addr(), uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func GetStdHandle(stdhandle uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetFullPathNameW.Addr(), uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname))) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func SetStdHandle(stdhandle uint32, handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetLargePageMinimum() (size uintptr) { + r0, _, _ := syscall.SyscallN(procGetLargePageMinimum.Addr()) + size = uintptr(r0) return } -func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetLastError() (lasterr error) { + r0, _, _ := syscall.SyscallN(procGetLastError.Addr()) + if r0 != 0 { + lasterr = syscall.Errno(r0) } return } -func findNextFile1(handle Handle, data *win32finddata1) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetLogicalDriveStringsW.Addr(), uintptr(bufferLength), uintptr(unsafe.Pointer(buffer))) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func FindClose(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetLogicalDrives() (drivesBitMask uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetLogicalDrives.Addr()) + drivesBitMask = uint32(r0) + if drivesBitMask == 0 { + err = errnoErr(e1) } return } -func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { - r1, _, e1 := syscall.Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetLongPathNameW.Addr(), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetMaximumProcessorCount(groupNumber uint16) (ret uint32) { + r0, _, _ := syscall.SyscallN(procGetMaximumProcessorCount.Addr(), uintptr(groupNumber)) + ret = uint32(r0) return } -func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) +func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetModuleFileNameW.Addr(), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) n = uint32(r0) if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetCurrentDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) +func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procGetModuleHandleExW.Addr(), uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { - r1, _, e1 := syscall.Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) +func GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNamedPipeClientProcessId.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(clientProcessID))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func RemoveDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) +func GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNamedPipeHandleStateW.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func DeleteFile(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) +func GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNamedPipeInfo.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func MoveFile(from *uint16, to *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) +func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNamedPipeServerProcessId.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(serverProcessID))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) +func GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNumberOfConsoleInputEvents.Addr(), uintptr(console), uintptr(unsafe.Pointer(numevents))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) +func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } + r1, _, e1 := syscall.SyscallN(procGetOverlappedResult.Addr(), uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetPriorityClass(process Handle) (ret uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetPriorityClass.Addr(), uintptr(process)) + ret = uint32(r0) + if ret == 0 { + err = errnoErr(e1) } return } -func GetComputerName(buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) +func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(procname) + if err != nil { + return + } + return _GetProcAddress(module, _p0) +} + +func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { + r0, _, e1 := syscall.SyscallN(procGetProcAddress.Addr(), uintptr(module), uintptr(unsafe.Pointer(procname))) + proc = uintptr(r0) + if proc == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcessId(process Handle) (id uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetProcessId.Addr(), uintptr(process)) + id = uint32(r0) + if id == 0 { + err = errnoErr(e1) + } + return +} + +func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetProcessPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) +func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetProcessShutdownParameters.Addr(), uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetEndOfFile(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) +func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { + r1, _, e1 := syscall.SyscallN(procGetProcessTimes.Addr(), uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetSystemTimeAsFileTime(time *Filetime) { - syscall.Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) +func GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) { + syscall.SyscallN(procGetProcessWorkingSetSizeEx.Addr(), uintptr(hProcess), uintptr(unsafe.Pointer(lpMinimumWorkingSetSize)), uintptr(unsafe.Pointer(lpMaximumWorkingSetSize)), uintptr(unsafe.Pointer(flags))) return } -func GetSystemTimePreciseAsFileTime(time *Filetime) { - syscall.Syscall(procGetSystemTimePreciseAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) +func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetQueuedCompletionStatus.Addr(), uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout)) + if r1 == 0 { + err = errnoErr(e1) + } return } -func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) - rc = uint32(r0) - if rc == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetShortPathNameW.Addr(), uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) +func getStartupInfo(startupInfo *StartupInfo) { + syscall.SyscallN(procGetStartupInfoW.Addr(), uintptr(unsafe.Pointer(startupInfo))) + return +} + +func GetStdHandle(stdhandle uint32) (handle Handle, err error) { + r0, _, e1 := syscall.SyscallN(procGetStdHandle.Addr(), uintptr(stdhandle)) handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + if handle == InvalidHandle { + err = errnoErr(e1) } return } -func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetSystemDirectoryW.Addr(), uintptr(unsafe.Pointer(dir)), uintptr(dirLen)) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) } return } -func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) +func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetSystemPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CancelIo(s Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetSystemTimeAsFileTime(time *Filetime) { + syscall.SyscallN(procGetSystemTimeAsFileTime.Addr(), uintptr(unsafe.Pointer(time))) return } -func CancelIoEx(s Handle, o *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetSystemTimePreciseAsFileTime(time *Filetime) { + syscall.SyscallN(procGetSystemTimePreciseAsFileTime.Addr(), uintptr(unsafe.Pointer(time))) return } -func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { - var _p0 uint32 - if inheritHandles { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetSystemWindowsDirectoryW.Addr(), uintptr(unsafe.Pointer(dir)), uintptr(dirLen)) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) } return } -func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenProcess.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(processId)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetTempPathW.Addr(), uintptr(buflen), uintptr(unsafe.Pointer(buf))) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) { - r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) - if r1 <= 32 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetThreadPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) + if r1 == 0 { + err = errnoErr(e1) } return } -func shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) { - r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(token), uintptr(unsafe.Pointer(path)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) +func getTickCount64() (ms uint64) { + r0, _, _ := syscall.SyscallN(procGetTickCount64.Addr()) + ms = uint64(r0) + return +} + +func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetTimeZoneInformation.Addr(), uintptr(unsafe.Pointer(tzi))) + rc = uint32(r0) + if rc == 0xffffffff { + err = errnoErr(e1) } return } -func TerminateProcess(handle Handle, exitcode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) +func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetUserPreferredUILanguages.Addr(), uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetVersion() (ver uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetVersion.Addr()) + ver = uint32(r0) + if ver == 0 { + err = errnoErr(e1) } return } -func GetStartupInfo(startupInfo *StartupInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) +func GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetVolumeInformationByHandleW.Addr(), uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) +func GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetVolumeInformationW.Addr(), uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { - var _p0 uint32 - if bInheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) +func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetVolumeNameForVolumeMountPointW.Addr(), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { - r0, _, e1 := syscall.Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) - event = uint32(r0) - if event == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetVolumePathNameW.Addr(), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(volumePathName)), uintptr(bufferLength)) + if r1 == 0 { + err = errnoErr(e1) } return } -func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { - var _p0 uint32 - if waitAll { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall6(procWaitForMultipleObjects.Addr(), 4, uintptr(count), uintptr(handles), uintptr(_p0), uintptr(waitMilliseconds), 0, 0) - event = uint32(r0) - if event == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16, bufferLength uint32, returnLength *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetVolumePathNamesForVolumeNameW.Addr(), uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(volumePathNames)), uintptr(bufferLength), uintptr(unsafe.Pointer(returnLength))) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetWindowsDirectoryW.Addr(), uintptr(unsafe.Pointer(dir)), uintptr(dirLen)) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) } return } -func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) +func initializeProcThreadAttributeList(attrlist *ProcThreadAttributeList, attrcount uint32, flags uint32, size *uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procInitializeProcThreadAttributeList.Addr(), uintptr(unsafe.Pointer(attrlist)), uintptr(attrcount), uintptr(flags), uintptr(unsafe.Pointer(size))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetFileType(filehandle Handle) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func IsWow64Process(handle Handle, isWow64 *bool) (err error) { + var _p0 uint32 + if *isWow64 { + _p0 = 1 + } + r1, _, e1 := syscall.SyscallN(procIsWow64Process.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&_p0))) + *isWow64 = _p0 != 0 + if r1 == 0 { + err = errnoErr(e1) } return } -func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0) +func IsWow64Process2(handle Handle, processMachine *uint16, nativeMachine *uint16) (err error) { + err = procIsWow64Process2.Find() + if err != nil { + return + } + r1, _, e1 := syscall.SyscallN(procIsWow64Process2.Addr(), uintptr(handle), uintptr(unsafe.Pointer(processMachine)), uintptr(unsafe.Pointer(nativeMachine))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(libname) + if err != nil { + return } - return + return _LoadLibraryEx(_p0, zero, flags) } -func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { - r1, _, e1 := syscall.Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func _LoadLibraryEx(libname *uint16, zero Handle, flags uintptr) (handle Handle, err error) { + r0, _, e1 := syscall.SyscallN(procLoadLibraryExW.Addr(), uintptr(unsafe.Pointer(libname)), uintptr(zero), uintptr(flags)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func GetEnvironmentStrings() (envs *uint16, err error) { - r0, _, e1 := syscall.Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) - envs = (*uint16)(unsafe.Pointer(r0)) - if envs == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func LoadLibrary(libname string) (handle Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(libname) + if err != nil { + return } - return + return _LoadLibrary(_p0) } -func FreeEnvironmentStrings(envs *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func _LoadLibrary(libname *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.SyscallN(procLoadLibraryW.Addr(), uintptr(unsafe.Pointer(libname))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func LoadResource(module Handle, resInfo Handle) (resData Handle, err error) { + r0, _, e1 := syscall.SyscallN(procLoadResource.Addr(), uintptr(module), uintptr(resInfo)) + resData = Handle(r0) + if resData == 0 { + err = errnoErr(e1) } return } -func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error) { + r0, _, e1 := syscall.SyscallN(procLocalAlloc.Addr(), uintptr(flags), uintptr(length)) + ptr = uintptr(r0) + if ptr == 0 { + err = errnoErr(e1) } return } -func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { - var _p0 uint32 - if inheritExisting { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func LocalFree(hmem Handle) (handle Handle, err error) { + r0, _, e1 := syscall.SyscallN(procLocalFree.Addr(), uintptr(hmem)) + handle = Handle(r0) + if handle != 0 { + err = errnoErr(e1) } return } -func DestroyEnvironmentBlock(block *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0) +func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procLockFileEx.Addr(), uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getTickCount64() (ms uint64) { - r0, _, _ := syscall.Syscall(procGetTickCount64.Addr(), 0, 0, 0, 0) - ms = uint64(r0) +func LockResource(resData Handle) (addr uintptr, err error) { + r0, _, e1 := syscall.SyscallN(procLockResource.Addr(), uintptr(resData)) + addr = uintptr(r0) + if addr == 0 { + err = errnoErr(e1) + } return } -func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { + r0, _, e1 := syscall.SyscallN(procMapViewOfFile.Addr(), uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length)) + addr = uintptr(r0) + if addr == 0 { + err = errnoErr(e1) } return } -func GetFileAttributes(name *uint16) (attrs uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - attrs = uint32(r0) - if attrs == INVALID_FILE_ATTRIBUTES { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { + r1, _, e1 := syscall.SyscallN(procModule32FirstW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry))) + if r1 == 0 { + err = errnoErr(e1) } return } -func SetFileAttributes(name *uint16, attrs uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) +func Module32Next(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { + r1, _, e1 := syscall.SyscallN(procModule32NextW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { - r1, _, e1 := syscall.Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) +func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procMoveFileExW.Addr(), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetCommandLine() (cmd *uint16) { - r0, _, _ := syscall.Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) - cmd = (*uint16)(unsafe.Pointer(r0)) +func MoveFile(from *uint16, to *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procMoveFileW.Addr(), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { - r0, _, e1 := syscall.Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) - argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) - if argv == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { + r0, _, e1 := syscall.SyscallN(procMultiByteToWideChar.Addr(), uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) + nwrite = int32(r0) + if nwrite == 0 { + err = errnoErr(e1) } return } -func LocalFree(hmem Handle) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) +func OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := syscall.SyscallN(procOpenEventW.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) handle = Handle(r0) - if handle != 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + if handle == 0 { + err = errnoErr(e1) } return } -func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 } - return -} - -func FlushFileBuffers(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + r0, _, e1 := syscall.SyscallN(procOpenMutexW.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 } - return -} - -func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + r0, _, e1 := syscall.SyscallN(procOpenProcess.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(processId)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := syscall.SyscallN(procOpenThread.Addr(), uintptr(desiredAccess), uintptr(_p0), uintptr(threadId)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procPostQueuedCompletionStatus.Addr(), uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + err = errnoErr(e1) } return } -func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { - r0, _, e1 := syscall.Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) - addr = uintptr(r0) - if addr == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := syscall.SyscallN(procProcess32FirstW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(procEntry))) + if r1 == 0 { + err = errnoErr(e1) } return } -func UnmapViewOfFile(addr uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) +func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := syscall.SyscallN(procProcess32NextW.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(procEntry))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func FlushViewOfFile(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) +func ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procProcessIdToSessionId.Addr(), uintptr(pid), uintptr(unsafe.Pointer(sessionid))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func VirtualLock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) +func PulseEvent(event Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procPulseEvent.Addr(), uintptr(event)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func VirtualUnlock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) +func PurgeComm(handle Handle, dwFlags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procPurgeComm.Addr(), uintptr(handle), uintptr(dwFlags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) { - r0, _, e1 := syscall.Syscall6(procVirtualAlloc.Addr(), 4, uintptr(address), uintptr(size), uintptr(alloctype), uintptr(protect), 0, 0) - value = uintptr(r0) - if value == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) { + r0, _, e1 := syscall.SyscallN(procQueryDosDeviceW.Addr(), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) } return } -func VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualFree.Addr(), 3, uintptr(address), uintptr(size), uintptr(freetype)) +func QueryFullProcessImageName(proc Handle, flags uint32, exeName *uint16, size *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procQueryFullProcessImageNameW.Addr(), uintptr(proc), uintptr(flags), uintptr(unsafe.Pointer(exeName)), uintptr(unsafe.Pointer(size))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procVirtualProtect.Addr(), 4, uintptr(address), uintptr(size), uintptr(newprotect), uintptr(unsafe.Pointer(oldprotect)), 0, 0) +func QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobObjectInformation uintptr, JobObjectInformationLength uint32, retlen *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procQueryInformationJobObject.Addr(), uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), uintptr(unsafe.Pointer(retlen))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) +func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procReadConsoleW.Addr(), uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -1762,486 +3078,357 @@ func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree var _p0 uint32 if watchSubTree { _p0 = 1 - } else { - _p0 = 0 } - r1, _, e1 := syscall.Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) + r1, _, e1 := syscall.SyscallN(procReadDirectoryChangesW.Addr(), uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { - r0, _, e1 := syscall.Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) - store = Handle(r0) - if store == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.SyscallN(procReadFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + err = errnoErr(e1) } return } -func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procReadProcessMemory.Addr(), uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesRead))) + if r1 == 0 { + err = errnoErr(e1) } return } -func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { - r0, _, e1 := syscall.Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) - context = (*CertContext)(unsafe.Pointer(r0)) - if context == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func ReleaseMutex(mutex Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procReleaseMutex.Addr(), uintptr(mutex)) + if r1 == 0 { + err = errnoErr(e1) } return } -func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { - r1, _, e1 := syscall.Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) +func RemoveDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procRemoveDirectoryW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CertCloseStore(store Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) +func RemoveDllDirectory(cookie uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procRemoveDllDirectory.Addr(), uintptr(cookie)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { - r1, _, e1 := syscall.Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) +func ResetEvent(event Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procResetEvent.Addr(), uintptr(event)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CertFreeCertificateChain(ctx *CertChainContext) { - syscall.Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) +func resizePseudoConsole(pconsole Handle, size uint32) (hr error) { + r0, _, _ := syscall.SyscallN(procResizePseudoConsole.Addr(), uintptr(pconsole), uintptr(size)) + if r0 != 0 { + hr = syscall.Errno(r0) + } return } -func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { - r0, _, e1 := syscall.Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) - context = (*CertContext)(unsafe.Pointer(r0)) - if context == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func ResumeThread(thread Handle) (ret uint32, err error) { + r0, _, e1 := syscall.SyscallN(procResumeThread.Addr(), uintptr(thread)) + ret = uint32(r0) + if ret == 0xffffffff { + err = errnoErr(e1) } return } -func CertFreeCertificateContext(ctx *CertContext) (err error) { - r1, _, e1 := syscall.Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) +func SetCommBreak(handle Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procSetCommBreak.Addr(), uintptr(handle)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { - r1, _, e1 := syscall.Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) +func SetCommMask(handle Handle, dwEvtMask uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetCommMask.Addr(), uintptr(handle), uintptr(dwEvtMask)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) - if r0 != 0 { - regerrno = syscall.Errno(r0) +func SetCommState(handle Handle, lpDCB *DCB) (err error) { + r1, _, e1 := syscall.SyscallN(procSetCommState.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpDCB))) + if r1 == 0 { + err = errnoErr(e1) } return } -func RegCloseKey(key Handle) (regerrno error) { - r0, _, _ := syscall.Syscall(procRegCloseKey.Addr(), 1, uintptr(key), 0, 0) - if r0 != 0 { - regerrno = syscall.Errno(r0) +func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { + r1, _, e1 := syscall.SyscallN(procSetCommTimeouts.Addr(), uintptr(handle), uintptr(unsafe.Pointer(timeouts))) + if r1 == 0 { + err = errnoErr(e1) } return } -func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { - r0, _, _ := syscall.Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) - if r0 != 0 { - regerrno = syscall.Errno(r0) +func SetConsoleCP(cp uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetConsoleCP.Addr(), uintptr(cp)) + if r1 == 0 { + err = errnoErr(e1) } return } -func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) - if r0 != 0 { - regerrno = syscall.Errno(r0) +func setConsoleCursorPosition(console Handle, position uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(console), uintptr(position)) + if r1 == 0 { + err = errnoErr(e1) } return } -func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) - if r0 != 0 { - regerrno = syscall.Errno(r0) +func SetConsoleMode(console Handle, mode uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(console), uintptr(mode)) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetCurrentProcessId() (pid uint32) { - r0, _, _ := syscall.Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) - pid = uint32(r0) +func SetConsoleOutputCP(cp uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetConsoleOutputCP.Addr(), uintptr(cp)) + if r1 == 0 { + err = errnoErr(e1) + } return } -func GetConsoleMode(console Handle, mode *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) +func SetCurrentDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procSetCurrentDirectoryW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetConsoleMode(console Handle, mode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(console), uintptr(mode), 0) +func SetDefaultDllDirectories(directoryFlags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetDefaultDllDirectories.Addr(), uintptr(directoryFlags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) +func SetDllDirectory(path string) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(path) + if err != nil { + return + } + return _SetDllDirectory(_p0) +} + +func _SetDllDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procSetDllDirectoryW.Addr(), uintptr(unsafe.Pointer(path))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { - r1, _, e1 := syscall.Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) +func SetEndOfFile(handle Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procSetEndOfFile.Addr(), uintptr(handle)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { - r1, _, e1 := syscall.Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) +func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procSetEnvironmentVariableW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func SetErrorMode(mode uint32) (ret uint32) { + r0, _, _ := syscall.SyscallN(procSetErrorMode.Addr(), uintptr(mode)) + ret = uint32(r0) return } -func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) +func SetEvent(event Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procSetEvent.Addr(), uintptr(event)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) +func SetFileAttributes(name *uint16, attrs uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetFileAttributesW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(attrs)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procThread32First.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) +func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { + r1, _, e1 := syscall.SyscallN(procSetFileCompletionNotificationModes.Addr(), uintptr(handle), uintptr(flags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procThread32Next.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) +func SetFileInformationByHandle(handle Handle, class uint32, inBuffer *byte, inBufferLen uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetFileInformationByHandle.Addr(), uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) +func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { + r0, _, e1 := syscall.SyscallN(procSetFilePointer.Addr(), uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence)) + newlowoffset = uint32(r0) + if newlowoffset == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := syscall.SyscallN(procSetFileTime.Addr(), uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetFileValidData(handle Handle, validDataLength int64) (err error) { + r1, _, e1 := syscall.SyscallN(procSetFileValidData.Addr(), uintptr(handle), uintptr(validDataLength)) + if r1 == 0 { + err = errnoErr(e1) } return } -func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetHandleInformation.Addr(), uintptr(handle), uintptr(mask), uintptr(flags)) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetCurrentThreadId() (id uint32) { - r0, _, _ := syscall.Syscall(procGetCurrentThreadId.Addr(), 0, 0, 0, 0) - id = uint32(r0) +func SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) { + r0, _, e1 := syscall.SyscallN(procSetInformationJobObject.Addr(), uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength)) + ret = int(r0) + if ret == 0 { + err = errnoErr(e1) + } return } -func CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name)), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetNamedPipeHandleState.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout))) + if r1 == 0 { + err = errnoErr(e1) } return } -func CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateEventExW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetPriorityClass(process Handle, priorityClass uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetPriorityClass.Addr(), uintptr(process), uintptr(priorityClass)) + if r1 == 0 { + err = errnoErr(e1) } return } -func OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { +func SetProcessPriorityBoost(process Handle, disable bool) (err error) { var _p0 uint32 - if inheritHandle { + if disable { _p0 = 1 - } else { - _p0 = 0 } - r0, _, e1 := syscall.Syscall(procOpenEventW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + r1, _, e1 := syscall.SyscallN(procSetProcessPriorityBoost.Addr(), uintptr(process), uintptr(_p0)) + if r1 == 0 { + err = errnoErr(e1) } return } -func SetEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(event), 0, 0) +func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetProcessShutdownParameters.Addr(), uintptr(level), uintptr(flags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ResetEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(event), 0, 0) +func SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetProcessWorkingSetSizeEx.Addr(), uintptr(hProcess), uintptr(dwMinimumWorkingSetSize), uintptr(dwMaximumWorkingSetSize), uintptr(flags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func PulseEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procPulseEvent.Addr(), 1, uintptr(event), 0, 0) +func SetStdHandle(stdhandle uint32, handle Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procSetStdHandle.Addr(), uintptr(stdhandle), uintptr(handle)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) { - var _p0 uint32 - if initialOwner { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procCreateMutexW.Addr(), 3, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procSetVolumeLabelW.Addr(), uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeName))) + if r1 == 0 { + err = errnoErr(e1) } return } -func CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateMutexExW.Addr(), 4, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procSetVolumeMountPointW.Addr(), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName))) + if r1 == 0 { + err = errnoErr(e1) } return } -func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenMutexW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupComm.Addr(), uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue)) + if r1 == 0 { + err = errnoErr(e1) } return } -func ReleaseMutex(mutex Handle) (err error) { - r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) { + r0, _, e1 := syscall.SyscallN(procSizeofResource.Addr(), uintptr(module), uintptr(resInfo)) + size = uint32(r0) + if size == 0 { + err = errnoErr(e1) } return } @@ -2250,1802 +3437,1314 @@ func SleepEx(milliseconds uint32, alertable bool) (ret uint32) { var _p0 uint32 if alertable { _p0 = 1 - } else { - _p0 = 0 } - r0, _, _ := syscall.Syscall(procSleepEx.Addr(), 2, uintptr(milliseconds), uintptr(_p0), 0) + r0, _, _ := syscall.SyscallN(procSleepEx.Addr(), uintptr(milliseconds), uintptr(_p0)) ret = uint32(r0) return } -func CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procCreateJobObjectW.Addr(), 2, uintptr(unsafe.Pointer(jobAttr)), uintptr(unsafe.Pointer(name)), 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func TerminateJobObject(job Handle, exitCode uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procTerminateJobObject.Addr(), uintptr(job), uintptr(exitCode)) + if r1 == 0 { + err = errnoErr(e1) } return } -func AssignProcessToJobObject(job Handle, process Handle) (err error) { - r1, _, e1 := syscall.Syscall(procAssignProcessToJobObject.Addr(), 2, uintptr(job), uintptr(process), 0) +func TerminateProcess(handle Handle, exitcode uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procTerminateProcess.Addr(), uintptr(handle), uintptr(exitcode)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func TerminateJobObject(job Handle, exitCode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procTerminateJobObject.Addr(), 2, uintptr(job), uintptr(exitCode), 0) +func Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) { + r1, _, e1 := syscall.SyscallN(procThread32First.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetErrorMode(mode uint32) (ret uint32) { - r0, _, _ := syscall.Syscall(procSetErrorMode.Addr(), 1, uintptr(mode), 0, 0) - ret = uint32(r0) +func Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) { + r1, _, e1 := syscall.SyscallN(procThread32Next.Addr(), uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func ResumeThread(thread Handle) (ret uint32, err error) { - r0, _, e1 := syscall.Syscall(procResumeThread.Addr(), 1, uintptr(thread), 0, 0) - ret = uint32(r0) - if ret == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procUnlockFileEx.Addr(), uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + err = errnoErr(e1) } return } -func SetPriorityClass(process Handle, priorityClass uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetPriorityClass.Addr(), 2, uintptr(process), uintptr(priorityClass), 0) +func UnmapViewOfFile(addr uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procUnmapViewOfFile.Addr(), uintptr(addr)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetPriorityClass(process Handle) (ret uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetPriorityClass.Addr(), 1, uintptr(process), 0, 0) - ret = uint32(r0) - if ret == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func updateProcThreadAttribute(attrlist *ProcThreadAttributeList, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procUpdateProcThreadAttribute.Addr(), uintptr(unsafe.Pointer(attrlist)), uintptr(flags), uintptr(attr), uintptr(value), uintptr(size), uintptr(prevvalue), uintptr(unsafe.Pointer(returnedsize))) + if r1 == 0 { + err = errnoErr(e1) } return } -func SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) { - r0, _, e1 := syscall.Syscall6(procSetInformationJobObject.Addr(), 4, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), 0, 0) - ret = int(r0) - if ret == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) { + r0, _, e1 := syscall.SyscallN(procVirtualAlloc.Addr(), uintptr(address), uintptr(size), uintptr(alloctype), uintptr(protect)) + value = uintptr(r0) + if value == 0 { + err = errnoErr(e1) } return } -func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGenerateConsoleCtrlEvent.Addr(), 2, uintptr(ctrlEvent), uintptr(processGroupID), 0) +func VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualFree.Addr(), uintptr(address), uintptr(size), uintptr(freetype)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetProcessId(process Handle) (id uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetProcessId.Addr(), 1, uintptr(process), 0, 0) - id = uint32(r0) - if id == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func VirtualLock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualLock.Addr(), uintptr(addr), uintptr(length)) + if r1 == 0 { + err = errnoErr(e1) } return } -func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenThread.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(threadId)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualProtect.Addr(), uintptr(address), uintptr(size), uintptr(newprotect), uintptr(unsafe.Pointer(oldprotect))) + if r1 == 0 { + err = errnoErr(e1) } return } -func SetProcessPriorityBoost(process Handle, disable bool) (err error) { - var _p0 uint32 - if disable { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0) +func VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualProtectEx.Addr(), uintptr(process), uintptr(address), uintptr(size), uintptr(newProtect), uintptr(unsafe.Pointer(oldProtect))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) +func VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualQuery.Addr(), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func DeleteVolumeMountPoint(volumeMountPoint *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteVolumeMountPointW.Addr(), 1, uintptr(unsafe.Pointer(volumeMountPoint)), 0, 0) +func VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualQueryEx.Addr(), uintptr(process), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func FindFirstVolume(volumeName *uint16, bufferLength uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstVolumeW.Addr(), 2, uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func VirtualUnlock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procVirtualUnlock.Addr(), uintptr(addr), uintptr(length)) + if r1 == 0 { + err = errnoErr(e1) } return } -func FindFirstVolumeMountPoint(rootPathName *uint16, volumeMountPoint *uint16, bufferLength uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func WTSGetActiveConsoleSessionId() (sessionID uint32) { + r0, _, _ := syscall.SyscallN(procWTSGetActiveConsoleSessionId.Addr()) + sessionID = uint32(r0) return } -func FindNextVolume(findVolume Handle, volumeName *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextVolumeW.Addr(), 3, uintptr(findVolume), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength)) +func WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procWaitCommEvent.Addr(), uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextVolumeMountPointW.Addr(), 3, uintptr(findVolumeMountPoint), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { + var _p0 uint32 + if waitAll { + _p0 = 1 + } + r0, _, e1 := syscall.SyscallN(procWaitForMultipleObjects.Addr(), uintptr(count), uintptr(handles), uintptr(_p0), uintptr(waitMilliseconds)) + event = uint32(r0) + if event == 0xffffffff { + err = errnoErr(e1) } return } -func FindVolumeClose(findVolume Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindVolumeClose.Addr(), 1, uintptr(findVolume), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { + r0, _, e1 := syscall.SyscallN(procWaitForSingleObject.Addr(), uintptr(handle), uintptr(waitMilliseconds)) + event = uint32(r0) + if event == 0xffffffff { + err = errnoErr(e1) } return } -func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindVolumeMountPointClose.Addr(), 1, uintptr(findVolumeMountPoint), 0, 0) +func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procWriteConsoleW.Addr(), uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { - r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) +func writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.SyscallN(procWriteFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetDriveType(rootPathName *uint16) (driveType uint32) { - r0, _, _ := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0) - driveType = uint32(r0) +func WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procWriteProcessMemory.Addr(), uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesWritten))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func GetLogicalDrives() (drivesBitMask uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLogicalDrives.Addr(), 0, 0, 0, 0) - drivesBitMask = uint32(r0) - if drivesBitMask == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procAcceptEx.Addr(), uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { + syscall.SyscallN(procGetAcceptExSockaddrs.Addr(), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen))) return } -func GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetVolumeInformationW.Addr(), 8, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) +func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procTransmitFile.Addr(), uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetVolumeInformationByHandleW.Addr(), 8, uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NetApiBufferFree(buf *byte) (neterr error) { + r0, _, _ := syscall.SyscallN(procNetApiBufferFree.Addr(), uintptr(unsafe.Pointer(buf))) + if r0 != 0 { + neterr = syscall.Errno(r0) } return } -func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetVolumeNameForVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) { + r0, _, _ := syscall.SyscallN(procNetGetJoinInformation.Addr(), uintptr(unsafe.Pointer(server)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bufType))) + if r0 != 0 { + neterr = syscall.Errno(r0) } return } -func GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetVolumePathNameW.Addr(), 3, uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(volumePathName)), uintptr(bufferLength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) { + r0, _, _ := syscall.SyscallN(procNetUserEnum.Addr(), uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle))) + if r0 != 0 { + neterr = syscall.Errno(r0) } return } -func GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16, bufferLength uint32, returnLength *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetVolumePathNamesForVolumeNameW.Addr(), 4, uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(volumePathNames)), uintptr(bufferLength), uintptr(unsafe.Pointer(returnLength)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { + r0, _, _ := syscall.SyscallN(procNetUserGetInfo.Addr(), uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf))) + if r0 != 0 { + neterr = syscall.Errno(r0) } return } -func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtCreateFile.Addr(), uintptr(unsafe.Pointer(handle)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(attributes), uintptr(share), uintptr(disposition), uintptr(options), uintptr(eabuffer), uintptr(ealength)) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetVolumeLabelW.Addr(), 2, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeName)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtCreateNamedPipeFile.Addr(), uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout))) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetVolumeMountPointW.Addr(), 2, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtQueryInformationProcess.Addr(), uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), uintptr(unsafe.Pointer(retLen))) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { - r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) - ret = int32(r0) - if ret == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtQuerySystemInformation.Addr(), uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen), uintptr(unsafe.Pointer(retLen))) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func ExitWindowsEx(flags uint32, reason uint32) (err error) { - r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtSetInformationFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class)) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) { - var _p0 uint32 - if forceAppsClosed { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if rebootAfterShutdown { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtSetInformationProcess.Addr(), uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen)) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procNtSetSystemInformation.Addr(), uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen)) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) { + r0, _, _ := syscall.SyscallN(procRtlAddFunctionTable.Addr(), uintptr(unsafe.Pointer(functionTable)), uintptr(entryCount), uintptr(baseAddress)) + ret = r0 != 0 return } -func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { - r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) +func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procRtlDefaultNpAcl.Addr(), uintptr(unsafe.Pointer(acl))) if r0 != 0 { - ret = syscall.Errno(r0) + ntstatus = NTStatus(r0) } return } -func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { - r0, _, _ := syscall.Syscall(procStringFromGUID2.Addr(), 3, uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(lpsz)), uintptr(cchMax)) - chars = int32(r0) +func RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) { + r0, _, _ := syscall.SyscallN(procRtlDeleteFunctionTable.Addr(), uintptr(unsafe.Pointer(functionTable))) + ret = r0 != 0 return } -func coCreateGuid(pguid *GUID) (ret error) { - r0, _, _ := syscall.Syscall(procCoCreateGuid.Addr(), 1, uintptr(unsafe.Pointer(pguid)), 0, 0) +func RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procRtlDosPathNameToNtPathName_U_WithStatus.Addr(), uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName))) if r0 != 0 { - ret = syscall.Errno(r0) + ntstatus = NTStatus(r0) } return } -func CoTaskMemFree(address unsafe.Pointer) { - syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0) +func RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procRtlDosPathNameToRelativeNtPathName_U_WithStatus.Addr(), uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName))) + if r0 != 0 { + ntstatus = NTStatus(r0) + } return } -func rtlGetVersion(info *OsVersionInfoEx) (ret error) { - r0, _, _ := syscall.Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } +func RtlGetCurrentPeb() (peb *PEB) { + r0, _, _ := syscall.SyscallN(procRtlGetCurrentPeb.Addr()) + peb = (*PEB)(unsafe.Pointer(r0)) return } func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { - syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) + syscall.SyscallN(procRtlGetNtVersionNumbers.Addr(), uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) return } -func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetProcessPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func rtlGetVersion(info *OsVersionInfoEx) (ntstatus error) { + r0, _, _ := syscall.SyscallN(procRtlGetVersion.Addr(), uintptr(unsafe.Pointer(info))) + if r0 != 0 { + ntstatus = NTStatus(r0) } return } -func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetThreadPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func RtlInitString(destinationString *NTString, sourceString *byte) { + syscall.SyscallN(procRtlInitString.Addr(), uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString))) return } -func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetUserPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func RtlInitUnicodeString(destinationString *NTUnicodeString, sourceString *uint16) { + syscall.SyscallN(procRtlInitUnicodeString.Addr(), uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString))) return } -func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetSystemPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) { + r0, _, _ := syscall.SyscallN(procRtlNtStatusToDosErrorNoTeb.Addr(), uintptr(ntstatus)) + ret = syscall.Errno(r0) return } -func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { - var _p0 *uint32 - if len(processIds) > 0 { - _p0 = &processIds[0] - } - r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(processIds)), uintptr(unsafe.Pointer(bytesReturned))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { + r0, _, _ := syscall.SyscallN(procCLSIDFromString.Addr(), uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid))) + if r0 != 0 { + ret = syscall.Errno(r0) } return } -func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { - r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) +func coCreateGuid(pguid *GUID) (ret error) { + r0, _, _ := syscall.SyscallN(procCoCreateGuid.Addr(), uintptr(unsafe.Pointer(pguid))) if r0 != 0 { - sockerr = syscall.Errno(r0) + ret = syscall.Errno(r0) } return } -func WSACleanup() (err error) { - r1, _, e1 := syscall.Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func CoGetObject(name *uint16, bindOpts *BIND_OPTS3, guid *GUID, functionTable **uintptr) (ret error) { + r0, _, _ := syscall.SyscallN(procCoGetObject.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bindOpts)), uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(functionTable))) + if r0 != 0 { + ret = syscall.Errno(r0) } return } -func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { - r1, _, e1 := syscall.Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func CoInitializeEx(reserved uintptr, coInit uint32) (ret error) { + r0, _, _ := syscall.SyscallN(procCoInitializeEx.Addr(), uintptr(reserved), uintptr(coInit)) + if r0 != 0 { + ret = syscall.Errno(r0) } return } -func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func CoTaskMemFree(address unsafe.Pointer) { + syscall.SyscallN(procCoTaskMemFree.Addr(), uintptr(address)) return } -func sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := syscall.Syscall6(procsendto.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(tolen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func CoUninitialize() { + syscall.SyscallN(procCoUninitialize.Addr()) return } -func recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] +func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { + r0, _, _ := syscall.SyscallN(procStringFromGUID2.Addr(), uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(lpsz)), uintptr(cchMax)) + chars = int32(r0) + return +} + +func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procEnumProcessModules.Addr(), uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded))) + if r1 == 0 { + err = errnoErr(e1) } - r0, _, e1 := syscall.Syscall6(procrecvfrom.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int32(r0) - if n == -1 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + return +} + +func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procEnumProcessModulesEx.Addr(), uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag)) + if r1 == 0 { + err = errnoErr(e1) } return } -func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { - r1, _, e1 := syscall.Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func enumProcesses(processIds *uint32, nSize uint32, bytesReturned *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procEnumProcesses.Addr(), uintptr(unsafe.Pointer(processIds)), uintptr(nSize), uintptr(unsafe.Pointer(bytesReturned))) + if r1 == 0 { + err = errnoErr(e1) } return } -func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { - r1, _, e1 := syscall.Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetModuleBaseNameW.Addr(), uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size)) + if r1 == 0 { + err = errnoErr(e1) } return } -func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetModuleFileNameExW.Addr(), uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) + if r1 == 0 { + err = errnoErr(e1) } return } -func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetModuleInformation.Addr(), uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb)) + if r1 == 0 { + err = errnoErr(e1) } return } -func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func QueryWorkingSetEx(process Handle, pv uintptr, cb uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procQueryWorkingSetEx.Addr(), uintptr(process), uintptr(pv), uintptr(cb)) + if r1 == 0 { + err = errnoErr(e1) } return } -func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) { + ret = procSubscribeServiceChangeNotifications.Find() + if ret != nil { + return + } + r0, _, _ := syscall.SyscallN(procSubscribeServiceChangeNotifications.Addr(), uintptr(service), uintptr(eventType), uintptr(callback), uintptr(callbackCtx), uintptr(unsafe.Pointer(subscription))) + if r0 != 0 { + ret = syscall.Errno(r0) } return } -func listen(s Handle, backlog int32) (err error) { - r1, _, e1 := syscall.Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func UnsubscribeServiceChangeNotifications(subscription uintptr) (err error) { + err = procUnsubscribeServiceChangeNotifications.Find() + if err != nil { + return } + syscall.SyscallN(procUnsubscribeServiceChangeNotifications.Addr(), uintptr(subscription)) return } -func shutdown(s Handle, how int32) (err error) { - r1, _, e1 := syscall.Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetUserNameExW.Addr(), uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) + if r1&0xff == 0 { + err = errnoErr(e1) } return } -func Closesocket(s Handle) (err error) { - r1, _, e1 := syscall.Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procTranslateNameW.Addr(), uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize))) + if r1&0xff == 0 { + err = errnoErr(e1) } return } -func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) +func SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiBuildDriverInfoList.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { - syscall.Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) +func SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiCallClassInstaller.Addr(), uintptr(installFunction), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiCancelDriverInfoSearch.Addr(), uintptr(deviceInfoSet)) + if r1 == 0 { + err = errnoErr(e1) } return } -func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiClassGuidsFromNameExW.Addr(), uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(classGuidList)), uintptr(classGuidListSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + if r1 == 0 { + err = errnoErr(e1) } return } -func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiClassNameFromGuidExW.Addr(), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(className)), uintptr(classNameSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + if r1 == 0 { + err = errnoErr(e1) } return } -func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) { + r0, _, e1 := syscall.SyscallN(procSetupDiCreateDeviceInfoListExW.Addr(), uintptr(unsafe.Pointer(classGUID)), uintptr(hwndParent), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + handle = DevInfo(r0) + if handle == DevInfo(InvalidHandle) { + err = errnoErr(e1) } return } -func GetHostByName(name string) (h *Hostent, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(name) - if err != nil { - return +func setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiCreateDeviceInfoW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(DeviceName)), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(DeviceDescription)), uintptr(hwndParent), uintptr(CreationFlags), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) } - return _GetHostByName(_p0) + return } -func _GetHostByName(name *byte) (h *Hostent, err error) { - r0, _, e1 := syscall.Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - h = (*Hostent)(unsafe.Pointer(r0)) - if h == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiDestroyDeviceInfoList.Addr(), uintptr(deviceInfoSet)) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetServByName(name string, proto string) (s *Servent, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(name) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(proto) - if err != nil { - return +func SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiDestroyDriverInfoList.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) + if r1 == 0 { + err = errnoErr(e1) } - return _GetServByName(_p0, _p1) + return } -func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { - r0, _, e1 := syscall.Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) - s = (*Servent)(unsafe.Pointer(r0)) - if s == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiEnumDeviceInfo.Addr(), uintptr(deviceInfoSet), uintptr(memberIndex), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) } return } -func Ntohs(netshort uint16) (u uint16) { - r0, _, _ := syscall.Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) - u = uint16(r0) +func setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiEnumDriverInfoW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType), uintptr(memberIndex), uintptr(unsafe.Pointer(driverInfoData))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func GetProtoByName(name string) (p *Protoent, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(name) - if err != nil { - return +func setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) { + r0, _, e1 := syscall.SyscallN(procSetupDiGetClassDevsExW.Addr(), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(Enumerator)), uintptr(hwndParent), uintptr(Flags), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + handle = DevInfo(r0) + if handle == DevInfo(InvalidHandle) { + err = errnoErr(e1) } - return _GetProtoByName(_p0) + return } -func _GetProtoByName(name *byte) (p *Protoent, err error) { - r0, _, e1 := syscall.Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - p = (*Protoent)(unsafe.Pointer(r0)) - if p == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetClassInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), uintptr(unsafe.Pointer(requiredSize))) + if r1 == 0 { + err = errnoErr(e1) } return } -func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) { - var _p0 *uint16 - _p0, status = syscall.UTF16PtrFromString(name) - if status != nil { - return +func setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceInfoListDetailW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoSetDetailData))) + if r1 == 0 { + err = errnoErr(e1) } - return _DnsQuery(_p0, qtype, options, extra, qrs, pr) + return } -func _DnsQuery(name *uint16, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) { - r0, _, _ := syscall.Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(name)), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr))) - if r0 != 0 { - status = syscall.Errno(r0) +func setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) + if r1 == 0 { + err = errnoErr(e1) } return } -func DnsRecordListFree(rl *DNSRecord, freetype uint32) { - syscall.Syscall(procDnsRecordListFree.Addr(), 2, uintptr(unsafe.Pointer(rl)), uintptr(freetype), 0) +func setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceInstanceIdW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(instanceId)), uintptr(instanceIdSize), uintptr(unsafe.Pointer(instanceIdRequiredSize))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { - r0, _, _ := syscall.Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) - same = r0 != 0 +func setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetDevicePropertyW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(propertyKey)), uintptr(unsafe.Pointer(propertyType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(flags)) + if r1 == 0 { + err = errnoErr(e1) + } return } -func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { - r0, _, _ := syscall.Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) - if r0 != 0 { - sockerr = syscall.Errno(r0) +func setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetDeviceRegistryPropertyW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyRegDataType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize))) + if r1 == 0 { + err = errnoErr(e1) } return } -func FreeAddrInfoW(addrinfo *AddrinfoW) { - syscall.Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) +func setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetDriverInfoDetailW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)), uintptr(unsafe.Pointer(driverInfoDetailData)), uintptr(driverInfoDetailDataSize), uintptr(unsafe.Pointer(requiredSize))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func GetIfEntry(pIfRow *MibIfRow) (errcode error) { - r0, _, _ := syscall.Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0) - if r0 != 0 { - errcode = syscall.Errno(r0) +func setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetSelectedDevice.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { - r0, _, _ := syscall.Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0) - if r0 != 0 { - errcode = syscall.Errno(r0) +func setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiGetSelectedDriverW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) + if r1 == 0 { + err = errnoErr(e1) } return } -func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) { + r0, _, e1 := syscall.SyscallN(procSetupDiOpenDevRegKey.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(Scope), uintptr(HwProfile), uintptr(KeyType), uintptr(samDesired)) + key = Handle(r0) + if key == InvalidHandle { + err = errnoErr(e1) } return } -func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { - r0, _, e1 := syscall.Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) - n = int32(r0) - if n == -1 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiSetClassInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize)) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { - r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) - if r0 != 0 { - errcode = syscall.Errno(r0) +func SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiSetDeviceInstallParamsW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetACP() (acp uint32) { - r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0) - acp = uint32(r0) +func setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiSetDeviceRegistryPropertyW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize)) + if r1 == 0 { + err = errnoErr(e1) + } return } -func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { - r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) - nwrite = int32(r0) - if nwrite == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiSetSelectedDevice.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) } return } -func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupDiSetSelectedDriverW.Addr(), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procSetupUninstallOEMInfW.Addr(), uintptr(unsafe.Pointer(infFileName)), uintptr(flags), uintptr(reserved)) + if r1 == 0 { + err = errnoErr(e1) } return } -func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { - r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) - if r0 != 0 { - neterr = syscall.Errno(r0) +func commandLineToArgv(cmd *uint16, argc *int32) (argv **uint16, err error) { + r0, _, e1 := syscall.SyscallN(procCommandLineToArgvW.Addr(), uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc))) + argv = (**uint16)(unsafe.Pointer(r0)) + if argv == nil { + err = errnoErr(e1) } return } -func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) { - r0, _, _ := syscall.Syscall(procNetGetJoinInformation.Addr(), 3, uintptr(unsafe.Pointer(server)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(bufType))) +func shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) { + r0, _, _ := syscall.SyscallN(procSHGetKnownFolderPath.Addr(), uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(token), uintptr(unsafe.Pointer(path))) if r0 != 0 { - neterr = syscall.Errno(r0) + ret = syscall.Errno(r0) } return } -func NetApiBufferFree(buf *byte) (neterr error) { - r0, _, _ := syscall.Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) - if r0 != 0 { - neterr = syscall.Errno(r0) +func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) { + r1, _, e1 := syscall.SyscallN(procShellExecuteW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) + if r1 <= 32 { + err = errnoErr(e1) } return } -func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func EnumChildWindows(hwnd HWND, enumFunc uintptr, param unsafe.Pointer) { + syscall.SyscallN(procEnumChildWindows.Addr(), uintptr(hwnd), uintptr(enumFunc), uintptr(param)) return } -func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) +func EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) { + r1, _, e1 := syscall.SyscallN(procEnumWindows.Addr(), uintptr(enumFunc), uintptr(param)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { - r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) +func ExitWindowsEx(flags uint32, reason uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procExitWindowsEx.Addr(), uintptr(flags), uintptr(reason)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { - r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetClassName(hwnd HWND, className *uint16, maxCount int32) (copied int32, err error) { + r0, _, e1 := syscall.SyscallN(procGetClassNameW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(className)), uintptr(maxCount)) + copied = int32(r0) + if copied == 0 { + err = errnoErr(e1) } return } -func GetLengthSid(sid *SID) (len uint32) { - r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - len = uint32(r0) +func GetDesktopWindow() (hwnd HWND) { + r0, _, _ := syscall.SyscallN(procGetDesktopWindow.Addr()) + hwnd = HWND(r0) return } -func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { - r1, _, e1 := syscall.Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetForegroundWindow() (hwnd HWND) { + r0, _, _ := syscall.SyscallN(procGetForegroundWindow.Addr()) + hwnd = HWND(r0) return } -func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) { - r1, _, e1 := syscall.Syscall12(procAllocateAndInitializeSid.Addr(), 11, uintptr(unsafe.Pointer(identAuth)), uintptr(subAuth), uintptr(subAuth0), uintptr(subAuth1), uintptr(subAuth2), uintptr(subAuth3), uintptr(subAuth4), uintptr(subAuth5), uintptr(subAuth6), uintptr(subAuth7), uintptr(unsafe.Pointer(sid)), 0) +func GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) { + r1, _, e1 := syscall.SyscallN(procGetGUIThreadInfo.Addr(), uintptr(thread), uintptr(unsafe.Pointer(info))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCreateWellKnownSid.Addr(), 4, uintptr(sidType), uintptr(unsafe.Pointer(domainSid)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sizeSid)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetKeyboardLayout(tid uint32) (hkl Handle) { + r0, _, _ := syscall.SyscallN(procGetKeyboardLayout.Addr(), uintptr(tid)) + hkl = Handle(r0) return } -func isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) { - r0, _, _ := syscall.Syscall(procIsWellKnownSid.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(sidType), 0) - isWellKnown = r0 != 0 +func GetShellWindow() (shellWindow HWND) { + r0, _, _ := syscall.SyscallN(procGetShellWindow.Addr()) + shellWindow = HWND(r0) return } -func FreeSid(sid *SID) (err error) { - r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - if r1 != 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetWindowThreadProcessId.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(pid))) + tid = uint32(r0) + if tid == 0 { + err = errnoErr(e1) } return } -func EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) { - r0, _, _ := syscall.Syscall(procEqualSid.Addr(), 2, uintptr(unsafe.Pointer(sid1)), uintptr(unsafe.Pointer(sid2)), 0) - isEqual = r0 != 0 +func IsWindow(hwnd HWND) (isWindow bool) { + r0, _, _ := syscall.SyscallN(procIsWindow.Addr(), uintptr(hwnd)) + isWindow = r0 != 0 return } -func getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) { - r0, _, _ := syscall.Syscall(procGetSidIdentifierAuthority.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - authority = (*SidIdentifierAuthority)(unsafe.Pointer(r0)) +func IsWindowUnicode(hwnd HWND) (isUnicode bool) { + r0, _, _ := syscall.SyscallN(procIsWindowUnicode.Addr(), uintptr(hwnd)) + isUnicode = r0 != 0 return } -func getSidSubAuthorityCount(sid *SID) (count *uint8) { - r0, _, _ := syscall.Syscall(procGetSidSubAuthorityCount.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - count = (*uint8)(unsafe.Pointer(r0)) +func IsWindowVisible(hwnd HWND) (isVisible bool) { + r0, _, _ := syscall.SyscallN(procIsWindowVisible.Addr(), uintptr(hwnd)) + isVisible = r0 != 0 return } -func getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) { - r0, _, _ := syscall.Syscall(procGetSidSubAuthority.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(index), 0) - subAuthority = (*uint32)(unsafe.Pointer(r0)) +func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) { + r0, _, e1 := syscall.SyscallN(procLoadKeyboardLayoutW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(flags)) + hkl = Handle(r0) + if hkl == 0 { + err = errnoErr(e1) + } return } -func isValidSid(sid *SID) (isValid bool) { - r0, _, _ := syscall.Syscall(procIsValidSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - isValid = r0 != 0 +func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { + r0, _, e1 := syscall.SyscallN(procMessageBoxW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype)) + ret = int32(r0) + if ret == 0 { + err = errnoErr(e1) + } return } -func checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) { - r1, _, e1 := syscall.Syscall(procCheckTokenMembership.Addr(), 3, uintptr(tokenHandle), uintptr(unsafe.Pointer(sidToCheck)), uintptr(unsafe.Pointer(isMember))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { + r0, _, _ := syscall.SyscallN(procToUnicodeEx.Addr(), uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl)) + ret = int32(r0) return } -func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { - r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(process), uintptr(access), uintptr(unsafe.Pointer(token))) +func UnloadKeyboardLayout(hkl Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procUnloadKeyboardLayout.Addr(), uintptr(hkl)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) { +func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { var _p0 uint32 - if openAsSelf { + if inheritExisting { _p0 = 1 - } else { - _p0 = 0 } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCreateEnvironmentBlock.Addr(), uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ImpersonateSelf(impersonationlevel uint32) (err error) { - r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) +func DestroyEnvironmentBlock(block *uint16) (err error) { + r1, _, e1 := syscall.SyscallN(procDestroyEnvironmentBlock.Addr(), uintptr(unsafe.Pointer(block))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func RevertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) +func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetUserProfileDirectoryW.Addr(), uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetThreadToken(thread *Handle, token Token) (err error) { - r1, _, e1 := syscall.Syscall(procSetThreadToken.Addr(), 2, uintptr(unsafe.Pointer(thread)), uintptr(token), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(filename) + if err != nil { + return + } + return _GetFileVersionInfoSize(_p0, zeroHandle) +} + +func _GetFileVersionInfoSize(filename *uint16, zeroHandle *Handle) (bufSize uint32, err error) { + r0, _, e1 := syscall.SyscallN(procGetFileVersionInfoSizeW.Addr(), uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(zeroHandle))) + bufSize = uint32(r0) + if bufSize == 0 { + err = errnoErr(e1) } return } -func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) { - r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) +func GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(filename) + if err != nil { + return + } + return _GetFileVersionInfo(_p0, handle, bufSize, buffer) +} + +func _GetFileVersionInfo(filename *uint16, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { + r1, _, e1 := syscall.SyscallN(procGetFileVersionInfoW.Addr(), uintptr(unsafe.Pointer(filename)), uintptr(handle), uintptr(bufSize), uintptr(buffer)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) { - var _p0 uint32 - if disableAllPrivileges { - _p0 = 1 - } else { - _p0 = 0 +func VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(subBlock) + if err != nil { + return } - r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) + return _VerQueryValue(block, _p0, pointerToBufferPointer, bufSize) +} + +func _VerQueryValue(block unsafe.Pointer, subBlock *uint16, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procVerQueryValueW.Addr(), uintptr(block), uintptr(unsafe.Pointer(subBlock)), uintptr(pointerToBufferPointer), uintptr(unsafe.Pointer(bufSize))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) { - var _p0 uint32 - if resetToDefault { - _p0 = 1 - } else { - _p0 = 0 +func TimeBeginPeriod(period uint32) (err error) { + r1, _, e1 := syscall.SyscallN(proctimeBeginPeriod.Addr(), uintptr(period)) + if r1 != 0 { + err = errnoErr(e1) } - r1, _, e1 := syscall.Syscall6(procAdjustTokenGroups.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + return +} + +func TimeEndPeriod(period uint32) (err error) { + r1, _, e1 := syscall.SyscallN(proctimeEndPeriod.Addr(), uintptr(period)) + if r1 != 0 { + err = errnoErr(e1) + } + return +} + +func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) { + r0, _, _ := syscall.SyscallN(procWinVerifyTrustEx.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data))) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func FreeAddrInfoW(addrinfo *AddrinfoW) { + syscall.SyscallN(procFreeAddrInfoW.Addr(), uintptr(unsafe.Pointer(addrinfo))) + return +} + +func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { + r0, _, _ := syscall.SyscallN(procGetAddrInfoW.Addr(), uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result))) + if r0 != 0 { + sockerr = syscall.Errno(r0) } return } -func GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSACleanup() (err error) { + r1, _, e1 := syscall.SyscallN(procWSACleanup.Addr()) + if r1 == socket_error { + err = errnoErr(e1) } return } -func SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSADuplicateSocket(s Handle, processID uint32, info *WSAProtocolInfo) (err error) { + r1, _, e1 := syscall.SyscallN(procWSADuplicateSocketW.Addr(), uintptr(s), uintptr(processID), uintptr(unsafe.Pointer(info))) + if r1 != 0 { + err = errnoErr(e1) } return } -func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) { - r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(existingToken), uintptr(desiredAccess), uintptr(unsafe.Pointer(tokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(newToken))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { + r0, _, e1 := syscall.SyscallN(procWSAEnumProtocolsW.Addr(), uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) + n = int32(r0) + if n == -1 { + err = errnoErr(e1) } return } -func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetUserProfileDirectoryW.Addr(), 3, uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) +func WSAGetOverlappedResult(h Handle, o *Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } + r1, _, e1 := syscall.SyscallN(procWSAGetOverlappedResult.Addr(), uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + r1, _, e1 := syscall.SyscallN(procWSAIoctl.Addr(), uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSALookupServiceBegin(querySet *WSAQUERYSET, flags uint32, handle *Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procWSALookupServiceBeginW.Addr(), uintptr(unsafe.Pointer(querySet)), uintptr(flags), uintptr(unsafe.Pointer(handle))) + if r1 == socket_error { + err = errnoErr(e1) } return } -func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSALookupServiceEnd(handle Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procWSALookupServiceEnd.Addr(), uintptr(handle)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func WTSQueryUserToken(session uint32, token *Token) (err error) { - r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSALookupServiceNext(handle Handle, flags uint32, size *int32, querySet *WSAQUERYSET) (err error) { + r1, _, e1 := syscall.SyscallN(procWSALookupServiceNextW.Addr(), uintptr(handle), uintptr(flags), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(querySet))) + if r1 == socket_error { + err = errnoErr(e1) } return } -func WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procWTSEnumerateSessionsW.Addr(), 5, uintptr(handle), uintptr(reserved), uintptr(version), uintptr(unsafe.Pointer(sessions)), uintptr(unsafe.Pointer(count)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procWSARecv.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) } return } -func WTSFreeMemory(ptr uintptr) { - syscall.Syscall(procWTSFreeMemory.Addr(), 1, uintptr(ptr), 0, 0) +func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procWSARecvFrom.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) + } return } -func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) - if r0 != 0 { - ret = syscall.Errno(r0) +func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procWSASend.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) } return } -func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) { - syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) +func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.SyscallN(procWSASendTo.Addr(), uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) + } return } -func getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - var _p0 *uint16 - _p0, ret = syscall.UTF16PtrFromString(objectName) - if ret != nil { - return +func WSASocket(af int32, typ int32, protocol int32, protoInfo *WSAProtocolInfo, group uint32, flags uint32) (handle Handle, err error) { + r0, _, e1 := syscall.SyscallN(procWSASocketW.Addr(), uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protoInfo)), uintptr(group), uintptr(flags)) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) } - return _getNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl, sd) + return } -func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procGetNamedSecurityInfoW.Addr(), 8, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) +func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { + r0, _, _ := syscall.SyscallN(procWSAStartup.Addr(), uintptr(verreq), uintptr(unsafe.Pointer(data))) if r0 != 0 { - ret = syscall.Errno(r0) + sockerr = syscall.Errno(r0) } return } -func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { - var _p0 *uint16 - _p0, ret = syscall.UTF16PtrFromString(objectName) - if ret != nil { - return +func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.SyscallN(procbind.Addr(), uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + err = errnoErr(e1) } - return _SetNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl) + return } -func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { - r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfoW.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) +func Closesocket(s Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procclosesocket.Addr(), uintptr(s)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procBuildSecurityDescriptorW.Addr(), 9, uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) - if r0 != 0 { - ret = syscall.Errno(r0) +func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.SyscallN(procconnect.Addr(), uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) { - r1, _, e1 := syscall.Syscall(procInitializeSecurityDescriptor.Addr(), 2, uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetHostByName(name string) (h *Hostent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return } - return + return _GetHostByName(_p0) } -func getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func _GetHostByName(name *byte) (h *Hostent, err error) { + r0, _, e1 := syscall.SyscallN(procgethostbyname.Addr(), uintptr(unsafe.Pointer(name))) + h = (*Hostent)(unsafe.Pointer(r0)) + if h == nil { + err = errnoErr(e1) } return } -func getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) { - var _p0 uint32 - if *daclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if *daclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) - *daclPresent = _p0 != 0 - *daclDefaulted = _p1 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := syscall.SyscallN(procgetpeername.Addr(), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + err = errnoErr(e1) } return } -func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) { - var _p0 uint32 - if *saclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if *saclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) - *saclPresent = _p0 != 0 - *saclDefaulted = _p1 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func GetProtoByName(name string) (p *Protoent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return } - return + return _GetProtoByName(_p0) } -func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) { - var _p0 uint32 - if *ownerDefaulted { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) - *ownerDefaulted = _p0 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func _GetProtoByName(name *byte) (p *Protoent, err error) { + r0, _, e1 := syscall.SyscallN(procgetprotobyname.Addr(), uintptr(unsafe.Pointer(name))) + p = (*Protoent)(unsafe.Pointer(r0)) + if p == nil { + err = errnoErr(e1) } return } -func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) { - var _p0 uint32 - if *groupDefaulted { - _p0 = 1 - } else { - _p0 = 0 +func GetServByName(name string, proto string) (s *Servent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return } - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) - *groupDefaulted = _p0 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(proto) + if err != nil { + return } - return -} - -func getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) - len = uint32(r0) - return + return _GetServByName(_p0, _p1) } -func getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) - if r0 != 0 { - ret = syscall.Errno(r0) +func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { + r0, _, e1 := syscall.SyscallN(procgetservbyname.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto))) + s = (*Servent)(unsafe.Pointer(r0)) + if s == nil { + err = errnoErr(e1) } return } -func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { - r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) - isValid = r0 != 0 +func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := syscall.SyscallN(procgetsockname.Addr(), uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + err = errnoErr(e1) + } return } -func setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) { - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { + r1, _, e1 := syscall.SyscallN(procgetsockopt.Addr(), uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen))) + if r1 == socket_error { + err = errnoErr(e1) } return } -func setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) { - var _p0 uint32 - if daclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if daclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func listen(s Handle, backlog int32) (err error) { + r1, _, e1 := syscall.SyscallN(proclisten.Addr(), uintptr(s), uintptr(backlog)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) { - var _p0 uint32 - if saclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if saclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func Ntohs(netshort uint16) (u uint16) { + r0, _, _ := syscall.SyscallN(procntohs.Addr(), uintptr(netshort)) + u = uint16(r0) return } -func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) { - var _p0 uint32 - if ownerDefaulted { - _p0 = 1 - } else { - _p0 = 0 +func recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + r0, _, e1 := syscall.SyscallN(procrecvfrom.Addr(), uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int32(r0) + if n == -1 { + err = errnoErr(e1) } return } -func setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) { - var _p0 uint32 - if groupDefaulted { - _p0 = 1 - } else { - _p0 = 0 +func sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + r1, _, e1 := syscall.SyscallN(procsendto.Addr(), uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(tolen)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) { - syscall.Syscall(procSetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) - return -} - -func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(str) - if err != nil { - return +func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { + r1, _, e1 := syscall.SyscallN(procsetsockopt.Addr(), uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen)) + if r1 == socket_error { + err = errnoErr(e1) } - return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) + return } -func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func shutdown(s Handle, how int32) (err error) { + r1, _, e1 := syscall.SyscallN(procshutdown.Addr(), uintptr(s), uintptr(how)) + if r1 == socket_error { + err = errnoErr(e1) } return } -func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { + r0, _, e1 := syscall.SyscallN(procsocket.Addr(), uintptr(af), uintptr(typ), uintptr(protocol)) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) } return } -func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize)), 0) +func WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procWTSEnumerateSessionsW.Addr(), uintptr(handle), uintptr(reserved), uintptr(version), uintptr(unsafe.Pointer(sessions)), uintptr(unsafe.Pointer(count))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func WTSFreeMemory(ptr uintptr) { + syscall.SyscallN(procWTSFreeMemory.Addr(), uintptr(ptr)) return } -func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) { - r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) +func WTSQueryUserToken(session uint32, token *Token) (err error) { + r1, _, e1 := syscall.SyscallN(procWTSQueryUserToken.Addr(), uintptr(session), uintptr(unsafe.Pointer(token))) + if r1 == 0 { + err = errnoErr(e1) } return } diff --git a/vendor/golang.org/x/time/AUTHORS b/vendor/golang.org/x/time/AUTHORS deleted file mode 100644 index 15167cd..0000000 --- a/vendor/golang.org/x/time/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/time/CONTRIBUTORS b/vendor/golang.org/x/time/CONTRIBUTORS deleted file mode 100644 index 1c4577e..0000000 --- a/vendor/golang.org/x/time/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/time/LICENSE b/vendor/golang.org/x/time/LICENSE index 6a66aea..2a7cf70 100644 --- a/vendor/golang.org/x/time/LICENSE +++ b/vendor/golang.org/x/time/LICENSE @@ -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. diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go index a114b1a..563270c 100644 --- a/vendor/golang.org/x/time/rate/rate.go +++ b/vendor/golang.org/x/time/rate/rate.go @@ -52,11 +52,12 @@ func Every(interval time.Duration) Limit { // or its associated context.Context is canceled. // // The methods AllowN, ReserveN, and WaitN consume n tokens. +// +// Limiter is safe for simultaneous use by multiple goroutines. type Limiter struct { - limit Limit - burst int - mu sync.Mutex + limit Limit + burst int tokens float64 // last is the last time the limiter's tokens field was updated last time.Time @@ -76,28 +77,44 @@ func (lim *Limiter) Limit() Limit { // Burst values allow more events to happen at once. // A zero Burst allows no events, unless limit == Inf. func (lim *Limiter) Burst() int { + lim.mu.Lock() + defer lim.mu.Unlock() return lim.burst } +// TokensAt returns the number of tokens available at time t. +func (lim *Limiter) TokensAt(t time.Time) float64 { + lim.mu.Lock() + tokens := lim.advance(t) // does not mutate lim + lim.mu.Unlock() + return tokens +} + +// Tokens returns the number of tokens available now. +func (lim *Limiter) Tokens() float64 { + return lim.TokensAt(time.Now()) +} + // NewLimiter returns a new Limiter that allows events up to rate r and permits // bursts of at most b tokens. func NewLimiter(r Limit, b int) *Limiter { return &Limiter{ - limit: r, - burst: b, + limit: r, + burst: b, + tokens: float64(b), } } -// Allow is shorthand for AllowN(time.Now(), 1). +// Allow reports whether an event may happen now. func (lim *Limiter) Allow() bool { return lim.AllowN(time.Now(), 1) } -// AllowN reports whether n events may happen at time now. +// AllowN reports whether n events may happen at time t. // Use this method if you intend to drop / skip events that exceed the rate limit. // Otherwise use Reserve or Wait. -func (lim *Limiter) AllowN(now time.Time, n int) bool { - return lim.reserveN(now, n, 0).ok +func (lim *Limiter) AllowN(t time.Time, n int) bool { + return lim.reserveN(t, n, 0).ok } // A Reservation holds information about events that are permitted by a Limiter to happen after a delay. @@ -124,17 +141,17 @@ func (r *Reservation) Delay() time.Duration { } // InfDuration is the duration returned by Delay when a Reservation is not OK. -const InfDuration = time.Duration(1<<63 - 1) +const InfDuration = time.Duration(math.MaxInt64) // DelayFrom returns the duration for which the reservation holder must wait // before taking the reserved action. Zero duration means act immediately. // InfDuration means the limiter cannot grant the tokens requested in this // Reservation within the maximum wait time. -func (r *Reservation) DelayFrom(now time.Time) time.Duration { +func (r *Reservation) DelayFrom(t time.Time) time.Duration { if !r.ok { return InfDuration } - delay := r.timeToAct.Sub(now) + delay := r.timeToAct.Sub(t) if delay < 0 { return 0 } @@ -144,13 +161,12 @@ func (r *Reservation) DelayFrom(now time.Time) time.Duration { // Cancel is shorthand for CancelAt(time.Now()). func (r *Reservation) Cancel() { r.CancelAt(time.Now()) - return } // CancelAt indicates that the reservation holder will not perform the reserved action // and reverses the effects of this Reservation on the rate limit as much as possible, // considering that other reservations may have already been made. -func (r *Reservation) CancelAt(now time.Time) { +func (r *Reservation) CancelAt(t time.Time) { if !r.ok { return } @@ -158,7 +174,7 @@ func (r *Reservation) CancelAt(now time.Time) { r.lim.mu.Lock() defer r.lim.mu.Unlock() - if r.lim.limit == Inf || r.tokens == 0 || r.timeToAct.Before(now) { + if r.lim.limit == Inf || r.tokens == 0 || r.timeToAct.Before(t) { return } @@ -170,23 +186,21 @@ func (r *Reservation) CancelAt(now time.Time) { return } // advance time to now - now, _, tokens := r.lim.advance(now) + tokens := r.lim.advance(t) // calculate new number of tokens tokens += restoreTokens if burst := float64(r.lim.burst); tokens > burst { tokens = burst } // update state - r.lim.last = now + r.lim.last = t r.lim.tokens = tokens - if r.timeToAct == r.lim.lastEvent { + if r.timeToAct.Equal(r.lim.lastEvent) { prevEvent := r.timeToAct.Add(r.limit.durationFromTokens(float64(-r.tokens))) - if !prevEvent.Before(now) { + if !prevEvent.Before(t) { r.lim.lastEvent = prevEvent } } - - return } // Reserve is shorthand for ReserveN(time.Now(), 1). @@ -198,18 +212,20 @@ func (lim *Limiter) Reserve() *Reservation { // The Limiter takes this Reservation into account when allowing future events. // The returned Reservation’s OK() method returns false if n exceeds the Limiter's burst size. // Usage example: -// r := lim.ReserveN(time.Now(), 1) -// if !r.OK() { -// // Not allowed to act! Did you remember to set lim.burst to be > 0 ? -// return -// } -// time.Sleep(r.Delay()) -// Act() +// +// r := lim.ReserveN(time.Now(), 1) +// if !r.OK() { +// // Not allowed to act! Did you remember to set lim.burst to be > 0 ? +// return +// } +// time.Sleep(r.Delay()) +// Act() +// // Use this method if you wish to wait and slow down in accordance with the rate limit without dropping events. // If you need to respect a deadline or cancel the delay, use Wait instead. // To drop or skip events exceeding rate limit, use Allow instead. -func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation { - r := lim.reserveN(now, n, InfDuration) +func (lim *Limiter) ReserveN(t time.Time, n int) *Reservation { + r := lim.reserveN(t, n, InfDuration) return &r } @@ -223,13 +239,25 @@ func (lim *Limiter) Wait(ctx context.Context) (err error) { // canceled, or the expected wait time exceeds the Context's Deadline. // The burst limit is ignored if the rate limit is Inf. func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { + // The test code calls lim.wait with a fake timer generator. + // This is the real timer generator. + newTimer := func(d time.Duration) (<-chan time.Time, func() bool, func()) { + timer := time.NewTimer(d) + return timer.C, timer.Stop, func() {} + } + + return lim.wait(ctx, n, time.Now(), newTimer) +} + +// wait is the internal implementation of WaitN. +func (lim *Limiter) wait(ctx context.Context, n int, t time.Time, newTimer func(d time.Duration) (<-chan time.Time, func() bool, func())) error { lim.mu.Lock() burst := lim.burst limit := lim.limit lim.mu.Unlock() if n > burst && limit != Inf { - return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst) + return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, burst) } // Check if ctx is already cancelled select { @@ -238,25 +266,25 @@ func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { default: } // Determine wait limit - now := time.Now() waitLimit := InfDuration if deadline, ok := ctx.Deadline(); ok { - waitLimit = deadline.Sub(now) + waitLimit = deadline.Sub(t) } // Reserve - r := lim.reserveN(now, n, waitLimit) + r := lim.reserveN(t, n, waitLimit) if !r.ok { return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", n) } // Wait if necessary - delay := r.DelayFrom(now) + delay := r.DelayFrom(t) if delay == 0 { return nil } - t := time.NewTimer(delay) - defer t.Stop() + ch, stop, advance := newTimer(delay) + defer stop() + advance() // only has an effect when testing select { - case <-t.C: + case <-ch: // We can proceed. return nil case <-ctx.Done(): @@ -275,13 +303,13 @@ func (lim *Limiter) SetLimit(newLimit Limit) { // SetLimitAt sets a new Limit for the limiter. The new Limit, and Burst, may be violated // or underutilized by those which reserved (using Reserve or Wait) but did not yet act // before SetLimitAt was called. -func (lim *Limiter) SetLimitAt(now time.Time, newLimit Limit) { +func (lim *Limiter) SetLimitAt(t time.Time, newLimit Limit) { lim.mu.Lock() defer lim.mu.Unlock() - now, _, tokens := lim.advance(now) + tokens := lim.advance(t) - lim.last = now + lim.last = t lim.tokens = tokens lim.limit = newLimit } @@ -292,13 +320,13 @@ func (lim *Limiter) SetBurst(newBurst int) { } // SetBurstAt sets a new burst size for the limiter. -func (lim *Limiter) SetBurstAt(now time.Time, newBurst int) { +func (lim *Limiter) SetBurstAt(t time.Time, newBurst int) { lim.mu.Lock() defer lim.mu.Unlock() - now, _, tokens := lim.advance(now) + tokens := lim.advance(t) - lim.last = now + lim.last = t lim.tokens = tokens lim.burst = newBurst } @@ -306,20 +334,20 @@ func (lim *Limiter) SetBurstAt(now time.Time, newBurst int) { // reserveN is a helper method for AllowN, ReserveN, and WaitN. // maxFutureReserve specifies the maximum reservation wait duration allowed. // reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN. -func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation { +func (lim *Limiter) reserveN(t time.Time, n int, maxFutureReserve time.Duration) Reservation { lim.mu.Lock() + defer lim.mu.Unlock() if lim.limit == Inf { - lim.mu.Unlock() return Reservation{ ok: true, lim: lim, tokens: n, - timeToAct: now, + timeToAct: t, } } - now, last, tokens := lim.advance(now) + tokens := lim.advance(t) // Calculate the remaining number of tokens resulting from the request. tokens -= float64(n) @@ -341,60 +369,59 @@ func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duratio } if ok { r.tokens = n - r.timeToAct = now.Add(waitDuration) - } + r.timeToAct = t.Add(waitDuration) - // Update state - if ok { - lim.last = now + // Update state + lim.last = t lim.tokens = tokens lim.lastEvent = r.timeToAct - } else { - lim.last = last } - lim.mu.Unlock() return r } -// advance calculates and returns an updated state for lim resulting from the passage of time. +// advance calculates and returns an updated number of tokens for lim +// resulting from the passage of time. // lim is not changed. -func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) { +// advance requires that lim.mu is held. +func (lim *Limiter) advance(t time.Time) (newTokens float64) { last := lim.last - if now.Before(last) { - last = now - } - - // Avoid making delta overflow below when last is very old. - maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens) - elapsed := now.Sub(last) - if elapsed > maxElapsed { - elapsed = maxElapsed + if t.Before(last) { + last = t } // Calculate the new number of tokens, due to time that passed. + elapsed := t.Sub(last) delta := lim.limit.tokensFromDuration(elapsed) tokens := lim.tokens + delta if burst := float64(lim.burst); tokens > burst { tokens = burst } - - return now, last, tokens + return tokens } // durationFromTokens is a unit conversion function from the number of tokens to the duration // of time it takes to accumulate them at a rate of limit tokens per second. func (limit Limit) durationFromTokens(tokens float64) time.Duration { - seconds := tokens / float64(limit) - return time.Nanosecond * time.Duration(1e9*seconds) + if limit <= 0 { + return InfDuration + } + + duration := (tokens / float64(limit)) * float64(time.Second) + + // Cap the duration to the maximum representable int64 value, to avoid overflow. + if duration > float64(math.MaxInt64) { + return InfDuration + } + + return time.Duration(duration) } // tokensFromDuration is a unit conversion function from a time duration to the number of tokens // which could be accumulated during that duration at a rate of limit tokens per second. func (limit Limit) tokensFromDuration(d time.Duration) float64 { - // Split the integer and fractional parts ourself to minimize rounding errors. - // See golang.org/issues/34861. - sec := float64(d/time.Second) * float64(limit) - nsec := float64(d%time.Second) * float64(limit) - return sec + nsec/1e9 + if limit <= 0 { + return 0 + } + return d.Seconds() * float64(limit) } diff --git a/vendor/golang.org/x/time/rate/sometimes.go b/vendor/golang.org/x/time/rate/sometimes.go new file mode 100644 index 0000000..9b83932 --- /dev/null +++ b/vendor/golang.org/x/time/rate/sometimes.go @@ -0,0 +1,69 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rate + +import ( + "sync" + "time" +) + +// Sometimes will perform an action occasionally. The First, Every, and +// Interval fields govern the behavior of Do, which performs the action. +// A zero Sometimes value will perform an action exactly once. +// +// # Example: logging with rate limiting +// +// var sometimes = rate.Sometimes{First: 3, Interval: 10*time.Second} +// func Spammy() { +// sometimes.Do(func() { log.Info("here I am!") }) +// } +type Sometimes struct { + First int // if non-zero, the first N calls to Do will run f. + Every int // if non-zero, every Nth call to Do will run f. + Interval time.Duration // if non-zero and Interval has elapsed since f's last run, Do will run f. + + mu sync.Mutex + count int // number of Do calls + last time.Time // last time f was run +} + +// Do runs the function f as allowed by First, Every, and Interval. +// +// The model is a union (not intersection) of filters. The first call to Do +// always runs f. Subsequent calls to Do run f if allowed by First or Every or +// Interval. +// +// A non-zero First:N causes the first N Do(f) calls to run f. +// +// A non-zero Every:M causes every Mth Do(f) call, starting with the first, to +// run f. +// +// A non-zero Interval causes Do(f) to run f if Interval has elapsed since +// Do last ran f. +// +// Specifying multiple filters produces the union of these execution streams. +// For example, specifying both First:N and Every:M causes the first N Do(f) +// calls and every Mth Do(f) call, starting with the first, to run f. See +// Examples for more. +// +// If Do is called multiple times simultaneously, the calls will block and run +// serially. Therefore, Do is intended for lightweight operations. +// +// Because a call to Do may block until f returns, if f causes Do to be called, +// it will deadlock. +func (s *Sometimes) Do(f func()) { + s.mu.Lock() + defer s.mu.Unlock() + if s.count == 0 || + (s.First > 0 && s.count < s.First) || + (s.Every > 0 && s.count%s.Every == 0) || + (s.Interval > 0 && time.Since(s.last) >= s.Interval) { + f() + if s.Interval > 0 { + s.last = time.Now() + } + } + s.count++ +} diff --git a/vendor/gopkg.in/yaml.v3/.travis.yml b/vendor/gopkg.in/yaml.v3/.travis.yml deleted file mode 100644 index 04d4dae..0000000 --- a/vendor/gopkg.in/yaml.v3/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go - -go: - - "1.4.x" - - "1.5.x" - - "1.6.x" - - "1.7.x" - - "1.8.x" - - "1.9.x" - - "1.10.x" - - "1.11.x" - - "1.12.x" - - "1.13.x" - - "tip" - -go_import_path: gopkg.in/yaml.v3 diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go index 65846e6..ae7d049 100644 --- a/vendor/gopkg.in/yaml.v3/apic.go +++ b/vendor/gopkg.in/yaml.v3/apic.go @@ -108,6 +108,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) { raw_buffer: make([]byte, 0, output_raw_buffer_size), states: make([]yaml_emitter_state_t, 0, initial_stack_size), events: make([]yaml_event_t, 0, initial_queue_size), + best_width: -1, } } diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go index be63169..0173b69 100644 --- a/vendor/gopkg.in/yaml.v3/decode.go +++ b/vendor/gopkg.in/yaml.v3/decode.go @@ -35,6 +35,7 @@ type parser struct { doc *Node anchors map[string]*Node doneInit bool + textless bool } func newParser(b []byte) *parser { @@ -99,7 +100,10 @@ func (p *parser) peek() yaml_event_type_t { if p.event.typ != yaml_NO_EVENT { return p.event.typ } - if !yaml_parser_parse(&p.parser, &p.event) { + // It's curious choice from the underlying API to generally return a + // positive result on success, but on this case return true in an error + // scenario. This was the source of bugs in the past (issue #666). + if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { p.fail() } return p.event.typ @@ -108,14 +112,18 @@ func (p *parser) peek() yaml_event_type_t { func (p *parser) fail() { var where string var line int - if p.parser.problem_mark.line != 0 { + if p.parser.context_mark.line != 0 { + line = p.parser.context_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } + } else if p.parser.problem_mark.line != 0 { line = p.parser.problem_mark.line // Scanner errors don't iterate line before returning error if p.parser.error == yaml_SCANNER_ERROR { line++ } - } else if p.parser.context_mark.line != 0 { - line = p.parser.context_mark.line } if line != 0 { where = "line " + strconv.Itoa(line) + ": " @@ -169,17 +177,20 @@ func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { } else if kind == ScalarNode { tag, _ = resolve("", value) } - return &Node{ - Kind: kind, - Tag: tag, - Value: value, - Style: style, - Line: p.event.start_mark.line + 1, - Column: p.event.start_mark.column + 1, - HeadComment: string(p.event.head_comment), - LineComment: string(p.event.line_comment), - FootComment: string(p.event.foot_comment), + n := &Node{ + Kind: kind, + Tag: tag, + Value: value, + Style: style, + } + if !p.textless { + n.Line = p.event.start_mark.line + 1 + n.Column = p.event.start_mark.column + 1 + n.HeadComment = string(p.event.head_comment) + n.LineComment = string(p.event.line_comment) + n.FootComment = string(p.event.foot_comment) } + return n } func (p *parser) parseChild(parent *Node) *Node { @@ -312,6 +323,8 @@ type decoder struct { decodeCount int aliasCount int aliasDepth int + + mergedFields map[interface{}]bool } var ( @@ -497,8 +510,13 @@ func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { good = d.mapping(n, out) case SequenceNode: good = d.sequence(n, out) + case 0: + if n.IsZero() { + return d.null(out) + } + fallthrough default: - panic("internal error: unknown node kind: " + strconv.Itoa(int(n.Kind))) + failf("cannot decode node with unknown kind %d", n.Kind) } return good } @@ -533,6 +551,17 @@ func resetMap(out reflect.Value) { } } +func (d *decoder) null(out reflect.Value) bool { + if out.CanAddr() { + switch out.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + out.Set(reflect.Zero(out.Type())) + return true + } + } + return false +} + func (d *decoder) scalar(n *Node, out reflect.Value) bool { var tag string var resolved interface{} @@ -550,14 +579,7 @@ func (d *decoder) scalar(n *Node, out reflect.Value) bool { } } if resolved == nil { - if out.CanAddr() { - switch out.Kind() { - case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - out.Set(reflect.Zero(out.Type())) - return true - } - } - return false + return d.null(out) } if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { // We've resolved to exactly the type we want, so use that. @@ -791,16 +813,30 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { } } + mergedFields := d.mergedFields + d.mergedFields = nil + + var mergeNode *Node + + mapIsNew := false if out.IsNil() { out.Set(reflect.MakeMap(outt)) + mapIsNew = true } for i := 0; i < l; i += 2 { if isMerge(n.Content[i]) { - d.merge(n.Content[i+1], out) + mergeNode = n.Content[i+1] continue } k := reflect.New(kt).Elem() if d.unmarshal(n.Content[i], k) { + if mergedFields != nil { + ki := k.Interface() + if mergedFields[ki] { + continue + } + mergedFields[ki] = true + } kkind := k.Kind() if kkind == reflect.Interface { kkind = k.Elem().Kind() @@ -809,11 +845,17 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { failf("invalid map key: %#v", k.Interface()) } e := reflect.New(et).Elem() - if d.unmarshal(n.Content[i+1], e) { + if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { out.SetMapIndex(k, e) } } } + + d.mergedFields = mergedFields + if mergeNode != nil { + d.merge(n, mergeNode, out) + } + d.stringMapType = stringMapType d.generalMapType = generalMapType return true @@ -825,7 +867,8 @@ func isStringMap(n *Node) bool { } l := len(n.Content) for i := 0; i < l; i += 2 { - if n.Content[i].ShortTag() != strTag { + shortTag := n.Content[i].ShortTag() + if shortTag != strTag && shortTag != mergeTag { return false } } @@ -842,7 +885,6 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { var elemType reflect.Type if sinfo.InlineMap != -1 { inlineMap = out.Field(sinfo.InlineMap) - inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) elemType = inlineMap.Type().Elem() } @@ -851,6 +893,9 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { d.prepare(n, field) } + mergedFields := d.mergedFields + d.mergedFields = nil + var mergeNode *Node var doneFields []bool if d.uniqueKeys { doneFields = make([]bool, len(sinfo.FieldsList)) @@ -860,13 +905,20 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { for i := 0; i < l; i += 2 { ni := n.Content[i] if isMerge(ni) { - d.merge(n.Content[i+1], out) + mergeNode = n.Content[i+1] continue } if !d.unmarshal(ni, name) { continue } - if info, ok := sinfo.FieldsMap[name.String()]; ok { + sname := name.String() + if mergedFields != nil { + if mergedFields[sname] { + continue + } + mergedFields[sname] = true + } + if info, ok := sinfo.FieldsMap[sname]; ok { if d.uniqueKeys { if doneFields[info.Id] { d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) @@ -892,6 +944,11 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) } } + + d.mergedFields = mergedFields + if mergeNode != nil { + d.merge(n, mergeNode, out) + } return true } @@ -899,19 +956,29 @@ func failWantMap() { failf("map merge requires map or sequence of maps as the value") } -func (d *decoder) merge(n *Node, out reflect.Value) { - switch n.Kind { +func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { + mergedFields := d.mergedFields + if mergedFields == nil { + d.mergedFields = make(map[interface{}]bool) + for i := 0; i < len(parent.Content); i += 2 { + k := reflect.New(ifaceType).Elem() + if d.unmarshal(parent.Content[i], k) { + d.mergedFields[k.Interface()] = true + } + } + } + + switch merge.Kind { case MappingNode: - d.unmarshal(n, out) + d.unmarshal(merge, out) case AliasNode: - if n.Alias != nil && n.Alias.Kind != MappingNode { + if merge.Alias != nil && merge.Alias.Kind != MappingNode { failWantMap() } - d.unmarshal(n, out) + d.unmarshal(merge, out) case SequenceNode: - // Step backwards as earlier nodes take precedence. - for i := len(n.Content) - 1; i >= 0; i-- { - ni := n.Content[i] + for i := 0; i < len(merge.Content); i++ { + ni := merge.Content[i] if ni.Kind == AliasNode { if ni.Alias != nil && ni.Alias.Kind != MappingNode { failWantMap() @@ -924,6 +991,8 @@ func (d *decoder) merge(n *Node, out reflect.Value) { default: failWantMap() } + + d.mergedFields = mergedFields } func isMerge(n *Node) bool { diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go index ab2a066..0f47c9c 100644 --- a/vendor/gopkg.in/yaml.v3/emitterc.go +++ b/vendor/gopkg.in/yaml.v3/emitterc.go @@ -235,10 +235,13 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool emitter.indent = 0 } } else if !indentless { - emitter.indent += emitter.best_indent - // [Go] If inside a block sequence item, discount the space taken by the indicator. - if emitter.best_indent > 2 && emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { - emitter.indent -= 2 + // [Go] This was changed so that indentations are more regular. + if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { + // The first indent inside a sequence will just skip the "- " indicator. + emitter.indent += 2 + } else { + // Everything else aligns to the chosen indentation. + emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent) } } return true @@ -725,16 +728,9 @@ func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_e // Expect a block item node. func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { if first { - // [Go] The original logic here would not indent the sequence when inside a mapping. - // In Go we always indent it, but take the sequence indicator out of the indentation. - indentless := emitter.best_indent == 2 && emitter.mapping_context && (emitter.column == 0 || !emitter.indention) - original := emitter.indent - if !yaml_emitter_increase_indent(emitter, false, indentless) { + if !yaml_emitter_increase_indent(emitter, false, false) { return false } - if emitter.indent > original+2 { - emitter.indent -= 2 - } } if event.typ == yaml_SEQUENCE_END_EVENT { emitter.indent = emitter.indents[len(emitter.indents)-1] @@ -785,6 +781,13 @@ func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_ev if !yaml_emitter_write_indent(emitter) { return false } + if len(emitter.line_comment) > 0 { + // [Go] A line comment was provided for the key. That's unusual as the + // scanner associates line comments with the value. Either way, + // save the line comment and render it appropriately later. + emitter.key_line_comment = emitter.line_comment + emitter.line_comment = nil + } if yaml_emitter_check_simple_key(emitter) { emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) return yaml_emitter_emit_node(emitter, event, false, false, true, true) @@ -810,6 +813,27 @@ func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_ return false } } + if len(emitter.key_line_comment) > 0 { + // [Go] Line comments are generally associated with the value, but when there's + // no value on the same line as a mapping key they end up attached to the + // key itself. + if event.typ == yaml_SCALAR_EVENT { + if len(emitter.line_comment) == 0 { + // A scalar is coming and it has no line comments by itself yet, + // so just let it handle the line comment as usual. If it has a + // line comment, we can't have both so the one from the key is lost. + emitter.line_comment = emitter.key_line_comment + emitter.key_line_comment = nil + } + } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { + // An indented block follows, so write the comment right now. + emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment + if !yaml_emitter_process_line_comment(emitter) { + return false + } + emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment + } + } emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { return false @@ -823,6 +847,10 @@ func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_ return true } +func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 +} + // Expect a node. func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, root bool, sequence bool, mapping bool, simple_key bool) bool { @@ -1866,7 +1894,7 @@ func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bo if !yaml_emitter_write_block_scalar_hints(emitter, value) { return false } - if !put_break(emitter) { + if !yaml_emitter_process_line_comment(emitter) { return false } //emitter.indention = true @@ -1903,10 +1931,10 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo if !yaml_emitter_write_block_scalar_hints(emitter, value) { return false } - - if !put_break(emitter) { + if !yaml_emitter_process_line_comment(emitter) { return false } + //emitter.indention = true emitter.whitespace = true diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go index 1f37271..de9e72a 100644 --- a/vendor/gopkg.in/yaml.v3/encode.go +++ b/vendor/gopkg.in/yaml.v3/encode.go @@ -119,6 +119,14 @@ func (e *encoder) marshal(tag string, in reflect.Value) { case *Node: e.nodev(in) return + case Node: + if !in.CanAddr() { + var n = reflect.New(in.Type()).Elem() + n.Set(in) + in = n + } + e.nodev(in.Addr()) + return case time.Time: e.timev(tag, in) return @@ -422,18 +430,23 @@ func (e *encoder) nodev(in reflect.Value) { } func (e *encoder) node(node *Node, tail string) { + // Zero nodes behave as nil. + if node.Kind == 0 && node.IsZero() { + e.nilv() + return + } + // If the tag was not explicitly requested, and dropping it won't change the // implicit tag of the value, don't include it in the presentation. var tag = node.Tag var stag = shortTag(tag) - var rtag string var forceQuoting bool if tag != "" && node.Style&TaggedStyle == 0 { if node.Kind == ScalarNode { if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { tag = "" } else { - rtag, _ = resolve("", node.Value) + rtag, _ := resolve("", node.Value) if rtag == stag { tag = "" } else if stag == strTag { @@ -442,6 +455,7 @@ func (e *encoder) node(node *Node, tail string) { } } } else { + var rtag string switch node.Kind { case MappingNode: rtag = mapTag @@ -471,7 +485,7 @@ func (e *encoder) node(node *Node, tail string) { if node.Style&FlowStyle != 0 { style = yaml_FLOW_SEQUENCE_STYLE } - e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(tag), tag == "", style)) + e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) e.event.head_comment = []byte(node.HeadComment) e.emit() for _, node := range node.Content { @@ -487,7 +501,7 @@ func (e *encoder) node(node *Node, tail string) { if node.Style&FlowStyle != 0 { style = yaml_FLOW_MAPPING_STYLE } - yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(tag), tag == "", style) + yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) e.event.tail_comment = []byte(tail) e.event.head_comment = []byte(node.HeadComment) e.emit() @@ -528,11 +542,11 @@ func (e *encoder) node(node *Node, tail string) { case ScalarNode: value := node.Value if !utf8.ValidString(value) { - if tag == binaryTag { + if stag == binaryTag { failf("explicitly tagged !!binary data must be base64-encoded") } - if tag != "" { - failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) + if stag != "" { + failf("cannot marshal invalid UTF-8 data as %s", stag) } // It can't be encoded directly as YAML so use a binary tag // and encode it as base64. @@ -557,5 +571,7 @@ func (e *encoder) node(node *Node, tail string) { } e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) + default: + failf("cannot encode node with unknown kind %d", node.Kind) } } diff --git a/vendor/gopkg.in/yaml.v3/go.mod b/vendor/gopkg.in/yaml.v3/go.mod deleted file mode 100644 index f407ea3..0000000 --- a/vendor/gopkg.in/yaml.v3/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module "gopkg.in/yaml.v3" - -require ( - "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 -) diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go index aea9050..268558a 100644 --- a/vendor/gopkg.in/yaml.v3/parserc.go +++ b/vendor/gopkg.in/yaml.v3/parserc.go @@ -648,6 +648,10 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i implicit: implicit, style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), } + if parser.stem_comment != nil { + event.head_comment = parser.stem_comment + parser.stem_comment = nil + } return true } if len(anchor) > 0 || len(tag) > 0 { @@ -683,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { if first { token := peek_token(parser) + if token == nil { + return false + } parser.marks = append(parser.marks, token.start_mark) skip_token(parser) } @@ -694,25 +701,13 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e if token.typ == yaml_BLOCK_ENTRY_TOKEN { mark := token.end_mark - prior_head := len(parser.head_comment) + prior_head_len := len(parser.head_comment) skip_token(parser) + yaml_parser_split_stem_comment(parser, prior_head_len) token = peek_token(parser) if token == nil { return false } - if prior_head > 0 && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { - // [Go] It's a sequence under a sequence entry, so the former head comment - // is for the list itself, not the first list item under it. - parser.stem_comment = parser.head_comment[:prior_head] - if len(parser.head_comment) == prior_head { - parser.head_comment = nil - } else { - // Copy suffix to prevent very strange bugs if someone ever appends - // further bytes to the prefix in the stem_comment slice above. - parser.head_comment = append([]byte(nil), parser.head_comment[prior_head+1:]...) - } - - } if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) return yaml_parser_parse_node(parser, event, true, false) @@ -754,7 +749,9 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y if token.typ == yaml_BLOCK_ENTRY_TOKEN { mark := token.end_mark + prior_head_len := len(parser.head_comment) skip_token(parser) + yaml_parser_split_stem_comment(parser, prior_head_len) token = peek_token(parser) if token == nil { return false @@ -780,6 +777,32 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y return true } +// Split stem comment from head comment. +// +// When a sequence or map is found under a sequence entry, the former head comment +// is assigned to the underlying sequence or map as a whole, not the individual +// sequence or map entry as would be expected otherwise. To handle this case the +// previous head comment is moved aside as the stem comment. +func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { + if stem_len == 0 { + return + } + + token := peek_token(parser) + if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { + return + } + + parser.stem_comment = parser.head_comment[:stem_len] + if len(parser.head_comment) == stem_len { + parser.head_comment = nil + } else { + // Copy suffix to prevent very strange bugs if someone ever appends + // further bytes to the prefix in the stem_comment slice above. + parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) + } +} + // Parse the productions: // block_mapping ::= BLOCK-MAPPING_START // ******************* @@ -793,6 +816,9 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { if first { token := peek_token(parser) + if token == nil { + return false + } parser.marks = append(parser.marks, token.start_mark) skip_token(parser) } @@ -902,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { if first { token := peek_token(parser) + if token == nil { + return false + } parser.marks = append(parser.marks, token.start_mark) skip_token(parser) } diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go index 57e954c..ca00701 100644 --- a/vendor/gopkg.in/yaml.v3/scannerc.go +++ b/vendor/gopkg.in/yaml.v3/scannerc.go @@ -749,6 +749,11 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { if !ok { return } + if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { + // Sequence indicators alone have no line comments. It becomes + // a head comment for whatever follows. + return + } if !yaml_parser_scan_line_comment(parser, comment_mark) { ok = false return @@ -2255,10 +2260,9 @@ func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, l } } if parser.buffer[parser.buffer_pos] == '#' { - // TODO Test this and then re-enable it. - //if !yaml_parser_scan_line_comment(parser, start_mark) { - // return false - //} + if !yaml_parser_scan_line_comment(parser, start_mark) { + return false + } for !is_breakz(parser.buffer, parser.buffer_pos) { skip(parser) if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { @@ -2856,13 +2860,12 @@ func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t return false } skip_line(parser) - } else { - if parser.mark.index >= seen { - if len(text) == 0 { - start_mark = parser.mark - } - text = append(text, parser.buffer[parser.buffer_pos]) + } else if parser.mark.index >= seen { + if len(text) == 0 { + start_mark = parser.mark } + text = read(parser, text) + } else { skip(parser) } } @@ -2888,6 +2891,10 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo var token_mark = token.start_mark var start_mark yaml_mark_t + var next_indent = parser.indent + if next_indent < 0 { + next_indent = 0 + } var recent_empty = false var first_empty = parser.newlines <= 1 @@ -2919,15 +2926,18 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo continue } c := parser.buffer[parser.buffer_pos+peek] - if is_breakz(parser.buffer, parser.buffer_pos+peek) || parser.flow_level > 0 && (c == ']' || c == '}') { + var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') + if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { // Got line break or terminator. - if !recent_empty { - if first_empty && (start_mark.line == foot_line || start_mark.column-1 < parser.indent) { + if close_flow || !recent_empty { + if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { // This is the first empty line and there were no empty lines before, // so this initial part of the comment is a foot of the prior token // instead of being a head for the following one. Split it up. + // Alternatively, this might also be the last comment inside a flow + // scope, so it must be a footer. if len(text) > 0 { - if start_mark.column-1 < parser.indent { + if start_mark.column-1 < next_indent { // If dedented it's unrelated to the prior token. token_mark = start_mark } @@ -2958,7 +2968,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo continue } - if len(text) > 0 && column < parser.indent+1 && column != start_mark.column { + if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { // The comment at the different indentation is a foot of the // preceding data rather than a head of the upcoming one. parser.comments = append(parser.comments, yaml_comment_t{ @@ -2999,10 +3009,9 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo return false } skip_line(parser) + } else if parser.mark.index >= seen { + text = read(parser, text) } else { - if parser.mark.index >= seen { - text = append(text, parser.buffer[parser.buffer_pos]) - } skip(parser) } } @@ -3010,6 +3019,10 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo peek = 0 column = 0 line = parser.mark.line + next_indent = parser.indent + if next_indent < 0 { + next_indent = 0 + } } if len(text) > 0 { diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go index b5d35a5..8cec6da 100644 --- a/vendor/gopkg.in/yaml.v3/yaml.go +++ b/vendor/gopkg.in/yaml.v3/yaml.go @@ -89,7 +89,7 @@ func Unmarshal(in []byte, out interface{}) (err error) { return unmarshal(in, out, false) } -// A Decorder reads and decodes YAML values from an input stream. +// A Decoder reads and decodes YAML values from an input stream. type Decoder struct { parser *parser knownFields bool @@ -194,7 +194,7 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) { // Zero valued structs will be omitted if all their public // fields are zero, unless they implement an IsZero // method (see the IsZeroer interface type), in which -// case the field will be included if that method returns true. +// case the field will be excluded if IsZero returns true. // // flow Marshal using a flow style (useful for structs, // sequences and maps). @@ -252,6 +252,24 @@ func (e *Encoder) Encode(v interface{}) (err error) { return nil } +// Encode encodes value v and stores its representation in n. +// +// See the documentation for Marshal for details about the +// conversion of Go values into YAML. +func (n *Node) Encode(v interface{}) (err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshalDoc("", reflect.ValueOf(v)) + e.finish() + p := newParser(e.out) + p.textless = true + defer p.destroy() + doc := p.parse() + *n = *doc.Content[0] + return nil +} + // SetIndent changes the used indentation used when encoding. func (e *Encoder) SetIndent(spaces int) { if spaces < 0 { @@ -328,6 +346,12 @@ const ( // and maps, Node is an intermediate representation that allows detailed // control over the content being decoded or encoded. // +// It's worth noting that although Node offers access into details such as +// line numbers, colums, and comments, the content when re-encoded will not +// have its original textual representation preserved. An effort is made to +// render the data plesantly, and to preserve comments near the data they +// describe, though. +// // Values that make use of the Node type interact with the yaml package in the // same way any other type would do, by encoding and decoding yaml data // directly or indirectly into them. @@ -391,6 +415,13 @@ type Node struct { Column int } +// IsZero returns whether the node has all of its fields unset. +func (n *Node) IsZero() bool { + return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && + n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 +} + + // LongTag returns the long form of the tag that indicates the data type for // the node. If the Tag field isn't explicitly defined, one will be computed // based on the node properties. @@ -418,6 +449,11 @@ func (n *Node) ShortTag() string { case ScalarNode: tag, _ := resolve("", n.Value) return tag + case 0: + // Special case to make the zero value convenient. + if n.IsZero() { + return nullTag + } } return "" } diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go index 2719cfb..7c6d007 100644 --- a/vendor/gopkg.in/yaml.v3/yamlh.go +++ b/vendor/gopkg.in/yaml.v3/yamlh.go @@ -787,6 +787,8 @@ type yaml_emitter_t struct { foot_comment []byte tail_comment []byte + key_line_comment []byte + // Dumper stuff opened bool // If the stream was already opened? diff --git a/vendor/modules.txt b/vendor/modules.txt index 687b35d..bcb5964 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,44 +1,98 @@ -# github.com/davecgh/go-spew v1.1.0 +# github.com/antithesishq/antithesis-sdk-go v0.5.0-default-no-op +## explicit; go 1.20 +github.com/antithesishq/antithesis-sdk-go/assert +github.com/antithesishq/antithesis-sdk-go/internal +# github.com/davecgh/go-spew v1.1.1 +## explicit github.com/davecgh/go-spew/spew -# github.com/julienschmidt/httprouter v1.2.0 +# github.com/google/go-tpm v0.9.8 +## explicit; go 1.22 +github.com/google/go-tpm/legacy/tpm2 +github.com/google/go-tpm/tpmutil +github.com/google/go-tpm/tpmutil/tbs +# github.com/julienschmidt/httprouter v1.3.0 +## explicit; go 1.7 github.com/julienschmidt/httprouter -# github.com/minio/highwayhash v1.0.0 +# github.com/klauspost/compress v1.18.3 +## explicit; go 1.23 +github.com/klauspost/compress/flate +github.com/klauspost/compress/internal/le +github.com/klauspost/compress/internal/race +github.com/klauspost/compress/s2 +# github.com/kr/pretty v0.2.1 +## explicit; go 1.12 +# github.com/kr/text v0.2.0 +## explicit +# github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 +## explicit; go 1.15 github.com/minio/highwayhash # github.com/mitchellh/go-homedir v1.1.0 +## explicit github.com/mitchellh/go-homedir # github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7 +## explicit; go 1.13 github.com/nats-io/jwt -# github.com/nats-io/jwt/v2 v2.0.0-20201015190852-e11ce317263c +# github.com/nats-io/jwt/v2 v2.8.0 +## explicit; go 1.23.0 github.com/nats-io/jwt/v2 -# github.com/nats-io/nats-server/v2 v2.1.8-0.20201209001253-25a5fa62ebc8 +# github.com/nats-io/nats-server/v2 v2.11.12 +## explicit; go 1.24.0 github.com/nats-io/nats-server/v2/conf +github.com/nats-io/nats-server/v2/internal/fastrand github.com/nats-io/nats-server/v2/internal/ldap github.com/nats-io/nats-server/v2/logger github.com/nats-io/nats-server/v2/server +github.com/nats-io/nats-server/v2/server/ats +github.com/nats-io/nats-server/v2/server/avl +github.com/nats-io/nats-server/v2/server/certidp +github.com/nats-io/nats-server/v2/server/certstore +github.com/nats-io/nats-server/v2/server/gsl github.com/nats-io/nats-server/v2/server/pse +github.com/nats-io/nats-server/v2/server/stree github.com/nats-io/nats-server/v2/server/sysmem +github.com/nats-io/nats-server/v2/server/thw +github.com/nats-io/nats-server/v2/server/tpm github.com/nats-io/nats-server/v2/test -# github.com/nats-io/nats.go v1.10.1-0.20201021145452-94be476ad6e0 +# github.com/nats-io/nats.go v1.48.0 +## explicit; go 1.23.0 github.com/nats-io/nats.go github.com/nats-io/nats.go/encoders/builtin +github.com/nats-io/nats.go/internal/parser github.com/nats-io/nats.go/util -# github.com/nats-io/nkeys v0.2.0 +# github.com/nats-io/nkeys v0.4.12 +## explicit; go 1.24.0 github.com/nats-io/nkeys # github.com/nats-io/nuid v1.0.1 +## explicit github.com/nats-io/nuid # github.com/pmezard/go-difflib v1.0.0 +## explicit github.com/pmezard/go-difflib/difflib -# github.com/rs/cors v1.6.0 +# github.com/rs/cors v1.8.0 +## explicit; go 1.13 github.com/rs/cors -# github.com/stretchr/testify v1.6.1 +# github.com/stretchr/testify v1.7.1 +## explicit; go 1.13 github.com/stretchr/testify/assert github.com/stretchr/testify/require -# golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 +# golang.org/x/crypto v0.47.0 +## explicit; go 1.24.0 golang.org/x/crypto/bcrypt +golang.org/x/crypto/blake2b golang.org/x/crypto/blowfish -golang.org/x/crypto/ed25519 -golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd +golang.org/x/crypto/chacha20 +golang.org/x/crypto/chacha20poly1305 +golang.org/x/crypto/cryptobyte +golang.org/x/crypto/cryptobyte/asn1 +golang.org/x/crypto/curve25519 +golang.org/x/crypto/internal/alias +golang.org/x/crypto/internal/poly1305 +golang.org/x/crypto/nacl/box +golang.org/x/crypto/nacl/secretbox +golang.org/x/crypto/ocsp +golang.org/x/crypto/salsa20/salsa +# golang.org/x/sys v0.40.0 +## explicit; go 1.24.0 golang.org/x/sys/cpu golang.org/x/sys/unix golang.org/x/sys/windows @@ -46,7 +100,11 @@ golang.org/x/sys/windows/registry golang.org/x/sys/windows/svc golang.org/x/sys/windows/svc/eventlog golang.org/x/sys/windows/svc/mgr -# golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 +# golang.org/x/time v0.14.0 +## explicit; go 1.24.0 golang.org/x/time/rate -# gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c +# gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 +## explicit +# gopkg.in/yaml.v3 v3.0.1 +## explicit gopkg.in/yaml.v3